feat: add OpenAI and Anthropic cloud AI providers (#74) - #78
Conversation
|
@prince-pokharna is attempting to deploy a commit to the nirvik34's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Warning
|
| Layer / File(s) | Summary |
|---|---|
Provider configuration and SDK dependencies src/config/loadConfig.ts, package.json |
GitbunConfig now supports AI, interactive mode, provider selection, and an optional API key; OpenAI and Anthropic SDKs are added as dependencies. |
Remote provider implementations src/providers/openai.provider.ts, src/providers/anthropic.provider.ts |
Adds provider wrappers for OpenAI Chat Completions and Anthropic Messages API requests, using configurable models and returning trimmed generated text. |
Estimated code review effort: 3 (Moderate) | ~20 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Linked Issues check | Provider classes and config fields were added, but env-var API key handling, Ollama fallback resolution, docs, and diff truncation are not shown. | Add provider-selection logic with Ollama fallback, read keys from OPENAI_API_KEY/ANTHROPIC_API_KEY, document .gitbunrc usage, and truncate diffs to 8000 chars. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title clearly summarizes the main change: adding OpenAI and Anthropic cloud AI providers. |
| Out of Scope Changes check | ✅ Passed | The changes stay focused on cloud AI provider support, dependency additions, and related config/provider code. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/config/loadConfig.ts`:
- Line 11: Remove apiKey from the GitbunConfig type and keep loadConfig()
limited to returning configuration-file contents. Update the provider factory to
resolve OPENAI_API_KEY and ANTHROPIC_API_KEY directly from the environment
instead of reading an API key from GitbunConfig.
- Around line 8-11: Update the src/index.ts runtime flow around
isOllamaRunning() and enhanceCommit() to resolve the configured provider and
route execution through the selected OpenAI or Anthropic implementation; retain
Ollama only when provider is unset or unsupported, and ensure the apiKey is
passed to the chosen provider as required.
- Around line 8-11: Update the cosmiconfig explorer used by the configuration
loader to include `.gitbunrc` in its searchPlaces, while preserving the existing
supported formats. Add a config-loading test covering the documented `.gitbunrc`
filename and verifying its fields, including provider and apiKey, are loaded.
In `@src/providers/anthropic.provider.ts`:
- Around line 13-16: Update the Anthropic messages.create call to pass prompt
through the top-level system parameter and make the user message contain only
the untrusted diff content. Remove the prompt interpolation from the user
message while preserving the existing model and token settings.
In `@src/providers/openai.provider.ts`:
- Around line 12-17: Apply the shared 8,000-character diff cap before
constructing the user message in generateCommitMessage for
src/providers/openai.provider.ts (lines 12-17) and the corresponding Anthropic
request in src/providers/anthropic.provider.ts (lines 12-16). Ensure both
providers interpolate only the truncated diff while preserving the existing
prompt and request structure.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 8246fd23-8d63-41fa-9eb4-70ce836a4256
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (4)
package.jsonsrc/config/loadConfig.tssrc/providers/anthropic.provider.tssrc/providers/openai.provider.ts
| ai?: boolean; | ||
| interactive?: boolean; | ||
| provider?: 'ollama' | 'openai' | 'anthropic'; // add this | ||
| apiKey?: string; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Wire provider selection into the runtime path.
The new fields are never consumed: the supplied src/index.ts flow still calls isOllamaRunning() and enhanceCommit() directly. Selecting openai or anthropic therefore has no effect. Add provider resolution and retain Ollama only as the fallback.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/config/loadConfig.ts` around lines 8 - 11, Update the src/index.ts
runtime flow around isOllamaRunning() and enhanceCommit() to resolve the
configured provider and route execution through the selected OpenAI or Anthropic
implementation; retain Ollama only when provider is unset or unsupported, and
ensure the apiKey is passed to the chosen provider as required.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg '(^|/)loadConfig\.ts$|package\.json|README|\.gitbunrc|smartcommit' || true
echo "== config loader candidates =="
fd -a -i 'loadConfig|config' . | sed 's#^\./##' | head -50
echo "== loadConfig.ts =="
for f in $(fd -i 'loadConfig\.ts$' .); do
echo "--- $f"
wc -l "$f"
cat -n "$f"
done
echo "== searchPlaces / cosmiconfig usages =="
rg -n "cosmiconfig|searchPlaces|smartcommit|gitbunrc|\\.git" -S . --glob '!node_modules' --glob '!dist' --glob '!build' || true
echo "== package manifests =="
for f in $(fd -i 'package\.json$' .); do
echo "--- $f"
sed -n '1,220p' "$f"
doneRepository: nirvik34/gitbun
Length of output: 8530
🌐 Web query:
cosmiconfig 9.0 searchPlaces default .gitignore dotfiles
💡 Result:
In cosmiconfig 9.0, the searchPlaces option defines the list of filenames and paths the library checks when searching for a configuration [1][2]. Cosmiconfig does not have any built-in logic to ignore or respect.gitignore files; it simply attempts to locate and load the configuration files specified in the searchPlaces array [1][3]. The default searchPlaces configuration includes various rc-style files and a.config/ subdirectory [1][3]. The default list is as follows: [ 'package.json', .${moduleName}rc, .${moduleName}rc.json, .${moduleName}rc.yaml, .${moduleName}rc.yml, .${moduleName}rc.js, .${moduleName}rc.ts, .${moduleName}rc.mjs, .${moduleName}rc.cjs, .config/${moduleName}rc, .config/${moduleName}rc.json, .config/${moduleName}rc.yaml, .config/${moduleName}rc.yml, .config/${moduleName}rc.js, .config/${moduleName}rc.ts, .config/${moduleName}rc.mjs, .config/${moduleName}rc.cjs, ${moduleName}.config.js, ${moduleName}.config.ts, ${moduleName}.config.mjs, ${moduleName}.config.cjs ] In this list, {moduleName} is the name provided to the cosmiconfig explorer instance [1][4]. The library searches for these files in the current working directory by default (in version 9.0, the default searchStrategy is 'none', meaning it does not traverse upward by default) [5][3][6]. If you need to exclude specific files, you must manage that at the project or file system level, as cosmiconfig will attempt to load any file matching these patterns if it exists in the designated search paths [1][3].
Citations:
- 1: https://github.com/cosmiconfig/cosmiconfig/blob/v9.0.0/README.md
- 2: https://github.com/cosmiconfig/cosmiconfig/blob/HEAD/README.md
- 3: https://github.com/cosmiconfig/cosmiconfig?tab=readme-ov-file
- 4: https://www.npmjs.com/package/cosmiconfig
- 5: https://github.com/cosmiconfig/cosmiconfig/releases/tag/v9.0.0
- 6: https://github.com/cosmiconfig/cosmiconfig/blob/main/src/index.ts
🌐 Web query:
cosmiconfig 9 searchPlaces default file extensions
💡 Result:
In Cosmiconfig 9, the default searchPlaces consist of a predefined list of files that the library searches for when looking for configuration [1][2]. The list includes files in the current directory and a .config/ subdirectory, using the moduleName provided to the library [1][2]. The default search places are [1][2]: * package.json (parsed for a specific property) *.${moduleName}rc *.${moduleName}rc.json *.${moduleName}rc.yaml *.${moduleName}rc.yml *.${moduleName}rc.js *.${moduleName}rc.ts *.${moduleName}rc.mjs *.${moduleName}rc.cjs *.config/${moduleName}rc *.config/${moduleName}rc.json *.config/${moduleName}rc.yaml *.config/${moduleName}rc.yml *.config/${moduleName}rc.js *.config/${moduleName}rc.ts *.config/${moduleName}rc.mjs *.config/${moduleName}rc.cjs * ${moduleName}.config.js * ${moduleName}.config.ts * ${moduleName}.config.mjs * ${moduleName}.config.cjs Each item in this list must have a corresponding loader configured in the loaders option that matches its file extension [1][2]. Common extensions are covered by default loaders, while files without extensions (e.g.,.${moduleName}rc) are handled by the noExt loader key [1][3]. Additionally, when package.json is included, Cosmiconfig parses it as JSON and loads a specific property (defaulting to the moduleName) rather than the entire file [1][2].
Citations:
- 1: https://github.com/cosmiconfig/cosmiconfig/blob/v9.0.0/README.md
- 2: https://github.com/cosmiconfig/cosmiconfig/blob/HEAD/README.md
- 3: https://www.npmjs.com/package/cosmiconfig
Add .gitbunrc to the cosmiconfig search paths.
cosmiconfig("smartcommit") uses an explorer named smartcommit, so with the default searchPlaces it will only look for .smartcommitrc* / smartcommit.config.*; .gitbunrc will not be loaded and these new config fields are ignored. Also add a config-loading test for the documented .gitbunrc file.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/config/loadConfig.ts` around lines 8 - 11, Update the cosmiconfig
explorer used by the configuration loader to include `.gitbunrc` in its
searchPlaces, while preserving the existing supported formats. Add a
config-loading test covering the documented `.gitbunrc` filename and verifying
its fields, including provider and apiKey, are loaded.
| ai?: boolean; | ||
| interactive?: boolean; | ||
| provider?: 'ollama' | 'openai' | 'anthropic'; // add this | ||
| apiKey?: string; |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
Keep API keys out of GitbunConfig.
loadConfig() returns configuration-file contents unchanged, so apiKey?: string permits secrets to be stored in .gitbunrc, contradicting the environment-only requirement. Resolve OPENAI_API_KEY/ANTHROPIC_API_KEY in the provider factory instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/config/loadConfig.ts` at line 11, Remove apiKey from the GitbunConfig
type and keep loadConfig() limited to returning configuration-file contents.
Update the provider factory to resolve OPENAI_API_KEY and ANTHROPIC_API_KEY
directly from the environment instead of reading an API key from GitbunConfig.
| const response = await this.client.messages.create({ | ||
| model: this.model, | ||
| max_tokens: 200, | ||
| messages: [{ role: 'user', content: `${prompt}\n\nGit diff:\n\`\`\`\n${diff}\n\`\`\`` }], |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
npm view `@anthropic-ai/sdk`@0.115.0 versionRepository: nirvik34/gitbun
Length of output: 310
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
echo "== file excerpt =="
sed -n '1,120p' src/providers/anthropic.provider.ts
echo
echo "== package versions / constraints =="
for f in package.json package-lock.json pnpm-lock.yaml yarn.lock; do
if [ -f "$f" ]; then
echo "--- $f ---"
rg -n '"`@anthropic-ai/sdk`"|anthropic' "$f" || true
fi
done
echo
echo "== occurrences of this provider / prompt diff usage =="
rg -n "AnthropicProvider|anthropic\\.provider|max_tokens: 200|this\\.client\\.messages\\.create|messages: \\[\\{ role: 'user', content" src package.json package-lock.json pnpm-lock.yaml yarn.lock || trueRepository: nirvik34/gitbun
Length of output: 1724
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
echo "== installed anthropic SDK type if present =="
node -e "const fs=require('fs'); const p='node_modules/@anthropic-ai/sdk/resources/messages.d.ts'; console.log(fs.existsSync(p))?fs.readFileSync(p,'utf8').slice(0,1200):p+' not present'" 2>/dev/null || true
echo
echo "== local anthropic types if present =="
if [ -d node_modules/@anthropic-ai/sdk ]; then
find node_modules/@anthropic-ai/sdk -maxdepth 3 -type f | sed -n '1,80p'
fiRepository: nirvik34/gitbun
Length of output: 5036
🌐 Web query:
Anthropic Messages API system parameter documentation untrusted content safety
💡 Result:
To safely handle untrusted content when using the Anthropic Messages API, you must leverage structural separation at the API level [1][2]. The Messages API is designed to distinguish between system instructions and user-provided data, which is critical for preventing prompt injection attacks [2]. Key security practices for the Messages API: 1. Use the Dedicated System Parameter: The API provides a top-level system parameter specifically for instructions that define the model's behavior, goal, or role [3][4][5]. You must use this parameter for your system instructions rather than attempting to include them within the messages array or concatenating them with user input [3][2][6]. 2. Maintain Architectural Boundary for Untrusted Input: All untrusted content—such as data from web pages, user uploads, third-party APIs, or tool outputs—must be placed within the messages array, specifically using the user role [1][7]. Do not interpolate untrusted content into the system parameter or mix it with your application's instructions [2]. For Claude 3.7 and later, the API enforces a token-level boundary that prevents user messages from syntactically overriding system instructions, provided the inputs are correctly separated at the call level [2]. 3. Handle Tool Outputs as Untrusted: When using tools, treat all tool outputs as untrusted content [7]. Keep these outputs inside tool_result blocks rather than placing them in the system prompt or plain text blocks [7]. Anthropic recommends screening tool outputs for injection attempts before passing them to the model, which can be done by using a smaller, lightweight model (e.g., Claude Haiku) to evaluate the tool output for adversarial commands before it is processed by the main agent [8]. 4. Leverage Enterprise Trust & Safety: For enterprise-tier users, additional "Trust & Safety Configuration" is available [9]. This feature allows you to inject organizational policies and audit requirements via request headers, which Anthropic's safety layer uses to evaluate both the prompt and the response [9]. If a safety violation is detected, the API will return a stop_reason of safety_violation, which must be handled programmatically in your application logic, as the API may still return a 200 OK status [9]. By strictly enforcing the separation between system-defined instructions and untrusted user/tool data, you shift the security burden from relying on model robustness alone to utilizing the API's structural protections [2].
Citations:
- 1: https://theneuralbase.com/prompt-injection/learn/advanced/mark-untrusted-input/
- 2: https://theneuralbase.com/prompt-injection/learn/advanced/claude-3-7-deployment/
- 3: https://platform.claude.com/docs/en/api/messages/create
- 4: https://platform.claude.com/docs/en/api/cli/messages
- 5: https://github.com/anthropics/anthropic-sdk-python/blob/main/src/anthropic/resources/messages/messages.py
- 6: https://archon-eight.vercel.app/ai-ml-engineering/anthropic-claude-api
- 7: https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls
- 8: https://platform.claude.com/docs/en/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks
- 9: https://theneuralbase.com/anthropic-api/learn/advanced/enterprise-trust-and-safety-configuration/
Pass system instructions via Anthropic’s top-level system parameter.
prompt drives the provider behavior, while diff is untrusted tool output. Keep them split: system: prompt plus a user message with the git diff only.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/providers/anthropic.provider.ts` around lines 13 - 16, Update the
Anthropic messages.create call to pass prompt through the top-level system
parameter and make the user message contain only the untrusted diff content.
Remove the prompt interpolation from the user message while preserving the
existing model and token settings.
| async generateCommitMessage(diff: string, prompt: string): Promise<string> { | ||
| const response = await this.client.chat.completions.create({ | ||
| model: this.model, | ||
| messages: [ | ||
| { role: 'system', content: prompt }, | ||
| { role: 'user', content: `Git diff:\n\`\`\`\n${diff}\n\`\`\`` }, |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win
Apply the 8,000-character diff cap consistently across cloud providers.
Both implementations interpolate the complete diff into their requests, violating the shared PR requirement.
src/providers/openai.provider.ts#L12-L17: truncatediffbefore constructing the OpenAI user message.src/providers/anthropic.provider.ts#L12-L16: truncatediffbefore constructing the Anthropic user message.
📍 Affects 2 files
src/providers/openai.provider.ts#L12-L17(this comment)src/providers/anthropic.provider.ts#L12-L16
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/providers/openai.provider.ts` around lines 12 - 17, Apply the shared
8,000-character diff cap before constructing the user message in
generateCommitMessage for src/providers/openai.provider.ts (lines 12-17) and the
corresponding Anthropic request in src/providers/anthropic.provider.ts (lines
12-16). Ensure both providers interpolate only the truncated diff while
preserving the existing prompt and request structure.
Fixes #74
Summary by CodeRabbit