jinzd-ai-cli 0.4.286 → 0.4.288
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/dist/{batch-GY3I53DE.js → batch-YAEXKK2C.js} +2 -2
- package/dist/{chunk-BRLLV3FX.js → chunk-37WBQV3E.js} +90 -127
- package/dist/{chunk-EYUCJBGS.js → chunk-5G6HX57U.js} +1 -1
- package/dist/{chunk-S7ABWTDV.js → chunk-6NEEFOVF.js} +1 -1
- package/dist/{chunk-7G7RZHJI.js → chunk-7RC7AN6V.js} +1 -1
- package/dist/{chunk-UGY5SVNX.js → chunk-ALSSNFNK.js} +94 -4
- package/dist/{chunk-6SCELZG6.js → chunk-C5UAM4X7.js} +4 -4
- package/dist/{chunk-L4FDTQ42.js → chunk-E66SCDTD.js} +1 -1
- package/dist/{chunk-D7HYLMCC.js → chunk-EYA4IXQJ.js} +1 -1
- package/dist/{chunk-2YDLBM3Z.js → chunk-G5QZS5TN.js} +1 -1
- package/dist/{chunk-UKITSNSH.js → chunk-JBNNJ32H.js} +1 -1
- package/dist/{chunk-53V3RQY5.js → chunk-NJDQCQ7P.js} +7 -7
- package/dist/{chunk-THUXZNJL.js → chunk-O4CZPTPU.js} +1 -1
- package/dist/{chunk-GIJL4EFA.js → chunk-U4NQ2IRE.js} +1 -1
- package/dist/{chunk-3ZQZO5F7.js → chunk-WQ2YQ5YC.js} +4 -4
- package/dist/{ci-JBUIVM7P.js → ci-RO2NLIRH.js} +5 -5
- package/dist/{ci-format-B4AHV5SI.js → ci-format-GBSRK2J4.js} +2 -2
- package/dist/{constants-P75MLFV7.js → constants-JQP6BENR.js} +1 -1
- package/dist/{constants-5FYUQLKN.js → constants-T2B3SBMR.js} +1 -1
- package/dist/{doctor-cli-VLFE46PX.js → doctor-cli-CVOE7FAE.js} +5 -5
- package/dist/electron-server.js +211 -239
- package/dist/{hub-CNORVRYW.js → hub-LFWL5PGH.js} +1 -1
- package/dist/index.js +18 -18
- package/dist/{persistent-memory-LVX2OT4L.js → persistent-memory-4UR27ACM.js} +2 -2
- package/dist/{persistent-memory-3KL4N27E.js → persistent-memory-LFE3YHZO.js} +2 -2
- package/dist/{pr-2YUV4KII.js → pr-3QAG7XO7.js} +5 -5
- package/dist/{run-tests-KZ2IUZHK.js → run-tests-GGNFI7CL.js} +2 -2
- package/dist/{run-tests-ERD6X534.js → run-tests-R3JB4UEI.js} +2 -2
- package/dist/{server-A3OX52UC.js → server-I6DXVJRO.js} +40 -115
- package/dist/{server-7VSLW446.js → server-THHSJRNI.js} +5 -5
- package/dist/{task-orchestrator-XAMKOFUE.js → task-orchestrator-6HH3KQUQ.js} +5 -5
- package/dist/{usage-ZXNYCAZB.js → usage-UB4ZT5PE.js} +2 -2
- package/package.json +1 -1
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
} from "./chunk-RS7SKYTS.js";
|
|
5
5
|
import {
|
|
6
6
|
ConfigManager
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-7RC7AN6V.js";
|
|
8
8
|
import "./chunk-TU3L3PW7.js";
|
|
9
9
|
import {
|
|
10
10
|
atomicWriteFileSync
|
|
11
11
|
} from "./chunk-IW3Q7AE5.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-O4CZPTPU.js";
|
|
13
13
|
|
|
14
14
|
// src/cli/batch.ts
|
|
15
15
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
searchPersistentMemories,
|
|
12
12
|
touchMemoryReferences,
|
|
13
13
|
updateMemoryEntry
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-JBNNJ32H.js";
|
|
15
15
|
import {
|
|
16
16
|
indexProject
|
|
17
17
|
} from "./chunk-4DEMGCK4.js";
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
runHook,
|
|
31
31
|
runLifecycleHooks,
|
|
32
32
|
runTool
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-5G6HX57U.js";
|
|
34
34
|
import {
|
|
35
35
|
buildTruncatedArgumentsError,
|
|
36
36
|
getDangerLevel,
|
|
@@ -50,14 +50,14 @@ import {
|
|
|
50
50
|
} from "./chunk-4BKXL7SM.js";
|
|
51
51
|
import {
|
|
52
52
|
runTestsTool
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-6NEEFOVF.js";
|
|
54
54
|
import {
|
|
55
55
|
CONFIG_DIR_NAME,
|
|
56
56
|
DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
|
|
57
57
|
SUBAGENT_ALLOWED_TOOLS,
|
|
58
58
|
SUBAGENT_DEFAULT_MAX_ROUNDS,
|
|
59
59
|
SUBAGENT_MAX_ROUNDS_LIMIT
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-O4CZPTPU.js";
|
|
61
61
|
|
|
62
62
|
// src/tools/shell-pool.ts
|
|
63
63
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -1628,6 +1628,63 @@ function simpleDiff(oldLines, newLines) {
|
|
|
1628
1628
|
return result;
|
|
1629
1629
|
}
|
|
1630
1630
|
|
|
1631
|
+
// src/core/tool-gate.ts
|
|
1632
|
+
var gateMessages = {
|
|
1633
|
+
hookDenied: (toolName, reason) => `[Hook denied] ${reason ?? `PreToolUse blocked ${toolName}`}. Do not retry without asking.`,
|
|
1634
|
+
networkDenied: (toolName, reason) => `[Permission denied] Tool ${toolName} is blocked by networkPolicy${reason ? ` (${reason})` : ""}. Do not retry.`,
|
|
1635
|
+
profileDenied: (toolName, profileName, reason) => `[Permission denied] Tool ${toolName} is blocked by permission profile "${profileName}"${reason ? ` (${reason})` : ""}. Do not retry.`,
|
|
1636
|
+
autoDenied: (reason) => `[Auto denied] ${reason}. Do not retry without asking.`,
|
|
1637
|
+
permissionCancelled: (toolName) => `[User cancelled] The user declined permission for ${toolName}. Do not retry without asking.`,
|
|
1638
|
+
operationCancelled: (toolName, level) => `[User cancelled] The user declined the ${level === "destructive" ? "destructive " : ""}${toolName} operation. Do not retry without asking.`
|
|
1639
|
+
};
|
|
1640
|
+
function needsPermissionRequestHook(input) {
|
|
1641
|
+
return input.networkPermission?.action === "confirm" || input.permission.action === "confirm";
|
|
1642
|
+
}
|
|
1643
|
+
function decideToolGate(call, input) {
|
|
1644
|
+
const { dangerLevel, permission, networkPermission } = input;
|
|
1645
|
+
if (input.hookDeny) {
|
|
1646
|
+
return { kind: "denied", source: "hook", message: gateMessages.hookDenied(call.name, input.hookDeny.reason) };
|
|
1647
|
+
}
|
|
1648
|
+
if (networkPermission?.action === "deny") {
|
|
1649
|
+
return { kind: "denied", source: "network", message: gateMessages.networkDenied(call.name, networkPermission.reason) };
|
|
1650
|
+
}
|
|
1651
|
+
if (permission.action === "deny") {
|
|
1652
|
+
return {
|
|
1653
|
+
kind: "denied",
|
|
1654
|
+
source: "profile",
|
|
1655
|
+
message: gateMessages.profileDenied(call.name, permission.profileName ?? "default", permission.reason)
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1658
|
+
if (permission.action === "auto-approve" && networkPermission?.action !== "confirm") {
|
|
1659
|
+
return { kind: "allow", source: "profile" };
|
|
1660
|
+
}
|
|
1661
|
+
const requiresHardConfirmation = permission.action === "confirm" && permission.hardBoundary === true;
|
|
1662
|
+
if ((networkPermission?.action === "confirm" || requiresHardConfirmation) && dangerLevel === "safe") {
|
|
1663
|
+
return { kind: "confirm", level: "write", source: "permission" };
|
|
1664
|
+
}
|
|
1665
|
+
if (input.sessionAutoMode && networkPermission?.action !== "confirm") {
|
|
1666
|
+
const classification = input.classify();
|
|
1667
|
+
if (classification.decision === "deny") {
|
|
1668
|
+
return {
|
|
1669
|
+
kind: "denied",
|
|
1670
|
+
source: "auto-mode",
|
|
1671
|
+
message: gateMessages.autoDenied(classification.reason),
|
|
1672
|
+
classification
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
if (classification.decision === "auto-approve" && !requiresHardConfirmation) {
|
|
1676
|
+
return { kind: "allow", source: "auto-mode" };
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
if (input.sessionAutoApprove && dangerLevel === "write" && !requiresHardConfirmation) {
|
|
1680
|
+
return { kind: "allow", source: "yolo" };
|
|
1681
|
+
}
|
|
1682
|
+
if (dangerLevel === "write" || dangerLevel === "destructive") {
|
|
1683
|
+
return { kind: "confirm", level: dangerLevel, source: "danger" };
|
|
1684
|
+
}
|
|
1685
|
+
return { kind: "allow", source: "safe" };
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1631
1688
|
// src/tools/permissions.ts
|
|
1632
1689
|
import { existsSync as existsSync4, realpathSync } from "fs";
|
|
1633
1690
|
import { basename as basename2, dirname as dirname2, isAbsolute, resolve as resolve3 } from "path";
|
|
@@ -2290,13 +2347,6 @@ var ToolExecutor = class {
|
|
|
2290
2347
|
{ configDir: this.hookConfigDir, onSummary: (msg) => console.log(theme.dim(` [hook] ${msg}`)) }
|
|
2291
2348
|
);
|
|
2292
2349
|
const preDeny = preToolDecisions.find((d) => d.action === "deny");
|
|
2293
|
-
if (preDeny) {
|
|
2294
|
-
return {
|
|
2295
|
-
callId: call.id,
|
|
2296
|
-
content: `[Hook denied] ${preDeny.reason ?? `PreToolUse blocked ${call.name}`}. Do not retry without asking.`,
|
|
2297
|
-
isError: true
|
|
2298
|
-
};
|
|
2299
|
-
}
|
|
2300
2350
|
for (const d of preToolDecisions) {
|
|
2301
2351
|
const warnings = [d.warning, ...d.warnings ?? []].filter(Boolean);
|
|
2302
2352
|
for (const w of warnings) console.log(theme.warning(` \u26A0 Hook warning: ${w}`));
|
|
@@ -2316,7 +2366,19 @@ var ToolExecutor = class {
|
|
|
2316
2366
|
}
|
|
2317
2367
|
);
|
|
2318
2368
|
const networkPermission = checkNetworkPolicy(call.name, call.arguments, this.networkPolicy);
|
|
2319
|
-
|
|
2369
|
+
const gate = decideToolGate(call, {
|
|
2370
|
+
dangerLevel,
|
|
2371
|
+
permission,
|
|
2372
|
+
networkPermission,
|
|
2373
|
+
hookDeny: preDeny ? { reason: preDeny.reason } : void 0,
|
|
2374
|
+
sessionAutoMode: this.sessionAutoMode,
|
|
2375
|
+
sessionAutoApprove: this.sessionAutoApprove,
|
|
2376
|
+
classify: () => defaultActionClassifier.classify(call, dangerLevel, {
|
|
2377
|
+
workspaceRoot: this.workspaceRoot,
|
|
2378
|
+
tempDirs: [tmpdir()]
|
|
2379
|
+
})
|
|
2380
|
+
});
|
|
2381
|
+
if (needsPermissionRequestHook({ permission, networkPermission })) {
|
|
2320
2382
|
runLifecycleHooks(
|
|
2321
2383
|
this.hookConfig,
|
|
2322
2384
|
"PermissionRequest",
|
|
@@ -2324,131 +2386,29 @@ var ToolExecutor = class {
|
|
|
2324
2386
|
{ configDir: this.hookConfigDir, onSummary: (msg) => console.log(theme.dim(" [hook] " + msg)) }
|
|
2325
2387
|
);
|
|
2326
2388
|
}
|
|
2327
|
-
if (
|
|
2328
|
-
|
|
2329
|
-
return {
|
|
2330
|
-
callId: call.id,
|
|
2331
|
-
content: `[Permission denied] Tool ${call.name} is blocked by networkPolicy${reason}. Do not retry.`,
|
|
2332
|
-
isError: true
|
|
2333
|
-
};
|
|
2334
|
-
}
|
|
2335
|
-
if (permission.action === "deny") {
|
|
2336
|
-
const reason = permission.reason ? ` (${permission.reason})` : "";
|
|
2337
|
-
return {
|
|
2338
|
-
callId: call.id,
|
|
2339
|
-
content: `[Permission denied] Tool ${call.name} is blocked by permission profile "${permission.profileName}"${reason}. Do not retry.`,
|
|
2340
|
-
isError: true
|
|
2341
|
-
};
|
|
2342
|
-
}
|
|
2343
|
-
if (permission.action === "auto-approve" && networkPermission?.action !== "confirm") {
|
|
2344
|
-
if (!toolCallAlreadyPrinted) this.printToolCall(call);
|
|
2345
|
-
try {
|
|
2346
|
-
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
2347
|
-
const content = truncateOutput(rawContent, call.name);
|
|
2348
|
-
const wasTruncated = content !== rawContent;
|
|
2349
|
-
this.printToolResult(call.name, rawContent, false, wasTruncated);
|
|
2350
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
|
|
2351
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
|
|
2352
|
-
return { callId: call.id, content, isError: false };
|
|
2353
|
-
} catch (err) {
|
|
2354
|
-
const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
|
|
2355
|
-
this.printToolResult(call.name, message, true, false);
|
|
2356
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
|
|
2357
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
|
|
2358
|
-
return { callId: call.id, content: message, isError: true };
|
|
2359
|
-
}
|
|
2360
|
-
}
|
|
2361
|
-
const requiresHardConfirmation = permission.action === "confirm" && permission.hardBoundary === true;
|
|
2362
|
-
if ((networkPermission?.action === "confirm" || requiresHardConfirmation) && dangerLevel === "safe") {
|
|
2363
|
-
this.printToolCall(call);
|
|
2364
|
-
toolCallAlreadyPrinted = true;
|
|
2365
|
-
const confirmed = await this.confirm(call, "write");
|
|
2366
|
-
if (!confirmed) {
|
|
2367
|
-
return {
|
|
2368
|
-
callId: call.id,
|
|
2369
|
-
content: `[User cancelled] The user declined permission for ${call.name}. Do not retry without asking.`,
|
|
2370
|
-
isError: true
|
|
2371
|
-
};
|
|
2372
|
-
}
|
|
2389
|
+
if (gate.kind === "denied") {
|
|
2390
|
+
if (gate.source === "auto-mode") recordRecentlyDeniedAutoAction(call, gate.classification);
|
|
2391
|
+
return { callId: call.id, content: gate.message, isError: true };
|
|
2373
2392
|
}
|
|
2374
|
-
if (
|
|
2375
|
-
|
|
2376
|
-
workspaceRoot: this.workspaceRoot,
|
|
2377
|
-
tempDirs: [tmpdir()]
|
|
2378
|
-
});
|
|
2379
|
-
if (classification.decision === "deny") {
|
|
2380
|
-
recordRecentlyDeniedAutoAction(call, classification);
|
|
2381
|
-
return {
|
|
2382
|
-
callId: call.id,
|
|
2383
|
-
content: `[Auto denied] ${classification.reason}. Do not retry without asking.`,
|
|
2384
|
-
isError: true
|
|
2385
|
-
};
|
|
2386
|
-
}
|
|
2387
|
-
if (classification.decision === "auto-approve" && !requiresHardConfirmation) {
|
|
2393
|
+
if (gate.kind === "confirm") {
|
|
2394
|
+
if (gate.source === "danger" && gate.level === "write") {
|
|
2388
2395
|
this.printToolCall(call);
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
const wasTruncated = content !== rawContent;
|
|
2395
|
-
this.printToolResult(call.name, rawContent, false, wasTruncated);
|
|
2396
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
|
|
2397
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
|
|
2398
|
-
return { callId: call.id, content, isError: false };
|
|
2399
|
-
} catch (err) {
|
|
2400
|
-
const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
|
|
2401
|
-
this.printToolResult(call.name, message, true, false);
|
|
2402
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
|
|
2403
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
|
|
2404
|
-
return { callId: call.id, content: message, isError: true };
|
|
2405
|
-
}
|
|
2406
|
-
}
|
|
2407
|
-
}
|
|
2408
|
-
if (this.sessionAutoApprove && dangerLevel === "write" && !requiresHardConfirmation) {
|
|
2409
|
-
this.printToolCall(call);
|
|
2410
|
-
if (dangerLevel === "write") this.printDiffPreview(call);
|
|
2411
|
-
console.log(theme.warning(" \u26A1 Auto-approved (session /yolo mode)"));
|
|
2412
|
-
try {
|
|
2413
|
-
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
2414
|
-
const content = truncateOutput(rawContent, call.name);
|
|
2415
|
-
const wasTruncated = content !== rawContent;
|
|
2416
|
-
this.printToolResult(call.name, rawContent, false, wasTruncated);
|
|
2417
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
|
|
2418
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
|
|
2419
|
-
return { callId: call.id, content, isError: false };
|
|
2420
|
-
} catch (err) {
|
|
2421
|
-
const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
|
|
2422
|
-
this.printToolResult(call.name, message, true, false);
|
|
2423
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
|
|
2424
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
|
|
2425
|
-
return { callId: call.id, content: message, isError: true };
|
|
2426
|
-
}
|
|
2427
|
-
}
|
|
2428
|
-
if (dangerLevel === "write") {
|
|
2429
|
-
this.printToolCall(call);
|
|
2430
|
-
this.printDiffPreview(call);
|
|
2431
|
-
const confirmed = await this.confirm(call, dangerLevel);
|
|
2432
|
-
if (!confirmed) {
|
|
2433
|
-
return {
|
|
2434
|
-
callId: call.id,
|
|
2435
|
-
content: `[User cancelled] The user declined the ${call.name} operation. Do not retry without asking.`,
|
|
2436
|
-
isError: true
|
|
2437
|
-
};
|
|
2396
|
+
this.printDiffPreview(call);
|
|
2397
|
+
toolCallAlreadyPrinted = true;
|
|
2398
|
+
} else if (gate.source === "permission") {
|
|
2399
|
+
this.printToolCall(call);
|
|
2400
|
+
toolCallAlreadyPrinted = true;
|
|
2438
2401
|
}
|
|
2439
|
-
|
|
2440
|
-
const confirmed = await this.confirm(call, dangerLevel);
|
|
2402
|
+
const confirmed = await this.confirm(call, gate.level);
|
|
2441
2403
|
if (!confirmed) {
|
|
2442
2404
|
return {
|
|
2443
2405
|
callId: call.id,
|
|
2444
|
-
content:
|
|
2406
|
+
content: gate.source === "permission" ? gateMessages.permissionCancelled(call.name) : gateMessages.operationCancelled(call.name, gate.level),
|
|
2445
2407
|
isError: true
|
|
2446
2408
|
};
|
|
2447
2409
|
}
|
|
2448
|
-
this.printToolCall(call);
|
|
2449
|
-
} else {
|
|
2450
|
-
this.printToolCall(call);
|
|
2451
2410
|
}
|
|
2411
|
+
if (!toolCallAlreadyPrinted) this.printToolCall(call);
|
|
2452
2412
|
try {
|
|
2453
2413
|
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
2454
2414
|
const content = truncateOutput(rawContent, call.name);
|
|
@@ -6997,6 +6957,9 @@ export {
|
|
|
6997
6957
|
groupCallsByPhase,
|
|
6998
6958
|
runSafePhases,
|
|
6999
6959
|
resolveWriteFileArgs,
|
|
6960
|
+
gateMessages,
|
|
6961
|
+
needsPermissionRequestHook,
|
|
6962
|
+
decideToolGate,
|
|
7000
6963
|
checkPermissionWithProfile,
|
|
7001
6964
|
formatPermissionProfileWarning,
|
|
7002
6965
|
checkNetworkPolicy,
|
|
@@ -53,9 +53,76 @@ var BaseProvider = class {
|
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
+
// src/core/network-error.ts
|
|
57
|
+
var NETWORK_CODES = /* @__PURE__ */ new Set([
|
|
58
|
+
"ECONNREFUSED",
|
|
59
|
+
// 端口没人听(代理没起来最常见)
|
|
60
|
+
"ECONNRESET",
|
|
61
|
+
// 对端断开
|
|
62
|
+
"ENOTFOUND",
|
|
63
|
+
// DNS 查不到
|
|
64
|
+
"EAI_AGAIN",
|
|
65
|
+
// DNS 临时失败
|
|
66
|
+
"ETIMEDOUT",
|
|
67
|
+
// 连接超时
|
|
68
|
+
"EHOSTUNREACH",
|
|
69
|
+
"ENETUNREACH",
|
|
70
|
+
"EPIPE",
|
|
71
|
+
"UND_ERR_SOCKET",
|
|
72
|
+
// undici:socket 意外关闭
|
|
73
|
+
"UND_ERR_CONNECT_TIMEOUT"
|
|
74
|
+
]);
|
|
75
|
+
var TRANSIENT_CODES = /* @__PURE__ */ new Set(["ECONNRESET", "UND_ERR_SOCKET", "EPIPE", "EAI_AGAIN"]);
|
|
76
|
+
function findCause(err, depth = 0) {
|
|
77
|
+
if (!err || depth > 4) return null;
|
|
78
|
+
const e = err;
|
|
79
|
+
if (typeof e.code === "string") {
|
|
80
|
+
return {
|
|
81
|
+
code: e.code,
|
|
82
|
+
address: e.address ? `${e.address}${e.port !== void 0 ? `:${e.port}` : ""}` : void 0,
|
|
83
|
+
message: e.message
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (Array.isArray(e.errors) && e.errors.length > 0) {
|
|
87
|
+
for (const inner of e.errors) {
|
|
88
|
+
const found = findCause(inner, depth + 1);
|
|
89
|
+
if (found) return found;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return findCause(e.cause, depth + 1);
|
|
93
|
+
}
|
|
94
|
+
function describeNetworkFailure(err, ctx = {}) {
|
|
95
|
+
const cause = findCause(err);
|
|
96
|
+
const topMessage = err instanceof Error ? err.message : String(err);
|
|
97
|
+
const looksNetwork = cause?.code && NETWORK_CODES.has(cause.code) || topMessage === "fetch failed" || topMessage.includes("Connection error");
|
|
98
|
+
if (!looksNetwork) return null;
|
|
99
|
+
const code = cause?.code;
|
|
100
|
+
const address = cause?.address;
|
|
101
|
+
const transient = !!code && TRANSIENT_CODES.has(code);
|
|
102
|
+
const what = code ? `${code}${address ? ` ${address}` : ""}` : cause?.message ?? "no further detail from the network layer";
|
|
103
|
+
const where = ctx.target ? ` while connecting to ${ctx.target}` : "";
|
|
104
|
+
const parts = [`Connection failed${where} (${what}).`];
|
|
105
|
+
if (ctx.proxyUrl) {
|
|
106
|
+
parts.push(`The request went through the proxy from config.proxy (${ctx.proxyUrl}).`);
|
|
107
|
+
if (code === "ECONNREFUSED") {
|
|
108
|
+
parts.push(`That address refused the connection \u2014 the proxy is probably not running. Start it, or unset config.proxy to connect directly.`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (transient) {
|
|
112
|
+
parts.push(`This usually means an idle connection was dropped by the other side \u2014 just send the message again.`);
|
|
113
|
+
} else if (code === "ENOTFOUND" || code === "EAI_AGAIN") {
|
|
114
|
+
parts.push(`DNS lookup failed \u2014 check the network connection${ctx.proxyUrl ? " and the proxy" : ""}.`);
|
|
115
|
+
} else if (code === "ETIMEDOUT" || code === "UND_ERR_CONNECT_TIMEOUT") {
|
|
116
|
+
parts.push(`The connection timed out before it was established${ctx.proxyUrl ? " \u2014 check whether the proxy can reach this host" : ""}.`);
|
|
117
|
+
}
|
|
118
|
+
return { code, address, transient, message: parts.join(" ") };
|
|
119
|
+
}
|
|
120
|
+
|
|
56
121
|
// src/providers/claude.ts
|
|
57
122
|
var CACHE_MIN_SYSTEM_CHARS = 2e3;
|
|
58
123
|
var ClaudeProvider = class extends BaseProvider {
|
|
124
|
+
/** 生效的代理(网络失败时点名它,见 core/network-error.ts)。 */
|
|
125
|
+
activeProxyUrl;
|
|
59
126
|
client;
|
|
60
127
|
info = {
|
|
61
128
|
id: "claude",
|
|
@@ -90,6 +157,7 @@ var ClaudeProvider = class extends BaseProvider {
|
|
|
90
157
|
baseURL: options?.baseUrl
|
|
91
158
|
};
|
|
92
159
|
const proxyUrl = options?.proxy;
|
|
160
|
+
this.activeProxyUrl = proxyUrl;
|
|
93
161
|
try {
|
|
94
162
|
const { Agent, ProxyAgent, fetch: undiciFetch } = await import("undici");
|
|
95
163
|
const STREAM_BODY_TIMEOUT = 30 * 60 * 1e3;
|
|
@@ -614,6 +682,8 @@ var ClaudeProvider = class extends BaseProvider {
|
|
|
614
682
|
if (err instanceof Anthropic.RateLimitError) {
|
|
615
683
|
return new RateLimitError("claude");
|
|
616
684
|
}
|
|
685
|
+
const net = describeNetworkFailure(err, { target: "api.anthropic.com", proxyUrl: this.activeProxyUrl });
|
|
686
|
+
if (net) return new ProviderError("claude", net.message, err instanceof Error ? err : void 0);
|
|
617
687
|
if (err instanceof Error) {
|
|
618
688
|
return new ProviderError("claude", err.message, err);
|
|
619
689
|
}
|
|
@@ -930,10 +1000,11 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
930
1000
|
err
|
|
931
1001
|
);
|
|
932
1002
|
}
|
|
933
|
-
|
|
1003
|
+
const net = describeNetworkFailure(err, { target: "generativelanguage.googleapis.com" });
|
|
1004
|
+
if (net || msg.includes("socket hang up")) {
|
|
934
1005
|
return new ProviderError(
|
|
935
1006
|
"gemini",
|
|
936
|
-
`Network connection failed: ${msg}
|
|
1007
|
+
`${net?.message ?? `Network connection failed: ${msg}`}
|
|
937
1008
|
Node.js does not automatically use system proxies. Try one of the following:
|
|
938
1009
|
1. Set environment variable: set HTTPS_PROXY=http://127.0.0.1:<proxy-port>
|
|
939
1010
|
2. Configure an accessible Gemini API mirror URL in config.json under customBaseUrls.gemini`,
|
|
@@ -1002,6 +1073,8 @@ function readRetryCount(headers) {
|
|
|
1002
1073
|
}
|
|
1003
1074
|
var OpenAICompatibleProvider = class extends BaseProvider {
|
|
1004
1075
|
client;
|
|
1076
|
+
/** 生效的代理(wrapError 要在网络失败时点名它);未配代理时为 undefined。 */
|
|
1077
|
+
activeProxyUrl;
|
|
1005
1078
|
defaultTimeout = 6e4;
|
|
1006
1079
|
// ms
|
|
1007
1080
|
/**
|
|
@@ -1031,13 +1104,17 @@ var OpenAICompatibleProvider = class extends BaseProvider {
|
|
|
1031
1104
|
const { Agent, ProxyAgent, fetch: undiciFetch } = await import("undici");
|
|
1032
1105
|
const STREAM_BODY_TIMEOUT = 30 * 60 * 1e3;
|
|
1033
1106
|
const STREAM_HEADERS_TIMEOUT = 5 * 60 * 1e3;
|
|
1107
|
+
const KEEP_ALIVE_TIMEOUT = 2e3;
|
|
1108
|
+
this.activeProxyUrl = proxyUrl;
|
|
1034
1109
|
const dispatcher = proxyUrl ? new ProxyAgent({
|
|
1035
1110
|
uri: proxyUrl,
|
|
1036
1111
|
bodyTimeout: STREAM_BODY_TIMEOUT,
|
|
1037
|
-
headersTimeout: STREAM_HEADERS_TIMEOUT
|
|
1112
|
+
headersTimeout: STREAM_HEADERS_TIMEOUT,
|
|
1113
|
+
keepAliveTimeout: KEEP_ALIVE_TIMEOUT
|
|
1038
1114
|
}) : new Agent({
|
|
1039
1115
|
bodyTimeout: STREAM_BODY_TIMEOUT,
|
|
1040
|
-
headersTimeout: STREAM_HEADERS_TIMEOUT
|
|
1116
|
+
headersTimeout: STREAM_HEADERS_TIMEOUT,
|
|
1117
|
+
keepAliveTimeout: KEEP_ALIVE_TIMEOUT
|
|
1041
1118
|
});
|
|
1042
1119
|
clientOptions.fetch = ((url, init) => {
|
|
1043
1120
|
const retryCount = readRetryCount(init?.headers);
|
|
@@ -1511,11 +1588,24 @@ var OpenAICompatibleProvider = class extends BaseProvider {
|
|
|
1511
1588
|
if (err instanceof OpenAI.RateLimitError) {
|
|
1512
1589
|
return new RateLimitError(this.info.id);
|
|
1513
1590
|
}
|
|
1591
|
+
const net = describeNetworkFailure(err, {
|
|
1592
|
+
target: this.hostLabel(),
|
|
1593
|
+
proxyUrl: this.activeProxyUrl
|
|
1594
|
+
});
|
|
1595
|
+
if (net) return new ProviderError(this.info.id, net.message, err instanceof Error ? err : void 0);
|
|
1514
1596
|
if (err instanceof Error) {
|
|
1515
1597
|
return new ProviderError(this.info.id, err.message, err);
|
|
1516
1598
|
}
|
|
1517
1599
|
return new ProviderError(this.info.id, String(err));
|
|
1518
1600
|
}
|
|
1601
|
+
/** 请求实际打向的主机,用于「连谁失败了」。 */
|
|
1602
|
+
hostLabel() {
|
|
1603
|
+
try {
|
|
1604
|
+
return new URL(this.info.baseUrl ?? this.defaultBaseUrl).host;
|
|
1605
|
+
} catch {
|
|
1606
|
+
return this.info.id;
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1519
1609
|
};
|
|
1520
1610
|
|
|
1521
1611
|
// src/providers/deepseek.ts
|
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
listHooks,
|
|
9
9
|
listInstalledPlugins,
|
|
10
10
|
resetStats
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-5G6HX57U.js";
|
|
12
12
|
import {
|
|
13
13
|
ProviderRegistry
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ALSSNFNK.js";
|
|
15
15
|
import {
|
|
16
16
|
ConfigManager
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-7RC7AN6V.js";
|
|
18
18
|
import {
|
|
19
19
|
getGitRoot
|
|
20
20
|
} from "./chunk-HOSJZMQS.js";
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
MCP_PROJECT_CONFIG_NAME,
|
|
27
27
|
MEMORY_FILE_NAME,
|
|
28
28
|
VERSION
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-O4CZPTPU.js";
|
|
30
30
|
|
|
31
31
|
// src/diagnostics/doctor-report.ts
|
|
32
32
|
import { existsSync as existsSync3, statSync as statSync2 } from "fs";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
MEMORY_FILE_NAME,
|
|
13
13
|
MEMORY_MAX_CHARS,
|
|
14
14
|
MEMORY_STORE_FILE_NAME
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-U4NQ2IRE.js";
|
|
16
16
|
|
|
17
17
|
// src/memory/persistent-memory.ts
|
|
18
18
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
MEMORY_FILE_NAME,
|
|
14
14
|
MEMORY_MAX_CHARS,
|
|
15
15
|
MEMORY_STORE_FILE_NAME
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-O4CZPTPU.js";
|
|
17
17
|
|
|
18
18
|
// src/memory/persistent-memory.ts
|
|
19
19
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
setPreferredAgentName,
|
|
17
17
|
truncateForPersist,
|
|
18
18
|
undoStack
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-37WBQV3E.js";
|
|
20
20
|
import {
|
|
21
21
|
buildReviewPrompt,
|
|
22
22
|
buildSecurityReviewPrompt
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
touchMemoryReferences,
|
|
52
52
|
updateMemoryApproval,
|
|
53
53
|
updateMemoryEntry
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-JBNNJ32H.js";
|
|
55
55
|
import {
|
|
56
56
|
theme
|
|
57
57
|
} from "./chunk-5C76XDDF.js";
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
import {
|
|
66
66
|
buildDoctorReport,
|
|
67
67
|
formatDoctorReport
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-C5UAM4X7.js";
|
|
69
69
|
import {
|
|
70
70
|
describePlugin,
|
|
71
71
|
getActivePluginAssets,
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
trustHook,
|
|
81
81
|
trustPlugin,
|
|
82
82
|
untrustHook
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-5G6HX57U.js";
|
|
84
84
|
import {
|
|
85
85
|
isCleanDocumentBody,
|
|
86
86
|
stripOuterCodeFence
|
|
@@ -109,7 +109,7 @@ import {
|
|
|
109
109
|
MCP_TOOL_PREFIX,
|
|
110
110
|
REPO_URL,
|
|
111
111
|
VERSION
|
|
112
|
-
} from "./chunk-
|
|
112
|
+
} from "./chunk-O4CZPTPU.js";
|
|
113
113
|
|
|
114
114
|
// src/mcp/client.ts
|
|
115
115
|
import { spawn } from "child_process";
|
|
@@ -2393,7 +2393,7 @@ No tools match "${filter}".
|
|
|
2393
2393
|
const { join: join6 } = await import("path");
|
|
2394
2394
|
const { existsSync: existsSync6 } = await import("fs");
|
|
2395
2395
|
const { getGitRoot } = await import("./git-context-EXOEHQSF.js");
|
|
2396
|
-
const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-
|
|
2396
|
+
const { MCP_PROJECT_CONFIG_NAME } = await import("./constants-T2B3SBMR.js");
|
|
2397
2397
|
const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
|
|
2398
2398
|
const cwd = process.cwd();
|
|
2399
2399
|
const projectRoot = getGitRoot(cwd) ?? cwd;
|
|
@@ -3497,7 +3497,7 @@ function createReviewCommands() {
|
|
|
3497
3497
|
usage: "/test [command|filter]",
|
|
3498
3498
|
async execute(args, ctx) {
|
|
3499
3499
|
try {
|
|
3500
|
-
const { executeTests } = await import("./run-tests-
|
|
3500
|
+
const { executeTests } = await import("./run-tests-GGNFI7CL.js");
|
|
3501
3501
|
const argStr = args.join(" ").trim();
|
|
3502
3502
|
let testArgs = {};
|
|
3503
3503
|
if (argStr) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
evaluateCiGate,
|
|
4
4
|
normalizeCiThresholds
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-G5QZS5TN.js";
|
|
6
6
|
import {
|
|
7
7
|
buildReviewPrompt,
|
|
8
8
|
buildSecurityReviewPrompt,
|
|
@@ -13,13 +13,13 @@ import {
|
|
|
13
13
|
} from "./chunk-6YZEZFX5.js";
|
|
14
14
|
import {
|
|
15
15
|
ProviderRegistry
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ALSSNFNK.js";
|
|
17
17
|
import {
|
|
18
18
|
ConfigManager
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-7RC7AN6V.js";
|
|
20
20
|
import {
|
|
21
21
|
VERSION
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-O4CZPTPU.js";
|
|
23
23
|
|
|
24
24
|
// src/cli/ci.ts
|
|
25
25
|
import { execFileSync } from "child_process";
|