-
Notifications
You must be signed in to change notification settings - Fork 19
feat: add OpenAI and Anthropic cloud AI providers (#74) #78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,10 @@ export interface GitbunConfig { | |
| customPrompt?: string; | ||
| format?: string; | ||
| model?: string; | ||
| ai?: boolean; | ||
| interactive?: boolean; | ||
| provider?: 'ollama' | 'openai' | 'anthropic'; // add this | ||
| apiKey?: string; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift Keep API keys out of
🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| /** Loads and returns user config from .gitbunrc or cosmiconfig. */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import Anthropic from '@anthropic-ai/sdk'; | ||
|
|
||
| export class AnthropicProvider { | ||
| private client: Anthropic; | ||
| private model: string; | ||
|
|
||
| constructor(apiKey: string, model = 'claude-haiku-4-5') { | ||
| this.client = new Anthropic({ apiKey }); | ||
| this.model = model; | ||
| } | ||
|
|
||
| async generateCommitMessage(diff: string, prompt: string): Promise<string> { | ||
| 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\`\`\`` }], | ||
|
Comment on lines
+13
to
+16
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 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:
💡 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 Citations:
Pass system instructions via Anthropic’s top-level
🤖 Prompt for AI Agents |
||
| }); | ||
| return (response.content[0] as { text: string }).text.trim(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import OpenAI from 'openai'; | ||
|
|
||
| export class OpenAIProvider { | ||
| private client: OpenAI; | ||
| private model: string; | ||
|
|
||
| constructor(apiKey: string, model = 'gpt-4o-mini') { | ||
| this.client = new OpenAI({ apiKey }); | ||
| this.model = model; | ||
| } | ||
|
|
||
| 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\`\`\`` }, | ||
|
Comment on lines
+12
to
+17
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚀 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.
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| ], | ||
| max_tokens: 200, | ||
| temperature: 0.3, | ||
| }); | ||
| return response.choices[0].message.content?.trim() ?? ''; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Wire provider selection into the runtime path.
The new fields are never consumed: the supplied
src/index.tsflow still callsisOllamaRunning()andenhanceCommit()directly. Selectingopenaioranthropictherefore has no effect. Add provider resolution and retain Ollama only as the fallback.🤖 Prompt for AI Agents
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: 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:
🌐 Web query:
cosmiconfig 9 searchPlaces default file extensions💡 Result:
In Cosmiconfig 9, the default
searchPlacesconsist 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 themoduleNameprovided 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 theloadersoption 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 thenoExtloader key [1][3]. Additionally, whenpackage.jsonis included, Cosmiconfig parses it as JSON and loads a specific property (defaulting to themoduleName) rather than the entire file [1][2].Citations:
Add
.gitbunrcto the cosmiconfig search paths.cosmiconfig("smartcommit")uses an explorer namedsmartcommit, so with the defaultsearchPlacesit will only look for.smartcommitrc*/smartcommit.config.*;.gitbunrcwill not be loaded and these new config fields are ignored. Also add a config-loading test for the documented.gitbunrcfile.🤖 Prompt for AI Agents