jinzd-ai-cli 0.4.287 → 0.4.289
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-6OH7D5YU.js → batch-GVD4CZZQ.js} +2 -2
- package/dist/{chunk-UDFK5Q52.js → chunk-25VQORAZ.js} +1 -1
- package/dist/{chunk-5F7BGV72.js → chunk-2SQCGJ6H.js} +1 -1
- package/dist/{chunk-AXSWLNCU.js → chunk-AA6PZRJO.js} +104 -127
- package/dist/{chunk-L7RAEUUN.js → chunk-BDN6ZCPQ.js} +1 -1
- package/dist/{chunk-HNUT4STJ.js → chunk-BW4H53KI.js} +7 -7
- package/dist/{chunk-L625B2XV.js → chunk-GXB5EOFI.js} +1 -1
- package/dist/{chunk-3BHJKMPQ.js → chunk-I73JWHNT.js} +1 -1
- package/dist/{chunk-RZVGR3KD.js → chunk-NP446QJS.js} +3 -3
- package/dist/{chunk-CYUAHF6X.js → chunk-NWM7CTQQ.js} +1 -1
- package/dist/{chunk-HEUB5PV6.js → chunk-QL2QACHI.js} +1 -1
- package/dist/{chunk-3Y5BCGD2.js → chunk-TKG6BI6G.js} +1 -1
- package/dist/{chunk-ERDFOXYK.js → chunk-TOH67ARY.js} +1 -1
- package/dist/{chunk-EU6NMK7G.js → chunk-VIDUFFHT.js} +3 -3
- package/dist/{ci-WXCMI4ND.js → ci-U7X5OWOA.js} +4 -4
- package/dist/{ci-format-JXD2BQM6.js → ci-format-PDP5K5LR.js} +2 -2
- package/dist/{constants-2B7CN2ER.js → constants-GBIMYBKD.js} +1 -1
- package/dist/{constants-SRRV3K5Y.js → constants-MYTDRODA.js} +1 -1
- package/dist/{doctor-cli-LQYTDJ74.js → doctor-cli-64WRAKH3.js} +4 -4
- package/dist/electron-server.js +143 -238
- package/dist/{hub-Y62P5MIA.js → hub-FSITPTD5.js} +1 -1
- package/dist/index.js +18 -17
- package/dist/{persistent-memory-46JSUEYV.js → persistent-memory-7GPL7NSO.js} +2 -2
- package/dist/{persistent-memory-3N2XQKJK.js → persistent-memory-7PPH6QES.js} +2 -2
- package/dist/{pr-L7Y3XHGL.js → pr-T7VURNFJ.js} +4 -4
- package/dist/{run-tests-WC644BHH.js → run-tests-CSAB2M4A.js} +2 -2
- package/dist/{run-tests-3ZOMRFIX.js → run-tests-PPTDYVS7.js} +2 -2
- package/dist/{server-XWURZCAF.js → server-6B2JFKRN.js} +53 -117
- package/dist/{server-L4QHJT2I.js → server-O54U4OOB.js} +5 -5
- package/dist/{task-orchestrator-6TVKJYKC.js → task-orchestrator-HA4JE4TF.js} +5 -5
- package/dist/{usage-L2PSI2KH.js → usage-HX6MPQT2.js} +2 -2
- package/package.json +1 -1
package/dist/electron-server.js
CHANGED
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
touchMemoryReferences,
|
|
51
51
|
updateMemoryApproval,
|
|
52
52
|
updateMemoryEntry
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-GXB5EOFI.js";
|
|
54
54
|
import {
|
|
55
55
|
DEFAULT_PATTERNS,
|
|
56
56
|
redactJson,
|
|
@@ -66,7 +66,7 @@ import {
|
|
|
66
66
|
} from "./chunk-CGLYJRFA.js";
|
|
67
67
|
import {
|
|
68
68
|
runTestsTool
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-I73JWHNT.js";
|
|
70
70
|
import {
|
|
71
71
|
AGENTIC_BEHAVIOR_GUIDELINE,
|
|
72
72
|
APP_NAME,
|
|
@@ -100,7 +100,7 @@ import {
|
|
|
100
100
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
101
101
|
VERSION,
|
|
102
102
|
buildUserIdentityPrompt
|
|
103
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-NWM7CTQQ.js";
|
|
104
104
|
|
|
105
105
|
// src/web/server.ts
|
|
106
106
|
import express from "express";
|
|
@@ -7262,6 +7262,67 @@ function runHook(template, vars) {
|
|
|
7262
7262
|
}
|
|
7263
7263
|
}
|
|
7264
7264
|
|
|
7265
|
+
// src/core/tool-gate.ts
|
|
7266
|
+
var gateMessages = {
|
|
7267
|
+
hookDenied: (toolName, reason) => `[Hook denied] ${reason ?? `PreToolUse blocked ${toolName}`}. Do not retry without asking.`,
|
|
7268
|
+
networkDenied: (toolName, reason) => `[Permission denied] Tool ${toolName} is blocked by networkPolicy${reason ? ` (${reason})` : ""}. Do not retry.`,
|
|
7269
|
+
profileDenied: (toolName, profileName, reason) => `[Permission denied] Tool ${toolName} is blocked by permission profile "${profileName}"${reason ? ` (${reason})` : ""}. Do not retry.`,
|
|
7270
|
+
planModeDenied: (toolName) => `[Plan Mode] ${toolName} is disabled in read-only Plan Mode. Do not retry it. Use read_file / list_dir / grep_files / glob_files to investigate, and write_todos to present your plan. If the user wants this executed, tell them to type /plan execute first.`,
|
|
7271
|
+
autoDenied: (reason) => `[Auto denied] ${reason}. Do not retry without asking.`,
|
|
7272
|
+
permissionCancelled: (toolName) => `[User cancelled] The user declined permission for ${toolName}. Do not retry without asking.`,
|
|
7273
|
+
operationCancelled: (toolName, level) => `[User cancelled] The user declined the ${level === "destructive" ? "destructive " : ""}${toolName} operation. Do not retry without asking.`
|
|
7274
|
+
};
|
|
7275
|
+
function needsPermissionRequestHook(input) {
|
|
7276
|
+
return input.networkPermission?.action === "confirm" || input.permission.action === "confirm";
|
|
7277
|
+
}
|
|
7278
|
+
function decideToolGate(call, input) {
|
|
7279
|
+
const { dangerLevel, permission, networkPermission } = input;
|
|
7280
|
+
if (input.hookDeny) {
|
|
7281
|
+
return { kind: "denied", source: "hook", message: gateMessages.hookDenied(call.name, input.hookDeny.reason) };
|
|
7282
|
+
}
|
|
7283
|
+
if (input.planMode && !PLAN_MODE_READONLY_TOOLS.has(call.name)) {
|
|
7284
|
+
return { kind: "denied", source: "plan-mode", message: gateMessages.planModeDenied(call.name) };
|
|
7285
|
+
}
|
|
7286
|
+
if (networkPermission?.action === "deny") {
|
|
7287
|
+
return { kind: "denied", source: "network", message: gateMessages.networkDenied(call.name, networkPermission.reason) };
|
|
7288
|
+
}
|
|
7289
|
+
if (permission.action === "deny") {
|
|
7290
|
+
return {
|
|
7291
|
+
kind: "denied",
|
|
7292
|
+
source: "profile",
|
|
7293
|
+
message: gateMessages.profileDenied(call.name, permission.profileName ?? "default", permission.reason)
|
|
7294
|
+
};
|
|
7295
|
+
}
|
|
7296
|
+
if (permission.action === "auto-approve" && networkPermission?.action !== "confirm") {
|
|
7297
|
+
return { kind: "allow", source: "profile" };
|
|
7298
|
+
}
|
|
7299
|
+
const requiresHardConfirmation = permission.action === "confirm" && permission.hardBoundary === true;
|
|
7300
|
+
if ((networkPermission?.action === "confirm" || requiresHardConfirmation) && dangerLevel === "safe") {
|
|
7301
|
+
return { kind: "confirm", level: "write", source: "permission" };
|
|
7302
|
+
}
|
|
7303
|
+
if (input.sessionAutoMode && networkPermission?.action !== "confirm") {
|
|
7304
|
+
const classification = input.classify();
|
|
7305
|
+
if (classification.decision === "deny") {
|
|
7306
|
+
return {
|
|
7307
|
+
kind: "denied",
|
|
7308
|
+
source: "auto-mode",
|
|
7309
|
+
message: gateMessages.autoDenied(classification.reason),
|
|
7310
|
+
classification
|
|
7311
|
+
};
|
|
7312
|
+
}
|
|
7313
|
+
if (classification.decision === "auto-approve" && !requiresHardConfirmation) {
|
|
7314
|
+
return { kind: "allow", source: "auto-mode" };
|
|
7315
|
+
}
|
|
7316
|
+
}
|
|
7317
|
+
if (input.sessionAutoApprove && dangerLevel === "write" && !requiresHardConfirmation) {
|
|
7318
|
+
return { kind: "allow", source: "yolo" };
|
|
7319
|
+
}
|
|
7320
|
+
if (dangerLevel === "write" || dangerLevel === "destructive") {
|
|
7321
|
+
return { kind: "confirm", level: dangerLevel, source: "danger" };
|
|
7322
|
+
}
|
|
7323
|
+
return { kind: "allow", source: "safe" };
|
|
7324
|
+
}
|
|
7325
|
+
|
|
7265
7326
|
// src/tools/permissions.ts
|
|
7266
7327
|
import { existsSync as existsSync9, realpathSync } from "fs";
|
|
7267
7328
|
import { basename as basename2, dirname as dirname3, isAbsolute, resolve as resolve3 } from "path";
|
|
@@ -7968,6 +8029,14 @@ var ToolExecutor = class {
|
|
|
7968
8029
|
sessionAutoApprove = false;
|
|
7969
8030
|
/** Session-level Auto Mode: rule-based low-risk auto approval. */
|
|
7970
8031
|
sessionAutoMode = false;
|
|
8032
|
+
/**
|
|
8033
|
+
* Plan Mode(只读规划模式)。由宿主在每轮开始前同步。
|
|
8034
|
+
*
|
|
8035
|
+
* 必须在**执行层**也知道它:Plan Mode 此前只过滤"给模型看的工具清单",模型一旦吐出
|
|
8036
|
+
* 白名单外的调用,executor 一无所知照常执行,而 `alwaysYolo` 下 write 级还会被直接
|
|
8037
|
+
* 放行——只读保护形同虚设(审计 P2-01)。
|
|
8038
|
+
*/
|
|
8039
|
+
planMode = false;
|
|
7971
8040
|
/**
|
|
7972
8041
|
* Logical session key used to scope per-session state in stateful tools
|
|
7973
8042
|
* (currently only `bash`'s persistent cwd). Web mode sets this per-tab so
|
|
@@ -8056,13 +8125,6 @@ var ToolExecutor = class {
|
|
|
8056
8125
|
{ configDir: this.hookConfigDir, onSummary: (msg) => console.log(theme.dim(` [hook] ${msg}`)) }
|
|
8057
8126
|
);
|
|
8058
8127
|
const preDeny = preToolDecisions.find((d) => d.action === "deny");
|
|
8059
|
-
if (preDeny) {
|
|
8060
|
-
return {
|
|
8061
|
-
callId: call.id,
|
|
8062
|
-
content: `[Hook denied] ${preDeny.reason ?? `PreToolUse blocked ${call.name}`}. Do not retry without asking.`,
|
|
8063
|
-
isError: true
|
|
8064
|
-
};
|
|
8065
|
-
}
|
|
8066
8128
|
for (const d of preToolDecisions) {
|
|
8067
8129
|
const warnings = [d.warning, ...d.warnings ?? []].filter(Boolean);
|
|
8068
8130
|
for (const w of warnings) console.log(theme.warning(` \u26A0 Hook warning: ${w}`));
|
|
@@ -8082,7 +8144,20 @@ var ToolExecutor = class {
|
|
|
8082
8144
|
}
|
|
8083
8145
|
);
|
|
8084
8146
|
const networkPermission = checkNetworkPolicy(call.name, call.arguments, this.networkPolicy);
|
|
8085
|
-
|
|
8147
|
+
const gate = decideToolGate(call, {
|
|
8148
|
+
dangerLevel,
|
|
8149
|
+
permission,
|
|
8150
|
+
networkPermission,
|
|
8151
|
+
hookDeny: preDeny ? { reason: preDeny.reason } : void 0,
|
|
8152
|
+
planMode: this.planMode,
|
|
8153
|
+
sessionAutoMode: this.sessionAutoMode,
|
|
8154
|
+
sessionAutoApprove: this.sessionAutoApprove,
|
|
8155
|
+
classify: () => defaultActionClassifier.classify(call, dangerLevel, {
|
|
8156
|
+
workspaceRoot: this.workspaceRoot,
|
|
8157
|
+
tempDirs: [tmpdir()]
|
|
8158
|
+
})
|
|
8159
|
+
});
|
|
8160
|
+
if (needsPermissionRequestHook({ permission, networkPermission })) {
|
|
8086
8161
|
runLifecycleHooks(
|
|
8087
8162
|
this.hookConfig,
|
|
8088
8163
|
"PermissionRequest",
|
|
@@ -8090,131 +8165,29 @@ var ToolExecutor = class {
|
|
|
8090
8165
|
{ configDir: this.hookConfigDir, onSummary: (msg) => console.log(theme.dim(" [hook] " + msg)) }
|
|
8091
8166
|
);
|
|
8092
8167
|
}
|
|
8093
|
-
if (
|
|
8094
|
-
|
|
8095
|
-
return {
|
|
8096
|
-
callId: call.id,
|
|
8097
|
-
content: `[Permission denied] Tool ${call.name} is blocked by networkPolicy${reason}. Do not retry.`,
|
|
8098
|
-
isError: true
|
|
8099
|
-
};
|
|
8100
|
-
}
|
|
8101
|
-
if (permission.action === "deny") {
|
|
8102
|
-
const reason = permission.reason ? ` (${permission.reason})` : "";
|
|
8103
|
-
return {
|
|
8104
|
-
callId: call.id,
|
|
8105
|
-
content: `[Permission denied] Tool ${call.name} is blocked by permission profile "${permission.profileName}"${reason}. Do not retry.`,
|
|
8106
|
-
isError: true
|
|
8107
|
-
};
|
|
8108
|
-
}
|
|
8109
|
-
if (permission.action === "auto-approve" && networkPermission?.action !== "confirm") {
|
|
8110
|
-
if (!toolCallAlreadyPrinted) this.printToolCall(call);
|
|
8111
|
-
try {
|
|
8112
|
-
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
8113
|
-
const content = truncateOutput(rawContent, call.name);
|
|
8114
|
-
const wasTruncated = content !== rawContent;
|
|
8115
|
-
this.printToolResult(call.name, rawContent, false, wasTruncated);
|
|
8116
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
|
|
8117
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
|
|
8118
|
-
return { callId: call.id, content, isError: false };
|
|
8119
|
-
} catch (err) {
|
|
8120
|
-
const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
|
|
8121
|
-
this.printToolResult(call.name, message, true, false);
|
|
8122
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
|
|
8123
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
|
|
8124
|
-
return { callId: call.id, content: message, isError: true };
|
|
8125
|
-
}
|
|
8126
|
-
}
|
|
8127
|
-
const requiresHardConfirmation = permission.action === "confirm" && permission.hardBoundary === true;
|
|
8128
|
-
if ((networkPermission?.action === "confirm" || requiresHardConfirmation) && dangerLevel === "safe") {
|
|
8129
|
-
this.printToolCall(call);
|
|
8130
|
-
toolCallAlreadyPrinted = true;
|
|
8131
|
-
const confirmed = await this.confirm(call, "write");
|
|
8132
|
-
if (!confirmed) {
|
|
8133
|
-
return {
|
|
8134
|
-
callId: call.id,
|
|
8135
|
-
content: `[User cancelled] The user declined permission for ${call.name}. Do not retry without asking.`,
|
|
8136
|
-
isError: true
|
|
8137
|
-
};
|
|
8138
|
-
}
|
|
8168
|
+
if (gate.kind === "denied") {
|
|
8169
|
+
if (gate.source === "auto-mode") recordRecentlyDeniedAutoAction(call, gate.classification);
|
|
8170
|
+
return { callId: call.id, content: gate.message, isError: true };
|
|
8139
8171
|
}
|
|
8140
|
-
if (
|
|
8141
|
-
|
|
8142
|
-
workspaceRoot: this.workspaceRoot,
|
|
8143
|
-
tempDirs: [tmpdir()]
|
|
8144
|
-
});
|
|
8145
|
-
if (classification.decision === "deny") {
|
|
8146
|
-
recordRecentlyDeniedAutoAction(call, classification);
|
|
8147
|
-
return {
|
|
8148
|
-
callId: call.id,
|
|
8149
|
-
content: `[Auto denied] ${classification.reason}. Do not retry without asking.`,
|
|
8150
|
-
isError: true
|
|
8151
|
-
};
|
|
8152
|
-
}
|
|
8153
|
-
if (classification.decision === "auto-approve" && !requiresHardConfirmation) {
|
|
8172
|
+
if (gate.kind === "confirm") {
|
|
8173
|
+
if (gate.source === "danger" && gate.level === "write") {
|
|
8154
8174
|
this.printToolCall(call);
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
const wasTruncated = content !== rawContent;
|
|
8161
|
-
this.printToolResult(call.name, rawContent, false, wasTruncated);
|
|
8162
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
|
|
8163
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
|
|
8164
|
-
return { callId: call.id, content, isError: false };
|
|
8165
|
-
} catch (err) {
|
|
8166
|
-
const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
|
|
8167
|
-
this.printToolResult(call.name, message, true, false);
|
|
8168
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
|
|
8169
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
|
|
8170
|
-
return { callId: call.id, content: message, isError: true };
|
|
8171
|
-
}
|
|
8172
|
-
}
|
|
8173
|
-
}
|
|
8174
|
-
if (this.sessionAutoApprove && dangerLevel === "write" && !requiresHardConfirmation) {
|
|
8175
|
-
this.printToolCall(call);
|
|
8176
|
-
if (dangerLevel === "write") this.printDiffPreview(call);
|
|
8177
|
-
console.log(theme.warning(" \u26A1 Auto-approved (session /yolo mode)"));
|
|
8178
|
-
try {
|
|
8179
|
-
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
8180
|
-
const content = truncateOutput(rawContent, call.name);
|
|
8181
|
-
const wasTruncated = content !== rawContent;
|
|
8182
|
-
this.printToolResult(call.name, rawContent, false, wasTruncated);
|
|
8183
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
|
|
8184
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
|
|
8185
|
-
return { callId: call.id, content, isError: false };
|
|
8186
|
-
} catch (err) {
|
|
8187
|
-
const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
|
|
8188
|
-
this.printToolResult(call.name, message, true, false);
|
|
8189
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
|
|
8190
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
|
|
8191
|
-
return { callId: call.id, content: message, isError: true };
|
|
8192
|
-
}
|
|
8193
|
-
}
|
|
8194
|
-
if (dangerLevel === "write") {
|
|
8195
|
-
this.printToolCall(call);
|
|
8196
|
-
this.printDiffPreview(call);
|
|
8197
|
-
const confirmed = await this.confirm(call, dangerLevel);
|
|
8198
|
-
if (!confirmed) {
|
|
8199
|
-
return {
|
|
8200
|
-
callId: call.id,
|
|
8201
|
-
content: `[User cancelled] The user declined the ${call.name} operation. Do not retry without asking.`,
|
|
8202
|
-
isError: true
|
|
8203
|
-
};
|
|
8175
|
+
this.printDiffPreview(call);
|
|
8176
|
+
toolCallAlreadyPrinted = true;
|
|
8177
|
+
} else if (gate.source === "permission") {
|
|
8178
|
+
this.printToolCall(call);
|
|
8179
|
+
toolCallAlreadyPrinted = true;
|
|
8204
8180
|
}
|
|
8205
|
-
|
|
8206
|
-
const confirmed = await this.confirm(call, dangerLevel);
|
|
8181
|
+
const confirmed = await this.confirm(call, gate.level);
|
|
8207
8182
|
if (!confirmed) {
|
|
8208
8183
|
return {
|
|
8209
8184
|
callId: call.id,
|
|
8210
|
-
content:
|
|
8185
|
+
content: gate.source === "permission" ? gateMessages.permissionCancelled(call.name) : gateMessages.operationCancelled(call.name, gate.level),
|
|
8211
8186
|
isError: true
|
|
8212
8187
|
};
|
|
8213
8188
|
}
|
|
8214
|
-
this.printToolCall(call);
|
|
8215
|
-
} else {
|
|
8216
|
-
this.printToolCall(call);
|
|
8217
8189
|
}
|
|
8190
|
+
if (!toolCallAlreadyPrinted) this.printToolCall(call);
|
|
8218
8191
|
try {
|
|
8219
8192
|
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
8220
8193
|
const content = truncateOutput(rawContent, call.name);
|
|
@@ -13843,6 +13816,14 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
13843
13816
|
sessionAutoApprove = false;
|
|
13844
13817
|
/** Session-level Auto Mode: rule-based low-risk auto approval. */
|
|
13845
13818
|
sessionAutoMode = false;
|
|
13819
|
+
/**
|
|
13820
|
+
* Plan Mode(只读规划模式)。由宿主在每轮开始前同步。
|
|
13821
|
+
*
|
|
13822
|
+
* 必须在**执行层**也知道它:Plan Mode 此前只过滤"给模型看的工具清单",模型一旦吐出
|
|
13823
|
+
* 白名单外的调用,executor 一无所知照常执行,而 `alwaysYolo` 下 write 级还会被直接
|
|
13824
|
+
* 放行——只读保护形同虚设(审计 P2-01)。
|
|
13825
|
+
*/
|
|
13826
|
+
planMode = false;
|
|
13846
13827
|
/** Track tool start times for duration calculation */
|
|
13847
13828
|
toolStartTimes = /* @__PURE__ */ new Map();
|
|
13848
13829
|
/**
|
|
@@ -14048,15 +14029,6 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
14048
14029
|
{ configDir: this.hookConfigDir, onSummary: (message) => this.send({ type: "info", message: `[hook] ${message}` }) }
|
|
14049
14030
|
);
|
|
14050
14031
|
const preDeny = preToolDecisions.find((d) => d.action === "deny");
|
|
14051
|
-
if (preDeny) {
|
|
14052
|
-
const result = {
|
|
14053
|
-
callId: call.id,
|
|
14054
|
-
content: `[Hook denied] ${preDeny.reason ?? `PreToolUse blocked ${call.name}`}. Do not retry without asking.`,
|
|
14055
|
-
isError: true
|
|
14056
|
-
};
|
|
14057
|
-
this.sendToolCallResult(call, result.content, true);
|
|
14058
|
-
return result;
|
|
14059
|
-
}
|
|
14060
14032
|
for (const d of preToolDecisions) {
|
|
14061
14033
|
const warnings = [d.warning, ...d.warnings ?? []].filter(Boolean);
|
|
14062
14034
|
for (const warning of warnings) this.send({ type: "info", message: `[hook] ${warning}` });
|
|
@@ -14076,7 +14048,20 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
14076
14048
|
}
|
|
14077
14049
|
);
|
|
14078
14050
|
const networkPermission = checkNetworkPolicy(call.name, call.arguments, this.networkPolicy);
|
|
14079
|
-
|
|
14051
|
+
const gate = decideToolGate(call, {
|
|
14052
|
+
dangerLevel,
|
|
14053
|
+
permission,
|
|
14054
|
+
networkPermission,
|
|
14055
|
+
hookDeny: preDeny ? { reason: preDeny.reason } : void 0,
|
|
14056
|
+
planMode: this.planMode,
|
|
14057
|
+
sessionAutoMode: this.sessionAutoMode,
|
|
14058
|
+
sessionAutoApprove: this.sessionAutoApprove,
|
|
14059
|
+
classify: () => defaultActionClassifier.classify(call, dangerLevel, {
|
|
14060
|
+
workspaceRoot: this.workspaceRoot,
|
|
14061
|
+
tempDirs: [tmpdir2()]
|
|
14062
|
+
})
|
|
14063
|
+
});
|
|
14064
|
+
if (needsPermissionRequestHook({ permission, networkPermission })) {
|
|
14080
14065
|
runLifecycleHooks(
|
|
14081
14066
|
this.hookConfig,
|
|
14082
14067
|
"PermissionRequest",
|
|
@@ -14084,105 +14069,24 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
|
|
|
14084
14069
|
{ configDir: this.hookConfigDir, onSummary: (message) => this.send({ type: "info", message: "[hook] " + message }) }
|
|
14085
14070
|
);
|
|
14086
14071
|
}
|
|
14087
|
-
if (
|
|
14088
|
-
|
|
14089
|
-
|
|
14090
|
-
|
|
14091
|
-
content: `[Permission denied] Tool ${call.name} is blocked by networkPolicy${reason}. Do not retry.`,
|
|
14092
|
-
isError: true
|
|
14093
|
-
};
|
|
14094
|
-
}
|
|
14095
|
-
if (permission.action === "deny") {
|
|
14096
|
-
const reason = permission.reason ? ` (${permission.reason})` : "";
|
|
14097
|
-
return {
|
|
14098
|
-
callId: call.id,
|
|
14099
|
-
content: `[Permission denied] Tool ${call.name} is blocked by permission profile "${permission.profileName}"${reason}. Do not retry.`,
|
|
14100
|
-
isError: true
|
|
14101
|
-
};
|
|
14102
|
-
}
|
|
14103
|
-
if (permission.action === "auto-approve" && networkPermission?.action !== "confirm") {
|
|
14104
|
-
this.sendToolCallStart(call);
|
|
14105
|
-
try {
|
|
14106
|
-
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
14107
|
-
const content = truncateOutput(rawContent, call.name);
|
|
14108
|
-
this.sendToolCallResult(call, rawContent, false);
|
|
14109
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
|
|
14110
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
|
|
14111
|
-
return { callId: call.id, content, isError: false };
|
|
14112
|
-
} catch (err) {
|
|
14113
|
-
const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
|
|
14114
|
-
this.sendToolCallResult(call, message, true);
|
|
14115
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
|
|
14116
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
|
|
14117
|
-
return { callId: call.id, content: message, isError: true };
|
|
14118
|
-
}
|
|
14119
|
-
}
|
|
14120
|
-
const requiresHardConfirmation = permission.action === "confirm" && permission.hardBoundary === true;
|
|
14121
|
-
if ((networkPermission?.action === "confirm" || requiresHardConfirmation) && dangerLevel === "safe") {
|
|
14122
|
-
this.sendToolCallStart(call);
|
|
14123
|
-
toolCallStarted = true;
|
|
14124
|
-
const confirmed = await this.confirm(call, "write");
|
|
14125
|
-
if (!confirmed) {
|
|
14126
|
-
const rejectionMsg = `[User cancelled] The user declined permission for ${call.name}. Do not retry without asking.`;
|
|
14127
|
-
this.sendToolCallResult(call, rejectionMsg, true);
|
|
14128
|
-
return { callId: call.id, content: rejectionMsg, isError: true };
|
|
14129
|
-
}
|
|
14072
|
+
if (gate.kind === "denied") {
|
|
14073
|
+
if (gate.source === "auto-mode") recordRecentlyDeniedAutoAction(call, gate.classification);
|
|
14074
|
+
this.sendToolCallResult(call, gate.message, true);
|
|
14075
|
+
return { callId: call.id, content: gate.message, isError: true };
|
|
14130
14076
|
}
|
|
14131
|
-
if (
|
|
14132
|
-
|
|
14133
|
-
|
|
14134
|
-
|
|
14135
|
-
tempDirs: [tmpdir2()]
|
|
14136
|
-
});
|
|
14137
|
-
if (classification.decision === "deny") {
|
|
14138
|
-
recordRecentlyDeniedAutoAction(call, classification);
|
|
14139
|
-
const rejectionMsg = `[Auto denied] ${classification.reason}. Do not retry without asking.`;
|
|
14140
|
-
this.sendToolCallResult(call, rejectionMsg, true);
|
|
14141
|
-
return { callId: call.id, content: rejectionMsg, isError: true };
|
|
14077
|
+
if (gate.kind === "confirm") {
|
|
14078
|
+
if (!toolCallStarted) {
|
|
14079
|
+
this.sendToolCallStart(call);
|
|
14080
|
+
toolCallStarted = true;
|
|
14142
14081
|
}
|
|
14143
|
-
|
|
14144
|
-
this.send({ type: "info", message: `\u26A1 Auto-approved (/auto: ${classification.ruleId})` });
|
|
14145
|
-
try {
|
|
14146
|
-
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
14147
|
-
const content = truncateOutput(rawContent, call.name);
|
|
14148
|
-
this.sendToolCallResult(call, rawContent, false);
|
|
14149
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
|
|
14150
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
|
|
14151
|
-
return { callId: call.id, content, isError: false };
|
|
14152
|
-
} catch (err) {
|
|
14153
|
-
const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
|
|
14154
|
-
this.sendToolCallResult(call, message, true);
|
|
14155
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
|
|
14156
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
|
|
14157
|
-
return { callId: call.id, content: message, isError: true };
|
|
14158
|
-
}
|
|
14159
|
-
}
|
|
14160
|
-
}
|
|
14161
|
-
if (this.sessionAutoApprove && dangerLevel === "write" && !requiresHardConfirmation) {
|
|
14162
|
-
try {
|
|
14163
|
-
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
14164
|
-
const content = truncateOutput(rawContent, call.name);
|
|
14165
|
-
this.sendToolCallResult(call, rawContent, false);
|
|
14166
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "ok" });
|
|
14167
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "ok" }, { configDir: this.hookConfigDir });
|
|
14168
|
-
return { callId: call.id, content, isError: false };
|
|
14169
|
-
} catch (err) {
|
|
14170
|
-
const message = err instanceof Error ? err.message : err && typeof err === "object" && "message" in err ? String(err.message) : String(err);
|
|
14171
|
-
this.sendToolCallResult(call, message, true);
|
|
14172
|
-
runHook(this.hookConfig?.postToolExecution, { tool: call.name, status: "error" });
|
|
14173
|
-
runLifecycleHooks(this.hookConfig, "PostToolUse", { tool: call.name, status: "error", error: message }, { configDir: this.hookConfigDir });
|
|
14174
|
-
return { callId: call.id, content: message, isError: true };
|
|
14175
|
-
}
|
|
14176
|
-
}
|
|
14177
|
-
if (dangerLevel === "write" || dangerLevel === "destructive") {
|
|
14178
|
-
const confirmed = await this.confirm(call, dangerLevel);
|
|
14082
|
+
const confirmed = await this.confirm(call, gate.level);
|
|
14179
14083
|
if (!confirmed) {
|
|
14180
|
-
const
|
|
14181
|
-
const rejectionMsg = `[User cancelled] The user declined the ${label}${call.name} operation. Do not retry without asking.`;
|
|
14084
|
+
const rejectionMsg = gate.source === "permission" ? gateMessages.permissionCancelled(call.name) : gateMessages.operationCancelled(call.name, gate.level);
|
|
14182
14085
|
this.sendToolCallResult(call, rejectionMsg, true);
|
|
14183
14086
|
return { callId: call.id, content: rejectionMsg, isError: true };
|
|
14184
14087
|
}
|
|
14185
14088
|
}
|
|
14089
|
+
if (!toolCallStarted) this.sendToolCallStart(call);
|
|
14186
14090
|
try {
|
|
14187
14091
|
const rawContent = await runTool(tool, call.arguments, call.name);
|
|
14188
14092
|
const content = truncateOutput(rawContent, call.name);
|
|
@@ -16997,7 +16901,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
16997
16901
|
Cost: ${formatCost(cost)}` : "";
|
|
16998
16902
|
let memoryLine = "";
|
|
16999
16903
|
try {
|
|
17000
|
-
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-
|
|
16904
|
+
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-7PPH6QES.js");
|
|
17001
16905
|
const pending = countPendingMemories2(ctx.config.getConfigDir());
|
|
17002
16906
|
if (pending > 0) memoryLine = `
|
|
17003
16907
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -17980,7 +17884,7 @@ async function handleTest(args, ctx) {
|
|
|
17980
17884
|
const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
|
|
17981
17885
|
testArgs = isCommand ? { command: argStr } : { filter: argStr };
|
|
17982
17886
|
}
|
|
17983
|
-
const runTests = ctx.runTests ?? (await import("./run-tests-
|
|
17887
|
+
const runTests = ctx.runTests ?? (await import("./run-tests-PPTDYVS7.js")).executeTests;
|
|
17984
17888
|
const report = await runTests(testArgs);
|
|
17985
17889
|
ctx.send({ type: "info", message: report });
|
|
17986
17890
|
} catch (err) {
|
|
@@ -18370,7 +18274,7 @@ async function handleMemory(args, ctx) {
|
|
|
18370
18274
|
}
|
|
18371
18275
|
if (intent.kind === "status") {
|
|
18372
18276
|
const { getChatIndexStatus: getChatIndexStatus2 } = await import("./chat-index-DGUOUUQW.js");
|
|
18373
|
-
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-
|
|
18277
|
+
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-7PPH6QES.js");
|
|
18374
18278
|
const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
|
|
18375
18279
|
const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
|
|
18376
18280
|
const view = buildMemoryStatusView({
|
|
@@ -18393,7 +18297,7 @@ async function handleMemory(args, ctx) {
|
|
|
18393
18297
|
return;
|
|
18394
18298
|
}
|
|
18395
18299
|
if (intent.kind === "recall") {
|
|
18396
|
-
const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-
|
|
18300
|
+
const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-7PPH6QES.js");
|
|
18397
18301
|
const { searchChatMemory: searchChatMemory2 } = await import("./chat-index-DGUOUUQW.js");
|
|
18398
18302
|
const persistentHits = searchPersistentMemories2(configDir, intent.query, process.cwd(), 3);
|
|
18399
18303
|
if (persistentHits.length > 0) {
|
|
@@ -18514,7 +18418,7 @@ async function handleMemory(args, ctx) {
|
|
|
18514
18418
|
ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
|
|
18515
18419
|
} else if (intent.kind === "export") {
|
|
18516
18420
|
if (args[1] === "md") {
|
|
18517
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
18421
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-7PPH6QES.js");
|
|
18518
18422
|
ctx.send({
|
|
18519
18423
|
type: "export_data",
|
|
18520
18424
|
format: "md",
|
|
@@ -19519,7 +19423,7 @@ No tools match "${filter}".
|
|
|
19519
19423
|
const { join: join29 } = await import("path");
|
|
19520
19424
|
const { existsSync: existsSync33 } = await import("fs");
|
|
19521
19425
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-VNCA2GU7.js");
|
|
19522
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
19426
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-MYTDRODA.js");
|
|
19523
19427
|
const { approveProject, hashMcpFile } = await import("./project-trust-MUG325AW.js");
|
|
19524
19428
|
const cwd = process.cwd();
|
|
19525
19429
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
@@ -20434,7 +20338,7 @@ function createReviewCommands() {
|
|
|
20434
20338
|
usage: "/test [command|filter]",
|
|
20435
20339
|
async execute(args, ctx) {
|
|
20436
20340
|
try {
|
|
20437
|
-
const { executeTests } = await import("./run-tests-
|
|
20341
|
+
const { executeTests } = await import("./run-tests-PPTDYVS7.js");
|
|
20438
20342
|
const argStr = args.join(" ").trim();
|
|
20439
20343
|
let testArgs = {};
|
|
20440
20344
|
if (argStr) {
|
|
@@ -22931,7 +22835,7 @@ var SessionHandler = class {
|
|
|
22931
22835
|
...simpleReasoning ? { reasoningContent: simpleReasoning } : {}
|
|
22932
22836
|
});
|
|
22933
22837
|
} catch (err) {
|
|
22934
|
-
if (err
|
|
22838
|
+
if (isAbortError(err)) {
|
|
22935
22839
|
this.send({ type: "info", message: "[interrupted]" });
|
|
22936
22840
|
} else {
|
|
22937
22841
|
throw err;
|
|
@@ -22948,7 +22852,7 @@ var SessionHandler = class {
|
|
|
22948
22852
|
const autoPauseIntervalRaw = this.config.get("autoPauseInterval");
|
|
22949
22853
|
const autoPauseInterval = typeof autoPauseIntervalRaw === "number" ? autoPauseIntervalRaw : 50;
|
|
22950
22854
|
const { stable: toolStable, volatile: toolVolatile } = this.buildSystemPrompt();
|
|
22951
|
-
const roundBudgetHint = buildRoundBudgetHint({ maxToolRounds, autoPauseInterval });
|
|
22855
|
+
const roundBudgetHint = buildRoundBudgetHint({ maxToolRounds, autoPauseInterval, planMode: this.planMode });
|
|
22952
22856
|
const systemPrompt = toolStable + TOOL_CALL_REMINDER + roundBudgetHint + (mcpBudgetNote ? `
|
|
22953
22857
|
|
|
22954
22858
|
${mcpBudgetNote}` : "");
|
|
@@ -23251,7 +23155,7 @@ ${summaryContent}`,
|
|
|
23251
23155
|
this.send({ type: "info", message: "[interrupted]" });
|
|
23252
23156
|
}
|
|
23253
23157
|
} catch (err) {
|
|
23254
|
-
if (err
|
|
23158
|
+
if (isAbortError(err)) {
|
|
23255
23159
|
this.send({ type: "info", message: "[interrupted]" });
|
|
23256
23160
|
} else {
|
|
23257
23161
|
throw err;
|
|
@@ -23864,6 +23768,7 @@ Backup saved: ${result.backupPath}` : "";
|
|
|
23864
23768
|
};
|
|
23865
23769
|
}
|
|
23866
23770
|
getFilteredToolDefs() {
|
|
23771
|
+
this.toolExecutor.planMode = this.planMode;
|
|
23867
23772
|
if (this.planMode) {
|
|
23868
23773
|
return {
|
|
23869
23774
|
toolDefs: this.toolRegistry.getDefinitions().filter((t) => PLAN_MODE_READONLY_TOOLS.has(t.name)),
|
|
@@ -158,7 +158,7 @@ ${content}`);
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
161
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
161
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-HA4JE4TF.js");
|
|
162
162
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
163
163
|
let interrupted = false;
|
|
164
164
|
const onSigint = () => {
|