context-mode 2.0.0-next.7 → 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 +14 -14
- package/cli.mjs +2988 -684
- package/copilot/plugin.json +1 -1
- package/gemini-extension.json +1 -1
- package/hook.mjs +84 -82
- package/opencode/plugin.js +3031 -818
- package/package.json +1 -1
- package/pi/index.js +2982 -769
- package/qwen-extension.json +1 -1
- package/run.mjs +96 -33
- package/search.mjs +96 -33
- package/server.mjs +2946 -732
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",
|
|
@@ -360,7 +368,7 @@ var CODEX_APPROVAL_MODE_FIELD = "default_tools_approval_mode";
|
|
|
360
368
|
var CODEX_APPROVAL_APPROVE = "approve";
|
|
361
369
|
var OWN_MCP_ENTRY = Object.freeze({
|
|
362
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 } },
|
|
363
|
-
vscode: { file: [
|
|
371
|
+
vscode: { file: [VSCODE_MCP_FILE], key: ["servers", SERVER_KEY] },
|
|
364
372
|
kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
|
|
365
373
|
zcode: {
|
|
366
374
|
file: [".zcode", "cli", "config.json"],
|
|
@@ -734,8 +742,14 @@ var VSCODE_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostTool
|
|
|
734
742
|
var MCP_PREFIX2 = "mcp_";
|
|
735
743
|
var MCP_SEP2 = "_";
|
|
736
744
|
var SESSION_START_NEW = "new";
|
|
737
|
-
var
|
|
738
|
-
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
|
+
]);
|
|
739
753
|
function canonicalName4(name) {
|
|
740
754
|
if (name.startsWith(TOOL_NAME_PREFIX6)) return name.slice(TOOL_NAME_PREFIX6.length);
|
|
741
755
|
if (Object.hasOwn(NATIVE_TO_CANONICAL4, name)) return NATIVE_TO_CANONICAL4[name];
|
|
@@ -745,6 +759,26 @@ function canonicalName4(name) {
|
|
|
745
759
|
if (sep3 <= 0 || sep3 === rest.length - 1) return name;
|
|
746
760
|
return "mcp:" + rest.slice(0, sep3) + ":" + rest.slice(sep3 + MCP_SEP2.length);
|
|
747
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
|
+
}
|
|
748
782
|
function readResult4(resp) {
|
|
749
783
|
const text = resp === void 0 ? "" : typeof resp === "string" ? resp : JSON.stringify(resp);
|
|
750
784
|
const isError = typeof resp === "object" && resp !== null && resp.is_error === true;
|
|
@@ -792,7 +826,8 @@ function decodeCamel(p, name) {
|
|
|
792
826
|
if (event === "UserPromptSubmit" && typeof p.prompt === "string") ev.prompt = p.prompt;
|
|
793
827
|
if (event === "PreToolUse" || event === "PostToolUse") {
|
|
794
828
|
const toolName = String(p.toolName ?? "");
|
|
795
|
-
|
|
829
|
+
const canonical = canonicalName4(toolName);
|
|
830
|
+
ev.tool = { name: toolName, canonicalName: canonical, input: policyInput(toolName, canonical, readArgs2(p.toolArgs)) };
|
|
796
831
|
}
|
|
797
832
|
if (event === "PostToolUse") ev.result = readCamelResult(p.toolResult);
|
|
798
833
|
return ev;
|
|
@@ -814,7 +849,8 @@ function decode6(raw) {
|
|
|
814
849
|
if (event === "PreToolUse" || event === "PostToolUse") {
|
|
815
850
|
const name = String(p.tool_name ?? "");
|
|
816
851
|
const input = isRecord2(p.tool_input) ? p.tool_input : {};
|
|
817
|
-
|
|
852
|
+
const canonical = canonicalName4(name);
|
|
853
|
+
ev.tool = { name, canonicalName: canonical, input: policyInput(name, canonical, input) };
|
|
818
854
|
}
|
|
819
855
|
if (event === "PostToolUse") ev.result = readResult4(p.tool_response);
|
|
820
856
|
return ev;
|
|
@@ -838,8 +874,8 @@ var KIRO_EVENTS = {
|
|
|
838
874
|
};
|
|
839
875
|
var PROMPT_ENV = "USER_PROMPT";
|
|
840
876
|
var MCP_PREFIX3 = "mcp_";
|
|
841
|
-
var
|
|
842
|
-
var NATIVE_TO_CANONICAL5 = Object.fromEntries(
|
|
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"]));
|
|
843
879
|
var MCP_SEP3 = "_";
|
|
844
880
|
var KIRO_SOURCES = { startup: "startup", resume: "resume", clear: "clear", compact: "compact" };
|
|
845
881
|
function canonicalName5(name) {
|
|
@@ -980,8 +1016,8 @@ var OPENCODE_EVENTS = {
|
|
|
980
1016
|
compaction: "PreCompact",
|
|
981
1017
|
"step-finish": "Usage"
|
|
982
1018
|
};
|
|
983
|
-
var
|
|
984
|
-
var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [
|
|
1019
|
+
var SHELL_TOOL_NAME = "bash";
|
|
1020
|
+
var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [SHELL_TOOL_NAME]: "Bash" };
|
|
985
1021
|
function toCanonicalTool(name) {
|
|
986
1022
|
if (name.startsWith(OWN_WIRE_PREFIX)) return name.slice(OWN_WIRE_PREFIX.length);
|
|
987
1023
|
return Object.prototype.hasOwnProperty.call(NATIVE_TO_CANONICAL7, name) ? NATIVE_TO_CANONICAL7[name] : name;
|
|
@@ -1130,7 +1166,8 @@ var ADAPTERS = Object.freeze([
|
|
|
1130
1166
|
projectSource: "arg:workspaceFolder",
|
|
1131
1167
|
toolNamePrefix: TOOL_NAME_PREFIX6,
|
|
1132
1168
|
// PreCompact sets the pending flag (ADR-0009 §6, DEVIATIONS D-M3-A4-1).
|
|
1133
|
-
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
|
|
1134
1171
|
execReadOnlyHint: false,
|
|
1135
1172
|
eventMap: { ...CLAUDE_EVENTS, PreCompact: "PreCompact" },
|
|
1136
1173
|
compactDelivery: "pending-flag",
|
|
@@ -1148,7 +1185,7 @@ var ADAPTERS = Object.freeze([
|
|
|
1148
1185
|
installMode: "mcp-entry",
|
|
1149
1186
|
projectSource: "arg:--agent+cwd",
|
|
1150
1187
|
toolNamePrefix: TOOL_NAME_PREFIX7,
|
|
1151
|
-
nativeTools: { shell: [...
|
|
1188
|
+
nativeTools: { shell: [...SHELL_TOOL_NAMES2] },
|
|
1152
1189
|
execReadOnlyHint: false,
|
|
1153
1190
|
// D-HF-KIRO-SHELL-1, D-N7-KIRO-1
|
|
1154
1191
|
eventMap: { SessionStart: "SessionStart", UserPromptSubmit: "UserPromptSubmit", PreToolUse: "PreToolUse", PostToolUse: "PostToolUse" },
|
|
@@ -1205,7 +1242,7 @@ var ADAPTERS = Object.freeze([
|
|
|
1205
1242
|
installMode: "in-process",
|
|
1206
1243
|
projectSource: "spawn-cwd",
|
|
1207
1244
|
toolNamePrefix: TOOL_NAME_PREFIX10,
|
|
1208
|
-
nativeTools: { shell: [
|
|
1245
|
+
nativeTools: { shell: [SHELL_TOOL_NAME] },
|
|
1209
1246
|
execReadOnlyHint: false,
|
|
1210
1247
|
// D-HF-OPENCODE-SHELL-1
|
|
1211
1248
|
// Usage: step-finish cost row (DEVIATIONS D-M5-arch-2).
|
|
@@ -1243,6 +1280,8 @@ var ERROR_TEXT = Object.freeze({
|
|
|
1243
1280
|
NO_PROJECT: "Project source <kind> is missing. Fix: run ctx_doctor.",
|
|
1244
1281
|
UNKNOWN_FIELD: 'Unknown field "<f>". Fix: use "queries".',
|
|
1245
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
|
|
1246
1285
|
NO_RUNTIME: "No <lang> runtime on PATH. Fix: install it or pick another language.",
|
|
1247
1286
|
FETCH_FAILED: "Fetch failed: <code>. Fix: check the URL or proxy.",
|
|
1248
1287
|
SSRF: "Blocked private address <host>. Fix: use a public URL.",
|
|
@@ -4247,22 +4286,25 @@ function parseShell(cmd) {
|
|
|
4247
4286
|
import { join as join2 } from "node:path";
|
|
4248
4287
|
|
|
4249
4288
|
// src/core/project/config-dir.ts
|
|
4250
|
-
import { join } from "node:path";
|
|
4289
|
+
import { join, posix, win32 } from "node:path";
|
|
4251
4290
|
var { mkdirSync: mkdirSync2, realpathSync } = process.getBuiltinModule("node:fs");
|
|
4252
|
-
function homeDirOf(env) {
|
|
4253
|
-
const
|
|
4254
|
-
if (
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
}
|
|
4259
|
-
|
|
4260
|
-
|
|
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);
|
|
4261
4303
|
if (home !== null) return home;
|
|
4262
|
-
throw new CtxError("NO_HOME", { name:
|
|
4304
|
+
throw new CtxError("NO_HOME", { name: platform === "win32" ? "USERPROFILE" : "HOME" });
|
|
4263
4305
|
}
|
|
4264
4306
|
function resolveConfigDir(env) {
|
|
4265
|
-
const dir = join(
|
|
4307
|
+
const dir = join(requireHomeDir(env), DATA_ROOT.slice(1));
|
|
4266
4308
|
mkdirSync2(dir, { recursive: true });
|
|
4267
4309
|
return realpathSync.native(dir);
|
|
4268
4310
|
}
|
|
@@ -5004,7 +5046,7 @@ function firstLine(file) {
|
|
|
5004
5046
|
}
|
|
5005
5047
|
function git(dir, args) {
|
|
5006
5048
|
const { spawnSync } = process.getBuiltinModule("node:child_process");
|
|
5007
|
-
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 });
|
|
5008
5050
|
if (r.error !== void 0 || r.status !== 0) throw new CtxError("NO_GIT_DIR", { path: dir });
|
|
5009
5051
|
return r.stdout.split("\n").filter((l) => l !== "");
|
|
5010
5052
|
}
|
|
@@ -5079,6 +5121,14 @@ function buildChildEnv(parent, extra) {
|
|
|
5079
5121
|
// src/core/sandbox/runtimes.ts
|
|
5080
5122
|
import { accessSync, constants as fsConstants, statSync as statSync3 } from "node:fs";
|
|
5081
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
|
|
5082
5132
|
var PATHEXT_SEPARATOR = ";";
|
|
5083
5133
|
var WIN_STARTABLE_EXT = Object.freeze([".exe", ".com"]);
|
|
5084
5134
|
function isWin() {
|
|
@@ -5088,7 +5138,7 @@ function candidates(lang) {
|
|
|
5088
5138
|
const win = isWin();
|
|
5089
5139
|
switch (lang) {
|
|
5090
5140
|
case "shell":
|
|
5091
|
-
return win ? [
|
|
5141
|
+
return win ? [] : ["sh"];
|
|
5092
5142
|
case "powershell":
|
|
5093
5143
|
return ["pwsh", "pwsh.exe", "powershell.exe"];
|
|
5094
5144
|
case "javascript":
|
|
@@ -5119,7 +5169,8 @@ function isRunnable(full) {
|
|
|
5119
5169
|
}
|
|
5120
5170
|
}
|
|
5121
5171
|
function findRuntime(lang, env = process.env) {
|
|
5122
|
-
|
|
5172
|
+
if (isWin() && WIN_SHELL_LANGS.includes(lang)) return findGitBash(env);
|
|
5173
|
+
const dirs = pathEntries(env.PATH ?? "", process.platform, path.delimiter);
|
|
5123
5174
|
const pathExt = isWin() ? (env.PATHEXT ?? PATHEXT_DEFAULT).split(PATHEXT_SEPARATOR).filter((e) => e !== "") : [];
|
|
5124
5175
|
const names = candidates(lang);
|
|
5125
5176
|
let shim = null;
|
|
@@ -5135,6 +5186,18 @@ function findRuntime(lang, env = process.env) {
|
|
|
5135
5186
|
}
|
|
5136
5187
|
return shim;
|
|
5137
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
|
+
}
|
|
5138
5201
|
|
|
5139
5202
|
// src/core/sandbox/spawn.ts
|
|
5140
5203
|
import { spawn } from "node:child_process";
|
|
@@ -5641,7 +5704,7 @@ async function runWrapperMain(argv, env) {
|
|
|
5641
5704
|
if (d.kind === "deny" && userPolicyDeny(d.reason)) return exit(RUN_FAIL_EXIT, "", d.reason + "\n");
|
|
5642
5705
|
try {
|
|
5643
5706
|
const runtime = findRuntime(SHELL);
|
|
5644
|
-
if (runtime === null) throw
|
|
5707
|
+
if (runtime === null) throw noRuntimeError(SHELL);
|
|
5645
5708
|
const project = projectOf(argv, cwd);
|
|
5646
5709
|
const r = await runProcess([runtime, "-c", command], {
|
|
5647
5710
|
cwd,
|
package/search.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",
|
|
@@ -360,7 +368,7 @@ var CODEX_APPROVAL_MODE_FIELD = "default_tools_approval_mode";
|
|
|
360
368
|
var CODEX_APPROVAL_APPROVE = "approve";
|
|
361
369
|
var OWN_MCP_ENTRY = Object.freeze({
|
|
362
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 } },
|
|
363
|
-
vscode: { file: [
|
|
371
|
+
vscode: { file: [VSCODE_MCP_FILE], key: ["servers", SERVER_KEY] },
|
|
364
372
|
kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
|
|
365
373
|
zcode: {
|
|
366
374
|
file: [".zcode", "cli", "config.json"],
|
|
@@ -734,8 +742,14 @@ var VSCODE_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostTool
|
|
|
734
742
|
var MCP_PREFIX2 = "mcp_";
|
|
735
743
|
var MCP_SEP2 = "_";
|
|
736
744
|
var SESSION_START_NEW = "new";
|
|
737
|
-
var
|
|
738
|
-
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
|
+
]);
|
|
739
753
|
function canonicalName4(name) {
|
|
740
754
|
if (name.startsWith(TOOL_NAME_PREFIX6)) return name.slice(TOOL_NAME_PREFIX6.length);
|
|
741
755
|
if (Object.hasOwn(NATIVE_TO_CANONICAL4, name)) return NATIVE_TO_CANONICAL4[name];
|
|
@@ -745,6 +759,26 @@ function canonicalName4(name) {
|
|
|
745
759
|
if (sep3 <= 0 || sep3 === rest.length - 1) return name;
|
|
746
760
|
return "mcp:" + rest.slice(0, sep3) + ":" + rest.slice(sep3 + MCP_SEP2.length);
|
|
747
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
|
+
}
|
|
748
782
|
function readResult4(resp) {
|
|
749
783
|
const text = resp === void 0 ? "" : typeof resp === "string" ? resp : JSON.stringify(resp);
|
|
750
784
|
const isError = typeof resp === "object" && resp !== null && resp.is_error === true;
|
|
@@ -792,7 +826,8 @@ function decodeCamel(p, name) {
|
|
|
792
826
|
if (event === "UserPromptSubmit" && typeof p.prompt === "string") ev.prompt = p.prompt;
|
|
793
827
|
if (event === "PreToolUse" || event === "PostToolUse") {
|
|
794
828
|
const toolName = String(p.toolName ?? "");
|
|
795
|
-
|
|
829
|
+
const canonical = canonicalName4(toolName);
|
|
830
|
+
ev.tool = { name: toolName, canonicalName: canonical, input: policyInput(toolName, canonical, readArgs2(p.toolArgs)) };
|
|
796
831
|
}
|
|
797
832
|
if (event === "PostToolUse") ev.result = readCamelResult(p.toolResult);
|
|
798
833
|
return ev;
|
|
@@ -814,7 +849,8 @@ function decode6(raw) {
|
|
|
814
849
|
if (event === "PreToolUse" || event === "PostToolUse") {
|
|
815
850
|
const name = String(p.tool_name ?? "");
|
|
816
851
|
const input = isRecord2(p.tool_input) ? p.tool_input : {};
|
|
817
|
-
|
|
852
|
+
const canonical = canonicalName4(name);
|
|
853
|
+
ev.tool = { name, canonicalName: canonical, input: policyInput(name, canonical, input) };
|
|
818
854
|
}
|
|
819
855
|
if (event === "PostToolUse") ev.result = readResult4(p.tool_response);
|
|
820
856
|
return ev;
|
|
@@ -838,8 +874,8 @@ var KIRO_EVENTS = {
|
|
|
838
874
|
};
|
|
839
875
|
var PROMPT_ENV = "USER_PROMPT";
|
|
840
876
|
var MCP_PREFIX3 = "mcp_";
|
|
841
|
-
var
|
|
842
|
-
var NATIVE_TO_CANONICAL5 = Object.fromEntries(
|
|
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"]));
|
|
843
879
|
var MCP_SEP3 = "_";
|
|
844
880
|
var KIRO_SOURCES = { startup: "startup", resume: "resume", clear: "clear", compact: "compact" };
|
|
845
881
|
function canonicalName5(name) {
|
|
@@ -980,8 +1016,8 @@ var OPENCODE_EVENTS = {
|
|
|
980
1016
|
compaction: "PreCompact",
|
|
981
1017
|
"step-finish": "Usage"
|
|
982
1018
|
};
|
|
983
|
-
var
|
|
984
|
-
var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [
|
|
1019
|
+
var SHELL_TOOL_NAME = "bash";
|
|
1020
|
+
var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [SHELL_TOOL_NAME]: "Bash" };
|
|
985
1021
|
function toCanonicalTool(name) {
|
|
986
1022
|
if (name.startsWith(OWN_WIRE_PREFIX)) return name.slice(OWN_WIRE_PREFIX.length);
|
|
987
1023
|
return Object.prototype.hasOwnProperty.call(NATIVE_TO_CANONICAL7, name) ? NATIVE_TO_CANONICAL7[name] : name;
|
|
@@ -1130,7 +1166,8 @@ var ADAPTERS = Object.freeze([
|
|
|
1130
1166
|
projectSource: "arg:workspaceFolder",
|
|
1131
1167
|
toolNamePrefix: TOOL_NAME_PREFIX6,
|
|
1132
1168
|
// PreCompact sets the pending flag (ADR-0009 §6, DEVIATIONS D-M3-A4-1).
|
|
1133
|
-
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
|
|
1134
1171
|
execReadOnlyHint: false,
|
|
1135
1172
|
eventMap: { ...CLAUDE_EVENTS, PreCompact: "PreCompact" },
|
|
1136
1173
|
compactDelivery: "pending-flag",
|
|
@@ -1148,7 +1185,7 @@ var ADAPTERS = Object.freeze([
|
|
|
1148
1185
|
installMode: "mcp-entry",
|
|
1149
1186
|
projectSource: "arg:--agent+cwd",
|
|
1150
1187
|
toolNamePrefix: TOOL_NAME_PREFIX7,
|
|
1151
|
-
nativeTools: { shell: [...
|
|
1188
|
+
nativeTools: { shell: [...SHELL_TOOL_NAMES2] },
|
|
1152
1189
|
execReadOnlyHint: false,
|
|
1153
1190
|
// D-HF-KIRO-SHELL-1, D-N7-KIRO-1
|
|
1154
1191
|
eventMap: { SessionStart: "SessionStart", UserPromptSubmit: "UserPromptSubmit", PreToolUse: "PreToolUse", PostToolUse: "PostToolUse" },
|
|
@@ -1205,7 +1242,7 @@ var ADAPTERS = Object.freeze([
|
|
|
1205
1242
|
installMode: "in-process",
|
|
1206
1243
|
projectSource: "spawn-cwd",
|
|
1207
1244
|
toolNamePrefix: TOOL_NAME_PREFIX10,
|
|
1208
|
-
nativeTools: { shell: [
|
|
1245
|
+
nativeTools: { shell: [SHELL_TOOL_NAME] },
|
|
1209
1246
|
execReadOnlyHint: false,
|
|
1210
1247
|
// D-HF-OPENCODE-SHELL-1
|
|
1211
1248
|
// Usage: step-finish cost row (DEVIATIONS D-M5-arch-2).
|
|
@@ -1243,6 +1280,8 @@ var ERROR_TEXT = Object.freeze({
|
|
|
1243
1280
|
NO_PROJECT: "Project source <kind> is missing. Fix: run ctx_doctor.",
|
|
1244
1281
|
UNKNOWN_FIELD: 'Unknown field "<f>". Fix: use "queries".',
|
|
1245
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
|
|
1246
1285
|
NO_RUNTIME: "No <lang> runtime on PATH. Fix: install it or pick another language.",
|
|
1247
1286
|
FETCH_FAILED: "Fetch failed: <code>. Fix: check the URL or proxy.",
|
|
1248
1287
|
SSRF: "Blocked private address <host>. Fix: use a public URL.",
|
|
@@ -4247,22 +4286,25 @@ function parseShell(cmd) {
|
|
|
4247
4286
|
import { join as join2 } from "node:path";
|
|
4248
4287
|
|
|
4249
4288
|
// src/core/project/config-dir.ts
|
|
4250
|
-
import { join } from "node:path";
|
|
4289
|
+
import { join, posix, win32 } from "node:path";
|
|
4251
4290
|
var { mkdirSync: mkdirSync2, realpathSync } = process.getBuiltinModule("node:fs");
|
|
4252
|
-
function homeDirOf(env) {
|
|
4253
|
-
const
|
|
4254
|
-
if (
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
}
|
|
4259
|
-
|
|
4260
|
-
|
|
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);
|
|
4261
4303
|
if (home !== null) return home;
|
|
4262
|
-
throw new CtxError("NO_HOME", { name:
|
|
4304
|
+
throw new CtxError("NO_HOME", { name: platform === "win32" ? "USERPROFILE" : "HOME" });
|
|
4263
4305
|
}
|
|
4264
4306
|
function resolveConfigDir(env) {
|
|
4265
|
-
const dir = join(
|
|
4307
|
+
const dir = join(requireHomeDir(env), DATA_ROOT.slice(1));
|
|
4266
4308
|
mkdirSync2(dir, { recursive: true });
|
|
4267
4309
|
return realpathSync.native(dir);
|
|
4268
4310
|
}
|
|
@@ -5004,7 +5046,7 @@ function firstLine(file) {
|
|
|
5004
5046
|
}
|
|
5005
5047
|
function git(dir, args) {
|
|
5006
5048
|
const { spawnSync } = process.getBuiltinModule("node:child_process");
|
|
5007
|
-
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 });
|
|
5008
5050
|
if (r.error !== void 0 || r.status !== 0) throw new CtxError("NO_GIT_DIR", { path: dir });
|
|
5009
5051
|
return r.stdout.split("\n").filter((l) => l !== "");
|
|
5010
5052
|
}
|
|
@@ -5079,6 +5121,14 @@ function buildChildEnv(parent, extra) {
|
|
|
5079
5121
|
// src/core/sandbox/runtimes.ts
|
|
5080
5122
|
import { accessSync, constants as fsConstants, statSync as statSync3 } from "node:fs";
|
|
5081
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
|
|
5082
5132
|
var PATHEXT_SEPARATOR = ";";
|
|
5083
5133
|
var WIN_STARTABLE_EXT = Object.freeze([".exe", ".com"]);
|
|
5084
5134
|
function isWin() {
|
|
@@ -5088,7 +5138,7 @@ function candidates(lang) {
|
|
|
5088
5138
|
const win = isWin();
|
|
5089
5139
|
switch (lang) {
|
|
5090
5140
|
case "shell":
|
|
5091
|
-
return win ? [
|
|
5141
|
+
return win ? [] : ["sh"];
|
|
5092
5142
|
case "powershell":
|
|
5093
5143
|
return ["pwsh", "pwsh.exe", "powershell.exe"];
|
|
5094
5144
|
case "javascript":
|
|
@@ -5119,7 +5169,8 @@ function isRunnable(full) {
|
|
|
5119
5169
|
}
|
|
5120
5170
|
}
|
|
5121
5171
|
function findRuntime(lang, env = process.env) {
|
|
5122
|
-
|
|
5172
|
+
if (isWin() && WIN_SHELL_LANGS.includes(lang)) return findGitBash(env);
|
|
5173
|
+
const dirs = pathEntries(env.PATH ?? "", process.platform, path.delimiter);
|
|
5123
5174
|
const pathExt = isWin() ? (env.PATHEXT ?? PATHEXT_DEFAULT).split(PATHEXT_SEPARATOR).filter((e) => e !== "") : [];
|
|
5124
5175
|
const names = candidates(lang);
|
|
5125
5176
|
let shim = null;
|
|
@@ -5135,6 +5186,18 @@ function findRuntime(lang, env = process.env) {
|
|
|
5135
5186
|
}
|
|
5136
5187
|
return shim;
|
|
5137
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
|
+
}
|
|
5138
5201
|
|
|
5139
5202
|
// src/core/sandbox/spawn.ts
|
|
5140
5203
|
import { spawn } from "node:child_process";
|
|
@@ -5641,7 +5704,7 @@ async function runWrapperMain(argv, env) {
|
|
|
5641
5704
|
if (d.kind === "deny" && userPolicyDeny(d.reason)) return exit(RUN_FAIL_EXIT, "", d.reason + "\n");
|
|
5642
5705
|
try {
|
|
5643
5706
|
const runtime = findRuntime(SHELL);
|
|
5644
|
-
if (runtime === null) throw
|
|
5707
|
+
if (runtime === null) throw noRuntimeError(SHELL);
|
|
5645
5708
|
const project = projectOf(argv, cwd);
|
|
5646
5709
|
const r = await runProcess([runtime, "-c", command], {
|
|
5647
5710
|
cwd,
|