codeep 2.4.0 → 2.4.2

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
@@ -48,12 +48,12 @@ custom slash commands, lifecycle hooks, checkpoints, `/cost`,
48
48
  ## Features
49
49
 
50
50
  ### Multi-Provider Support
51
- - **Z.AI (ZhipuAI)** — GLM-5.1, GLM-5, GLM-5 Turbo, GLM-4.5 Air — Coding Plan & pay-per-use API (international & China)
52
- - **OpenAI** — GPT-5.5, GPT-5.4, GPT-5.4 Mini, GPT-5.4 Nano
53
- - **Anthropic** — Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 4.6, Claude Haiku 4.5
54
- - **DeepSeek** — DeepSeek V4 Pro, DeepSeek V4 Flash
55
- - **Google AI** — Gemini 3.1 Pro Preview, Gemini 3 Flash Preview, Gemini 2.5 Pro, Gemini 2.5 Flash
56
- - **MiniMax** — MiniMax M2.7, M2.5, M2.1, M2 — Coding Plan & pay-per-use API (international & China)
51
+ - **Z.AI (ZhipuAI)** — GLM models (Coding Plan & pay-per-use API, international & China)
52
+ - **OpenAI** — GPT models (flagship, Mini, Nano)
53
+ - **Anthropic** — Claude models (Opus, Sonnet, Haiku)
54
+ - **DeepSeek** — DeepSeek models (Pro, Flash)
55
+ - **Google AI** — Gemini models (Pro, Flash)
56
+ - **MiniMax** — MiniMax models (Coding Plan & pay-per-use API, international & China)
57
57
  - **Ollama** — Run any model locally or on a remote server, no API key required. Models are fetched dynamically from your Ollama instance.
58
58
  - **OpenRouter** — One key, 100+ models from Anthropic, OpenAI, Google, Meta, Mistral, DeepSeek, Qwen, xAI and more. Per-call cost reported directly by OpenRouter (matches their dashboard exactly). Use `openrouter/auto` to let OpenRouter pick the best model. Tune routing with `/openrouter prefer|ignore|fallbacks|privacy`.
59
59
  - **Custom (OpenAI-compatible)** — Point Codeep at any self-hosted or proxied OpenAI-compatible endpoint (vLLM, LiteLLM, LM Studio, text-generation-webui). Set the base URL in `/settings` → **Custom Base URL** (config key `customBaseUrl`, e.g. `http://host:8000/v1`), then pick your model with `/model` (fetched from the server's `/models`). No API key required unless your endpoint enforces one. The `openai` provider also honors the `OPENAI_BASE_URL` env var for proxies that serve `gpt-*` model names.
@@ -126,9 +126,9 @@ export const PROVIDERS = {
126
126
  },
127
127
  },
128
128
  models: [
129
- { id: 'MiniMax-M2.7', name: 'MiniMax M2.7', description: 'Latest MiniMax model' },
129
+ { id: 'MiniMax-M3', name: 'MiniMax M3', description: 'Latest MiniMax model' },
130
130
  ],
131
- defaultModel: 'MiniMax-M2.7',
131
+ defaultModel: 'MiniMax-M3',
132
132
  defaultProtocol: 'anthropic',
133
133
  envKey: 'MINIMAX_API_KEY',
134
134
  subscribeUrl: 'https://platform.minimax.io/subscribe/coding-plan?code=2lWvoWUhrp&source=link',
@@ -146,9 +146,9 @@ export const PROVIDERS = {
146
146
  },
147
147
  },
148
148
  models: [
149
- { id: 'MiniMax-M2.7', name: 'MiniMax M2.7', description: 'Latest MiniMax model' },
149
+ { id: 'MiniMax-M3', name: 'MiniMax M3', description: 'Latest MiniMax model' },
150
150
  ],
151
- defaultModel: 'MiniMax-M2.7',
151
+ defaultModel: 'MiniMax-M3',
152
152
  defaultProtocol: 'openai',
153
153
  envKey: 'MINIMAX_API_KEY',
154
154
  subscribeUrl: 'https://platform.minimax.io',
@@ -171,9 +171,9 @@ export const PROVIDERS = {
171
171
  },
172
172
  },
173
173
  models: [
174
- { id: 'MiniMax-M2.7', name: 'MiniMax M2.7', description: 'Latest MiniMax model' },
174
+ { id: 'MiniMax-M3', name: 'MiniMax M3', description: 'Latest MiniMax model' },
175
175
  ],
