Skip to content

Commit 6752d83

Browse files
vraj00222claude
andcommitted
feat: extend providerOptions with baseUrl/apiKey for OpenAI-compatible endpoints
Adds two optional fields to AgentDefinition.providerOptions (and the backend OpenRouterProviderRoutingOptions + Zod schema) so an agent can direct its LLM calls at a custom OpenAI-compatible base URL (Ollama, LM Studio, self-hosted). The dispatch logic that consumes these fields lands in a follow-up commit. Also adds CODEBUFF_BASE_URL / CODEBUFF_PROVIDER_API_KEY env var constants and SDK getters for them. Part of issue #678. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent aa6555f commit 6752d83

7 files changed

Lines changed: 106 additions & 0 deletions

File tree

.agents/types/agent-definition.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,25 @@ export interface AgentDefinition {
109109
audio?: number | string
110110
request?: number | string
111111
}
112+
/**
113+
* Override the upstream LLM endpoint with an OpenAI-compatible base URL.
114+
* When set, this agent's LLM calls bypass the Codebuff backend / OpenRouter
115+
* and go directly to `${baseUrl}/chat/completions`.
116+
*
117+
* Use for local models (Ollama, LM Studio) or self-hosted OpenAI-compatible
118+
* providers. The other providerOptions keys (order, allow_fallbacks, etc.)
119+
* are OpenRouter-specific and ignored when `baseUrl` is set.
120+
*
121+
* Falls back to env var CODEBUFF_BASE_URL when unset.
122+
* Example: "http://localhost:11434/v1"
123+
*/
124+
baseUrl?: string
125+
/**
126+
* API key for the endpoint set in `baseUrl`. Ignored if `baseUrl` is unset.
127+
* Falls back to env var CODEBUFF_PROVIDER_API_KEY. Most local runtimes
128+
* (Ollama, LM Studio) ignore the value entirely.
129+
*/
130+
apiKey?: string
112131
}
113132

114133
// ============================================================================

agents/types/agent-definition.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,25 @@ export interface AgentDefinition {
109109
audio?: number | string
110110
request?: number | string
111111
}
112+
/**
113+
* Override the upstream LLM endpoint with an OpenAI-compatible base URL.
114+
* When set, this agent's LLM calls bypass the Codebuff backend / OpenRouter
115+
* and go directly to `${baseUrl}/chat/completions`.
116+
*
117+
* Use for local models (Ollama, LM Studio) or self-hosted OpenAI-compatible
118+
* providers. The other providerOptions keys (order, allow_fallbacks, etc.)
119+
* are OpenRouter-specific and ignored when `baseUrl` is set.
120+
*
121+
* Falls back to env var CODEBUFF_BASE_URL when unset.
122+
* Example: "http://localhost:11434/v1"
123+
*/
124+
baseUrl?: string
125+
/**
126+
* API key for the endpoint set in `baseUrl`. Ignored if `baseUrl` is unset.
127+
* Falls back to env var CODEBUFF_PROVIDER_API_KEY. Most local runtimes
128+
* (Ollama, LM Studio) ignore the value entirely.
129+
*/
130+
apiKey?: string
112131
}
113132

114133
// ============================================================================
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/** Env var that overrides the upstream LLM endpoint with an OpenAI-compatible base URL.
2+
* Lower precedence than per-agent providerOptions.baseUrl and the CodebuffClient option. */
3+
export const PROVIDER_BASE_URL_ENV_VAR = 'CODEBUFF_BASE_URL'
4+
5+
/** Env var providing the API key for the endpoint set by PROVIDER_BASE_URL_ENV_VAR.
6+
* Most local runtimes (Ollama, LM Studio) ignore the key entirely. */
7+
export const PROVIDER_API_KEY_ENV_VAR = 'CODEBUFF_PROVIDER_API_KEY'

