codeep 1.2.75 → 1.2.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,7 +25,8 @@
25
25
  - **Z.AI (ZhipuAI)** — GLM-5, GLM-4.7, GLM-4.7 Flash (international & China endpoints)
26
26
  - **MiniMax** — MiniMax M2.5 (international & China endpoints)
27
27
  - **DeepSeek** — DeepSeek V3, DeepSeek R1 (reasoning)
28
- - **Anthropic** — Claude Sonnet 4.6, Claude Opus 4.6, Claude Haiku 4.5
28
+ - **Anthropic** — Claude Sonnet 4.6, Claude Opus 4.6, Claude Sonnet 4.5, Claude Haiku 4.5
29
+ - **Google AI** — Gemini 3.1 Pro Preview, Gemini 3 Pro Preview, Gemini 3 Flash Preview, Gemini 2.5 Pro, Gemini 2.5 Flash, Gemini 2.5 Flash Lite
29
30
  - Switch between providers with `/provider`
30
31
  - Configure different API keys per provider
31
32
  - Both OpenAI-compatible and Anthropic API protocols supported
@@ -668,6 +669,7 @@ With write access enabled:
668
669
  | `MINIMAX_CN_API_KEY` | MiniMax China API key |
669
670
  | `DEEPSEEK_API_KEY` | DeepSeek API key |
670
671
  | `ANTHROPIC_API_KEY` | Anthropic Claude API key |
672
+ | `GOOGLE_API_KEY` | Google AI (Gemini) API key |
671
673
 
672
674
  ### Settings (`/settings`)
673
675
 
@@ -7,6 +7,7 @@ import { runAgentSession } from './session.js';
7
7
  import { executeCommandAsync } from '../utils/shell.js';
8
8
  import { initWorkspace, loadWorkspace, handleCommand } from './commands.js';
9
9
  import { autoSaveSession, config, setProvider, listSessionsWithInfo, deleteSession as deleteSessionFile } from '../config/index.js';
10
+ import { ApiError } from '../api/index.js';
10
11
  import { PROVIDERS } from '../config/providers.js';
11
12
  import { getCurrentVersion } from '../utils/update.js';
12
13
  // ─── Slash commands advertised to Zed ────────────────────────────────────────
@@ -149,6 +150,7 @@ export function startAcpServer() {
149
150
  handleSessionDelete(req);
150
151
  break;
151
152
  default:
153
+ process.stderr.write(`[codeep-acp] Unknown method: ${req.method}\n`);
152
154
  transport.error(req.id, -32601, `Method not found: ${req.method}`);
153
155
  }
154
156
  });
@@ -575,6 +577,14 @@ export function startAcpServer() {
575
577
  if (err.name === 'AbortError') {
576
578
  transport.respond(msg.id, { stopReason: 'cancelled' });
577
579
  }
580
+ else if (err.message?.includes('API key not configured') || err.message?.includes('API key') || (err instanceof ApiError && err.status === 401)) {
581
+ sendChunk(`❌ No API key configured. Use /login <provider> <key> or set the environment variable (e.g. ZAI_API_KEY, ANTHROPIC_API_KEY).`);
582
+ transport.respond(msg.id, { stopReason: 'end_turn' });
583
+ }
584
+ else if (err instanceof ApiError && err.status >= 500) {
585
+ sendChunk(`⚠️ API server error (${err.status}). Please try again.`);
586
+ transport.respond(msg.id, { stopReason: 'end_turn' });
587
+ }
578
588
  else {
579
589
  transport.error(msg.id, -32000, err.message);
580
590
  }
@@ -584,7 +594,17 @@ export function startAcpServer() {
584
594
  });
585
595
  })
586
596
  .catch((err) => {
587
- transport.error(msg.id, -32000, err.message);
597
+ if (err.message?.includes('API key not configured') || err.message?.includes('API key') || (err instanceof ApiError && err.status === 401)) {
598
+ sendChunk(`❌ No API key configured. Use /login <provider> <key> or set the environment variable (e.g. ZAI_API_KEY, ANTHROPIC_API_KEY).`);
599
+ transport.respond(msg.id, { stopReason: 'end_turn' });
600
+ }
601
+ else if (err instanceof ApiError && err.status >= 500) {
602
+ sendChunk(`⚠️ API server error (${err.status}). Please try again.`);
603
+ transport.respond(msg.id, { stopReason: 'end_turn' });
604
+ }
605
+ else {
606
+ transport.error(msg.id, -32000, err.message);
607
+ }
588
608
  if (session)
589
609
  session.abortController = null;
590
610
  });
@@ -148,9 +148,15 @@ export async function runAgentSession(opts) {
148
148
  if (result.finalResponse && chunksEmitted === 0) {
149
149
  opts.onChunk(result.finalResponse);
150
150
  }
151
- // Surface errors as thrown exceptions so index.ts can handle them correctly
151
+ // Surface errors as thrown exceptions so the ACP server can handle them correctly.
152
+ // Exception: if finalResponse was already sent as a chunk (e.g. "Agent reached the
153
+ // iteration limit", "Agent stopped due to repeated API timeouts"), don't also throw —
154
+ // the user already received the explanation and Zed would show a confusing second error.
152
155
  if (!result.success && !result.aborted) {
153
- throw new Error(result.error ?? 'Agent run failed without a specific error message');
156
+ const alreadyExplained = result.finalResponse && chunksEmitted > 0;
157
+ if (!alreadyExplained) {
158
+ throw new Error(result.error ?? 'Agent run failed without a specific error message');
159
+ }
154
160
  }
155
161
  if (result.aborted) {
156
162
  const abortError = new Error('Agent session was cancelled');
@@ -11,6 +11,7 @@ const debug = (...args) => {
11
11
  };
12
12
  // Import chat layer (prompt building + API calls)
13
13
  import { agentChat, getAgentSystemPrompt, getFallbackSystemPrompt, loadProjectRules, formatChatHistoryForAgent, } from './agentChat.js';
14
+ import { ApiError } from '../api/index.js';
14
15
  export { loadProjectRules, formatChatHistoryForAgent };
15
16
  /**
16
17
  * Calculate dynamic timeout based on task complexity
@@ -287,6 +288,17 @@ export async function runAgent(prompt, projectContext, options = {}) {
287
288
  await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
288
289
  continue;
289
290
  }
291
+ // Don't retry on 4xx client errors except 429 (rate limit)
292
+ if (err instanceof ApiError && err.status >= 400 && err.status < 500 && err.status !== 429) {
293
+ result = {
294
+ success: false,
295
+ iterations: iteration,
296
+ actions,
297
+ finalResponse: '',
298
+ error: err.message,
299
+ };
300
+ return result;
301
+ }
290
302
  // All non-abort errors are retryable — retry with backoff
291
303
  retryCount++;
292
304
  const isRateLimit = err.message.includes('429');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeep",
3
- "version": "1.2.75",
3
+ "version": "1.2.77",
4
4
  "description": "AI-powered coding assistant built for the terminal. Multiple LLM providers, project-aware context, and a seamless development workflow.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",