Skip to content

Commit 6a33ca4

Browse files
Add session/list_providers endpoint and enhance provider metadata in configuration
1 parent 812fa1b commit 6a33ca4

3 files changed

Lines changed: 50 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -975,3 +975,5 @@ The chat sidebar now surfaces two extra ACP signals that previously only the TUI
975975
- **Live plan** — for multi-step tasks the agent's plan appears as a small green card with status icons (`` pending, `` in progress, `` done) that update in place as work progresses.
976976
- **Reasoning stream** — when the model exposes a thinking trace (e.g. Claude extended thinking, GPT-5 reasoning), it shows up in a collapsible "Thinking" card above the answer. Closed by default; click to expand.
977977
- **Diff preview on permission prompts** — manual-mode permission cards now show a `-` / `+` diff for `edit_file`, a content preview for `write_file`, and the full `$ command` + `cwd` for `execute_command`, so users can verify before clicking *Allow*. Payload is truncated (~4 KB per field, 200 lines per file) with a visible marker. Other ACP clients (Zed, etc.) ignore the extra fields silently.
978+
- **`@file` mentions** — type `@` in the chat input to open a workspace-wide file picker. Pick with arrow keys + Enter; the file's content is inlined into the prompt as an `[Attached files]` preamble. Files over 200 KB are skipped with a marker. Multiple mentions in one message are deduplicated.
979+
- **Auto-reconnect** — if the CLI process exits unexpectedly (crash, OOM kill, parent restart), the extension reconnects on its own with exponential backoff (1s → 2s → 4s → 8s → 16s → 30s, capped at 6 attempts). The status bar shows the countdown. Configurable idle-watchdog timeout (`codeep.requestTimeoutMinutes`, default 5 min) replaces the old fixed cap so slow reasoning models don't get killed mid-thought.