176
- defaultModel: 'MiniMax-M2.7',
176
+ defaultModel: 'MiniMax-M3',
177
177
  defaultProtocol: 'anthropic',
178
178
  envKey: 'MINIMAX_CN_API_KEY',
179
179
  subscribeUrl: 'https://platform.minimaxi.com',
@@ -825,6 +825,43 @@ async function gracefulShutdown() {
825
825
  }),
826
826
  ]);
827
827
  }
828
+ // ─── Last-resort crash handlers ───────────────────────────────────────────────
829
+ // Without these, a stray throw or rejected promise (deep in the agent loop or a
830
+ // background cloud sync) crashes Node with the terminal still in raw mode +
831
+ // alternate screen — leaving the user's shell garbled — or vanishes silently.
832
+ process.on('uncaughtException', (error) => {
833
+ logAppError(error instanceof Error ? error : new Error(String(error)), 'uncaughtException');
834
+ // After an uncaught exception the process state is undefined; Node's guidance
835
+ // is to clean up synchronously and exit rather than limp on. Restore the
836
+ // terminal and best-effort save the conversation so the crash doesn't lose it.
837
+ try {
838
+ if (app)
839
+ app.stop();
840
+ }
841
+ catch { /* ignore */ }
842
+ try {
843
+ process.stdout.write('\x1b[2J\x1b[3J\x1b[H');
844
+ }
845
+ catch { /* ignore */ }
846
+ console.error('Fatal error:', error);
847
+ try {
848
+ if (app)
849
+ autoSaveSession(app.getMessages(), projectPath);
850
+ }
851
+ catch { /* ignore */ }
852
+ process.exit(1);
853
+ });
854
+ process.on('unhandledRejection', (reason) => {
855
+ logAppError(reason instanceof Error ? reason : new Error(String(reason)), 'unhandledRejection');
856
+ // A rejected promise is usually recoverable (failed background sync, network
857
+ // blip), so surface it and keep the TUI alive instead of tearing it down.
858
+ // Fall back to stderr if the app isn't up yet.
859
+ const message = reason instanceof Error ? reason.message : String(reason);
860
+ if (app)
861
+ app.notifyWarn(`Background error: ${message}`);
862
+ else
863
+ console.error('Unhandled rejection:', reason);
864
+ });
828
865
  process.on('SIGINT', () => {
829
866
  gracefulShutdown().finally(() => process.exit(0));
830
867
  });
@@ -68,10 +68,13 @@ export async function runAccountFlow() {
68
68
  if (!res.ok)
69
69
  continue;
70
70
  const data = await res.json();
71
- if (data.status === 'authorized' && data.github_id) {
71
+ // Require the sync token, not just github_id: the server can briefly
72
+ // report authorized after claiming the code but before the token is
73
+ // issued. Linking without it leaves `account sync` broken ("Not linked"),
74
+ // so keep polling until the token is present.
75
+ if (data.status === 'authorized' && data.github_id && data.sync_token) {
72
76
  setGithubAccount(data.github_id, data.username ?? '');
73
- if (data.sync_token)
74
- setSyncToken(data.sync_token);
77
+ setSyncToken(data.sync_token);
75
78
  // Register device info
76
79
  try {
77
80
  await fetch(`${API_BASE}/api/auth/cli/device`, {
@@ -29,7 +29,7 @@ const MODEL_CONTEXT_WINDOWS = {
29
29
  'gemini-3.5-flash': 1_000_000,
30
30
  'gemini-3-flash-preview': 1_000_000,
31
31
  // MiniMax
32
- 'MiniMax-M2.7': 204_800,
32
+ 'MiniMax-M3': 524_288,
33
33
  };
34
34
  const DEFAULT_CONTEXT_WINDOW = 128_000;
35
35
  /**
@@ -65,7 +65,7 @@ const MODEL_PRICING = {
65
65
  'gemini-3.5-flash': { inputPer1M: 1.50, outputPer1M: 9.00 },
66
66
  'gemini-3-flash-preview': { inputPer1M: 0.50, outputPer1M: 3.00 },
67
67
  // MiniMax
68
- 'MiniMax-M2.7': { inputPer1M: 0.30, outputPer1M: 1.20 },
68
+ 'MiniMax-M3': { inputPer1M: 0.60, outputPer1M: 2.40 },
69
69
  };
70
70
  export function getPricingTable() {
71
71
  return Object.entries(MODEL_PRICING).map(([model, p]) => ({ model, ...p }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeep",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
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",