common/src/templates/initial-agents-dir/types/agent-definition.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,25 @@ export interface AgentDefinition {
109109
audio?: number | string
110110
request?: number | string
111111
}
112+
/**
113+
* Override the upstream LLM endpoint with an OpenAI-compatible base URL.
114+
* When set, this agent's LLM calls bypass the Codebuff backend / OpenRouter
115+
* and go directly to `${baseUrl}/chat/completions`.
116+
*
117+
* Use for local models (Ollama, LM Studio) or self-hosted OpenAI-compatible
118+
* providers. The other providerOptions keys (order, allow_fallbacks, etc.)
119+
* are OpenRouter-specific and ignored when `baseUrl` is set.
120+
*
121+
* Falls back to env var CODEBUFF_BASE_URL when unset.
122+
* Example: "http://localhost:11434/v1"
123+
*/
124+
baseUrl?: string
125+
/**
126+
* API key for the endpoint set in `baseUrl`. Ignored if `baseUrl` is unset.
127+
* Falls back to env var CODEBUFF_PROVIDER_API_KEY. Most local runtimes
128+
* (Ollama, LM Studio) ignore the value entirely.
129+
*/
130+
apiKey?: string
112131
}
113132

114133
// ============================================================================

common/src/types/agent-template.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ export type OpenRouterReasoningOptions = {
3737
}
3838
)
3939

40+
/**
41+
* OpenRouter provider-routing options, plus optional fields to override the
42+
* upstream endpoint with an OpenAI-compatible base URL (e.g. Ollama, LM Studio,
43+
* self-hosted). The routing fields below are OpenRouter-specific and are
44+
* ignored when `baseUrl` is set.
45+
*/
4046
export type OpenRouterProviderRoutingOptions = {
4147
/**
4248
* List of provider slugs to try in order (e.g. ["anthropic", "openai"])
@@ -90,6 +96,20 @@ export type OpenRouterProviderRoutingOptions = {
9096
audio?: number | string
9197
request?: number | string
9298
}
99+
/**
100+
* Override the upstream LLM endpoint with an OpenAI-compatible base URL.
101+
* When set, this agent's calls bypass the Codebuff backend / OpenRouter
102+
* and go directly to `${baseUrl}/chat/completions`.
103+
*
104+
* Other keys above (order, allow_fallbacks, ...) are OpenRouter-specific and
105+
* are ignored when baseUrl is set. Falls back to env var CODEBUFF_BASE_URL.
106+
*/
107+
baseUrl?: string
108+
/**
109+
* API key for the endpoint set in `baseUrl`. Ignored if baseUrl is unset.
110+
* Falls back to env var CODEBUFF_PROVIDER_API_KEY.
111+
*/
112+
apiKey?: string
93113
}
94114

95115
export type OpenRouterProviderOptions = {

common/src/types/dynamic-agent-template.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ export const DynamicAgentDefinitionSchema = z.object({
167167
request: z.union([z.number(), z.string()]).optional(),
168168
})
169169
.optional(),
170+
baseUrl: z.string().url().optional(),
171+
apiKey: z.string().optional(),
170172
})
171173
.optional(),
172174

sdk/src/env.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
import { BYOK_OPENROUTER_ENV_VAR } from '@codebuff/common/constants/byok'
99
import { CHATGPT_OAUTH_TOKEN_ENV_VAR } from '@codebuff/common/constants/chatgpt-oauth'
10+
import {
11+
PROVIDER_API_KEY_ENV_VAR,
12+
PROVIDER_BASE_URL_ENV_VAR,
13+
} from '@codebuff/common/constants/custom-provider'
1014
import { API_KEY_ENV_VAR } from '@codebuff/common/constants/paths'
1115
import { getBaseEnv } from '@codebuff/common/env-process'
1216

@@ -48,3 +52,19 @@ export const getByokOpenrouterApiKeyFromEnv = (): string | undefined => {
4852
export const getChatGptOAuthTokenFromEnv = (): string | undefined => {
4953
return process.env[CHATGPT_OAUTH_TOKEN_ENV_VAR]
5054
}
55+
56+
/**
57+
* Get the custom upstream provider base URL from environment.
58+
* Used when an agent's providerOptions.baseUrl is unset and no CodebuffClient option overrides it.
59+
*/
60+
export const getCustomProviderBaseUrlFromEnv = (): string | undefined => {
61+
return process.env[PROVIDER_BASE_URL_ENV_VAR]
62+
}
63+
64+
/**
65+
* Get the custom upstream provider API key from environment.
66+
* Paired with getCustomProviderBaseUrlFromEnv.
67+
*/
68+
export const getCustomProviderApiKeyFromEnv = (): string | undefined => {
69+
return process.env[PROVIDER_API_KEY_ENV_VAR]
70+
}

0 commit comments

Comments
 (0)