src/acp/server.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ export function startAcpServer(): Promise<void> {
277277
case 'session/set_config_option': handleSetConfigOption(req); break;
278278
case 'session/list': handleSessionList(req); break;
279279
case 'session/delete': handleSessionDelete(req); break;
280+
case 'session/list_providers': handleListProviders(req); break;
280281
default:
281282
process.stderr.write(`[codeep-acp] Unknown method: ${req.method}\n`);
282283
transport.error(req.id, -32601, `Method not found: ${req.method}`);
@@ -563,6 +564,24 @@ export function startAcpServer(): Promise<void> {
563564
transport.respond(msg.id, {});
564565
}
565566

567+
// ── session/list_providers ──────────────────────────────────────────────────
568+
// Canonical provider list for ACP clients (Codeep VS Code extension etc.).
569+
// Lets the client populate its API-key dropdowns and group labels from one
570+
// source instead of carrying its own hardcoded copy. Keep this stable —
571+
// adding new fields is fine, removing/renaming would break existing clients.
572+
function handleListProviders(msg: JsonRpcRequest): void {
573+
const providers = Object.entries(PROVIDERS).map(([id, p]) => ({
574+
id,
575+
name: p.name,
576+
description: p.description,
577+
groupLabel: p.groupLabel ?? p.name,
578+
hint: p.hint ?? p.description,
579+
requiresKey: !p.noApiKey,
580+
subscribeUrl: p.subscribeUrl,
581+
}));
582+
transport.respond(msg.id, { providers });
583+
}
584+
566585
// ── session/prompt ──────────────────────────────────────────────────────────
567586

568587
async function handleSessionPrompt(msg: JsonRpcRequest): Promise<void> {

src/config/providers.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ export interface ProviderConfig {
3131
subscribeUrl?: string; // URL to get API key
3232
noApiKey?: boolean; // Provider doesn't require an API key (e.g. Ollama)
3333
dynamicModels?: boolean; // Models are fetched dynamically at runtime
34+
// UI metadata exposed to ACP clients (Codeep VS Code extension, etc.) so
35+
// they don't have to hardcode their own copy of the provider list. Keep these
36+
// strings short and human-readable — they show up in dropdowns and hints.
37+
groupLabel?: string; // Heading shown in grouped model selectors / settings
38+
hint?: string; // One-line hint about pricing/auth model
3439
mcpEndpoints?: { // Z.AI MCP service endpoints
3540
webSearch?: string;
3641
webReader?: string;
@@ -63,6 +68,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
6368
defaultProtocol: 'openai',
6469
envKey: 'ZAI_API_KEY',
6570
subscribeUrl: 'https://z.ai/subscribe?ic=NXYNXZOV14',
71+
groupLabel: 'Z.AI — Subscription (GLM Coding Plan)',
72+
hint: 'Uses your Z.AI subscription — no per-token charges.',
6673
mcpEndpoints: {
6774
webSearch: 'https://api.z.ai/api/mcp/web_search_prime/mcp',
6875
webReader: 'https://api.z.ai/api/mcp/web_reader/mcp',
@@ -88,6 +95,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
8895
defaultProtocol: 'openai',
8996
envKey: 'ZAI_API_KEY',
9097
subscribeUrl: 'https://api.z.ai',
98+
groupLabel: 'Z.AI — API (pay-per-use)',
99+
hint: 'Pay-per-use via Z.AI API key (zai.ai → API Keys).',
91100
},
92101
'z.ai-cn': {
93102
name: 'Z.AI China (ZhipuAI)',
@@ -113,6 +122,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
113122
defaultProtocol: 'openai',
114123
envKey: 'ZAI_CN_API_KEY',
115124
subscribeUrl: 'https://open.bigmodel.cn/glm-coding',
125+
groupLabel: 'Z.AI China — Subscription (GLM Coding Plan)',
126+
hint: 'Uses your ZhipuAI China subscription.',
116127
mcpEndpoints: {
117128
webSearch: 'https://open.bigmodel.cn/api/mcp/web_search_prime/mcp',
118129
webReader: 'https://open.bigmodel.cn/api/mcp/web_reader/mcp',
@@ -138,6 +149,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
138149
defaultProtocol: 'openai',
139150
envKey: 'ZAI_CN_API_KEY',
140151
subscribeUrl: 'https://open.bigmodel.cn',
152+
groupLabel: 'Z.AI China — API (pay-per-use)',
153+
hint: 'Pay-per-use via ZhipuAI China API key.',
141154
},
142155
'minimax': {
143156
name: 'MiniMax',
@@ -161,6 +174,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
161174
defaultProtocol: 'anthropic',
162175
envKey: 'MINIMAX_API_KEY',
163176
subscribeUrl: 'https://platform.minimax.io/subscribe/coding-plan?code=2lWvoWUhrp&source=link',
177+
groupLabel: 'MiniMax — Subscription',
178+
hint: 'Uses your MiniMax subscription — no per-token charges.',
164179
},
165180
'minimax-api': {
166181
name: 'MiniMax API (pay-per-use)',
@@ -179,6 +194,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
179194
defaultProtocol: 'openai',
180195
envKey: 'MINIMAX_API_KEY',
181196
subscribeUrl: 'https://platform.minimax.io',
197+
groupLabel: 'MiniMax — API (pay-per-use)',
198+
hint: 'Pay-per-use via MiniMax API key (minimaxi.com → API Keys).',
182199
},
183200
'minimax-cn': {
184201
name: 'MiniMax China',
@@ -202,6 +219,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
202219
defaultProtocol: 'anthropic',
203220
envKey: 'MINIMAX_CN_API_KEY',
204221
subscribeUrl: 'https://platform.minimaxi.com',
222+
groupLabel: 'MiniMax China — Subscription',
223+
hint: 'Uses your MiniMax China subscription.',
205224
},
206225
'deepseek': {
207226
name: 'DeepSeek',
@@ -227,6 +246,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
227246
maxOutputTokens: 384_000, // DeepSeek V4 max output
228247
envKey: 'DEEPSEEK_API_KEY',
229248
subscribeUrl: 'https://platform.deepseek.com/sign_up',
249+
groupLabel: 'DeepSeek',
250+
hint: 'Pay-per-use via DeepSeek API key (platform.deepseek.com).',
230251
},
231252
'openai': {
232253
name: 'OpenAI',
@@ -250,6 +271,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
250271
requiresDefaultTemperature: true,
251272
envKey: 'OPENAI_API_KEY',
252273
subscribeUrl: 'https://platform.openai.com/api-keys',
274+
groupLabel: 'OpenAI',
275+
hint: 'Pay-per-use via OpenAI API key (platform.openai.com).',
253276
},
254277
'anthropic': {
255278
name: 'Anthropic',
@@ -270,6 +293,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
270293
defaultModel: 'claude-opus-4-7',
271294
defaultProtocol: 'anthropic',
272295
envKey: 'ANTHROPIC_API_KEY',
296+
groupLabel: 'Anthropic',
297+
hint: 'Pay-per-use via Anthropic API key (console.anthropic.com).',
273298
},
274299
'google': {
275300
name: 'Google AI',
@@ -289,6 +314,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
289314
defaultProtocol: 'openai',
290315
envKey: 'GOOGLE_API_KEY',
291316
subscribeUrl: 'https://aistudio.google.com/apikey',
317+
groupLabel: 'Google AI',
318+
hint: 'Pay-per-use via Google AI API key (aistudio.google.com).',
292319
},
293320
'ollama': {
294321
name: 'Ollama (local)',
@@ -307,6 +334,8 @@ export const PROVIDERS: Record<string, ProviderConfig> = {
307334
defaultProtocol: 'openai',
308335
noApiKey: true,
309336
dynamicModels: true,
337+
groupLabel: 'Ollama (local)',
338+
hint: 'Runs locally — no API key or account needed.',
310339
},
311340
};
312341

0 commit comments

Comments
 (0)