jinzd-ai-cli 0.4.142 → 0.4.144
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 +2 -2
- package/README.zh-CN.md +1 -1
- package/dist/{batch-MJUH762U.js → batch-64YESATH.js} +2 -2
- package/dist/{chunk-KSLJCZCE.js → chunk-2JPLV25X.js} +1 -1
- package/dist/{chunk-BJAT4GNC.js → chunk-DQ2OHJNF.js} +15 -0
- package/dist/{chunk-INPG2HXR.js → chunk-EHLHWFZP.js} +1 -1
- package/dist/{chunk-3UZBSMNI.js → chunk-HUILGJNB.js} +1 -1
- package/dist/{chunk-DES5NNPU.js → chunk-IGZVCNGE.js} +2 -2
- package/dist/{chunk-MO7MWNWC.js → chunk-NKR53CPL.js} +1 -1
- package/dist/{chunk-6VRJGH25.js → chunk-OVWE4E46.js} +15 -0
- package/dist/{chunk-Q3ZEZHSU.js → chunk-PWCPOHZ4.js} +7 -7
- package/dist/{chunk-G3CH252E.js → chunk-QSGDXXE6.js} +1 -1
- package/dist/{chunk-RFQVUMDB.js → chunk-SEFOKYYP.js} +276 -5
- package/dist/{chunk-3BICTI5M.js → chunk-UQQJWHRV.js} +1 -1
- package/dist/{chunk-NHNWUBXB.js → chunk-VNNYHW6N.js} +276 -5
- package/dist/{chunk-WLZJANJO.js → chunk-WPYKTLP2.js} +22 -2
- package/dist/{chunk-NSTXHD33.js → chunk-XW4EP5IE.js} +1 -1
- package/dist/{chunk-UXGHSFGB.js → chunk-YGGW2D2V.js} +1 -1
- package/dist/{constants-QDFO3IJP.js → constants-7Q5DB2X6.js} +1 -1
- package/dist/{doctor-cli-CLKZYOOI.js → doctor-cli-RHGMQVCU.js} +5 -5
- package/dist/electron-server.js +30 -10
- package/dist/{hub-X4ISNM7B.js → hub-SXNKYCN7.js} +1 -1
- package/dist/index.js +234 -33
- package/dist/{indexer-Z6AQTGBK.js → indexer-ISSNIFQY.js} +2 -2
- package/dist/{indexer-XGY7XGJM.js → indexer-S6UMGQKA.js} +2 -2
- package/dist/{run-tests-3AYPKO5U.js → run-tests-SUYREW3B.js} +1 -1
- package/dist/{run-tests-QER6ETNZ.js → run-tests-X4YQXIGP.js} +2 -2
- package/dist/{semantic-FR2ZSQLY.js → semantic-IJKF5ZZC.js} +2 -2
- package/dist/{semantic-UFKVYKFE.js → semantic-V37U4MCW.js} +2 -2
- package/dist/{server-PBOIZFFD.js → server-MGKTVVAR.js} +7 -7
- package/dist/{server-FFPJP2GQ.js → server-X24SIKZE.js} +14 -14
- package/dist/{store-Q7NMUCPP.js → store-A3TZM6PS.js} +1 -1
- package/dist/{store-JDEW743P.js → store-VMK543OQ.js} +1 -1
- package/dist/{task-orchestrator-O4FTLSHK.js → task-orchestrator-R6VOCA4V.js} +7 -7
- package/dist/wasm/tree-sitter-cpp.wasm +0 -0
- package/dist/wasm/tree-sitter-go.wasm +0 -0
- package/dist/wasm/tree-sitter-java.wasm +0 -0
- package/dist/wasm/tree-sitter-rust.wasm +0 -0
- package/package.json +6 -2
package/dist/index.js
CHANGED
|
@@ -16,12 +16,12 @@ import {
|
|
|
16
16
|
saveDevState,
|
|
17
17
|
sessionHasMeaningfulContent,
|
|
18
18
|
setupProxy
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-IGZVCNGE.js";
|
|
20
20
|
import {
|
|
21
21
|
getConfigDirUsage,
|
|
22
22
|
listRecentCrashes,
|
|
23
23
|
writeCrashLog
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-HUILGJNB.js";
|
|
25
25
|
import {
|
|
26
26
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
27
27
|
HALLUCINATION_CORRECTION_MESSAGE,
|
|
@@ -39,10 +39,10 @@ import {
|
|
|
39
39
|
looksLikeDocumentBody,
|
|
40
40
|
stripPseudoToolCalls,
|
|
41
41
|
stripToolCallReminder
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-EHLHWFZP.js";
|
|
43
43
|
import {
|
|
44
44
|
ConfigManager
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-WPYKTLP2.js";
|
|
46
46
|
import {
|
|
47
47
|
ToolExecutor,
|
|
48
48
|
ToolRegistry,
|
|
@@ -61,17 +61,21 @@ import {
|
|
|
61
61
|
spawnAgentContext,
|
|
62
62
|
theme,
|
|
63
63
|
undoStack
|
|
64
|
-
} from "./chunk-
|
|
65
|
-
import "./chunk-
|
|
64
|
+
} from "./chunk-PWCPOHZ4.js";
|
|
65
|
+
import "./chunk-UQQJWHRV.js";
|
|
66
66
|
import "./chunk-2DXY7UGF.js";
|
|
67
|
-
import "./chunk-
|
|
67
|
+
import "./chunk-2JPLV25X.js";
|
|
68
68
|
import {
|
|
69
69
|
getStatsSnapshot,
|
|
70
70
|
getTopFailingTools,
|
|
71
71
|
getTopUsedTools,
|
|
72
72
|
installFlushOnExit
|
|
73
|
-
} from "./chunk-
|
|
74
|
-
import
|
|
73
|
+
} from "./chunk-QSGDXXE6.js";
|
|
74
|
+
import {
|
|
75
|
+
AuthError,
|
|
76
|
+
ProviderError,
|
|
77
|
+
RateLimitError
|
|
78
|
+
} from "./chunk-2ZD3YTVM.js";
|
|
75
79
|
import {
|
|
76
80
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
77
81
|
AUTHOR,
|
|
@@ -93,7 +97,7 @@ import {
|
|
|
93
97
|
SKILLS_DIR_NAME,
|
|
94
98
|
VERSION,
|
|
95
99
|
buildUserIdentityPrompt
|
|
96
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-XW4EP5IE.js";
|
|
97
101
|
import {
|
|
98
102
|
formatGitContextForPrompt,
|
|
99
103
|
getGitContext,
|
|
@@ -111,8 +115,8 @@ import {
|
|
|
111
115
|
searchChatMemory
|
|
112
116
|
} from "./chunk-7ZJN4KLV.js";
|
|
113
117
|
import "./chunk-KHYD3WXE.js";
|
|
114
|
-
import "./chunk-
|
|
115
|
-
import "./chunk-
|
|
118
|
+
import "./chunk-VNNYHW6N.js";
|
|
119
|
+
import "./chunk-OVWE4E46.js";
|
|
116
120
|
import "./chunk-PDX44BCA.js";
|
|
117
121
|
|
|
118
122
|
// src/index.ts
|
|
@@ -317,7 +321,7 @@ var Renderer = class {
|
|
|
317
321
|
console.log(theme.dim(" Gemini (Google) \xB7 Zhipu (GLM) \xB7 OpenRouter \xB7 Ollama (Local, no API key)"));
|
|
318
322
|
console.log(HR);
|
|
319
323
|
const mcpToolCount = mcpInfo?.tools ?? 0;
|
|
320
|
-
const toolTotal =
|
|
324
|
+
const toolTotal = 30 + pluginCount + mcpToolCount;
|
|
321
325
|
const extras = [];
|
|
322
326
|
if (pluginCount > 0) extras.push(`${pluginCount} plugin(s)`);
|
|
323
327
|
if (mcpToolCount > 0) extras.push(`${mcpToolCount} MCP`);
|
|
@@ -332,6 +336,7 @@ var Renderer = class {
|
|
|
332
336
|
console.log(tool("glob_files", "Match file paths by glob pattern"));
|
|
333
337
|
console.log(tool("run_interactive", "Run programs requiring stdin interaction (direct spawn)"));
|
|
334
338
|
console.log(tool("web_fetch", "Fetch web content (converted to Markdown)"));
|
|
339
|
+
console.log(tool("web_search", "Search web via Bing/Google scraping \u2014 no API key, structured {title,url,snippet} results (v0.4.135+)"));
|
|
335
340
|
console.log(tool("google_search", "Google search (requires API Key + CX config)"));
|
|
336
341
|
console.log(tool("save_last_response", "Save AI response to file (tee streaming to disk)"));
|
|
337
342
|
console.log(tool("save_memory", "Persist important info to ~/.aicli/memory.md, auto-injected across sessions"));
|
|
@@ -347,19 +352,19 @@ var Renderer = class {
|
|
|
347
352
|
console.log(tool("git_log", "Show commit history (oneline/full, filter by file/author)"));
|
|
348
353
|
console.log(tool("git_commit", "Create a git commit (stage files, message, stage_all)"));
|
|
349
354
|
console.log(tool("notebook_edit", "Edit Jupyter notebook cells (add/edit/delete/move)"));
|
|
350
|
-
console.log(tool("find_symbol", "Locate symbol definitions via persistent tree-sitter index (TS/JS/TSX/Python)"));
|
|
355
|
+
console.log(tool("find_symbol", "Locate symbol definitions via persistent tree-sitter index (TS/JS/TSX/Python/Go/Rust/Java/C++)"));
|
|
351
356
|
console.log(tool("get_outline", "Enumerate all top-level declarations in one source file"));
|
|
352
357
|
console.log(tool("find_references", "Search indexed files for references to a symbol name"));
|
|
353
358
|
console.log(tool("search_code", 'Semantic (meaning-based) code search via local embeddings \u2014 "grep by meaning", bilingual'));
|
|
354
359
|
console.log(tool("recall_memory", 'Semantic recall over past chat sessions \u2014 "remember when we discussed X" across history (v0.4.89+)'));
|
|
355
360
|
console.log(HR);
|
|
356
|
-
console.log(theme.dim(" REPL Commands (
|
|
361
|
+
console.log(theme.dim(" REPL Commands (45):"));
|
|
357
362
|
console.log(theme.dim(" /help /about /provider /model /route /clear /compact /plan"));
|
|
358
363
|
console.log(theme.dim(" /session /system /context /status /search /undo /export /copy"));
|
|
359
364
|
console.log(theme.dim(" /paste /cost /init /skill /tools /plugins /mcp /config"));
|
|
360
365
|
console.log(theme.dim(" /checkpoint /review /security-review /security /rewind /commands"));
|
|
361
366
|
console.log(theme.dim(" /test /scaffold /add-dir /memory /profile /doctor /bug /think"));
|
|
362
|
-
console.log(theme.dim(" /diff /fork /branch /index /yolo /exit"));
|
|
367
|
+
console.log(theme.dim(" /diff /fork /branch /index /yolo /snapshot /exit"));
|
|
363
368
|
console.log(HR);
|
|
364
369
|
console.log(theme.dim(" Key Features:"));
|
|
365
370
|
console.log(feat("Agentic loop (up to 200 tool-call rounds, configurable via config/CLI, final answer streamed)"));
|
|
@@ -431,7 +436,7 @@ var Renderer = class {
|
|
|
431
436
|
console.log(feat("Conversation Branching (B2, v0.4.74+): /branch list/new/switch/delete/rename \u2014 fork the conversation at any message; Web UI replay \u{1F33F} fork-here button"));
|
|
432
437
|
console.log(feat("Branch tree sidebar (B2 polish, v0.4.75+): Web UI \u{1F33F} Branches tab with tree-indented picker, click to switch, hover to rename/delete, + Fork button"));
|
|
433
438
|
console.log(feat("Cross-branch ops (B3, v0.4.80+): /branch diff and /branch cherry-pick \u2014 compare branches and pick messages across forks; v0.4.81 accepts id/title/prefix"));
|
|
434
|
-
console.log(feat("MCP Server mode (E1, v0.4.84+): aicli mcp-serve \u2014 reverse aicli into an MCP server so Claude Desktop/Cursor/any MCP client can use its
|
|
439
|
+
console.log(feat("MCP Server mode (E1, v0.4.84+): aicli mcp-serve \u2014 reverse aicli into an MCP server so Claude Desktop/Cursor/any MCP client can use its 28 built-in tools (excluding ask_user/spawn_agent which need interactive stdin)"));
|
|
435
440
|
console.log(feat("Session sensitive-data redaction (v0.4.88+): unified redactor scrubs passwords/tokens/keys from every message before it hits disk; /security status and scan to audit"));
|
|
436
441
|
console.log(feat('Chat memory recall (B4, v0.4.89+): "human-like long-term memory" \u2014 semantic index over all past sessions + recall_memory AI tool + /memory rebuild|refresh|status|recall, AI auto-recalls on "last time"/"\u4E0A\u6B21"'));
|
|
437
442
|
console.log(feat("Web UI Memory panel (B4, v0.4.90+): \u{1F9E0} Memory sidebar tab \u2014 cross-session semantic search with \u2795 Inject-to-input (quotes hit into chat box for user-reviewed recall) and \u2197 jump-to-session"));
|
|
@@ -443,6 +448,7 @@ var Renderer = class {
|
|
|
443
448
|
console.log(feat("Tool history ordering (v0.4.100+): preserve original tool-call order across multi-turn rounds \u2014 fixes reasoning drift on long agentic loops"));
|
|
444
449
|
console.log(feat("save_last_response Web mode (v0.4.101\u20130.4.102+): hidden from CLI-only contexts and tee-streams chunks to disk in Web UI as the response arrives"));
|
|
445
450
|
console.log(feat("write_file long-content guidance (v0.4.103+): tool description no longer encourages AI to chunk long files \u2014 single-shot writes prevented from being split into truncated parts"));
|
|
451
|
+
console.log(feat("Provider retry + fallback chain (v0.4.144+): transient network / 5xx / 429 errors retry on the same provider with exponential backoff; persistent failures walk config.fallback.chain (per-entry provider+model). Opt-in via config.fallback.enabled. Stream-safe: never retries after first chunk yielded"));
|
|
446
452
|
console.log();
|
|
447
453
|
}
|
|
448
454
|
printPrompt(provider, _model) {
|
|
@@ -1122,6 +1128,7 @@ function createDefaultCommands() {
|
|
|
1122
1128
|
["/branch [list|new|switch|delete|rename|diff|cherry-pick]", "Conversation branches"],
|
|
1123
1129
|
["/rewind [list|<n>]", "Rewind to message N (restores files too)"],
|
|
1124
1130
|
["/export [md|json] [file]", "Export session to file"],
|
|
1131
|
+
["/snapshot", "Save dev-state handoff snapshot now (auto-runs on /exit)"],
|
|
1125
1132
|
["/cost [reset|history]", "Session token usage / cost dashboard"],
|
|
1126
1133
|
["/status", "Show current status"]
|
|
1127
1134
|
]
|
|
@@ -1812,7 +1819,7 @@ No tools match "${filter}".
|
|
|
1812
1819
|
const { join: join6 } = await import("path");
|
|
1813
1820
|
const { existsSync: existsSync6 } = await import("fs");
|
|
1814
1821
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-7KIP4X2V.js");
|
|
1815
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
1822
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-7Q5DB2X6.js");
|
|
1816
1823
|
const { approveProject, hashMcpFile } = await import("./project-trust-IFM7FXEV.js");
|
|
1817
1824
|
const cwd = process.cwd();
|
|
1818
1825
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
@@ -2746,8 +2753,8 @@ ${hint}` : "")
|
|
|
2746
2753
|
async execute(args, ctx) {
|
|
2747
2754
|
const sub = (args[0] ?? "status").toLowerCase();
|
|
2748
2755
|
const root = process.cwd();
|
|
2749
|
-
const { loadIndex, clearIndex } = await import("./store-
|
|
2750
|
-
const { indexProject } = await import("./indexer-
|
|
2756
|
+
const { loadIndex, clearIndex } = await import("./store-VMK543OQ.js");
|
|
2757
|
+
const { indexProject } = await import("./indexer-S6UMGQKA.js");
|
|
2751
2758
|
const { loadVectorStore, clearVectorStore } = await import("./vector-store-MCQ77OOJ.js");
|
|
2752
2759
|
if (sub === "status") {
|
|
2753
2760
|
const idx = loadIndex(root);
|
|
@@ -2807,7 +2814,7 @@ ${hint}` : "")
|
|
|
2807
2814
|
}
|
|
2808
2815
|
console.log(theme.dim(` Building semantic index for ${idx.symbolCount} symbols\u2026`));
|
|
2809
2816
|
console.log(theme.dim(" (First run downloads ~117 MB embedding model to ~/.aicli/models/)"));
|
|
2810
|
-
const { rebuildSemanticIndex } = await import("./semantic-
|
|
2817
|
+
const { rebuildSemanticIndex } = await import("./semantic-V37U4MCW.js");
|
|
2811
2818
|
try {
|
|
2812
2819
|
const stats = await rebuildSemanticIndex(root, {
|
|
2813
2820
|
onProgress: (done, total) => {
|
|
@@ -2873,7 +2880,7 @@ ${hint}` : "")
|
|
|
2873
2880
|
usage: "/test [command|filter]",
|
|
2874
2881
|
async execute(args, ctx) {
|
|
2875
2882
|
try {
|
|
2876
|
-
const { executeTests } = await import("./run-tests-
|
|
2883
|
+
const { executeTests } = await import("./run-tests-X4YQXIGP.js");
|
|
2877
2884
|
const argStr = args.join(" ").trim();
|
|
2878
2885
|
let testArgs = {};
|
|
2879
2886
|
if (argStr) {
|
|
@@ -4462,6 +4469,154 @@ function stripRoutingTags(message) {
|
|
|
4462
4469
|
return message.replace(/(?:^|\s)#(fast|deep|default)\b/gi, " ").replace(/\s{2,}/g, " ").trim();
|
|
4463
4470
|
}
|
|
4464
4471
|
|
|
4472
|
+
// src/providers/fallback.ts
|
|
4473
|
+
var TRANSIENT_CODES = /* @__PURE__ */ new Set([
|
|
4474
|
+
"ECONNRESET",
|
|
4475
|
+
"ETIMEDOUT",
|
|
4476
|
+
"EAI_AGAIN",
|
|
4477
|
+
"EHOSTUNREACH",
|
|
4478
|
+
"ENOTFOUND",
|
|
4479
|
+
"EPIPE",
|
|
4480
|
+
"ECONNREFUSED",
|
|
4481
|
+
"EHOSTDOWN",
|
|
4482
|
+
"ENETUNREACH",
|
|
4483
|
+
"UND_ERR_SOCKET",
|
|
4484
|
+
// undici socket errors
|
|
4485
|
+
"UND_ERR_CONNECT_TIMEOUT"
|
|
4486
|
+
]);
|
|
4487
|
+
function classifyError(err) {
|
|
4488
|
+
if (err == null) return "unknown";
|
|
4489
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4490
|
+
let cur = err;
|
|
4491
|
+
for (let i = 0; i < 5 && cur && !seen.has(cur); i++) {
|
|
4492
|
+
seen.add(cur);
|
|
4493
|
+
const e = cur;
|
|
4494
|
+
if (e.name === "AbortError" || e.code === "ABORT_ERR") return "aborted";
|
|
4495
|
+
if (err instanceof AuthError) return "auth";
|
|
4496
|
+
if (err instanceof RateLimitError) return "rate_limit";
|
|
4497
|
+
const status = e.status ?? e.statusCode;
|
|
4498
|
+
if (typeof status === "number") {
|
|
4499
|
+
if (status === 429) return "rate_limit";
|
|
4500
|
+
if (status === 401 || status === 403) return "auth";
|
|
4501
|
+
if (status === 400 || status === 422) return "bad_request";
|
|
4502
|
+
if (status >= 500 && status < 600) return "transient";
|
|
4503
|
+
}
|
|
4504
|
+
if (e.code && TRANSIENT_CODES.has(e.code)) return "transient";
|
|
4505
|
+
cur = e.cause;
|
|
4506
|
+
}
|
|
4507
|
+
return "unknown";
|
|
4508
|
+
}
|
|
4509
|
+
function planAttempts(initialProvider, initialModel, registry, opts) {
|
|
4510
|
+
const out = [];
|
|
4511
|
+
for (let i = 0; i <= opts.retries; i++) {
|
|
4512
|
+
out.push({ providerId: initialProvider, model: initialModel, retryNumber: i });
|
|
4513
|
+
}
|
|
4514
|
+
for (const entry of opts.chain) {
|
|
4515
|
+
if (entry.provider === initialProvider) continue;
|
|
4516
|
+
if (!registry.has(entry.provider)) continue;
|
|
4517
|
+
const p = registry.get(entry.provider);
|
|
4518
|
+
const model = entry.model ?? p.info.defaultModel;
|
|
4519
|
+
out.push({ providerId: entry.provider, model, retryNumber: 0 });
|
|
4520
|
+
}
|
|
4521
|
+
return out;
|
|
4522
|
+
}
|
|
4523
|
+
function backoffDelay(retryNumber, opts, klass) {
|
|
4524
|
+
const base = klass === "rate_limit" ? Math.max(opts.initialBackoffMs, 2e3) : opts.initialBackoffMs;
|
|
4525
|
+
const expo = base * Math.pow(2, retryNumber);
|
|
4526
|
+
const jitter = Math.random() * (base / 2);
|
|
4527
|
+
return Math.min(opts.maxBackoffMs, expo + jitter);
|
|
4528
|
+
}
|
|
4529
|
+
function sleep(ms) {
|
|
4530
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
4531
|
+
}
|
|
4532
|
+
async function withFallback(initialProvider, initialModel, registry, opts, call) {
|
|
4533
|
+
if (!opts.enabled) {
|
|
4534
|
+
return call(registry.get(initialProvider), initialModel);
|
|
4535
|
+
}
|
|
4536
|
+
const attempts = planAttempts(initialProvider, initialModel, registry, opts);
|
|
4537
|
+
let lastErr;
|
|
4538
|
+
for (let i = 0; i < attempts.length; i++) {
|
|
4539
|
+
const a = attempts[i];
|
|
4540
|
+
const prev = i > 0 ? attempts[i - 1] : void 0;
|
|
4541
|
+
if (prev && prev.providerId !== a.providerId) {
|
|
4542
|
+
opts.onFallback?.(prev.providerId, a.providerId, a.model, lastErr);
|
|
4543
|
+
} else if (a.retryNumber > 0) {
|
|
4544
|
+
opts.onRetry?.(a.retryNumber, opts.retries, a.providerId, lastErr);
|
|
4545
|
+
await sleep(backoffDelay(a.retryNumber - 1, opts, classifyError(lastErr)));
|
|
4546
|
+
}
|
|
4547
|
+
try {
|
|
4548
|
+
return await call(registry.get(a.providerId), a.model);
|
|
4549
|
+
} catch (err) {
|
|
4550
|
+
lastErr = err;
|
|
4551
|
+
const klass = classifyError(err);
|
|
4552
|
+
if (klass === "aborted") throw err;
|
|
4553
|
+
if (klass === "auth" || klass === "bad_request") {
|
|
4554
|
+
let j = i + 1;
|
|
4555
|
+
while (j < attempts.length && attempts[j].providerId === a.providerId) j++;
|
|
4556
|
+
if (j >= attempts.length) throw err;
|
|
4557
|
+
i = j - 1;
|
|
4558
|
+
continue;
|
|
4559
|
+
}
|
|
4560
|
+
if (i === attempts.length - 1) throw err;
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
throw lastErr;
|
|
4564
|
+
}
|
|
4565
|
+
async function* withFallbackStream(initialProvider, initialModel, registry, opts, createStream) {
|
|
4566
|
+
if (!opts.enabled) {
|
|
4567
|
+
yield* createStream(registry.get(initialProvider), initialModel);
|
|
4568
|
+
return;
|
|
4569
|
+
}
|
|
4570
|
+
const attempts = planAttempts(initialProvider, initialModel, registry, opts);
|
|
4571
|
+
let lastErr;
|
|
4572
|
+
for (let i = 0; i < attempts.length; i++) {
|
|
4573
|
+
const a = attempts[i];
|
|
4574
|
+
const prev = i > 0 ? attempts[i - 1] : void 0;
|
|
4575
|
+
if (prev && prev.providerId !== a.providerId) {
|
|
4576
|
+
opts.onFallback?.(prev.providerId, a.providerId, a.model, lastErr);
|
|
4577
|
+
} else if (a.retryNumber > 0) {
|
|
4578
|
+
opts.onRetry?.(a.retryNumber, opts.retries, a.providerId, lastErr);
|
|
4579
|
+
await sleep(backoffDelay(a.retryNumber - 1, opts, classifyError(lastErr)));
|
|
4580
|
+
}
|
|
4581
|
+
let yielded = false;
|
|
4582
|
+
try {
|
|
4583
|
+
const gen = createStream(registry.get(a.providerId), a.model);
|
|
4584
|
+
for await (const chunk of gen) {
|
|
4585
|
+
yielded = true;
|
|
4586
|
+
yield chunk;
|
|
4587
|
+
}
|
|
4588
|
+
return;
|
|
4589
|
+
} catch (err) {
|
|
4590
|
+
lastErr = err;
|
|
4591
|
+
if (yielded) throw err;
|
|
4592
|
+
const klass = classifyError(err);
|
|
4593
|
+
if (klass === "aborted") throw err;
|
|
4594
|
+
if (klass === "auth" || klass === "bad_request") {
|
|
4595
|
+
let j = i + 1;
|
|
4596
|
+
while (j < attempts.length && attempts[j].providerId === a.providerId) j++;
|
|
4597
|
+
if (j >= attempts.length) throw err;
|
|
4598
|
+
i = j - 1;
|
|
4599
|
+
continue;
|
|
4600
|
+
}
|
|
4601
|
+
if (i === attempts.length - 1) throw err;
|
|
4602
|
+
}
|
|
4603
|
+
}
|
|
4604
|
+
throw lastErr;
|
|
4605
|
+
}
|
|
4606
|
+
function shortErrorTag(err) {
|
|
4607
|
+
if (err == null) return "unknown";
|
|
4608
|
+
const e = err;
|
|
4609
|
+
if (e.code) return e.code;
|
|
4610
|
+
const status = e.status ?? e.statusCode;
|
|
4611
|
+
if (typeof status === "number") return `HTTP ${status}`;
|
|
4612
|
+
if (e instanceof ProviderError && e.message) {
|
|
4613
|
+
const m = e.message.match(/\[[^\]]+\]\s*(.{0,60})/);
|
|
4614
|
+
if (m) return m[1].trim();
|
|
4615
|
+
}
|
|
4616
|
+
if (e instanceof Error && e.message) return e.message.slice(0, 60);
|
|
4617
|
+
return "error";
|
|
4618
|
+
}
|
|
4619
|
+
|
|
4465
4620
|
// src/repl/notify.ts
|
|
4466
4621
|
import { spawn } from "child_process";
|
|
4467
4622
|
import { platform as platform2 } from "os";
|
|
@@ -5434,8 +5589,8 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5434
5589
|
}
|
|
5435
5590
|
void (async () => {
|
|
5436
5591
|
try {
|
|
5437
|
-
const { indexProject } = await import("./indexer-
|
|
5438
|
-
const { loadIndex } = await import("./store-
|
|
5592
|
+
const { indexProject } = await import("./indexer-S6UMGQKA.js");
|
|
5593
|
+
const { loadIndex } = await import("./store-VMK543OQ.js");
|
|
5439
5594
|
const root = process.cwd();
|
|
5440
5595
|
const existed = loadIndex(root);
|
|
5441
5596
|
const { stats } = await indexProject(root);
|
|
@@ -5818,6 +5973,35 @@ Session '${this.resumeSessionId}' not found.
|
|
|
5818
5973
|
thinkingBudget: params.thinkingBudget
|
|
5819
5974
|
};
|
|
5820
5975
|
}
|
|
5976
|
+
/**
|
|
5977
|
+
* Build FallbackOptions from config + wire one-line notice callbacks to stderr.
|
|
5978
|
+
* v0.4.144+: when config.fallback.enabled is true, network/5xx/429 failures retry
|
|
5979
|
+
* on the same provider with exponential backoff; persistent failures walk the
|
|
5980
|
+
* config.fallback.chain. Returns disabled-opts if user hasn't opted in.
|
|
5981
|
+
*/
|
|
5982
|
+
getFallbackOptions(spinner) {
|
|
5983
|
+
const cfg = this.config.get("fallback");
|
|
5984
|
+
const enabled = !!cfg?.enabled;
|
|
5985
|
+
return {
|
|
5986
|
+
enabled,
|
|
5987
|
+
retries: cfg?.retries ?? 2,
|
|
5988
|
+
initialBackoffMs: cfg?.initialBackoffMs ?? 500,
|
|
5989
|
+
maxBackoffMs: cfg?.maxBackoffMs ?? 8e3,
|
|
5990
|
+
chain: cfg?.chain ?? [],
|
|
5991
|
+
onRetry: (attempt, total, providerId, err) => {
|
|
5992
|
+
spinner.stop();
|
|
5993
|
+
process.stderr.write(theme.warning(` [${providerId}] retry ${attempt}/${total}: ${shortErrorTag(err)}
|
|
5994
|
+
`));
|
|
5995
|
+
spinner.start("Retrying...");
|
|
5996
|
+
},
|
|
5997
|
+
onFallback: (from, to, toModel, err) => {
|
|
5998
|
+
spinner.stop();
|
|
5999
|
+
process.stderr.write(theme.warning(` [${from} \u2192 ${to}] falling over to ${toModel}: ${shortErrorTag(err)}
|
|
6000
|
+
`));
|
|
6001
|
+
spinner.start("Retrying...");
|
|
6002
|
+
}
|
|
6003
|
+
};
|
|
6004
|
+
}
|
|
5821
6005
|
/**
|
|
5822
6006
|
* Compute smart-routing decision for this user turn.
|
|
5823
6007
|
* Only considers models available for the current provider (rule skipped otherwise).
|
|
@@ -6513,9 +6697,19 @@ ${mcpBudgetNote}` : "");
|
|
|
6513
6697
|
if (supportsStreamingTools) {
|
|
6514
6698
|
const streamAc = this.setupStreamInterrupt();
|
|
6515
6699
|
try {
|
|
6516
|
-
const
|
|
6517
|
-
|
|
6518
|
-
|
|
6700
|
+
const fallbackOpts = this.getFallbackOptions(spinner);
|
|
6701
|
+
const streamGen = withFallbackStream(
|
|
6702
|
+
this.currentProvider,
|
|
6703
|
+
effectiveModel,
|
|
6704
|
+
this.providers,
|
|
6705
|
+
fallbackOpts,
|
|
6706
|
+
(p, m) => {
|
|
6707
|
+
const tc = p;
|
|
6708
|
+
if (typeof tc.chatWithToolsStream !== "function") {
|
|
6709
|
+
throw new Error(`provider ${p.info.id} does not support streaming tool calls`);
|
|
6710
|
+
}
|
|
6711
|
+
return tc.chatWithToolsStream({ ...chatRequest, model: m, signal: streamAc.signal }, toolDefs);
|
|
6712
|
+
}
|
|
6519
6713
|
);
|
|
6520
6714
|
const streamResult = await this.consumeToolStream(streamGen, spinner);
|
|
6521
6715
|
if (streamResult.toolCalls.length > 0) {
|
|
@@ -6544,7 +6738,14 @@ ${mcpBudgetNote}` : "");
|
|
|
6544
6738
|
this.teardownStreamInterrupt();
|
|
6545
6739
|
}
|
|
6546
6740
|
} else {
|
|
6547
|
-
|
|
6741
|
+
const fallbackOpts = this.getFallbackOptions(spinner);
|
|
6742
|
+
result = await withFallback(
|
|
6743
|
+
this.currentProvider,
|
|
6744
|
+
effectiveModel,
|
|
6745
|
+
this.providers,
|
|
6746
|
+
fallbackOpts,
|
|
6747
|
+
(p, m) => p.chatWithTools({ ...chatRequest, model: m }, toolDefs)
|
|
6748
|
+
);
|
|
6548
6749
|
}
|
|
6549
6750
|
if (result.usage) {
|
|
6550
6751
|
roundUsage.inputTokens += result.usage.inputTokens;
|
|
@@ -7379,7 +7580,7 @@ program.command("web").description("Start Web UI server with browser-based chat
|
|
|
7379
7580
|
console.error("Error: Invalid port number. Must be between 1 and 65535.");
|
|
7380
7581
|
process.exit(1);
|
|
7381
7582
|
}
|
|
7382
|
-
const { startWebServer } = await import("./server-
|
|
7583
|
+
const { startWebServer } = await import("./server-X24SIKZE.js");
|
|
7383
7584
|
await startWebServer({ port, host: options.host });
|
|
7384
7585
|
});
|
|
7385
7586
|
program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | logout-all <name> | migrate <name>)").action(async (action, username) => {
|
|
@@ -7546,12 +7747,12 @@ program.command("sessions").description("List recent conversation sessions").opt
|
|
|
7546
7747
|
console.log(footer + "\n");
|
|
7547
7748
|
});
|
|
7548
7749
|
program.command("doctor").description("Health check: API keys, config, MCP, recent crashes, tool usage, disk usage").option("--json", "Output as JSON (for scripting)").option("--reset-stats", "Reset accumulated tool usage statistics").action(async (options) => {
|
|
7549
|
-
const { runDoctorCli } = await import("./doctor-cli-
|
|
7750
|
+
const { runDoctorCli } = await import("./doctor-cli-RHGMQVCU.js");
|
|
7550
7751
|
await runDoctorCli({ json: !!options.json, resetStats: !!options.resetStats });
|
|
7551
7752
|
});
|
|
7552
7753
|
program.command("batch <action> [arg] [arg2]").description("Anthropic Message Batches: submit | list | status <id> | results <id> [out] | cancel <id>").option("--dry-run", "Parse and validate input without submitting (submit only)").action(async (action, arg, arg2, options) => {
|
|
7553
7754
|
try {
|
|
7554
|
-
const batch = await import("./batch-
|
|
7755
|
+
const batch = await import("./batch-64YESATH.js");
|
|
7555
7756
|
switch (action) {
|
|
7556
7757
|
case "submit":
|
|
7557
7758
|
if (!arg) {
|
|
@@ -7594,7 +7795,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
|
|
|
7594
7795
|
}
|
|
7595
7796
|
});
|
|
7596
7797
|
program.command("mcp-serve").description("Start an MCP server over STDIO, exposing aicli's built-in tools to Claude Desktop / Cursor / other MCP clients").option("--allow-destructive", "Allow bash / run_interactive / task_create (always destructive in MCP mode)").option("--allow-outside-cwd", "Allow tool path arguments to escape the sandbox root \u2014 disabled by default").option("--tools <list>", "Comma-separated whitelist of tools to expose (default: all eligible tools)").option("--cwd <path>", "Working directory AND sandbox root (default: current directory)").action(async (options) => {
|
|
7597
|
-
const { startMcpServer } = await import("./server-
|
|
7798
|
+
const { startMcpServer } = await import("./server-MGKTVVAR.js");
|
|
7598
7799
|
await startMcpServer({
|
|
7599
7800
|
allowDestructive: !!options.allowDestructive,
|
|
7600
7801
|
allowOutsideCwd: !!options.allowOutsideCwd,
|
|
@@ -7721,7 +7922,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
|
|
|
7721
7922
|
}),
|
|
7722
7923
|
config.get("customProviders")
|
|
7723
7924
|
);
|
|
7724
|
-
const { startHub } = await import("./hub-
|
|
7925
|
+
const { startHub } = await import("./hub-SXNKYCN7.js");
|
|
7725
7926
|
await startHub(
|
|
7726
7927
|
{
|
|
7727
7928
|
topic: topic ?? "",
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
pathTokens,
|
|
5
5
|
rebuildSemanticIndex,
|
|
6
6
|
semanticSearch
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-NKR53CPL.js";
|
|
8
|
+
import "./chunk-DQ2OHJNF.js";
|
|
9
9
|
import "./chunk-PASCDYMH.js";
|
|
10
10
|
import "./chunk-JV5N65KN.js";
|
|
11
11
|
import "./chunk-3RG5ZIWI.js";
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
pathTokens,
|
|
6
6
|
rebuildSemanticIndex,
|
|
7
7
|
semanticSearch
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-UQQJWHRV.js";
|
|
9
9
|
import "./chunk-2DXY7UGF.js";
|
|
10
10
|
import "./chunk-KHYD3WXE.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-OVWE4E46.js";
|
|
12
12
|
import "./chunk-PDX44BCA.js";
|
|
13
13
|
export {
|
|
14
14
|
buildEmbeddingText,
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ToolRegistry
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-PWCPOHZ4.js";
|
|
5
|
+
import "./chunk-UQQJWHRV.js";
|
|
6
6
|
import "./chunk-2DXY7UGF.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-2JPLV25X.js";
|
|
8
8
|
import {
|
|
9
9
|
getDangerLevel,
|
|
10
10
|
runTool,
|
|
11
11
|
schemaToJsonSchema
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-QSGDXXE6.js";
|
|
13
13
|
import "./chunk-2ZD3YTVM.js";
|
|
14
14
|
import {
|
|
15
15
|
VERSION
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-XW4EP5IE.js";
|
|
17
17
|
import "./chunk-4BKXL7SM.js";
|
|
18
18
|
import "./chunk-7ZJN4KLV.js";
|
|
19
19
|
import "./chunk-KHYD3WXE.js";
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-VNNYHW6N.js";
|
|
21
|
+
import "./chunk-OVWE4E46.js";
|
|
22
22
|
import "./chunk-PDX44BCA.js";
|
|
23
23
|
|
|
24
24
|
// src/mcp/server.ts
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
loadDevState,
|
|
15
15
|
persistToolRound,
|
|
16
16
|
setupProxy
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-IGZVCNGE.js";
|
|
18
18
|
import {
|
|
19
19
|
CONTENT_ONLY_STREAM_REMINDER,
|
|
20
20
|
HALLUCINATION_CORRECTION_MESSAGE,
|
|
@@ -28,10 +28,10 @@ import {
|
|
|
28
28
|
looksLikeDocumentBody,
|
|
29
29
|
stripPseudoToolCalls,
|
|
30
30
|
stripToolCallReminder
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-EHLHWFZP.js";
|
|
32
32
|
import {
|
|
33
33
|
ConfigManager
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-WPYKTLP2.js";
|
|
35
35
|
import {
|
|
36
36
|
ToolExecutor,
|
|
37
37
|
ToolRegistry,
|
|
@@ -49,14 +49,14 @@ import {
|
|
|
49
49
|
spawnAgentContext,
|
|
50
50
|
truncateOutput,
|
|
51
51
|
undoStack
|
|
52
|
-
} from "./chunk-
|
|
53
|
-
import "./chunk-
|
|
52
|
+
} from "./chunk-PWCPOHZ4.js";
|
|
53
|
+
import "./chunk-UQQJWHRV.js";
|
|
54
54
|
import "./chunk-2DXY7UGF.js";
|
|
55
|
-
import "./chunk-
|
|
55
|
+
import "./chunk-2JPLV25X.js";
|
|
56
56
|
import {
|
|
57
57
|
getDangerLevel,
|
|
58
58
|
runTool
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-QSGDXXE6.js";
|
|
60
60
|
import "./chunk-2ZD3YTVM.js";
|
|
61
61
|
import {
|
|
62
62
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
SKILLS_DIR_NAME,
|
|
77
77
|
VERSION,
|
|
78
78
|
buildUserIdentityPrompt
|
|
79
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-XW4EP5IE.js";
|
|
80
80
|
import {
|
|
81
81
|
formatGitContextForPrompt,
|
|
82
82
|
getGitContext,
|
|
@@ -85,8 +85,8 @@ import {
|
|
|
85
85
|
import "./chunk-4BKXL7SM.js";
|
|
86
86
|
import "./chunk-7ZJN4KLV.js";
|
|
87
87
|
import "./chunk-KHYD3WXE.js";
|
|
88
|
-
import "./chunk-
|
|
89
|
-
import "./chunk-
|
|
88
|
+
import "./chunk-VNNYHW6N.js";
|
|
89
|
+
import "./chunk-OVWE4E46.js";
|
|
90
90
|
import "./chunk-PDX44BCA.js";
|
|
91
91
|
|
|
92
92
|
// src/web/server.ts
|
|
@@ -2222,8 +2222,8 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2222
2222
|
case "index": {
|
|
2223
2223
|
const sub = (args[0] ?? "status").toLowerCase();
|
|
2224
2224
|
const root = process.cwd();
|
|
2225
|
-
const { loadIndex, clearIndex } = await import("./store-
|
|
2226
|
-
const { indexProject } = await import("./indexer-
|
|
2225
|
+
const { loadIndex, clearIndex } = await import("./store-VMK543OQ.js");
|
|
2226
|
+
const { indexProject } = await import("./indexer-S6UMGQKA.js");
|
|
2227
2227
|
const { loadVectorStore, clearVectorStore } = await import("./vector-store-MCQ77OOJ.js");
|
|
2228
2228
|
if (sub === "status") {
|
|
2229
2229
|
const idx = loadIndex(root);
|
|
@@ -2273,7 +2273,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2273
2273
|
message: `Building semantic index for ${idx.symbolCount} symbols\u2026 (first run downloads ~117 MB model)`
|
|
2274
2274
|
});
|
|
2275
2275
|
try {
|
|
2276
|
-
const { rebuildSemanticIndex } = await import("./semantic-
|
|
2276
|
+
const { rebuildSemanticIndex } = await import("./semantic-V37U4MCW.js");
|
|
2277
2277
|
const stats = await rebuildSemanticIndex(root);
|
|
2278
2278
|
const first = stats.modelFirstLoadMs ? ` (model load+first batch ${stats.modelFirstLoadMs}ms)` : "";
|
|
2279
2279
|
this.send({
|
|
@@ -2460,7 +2460,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
|
|
|
2460
2460
|
case "test": {
|
|
2461
2461
|
this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
|
|
2462
2462
|
try {
|
|
2463
|
-
const { executeTests } = await import("./run-tests-
|
|
2463
|
+
const { executeTests } = await import("./run-tests-X4YQXIGP.js");
|
|
2464
2464
|
const argStr = args.join(" ").trim();
|
|
2465
2465
|
let testArgs = {};
|
|
2466
2466
|
if (argStr) {
|