context-mode 2.0.0-next.6 → 2.0.0-next.8
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/SHA256SUMS +17 -17
- package/cli.mjs +3052 -691
- package/copilot/plugin.json +1 -1
- package/gemini-extension.json +1 -1
- package/hook.mjs +84 -82
- package/opencode/plugin.js +3230 -960
- package/package.json +1 -1
- package/pi/index.js +3047 -777
- package/qwen-extension.json +1 -1
- package/run.mjs +161 -41
- package/search.mjs +161 -41
- package/server.mjs +3011 -740
- package/skills/ctx-doctor/SKILL.md +1 -1
- package/skills/ctx-stats/SKILL.md +1 -1
- package/skills/ctx-upgrade/SKILL.md +1 -1
package/qwen-extension.json
CHANGED
package/run.mjs
CHANGED
|
@@ -236,7 +236,7 @@ var EDIT_TOOLS = Object.freeze(["Write", "Edit"]);
|
|
|
236
236
|
var EDIT_PATH_KEYS = Object.freeze(["file_path", "path"]);
|
|
237
237
|
var STATS_COLUMNS = Object.freeze(["Scope", "Produced", "Returned", "Saved", "Reduction %"]);
|
|
238
238
|
var PURGE_SCOPES = Object.freeze(["session", "source", "project"]);
|
|
239
|
-
var DOCTOR_CHECK_ORDER = Object.freeze(["D1", "D2", "D3", "D4", "D5", "D5b", "D6", "D7", "D8", "D9", "D10"]);
|
|
239
|
+
var DOCTOR_CHECK_ORDER = Object.freeze(["D1", "D2", "D3", "D4", "D5", "D5b", "D6", "D7", "D8", "D9", "D10", "D11"]);
|
|
240
240
|
var DOCTOR_LABEL = Object.freeze({
|
|
241
241
|
D1: "version",
|
|
242
242
|
D2: "node",
|
|
@@ -248,7 +248,8 @@ var DOCTOR_LABEL = Object.freeze({
|
|
|
248
248
|
D7: "project and worktree",
|
|
249
249
|
D8: "context.db",
|
|
250
250
|
D9: "index",
|
|
251
|
-
D10: "enforcement mode"
|
|
251
|
+
D10: "enforcement mode",
|
|
252
|
+
D11: "shell"
|
|
252
253
|
});
|
|
253
254
|
var REPORT_TRUNCATED_LINE = `(report truncated at ${REPORT_CAP} B; run ctx_doctor again after the first fix)`;
|
|
254
255
|
var D2_NODE_FIX = `install Node ${NODE_MIN} or later`;
|
|
@@ -271,6 +272,9 @@ var GIT_HEAD_SHA_ARGS = Object.freeze(["rev-parse", "HEAD"]);
|
|
|
271
272
|
var UPGRADE_GIT_CHECKOUT_AGENTS = Object.freeze(["pi", "opencode"]);
|
|
272
273
|
var GIT_NO_PROMPT_ENV = Object.freeze({ GIT_TERMINAL_PROMPT: "0" });
|
|
273
274
|
var GIT_NO_CRLF_ENV = Object.freeze({ GIT_CONFIG_COUNT: "1", GIT_CONFIG_KEY_0: "core.autocrlf", GIT_CONFIG_VALUE_0: "false" });
|
|
275
|
+
var GIT_BIN = "git";
|
|
276
|
+
var WIN_SHELL_LANGS = Object.freeze(["shell", "bash", "sh"]);
|
|
277
|
+
var GIT_BASH_RELATIVE = Object.freeze([["..", "bin", "bash.exe"], ["..", "..", "bin", "bash.exe"]]);
|
|
274
278
|
var OPS_SPLIT_FILES = Object.freeze([
|
|
275
279
|
"doctor-env.ts",
|
|
276
280
|
"doctor-config.ts",
|
|
@@ -287,10 +291,10 @@ var OPS_SPLIT_FILES = Object.freeze([
|
|
|
287
291
|
var HOOK_HOST_FILE = Object.freeze({
|
|
288
292
|
"claude-code": { root: "plugin", file: ["hooks", "claude-code.json"], key: ["hooks"], shape: "nested", timeoutKey: "timeout", matcher: true },
|
|
289
293
|
codex: { root: "home", file: [".codex", "hooks.json"], key: ["hooks"], shape: "nested", timeoutKey: "timeout", matcher: true },
|
|
290
|
-
gemini: { root: "
|
|
291
|
-
qwen: { root: "
|
|
294
|
+
gemini: { root: "plugin", file: ["hooks", "hooks.json"], key: ["hooks"], shape: "nested", timeoutKey: "timeout", matcher: false },
|
|
295
|
+
qwen: { root: "plugin", file: ["hooks", "qwen.json"], key: ["hooks"], shape: "nested", timeoutKey: "timeout", matcher: true },
|
|
292
296
|
"copilot-cli": { root: "home", file: [".copilot", "hooks", "context-mode.json"], key: ["hooks"], shape: "flat", timeoutKey: "timeoutSec", matcher: false },
|
|
293
|
-
vscode: { root: "
|
|
297
|
+
vscode: { root: "home", file: [".copilot", "hooks", "context-mode-vscode.json"], key: ["hooks"], shape: "flat", timeoutKey: "timeout", matcher: false },
|
|
294
298
|
kiro: { root: "home", file: [".kiro", "hooks", "context-mode.json"], key: ["hooks"], shape: "kiro", timeoutKey: "timeout", matcher: false },
|
|
295
299
|
zcode: { root: "home", file: [".zcode", "cli", "config.json"], key: ["hooks", "events"], shape: "zcode", timeoutKey: "timeoutMs", matcher: true },
|
|
296
300
|
pi: null,
|
|
@@ -324,12 +328,16 @@ var V1_SCRIPT_NAMES = Object.freeze([
|
|
|
324
328
|
]);
|
|
325
329
|
var V1_CODEX_HOOKS_DIR = Object.freeze(["hooks", "codex"]);
|
|
326
330
|
var V1_CACHE_HEAL_EXTS = Object.freeze([".mjs", ".sh"]);
|
|
331
|
+
var VSCODE_USER_DIR_SEGMENTS = Object.freeze(["Code", "User"]);
|
|
332
|
+
var VSCODE_MCP_FILE = "mcp.json";
|
|
327
333
|
var KIRO_AGENT_FILE = Object.freeze(["agents", "default.json"]);
|
|
328
334
|
var KIRO_STEERING_FILE = Object.freeze(["steering", "KIRO.md"]);
|
|
329
335
|
var OPENCODE_CONFIG_FILES = Object.freeze(["opencode.jsonc", "opencode.json"]);
|
|
330
336
|
var V1_DATA_ROOT_ENTRIES = Object.freeze(["content", "platform.json"]);
|
|
331
337
|
var PI_ROLE = "custom";
|
|
332
338
|
var V1_PATH_SEPS = Object.freeze(["/", "\\"]);
|
|
339
|
+
var HOST_SEP_TOKEN = "${/}";
|
|
340
|
+
var HOOK_SCRIPT_SEPS = Object.freeze([...V1_PATH_SEPS, HOST_SEP_TOKEN]);
|
|
333
341
|
var V1_REASON = Object.freeze({
|
|
334
342
|
hook: "old context-mode hook entry: command contains context-mode and an old script name or context-mode hook",
|
|
335
343
|
cacheHealHook: "old context-mode cache-heal SessionStart hook entry",
|
|
@@ -356,9 +364,11 @@ var OPENCODE_TOOL_PREFIX = SERVER_KEY + "_";
|
|
|
356
364
|
var ZCODE_MCP_FEATURE_KEY = Object.freeze(["features", "mcp"]);
|
|
357
365
|
var CODEX_OMIT_TOOLS_FROM_FIELD = "omit_tools_from";
|
|
358
366
|
var CODEX_OMIT_DEFERRED = Object.freeze(["deferred"]);
|
|
367
|
+
var CODEX_APPROVAL_MODE_FIELD = "default_tools_approval_mode";
|
|
368
|
+
var CODEX_APPROVAL_APPROVE = "approve";
|
|
359
369
|
var OWN_MCP_ENTRY = Object.freeze({
|
|
360
|
-
codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY], fields: { [CODEX_OMIT_TOOLS_FROM_FIELD]: CODEX_OMIT_DEFERRED } },
|
|
361
|
-
vscode: { file: [
|
|
370
|
+
codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY], fields: { [CODEX_OMIT_TOOLS_FROM_FIELD]: CODEX_OMIT_DEFERRED, [CODEX_APPROVAL_MODE_FIELD]: CODEX_APPROVAL_APPROVE } },
|
|
371
|
+
vscode: { file: [VSCODE_MCP_FILE], key: ["servers", SERVER_KEY] },
|
|
362
372
|
kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
|
|
363
373
|
zcode: {
|
|
364
374
|
file: [".zcode", "cli", "config.json"],
|
|
@@ -732,8 +742,14 @@ var VSCODE_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostTool
|
|
|
732
742
|
var MCP_PREFIX2 = "mcp_";
|
|
733
743
|
var MCP_SEP2 = "_";
|
|
734
744
|
var SESSION_START_NEW = "new";
|
|
735
|
-
var
|
|
736
|
-
var
|
|
745
|
+
var SHELL_TOOL_NAMES = Object.freeze(["run_in_terminal", "runTerminalCommand", "bash", "powershell"]);
|
|
746
|
+
var READ_TOOL_NAMES = Object.freeze(["read_file", "view"]);
|
|
747
|
+
var WEBFETCH_TOOL_NAMES = Object.freeze(["fetch_webpage", "web_fetch"]);
|
|
748
|
+
var NATIVE_TO_CANONICAL4 = Object.fromEntries([
|
|
749
|
+
...SHELL_TOOL_NAMES.map((n) => [n, "Bash"]),
|
|
750
|
+
...READ_TOOL_NAMES.map((n) => [n, "Read"]),
|
|
751
|
+
...WEBFETCH_TOOL_NAMES.map((n) => [n, "WebFetch"])
|
|
752
|
+
]);
|
|
737
753
|
function canonicalName4(name) {
|
|
738
754
|
if (name.startsWith(TOOL_NAME_PREFIX6)) return name.slice(TOOL_NAME_PREFIX6.length);
|
|
739
755
|
if (Object.hasOwn(NATIVE_TO_CANONICAL4, name)) return NATIVE_TO_CANONICAL4[name];
|
|
@@ -743,14 +759,88 @@ function canonicalName4(name) {
|
|
|
743
759
|
if (sep3 <= 0 || sep3 === rest.length - 1) return name;
|
|
744
760
|
return "mcp:" + rest.slice(0, sep3) + ":" + rest.slice(sep3 + MCP_SEP2.length);
|
|
745
761
|
}
|
|
762
|
+
var isNum = (v) => typeof v === "number" && Number.isFinite(v);
|
|
763
|
+
function policyInput(name, canonical, input) {
|
|
764
|
+
if (canonical === "Read" && READ_TOOL_NAMES.includes(name)) {
|
|
765
|
+
const out = { ...input };
|
|
766
|
+
if (name === "read_file") {
|
|
767
|
+
if (typeof input.filePath === "string") out.file_path = input.filePath;
|
|
768
|
+
if (isNum(input.startLine)) out.offset = input.startLine;
|
|
769
|
+
if (isNum(input.startLine) && isNum(input.endLine) && input.endLine >= input.startLine) out.limit = input.endLine - input.startLine + 1;
|
|
770
|
+
} else if (Array.isArray(input.view_range) && isNum(input.view_range[0])) {
|
|
771
|
+
out.offset = input.view_range[0];
|
|
772
|
+
const end = input.view_range[1];
|
|
773
|
+
if (isNum(end) && end >= input.view_range[0]) out.limit = end - input.view_range[0] + 1;
|
|
774
|
+
}
|
|
775
|
+
return out;
|
|
776
|
+
}
|
|
777
|
+
if (canonical === "WebFetch" && name === "fetch_webpage" && Array.isArray(input.urls) && typeof input.urls[0] === "string") {
|
|
778
|
+
return { ...input, url: input.urls[0] };
|
|
779
|
+
}
|
|
780
|
+
return input;
|
|
781
|
+
}
|
|
746
782
|
function readResult4(resp) {
|
|
747
783
|
const text = resp === void 0 ? "" : typeof resp === "string" ? resp : JSON.stringify(resp);
|
|
748
784
|
const isError = typeof resp === "object" && resp !== null && resp.is_error === true;
|
|
749
785
|
return { isError, bytes: Buffer.byteLength(text), text };
|
|
750
786
|
}
|
|
787
|
+
var CAMEL_EVENTS = {
|
|
788
|
+
sessionStart: "SessionStart",
|
|
789
|
+
userPromptSubmitted: "UserPromptSubmit",
|
|
790
|
+
preToolUse: "PreToolUse",
|
|
791
|
+
postToolUse: "PostToolUse",
|
|
792
|
+
preCompact: "PreCompact"
|
|
793
|
+
};
|
|
794
|
+
var EVENT_BY_KEY2 = [
|
|
795
|
+
["toolResult", "postToolUse"],
|
|
796
|
+
["toolName", "preToolUse"],
|
|
797
|
+
["prompt", "userPromptSubmitted"],
|
|
798
|
+
["source", "sessionStart"],
|
|
799
|
+
["trigger", "preCompact"]
|
|
800
|
+
];
|
|
801
|
+
var SESSION_SOURCES = { new: "startup", startup: "startup", resume: "resume" };
|
|
802
|
+
var RESULT_SUCCESS2 = "success";
|
|
803
|
+
function isRecord2(v) {
|
|
804
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
805
|
+
}
|
|
806
|
+
function readArgs2(v) {
|
|
807
|
+
if (isRecord2(v)) return v;
|
|
808
|
+
if (typeof v !== "string") return {};
|
|
809
|
+
try {
|
|
810
|
+
const parsed = JSON.parse(v);
|
|
811
|
+
return isRecord2(parsed) ? parsed : {};
|
|
812
|
+
} catch {
|
|
813
|
+
return {};
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
function readCamelResult(v) {
|
|
817
|
+
const r = isRecord2(v) ? v : {};
|
|
818
|
+
const text = typeof r.textResultForLlm === "string" ? r.textResultForLlm : "";
|
|
819
|
+
return { isError: typeof r.resultType === "string" && r.resultType !== RESULT_SUCCESS2, bytes: Buffer.byteLength(text), text };
|
|
820
|
+
}
|
|
821
|
+
function decodeCamel(p, name) {
|
|
822
|
+
const event = typeof name === "string" ? CAMEL_EVENTS[name] ?? VSCODE_EVENTS.find((e) => e === name) : void 0;
|
|
823
|
+
if (event === void 0) throw new Error("vscode: unknown hook event " + String(name));
|
|
824
|
+
const ev = { event, agent: "vscode", sessionId: String(p.sessionId ?? ""), cwd: String(p.cwd ?? "") };
|
|
825
|
+
if (event === "SessionStart" && typeof p.source === "string" && SESSION_SOURCES[p.source] !== void 0) ev.source = SESSION_SOURCES[p.source];
|
|
826
|
+
if (event === "UserPromptSubmit" && typeof p.prompt === "string") ev.prompt = p.prompt;
|
|
827
|
+
if (event === "PreToolUse" || event === "PostToolUse") {
|
|
828
|
+
const toolName = String(p.toolName ?? "");
|
|
829
|
+
const canonical = canonicalName4(toolName);
|
|
830
|
+
ev.tool = { name: toolName, canonicalName: canonical, input: policyInput(toolName, canonical, readArgs2(p.toolArgs)) };
|
|
831
|
+
}
|
|
832
|
+
if (event === "PostToolUse") ev.result = readCamelResult(p.toolResult);
|
|
833
|
+
return ev;
|
|
834
|
+
}
|
|
751
835
|
function decode6(raw) {
|
|
752
836
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new Error("vscode: hook payload is not a JSON object");
|
|
753
837
|
const p = raw;
|
|
838
|
+
if (p.hookEventName !== void 0) return decodeCamel(p, p.hookEventName);
|
|
839
|
+
if (p.hook_event_name === void 0) {
|
|
840
|
+
const byKey = EVENT_BY_KEY2.find(([key]) => Object.hasOwn(p, key))?.[1];
|
|
841
|
+
if (byKey === void 0) throw new Error("vscode: missing required field hook_event_name");
|
|
842
|
+
return decodeCamel(p, byKey);
|
|
843
|
+
}
|
|
754
844
|
const event = VSCODE_EVENTS.find((e) => e === p.hook_event_name);
|
|
755
845
|
if (event === void 0) throw new Error("vscode: unknown hook event " + String(p.hook_event_name));
|
|
756
846
|
const ev = { event, agent: "vscode", sessionId: String(p.session_id ?? ""), cwd: String(p.cwd ?? "") };
|
|
@@ -758,8 +848,9 @@ function decode6(raw) {
|
|
|
758
848
|
if (event === "UserPromptSubmit" && typeof p.prompt === "string") ev.prompt = p.prompt;
|
|
759
849
|
if (event === "PreToolUse" || event === "PostToolUse") {
|
|
760
850
|
const name = String(p.tool_name ?? "");
|
|
761
|
-
const input =
|
|
762
|
-
|
|
851
|
+
const input = isRecord2(p.tool_input) ? p.tool_input : {};
|
|
852
|
+
const canonical = canonicalName4(name);
|
|
853
|
+
ev.tool = { name, canonicalName: canonical, input: policyInput(name, canonical, input) };
|
|
763
854
|
}
|
|
764
855
|
if (event === "PostToolUse") ev.result = readResult4(p.tool_response);
|
|
765
856
|
return ev;
|
|
@@ -777,12 +868,14 @@ var KIRO_EVENTS = {
|
|
|
777
868
|
PromptSubmit: "UserPromptSubmit",
|
|
778
869
|
userPromptSubmit: "UserPromptSubmit",
|
|
779
870
|
PreToolUse: "PreToolUse",
|
|
780
|
-
|
|
871
|
+
preToolUse: "PreToolUse",
|
|
872
|
+
PostToolUse: "PostToolUse",
|
|
873
|
+
postToolUse: "PostToolUse"
|
|
781
874
|
};
|
|
782
875
|
var PROMPT_ENV = "USER_PROMPT";
|
|
783
876
|
var MCP_PREFIX3 = "mcp_";
|
|
784
|
-
var
|
|
785
|
-
var NATIVE_TO_CANONICAL5 =
|
|
877
|
+
var SHELL_TOOL_NAMES2 = Object.freeze(["execute_bash", "execute_pwsh", "shell"]);
|
|
878
|
+
var NATIVE_TO_CANONICAL5 = Object.fromEntries(SHELL_TOOL_NAMES2.map((n) => [n, "Bash"]));
|
|
786
879
|
var MCP_SEP3 = "_";
|
|
787
880
|
var KIRO_SOURCES = { startup: "startup", resume: "resume", clear: "clear", compact: "compact" };
|
|
788
881
|
function canonicalName5(name) {
|
|
@@ -923,8 +1016,8 @@ var OPENCODE_EVENTS = {
|
|
|
923
1016
|
compaction: "PreCompact",
|
|
924
1017
|
"step-finish": "Usage"
|
|
925
1018
|
};
|
|
926
|
-
var
|
|
927
|
-
var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [
|
|
1019
|
+
var SHELL_TOOL_NAME = "bash";
|
|
1020
|
+
var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [SHELL_TOOL_NAME]: "Bash" };
|
|
928
1021
|
function toCanonicalTool(name) {
|
|
929
1022
|
if (name.startsWith(OWN_WIRE_PREFIX)) return name.slice(OWN_WIRE_PREFIX.length);
|
|
930
1023
|
return Object.prototype.hasOwnProperty.call(NATIVE_TO_CANONICAL7, name) ? NATIVE_TO_CANONICAL7[name] : name;
|
|
@@ -1044,8 +1137,8 @@ var ADAPTERS = Object.freeze([
|
|
|
1044
1137
|
hookTimeoutMs: HOOK_TIMEOUT_MS,
|
|
1045
1138
|
denyChannel: "deny-reason",
|
|
1046
1139
|
hookChannel: { kind: "package", path: "hooks/qwen.json" },
|
|
1047
|
-
skillChannel: { kind: "
|
|
1048
|
-
// ADR-0020
|
|
1140
|
+
skillChannel: { kind: "package", path: "skills" },
|
|
1141
|
+
// ADR-0020, D-HQ-SKILLS-3: qwen loads <extension>/skills, shared with gemini
|
|
1049
1142
|
decode: decode4,
|
|
1050
1143
|
encode: encode4
|
|
1051
1144
|
},
|
|
@@ -1073,7 +1166,8 @@ var ADAPTERS = Object.freeze([
|
|
|
1073
1166
|
projectSource: "arg:workspaceFolder",
|
|
1074
1167
|
toolNamePrefix: TOOL_NAME_PREFIX6,
|
|
1075
1168
|
// PreCompact sets the pending flag (ADR-0009 §6, DEVIATIONS D-M3-A4-1).
|
|
1076
|
-
nativeTools: { shell: [
|
|
1169
|
+
nativeTools: { shell: [...SHELL_TOOL_NAMES], read: [...READ_TOOL_NAMES], webfetch: [...WEBFETCH_TOOL_NAMES] },
|
|
1170
|
+
// D-HF-VSCODE-PROJECT-1, D-N7-VSCODE-TOOLS-1
|
|
1077
1171
|
execReadOnlyHint: false,
|
|
1078
1172
|
eventMap: { ...CLAUDE_EVENTS, PreCompact: "PreCompact" },
|
|
1079
1173
|
compactDelivery: "pending-flag",
|
|
@@ -1081,8 +1175,8 @@ var ADAPTERS = Object.freeze([
|
|
|
1081
1175
|
hookTimeoutMs: HOOK_TIMEOUT_MS,
|
|
1082
1176
|
denyChannel: "deny-reason",
|
|
1083
1177
|
hookChannel: { kind: "home-file", path: ".copilot/hooks/context-mode-vscode.json" },
|
|
1084
|
-
skillChannel: { kind: "home-dir", path: ".
|
|
1085
|
-
// ADR-0020
|
|
1178
|
+
skillChannel: { kind: "home-dir", path: ".agents/skills" },
|
|
1179
|
+
// ADR-0020, D-HQ-COPILOT-NAMES-3: Copilot CLI owns ~/.copilot/skills
|
|
1086
1180
|
decode: decode6,
|
|
1087
1181
|
encode: encode6
|
|
1088
1182
|
},
|
|
@@ -1091,9 +1185,9 @@ var ADAPTERS = Object.freeze([
|
|
|
1091
1185
|
installMode: "mcp-entry",
|
|
1092
1186
|
projectSource: "arg:--agent+cwd",
|
|
1093
1187
|
toolNamePrefix: TOOL_NAME_PREFIX7,
|
|
1094
|
-
nativeTools: { shell: [
|
|
1188
|
+
nativeTools: { shell: [...SHELL_TOOL_NAMES2] },
|
|
1095
1189
|
execReadOnlyHint: false,
|
|
1096
|
-
// D-HF-KIRO-SHELL-1
|
|
1190
|
+
// D-HF-KIRO-SHELL-1, D-N7-KIRO-1
|
|
1097
1191
|
eventMap: { SessionStart: "SessionStart", UserPromptSubmit: "UserPromptSubmit", PreToolUse: "PreToolUse", PostToolUse: "PostToolUse" },
|
|
1098
1192
|
compactDelivery: "none",
|
|
1099
1193
|
compactSummary: "none",
|
|
@@ -1106,7 +1200,7 @@ var ADAPTERS = Object.freeze([
|
|
|
1106
1200
|
encode: encode7
|
|
1107
1201
|
},
|
|
1108
1202
|
{
|
|
1109
|
-
// toolNamePrefix
|
|
1203
|
+
// toolNamePrefix is the documented ZCode name mcp__<server>__<tool> (D-N7-ZCODE-NAMES-1); nativeTools are Claude names.
|
|
1110
1204
|
id: "zcode",
|
|
1111
1205
|
installMode: "hooks+mcp",
|
|
1112
1206
|
projectSource: "spawn-cwd",
|
|
@@ -1148,7 +1242,7 @@ var ADAPTERS = Object.freeze([
|
|
|
1148
1242
|
installMode: "in-process",
|
|
1149
1243
|
projectSource: "spawn-cwd",
|
|
1150
1244
|
toolNamePrefix: TOOL_NAME_PREFIX10,
|
|
1151
|
-
nativeTools: { shell: [
|
|
1245
|
+
nativeTools: { shell: [SHELL_TOOL_NAME] },
|
|
1152
1246
|
execReadOnlyHint: false,
|
|
1153
1247
|
// D-HF-OPENCODE-SHELL-1
|
|
1154
1248
|
// Usage: step-finish cost row (DEVIATIONS D-M5-arch-2).
|
|
@@ -1186,6 +1280,8 @@ var ERROR_TEXT = Object.freeze({
|
|
|
1186
1280
|
NO_PROJECT: "Project source <kind> is missing. Fix: run ctx_doctor.",
|
|
1187
1281
|
UNKNOWN_FIELD: 'Unknown field "<f>". Fix: use "queries".',
|
|
1188
1282
|
TIMEOUT: "Timed out after <ms> ms. Fix: pass background: true.",
|
|
1283
|
+
NO_GIT_BASH: "Git Bash not found. Fix: install Git for Windows.",
|
|
1284
|
+
// D-VT-WINBASH-1
|
|
1189
1285
|
NO_RUNTIME: "No <lang> runtime on PATH. Fix: install it or pick another language.",
|
|
1190
1286
|
FETCH_FAILED: "Fetch failed: <code>. Fix: check the URL or proxy.",
|
|
1191
1287
|
SSRF: "Blocked private address <host>. Fix: use a public URL.",
|
|
@@ -4190,22 +4286,25 @@ function parseShell(cmd) {
|
|
|
4190
4286
|
import { join as join2 } from "node:path";
|
|
4191
4287
|
|
|
4192
4288
|
// src/core/project/config-dir.ts
|
|
4193
|
-
import { join } from "node:path";
|
|
4289
|
+
import { join, posix, win32 } from "node:path";
|
|
4194
4290
|
var { mkdirSync: mkdirSync2, realpathSync } = process.getBuiltinModule("node:fs");
|
|
4195
|
-
function homeDirOf(env) {
|
|
4196
|
-
const
|
|
4197
|
-
if (
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
}
|
|
4202
|
-
|
|
4203
|
-
|
|
4291
|
+
function homeDirOf(env, platform = process.platform) {
|
|
4292
|
+
const set = (v) => v !== void 0 && v !== "";
|
|
4293
|
+
if (platform === "win32") {
|
|
4294
|
+
if (set(env.USERPROFILE)) return env.USERPROFILE;
|
|
4295
|
+
if (set(env.HOMEDRIVE) && set(env.HOMEPATH)) return env.HOMEDRIVE + env.HOMEPATH;
|
|
4296
|
+
return set(env.HOME) ? env.HOME : null;
|
|
4297
|
+
}
|
|
4298
|
+
if (set(env.HOME)) return env.HOME;
|
|
4299
|
+
return set(env.USERPROFILE) ? env.USERPROFILE : null;
|
|
4300
|
+
}
|
|
4301
|
+
function requireHomeDir(env, platform = process.platform) {
|
|
4302
|
+
const home = homeDirOf(env, platform);
|
|
4204
4303
|
if (home !== null) return home;
|
|
4205
|
-
throw new CtxError("NO_HOME", { name:
|
|
4304
|
+
throw new CtxError("NO_HOME", { name: platform === "win32" ? "USERPROFILE" : "HOME" });
|
|
4206
4305
|
}
|
|
4207
4306
|
function resolveConfigDir(env) {
|
|
4208
|
-
const dir = join(
|
|
4307
|
+
const dir = join(requireHomeDir(env), DATA_ROOT.slice(1));
|
|
4209
4308
|
mkdirSync2(dir, { recursive: true });
|
|
4210
4309
|
return realpathSync.native(dir);
|
|
4211
4310
|
}
|
|
@@ -4947,7 +5046,7 @@ function firstLine(file) {
|
|
|
4947
5046
|
}
|
|
4948
5047
|
function git(dir, args) {
|
|
4949
5048
|
const { spawnSync } = process.getBuiltinModule("node:child_process");
|
|
4950
|
-
const r = spawnSync("git", args, { cwd: dir, shell: false, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
5049
|
+
const r = spawnSync("git", args, { cwd: dir, shell: false, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
|
|
4951
5050
|
if (r.error !== void 0 || r.status !== 0) throw new CtxError("NO_GIT_DIR", { path: dir });
|
|
4952
5051
|
return r.stdout.split("\n").filter((l) => l !== "");
|
|
4953
5052
|
}
|
|
@@ -5022,6 +5121,14 @@ function buildChildEnv(parent, extra) {
|
|
|
5022
5121
|
// src/core/sandbox/runtimes.ts
|
|
5023
5122
|
import { accessSync, constants as fsConstants, statSync as statSync3 } from "node:fs";
|
|
5024
5123
|
import path from "node:path";
|
|
5124
|
+
|
|
5125
|
+
// src/core/sandbox/path-entries.ts
|
|
5126
|
+
function pathEntries(value, platform = process.platform, delimiter = platform === "win32" ? ";" : ":") {
|
|
5127
|
+
const win = platform === "win32";
|
|
5128
|
+
return value.split(delimiter).map((e) => win && e.length >= 2 && e.startsWith('"') && e.endsWith('"') ? e.slice(1, -1) : e).filter(Boolean);
|
|
5129
|
+
}
|
|
5130
|
+
|
|
5131
|
+
// src/core/sandbox/runtimes.ts
|
|
5025
5132
|
var PATHEXT_SEPARATOR = ";";
|
|
5026
5133
|
var WIN_STARTABLE_EXT = Object.freeze([".exe", ".com"]);
|
|
5027
5134
|
function isWin() {
|
|
@@ -5031,7 +5138,7 @@ function candidates(lang) {
|
|
|
5031
5138
|
const win = isWin();
|
|
5032
5139
|
switch (lang) {
|
|
5033
5140
|
case "shell":
|
|
5034
|
-
return win ? [
|
|
5141
|
+
return win ? [] : ["sh"];
|
|
5035
5142
|
case "powershell":
|
|
5036
5143
|
return ["pwsh", "pwsh.exe", "powershell.exe"];
|
|
5037
5144
|
case "javascript":
|
|
@@ -5062,7 +5169,8 @@ function isRunnable(full) {
|
|
|
5062
5169
|
}
|
|
5063
5170
|
}
|
|
5064
5171
|
function findRuntime(lang, env = process.env) {
|
|
5065
|
-
|
|
5172
|
+
if (isWin() && WIN_SHELL_LANGS.includes(lang)) return findGitBash(env);
|
|
5173
|
+
const dirs = pathEntries(env.PATH ?? "", process.platform, path.delimiter);
|
|
5066
5174
|
const pathExt = isWin() ? (env.PATHEXT ?? PATHEXT_DEFAULT).split(PATHEXT_SEPARATOR).filter((e) => e !== "") : [];
|
|
5067
5175
|
const names = candidates(lang);
|
|
5068
5176
|
let shim = null;
|
|
@@ -5078,6 +5186,18 @@ function findRuntime(lang, env = process.env) {
|
|
|
5078
5186
|
}
|
|
5079
5187
|
return shim;
|
|
5080
5188
|
}
|
|
5189
|
+
function findGitBash(env) {
|
|
5190
|
+
const git2 = findRuntime(GIT_BIN, env);
|
|
5191
|
+
if (git2 === null) return null;
|
|
5192
|
+
for (const rel of GIT_BASH_RELATIVE) {
|
|
5193
|
+
const full = path.resolve(path.dirname(git2), ...rel);
|
|
5194
|
+
if (isRunnable(full)) return full;
|
|
5195
|
+
}
|
|
5196
|
+
return null;
|
|
5197
|
+
}
|
|
5198
|
+
function noRuntimeError(lang) {
|
|
5199
|
+
return isWin() && WIN_SHELL_LANGS.includes(lang) ? new CtxError("NO_GIT_BASH") : new CtxError("NO_RUNTIME", { lang });
|
|
5200
|
+
}
|
|
5081
5201
|
|
|
5082
5202
|
// src/core/sandbox/spawn.ts
|
|
5083
5203
|
import { spawn } from "node:child_process";
|
|
@@ -5584,7 +5704,7 @@ async function runWrapperMain(argv, env) {
|
|
|
5584
5704
|
if (d.kind === "deny" && userPolicyDeny(d.reason)) return exit(RUN_FAIL_EXIT, "", d.reason + "\n");
|
|
5585
5705
|
try {
|
|
5586
5706
|
const runtime = findRuntime(SHELL);
|
|
5587
|
-
if (runtime === null) throw
|
|
5707
|
+
if (runtime === null) throw noRuntimeError(SHELL);
|
|
5588
5708
|
const project = projectOf(argv, cwd);
|
|
5589
5709
|
const r = await runProcess([runtime, "-c", command], {
|
|
5590
5710
|
cwd,
|