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.
@@ -330,8 +330,8 @@ var DECISION_OPTION_KEY = "option";
330
330
  var DECISION_LABEL_JOIN = " | ";
331
331
  var RELEASE_REPO_URL = "https://github.com/mksglu/context-mode.git";
332
332
  var RELEASE_BRANCH = "release";
333
- var BUNDLE_SHA = true ? "f61b6973877b47851ac5938c46fee1399946289e" : void 0;
334
- var DOCTOR_CHECK_ORDER = Object.freeze(["D1", "D2", "D3", "D4", "D5", "D5b", "D6", "D7", "D8", "D9", "D10"]);
333
+ var BUNDLE_SHA = true ? "4fb62aa646f6f53db6e655a59f4397d5ef78c0a4" : void 0;
334
+ var DOCTOR_CHECK_ORDER = Object.freeze(["D1", "D2", "D3", "D4", "D5", "D5b", "D6", "D7", "D8", "D9", "D10", "D11"]);
335
335
  var DOCTOR_LABEL = Object.freeze({
336
336
  D1: "version",
337
337
  D2: "node",
@@ -343,7 +343,8 @@ var DOCTOR_LABEL = Object.freeze({
343
343
  D7: "project and worktree",
344
344
  D8: "context.db",
345
345
  D9: "index",
346
- D10: "enforcement mode"
346
+ D10: "enforcement mode",
347
+ D11: "shell"
347
348
  });
348
349
  var HOOK_FIXTURE_DIR = "fixtures";
349
350
  var HOOK_FIXTURE_FILE = "hook-roundtrip.json";
@@ -449,6 +450,8 @@ var GIT_NO_PROMPT_ENV = Object.freeze({ GIT_TERMINAL_PROMPT: "0" });
449
450
  var GIT_NO_CRLF_ENV = Object.freeze({ GIT_CONFIG_COUNT: "1", GIT_CONFIG_KEY_0: "core.autocrlf", GIT_CONFIG_VALUE_0: "false" });
450
451
  var GIT_NOT_STARTED = "git did not start";
451
452
  var GIT_BIN = "git";
453
+ var WIN_SHELL_LANGS = Object.freeze(["shell", "bash", "sh"]);
454
+ var GIT_BASH_RELATIVE = Object.freeze([["..", "bin", "bash.exe"], ["..", "..", "bin", "bash.exe"]]);
452
455
  var GIT_EXIT_LABEL = "git exit ";
453
456
  var UPGRADE_TRASH_SUFFIX = ".ctx-upgrade-removing";
454
457
  var TABLE_ROW_START = "| ";
@@ -456,7 +459,6 @@ var TABLE_CELL_SEP = " | ";
456
459
  var TABLE_ROW_END = " |";
457
460
  var TABLE_PIPE = "|";
458
461
  var TABLE_PIPE_ESCAPED = "\\|";
459
- var TOML_TABLE_OPEN = "[";
460
462
  var OPS_SPLIT_FILES = Object.freeze([
461
463
  "doctor-env.ts",
462
464
  "doctor-config.ts",
@@ -484,10 +486,10 @@ function D3_DETAIL(parts) {
484
486
  var HOOK_HOST_FILE = Object.freeze({
485
487
  "claude-code": { root: "plugin", file: ["hooks", "claude-code.json"], key: ["hooks"], shape: "nested", timeoutKey: "timeout", matcher: true },
486
488
  codex: { root: "home", file: [".codex", "hooks.json"], key: ["hooks"], shape: "nested", timeoutKey: "timeout", matcher: true },
487
- gemini: { root: "home", file: [".gemini", "settings.json"], key: ["hooks"], shape: "nested", timeoutKey: "timeout", matcher: false },
488
- qwen: { root: "home", file: [".qwen", "settings.json"], key: ["hooks"], shape: "nested", timeoutKey: "timeout", matcher: true },
489
+ gemini: { root: "plugin", file: ["hooks", "hooks.json"], key: ["hooks"], shape: "nested", timeoutKey: "timeout", matcher: false },
490
+ qwen: { root: "plugin", file: ["hooks", "qwen.json"], key: ["hooks"], shape: "nested", timeoutKey: "timeout", matcher: true },
489
491
  "copilot-cli": { root: "home", file: [".copilot", "hooks", "context-mode.json"], key: ["hooks"], shape: "flat", timeoutKey: "timeoutSec", matcher: false },
490
- vscode: { root: "project", file: [".github", "hooks", "context-mode.json"], key: ["hooks"], shape: "flat", timeoutKey: "timeout", matcher: false },
492
+ vscode: { root: "home", file: [".copilot", "hooks", "context-mode-vscode.json"], key: ["hooks"], shape: "flat", timeoutKey: "timeout", matcher: false },
491
493
  kiro: { root: "home", file: [".kiro", "hooks", "context-mode.json"], key: ["hooks"], shape: "kiro", timeoutKey: "timeout", matcher: false },
492
494
  zcode: { root: "home", file: [".zcode", "cli", "config.json"], key: ["hooks", "events"], shape: "zcode", timeoutKey: "timeoutMs", matcher: true },
493
495
  pi: null,
@@ -520,6 +522,13 @@ var PRAGMA_INTEGRITY_CHECK = "PRAGMA integrity_check";
520
522
  function D10_DETAIL(mode) {
521
523
  return `enforcement mode: ${mode}`;
522
524
  }
525
+ var D11_WIN_DETAIL = "Git Bash not found";
526
+ var D11_WIN_FIX = "install Git for Windows";
527
+ var D11_POSIX_DETAIL = "no sh on PATH";
528
+ var D11_POSIX_FIX = "install sh or add it to PATH";
529
+ function D11_PASS_DETAIL(shell, win) {
530
+ return `${win ? "Git Bash" : "sh"}: ${shell}`;
531
+ }
523
532
  var DB_SIBLING_SUFFIXES = Object.freeze(["", DB_WAL_SUFFIX, DB_SHM_SUFFIX]);
524
533
  var HEAL_TMP_SUFFIX = ".heal";
525
534
  var HEAL_TS_SEP = ".";
@@ -528,6 +537,7 @@ var HASH_ENCODING = "hex";
528
537
  var PLUGIN_LINK_TMP_SUFFIX = ".swap";
529
538
  var PLUGIN_LINK_OLD_SUFFIX = ".old";
530
539
  var PLUGIN_LINK_TYPE = "dir";
540
+ var PLUGIN_LINK_TYPE_WIN32 = "junction";
531
541
  var OWNER_STOP_EXT = ".stop";
532
542
  var UPGRADE_DATA_DELETED = "user data deleted";
533
543
  var UPGRADE_HOST_COMMAND = Object.freeze({
@@ -568,7 +578,14 @@ var V1_HOOKS_DIR_NAME = "hooks";
568
578
  var SETTINGS_FILE = "settings.json";
569
579
  var CLAUDE_USER_CONFIG_FILE = ".claude.json";
570
580
  var HOOKS_JSON_FILE = "hooks.json";
581
+ var CLAUDE_CONFIG_DIR_ENV = "CLAUDE_CONFIG_DIR";
571
582
  var CODEX_HOME_ENV = "CODEX_HOME";
583
+ var COPILOT_HOME_ENV = "COPILOT_HOME";
584
+ var KIRO_HOME_ENV = "KIRO_HOME";
585
+ var OPENCODE_CONFIG_DIR_ENV = "OPENCODE_CONFIG_DIR";
586
+ var APPDATA_ENV = "APPDATA";
587
+ var VSCODE_USER_DIR_SEGMENTS = Object.freeze(["Code", "User"]);
588
+ var XDG_CONFIG_HOME_ENV = "XDG_CONFIG_HOME";
572
589
  var CONFIG_TOML_FILE = "config.toml";
573
590
  var CONFIG_JSON_FILE = "config.json";
574
591
  var ZCODE_CLI_DIR = "cli";
@@ -602,6 +619,8 @@ var PI_ROLE = "custom";
602
619
  var PI_AGENT_DIR_ENV = "PI_CODING_AGENT_DIR";
603
620
  var PI_PACKAGE_SOURCE_KEY = "source";
604
621
  var V1_PATH_SEPS = Object.freeze(["/", "\\"]);
622
+ var HOST_SEP_TOKEN = "${/}";
623
+ var HOOK_SCRIPT_SEPS = Object.freeze([...V1_PATH_SEPS, HOST_SEP_TOKEN]);
605
624
  var V1_REASON = Object.freeze({
606
625
  hook: "old context-mode hook entry: command contains context-mode and an old script name or context-mode hook",
607
626
  cacheHealHook: "old context-mode cache-heal SessionStart hook entry",
@@ -629,7 +648,13 @@ var PLUGIN_NAME = SERVER_KEY;
629
648
  var OPENCODE_TOOL_PREFIX = SERVER_KEY + "_";
630
649
  var SERVER_ENTRY_FILE = "server.mjs";
631
650
  var HOST_NODE_COMMAND = "node";
651
+ var EXE_SUFFIX = ".exe";
632
652
  var HOST_CONFIG_TMP_SUFFIX = ".tmp";
653
+ var ATOMIC_RENAME_RETRIES = 5;
654
+ var ATOMIC_RENAME_DELAY_MS = 50;
655
+ var ATOMIC_RENAME_BUSY_CODES = ["EPERM", "EBUSY", "EACCES"];
656
+ var ATOMIC_TMP_PREFIX = ".";
657
+ var ATOMIC_TMP_MARK = ".cm-tmp-";
633
658
  var HOST_CONFIG_TEXT_PATH = "(given text)";
634
659
  var JSON_INDENT_UNIT = " ";
635
660
  var MCP_COMMAND_FIELD = "command";
@@ -641,7 +666,7 @@ var CODEX_APPROVAL_MODE_FIELD = "default_tools_approval_mode";
641
666
  var CODEX_APPROVAL_APPROVE = "approve";
642
667
  var OWN_MCP_ENTRY = Object.freeze({
643
668
  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 } },
644
- vscode: { file: [".vscode", "mcp.json"], key: ["servers", SERVER_KEY] },
669
+ vscode: { file: [VSCODE_MCP_FILE], key: ["servers", SERVER_KEY] },
645
670
  kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
646
671
  zcode: {
647
672
  file: [".zcode", "cli", "config.json"],
@@ -664,6 +689,8 @@ var ERROR_TEXT = Object.freeze({
664
689
  NO_PROJECT: "Project source <kind> is missing. Fix: run ctx_doctor.",
665
690
  UNKNOWN_FIELD: 'Unknown field "<f>". Fix: use "queries".',
666
691
  TIMEOUT: "Timed out after <ms> ms. Fix: pass background: true.",
692
+ NO_GIT_BASH: "Git Bash not found. Fix: install Git for Windows.",
693
+ // D-VT-WINBASH-1
667
694
  NO_RUNTIME: "No <lang> runtime on PATH. Fix: install it or pick another language.",
668
695
  FETCH_FAILED: "Fetch failed: <code>. Fix: check the URL or proxy.",
669
696
  SSRF: "Blocked private address <host>. Fix: use a public URL.",
@@ -1087,8 +1114,14 @@ var VSCODE_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostTool
1087
1114
  var MCP_PREFIX2 = "mcp_";
1088
1115
  var MCP_SEP2 = "_";
1089
1116
  var SESSION_START_NEW = "new";
1090
- var SHELL_TOOL_NAME = "run_in_terminal";
1091
- var NATIVE_TO_CANONICAL4 = { [SHELL_TOOL_NAME]: "Bash" };
1117
+ var SHELL_TOOL_NAMES = Object.freeze(["run_in_terminal", "runTerminalCommand", "bash", "powershell"]);
1118
+ var READ_TOOL_NAMES = Object.freeze(["read_file", "view"]);
1119
+ var WEBFETCH_TOOL_NAMES = Object.freeze(["fetch_webpage", "web_fetch"]);
1120
+ var NATIVE_TO_CANONICAL4 = Object.fromEntries([
1121
+ ...SHELL_TOOL_NAMES.map((n) => [n, "Bash"]),
1122
+ ...READ_TOOL_NAMES.map((n) => [n, "Read"]),
1123
+ ...WEBFETCH_TOOL_NAMES.map((n) => [n, "WebFetch"])
1124
+ ]);
1092
1125
  function canonicalName4(name) {
1093
1126
  if (name.startsWith(TOOL_NAME_PREFIX6)) return name.slice(TOOL_NAME_PREFIX6.length);
1094
1127
  if (Object.hasOwn(NATIVE_TO_CANONICAL4, name)) return NATIVE_TO_CANONICAL4[name];
@@ -1098,6 +1131,26 @@ function canonicalName4(name) {
1098
1131
  if (sep3 <= 0 || sep3 === rest.length - 1) return name;
1099
1132
  return "mcp:" + rest.slice(0, sep3) + ":" + rest.slice(sep3 + MCP_SEP2.length);
1100
1133
  }
1134
+ var isNum = (v) => typeof v === "number" && Number.isFinite(v);
1135
+ function policyInput(name, canonical, input) {
1136
+ if (canonical === "Read" && READ_TOOL_NAMES.includes(name)) {
1137
+ const out = { ...input };
1138
+ if (name === "read_file") {
1139
+ if (typeof input.filePath === "string") out.file_path = input.filePath;
1140
+ if (isNum(input.startLine)) out.offset = input.startLine;
1141
+ if (isNum(input.startLine) && isNum(input.endLine) && input.endLine >= input.startLine) out.limit = input.endLine - input.startLine + 1;
1142
+ } else if (Array.isArray(input.view_range) && isNum(input.view_range[0])) {
1143
+ out.offset = input.view_range[0];
1144
+ const end = input.view_range[1];
1145
+ if (isNum(end) && end >= input.view_range[0]) out.limit = end - input.view_range[0] + 1;
1146
+ }
1147
+ return out;
1148
+ }
1149
+ if (canonical === "WebFetch" && name === "fetch_webpage" && Array.isArray(input.urls) && typeof input.urls[0] === "string") {
1150
+ return { ...input, url: input.urls[0] };
1151
+ }
1152
+ return input;
1153
+ }
1101
1154
  function readResult4(resp) {
1102
1155
  const text = resp === void 0 ? "" : typeof resp === "string" ? resp : JSON.stringify(resp);
1103
1156
  const isError = typeof resp === "object" && resp !== null && resp.is_error === true;
@@ -1145,7 +1198,8 @@ function decodeCamel(p, name) {
1145
1198
  if (event === "UserPromptSubmit" && typeof p.prompt === "string") ev.prompt = p.prompt;
1146
1199
  if (event === "PreToolUse" || event === "PostToolUse") {
1147
1200
  const toolName = String(p.toolName ?? "");
1148
- ev.tool = { name: toolName, canonicalName: canonicalName4(toolName), input: readArgs2(p.toolArgs) };
1201
+ const canonical = canonicalName4(toolName);
1202
+ ev.tool = { name: toolName, canonicalName: canonical, input: policyInput(toolName, canonical, readArgs2(p.toolArgs)) };
1149
1203
  }
1150
1204
  if (event === "PostToolUse") ev.result = readCamelResult(p.toolResult);
1151
1205
  return ev;
@@ -1167,7 +1221,8 @@ function decode6(raw) {
1167
1221
  if (event === "PreToolUse" || event === "PostToolUse") {
1168
1222
  const name = String(p.tool_name ?? "");
1169
1223
  const input = isRecord2(p.tool_input) ? p.tool_input : {};
1170
- ev.tool = { name, canonicalName: canonicalName4(name), input };
1224
+ const canonical = canonicalName4(name);
1225
+ ev.tool = { name, canonicalName: canonical, input: policyInput(name, canonical, input) };
1171
1226
  }
1172
1227
  if (event === "PostToolUse") ev.result = readResult4(p.tool_response);
1173
1228
  return ev;
@@ -1191,8 +1246,8 @@ var KIRO_EVENTS = {
1191
1246
  };
1192
1247
  var PROMPT_ENV = "USER_PROMPT";
1193
1248
  var MCP_PREFIX3 = "mcp_";
1194
- var SHELL_TOOL_NAMES = Object.freeze(["execute_bash", "execute_pwsh", "shell"]);
1195
- var NATIVE_TO_CANONICAL5 = Object.fromEntries(SHELL_TOOL_NAMES.map((n) => [n, "Bash"]));
1249
+ var SHELL_TOOL_NAMES2 = Object.freeze(["execute_bash", "execute_pwsh", "shell"]);
1250
+ var NATIVE_TO_CANONICAL5 = Object.fromEntries(SHELL_TOOL_NAMES2.map((n) => [n, "Bash"]));
1196
1251
  var MCP_SEP3 = "_";
1197
1252
  var KIRO_SOURCES = { startup: "startup", resume: "resume", clear: "clear", compact: "compact" };
1198
1253
  function canonicalName5(name) {
@@ -1333,8 +1388,8 @@ var OPENCODE_EVENTS = {
1333
1388
  compaction: "PreCompact",
1334
1389
  "step-finish": "Usage"
1335
1390
  };
1336
- var SHELL_TOOL_NAME2 = "bash";
1337
- var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [SHELL_TOOL_NAME2]: "Bash" };
1391
+ var SHELL_TOOL_NAME = "bash";
1392
+ var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [SHELL_TOOL_NAME]: "Bash" };
1338
1393
  function toCanonicalTool(name) {
1339
1394
  if (name.startsWith(OWN_WIRE_PREFIX)) return name.slice(OWN_WIRE_PREFIX.length);
1340
1395
  return Object.prototype.hasOwnProperty.call(NATIVE_TO_CANONICAL7, name) ? NATIVE_TO_CANONICAL7[name] : name;
@@ -1483,7 +1538,8 @@ var ADAPTERS = Object.freeze([
1483
1538
  projectSource: "arg:workspaceFolder",
1484
1539
  toolNamePrefix: TOOL_NAME_PREFIX6,
1485
1540
  // PreCompact sets the pending flag (ADR-0009 §6, DEVIATIONS D-M3-A4-1).
1486
- nativeTools: { shell: [SHELL_TOOL_NAME] },
1541
+ nativeTools: { shell: [...SHELL_TOOL_NAMES], read: [...READ_TOOL_NAMES], webfetch: [...WEBFETCH_TOOL_NAMES] },
1542
+ // D-HF-VSCODE-PROJECT-1, D-N7-VSCODE-TOOLS-1
1487
1543
  execReadOnlyHint: false,
1488
1544
  eventMap: { ...CLAUDE_EVENTS, PreCompact: "PreCompact" },
1489
1545
  compactDelivery: "pending-flag",
@@ -1501,7 +1557,7 @@ var ADAPTERS = Object.freeze([
1501
1557
  installMode: "mcp-entry",
1502
1558
  projectSource: "arg:--agent+cwd",
1503
1559
  toolNamePrefix: TOOL_NAME_PREFIX7,
1504
- nativeTools: { shell: [...SHELL_TOOL_NAMES] },
1560
+ nativeTools: { shell: [...SHELL_TOOL_NAMES2] },
1505
1561
  execReadOnlyHint: false,
1506
1562
  // D-HF-KIRO-SHELL-1, D-N7-KIRO-1
1507
1563
  eventMap: { SessionStart: "SessionStart", UserPromptSubmit: "UserPromptSubmit", PreToolUse: "PreToolUse", PostToolUse: "PostToolUse" },
@@ -1558,7 +1614,7 @@ var ADAPTERS = Object.freeze([
1558
1614
  installMode: "in-process",
1559
1615
  projectSource: "spawn-cwd",
1560
1616
  toolNamePrefix: TOOL_NAME_PREFIX10,
1561
- nativeTools: { shell: [SHELL_TOOL_NAME2] },
1617
+ nativeTools: { shell: [SHELL_TOOL_NAME] },
1562
1618
  execReadOnlyHint: false,
1563
1619
  // D-HF-OPENCODE-SHELL-1
1564
1620
  // Usage: step-finish cost row (DEVIATIONS D-M5-arch-2).
@@ -2482,10 +2538,10 @@ function element(p) {
2482
2538
  function pipeline(p) {
2483
2539
  if (isWord(at(p), NOT)) p.i++;
2484
2540
  const all = [];
2485
- let last = EMPTY3();
2541
+ let last2 = EMPTY3();
2486
2542
  while (p.err === null) {
2487
- last = element(p);
2488
- all.push(...last.cmds);
2543
+ last2 = element(p);
2544
+ all.push(...last2.cmds);
2489
2545
  const t = at(p);
2490
2546
  if (t !== void 0 && t.kind === "op" && PIPES.includes(t.text)) {
2491
2547
  p.i++;
@@ -2493,7 +2549,7 @@ function pipeline(p) {
2493
2549
  }
2494
2550
  break;
2495
2551
  }
2496
- if (last.simple !== null && isBoundedSink(last.simple)) for (const c of all) c.endsInBoundedSink = true;
2552
+ if (last2.simple !== null && isBoundedSink(last2.simple)) for (const c of all) c.endsInBoundedSink = true;
2497
2553
  return all;
2498
2554
  }
2499
2555
  function list(p, stop) {
@@ -2536,27 +2592,95 @@ function parseShell(cmd) {
2536
2592
  // src/core/policy/subagent.ts
2537
2593
  import { join as join2 } from "node:path";
2538
2594
 
2595
+ // src/core/ops/host-text.ts
2596
+ var BOM_CODE = 65279;
2597
+ var CR_CODE = 13;
2598
+ var CRLF2 = "\r\n";
2599
+ var LF = "\n";
2600
+ function hostLayout(raw) {
2601
+ let crlf = 0;
2602
+ let lf = 0;
2603
+ for (let i = raw.indexOf(LF); i >= 0; i = raw.indexOf(LF, i + 1)) {
2604
+ if (i > 0 && raw.charCodeAt(i - 1) === CR_CODE) crlf += 1;
2605
+ else lf += 1;
2606
+ }
2607
+ return { bom: raw.length > 0 && raw.charCodeAt(0) === BOM_CODE, crlf: crlf > 0 && crlf >= lf };
2608
+ }
2609
+ function hostText(raw) {
2610
+ const bare2 = raw.length > 0 && raw.charCodeAt(0) === BOM_CODE ? raw.slice(1) : raw;
2611
+ return bare2.indexOf(CRLF2) < 0 ? bare2 : bare2.split(CRLF2).join(LF);
2612
+ }
2613
+ function withLayout(text, layout) {
2614
+ const eol = layout.crlf ? text.split(LF).join(CRLF2) : text;
2615
+ return layout.bom ? String.fromCharCode(BOM_CODE) + eol : eol;
2616
+ }
2617
+
2539
2618
  // src/core/project/config-dir.ts
2540
- import { join } from "node:path";
2619
+ import { join, posix, win32 } from "node:path";
2541
2620
  var { mkdirSync, realpathSync } = process.getBuiltinModule("node:fs");
2542
- function homeDirOf(env) {
2543
- const home = env.HOME;
2544
- if (home !== void 0 && home !== "") return home;
2545
- const profile = env.USERPROFILE;
2546
- if (profile !== void 0 && profile !== "") return profile;
2547
- return null;
2621
+ function homeDirOf(env, platform = process.platform) {
2622
+ const set3 = (v) => v !== void 0 && v !== "";
2623
+ if (platform === "win32") {
2624
+ if (set3(env.USERPROFILE)) return env.USERPROFILE;
2625
+ if (set3(env.HOMEDRIVE) && set3(env.HOMEPATH)) return env.HOMEDRIVE + env.HOMEPATH;
2626
+ return set3(env.HOME) ? env.HOME : null;
2627
+ }
2628
+ if (set3(env.HOME)) return env.HOME;
2629
+ return set3(env.USERPROFILE) ? env.USERPROFILE : null;
2548
2630
  }
2549
2631
  function codexDirOf(env, home) {
2550
2632
  const dir = env[CODEX_HOME_ENV];
2551
2633
  return dir !== void 0 && dir !== "" ? dir : join(home, ...AGENT_HOME_DIR.codex);
2552
2634
  }
2553
- function homeOf(env) {
2554
- const home = homeDirOf(env);
2635
+ function copilotDirOf(env, home) {
2636
+ const dir = env[COPILOT_HOME_ENV];
2637
+ return dir !== void 0 && dir !== "" ? dir : join(home, ...AGENT_HOME_DIR["copilot-cli"]);
2638
+ }
2639
+ function kiroDirOf(env, home, platform = process.platform) {
2640
+ const p = platform === "win32" ? win32 : posix;
2641
+ const fallback = p.join(home, ...AGENT_HOME_DIR.kiro);
2642
+ const dir = env[KIRO_HOME_ENV];
2643
+ if (dir === void 0 || dir === "" || !p.isAbsolute(dir)) return fallback;
2644
+ if (platform === "win32" && p.parse(dir).root.length < 2) return fallback;
2645
+ const abs = p.resolve(dir);
2646
+ if (p.dirname(abs) === abs) return fallback;
2647
+ const up = p.relative(abs, p.resolve(home));
2648
+ if (!p.isAbsolute(up) && up.split(p.sep)[0] !== "..") return fallback;
2649
+ return dir;
2650
+ }
2651
+ function claudeDirOf(env, home) {
2652
+ const dir = env[CLAUDE_CONFIG_DIR_ENV];
2653
+ return dir !== void 0 && dir !== "" ? dir : join(home, ...AGENT_HOME_DIR["claude-code"]);
2654
+ }
2655
+ function opencodeDirOf(env, home) {
2656
+ const own2 = env[OPENCODE_CONFIG_DIR_ENV];
2657
+ if (own2 !== void 0 && own2 !== "") return own2;
2658
+ const xdg = env[XDG_CONFIG_HOME_ENV];
2659
+ if (xdg !== void 0 && xdg !== "") return join(xdg, AGENT_HOME_DIR.opencode[AGENT_HOME_DIR.opencode.length - 1]);
2660
+ return join(home, ...AGENT_HOME_DIR.opencode);
2661
+ }
2662
+ function piAgentDirOf(env, home) {
2663
+ const dir = env[PI_AGENT_DIR_ENV];
2664
+ return dir !== void 0 && dir !== "" ? dir : join(home, ...AGENT_HOME_DIR.pi, PI_AGENT_DIR);
2665
+ }
2666
+ function vscodeUserDirOf(env, home, platform = process.platform) {
2667
+ const set3 = (v) => v !== void 0 && v !== "";
2668
+ const p = platform === "win32" ? win32 : posix;
2669
+ if (platform === "win32") return p.join(set3(env[APPDATA_ENV]) ? env[APPDATA_ENV] : p.join(home, "AppData", "Roaming"), ...VSCODE_USER_DIR_SEGMENTS);
2670
+ if (platform === "darwin") return p.join(home, "Library", "Application Support", ...VSCODE_USER_DIR_SEGMENTS);
2671
+ return p.join(set3(env[XDG_CONFIG_HOME_ENV]) ? env[XDG_CONFIG_HOME_ENV] : p.join(home, ".config"), ...VSCODE_USER_DIR_SEGMENTS);
2672
+ }
2673
+ function ownMcpFileOf(agent, file2, env, home) {
2674
+ if (agent === "kiro") return join(kiroDirOf(env, home), ...file2.slice(1));
2675
+ return agent === "vscode" ? join(vscodeUserDirOf(env, home), ...file2) : join(home, ...file2);
2676
+ }
2677
+ function requireHomeDir(env, platform = process.platform) {
2678
+ const home = homeDirOf(env, platform);
2555
2679
  if (home !== null) return home;
2556
- throw new CtxError("NO_HOME", { name: process.platform === "win32" ? "USERPROFILE" : "HOME" });
2680
+ throw new CtxError("NO_HOME", { name: platform === "win32" ? "USERPROFILE" : "HOME" });
2557
2681
  }
2558
2682
  function resolveConfigDir(env) {
2559
- const dir = join(homeOf(env), DATA_ROOT.slice(1));
2683
+ const dir = join(requireHomeDir(env), DATA_ROOT.slice(1));
2560
2684
  mkdirSync(dir, { recursive: true });
2561
2685
  return realpathSync.native(dir);
2562
2686
  }
@@ -2593,11 +2717,11 @@ function findDef(type, src) {
2593
2717
  const p = readAgentFile(join2(src.projectDir, HOST_CONFIG_DIR_NAME, AGENTS_DIR_NAME, type + AGENT_FILE_EXT));
2594
2718
  if (p !== null) return p;
2595
2719
  if (home !== null) {
2596
- const u = readAgentFile(join2(home, HOST_CONFIG_DIR_NAME, AGENTS_DIR_NAME, type + AGENT_FILE_EXT));
2720
+ const u = readAgentFile(join2(claudeDirOf(src.env, home), AGENTS_DIR_NAME, type + AGENT_FILE_EXT));
2597
2721
  if (u !== null) return u;
2598
2722
  }
2599
2723
  } else if (home !== null) {
2600
- const pl = readPluginAgent(home, type);
2724
+ const pl = readPluginAgent(claudeDirOf(src.env, home), type);
2601
2725
  if (pl !== null) return pl;
2602
2726
  }
2603
2727
  const cli = src.cliAgents;
@@ -2616,14 +2740,14 @@ function safeType(type) {
2616
2740
  function homeDir(env) {
2617
2741
  return homeDirOf(env);
2618
2742
  }
2619
- function readPluginAgent(home, type) {
2743
+ function readPluginAgent(claudeDir, type) {
2620
2744
  const cut = type.indexOf(PLUGIN_AGENT_SEPARATOR);
2621
2745
  const plugin = type.slice(0, cut);
2622
2746
  const agent = type.slice(cut + PLUGIN_AGENT_SEPARATOR.length);
2623
2747
  if (agent.indexOf(PLUGIN_AGENT_SEPARATOR) >= 0) return null;
2624
2748
  let parsed;
2625
2749
  try {
2626
- parsed = JSON.parse(readFileSync(join2(home, HOST_CONFIG_DIR_NAME, HOST_PLUGINS_DIR_NAME, INSTALLED_PLUGINS_FILE), "utf8"));
2750
+ parsed = JSON.parse(hostText(readFileSync(join2(claudeDir, HOST_PLUGINS_DIR_NAME, INSTALLED_PLUGINS_FILE), "utf8")));
2627
2751
  } catch {
2628
2752
  return null;
2629
2753
  }
@@ -2643,10 +2767,10 @@ function readPluginAgent(home, type) {
2643
2767
  }
2644
2768
  return null;
2645
2769
  }
2646
- function readAgentFile(path4) {
2770
+ function readAgentFile(path5) {
2647
2771
  let text;
2648
2772
  try {
2649
- text = readFileSync(path4, "utf8");
2773
+ text = readFileSync(path5, "utf8");
2650
2774
  } catch {
2651
2775
  return null;
2652
2776
  }
@@ -2856,7 +2980,6 @@ function unwrap(commands) {
2856
2980
  import { isAbsolute, join as join3, relative, sep } from "node:path";
2857
2981
  var { readFileSync: readFileSync2 } = process.getBuiltinModule("node:fs");
2858
2982
  var CLAUDE_DIR = ".claude";
2859
- var CLAUDE_CONFIG_DIR_ENV = "CLAUDE_CONFIG_DIR";
2860
2983
  var LOCAL_SETTINGS = "settings.local.json";
2861
2984
  var SETTINGS = "settings.json";
2862
2985
  var BASH_TOOL = "Bash";
@@ -2870,9 +2993,9 @@ var WHITESPACE = " \n\r";
2870
2993
  var BASH_SUBJECT = Object.freeze({ tool: BASH_TOOL });
2871
2994
  function denyFiles(projectDir, agent) {
2872
2995
  if (agent !== "claude-code") return [];
2873
- const cfg = process.env[CLAUDE_CONFIG_DIR_ENV];
2874
2996
  const home = homeDirOf(process.env);
2875
- const userDir = cfg !== void 0 && cfg !== "" ? cfg : home === null ? null : join3(home, CLAUDE_DIR);
2997
+ const cfg = process.env[CLAUDE_CONFIG_DIR_ENV];
2998
+ const userDir = cfg !== void 0 && cfg !== "" ? cfg : home === null ? null : claudeDirOf(process.env, home);
2876
2999
  const project = [join3(projectDir, CLAUDE_DIR, LOCAL_SETTINGS), join3(projectDir, CLAUDE_DIR, SETTINGS)];
2877
3000
  return userDir === null ? project : [...project, join3(userDir, SETTINGS)];
2878
3001
  }
@@ -2882,7 +3005,7 @@ function isObject(v) {
2882
3005
  function readOne(file2) {
2883
3006
  let text;
2884
3007
  try {
2885
- text = readFileSync2(file2, "utf8");
3008
+ text = hostText(readFileSync2(file2, "utf8"));
2886
3009
  } catch (err) {
2887
3010
  return err.code === "ENOENT" ? { kind: "absent" } : { kind: "bad" };
2888
3011
  }
@@ -2910,12 +3033,12 @@ function readUserDeny(projectDir, agent) {
2910
3033
  }
2911
3034
  return out;
2912
3035
  }
2913
- function tokenize(glob, path4) {
3036
+ function tokenize(glob, path5) {
2914
3037
  const toks = [];
2915
3038
  let i = 0;
2916
3039
  while (i < glob.length) {
2917
3040
  const c = glob[i];
2918
- if (c === "*" && path4 && glob[i + 1] === "*") {
3041
+ if (c === "*" && path5 && glob[i + 1] === "*") {
2919
3042
  const dir = glob[i + "**".length] === "/";
2920
3043
  toks.push({ t: dir ? "globstarDir" : "globstar" });
2921
3044
  i += dir ? "**/".length : "**".length;
@@ -2929,8 +3052,8 @@ function tokenize(glob, path4) {
2929
3052
  }
2930
3053
  return toks;
2931
3054
  }
2932
- function globMatch(glob, text, path4) {
2933
- const toks = tokenize(glob, path4);
3055
+ function globMatch(glob, text, path5) {
3056
+ const toks = tokenize(glob, path5);
2934
3057
  const n = text.length;
2935
3058
  let next = new Uint8Array(n + 1);
2936
3059
  next[n] = 1;
@@ -2946,10 +3069,10 @@ function globMatch(glob, text, path4) {
2946
3069
  cur[j] = has2 && ch === tok.c ? next[j + 1] : 0;
2947
3070
  break;
2948
3071
  case "any1":
2949
- cur[j] = has2 && !(path4 && ch === "/") ? next[j + 1] : 0;
3072
+ cur[j] = has2 && !(path5 && ch === "/") ? next[j + 1] : 0;
2950
3073
  break;
2951
3074
  case "star":
2952
- cur[j] = next[j] || (has2 && !(path4 && ch === "/") ? cur[j + 1] : 0);
3075
+ cur[j] = next[j] || (has2 && !(path5 && ch === "/") ? cur[j + 1] : 0);
2953
3076
  break;
2954
3077
  case "globstar":
2955
3078
  cur[j] = next[j] || (has2 ? cur[j + 1] : 0);
@@ -3029,8 +3152,8 @@ var READ_DENY_TEMPLATE = 'context-mode: {size}-byte file, over the one-read limi
3029
3152
  // src/core/policy/read-deny.ts
3030
3153
  var SIZE = "{size}";
3031
3154
  var PATH = "{path}";
3032
- function READ_DENY_MESSAGE(path4, size, prefix = "") {
3033
- return prefixToolNames(READ_DENY_TEMPLATE, prefix).split(SIZE).join(String(size)).split(PATH).join(path4);
3155
+ function READ_DENY_MESSAGE(path5, size, prefix = "") {
3156
+ return prefixToolNames(READ_DENY_TEMPLATE, prefix).split(SIZE).join(String(size)).split(PATH).join(path5);
3034
3157
  }
3035
3158
 
3036
3159
  // src/core/policy/decide.ts
@@ -3517,7 +3640,7 @@ function firstLine(file2) {
3517
3640
  }
3518
3641
  function git(dir, args) {
3519
3642
  const { spawnSync } = process.getBuiltinModule("node:child_process");
3520
- const r = spawnSync("git", args, { cwd: dir, shell: false, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
3643
+ const r = spawnSync("git", args, { cwd: dir, shell: false, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
3521
3644
  if (r.error !== void 0 || r.status !== 0) throw new CtxError("NO_GIT_DIR", { path: dir });
3522
3645
  return r.stdout.split("\n").filter((l) => l !== "");
3523
3646
  }
@@ -3709,9 +3832,9 @@ function readUserVersion(raw) {
3709
3832
  const row5 = raw.prepare("PRAGMA user_version").get();
3710
3833
  return row5.user_version;
3711
3834
  }
3712
- function createAtomically(sqlite, path4) {
3835
+ function createAtomically(sqlite, path5) {
3713
3836
  const { randomUUID } = process.getBuiltinModule("node:crypto");
3714
- const tmp = path4 + "." + randomUUID() + DB_TMP_SUFFIX;
3837
+ const tmp = path5 + "." + randomUUID() + DB_TMP_SUFFIX;
3715
3838
  try {
3716
3839
  const raw = new sqlite.DatabaseSync(tmp, { timeout: DB_TIMEOUT_MS });
3717
3840
  try {
@@ -3720,7 +3843,7 @@ function createAtomically(sqlite, path4) {
3720
3843
  raw.close();
3721
3844
  }
3722
3845
  try {
3723
- linkSync(tmp, path4);
3846
+ linkSync(tmp, path5);
3724
3847
  } catch (err) {
3725
3848
  if (err.code !== "EEXIST") throw err;
3726
3849
  }
@@ -3728,11 +3851,11 @@ function createAtomically(sqlite, path4) {
3728
3851
  for (const suffix of ["", DB_WAL_SUFFIX, DB_SHM_SUFFIX]) rmSync(tmp + suffix, { force: true });
3729
3852
  }
3730
3853
  }
3731
- function openWritable(sqlite, path4) {
3854
+ function openWritable(sqlite, path5) {
3732
3855
  let raw = null;
3733
3856
  try {
3734
- if (!existsSync2(path4)) createAtomically(sqlite, path4);
3735
- raw = new sqlite.DatabaseSync(path4, { timeout: DB_TIMEOUT_MS });
3857
+ if (!existsSync2(path5)) createAtomically(sqlite, path5);
3858
+ raw = new sqlite.DatabaseSync(path5, { timeout: DB_TIMEOUT_MS });
3736
3859
  applyMigrations(raw, readUserVersion(raw));
3737
3860
  return raw;
3738
3861
  } catch (err) {
@@ -3740,8 +3863,8 @@ function openWritable(sqlite, path4) {
3740
3863
  throw err;
3741
3864
  }
3742
3865
  }
3743
- function openReadOnly(sqlite, path4) {
3744
- const raw = new sqlite.DatabaseSync(path4, { timeout: DB_TIMEOUT_MS, readOnly: true });
3866
+ function openReadOnly(sqlite, path5) {
3867
+ const raw = new sqlite.DatabaseSync(path5, { timeout: DB_TIMEOUT_MS, readOnly: true });
3745
3868
  try {
3746
3869
  const found = readUserVersion(raw);
3747
3870
  if (found !== SCHEMA_VERSION) throw new CtxError("SCHEMA_STALE", { found, want: SCHEMA_VERSION });
@@ -3755,20 +3878,20 @@ async function openDb(project, opts) {
3755
3878
  if (isBelow(process.version, NODE_MIN)) throw new CtxError("NODE_TOO_OLD", { v: process.version });
3756
3879
  const sqlite = await loadSqlite();
3757
3880
  mkdirSync2(project.projectDir, { recursive: true });
3758
- const path4 = project.dbPath;
3759
- const sibling = existsSync2(path4 + DB_WAL_SUFFIX) || existsSync2(path4 + DB_SHM_SUFFIX);
3760
- if (sibling && !existsSync2(path4)) {
3881
+ const path5 = project.dbPath;
3882
+ const sibling = existsSync2(path5 + DB_WAL_SUFFIX) || existsSync2(path5 + DB_SHM_SUFFIX);
3883
+ if (sibling && !existsSync2(path5)) {
3761
3884
  throw new CtxError("DB_GONE");
3762
3885
  }
3763
3886
  try {
3764
3887
  let raw;
3765
3888
  if (opts?.readOnly === true) {
3766
- if (!existsSync2(path4)) openWritable(sqlite, path4).close();
3767
- raw = openReadOnly(sqlite, path4);
3889
+ if (!existsSync2(path5)) openWritable(sqlite, path5).close();
3890
+ raw = openReadOnly(sqlite, path5);
3768
3891
  } else {
3769
- raw = openWritable(sqlite, path4);
3892
+ raw = openWritable(sqlite, path5);
3770
3893
  }
3771
- return { raw, projectKey: project.projectKey, path: path4 };
3894
+ return { raw, projectKey: project.projectKey, path: path5 };
3772
3895
  } catch (err) {
3773
3896
  if (isCorrupt(err)) throw new CtxError("DB_CORRUPT");
3774
3897
  throw err;
@@ -5805,9 +5928,9 @@ function isWordChar2(cp) {
5805
5928
  while (lo <= hi) {
5806
5929
  const mid = lo + hi >> 1;
5807
5930
  const first = WORD_RANGES[2 * mid];
5808
- const last = WORD_RANGES[2 * mid + 1];
5931
+ const last2 = WORD_RANGES[2 * mid + 1];
5809
5932
  if (cp < first) hi = mid - 1;
5810
- else if (cp > last) lo = mid + 1;
5933
+ else if (cp > last2) lo = mid + 1;
5811
5934
  else return true;
5812
5935
  }
5813
5936
  return false;
@@ -6306,8 +6429,8 @@ function ftsQueryTimeline(db, scope, ctx, sessionId, limit, after, source, memor
6306
6429
  merged.sort(timelineOrder);
6307
6430
  let end = Math.min(limit, merged.length);
6308
6431
  if (end > 0) {
6309
- const last = merged[end - 1].ts;
6310
- while (end < merged.length && merged[end].ts === last) end++;
6432
+ const last2 = merged[end - 1].ts;
6433
+ while (end < merged.length && merged[end].ts === last2) end++;
6311
6434
  }
6312
6435
  const rows = merged.slice(0, end);
6313
6436
  if (rows.length === 0) return { rows, more: false };
@@ -6446,8 +6569,8 @@ function buildCandidates(rows, sessionId) {
6446
6569
  if (!sessionId) return emptySet();
6447
6570
  const own2 = rows.filter((r) => r.session_id === sessionId).sort((a, b) => a.seq - b.seq);
6448
6571
  const prompts = own2.filter((r) => r.kind === "prompt");
6449
- const last = prompts.length > 0 ? prompts[prompts.length - 1] : void 0;
6450
- const lastRequest = last === void 0 ? null : make("last_request", last, "now: " + firstLine2(last.body), 1, null);
6572
+ const last2 = prompts.length > 0 ? prompts[prompts.length - 1] : void 0;
6573
+ const lastRequest = last2 === void 0 ? null : make("last_request", last2, "now: " + firstLine2(last2.body), 1, null);
6451
6574
  const earlierRequests = prompts.slice(0, prompts.length - 1).map((r) => make("earlier_requests", r, "asked #" + r.seq + ": " + firstLine2(r.body), 1, null));
6452
6575
  const failures = /* @__PURE__ */ new Map();
6453
6576
  const lastOk = /* @__PURE__ */ new Map();
@@ -6471,8 +6594,8 @@ function buildCandidates(rows, sessionId) {
6471
6594
  edits.set(r.path, { row: r, count: (edits.get(r.path)?.count ?? 0) + 1 });
6472
6595
  }
6473
6596
  const changedFiles = [];
6474
- for (const [path4, e] of edits) {
6475
- const c = make("changed_files", e.row, "edited " + path4 + " x" + e.count, e.count, path4);
6597
+ for (const [path5, e] of edits) {
6598
+ const c = make("changed_files", e.row, "edited " + path5 + " x" + e.count, e.count, path5);
6476
6599
  changedFiles.push({ ...c, editCount: e.count });
6477
6600
  }
6478
6601
  changedFiles.sort((a, b) => a.seq - b.seq);
@@ -6486,7 +6609,7 @@ function buildCandidates(rows, sessionId) {
6486
6609
  for (const [key, d] of decided) decisions.push(make("decisions", d.row, "decided #" + d.row.seq + ": " + firstLine2(d.row.body), d.count, key));
6487
6610
  decisions.sort((a, b) => a.seq - b.seq);
6488
6611
  const indexedSources = own2.filter((r) => r.kind === "index").map((r) => make("indexed_sources", r, "indexed " + (r.key ?? ""), 1, r.key));
6489
- const set2 = {
6612
+ const set3 = {
6490
6613
  lastRequest,
6491
6614
  openErrors: capSection(openErrors),
6492
6615
  changedFiles: capSection(changedFiles),
@@ -6494,17 +6617,17 @@ function buildCandidates(rows, sessionId) {
6494
6617
  earlierRequests: capSection(earlierRequests),
6495
6618
  indexedSources: capSection(indexedSources)
6496
6619
  };
6497
- const rest = [...set2.openErrors, ...set2.changedFiles, ...set2.decisions, ...set2.earlierRequests, ...set2.indexedSources];
6620
+ const rest = [...set3.openErrors, ...set3.changedFiles, ...set3.decisions, ...set3.earlierRequests, ...set3.indexedSources];
6498
6621
  const total = rest.length + (lastRequest === null ? 0 : 1);
6499
- if (total <= MAX_CANDIDATES_TOTAL) return set2;
6622
+ if (total <= MAX_CANDIDATES_TOTAL) return set3;
6500
6623
  const drop = new Set(rest.map((c) => c.seq).sort((a, b) => a - b).slice(0, total - MAX_CANDIDATES_TOTAL));
6501
6624
  return {
6502
6625
  lastRequest,
6503
- openErrors: set2.openErrors.filter((c) => !drop.has(c.seq)),
6504
- changedFiles: set2.changedFiles.filter((c) => !drop.has(c.seq)),
6505
- decisions: set2.decisions.filter((c) => !drop.has(c.seq)),
6506
- earlierRequests: set2.earlierRequests.filter((c) => !drop.has(c.seq)),
6507
- indexedSources: set2.indexedSources.filter((c) => !drop.has(c.seq))
6626
+ openErrors: set3.openErrors.filter((c) => !drop.has(c.seq)),
6627
+ changedFiles: set3.changedFiles.filter((c) => !drop.has(c.seq)),
6628
+ decisions: set3.decisions.filter((c) => !drop.has(c.seq)),
6629
+ earlierRequests: set3.earlierRequests.filter((c) => !drop.has(c.seq)),
6630
+ indexedSources: set3.indexedSources.filter((c) => !drop.has(c.seq))
6508
6631
  };
6509
6632
  }
6510
6633
 
@@ -6629,15 +6752,15 @@ function renderState(rows, turn, extras, prefix = "") {
6629
6752
  for (const r of rows) if (newest === void 0 || r.seq > newest.seq) newest = r;
6630
6753
  const sessionId = newest === void 0 ? "" : newest.session_id;
6631
6754
  const upto = newest === void 0 || sessionId === "" ? 0 : newest.seq;
6632
- const set2 = buildCandidates(rows, sessionId);
6755
+ const set3 = buildCandidates(rows, sessionId);
6633
6756
  const openTag = `<context_mode_state session="${sessionId}" upto="${upto}">`;
6634
6757
  const emptyMoreBytes = bytesOf2(moreLine([], prefix));
6635
6758
  const budget = STATE_BUDGET - (bytesOf2(openTag) + 1 + emptyMoreBytes + 1 + bytesOf2(STATE_CLOSE_TAG));
6636
6759
  let used = 0;
6637
- const pinnedLine = set2.lastRequest === null ? null : lineOf(set2.lastRequest, prefix);
6760
+ const pinnedLine = set3.lastRequest === null ? null : lineOf(set3.lastRequest, prefix);
6638
6761
  if (pinnedLine !== null) used += bytesOf2(pinnedLine) + 1;
6639
6762
  const remaining = scoreCandidates(
6640
- [...set2.openErrors, ...set2.changedFiles, ...set2.decisions, ...set2.earlierRequests, ...set2.indexedSources],
6763
+ [...set3.openErrors, ...set3.changedFiles, ...set3.decisions, ...set3.earlierRequests, ...set3.indexedSources],
6641
6764
  turn
6642
6765
  );
6643
6766
  const k = /* @__PURE__ */ new Map();
@@ -7637,9 +7760,9 @@ function askDetached(ev, project, tool, text) {
7637
7760
  void openDb(project).then((db) => {
7638
7761
  if (parts.length > 0) return writeDecisions(db, ev, project, parts);
7639
7762
  const prompts = readSessionEvents(db, ev.sessionId, "prompt");
7640
- const last = prompts[prompts.length - 1];
7641
- if (last === void 0 || ev.sessionId === "") return;
7642
- metaSet(db, optionsKey(ev.sessionId), JSON.stringify({ seq: last.seq, labels }));
7763
+ const last2 = prompts[prompts.length - 1];
7764
+ if (last2 === void 0 || ev.sessionId === "") return;
7765
+ metaSet(db, optionsKey(ev.sessionId), JSON.stringify({ seq: last2.seq, labels }));
7643
7766
  }).catch((err) => {
7644
7767
  process.stderr.write("hooks: decision write failed: " + message(err) + "\n");
7645
7768
  });
@@ -8443,10 +8566,10 @@ function jsonStringifyReplacer(_, value) {
8443
8566
  return value;
8444
8567
  }
8445
8568
  function cached(getter) {
8446
- const set2 = false;
8569
+ const set3 = false;
8447
8570
  return {
8448
8571
  get value() {
8449
- if (!set2) {
8572
+ if (!set3) {
8450
8573
  const value = getter();
8451
8574
  Object.defineProperty(this, "value", { value });
8452
8575
  return value;
@@ -8472,10 +8595,10 @@ function floatSafeRemainder(val, step) {
8472
8595
  return valInt % stepInt / 10 ** decCount;
8473
8596
  }
8474
8597
  function defineLazy(object2, key, getter) {
8475
- const set2 = false;
8598
+ const set3 = false;
8476
8599
  Object.defineProperty(object2, key, {
8477
8600
  get() {
8478
- if (!set2) {
8601
+ if (!set3) {
8479
8602
  const value = getter();
8480
8603
  object2[key] = value;
8481
8604
  return value;
@@ -8499,10 +8622,10 @@ function assignProp(target, prop, value) {
8499
8622
  configurable: true
8500
8623
  });
8501
8624
  }
8502
- function getElementAtPath(obj, path4) {
8503
- if (!path4)
8625
+ function getElementAtPath(obj, path5) {
8626
+ if (!path5)
8504
8627
  return obj;
8505
- return path4.reduce((acc, key) => acc?.[key], obj);
8628
+ return path5.reduce((acc, key) => acc?.[key], obj);
8506
8629
  }
8507
8630
  function promiseAllObject(promisesObj) {
8508
8631
  const keys = Object.keys(promisesObj);
@@ -8822,11 +8945,11 @@ function aborted(x, startIndex = 0) {
8822
8945
  }
8823
8946
  return false;
8824
8947
  }
8825
- function prefixIssues(path4, issues) {
8948
+ function prefixIssues(path5, issues) {
8826
8949
  return issues.map((iss) => {
8827
8950
  var _a;
8828
8951
  (_a = iss).path ?? (_a.path = []);
8829
- iss.path.unshift(path4);
8952
+ iss.path.unshift(path5);
8830
8953
  return iss;
8831
8954
  });
8832
8955
  }
@@ -8963,7 +9086,7 @@ function treeifyError(error40, _mapper) {
8963
9086
  return issue2.message;
8964
9087
  };
8965
9088
  const result = { errors: [] };
8966
- const processError = (error41, path4 = []) => {
9089
+ const processError = (error41, path5 = []) => {
8967
9090
  var _a, _b;
8968
9091
  for (const issue2 of error41.issues) {
8969
9092
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -8973,7 +9096,7 @@ function treeifyError(error40, _mapper) {
8973
9096
  } else if (issue2.code === "invalid_element") {
8974
9097
  processError({ issues: issue2.issues }, issue2.path);
8975
9098
  } else {
8976
- const fullpath = [...path4, ...issue2.path];
9099
+ const fullpath = [...path5, ...issue2.path];
8977
9100
  if (fullpath.length === 0) {
8978
9101
  result.errors.push(mapper(issue2));
8979
9102
  continue;
@@ -9003,9 +9126,9 @@ function treeifyError(error40, _mapper) {
9003
9126
  processError(error40);
9004
9127
  return result;
9005
9128
  }
9006
- function toDotPath(path4) {
9129
+ function toDotPath(path5) {
9007
9130
  const segs = [];
9008
- for (const seg of path4) {
9131
+ for (const seg of path5) {
9009
9132
  if (typeof seg === "number")
9010
9133
  segs.push(`[${seg}]`);
9011
9134
  else if (typeof seg === "symbol")
@@ -10345,8 +10468,8 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
10345
10468
  }
10346
10469
  const input = payload.value;
10347
10470
  const isDate = input instanceof Date;
10348
- const isValidDate = isDate && !Number.isNaN(input.getTime());
10349
- if (isValidDate)
10471
+ const isValidDate2 = isDate && !Number.isNaN(input.getTime());
10472
+ if (isValidDate2)
10350
10473
  return payload;
10351
10474
  payload.issues.push({
10352
10475
  expected: "date",
@@ -19027,6 +19150,14 @@ function buildChildEnv(parent, extra) {
19027
19150
  // src/core/sandbox/runtimes.ts
19028
19151
  import { accessSync, constants as fsConstants, statSync as statSync3 } from "node:fs";
19029
19152
  import path from "node:path";
19153
+
19154
+ // src/core/sandbox/path-entries.ts
19155
+ function pathEntries(value, platform = process.platform, delimiter = platform === "win32" ? ";" : ":") {
19156
+ const win = platform === "win32";
19157
+ return value.split(delimiter).map((e) => win && e.length >= 2 && e.startsWith('"') && e.endsWith('"') ? e.slice(1, -1) : e).filter(Boolean);
19158
+ }
19159
+
19160
+ // src/core/sandbox/runtimes.ts
19030
19161
  var PATHEXT_SEPARATOR = ";";
19031
19162
  var WIN_STARTABLE_EXT = Object.freeze([".exe", ".com"]);
19032
19163
  function isWin() {
@@ -19036,7 +19167,7 @@ function candidates(lang) {
19036
19167
  const win = isWin();
19037
19168
  switch (lang) {
19038
19169
  case "shell":
19039
- return win ? ["sh.exe", "bash.exe"] : ["sh"];
19170
+ return win ? [] : ["sh"];
19040
19171
  case "powershell":
19041
19172
  return ["pwsh", "pwsh.exe", "powershell.exe"];
19042
19173
  case "javascript":
@@ -19067,7 +19198,8 @@ function isRunnable(full) {
19067
19198
  }
19068
19199
  }
19069
19200
  function findRuntime(lang, env = process.env) {
19070
- const dirs = (env.PATH ?? "").split(path.delimiter).filter((d) => d !== "");
19201
+ if (isWin() && WIN_SHELL_LANGS.includes(lang)) return findGitBash(env);
19202
+ const dirs = pathEntries(env.PATH ?? "", process.platform, path.delimiter);
19071
19203
  const pathExt = isWin() ? (env.PATHEXT ?? PATHEXT_DEFAULT).split(PATHEXT_SEPARATOR).filter((e) => e !== "") : [];
19072
19204
  const names = candidates(lang);
19073
19205
  let shim = null;
@@ -19083,6 +19215,18 @@ function findRuntime(lang, env = process.env) {
19083
19215
  }
19084
19216
  return shim;
19085
19217
  }
19218
+ function findGitBash(env) {
19219
+ const git3 = findRuntime(GIT_BIN, env);
19220
+ if (git3 === null) return null;
19221
+ for (const rel of GIT_BASH_RELATIVE) {
19222
+ const full = path.resolve(path.dirname(git3), ...rel);
19223
+ if (isRunnable(full)) return full;
19224
+ }
19225
+ return null;
19226
+ }
19227
+ function noRuntimeError(lang) {
19228
+ return isWin() && WIN_SHELL_LANGS.includes(lang) ? new CtxError("NO_GIT_BASH") : new CtxError("NO_RUNTIME", { lang });
19229
+ }
19086
19230
 
19087
19231
  // src/core/sandbox/spawn.ts
19088
19232
  import { spawn } from "node:child_process";
@@ -19190,19 +19334,19 @@ function readAutoMemory(project) {
19190
19334
  if (project.agent !== "claude-code") return [];
19191
19335
  const rows = [];
19192
19336
  for (const segs of CLAUDE_CODE_MEMORY_FILES) {
19193
- const path4 = join6(project.worktree, ...segs);
19194
- if (!isInside(project.worktree, path4)) continue;
19337
+ const path5 = join6(project.worktree, ...segs);
19338
+ if (!isInside(project.worktree, path5)) continue;
19195
19339
  try {
19196
- const st = statSync4(path4);
19340
+ const st = statSync4(path5);
19197
19341
  if (!st.isFile()) continue;
19198
19342
  rows.push({
19199
19343
  origin: "memory",
19200
19344
  ts: Math.trunc(st.mtimeMs),
19201
19345
  seq: null,
19202
19346
  sourceId: null,
19203
- path: path4,
19347
+ path: path5,
19204
19348
  label: segs.join("/"),
19205
- text: readFileSync5(path4, "utf8")
19349
+ text: readFileSync5(path5, "utf8")
19206
19350
  });
19207
19351
  } catch {
19208
19352
  }
@@ -19453,7 +19597,7 @@ function stoppedAt(cmd, error40) {
19453
19597
  return { head: headOf(cmd), block: headOf(cmd) + error40, exitCode: null, bytes: 0, error: error40 };
19454
19598
  }
19455
19599
  async function runCommand(cmd, shell, ctx, deadline, boundMs) {
19456
- if (shell === null) return stoppedAt(cmd, formatError("NO_RUNTIME", { lang: SHELL }));
19600
+ if (shell === null) return stoppedAt(cmd, noRuntimeError(SHELL).toLine());
19457
19601
  const left = deadline - Date.now();
19458
19602
  if (left <= 0) return stoppedAt(cmd, formatError("TIMEOUT", { ms: boundMs }));
19459
19603
  const r = await runProcess([shell, SHELL_INLINE_FLAG, cmd], {
@@ -19573,19 +19717,19 @@ async function runBatch(input, ctx, boundMs, budgetBytes) {
19573
19717
  const shell = findRuntime(SHELL);
19574
19718
  const pool = await runPool(commands.map((c) => () => runCommand(c, shell, ctx, deadline, boundMs)), ONE_AT_A_TIME, (r) => r.error !== null);
19575
19719
  const ran = pool.results;
19576
- const last = ran[ran.length - 1];
19720
+ const last2 = ran[ran.length - 1];
19577
19721
  const sandboxBytes = ran.reduce((n, r) => n + r.bytes, 0);
19578
19722
  const label = LABEL_PREFIX + ctx.turn;
19579
19723
  try {
19580
19724
  const db = await openDb(ctx.project);
19581
19725
  let sections;
19582
19726
  let idx;
19583
- const summary = commands.length + " command(s), " + queries.length + " querie(s), exit " + last.exitCode;
19727
+ const summary = commands.length + " command(s), " + queries.length + " querie(s), exit " + last2.exitCode;
19584
19728
  const footer = "more: ctx_search({queries:[...], source:" + JSON.stringify(label) + "})";
19585
19729
  let notice;
19586
19730
  try {
19587
19731
  idx = indexCombined(db, ctx, label, ran, deadline, budgetBytes);
19588
- const stop = last.error;
19732
+ const stop = last2.error;
19589
19733
  const cut = idx.indexed < idx.total ? "Indexed " + idx.indexed + " of " + idx.total + " B." : null;
19590
19734
  const timeout = formatError("TIMEOUT", { ms: boundMs });
19591
19735
  const cause = stop ?? (ctx.signal.aborted ? CANCELLED_LINE : idx.stop === "deadline" ? timeout : null);
@@ -19603,7 +19747,7 @@ async function runBatch(input, ctx, boundMs, budgetBytes) {
19603
19747
  isError: false,
19604
19748
  // step 11
19605
19749
  sandboxBytes,
19606
- journal: { kind: "cmd", key: canonicalKey(TOOL, commands.join(LINE_SEP)), path: null, exit_code: last.exitCode }
19750
+ journal: { kind: "cmd", key: canonicalKey(TOOL, commands.join(LINE_SEP)), path: null, exit_code: last2.exitCode }
19607
19751
  };
19608
19752
  } catch (err) {
19609
19753
  if (err instanceof CtxError) return { text: err.toLine(), isError: true, sandboxBytes };
@@ -19627,305 +19771,2134 @@ import { basename as basename3, dirname as dirname6, join as join12 } from "node
19627
19771
  import { join as join10 } from "node:path";
19628
19772
 
19629
19773
  // src/core/ops/detect-v1.ts
19630
- import { existsSync as existsSync3, opendirSync, readdirSync, readFileSync as readFileSync6 } from "node:fs";
19774
+ import { existsSync as existsSync4, opendirSync, readdirSync, readFileSync as readFileSync7 } from "node:fs";
19631
19775
  import { tmpdir } from "node:os";
19632
- import { join as join7 } from "node:path";
19633
- var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
19634
- var keyPath = (...parts) => parts.join(".");
19635
- var finding = (file2, path4, reason) => ({ file: file2, path: path4, reason });
19636
- function stripJsonc(text) {
19637
- let out = "";
19638
- let inStr = false;
19639
- let esc2 = false;
19640
- for (let i = 0; i < text.length; i++) {
19641
- const c = text[i];
19642
- if (inStr) {
19643
- out += c;
19644
- if (esc2) esc2 = false;
19645
- else if (c === "\\") esc2 = true;
19646
- else if (c === '"') inStr = false;
19647
- continue;
19648
- }
19649
- if (c === '"') {
19650
- inStr = true;
19651
- out += c;
19652
- continue;
19653
- }
19654
- if (c === "/" && text[i + 1] === "/") {
19655
- while (i < text.length && text[i] !== "\n") i++;
19656
- out += "\n";
19657
- continue;
19658
- }
19659
- if (c === "/" && text[i + 1] === "*") {
19660
- const end = text.indexOf("*/", i + 2);
19661
- i = end === -1 ? text.length : end + 1;
19662
- continue;
19663
- }
19664
- if (c === ",") {
19665
- let j = i + 1;
19666
- while (j < text.length && " \r\n".includes(text[j])) j++;
19667
- if (text[j] === "}" || text[j] === "]") continue;
19776
+ import { join as join8 } from "node:path";
19777
+
19778
+ // src/core/ops/host-config.ts
19779
+ import { existsSync as existsSync3, readFileSync as readFileSync6 } from "node:fs";
19780
+ import { dirname as dirname4, join as join7 } from "node:path";
19781
+
19782
+ // node_modules/eslint-visitor-keys/lib/visitor-keys.js
19783
+ var KEYS2 = {
19784
+ ArrayExpression: ["elements"],
19785
+ ArrayPattern: ["elements"],
19786
+ ArrowFunctionExpression: ["params", "body"],
19787
+ AssignmentExpression: ["left", "right"],
19788
+ AssignmentPattern: ["left", "right"],
19789
+ AwaitExpression: ["argument"],
19790
+ BinaryExpression: ["left", "right"],
19791
+ BlockStatement: ["body"],
19792
+ BreakStatement: ["label"],
19793
+ CallExpression: ["callee", "arguments"],
19794
+ CatchClause: ["param", "body"],
19795
+ ChainExpression: ["expression"],
19796
+ ClassBody: ["body"],
19797
+ ClassDeclaration: ["id", "superClass", "body"],
19798
+ ClassExpression: ["id", "superClass", "body"],
19799
+ ConditionalExpression: ["test", "consequent", "alternate"],
19800
+ ContinueStatement: ["label"],
19801
+ DebuggerStatement: [],
19802
+ DoWhileStatement: ["body", "test"],
19803
+ EmptyStatement: [],
19804
+ ExperimentalRestProperty: ["argument"],
19805
+ ExperimentalSpreadProperty: ["argument"],
19806
+ ExportAllDeclaration: ["exported", "source", "attributes"],
19807
+ ExportDefaultDeclaration: ["declaration"],
19808
+ ExportNamedDeclaration: [
19809
+ "declaration",
19810
+ "specifiers",
19811
+ "source",
19812
+ "attributes"
19813
+ ],
19814
+ ExportSpecifier: ["local", "exported"],
19815
+ ExpressionStatement: ["expression"],
19816
+ ForInStatement: ["left", "right", "body"],
19817
+ ForOfStatement: ["left", "right", "body"],
19818
+ ForStatement: ["init", "test", "update", "body"],
19819
+ FunctionDeclaration: ["id", "params", "body"],
19820
+ FunctionExpression: ["id", "params", "body"],
19821
+ Identifier: [],
19822
+ IfStatement: ["test", "consequent", "alternate"],
19823
+ ImportAttribute: ["key", "value"],
19824
+ ImportDeclaration: ["specifiers", "source", "attributes"],
19825
+ ImportDefaultSpecifier: ["local"],
19826
+ ImportExpression: ["source", "options"],
19827
+ ImportNamespaceSpecifier: ["local"],
19828
+ ImportSpecifier: ["imported", "local"],
19829
+ JSXAttribute: ["name", "value"],
19830
+ JSXClosingElement: ["name"],
19831
+ JSXClosingFragment: [],
19832
+ JSXElement: ["openingElement", "children", "closingElement"],
19833
+ JSXEmptyExpression: [],
19834
+ JSXExpressionContainer: ["expression"],
19835
+ JSXFragment: ["openingFragment", "children", "closingFragment"],
19836
+ JSXIdentifier: [],
19837
+ JSXMemberExpression: ["object", "property"],
19838
+ JSXNamespacedName: ["namespace", "name"],
19839
+ JSXOpeningElement: ["name", "attributes"],
19840
+ JSXOpeningFragment: [],
19841
+ JSXSpreadAttribute: ["argument"],
19842
+ JSXSpreadChild: ["expression"],
19843
+ JSXText: [],
19844
+ LabeledStatement: ["label", "body"],
19845
+ Literal: [],
19846
+ LogicalExpression: ["left", "right"],
19847
+ MemberExpression: ["object", "property"],
19848
+ MetaProperty: ["meta", "property"],
19849
+ MethodDefinition: ["key", "value"],
19850
+ NewExpression: ["callee", "arguments"],
19851
+ ObjectExpression: ["properties"],
19852
+ ObjectPattern: ["properties"],
19853
+ PrivateIdentifier: [],
19854
+ Program: ["body"],
19855
+ Property: ["key", "value"],
19856
+ PropertyDefinition: ["key", "value"],
19857
+ RestElement: ["argument"],
19858
+ ReturnStatement: ["argument"],
19859
+ SequenceExpression: ["expressions"],
19860
+ SpreadElement: ["argument"],
19861
+ StaticBlock: ["body"],
19862
+ Super: [],
19863
+ SwitchCase: ["test", "consequent"],
19864
+ SwitchStatement: ["discriminant", "cases"],
19865
+ TaggedTemplateExpression: ["tag", "quasi"],
19866
+ TemplateElement: [],
19867
+ TemplateLiteral: ["quasis", "expressions"],
19868
+ ThisExpression: [],
19869
+ ThrowStatement: ["argument"],
19870
+ TryStatement: ["block", "handler", "finalizer"],
19871
+ UnaryExpression: ["argument"],
19872
+ UpdateExpression: ["argument"],
19873
+ VariableDeclaration: ["declarations"],
19874
+ VariableDeclarator: ["id", "init"],
19875
+ WhileStatement: ["test", "body"],
19876
+ WithStatement: ["object", "body"],
19877
+ YieldExpression: ["argument"]
19878
+ };
19879
+ var NODE_TYPES = Object.keys(KEYS2);
19880
+ for (const type of NODE_TYPES) {
19881
+ Object.freeze(KEYS2[type]);
19882
+ }
19883
+ Object.freeze(KEYS2);
19884
+ var visitor_keys_default = KEYS2;
19885
+
19886
+ // node_modules/eslint-visitor-keys/lib/index.js
19887
+ function unionWith(additionalKeys) {
19888
+ const retv = (
19889
+ /** @type {{ [type: string]: ReadonlyArray<string> }} */
19890
+ Object.assign({}, visitor_keys_default)
19891
+ );
19892
+ for (const type of Object.keys(additionalKeys)) {
19893
+ if (Object.hasOwn(retv, type)) {
19894
+ const keys = new Set(additionalKeys[type]);
19895
+ for (const key of retv[type]) {
19896
+ keys.add(key);
19897
+ }
19898
+ retv[type] = Object.freeze(Array.from(keys));
19899
+ } else {
19900
+ retv[type] = Object.freeze(Array.from(additionalKeys[type]));
19668
19901
  }
19669
- out += c;
19670
19902
  }
19671
- return out;
19903
+ return Object.freeze(retv);
19672
19904
  }
19673
- function readJson(file2) {
19674
- try {
19675
- return JSON.parse(stripJsonc(readFileSync6(file2, "utf8")));
19676
- } catch {
19677
- return void 0;
19678
- }
19905
+
19906
+ // node_modules/toml-eslint-parser/lib/index.mjs
19907
+ function last(arr) {
19908
+ return arr[arr.length - 1] ?? null;
19679
19909
  }
19680
- function readText(file2) {
19681
- try {
19682
- return readFileSync6(file2, "utf8");
19683
- } catch {
19684
- return "";
19685
- }
19910
+ function toKeyName(node) {
19911
+ return node.type === "TOMLBare" ? node.name : node.value;
19686
19912
  }
19687
- var listOf = (v) => Array.isArray(v) ? v : [];
19688
- var commandOf = (v) => isObj(v) && typeof v.command === "string" ? v.command : null;
19689
- function nestedCommands(doc) {
19690
- const out = [];
19691
- if (!isObj(doc) || !isObj(doc[HOOKS_KEY])) return out;
19692
- for (const [event, groups] of Object.entries(doc[HOOKS_KEY])) {
19693
- listOf(groups).forEach((group, i) => {
19694
- if (!isObj(group)) return;
19695
- listOf(group[HOOKS_KEY]).forEach((inner, j) => {
19696
- const command = commandOf(inner);
19697
- if (command !== null) out.push({ path: keyPath(HOOKS_KEY, event, i, HOOKS_KEY, j), command });
19698
- });
19699
- });
19913
+ var TOMLVerImpl = class {
19914
+ constructor(major, minor) {
19915
+ this.major = major;
19916
+ this.minor = minor;
19700
19917
  }
19701
- return out;
19702
- }
19703
- function flatCommands(events, prefix) {
19704
- const out = [];
19705
- if (!isObj(events)) return out;
19706
- for (const [event, entries] of Object.entries(events)) {
19707
- listOf(entries).forEach((entry, i) => {
19708
- const command = commandOf(entry);
19709
- if (command !== null) out.push({ path: keyPath(...prefix, event, i), command });
19710
- });
19918
+ lt(major, minor) {
19919
+ return this.major < major || this.major === major && this.minor < minor;
19711
19920
  }
19712
- return out;
19921
+ gte(major, minor) {
19922
+ return this.major > major || this.major === major && this.minor >= minor;
19923
+ }
19924
+ };
19925
+ var TOML_VERSION_1_0 = new TOMLVerImpl(1, 0);
19926
+ var TOML_VERSION_1_1 = new TOMLVerImpl(1, 1);
19927
+ var DEFAULT_TOML_VERSION = TOML_VERSION_1_1;
19928
+ var SUPPORTED_TOML_VERSIONS = {
19929
+ "1.0": TOML_VERSION_1_0,
19930
+ "1.0.0": TOML_VERSION_1_0,
19931
+ "1.1": TOML_VERSION_1_1,
19932
+ "1.1.0": TOML_VERSION_1_1,
19933
+ latest: TOML_VERSION_1_1,
19934
+ next: TOML_VERSION_1_1
19935
+ };
19936
+ function getTOMLVer(v) {
19937
+ return v && SUPPORTED_TOML_VERSIONS[v] || DEFAULT_TOML_VERSION;
19938
+ }
19939
+ var MESSAGES = {
19940
+ "unterminated-string": "Unterminated string constant",
19941
+ "unterminated-table-key": "Unterminated table-key",
19942
+ "unterminated-array": "Unterminated array",
19943
+ "unterminated-inline-table": "Unterminated inline table",
19944
+ "missing-key": "Empty bare keys are not allowed",
19945
+ "missing-newline": "Must be a newline",
19946
+ "missing-equals-sign": "Expected equal (=) token",
19947
+ "missing-value": "Unspecified values are invalid",
19948
+ "missing-comma": "Expected comma (,) token",
19949
+ "dupe-keys": "Defining a key multiple times is invalid",
19950
+ "unexpected-char": "Unexpected character",
19951
+ "unexpected-token": "Unexpected token",
19952
+ "invalid-control-character": "Control characters (codes < 0x1f and 0x7f) are not allowed",
19953
+ "invalid-comment-character": "Invalid code point {{cp}} within comments",
19954
+ "invalid-key-value-newline": "The key, equals sign, and value must be on the same line",
19955
+ "invalid-inline-table-newline": "No newlines are allowed between the curly braces unless they are valid within a value",
19956
+ "invalid-underscore": "Underscores are allowed between digits",
19957
+ "invalid-space": "Unexpected spaces",
19958
+ "invalid-three-quotes": "Three or more quotes are not permitted",
19959
+ "invalid-date": "Unexpected invalid date",
19960
+ "invalid-time": "Unexpected invalid time",
19961
+ "invalid-leading-zero": "Leading zeros are not allowed",
19962
+ "invalid-trailing-comma-in-inline-table": "Trailing comma is not permitted in an inline table",
19963
+ "invalid-char-in-escape-sequence": "Invalid character in escape sequence",
19964
+ "invalid-consecutive-dots-in-key": "Consecutive dots are not permitted in keys",
19965
+ "invalid-code-point": "Invalid code point {{cp}}",
19966
+ "invalid-trailing-dot-in-key": "Keys cannot end with a dot",
19967
+ "invalid-leading-dot-in-key": "Keys cannot start with a dot"
19968
+ };
19969
+ function getMessage(code, data) {
19970
+ if (data) return MESSAGES[code].replace(/\{\{(.*?)\}\}/gu, (_, name$2) => {
19971
+ if (name$2 in data) return data[name$2];
19972
+ return `{{${name$2}}}`;
19973
+ });
19974
+ return MESSAGES[code];
19975
+ }
19976
+ var ParseError = class extends SyntaxError {
19977
+ /**
19978
+ * Initialize this ParseError instance.
19979
+ *
19980
+ */
19981
+ constructor(code, offset, line, column, data) {
19982
+ super(getMessage(code, data));
19983
+ this.index = offset;
19984
+ this.lineNumber = line;
19985
+ this.column = column;
19986
+ }
19987
+ };
19988
+ var CodePoint = {
19989
+ EOF: -1,
19990
+ NULL: 0,
19991
+ SOH: 1,
19992
+ BACKSPACE: 8,
19993
+ TABULATION: 9,
19994
+ LINE_FEED: 10,
19995
+ FORM_FEED: 12,
19996
+ CARRIAGE_RETURN: 13,
19997
+ ESCAPE: 27,
19998
+ SO: 14,
19999
+ US: 31,
20000
+ SPACE: 32,
20001
+ QUOTATION_MARK: 34,
20002
+ HASH: 35,
20003
+ SINGLE_QUOTE: 39,
20004
+ PLUS_SIGN: 43,
20005
+ COMMA: 44,
20006
+ DASH: 45,
20007
+ DOT: 46,
20008
+ DIGIT_0: 48,
20009
+ DIGIT_1: 49,
20010
+ DIGIT_2: 50,
20011
+ DIGIT_3: 51,
20012
+ DIGIT_7: 55,
20013
+ DIGIT_9: 57,
20014
+ COLON: 58,
20015
+ EQUALS_SIGN: 61,
20016
+ LATIN_CAPITAL_A: 65,
20017
+ LATIN_CAPITAL_E: 69,
20018
+ LATIN_CAPITAL_F: 70,
20019
+ LATIN_CAPITAL_T: 84,
20020
+ LATIN_CAPITAL_U: 85,
20021
+ LATIN_CAPITAL_Z: 90,
20022
+ LEFT_BRACKET: 91,
20023
+ BACKSLASH: 92,
20024
+ RIGHT_BRACKET: 93,
20025
+ UNDERSCORE: 95,
20026
+ LATIN_SMALL_A: 97,
20027
+ LATIN_SMALL_B: 98,
20028
+ LATIN_SMALL_E: 101,
20029
+ LATIN_SMALL_F: 102,
20030
+ LATIN_SMALL_I: 105,
20031
+ LATIN_SMALL_L: 108,
20032
+ LATIN_SMALL_N: 110,
20033
+ LATIN_SMALL_O: 111,
20034
+ LATIN_SMALL_R: 114,
20035
+ LATIN_SMALL_S: 115,
20036
+ LATIN_SMALL_T: 116,
20037
+ LATIN_SMALL_U: 117,
20038
+ LATIN_SMALL_X: 120,
20039
+ LATIN_SMALL_Z: 122,
20040
+ LEFT_BRACE: 123,
20041
+ RIGHT_BRACE: 125,
20042
+ TILDE: 126,
20043
+ DELETE: 127,
20044
+ PAD: 128,
20045
+ SUPERSCRIPT_TWO: 178,
20046
+ SUPERSCRIPT_THREE: 179,
20047
+ SUPERSCRIPT_ONE: 185,
20048
+ VULGAR_FRACTION_ONE_QUARTER: 188,
20049
+ VULGAR_FRACTION_THREE_QUARTERS: 190,
20050
+ LATIN_CAPITAL_LETTER_A_WITH_GRAVE: 192,
20051
+ LATIN_CAPITAL_LETTER_O_WITH_DIAERESIS: 214,
20052
+ LATIN_CAPITAL_LETTER_O_WITH_STROKE: 216,
20053
+ LATIN_SMALL_LETTER_O_WITH_DIAERESIS: 246,
20054
+ LATIN_SMALL_LETTER_O_WITH_STROKE: 248,
20055
+ GREEK_SMALL_REVERSED_DOTTED_LUNATE_SIGMA_SYMBOL: 891,
20056
+ GREEK_CAPITAL_LETTER_YOT: 895,
20057
+ CP_1FFF: 8191,
20058
+ ZERO_WIDTH_NON_JOINER: 8204,
20059
+ ZERO_WIDTH_JOINER: 8205,
20060
+ UNDERTIE: 8255,
20061
+ CHARACTER_TIE: 8256,
20062
+ SUPERSCRIPT_ZERO: 8304,
20063
+ CP_218F: 8591,
20064
+ CIRCLED_DIGIT_ONE: 9312,
20065
+ NEGATIVE_CIRCLED_DIGIT_ZERO: 9471,
20066
+ GLAGOLITIC_CAPITAL_LETTER_AZU: 11264,
20067
+ CP_2FEF: 12271,
20068
+ IDEOGRAPHIC_COMMA: 12289,
20069
+ CP_D7FF: 55295,
20070
+ CP_E000: 57344,
20071
+ CJK_COMPATIBILITY_IDEOGRAPH_F900: 63744,
20072
+ ARABIC_LIGATURE_SALAAMUHU_ALAYNAA: 64975,
20073
+ ARABIC_LIGATURE_SALLA_USED_AS_KORANIC_STOP_SIGN_ISOLATED_FORM: 65008,
20074
+ REPLACEMENT_CHARACTER: 65533,
20075
+ LINEAR_B_SYLLABLE_B008_A: 65536,
20076
+ CP_EFFFF: 983039,
20077
+ CP_10FFFF: 1114111
20078
+ };
20079
+ function isControl(cp) {
20080
+ return cp >= CodePoint.NULL && cp <= CodePoint.US;
19713
20081
  }
19714
- var isV1Hook = (cmd) => cmd.includes(SERVER_KEY) && (V1_SCRIPT_NAMES.some((name) => cmd.includes(name)) || cmd.includes(V1_HOOK_COMMAND));
19715
- var isCodexScript = (cmd) => cmd.includes(V1_SCRIPT_EXT) && V1_PATH_SEPS.some((sep3) => cmd.includes(V1_CODEX_HOOKS_DIR.join(sep3) + sep3));
19716
- function dataDir(dir, reason, out) {
19717
- if (existsSync3(dir)) out.push(finding(dir, "", reason));
20082
+ function isWhitespace(cp) {
20083
+ return cp === CodePoint.TABULATION || cp === CodePoint.SPACE;
19718
20084
  }
19719
- function mcpEntry(file2, doc, out) {
19720
- if (isObj(doc) && isObj(doc[MCP_SERVERS_KEY]) && Object.hasOwn(doc[MCP_SERVERS_KEY], SERVER_KEY)) {
19721
- out.push(finding(file2, keyPath(MCP_SERVERS_KEY, SERVER_KEY), V1_REASON.mcpEntry));
19722
- }
20085
+ function isEOL(cp) {
20086
+ return cp === CodePoint.LINE_FEED || cp === CodePoint.CARRIAGE_RETURN;
19723
20087
  }
19724
- function claudeShapeSettings(agentHome, out) {
19725
- const file2 = join7(agentHome, SETTINGS_FILE);
19726
- const doc = readJson(file2);
19727
- for (const c of nestedCommands(doc)) {
19728
- if (c.command.includes(V1_CACHE_HEAL_NAME)) out.push(finding(file2, c.path, V1_REASON.cacheHealHook));
19729
- else if (isV1Hook(c.command)) out.push(finding(file2, c.path, V1_REASON.hook));
19730
- }
19731
- const status = isObj(doc) ? commandOf(doc[STATUS_LINE_KEY]) : null;
19732
- if (status !== null && status.includes(V1_STATUSLINE_COMMAND)) {
19733
- out.push(finding(file2, STATUS_LINE_KEY, V1_REASON.statusLine));
19734
- }
19735
- mcpEntry(file2, doc, out);
20088
+ function isUpperLetter(cp) {
20089
+ return cp >= CodePoint.LATIN_CAPITAL_A && cp <= CodePoint.LATIN_CAPITAL_Z;
19736
20090
  }
19737
- function v1HookFile(file2, out) {
19738
- const doc = readJson(file2);
19739
- const cmds = isObj(doc) ? flatCommands(doc[HOOKS_KEY], [HOOKS_KEY]) : [];
19740
- if (cmds.some((c) => c.command.includes(V1_HOOK_COMMAND))) out.push(finding(file2, "", V1_REASON.hookFile));
20091
+ function isLowerLetter(cp) {
20092
+ return cp >= CodePoint.LATIN_SMALL_A && cp <= CodePoint.LATIN_SMALL_Z;
19741
20093
  }
19742
- function scanClaudeCode(home, agentHome, out) {
19743
- claudeShapeSettings(agentHome, out);
19744
- for (const ext of V1_CACHE_HEAL_EXTS) {
19745
- const file2 = join7(agentHome, V1_HOOKS_DIR_NAME, V1_CACHE_HEAL_NAME + ext);
19746
- if (existsSync3(file2)) out.push(finding(file2, "", V1_REASON.cacheHealFile));
19747
- }
19748
- const userFile = join7(home, CLAUDE_USER_CONFIG_FILE);
19749
- mcpEntry(userFile, readJson(userFile), out);
19750
- dataDir(join7(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
20094
+ function isLetter2(cp) {
20095
+ return isLowerLetter(cp) || isUpperLetter(cp);
19751
20096
  }
19752
- function scanCodex(agentHome, out) {
19753
- const hooksFile = join7(agentHome, HOOKS_JSON_FILE);
19754
- for (const c of nestedCommands(readJson(hooksFile))) {
19755
- if (c.command.includes(V1_CODEX_HOOK_COMMAND) || isCodexScript(c.command)) {
19756
- out.push(finding(hooksFile, c.path, V1_REASON.codexHook));
19757
- }
19758
- }
19759
- const tomlFile = join7(agentHome, CONFIG_TOML_FILE);
19760
- for (const line of readText(tomlFile).split("\n")) {
19761
- const header = line.trim();
19762
- if (header.startsWith(V1_TOML_SECTION_PREFIX)) out.push(finding(tomlFile, header, V1_REASON.codexToml));
19763
- }
19764
- dataDir(join7(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
20097
+ function isDigit4(cp) {
20098
+ return cp >= CodePoint.DIGIT_0 && cp <= CodePoint.DIGIT_9;
19765
20099
  }
19766
- function scanGemini(agentHome, out) {
19767
- const file2 = join7(agentHome, SETTINGS_FILE);
19768
- for (const c of nestedCommands(readJson(file2))) {
19769
- if (c.command.includes(SERVER_KEY)) out.push(finding(file2, c.path, V1_REASON.hook));
19770
- }
19771
- dataDir(join7(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDirShared, out);
20100
+ function isHexDig(cp) {
20101
+ return isDigit4(cp) || cp >= CodePoint.LATIN_SMALL_A && cp <= CodePoint.LATIN_SMALL_F || cp >= CodePoint.LATIN_CAPITAL_A && cp <= CodePoint.LATIN_CAPITAL_F;
19772
20102
  }
19773
- function scanVscode(agentHome, project, out) {
19774
- if (project !== void 0) {
19775
- v1HookFile(join7(project, GITHUB_DIR_NAME, V1_HOOKS_DIR_NAME, OWN_HOOK_FILE), out);
19776
- const mcpFile2 = join7(project, VSCODE_DIR_NAME, VSCODE_MCP_FILE);
19777
- const doc = readJson(mcpFile2);
19778
- const servers = isObj(doc) && isObj(doc[VSCODE_MCP_SERVERS_KEY]) ? doc[VSCODE_MCP_SERVERS_KEY] : {};
19779
- const entry = Object.hasOwn(servers, SERVER_KEY) ? servers[SERVER_KEY] : void 0;
19780
- if (isObj(entry) && (entry.command === V1_BIN_COMMAND || listOf(entry.args).some((a) => a === V1_BIN_COMMAND))) {
19781
- out.push(finding(mcpFile2, keyPath(VSCODE_MCP_SERVERS_KEY, SERVER_KEY), V1_REASON.vscodeMcp));
19782
- }
19783
- dataDir(join7(project, GITHUB_DIR_NAME, V1_DATA_DIR_NAME, V1_SESSIONS_DIR_NAME), V1_REASON.dataDir, out);
19784
- }
19785
- dataDir(join7(agentHome, V1_DATA_DIR_NAME, V1_SESSIONS_DIR_NAME), V1_REASON.dataDir, out);
20103
+ function isOctalDig(cp) {
20104
+ return cp >= CodePoint.DIGIT_0 && cp <= CodePoint.DIGIT_7;
19786
20105
  }
19787
- function jsonFiles(dir) {
19788
- try {
19789
- return readdirSync(dir).filter((name) => name.endsWith(KIRO_AGENT_FILE_EXT)).sort();
19790
- } catch {
19791
- return [];
20106
+ function isUnicodeScalarValue(cp) {
20107
+ return cp >= 0 && cp <= 55295 || cp >= 57344 && cp <= 1114111;
20108
+ }
20109
+ function sortedLastIndex(array2, value) {
20110
+ let low = 0;
20111
+ let high = array2.length;
20112
+ while (low < high) {
20113
+ const mid = low + high >>> 1;
20114
+ const val = array2[mid];
20115
+ if (val === value) return mid + 1;
20116
+ if (val < value) low = mid + 1;
20117
+ else high = mid;
19792
20118
  }
20119
+ return low;
19793
20120
  }
19794
- function scanKiro(agentHome, project, out) {
19795
- const agentsDir = join7(agentHome, KIRO_AGENTS_DIR);
19796
- const defaultFile = join7(agentHome, ...KIRO_AGENT_FILE);
19797
- for (const name of jsonFiles(agentsDir)) {
19798
- const file2 = join7(agentsDir, name);
19799
- const doc = readJson(file2);
19800
- if (isObj(doc) && doc[KIRO_AGENT_NAME_KEY] === SERVER_KEY) {
19801
- out.push(finding(file2, "", V1_REASON.kiroAgentFile));
19802
- continue;
19803
- }
19804
- if (file2 !== defaultFile) continue;
19805
- for (const c of isObj(doc) ? flatCommands(doc[HOOKS_KEY], [HOOKS_KEY]) : []) {
19806
- if (isV1Hook(c.command)) out.push(finding(file2, c.path, V1_REASON.kiroHook));
20121
+ var Locations = class {
20122
+ constructor() {
20123
+ this.offsets = [];
20124
+ }
20125
+ addOffset(offset) {
20126
+ for (let i = this.offsets.length - 1; i >= 0; i--) {
20127
+ const element2 = this.offsets[i];
20128
+ if (element2 === offset) return;
20129
+ if (element2 < offset) break;
20130
+ }
20131
+ this.offsets.push(offset);
20132
+ }
20133
+ /**
20134
+ * Calculate the location of the given index.
20135
+ * @param index The index to calculate their location.
20136
+ * @returns The location of the index.
20137
+ */
20138
+ getLocFromIndex(offset) {
20139
+ const line = sortedLastIndex(this.offsets, offset) + 1;
20140
+ return {
20141
+ line,
20142
+ column: offset - (line === 1 ? 0 : this.offsets[line - 2])
20143
+ };
20144
+ }
20145
+ };
20146
+ var CodePointIterator = class {
20147
+ /**
20148
+ * Initialize this char iterator.
20149
+ */
20150
+ constructor(text) {
20151
+ this.locs = new Locations();
20152
+ this.lastCodePoint = CodePoint.NULL;
20153
+ this.start = -1;
20154
+ this.end = 0;
20155
+ this.text = text;
20156
+ }
20157
+ next() {
20158
+ if (this.lastCodePoint === CodePoint.EOF) return CodePoint.EOF;
20159
+ return this.lastCodePoint = this.moveAt(this.end);
20160
+ }
20161
+ getLocFromIndex(index) {
20162
+ return this.locs.getLocFromIndex(index);
20163
+ }
20164
+ eat(cp) {
20165
+ if (this.text.codePointAt(this.end) === cp) {
20166
+ this.next();
20167
+ return true;
19807
20168
  }
20169
+ return false;
19808
20170
  }
19809
- const steeringDocs = [join7(agentHome, ...KIRO_STEERING_FILE)];
19810
- if (project !== void 0) steeringDocs.push(join7(project, ...AGENT_HOME_DIR.kiro, ...KIRO_STEERING_FILE));
19811
- for (const file2 of steeringDocs) {
19812
- if (existsSync3(file2)) out.push(finding(file2, "", V1_REASON.kiroSteering));
20171
+ moveAt(offset) {
20172
+ this.start = this.end = offset;
20173
+ const cp = this.text.codePointAt(this.start) ?? CodePoint.EOF;
20174
+ if (cp === CodePoint.EOF) {
20175
+ this.end = this.start;
20176
+ return cp;
20177
+ }
20178
+ this.end += cp >= 65536 ? 2 : 1;
20179
+ if (cp === CodePoint.LINE_FEED) this.locs.addOffset(this.end);
20180
+ else if (cp === CodePoint.CARRIAGE_RETURN) {
20181
+ if (this.text.codePointAt(this.end) === CodePoint.LINE_FEED) {
20182
+ this.end++;
20183
+ this.locs.addOffset(this.end);
20184
+ }
20185
+ return CodePoint.LINE_FEED;
20186
+ }
20187
+ return cp;
19813
20188
  }
19814
- dataDir(join7(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
19815
- }
19816
- function scanPi(piAgentDir, agentHome, out) {
19817
- const file2 = join7(piAgentDir, SETTINGS_FILE);
19818
- const doc = readJson(file2);
19819
- listOf(isObj(doc) ? doc[PI_PACKAGES_KEY] : void 0).forEach((pkg, i) => {
19820
- const spec = isObj(pkg) ? pkg[PI_PACKAGE_SOURCE_KEY] : pkg;
19821
- if (spec === V1_PI_PACKAGE) out.push(finding(file2, keyPath(PI_PACKAGES_KEY, i), V1_REASON.piNpm));
19822
- });
19823
- dataDir(join7(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
19824
- }
19825
- function scanOpencode(agentHome, out) {
19826
- for (const name of OPENCODE_CONFIG_FILES) {
19827
- const file2 = join7(agentHome, name);
19828
- const doc = readJson(file2);
19829
- if (!isObj(doc) || !Array.isArray(doc[OPENCODE_PLUGIN_KEY])) continue;
19830
- doc[OPENCODE_PLUGIN_KEY].forEach((spec, i) => {
19831
- if (spec === V1_OPENCODE_PLUGIN_SPEC) out.push(finding(file2, keyPath(OPENCODE_PLUGIN_KEY, i), V1_REASON.opencodePlugin));
19832
- });
19833
- return;
20189
+ };
20190
+ var HAS_BIGINT = typeof BigInt !== "undefined";
20191
+ var RADIX_PREFIXES = {
20192
+ 16: "0x",
20193
+ 10: "",
20194
+ 8: "0o",
20195
+ 2: "0b"
20196
+ };
20197
+ var ESCAPES_1_0 = {
20198
+ [CodePoint.QUOTATION_MARK]: CodePoint.QUOTATION_MARK,
20199
+ [CodePoint.BACKSLASH]: CodePoint.BACKSLASH,
20200
+ [CodePoint.LATIN_SMALL_B]: CodePoint.BACKSPACE,
20201
+ [CodePoint.LATIN_SMALL_F]: CodePoint.FORM_FEED,
20202
+ [CodePoint.LATIN_SMALL_N]: CodePoint.LINE_FEED,
20203
+ [CodePoint.LATIN_SMALL_R]: CodePoint.CARRIAGE_RETURN,
20204
+ [CodePoint.LATIN_SMALL_T]: CodePoint.TABULATION
20205
+ };
20206
+ var ESCAPES_LATEST = {
20207
+ ...ESCAPES_1_0,
20208
+ [CodePoint.LATIN_SMALL_E]: CodePoint.ESCAPE
20209
+ };
20210
+ var Tokenizer = class {
20211
+ /**
20212
+ * Initialize this tokenizer.
20213
+ */
20214
+ constructor(text, parserOptions) {
20215
+ this.backCode = false;
20216
+ this.lastCodePoint = CodePoint.NULL;
20217
+ this.state = "DATA";
20218
+ this.token = null;
20219
+ this.tokenStart = -1;
20220
+ this.valuesEnabled = false;
20221
+ this.text = text;
20222
+ this.parserOptions = parserOptions || {};
20223
+ this.codePointIterator = new CodePointIterator(text);
20224
+ this.tomlVersion = getTOMLVer(this.parserOptions.tomlVersion);
20225
+ this.ESCAPES = this.tomlVersion.gte(1, 1) ? ESCAPES_LATEST : ESCAPES_1_0;
20226
+ }
20227
+ get start() {
20228
+ return this.codePointIterator.start;
20229
+ }
20230
+ get end() {
20231
+ return this.codePointIterator.end;
20232
+ }
20233
+ getLocFromIndex(index) {
20234
+ return this.codePointIterator.getLocFromIndex(index);
20235
+ }
20236
+ /**
20237
+ * Report an invalid character error.
20238
+ */
20239
+ reportParseError(code, data) {
20240
+ const offset = this.codePointIterator.start;
20241
+ const loc = this.codePointIterator.getLocFromIndex(offset);
20242
+ throw new ParseError(code, offset, loc.line, loc.column, data);
20243
+ }
20244
+ /**
20245
+ * Get the next token.
20246
+ */
20247
+ nextToken() {
20248
+ let token = this.token;
20249
+ if (token != null) {
20250
+ this.token = null;
20251
+ return token;
20252
+ }
20253
+ let cp = this.lastCodePoint;
20254
+ while (cp !== CodePoint.EOF && !this.token) {
20255
+ cp = this.nextCode();
20256
+ const nextState = this[this.state](cp);
20257
+ if (!nextState) throw new Error(`Unknown error: pre state=${this.state}`);
20258
+ this.state = nextState;
20259
+ }
20260
+ token = this.token;
20261
+ this.token = null;
20262
+ return token;
20263
+ }
20264
+ /**
20265
+ * Get the next code point.
20266
+ */
20267
+ nextCode() {
20268
+ if (this.lastCodePoint === CodePoint.EOF) return CodePoint.EOF;
20269
+ if (this.backCode) {
20270
+ this.backCode = false;
20271
+ return this.lastCodePoint;
20272
+ }
20273
+ return this.lastCodePoint = this.codePointIterator.next();
20274
+ }
20275
+ /**
20276
+ * Eat the next code point.
20277
+ */
20278
+ eatCode(cp) {
20279
+ if (this.lastCodePoint === CodePoint.EOF) return false;
20280
+ if (this.backCode) {
20281
+ if (this.lastCodePoint === cp) {
20282
+ this.backCode = false;
20283
+ return true;
20284
+ }
20285
+ return false;
20286
+ }
20287
+ return this.codePointIterator.eat(cp);
20288
+ }
20289
+ /**
20290
+ * Moves the character position to the given position.
20291
+ */
20292
+ moveAt(loc) {
20293
+ if (this.backCode) this.backCode = false;
20294
+ this.lastCodePoint = this.codePointIterator.moveAt(loc);
20295
+ }
20296
+ /**
20297
+ * Back the current code point as the given state.
20298
+ */
20299
+ back(state) {
20300
+ this.backCode = true;
20301
+ return state;
20302
+ }
20303
+ punctuatorToken() {
20304
+ this.startToken();
20305
+ this.endToken("Punctuator", "end");
20306
+ }
20307
+ startToken() {
20308
+ this.tokenStart = this.codePointIterator.start;
20309
+ }
20310
+ /**
20311
+ * Commit the current token.
20312
+ */
20313
+ endToken(type, pos, option1, option2) {
20314
+ const { tokenStart } = this;
20315
+ const end = this.codePointIterator[pos];
20316
+ const range = [tokenStart, end];
20317
+ const loc = {
20318
+ start: this.codePointIterator.getLocFromIndex(tokenStart),
20319
+ end: this.codePointIterator.getLocFromIndex(end)
20320
+ };
20321
+ if (type === "Block") this.token = {
20322
+ type,
20323
+ value: this.text.slice(tokenStart + 1, end),
20324
+ range,
20325
+ loc
20326
+ };
20327
+ else {
20328
+ let token;
20329
+ const value = this.text.slice(tokenStart, end);
20330
+ if (type === "BasicString" || type === "LiteralString" || type === "MultiLineBasicString" || type === "MultiLineLiteralString") token = {
20331
+ type,
20332
+ value,
20333
+ string: option1,
20334
+ range,
20335
+ loc
20336
+ };
20337
+ else if (type === "Integer") {
20338
+ const text = option1;
20339
+ token = {
20340
+ type,
20341
+ value,
20342
+ number: parseInt(text, option2),
20343
+ bigint: HAS_BIGINT ? BigInt(RADIX_PREFIXES[option2] + text) : null,
20344
+ range,
20345
+ loc
20346
+ };
20347
+ } else if (type === "Float") token = {
20348
+ type,
20349
+ value,
20350
+ number: option1,
20351
+ range,
20352
+ loc
20353
+ };
20354
+ else if (type === "Boolean") token = {
20355
+ type,
20356
+ value,
20357
+ boolean: option1,
20358
+ range,
20359
+ loc
20360
+ };
20361
+ else if (type === "LocalDate" || type === "LocalTime" || type === "LocalDateTime" || type === "OffsetDateTime") token = {
20362
+ type,
20363
+ value,
20364
+ date: option1,
20365
+ range,
20366
+ loc
20367
+ };
20368
+ else token = {
20369
+ type,
20370
+ value,
20371
+ range,
20372
+ loc
20373
+ };
20374
+ this.token = token;
20375
+ }
19834
20376
  }
19835
- }
19836
- function scanZcode(agentHome, out) {
19837
- const configFile = join7(agentHome, ZCODE_CLI_DIR, CONFIG_JSON_FILE);
19838
- const config2 = readJson(configFile);
19839
- const events = isObj(config2) && isObj(config2[HOOKS_KEY]) ? config2[HOOKS_KEY][ZCODE_EVENTS_KEY] : void 0;
19840
- for (const c of flatCommands(events, [HOOKS_KEY, ZCODE_EVENTS_KEY])) {
19841
- if (c.command.includes(V1_HOOK_COMMAND)) out.push(finding(configFile, c.path, V1_REASON.zcodeHook));
20377
+ DATA(cp) {
20378
+ while (isWhitespace(cp) || isEOL(cp)) cp = this.nextCode();
20379
+ if (cp === CodePoint.HASH) {
20380
+ this.startToken();
20381
+ return "COMMENT";
20382
+ }
20383
+ if (cp === CodePoint.QUOTATION_MARK) {
20384
+ this.startToken();
20385
+ return "BASIC_STRING";
20386
+ }
20387
+ if (cp === CodePoint.SINGLE_QUOTE) {
20388
+ this.startToken();
20389
+ return "LITERAL_STRING";
20390
+ }
20391
+ if (cp === CodePoint.DOT || cp === CodePoint.EQUALS_SIGN || cp === CodePoint.LEFT_BRACKET || cp === CodePoint.RIGHT_BRACKET || cp === CodePoint.LEFT_BRACE || cp === CodePoint.RIGHT_BRACE || cp === CodePoint.COMMA) {
20392
+ this.punctuatorToken();
20393
+ return "DATA";
20394
+ }
20395
+ if (this.valuesEnabled) {
20396
+ if (cp === CodePoint.DASH || cp === CodePoint.PLUS_SIGN) {
20397
+ this.startToken();
20398
+ return "SIGN";
20399
+ }
20400
+ if (cp === CodePoint.LATIN_SMALL_N || cp === CodePoint.LATIN_SMALL_I) {
20401
+ this.startToken();
20402
+ return this.back("NAN_OR_INF");
20403
+ }
20404
+ if (isDigit4(cp)) {
20405
+ this.startToken();
20406
+ return this.back("NUMBER");
20407
+ }
20408
+ if (cp === CodePoint.LATIN_SMALL_T || cp === CodePoint.LATIN_SMALL_F) {
20409
+ this.startToken();
20410
+ return this.back("BOOLEAN");
20411
+ }
20412
+ } else if (isUnquotedKeyChar(cp, this.tomlVersion)) {
20413
+ this.startToken();
20414
+ return "BARE";
20415
+ }
20416
+ if (cp === CodePoint.EOF) return "DATA";
20417
+ return this.reportParseError("unexpected-char");
19842
20418
  }
19843
- const hooksFile = join7(agentHome, ZCODE_CLI_DIR, HOOKS_JSON_FILE);
19844
- for (const c of nestedCommands(readJson(hooksFile))) {
19845
- if (c.command.includes(V1_HOOK_COMMAND)) out.push(finding(hooksFile, c.path, V1_REASON.zcodeHook));
20419
+ COMMENT(cp) {
20420
+ const processCommentChar = this.tomlVersion.gte(1, 1) ? (c) => {
20421
+ if (!isNonEOL(c)) this.reportParseError("invalid-comment-character", { cp: JSON.stringify(String.fromCodePoint(c)).slice(1, -1) });
20422
+ } : (c) => {
20423
+ if (isControlOtherThanTab(c)) this.reportParseErrorControlChar();
20424
+ };
20425
+ while (!isEOL(cp) && cp !== CodePoint.EOF) {
20426
+ processCommentChar(cp);
20427
+ cp = this.nextCode();
20428
+ }
20429
+ this.endToken("Block", "start");
20430
+ return "DATA";
19846
20431
  }
19847
- }
19848
- function firstTmpMatch(dir) {
19849
- let handle;
19850
- try {
19851
- handle = opendirSync(dir);
19852
- } catch {
19853
- return null;
20432
+ BARE(cp) {
20433
+ while (isUnquotedKeyChar(cp, this.tomlVersion)) cp = this.nextCode();
20434
+ this.endToken("Bare", "start");
20435
+ return this.back("DATA");
19854
20436
  }
19855
- try {
19856
- for (let e = handle.readSync(); e !== null; e = handle.readSync()) {
19857
- if (e.name.startsWith(V1_TMP_PREFIX)) return e.name;
20437
+ BASIC_STRING(cp) {
20438
+ if (cp === CodePoint.QUOTATION_MARK) {
20439
+ cp = this.nextCode();
20440
+ if (cp === CodePoint.QUOTATION_MARK) return "MULTI_LINE_BASIC_STRING";
20441
+ this.endToken("BasicString", "start", "");
20442
+ return this.back("DATA");
19858
20443
  }
19859
- return null;
19860
- } catch {
19861
- return null;
19862
- } finally {
19863
- handle.closeSync();
20444
+ const out = [];
20445
+ while (cp !== CodePoint.QUOTATION_MARK && cp !== CodePoint.EOF && cp !== CodePoint.LINE_FEED) {
20446
+ if (isControlOtherThanTab(cp)) return this.reportParseErrorControlChar();
20447
+ if (cp === CodePoint.BACKSLASH) {
20448
+ cp = this.nextCode();
20449
+ const ecp = this.ESCAPES[cp];
20450
+ if (ecp) {
20451
+ out.push(ecp);
20452
+ cp = this.nextCode();
20453
+ continue;
20454
+ } else if (cp === CodePoint.LATIN_SMALL_U) {
20455
+ const code = this.parseUnicode(4);
20456
+ out.push(code);
20457
+ cp = this.nextCode();
20458
+ continue;
20459
+ } else if (cp === CodePoint.LATIN_CAPITAL_U) {
20460
+ const code = this.parseUnicode(8);
20461
+ out.push(code);
20462
+ cp = this.nextCode();
20463
+ continue;
20464
+ } else if (cp === CodePoint.LATIN_SMALL_X && this.tomlVersion.gte(1, 1)) {
20465
+ const code = this.parseUnicode(2);
20466
+ out.push(code);
20467
+ cp = this.nextCode();
20468
+ continue;
20469
+ }
20470
+ return this.reportParseError("invalid-char-in-escape-sequence");
20471
+ }
20472
+ out.push(cp);
20473
+ cp = this.nextCode();
20474
+ }
20475
+ if (cp !== CodePoint.QUOTATION_MARK) return this.reportParseError("unterminated-string");
20476
+ this.endToken("BasicString", "end", String.fromCodePoint(...out));
20477
+ return "DATA";
20478
+ }
20479
+ MULTI_LINE_BASIC_STRING(cp) {
20480
+ const out = [];
20481
+ if (cp === CodePoint.LINE_FEED) cp = this.nextCode();
20482
+ while (cp !== CodePoint.EOF) {
20483
+ if (cp !== CodePoint.LINE_FEED && isControlOtherThanTab(cp)) return this.reportParseErrorControlChar();
20484
+ if (cp === CodePoint.QUOTATION_MARK) {
20485
+ const startPos = this.codePointIterator.start;
20486
+ if (this.eatCode(CodePoint.QUOTATION_MARK) && this.eatCode(CodePoint.QUOTATION_MARK)) {
20487
+ if (this.eatCode(CodePoint.QUOTATION_MARK)) {
20488
+ out.push(CodePoint.QUOTATION_MARK);
20489
+ if (this.eatCode(CodePoint.QUOTATION_MARK)) {
20490
+ out.push(CodePoint.QUOTATION_MARK);
20491
+ if (this.eatCode(CodePoint.QUOTATION_MARK)) {
20492
+ this.moveAt(startPos);
20493
+ return this.reportParseError("invalid-three-quotes");
20494
+ }
20495
+ }
20496
+ }
20497
+ this.endToken("MultiLineBasicString", "end", String.fromCodePoint(...out));
20498
+ return "DATA";
20499
+ }
20500
+ this.moveAt(startPos);
20501
+ }
20502
+ if (cp === CodePoint.BACKSLASH) {
20503
+ cp = this.nextCode();
20504
+ const ecp = this.ESCAPES[cp];
20505
+ if (ecp) {
20506
+ out.push(ecp);
20507
+ cp = this.nextCode();
20508
+ continue;
20509
+ } else if (cp === CodePoint.LATIN_SMALL_U) {
20510
+ const code = this.parseUnicode(4);
20511
+ out.push(code);
20512
+ cp = this.nextCode();
20513
+ continue;
20514
+ } else if (cp === CodePoint.LATIN_CAPITAL_U) {
20515
+ const code = this.parseUnicode(8);
20516
+ out.push(code);
20517
+ cp = this.nextCode();
20518
+ continue;
20519
+ } else if (cp === CodePoint.LATIN_SMALL_X && this.tomlVersion.gte(1, 1)) {
20520
+ const code = this.parseUnicode(2);
20521
+ out.push(code);
20522
+ cp = this.nextCode();
20523
+ continue;
20524
+ } else if (cp === CodePoint.LINE_FEED) {
20525
+ cp = this.nextCode();
20526
+ while (isWhitespace(cp) || cp === CodePoint.LINE_FEED) cp = this.nextCode();
20527
+ continue;
20528
+ } else if (isWhitespace(cp)) {
20529
+ let valid = true;
20530
+ const startPos = this.codePointIterator.start;
20531
+ let nextCp;
20532
+ while ((nextCp = this.nextCode()) !== CodePoint.EOF) {
20533
+ if (nextCp === CodePoint.LINE_FEED) break;
20534
+ if (!isWhitespace(nextCp)) {
20535
+ this.moveAt(startPos);
20536
+ valid = false;
20537
+ break;
20538
+ }
20539
+ }
20540
+ if (valid) {
20541
+ cp = this.nextCode();
20542
+ while (isWhitespace(cp) || cp === CodePoint.LINE_FEED) cp = this.nextCode();
20543
+ continue;
20544
+ }
20545
+ }
20546
+ return this.reportParseError("invalid-char-in-escape-sequence");
20547
+ }
20548
+ out.push(cp);
20549
+ cp = this.nextCode();
20550
+ }
20551
+ return this.reportParseError("unterminated-string");
20552
+ }
20553
+ LITERAL_STRING(cp) {
20554
+ if (cp === CodePoint.SINGLE_QUOTE) {
20555
+ cp = this.nextCode();
20556
+ if (cp === CodePoint.SINGLE_QUOTE) return "MULTI_LINE_LITERAL_STRING";
20557
+ this.endToken("LiteralString", "start", "");
20558
+ return this.back("DATA");
20559
+ }
20560
+ const out = [];
20561
+ while (cp !== CodePoint.SINGLE_QUOTE && cp !== CodePoint.EOF && cp !== CodePoint.LINE_FEED) {
20562
+ if (isControlOtherThanTab(cp)) return this.reportParseErrorControlChar();
20563
+ out.push(cp);
20564
+ cp = this.nextCode();
20565
+ }
20566
+ if (cp !== CodePoint.SINGLE_QUOTE) return this.reportParseError("unterminated-string");
20567
+ this.endToken("LiteralString", "end", String.fromCodePoint(...out));
20568
+ return "DATA";
19864
20569
  }
20570
+ MULTI_LINE_LITERAL_STRING(cp) {
20571
+ const out = [];
20572
+ if (cp === CodePoint.LINE_FEED) cp = this.nextCode();
20573
+ while (cp !== CodePoint.EOF) {
20574
+ if (cp !== CodePoint.LINE_FEED && isControlOtherThanTab(cp)) return this.reportParseErrorControlChar();
20575
+ if (cp === CodePoint.SINGLE_QUOTE) {
20576
+ const startPos = this.codePointIterator.start;
20577
+ if (this.eatCode(CodePoint.SINGLE_QUOTE) && this.eatCode(CodePoint.SINGLE_QUOTE)) {
20578
+ if (this.eatCode(CodePoint.SINGLE_QUOTE)) {
20579
+ out.push(CodePoint.SINGLE_QUOTE);
20580
+ if (this.eatCode(CodePoint.SINGLE_QUOTE)) {
20581
+ out.push(CodePoint.SINGLE_QUOTE);
20582
+ if (this.eatCode(CodePoint.SINGLE_QUOTE)) {
20583
+ this.moveAt(startPos);
20584
+ return this.reportParseError("invalid-three-quotes");
20585
+ }
20586
+ }
20587
+ }
20588
+ this.endToken("MultiLineLiteralString", "end", String.fromCodePoint(...out));
20589
+ return "DATA";
20590
+ }
20591
+ this.moveAt(startPos);
20592
+ }
20593
+ out.push(cp);
20594
+ cp = this.nextCode();
20595
+ }
20596
+ return this.reportParseError("unterminated-string");
20597
+ }
20598
+ SIGN(cp) {
20599
+ if (cp === CodePoint.LATIN_SMALL_N || cp === CodePoint.LATIN_SMALL_I) return this.back("NAN_OR_INF");
20600
+ if (isDigit4(cp)) return this.back("NUMBER");
20601
+ return this.reportParseError("unexpected-char");
20602
+ }
20603
+ NAN_OR_INF(cp) {
20604
+ if (cp === CodePoint.LATIN_SMALL_N) {
20605
+ const startPos = this.codePointIterator.start;
20606
+ if (this.eatCode(CodePoint.LATIN_SMALL_A) && this.eatCode(CodePoint.LATIN_SMALL_N)) {
20607
+ this.endToken("Float", "end", NaN);
20608
+ return "DATA";
20609
+ }
20610
+ this.moveAt(startPos);
20611
+ } else if (cp === CodePoint.LATIN_SMALL_I) {
20612
+ const startPos = this.codePointIterator.start;
20613
+ if (this.eatCode(CodePoint.LATIN_SMALL_N) && this.eatCode(CodePoint.LATIN_SMALL_F)) {
20614
+ this.endToken("Float", "end", this.text[this.tokenStart] === "-" ? -Infinity : Infinity);
20615
+ return "DATA";
20616
+ }
20617
+ this.moveAt(startPos);
20618
+ }
20619
+ return this.reportParseError("unexpected-char");
20620
+ }
20621
+ NUMBER(cp) {
20622
+ const start = this.text[this.tokenStart];
20623
+ const sign = start === "+" ? CodePoint.PLUS_SIGN : start === "-" ? CodePoint.DASH : CodePoint.NULL;
20624
+ if (cp === CodePoint.DIGIT_0) {
20625
+ if (sign === CodePoint.NULL) {
20626
+ const startPos = this.codePointIterator.start;
20627
+ const nextCp$1 = this.nextCode();
20628
+ if (isDigit4(nextCp$1)) {
20629
+ const nextNextCp = this.nextCode();
20630
+ if (nextNextCp === CodePoint.COLON) {
20631
+ this.data = {
20632
+ hasDate: false,
20633
+ year: 0,
20634
+ month: 0,
20635
+ day: 0,
20636
+ hour: Number(String.fromCodePoint(CodePoint.DIGIT_0, nextCp$1)),
20637
+ minute: 0,
20638
+ second: 0
20639
+ };
20640
+ return "TIME_MINUTE";
20641
+ }
20642
+ if (isDigit4(nextNextCp)) {
20643
+ const nextNextNextCp = this.nextCode();
20644
+ if (isDigit4(nextNextNextCp) && this.eatCode(CodePoint.DASH)) {
20645
+ this.data = {
20646
+ hasDate: true,
20647
+ year: Number(String.fromCodePoint(CodePoint.DIGIT_0, nextCp$1, nextNextCp, nextNextNextCp)),
20648
+ month: 0,
20649
+ day: 0,
20650
+ hour: 0,
20651
+ minute: 0,
20652
+ second: 0
20653
+ };
20654
+ return "DATE_MONTH";
20655
+ }
20656
+ }
20657
+ this.moveAt(startPos);
20658
+ return this.reportParseError("invalid-leading-zero");
20659
+ }
20660
+ this.moveAt(startPos);
20661
+ }
20662
+ cp = this.nextCode();
20663
+ if (cp === CodePoint.LATIN_SMALL_X || cp === CodePoint.LATIN_SMALL_O || cp === CodePoint.LATIN_SMALL_B) {
20664
+ if (sign !== CodePoint.NULL) return this.reportParseError("unexpected-char");
20665
+ return cp === CodePoint.LATIN_SMALL_X ? "HEX" : cp === CodePoint.LATIN_SMALL_O ? "OCTAL" : "BINARY";
20666
+ }
20667
+ if (cp === CodePoint.LATIN_SMALL_E || cp === CodePoint.LATIN_CAPITAL_E) {
20668
+ this.data = {
20669
+ minus: sign === CodePoint.DASH,
20670
+ left: [CodePoint.DIGIT_0]
20671
+ };
20672
+ return "EXPONENT_RIGHT";
20673
+ }
20674
+ if (cp === CodePoint.DOT) {
20675
+ this.data = {
20676
+ minus: sign === CodePoint.DASH,
20677
+ absInt: [CodePoint.DIGIT_0]
20678
+ };
20679
+ return "FRACTIONAL_RIGHT";
20680
+ }
20681
+ this.endToken("Integer", "start", "0", 10);
20682
+ return this.back("DATA");
20683
+ }
20684
+ const { out, nextCp, hasUnderscore } = this.parseDigits(cp, isDigit4);
20685
+ if (nextCp === CodePoint.DASH && sign === CodePoint.NULL && !hasUnderscore && out.length === 4) {
20686
+ this.data = {
20687
+ hasDate: true,
20688
+ year: Number(String.fromCodePoint(...out)),
20689
+ month: 0,
20690
+ day: 0,
20691
+ hour: 0,
20692
+ minute: 0,
20693
+ second: 0
20694
+ };
20695
+ return "DATE_MONTH";
20696
+ }
20697
+ if (nextCp === CodePoint.COLON && sign === CodePoint.NULL && !hasUnderscore && out.length === 2) {
20698
+ this.data = {
20699
+ hasDate: false,
20700
+ year: 0,
20701
+ month: 0,
20702
+ day: 0,
20703
+ hour: Number(String.fromCodePoint(...out)),
20704
+ minute: 0,
20705
+ second: 0
20706
+ };
20707
+ return "TIME_MINUTE";
20708
+ }
20709
+ if (nextCp === CodePoint.LATIN_SMALL_E || nextCp === CodePoint.LATIN_CAPITAL_E) {
20710
+ this.data = {
20711
+ minus: sign === CodePoint.DASH,
20712
+ left: out
20713
+ };
20714
+ return "EXPONENT_RIGHT";
20715
+ }
20716
+ if (nextCp === CodePoint.DOT) {
20717
+ this.data = {
20718
+ minus: sign === CodePoint.DASH,
20719
+ absInt: out
20720
+ };
20721
+ return "FRACTIONAL_RIGHT";
20722
+ }
20723
+ this.endToken("Integer", "start", sign === CodePoint.DASH ? String.fromCodePoint(CodePoint.DASH, ...out) : String.fromCodePoint(...out), 10);
20724
+ return this.back("DATA");
20725
+ }
20726
+ HEX(cp) {
20727
+ const { out } = this.parseDigits(cp, isHexDig);
20728
+ this.endToken("Integer", "start", String.fromCodePoint(...out), 16);
20729
+ return this.back("DATA");
20730
+ }
20731
+ OCTAL(cp) {
20732
+ const { out } = this.parseDigits(cp, isOctalDig);
20733
+ this.endToken("Integer", "start", String.fromCodePoint(...out), 8);
20734
+ return this.back("DATA");
20735
+ }
20736
+ BINARY(cp) {
20737
+ const { out } = this.parseDigits(cp, (c) => c === CodePoint.DIGIT_0 || c === CodePoint.DIGIT_1);
20738
+ this.endToken("Integer", "start", String.fromCodePoint(...out), 2);
20739
+ return this.back("DATA");
20740
+ }
20741
+ FRACTIONAL_RIGHT(cp) {
20742
+ const { minus, absInt } = this.data;
20743
+ const { out, nextCp } = this.parseDigits(cp, isDigit4);
20744
+ const absNum = [
20745
+ ...absInt,
20746
+ CodePoint.DOT,
20747
+ ...out
20748
+ ];
20749
+ if (nextCp === CodePoint.LATIN_SMALL_E || nextCp === CodePoint.LATIN_CAPITAL_E) {
20750
+ this.data = {
20751
+ minus,
20752
+ left: absNum
20753
+ };
20754
+ return "EXPONENT_RIGHT";
20755
+ }
20756
+ const value = Number(minus ? String.fromCodePoint(CodePoint.DASH, ...absNum) : String.fromCodePoint(...absNum));
20757
+ this.endToken("Float", "start", value);
20758
+ return this.back("DATA");
20759
+ }
20760
+ EXPONENT_RIGHT(cp) {
20761
+ const { left, minus: leftMinus } = this.data;
20762
+ let minus = false;
20763
+ if (cp === CodePoint.DASH || cp === CodePoint.PLUS_SIGN) {
20764
+ minus = cp === CodePoint.DASH;
20765
+ cp = this.nextCode();
20766
+ }
20767
+ const { out } = this.parseDigits(cp, isDigit4);
20768
+ const right = out;
20769
+ if (minus) right.unshift(CodePoint.DASH);
20770
+ const value = Number(leftMinus ? String.fromCodePoint(CodePoint.DASH, ...left, CodePoint.LATIN_SMALL_E, ...right) : String.fromCodePoint(...left, CodePoint.LATIN_SMALL_E, ...right));
20771
+ this.endToken("Float", "start", value);
20772
+ return this.back("DATA");
20773
+ }
20774
+ BOOLEAN(cp) {
20775
+ if (cp === CodePoint.LATIN_SMALL_T) {
20776
+ const startPos = this.codePointIterator.start;
20777
+ if (this.eatCode(CodePoint.LATIN_SMALL_R) && this.eatCode(CodePoint.LATIN_SMALL_U) && this.eatCode(CodePoint.LATIN_SMALL_E)) {
20778
+ this.endToken("Boolean", "end", true);
20779
+ return "DATA";
20780
+ }
20781
+ this.moveAt(startPos);
20782
+ } else if (cp === CodePoint.LATIN_SMALL_F) {
20783
+ const startPos = this.codePointIterator.start;
20784
+ if (this.eatCode(CodePoint.LATIN_SMALL_A) && this.eatCode(CodePoint.LATIN_SMALL_L) && this.eatCode(CodePoint.LATIN_SMALL_S) && this.eatCode(CodePoint.LATIN_SMALL_E)) {
20785
+ this.endToken("Boolean", "end", false);
20786
+ return "DATA";
20787
+ }
20788
+ this.moveAt(startPos);
20789
+ }
20790
+ return this.reportParseError("unexpected-char");
20791
+ }
20792
+ DATE_MONTH(cp) {
20793
+ const start = this.codePointIterator.start;
20794
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20795
+ cp = this.nextCode();
20796
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20797
+ cp = this.nextCode();
20798
+ if (cp !== CodePoint.DASH) return this.reportParseError("unexpected-char");
20799
+ const end = this.codePointIterator.start;
20800
+ const data = this.data;
20801
+ data.month = Number(this.text.slice(start, end));
20802
+ return "DATE_DAY";
20803
+ }
20804
+ DATE_DAY(cp) {
20805
+ const start = this.codePointIterator.start;
20806
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20807
+ cp = this.nextCode();
20808
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20809
+ const end = this.codePointIterator.end;
20810
+ const data = this.data;
20811
+ data.day = Number(this.text.slice(start, end));
20812
+ if (!isValidDate(data.year, data.month, data.day)) return this.reportParseError("invalid-date");
20813
+ cp = this.nextCode();
20814
+ if (cp === CodePoint.LATIN_CAPITAL_T || cp === CodePoint.LATIN_SMALL_T) return "TIME_HOUR";
20815
+ if (cp === CodePoint.SPACE) {
20816
+ const startPos = this.codePointIterator.start;
20817
+ if (isDigit4(this.nextCode()) && isDigit4(this.nextCode())) {
20818
+ this.moveAt(startPos);
20819
+ return "TIME_HOUR";
20820
+ }
20821
+ this.moveAt(startPos);
20822
+ }
20823
+ const dateValue = getDateFromDateTimeData(data, "");
20824
+ this.endToken("LocalDate", "start", dateValue);
20825
+ return this.back("DATA");
20826
+ }
20827
+ TIME_HOUR(cp) {
20828
+ const start = this.codePointIterator.start;
20829
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20830
+ cp = this.nextCode();
20831
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20832
+ cp = this.nextCode();
20833
+ if (cp !== CodePoint.COLON) return this.reportParseError("unexpected-char");
20834
+ const end = this.codePointIterator.start;
20835
+ const data = this.data;
20836
+ data.hour = Number(this.text.slice(start, end));
20837
+ return "TIME_MINUTE";
20838
+ }
20839
+ TIME_MINUTE(cp) {
20840
+ const start = this.codePointIterator.start;
20841
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20842
+ cp = this.nextCode();
20843
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20844
+ const end = this.codePointIterator.end;
20845
+ const data = this.data;
20846
+ data.minute = Number(this.text.slice(start, end));
20847
+ cp = this.nextCode();
20848
+ if (cp === CodePoint.COLON) return "TIME_SECOND";
20849
+ if (this.tomlVersion.lt(1, 1)) return this.reportParseError("unexpected-char");
20850
+ if (!isValidTime(data.hour, data.minute, data.second)) return this.reportParseError("invalid-time");
20851
+ return this.processTimeEnd(cp, data);
20852
+ }
20853
+ TIME_SECOND(cp) {
20854
+ const start = this.codePointIterator.start;
20855
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20856
+ cp = this.nextCode();
20857
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20858
+ const end = this.codePointIterator.end;
20859
+ const data = this.data;
20860
+ data.second = Number(this.text.slice(start, end));
20861
+ if (!isValidTime(data.hour, data.minute, data.second)) return this.reportParseError("invalid-time");
20862
+ cp = this.nextCode();
20863
+ if (cp === CodePoint.DOT) return "TIME_SEC_FRAC";
20864
+ return this.processTimeEnd(cp, data);
20865
+ }
20866
+ TIME_SEC_FRAC(cp) {
20867
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20868
+ const start = this.codePointIterator.start;
20869
+ while (isDigit4(cp)) cp = this.nextCode();
20870
+ const end = this.codePointIterator.start;
20871
+ const data = this.data;
20872
+ data.frac = this.text.slice(start, end);
20873
+ return this.processTimeEnd(cp, data);
20874
+ }
20875
+ processTimeEnd(cp, data) {
20876
+ if (data.hasDate) {
20877
+ if (cp === CodePoint.DASH || cp === CodePoint.PLUS_SIGN) {
20878
+ data.offsetSign = cp;
20879
+ return "TIME_OFFSET";
20880
+ }
20881
+ if (cp === CodePoint.LATIN_CAPITAL_Z || cp === CodePoint.LATIN_SMALL_Z) {
20882
+ const dateValue$2 = getDateFromDateTimeData(data, "Z");
20883
+ this.endToken("OffsetDateTime", "end", dateValue$2);
20884
+ return "DATA";
20885
+ }
20886
+ const dateValue$1 = getDateFromDateTimeData(data, "");
20887
+ this.endToken("LocalDateTime", "start", dateValue$1);
20888
+ return this.back("DATA");
20889
+ }
20890
+ const dateValue = getDateFromDateTimeData(data, "");
20891
+ this.endToken("LocalTime", "start", dateValue);
20892
+ return this.back("DATA");
20893
+ }
20894
+ TIME_OFFSET(cp) {
20895
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20896
+ const hourStart = this.codePointIterator.start;
20897
+ cp = this.nextCode();
20898
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20899
+ cp = this.nextCode();
20900
+ if (cp !== CodePoint.COLON) return this.reportParseError("unexpected-char");
20901
+ const hourEnd = this.codePointIterator.start;
20902
+ cp = this.nextCode();
20903
+ const minuteStart = this.codePointIterator.start;
20904
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20905
+ cp = this.nextCode();
20906
+ if (!isDigit4(cp)) return this.reportParseError("unexpected-char");
20907
+ const minuteEnd = this.codePointIterator.end;
20908
+ const hour = Number(this.text.slice(hourStart, hourEnd));
20909
+ const minute = Number(this.text.slice(minuteStart, minuteEnd));
20910
+ if (!isValidTime(hour, minute, 0)) return this.reportParseError("invalid-time");
20911
+ const data = this.data;
20912
+ const dateValue = getDateFromDateTimeData(data, `${String.fromCodePoint(data.offsetSign)}${padStart(hour, 2)}:${padStart(minute, 2)}`);
20913
+ this.endToken("OffsetDateTime", "end", dateValue);
20914
+ return "DATA";
20915
+ }
20916
+ parseDigits(cp, checkDigit) {
20917
+ if (cp === CodePoint.UNDERSCORE) return this.reportParseError("invalid-underscore");
20918
+ if (!checkDigit(cp)) return this.reportParseError("unexpected-char");
20919
+ const out = [];
20920
+ let before = CodePoint.NULL;
20921
+ let hasUnderscore = false;
20922
+ while (checkDigit(cp) || cp === CodePoint.UNDERSCORE) {
20923
+ if (cp === CodePoint.UNDERSCORE) {
20924
+ hasUnderscore = true;
20925
+ if (before === CodePoint.UNDERSCORE) return this.reportParseError("invalid-underscore");
20926
+ } else out.push(cp);
20927
+ before = cp;
20928
+ cp = this.nextCode();
20929
+ }
20930
+ if (before === CodePoint.UNDERSCORE) return this.reportParseError("invalid-underscore");
20931
+ return {
20932
+ out,
20933
+ nextCp: cp,
20934
+ hasUnderscore
20935
+ };
20936
+ }
20937
+ parseUnicode(count) {
20938
+ const startLoc = this.codePointIterator.start;
20939
+ const start = this.codePointIterator.end;
20940
+ let charCount = 0;
20941
+ let cp;
20942
+ while ((cp = this.nextCode()) !== CodePoint.EOF) {
20943
+ if (!isHexDig(cp)) {
20944
+ this.moveAt(startLoc);
20945
+ return this.reportParseError("invalid-char-in-escape-sequence");
20946
+ }
20947
+ charCount++;
20948
+ if (charCount >= count) break;
20949
+ }
20950
+ const end = this.codePointIterator.end;
20951
+ const code = this.text.slice(start, end);
20952
+ const codePoint = parseInt(code, 16);
20953
+ if (!isUnicodeScalarValue(codePoint)) return this.reportParseError("invalid-code-point", { cp: code });
20954
+ return codePoint;
20955
+ }
20956
+ reportParseErrorControlChar() {
20957
+ return this.reportParseError("invalid-control-character");
20958
+ }
20959
+ };
20960
+ function isUnquotedKeyChar(cp, tomlVersion) {
20961
+ if (isLetter2(cp) || isDigit4(cp) || cp === CodePoint.UNDERSCORE || cp === CodePoint.DASH) return true;
20962
+ if (tomlVersion.lt(1, 1)) return false;
20963
+ return false;
19865
20964
  }
19866
- function scanAll(home, tmp, out) {
19867
- const root = join7(home, DATA_ROOT.slice(1));
19868
- for (const name of V1_DATA_ROOT_ENTRIES) dataDir(join7(root, name), V1_REASON.dataRoot, out);
19869
- if (firstTmpMatch(tmp) !== null) out.push(finding(tmp, V1_TMP_PREFIX + "*", V1_REASON.tmpFile));
20965
+ function isControlOtherThanTab(cp) {
20966
+ return isControl(cp) && cp !== CodePoint.TABULATION || cp === CodePoint.DELETE;
19870
20967
  }
19871
- function detectV1(agent, home, scope = {}) {
19872
- const out = [];
19873
- const project = scope.project;
19874
- const agentHome = join7(home, ...AGENT_HOME_DIR[agent]);
19875
- switch (agent) {
19876
- case "claude-code":
19877
- scanClaudeCode(home, agentHome, out);
19878
- break;
19879
- case "codex":
19880
- scanCodex(agentHome, out);
19881
- break;
19882
- case "gemini":
19883
- scanGemini(agentHome, out);
19884
- break;
19885
- case "qwen":
19886
- claudeShapeSettings(agentHome, out);
19887
- dataDir(join7(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
19888
- break;
19889
- case "copilot-cli":
19890
- v1HookFile(join7(agentHome, V1_HOOKS_DIR_NAME, OWN_HOOK_FILE), out);
19891
- dataDir(join7(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
19892
- break;
19893
- case "vscode":
19894
- scanVscode(agentHome, project, out);
19895
- break;
19896
- case "kiro":
19897
- scanKiro(agentHome, project, out);
19898
- break;
19899
- case "pi":
19900
- scanPi(scope.piAgentDir ?? join7(agentHome, PI_AGENT_DIR), agentHome, out);
19901
- break;
19902
- case "opencode":
19903
- scanOpencode(agentHome, out);
19904
- break;
19905
- case "zcode":
19906
- scanZcode(agentHome, out);
19907
- break;
20968
+ function isNonEOL(cp) {
20969
+ return cp === CodePoint.TABULATION || CodePoint.SPACE <= cp && cp <= CodePoint.TILDE || isNonAscii(cp);
20970
+ }
20971
+ function isNonAscii(cp) {
20972
+ return CodePoint.PAD <= cp && cp <= CodePoint.CP_D7FF || CodePoint.CP_E000 <= cp && cp <= CodePoint.CP_10FFFF;
20973
+ }
20974
+ function isValidDate(y, m, d) {
20975
+ if (y >= 0 && m <= 12 && m >= 1 && d >= 1) return d <= (m === 2 ? y & 3 || !(y % 25) && y & 15 ? 28 : 29 : 30 + (m + (m >> 3) & 1));
20976
+ return false;
20977
+ }
20978
+ function isValidTime(h, m, s) {
20979
+ if (h >= 24 || h < 0 || m > 59 || m < 0 || s > 60 || s < 0) return false;
20980
+ return true;
20981
+ }
20982
+ function getDateFromDateTimeData(data, timeZone) {
20983
+ const year = padStart(data.year, 4);
20984
+ const month = data.month ? padStart(data.month, 2) : "01";
20985
+ const day = data.day ? padStart(data.day, 2) : "01";
20986
+ const hour = padStart(data.hour, 2);
20987
+ const minute = padStart(data.minute, 2);
20988
+ const second = padStart(data.second, 2);
20989
+ const textDate = `${year}-${month}-${day}`;
20990
+ const frac = data.frac ? `.${data.frac}` : "";
20991
+ const dateValue = /* @__PURE__ */ new Date(`${textDate}T${hour}:${minute}:${second}${frac}${timeZone}`);
20992
+ if (!isNaN(dateValue.getTime()) || data.second !== 60) return dateValue;
20993
+ return /* @__PURE__ */ new Date(`${textDate}T${hour}:${minute}:59${frac}${timeZone}`);
20994
+ }
20995
+ function padStart(num, maxLength) {
20996
+ return String(num).padStart(maxLength, "0");
20997
+ }
20998
+ var VALUE_KIND_VALUE = Symbol("VALUE_KIND_VALUE");
20999
+ var VALUE_KIND_INTERMEDIATE = Symbol("VALUE_KIND_INTERMEDIATE");
21000
+ var KeysResolver = class {
21001
+ constructor(ctx) {
21002
+ this.rootKeys = /* @__PURE__ */ new Map();
21003
+ this.tables = [];
21004
+ this.ctx = ctx;
21005
+ }
21006
+ applyResolveKeyForTable(node) {
21007
+ let keys = this.rootKeys;
21008
+ const peekKeyIndex = node.key.keys.length - 1;
21009
+ for (let index = 0; index < peekKeyIndex; index++) {
21010
+ const keyNode = node.key.keys[index];
21011
+ const keyName = toKeyName(keyNode);
21012
+ node.resolvedKey.push(keyName);
21013
+ let keyStore = keys.get(keyName);
21014
+ if (!keyStore) {
21015
+ keyStore = {
21016
+ node: keyNode,
21017
+ keys: /* @__PURE__ */ new Map()
21018
+ };
21019
+ keys.set(keyName, keyStore);
21020
+ } else if (keyStore.table === "array") {
21021
+ const peekIndex = keyStore.peekIndex;
21022
+ node.resolvedKey.push(peekIndex);
21023
+ keyStore = keyStore.keys.get(peekIndex);
21024
+ }
21025
+ keys = keyStore.keys;
21026
+ }
21027
+ const lastKeyNode = node.key.keys[peekKeyIndex];
21028
+ const lastKeyName = toKeyName(lastKeyNode);
21029
+ node.resolvedKey.push(lastKeyName);
21030
+ const lastKeyStore = keys.get(lastKeyName);
21031
+ if (!lastKeyStore) if (node.kind === "array") {
21032
+ node.resolvedKey.push(0);
21033
+ const newKeyStore = {
21034
+ node: lastKeyNode,
21035
+ keys: /* @__PURE__ */ new Map()
21036
+ };
21037
+ keys.set(lastKeyName, {
21038
+ table: node.kind,
21039
+ node: lastKeyNode,
21040
+ keys: /* @__PURE__ */ new Map([[0, newKeyStore]]),
21041
+ peekIndex: 0
21042
+ });
21043
+ this.tables.push({
21044
+ node,
21045
+ keys: newKeyStore.keys
21046
+ });
21047
+ } else {
21048
+ const newKeyStore = {
21049
+ table: node.kind,
21050
+ node: lastKeyNode,
21051
+ keys: /* @__PURE__ */ new Map()
21052
+ };
21053
+ keys.set(lastKeyName, newKeyStore);
21054
+ this.tables.push({
21055
+ node,
21056
+ keys: newKeyStore.keys
21057
+ });
21058
+ }
21059
+ else if (!lastKeyStore.table) if (node.kind === "array") this.ctx.reportParseError("dupe-keys", lastKeyNode);
21060
+ else {
21061
+ const transformKey = {
21062
+ table: node.kind,
21063
+ node: lastKeyNode,
21064
+ keys: lastKeyStore.keys
21065
+ };
21066
+ keys.set(lastKeyName, transformKey);
21067
+ this.tables.push({
21068
+ node,
21069
+ keys: transformKey.keys
21070
+ });
21071
+ }
21072
+ else if (lastKeyStore.table === "array") if (node.kind === "array") {
21073
+ const newKeyStore = {
21074
+ node: lastKeyNode,
21075
+ keys: /* @__PURE__ */ new Map()
21076
+ };
21077
+ const newIndex = lastKeyStore.peekIndex + 1;
21078
+ node.resolvedKey.push(newIndex);
21079
+ lastKeyStore.keys.set(newIndex, newKeyStore);
21080
+ lastKeyStore.peekIndex = newIndex;
21081
+ this.tables.push({
21082
+ node,
21083
+ keys: newKeyStore.keys
21084
+ });
21085
+ } else this.ctx.reportParseError("dupe-keys", lastKeyNode);
21086
+ else this.ctx.reportParseError("dupe-keys", lastKeyNode);
21087
+ }
21088
+ verifyDuplicateKeys(node) {
21089
+ for (const body of node.body) if (body.type === "TOMLKeyValue") verifyDuplicateKeysForKeyValue(this.ctx, this.rootKeys, body);
21090
+ for (const { node: tableNode, keys } of this.tables) for (const body of tableNode.body) verifyDuplicateKeysForKeyValue(this.ctx, keys, body);
21091
+ }
21092
+ };
21093
+ function verifyDuplicateKeysForKeyValue(ctx, defineKeys, node) {
21094
+ let keys = defineKeys;
21095
+ const lastKey = last(node.key.keys);
21096
+ for (const keyNode of node.key.keys) {
21097
+ const key = toKeyName(keyNode);
21098
+ let defineKey = keys.get(key);
21099
+ if (defineKey) {
21100
+ if (defineKey.value === VALUE_KIND_VALUE) ctx.reportParseError("dupe-keys", getAfterNode(keyNode, defineKey.node));
21101
+ else if (lastKey === keyNode) ctx.reportParseError("dupe-keys", getAfterNode(keyNode, defineKey.node));
21102
+ else if (defineKey.table) ctx.reportParseError("dupe-keys", getAfterNode(keyNode, defineKey.node));
21103
+ defineKey.value = VALUE_KIND_INTERMEDIATE;
21104
+ } else {
21105
+ if (lastKey === keyNode) defineKey = {
21106
+ value: VALUE_KIND_VALUE,
21107
+ node: keyNode,
21108
+ keys: /* @__PURE__ */ new Map()
21109
+ };
21110
+ else defineKey = {
21111
+ value: VALUE_KIND_INTERMEDIATE,
21112
+ node: keyNode,
21113
+ keys: /* @__PURE__ */ new Map()
21114
+ };
21115
+ keys.set(key, defineKey);
21116
+ }
21117
+ keys = defineKey.keys;
21118
+ }
21119
+ if (node.value.type === "TOMLInlineTable") verifyDuplicateKeysForInlineTable(ctx, keys, node.value);
21120
+ else if (node.value.type === "TOMLArray") verifyDuplicateKeysForArray(ctx, keys, node.value);
21121
+ }
21122
+ function verifyDuplicateKeysForInlineTable(ctx, defineKeys, node) {
21123
+ for (const body of node.body) verifyDuplicateKeysForKeyValue(ctx, defineKeys, body);
21124
+ }
21125
+ function verifyDuplicateKeysForArray(ctx, defineKeys, node) {
21126
+ const keys = defineKeys;
21127
+ for (let index = 0; index < node.elements.length; index++) {
21128
+ const element2 = node.elements[index];
21129
+ let defineKey = keys.get(index);
21130
+ if (defineKey) ctx.reportParseError("dupe-keys", getAfterNode(element2, defineKey.node));
21131
+ else {
21132
+ defineKey = {
21133
+ value: VALUE_KIND_VALUE,
21134
+ node: element2,
21135
+ keys: /* @__PURE__ */ new Map()
21136
+ };
21137
+ defineKeys.set(index, defineKey);
21138
+ if (element2.type === "TOMLInlineTable") verifyDuplicateKeysForInlineTable(ctx, defineKey.keys, element2);
21139
+ else if (element2.type === "TOMLArray") verifyDuplicateKeysForArray(ctx, defineKey.keys, element2);
21140
+ }
21141
+ }
21142
+ }
21143
+ function getAfterNode(a, b) {
21144
+ return a.range[0] <= b.range[0] ? b : a;
21145
+ }
21146
+ var Context = class {
21147
+ constructor(data) {
21148
+ this.tokens = [];
21149
+ this.comments = [];
21150
+ this.back = null;
21151
+ this.stateStack = [];
21152
+ this.needNewLine = false;
21153
+ this.needSameLine = false;
21154
+ this.currToken = null;
21155
+ this.prevToken = null;
21156
+ this.valueContainerStack = [];
21157
+ this.tokenizer = new Tokenizer(data.text, data.parserOptions);
21158
+ this.topLevelTable = data.topLevelTable;
21159
+ this.table = data.topLevelTable;
21160
+ this.keysResolver = new KeysResolver(this);
21161
+ }
21162
+ /**
21163
+ * Get the next token.
21164
+ */
21165
+ nextToken(option) {
21166
+ this.prevToken = this.currToken;
21167
+ if (this.back) {
21168
+ this.currToken = this.back;
21169
+ this.back = null;
21170
+ } else this.currToken = this._nextTokenFromTokenizer(option);
21171
+ if ((this.needNewLine || this.needSameLine || option?.needSameLine) && this.prevToken && this.currToken) if (this.prevToken.loc.end.line === this.currToken.loc.start.line) {
21172
+ if (this.needNewLine) return this.reportParseError("missing-newline", this.currToken);
21173
+ } else {
21174
+ const needSameLine = this.needSameLine || option?.needSameLine;
21175
+ if (needSameLine) return this.reportParseError(needSameLine, this.currToken);
21176
+ }
21177
+ this.needNewLine = false;
21178
+ this.needSameLine = false;
21179
+ return this.currToken;
21180
+ }
21181
+ _nextTokenFromTokenizer(option) {
21182
+ const valuesEnabled = this.tokenizer.valuesEnabled;
21183
+ if (option?.valuesEnabled) this.tokenizer.valuesEnabled = option.valuesEnabled;
21184
+ let token = this.tokenizer.nextToken();
21185
+ while (token && token.type === "Block") {
21186
+ this.comments.push(token);
21187
+ token = this.tokenizer.nextToken();
21188
+ }
21189
+ if (token) this.tokens.push(token);
21190
+ this.tokenizer.valuesEnabled = valuesEnabled;
21191
+ return token;
21192
+ }
21193
+ backToken() {
21194
+ if (this.back) throw new Error("Illegal state");
21195
+ this.back = this.currToken;
21196
+ this.currToken = this.prevToken;
21197
+ }
21198
+ addValueContainer(valueContainer) {
21199
+ this.valueContainerStack.push(valueContainer);
21200
+ this.tokenizer.valuesEnabled = true;
21201
+ }
21202
+ consumeValueContainer() {
21203
+ const valueContainer = this.valueContainerStack.pop();
21204
+ this.tokenizer.valuesEnabled = this.valueContainerStack.length > 0;
21205
+ return valueContainer;
21206
+ }
21207
+ applyResolveKeyForTable(node) {
21208
+ this.keysResolver.applyResolveKeyForTable(node);
21209
+ }
21210
+ verifyDuplicateKeys() {
21211
+ this.keysResolver.verifyDuplicateKeys(this.topLevelTable);
21212
+ }
21213
+ /**
21214
+ * Report an invalid token error.
21215
+ */
21216
+ reportParseError(code, token) {
21217
+ let offset, line, column;
21218
+ if (token) {
21219
+ offset = token.range[0];
21220
+ line = token.loc.start.line;
21221
+ column = token.loc.start.column;
21222
+ } else {
21223
+ offset = this.tokenizer.start;
21224
+ const startPos = this.tokenizer.getLocFromIndex(offset);
21225
+ line = startPos.line;
21226
+ column = startPos.column;
21227
+ }
21228
+ throw new ParseError(code, offset, line, column);
21229
+ }
21230
+ };
21231
+ var STATE_FOR_ERROR = { VALUE: "missing-value" };
21232
+ var STRING_VALUE_STYLE_MAP = {
21233
+ BasicString: "basic",
21234
+ MultiLineBasicString: "basic",
21235
+ LiteralString: "literal",
21236
+ MultiLineLiteralString: "literal"
21237
+ };
21238
+ var STRING_KEY_STYLE_MAP = {
21239
+ BasicString: "basic",
21240
+ LiteralString: "literal"
21241
+ };
21242
+ var DATETIME_VALUE_KIND_MAP = {
21243
+ OffsetDateTime: "offset-date-time",
21244
+ LocalDateTime: "local-date-time",
21245
+ LocalDate: "local-date",
21246
+ LocalTime: "local-time"
21247
+ };
21248
+ var TOMLParser = class {
21249
+ /**
21250
+ * Initialize this parser.
21251
+ */
21252
+ constructor(text, parserOptions) {
21253
+ this.text = text;
21254
+ this.parserOptions = parserOptions || {};
21255
+ this.tomlVersion = getTOMLVer(this.parserOptions.tomlVersion);
21256
+ }
21257
+ /**
21258
+ * Parse TOML
21259
+ */
21260
+ parse() {
21261
+ const ast = {
21262
+ type: "Program",
21263
+ body: [],
21264
+ sourceType: "module",
21265
+ tokens: [],
21266
+ comments: [],
21267
+ parent: null,
21268
+ range: [0, 0],
21269
+ loc: {
21270
+ start: {
21271
+ line: 1,
21272
+ column: 0
21273
+ },
21274
+ end: {
21275
+ line: 1,
21276
+ column: 0
21277
+ }
21278
+ }
21279
+ };
21280
+ const node = {
21281
+ type: "TOMLTopLevelTable",
21282
+ body: [],
21283
+ parent: ast,
21284
+ range: cloneRange(ast.range),
21285
+ loc: cloneLoc(ast.loc)
21286
+ };
21287
+ ast.body = [node];
21288
+ const ctx = new Context({
21289
+ text: this.text,
21290
+ parserOptions: this.parserOptions,
21291
+ topLevelTable: node
21292
+ });
21293
+ let token = ctx.nextToken();
21294
+ if (token) {
21295
+ node.range[0] = token.range[0];
21296
+ node.loc.start = clonePos(token.loc.start);
21297
+ while (token) {
21298
+ const state$1 = ctx.stateStack.pop() || "TABLE";
21299
+ ctx.stateStack.push(...this[state$1](token, ctx));
21300
+ token = ctx.nextToken();
21301
+ }
21302
+ const state = ctx.stateStack.pop() || "TABLE";
21303
+ if (state in STATE_FOR_ERROR) return ctx.reportParseError(STATE_FOR_ERROR[state], null);
21304
+ if (ctx.table.type === "TOMLTable") applyEndLoc(ctx.table, last(ctx.table.body));
21305
+ applyEndLoc(node, last(node.body));
21306
+ }
21307
+ ctx.verifyDuplicateKeys();
21308
+ ast.tokens = ctx.tokens;
21309
+ ast.comments = ctx.comments;
21310
+ const endOffset = ctx.tokenizer.end;
21311
+ const endPos = ctx.tokenizer.getLocFromIndex(endOffset);
21312
+ ast.range[1] = endOffset;
21313
+ ast.loc.end = {
21314
+ line: endPos.line,
21315
+ column: endPos.column
21316
+ };
21317
+ return ast;
21318
+ }
21319
+ TABLE(token, ctx) {
21320
+ if (isBare(token) || isString(token)) return this.processKeyValue(token, ctx.table, ctx);
21321
+ if (isLeftBracket(token)) return this.processTable(token, ctx.topLevelTable, ctx);
21322
+ return ctx.reportParseError("unexpected-token", token);
21323
+ }
21324
+ VALUE(token, ctx) {
21325
+ if (isString(token) || isMultiLineString(token)) return this.processStringValue(token, ctx);
21326
+ if (isNumber(token)) return this.processNumberValue(token, ctx);
21327
+ if (isBoolean(token)) return this.processBooleanValue(token, ctx);
21328
+ if (isDateTime(token)) return this.processDateTimeValue(token, ctx);
21329
+ if (isLeftBracket(token)) return this.processArray(token, ctx);
21330
+ if (isLeftBrace(token)) return this.processInlineTable(token, ctx);
21331
+ return ctx.reportParseError("unexpected-token", token);
21332
+ }
21333
+ processTable(token, topLevelTableNode, ctx) {
21334
+ const tableNode = {
21335
+ type: "TOMLTable",
21336
+ kind: "standard",
21337
+ key: null,
21338
+ resolvedKey: [],
21339
+ body: [],
21340
+ parent: topLevelTableNode,
21341
+ range: cloneRange(token.range),
21342
+ loc: cloneLoc(token.loc)
21343
+ };
21344
+ if (ctx.table.type === "TOMLTable") applyEndLoc(ctx.table, last(ctx.table.body));
21345
+ topLevelTableNode.body.push(tableNode);
21346
+ ctx.table = tableNode;
21347
+ let targetToken = ctx.nextToken({ needSameLine: "invalid-key-value-newline" });
21348
+ if (isLeftBracket(targetToken)) {
21349
+ if (token.range[1] < targetToken.range[0]) return ctx.reportParseError("invalid-space", targetToken);
21350
+ tableNode.kind = "array";
21351
+ targetToken = ctx.nextToken({ needSameLine: "invalid-key-value-newline" });
21352
+ }
21353
+ if (isRightBracket(targetToken)) return ctx.reportParseError("missing-key", targetToken);
21354
+ if (!targetToken) return ctx.reportParseError("unterminated-table-key", null);
21355
+ targetToken = this.processKeyNode(targetToken, tableNode, ctx).nextToken;
21356
+ if (!isRightBracket(targetToken)) return ctx.reportParseError("unterminated-table-key", targetToken);
21357
+ if (tableNode.kind === "array") {
21358
+ const rightBracket = targetToken;
21359
+ targetToken = ctx.nextToken({ needSameLine: "invalid-key-value-newline" });
21360
+ if (!isRightBracket(targetToken)) return ctx.reportParseError("unterminated-table-key", targetToken);
21361
+ if (rightBracket.range[1] < targetToken.range[0]) return ctx.reportParseError("invalid-space", targetToken);
21362
+ }
21363
+ applyEndLoc(tableNode, targetToken);
21364
+ ctx.applyResolveKeyForTable(tableNode);
21365
+ ctx.needNewLine = true;
21366
+ return [];
21367
+ }
21368
+ processKeyValue(token, tableNode, ctx) {
21369
+ const keyValueNode = {
21370
+ type: "TOMLKeyValue",
21371
+ key: null,
21372
+ value: null,
21373
+ parent: tableNode,
21374
+ range: cloneRange(token.range),
21375
+ loc: cloneLoc(token.loc)
21376
+ };
21377
+ tableNode.body.push(keyValueNode);
21378
+ const { nextToken: targetToken } = this.processKeyNode(token, keyValueNode, ctx);
21379
+ if (!isEq(targetToken)) return ctx.reportParseError("missing-equals-sign", targetToken);
21380
+ ctx.addValueContainer({
21381
+ parent: keyValueNode,
21382
+ set: (valNode) => {
21383
+ keyValueNode.value = valNode;
21384
+ applyEndLoc(keyValueNode, valNode);
21385
+ ctx.needNewLine = true;
21386
+ return [];
21387
+ }
21388
+ });
21389
+ ctx.needSameLine = "invalid-key-value-newline";
21390
+ return ["VALUE"];
21391
+ }
21392
+ processKeyNode(token, parent, ctx) {
21393
+ if (isDot(token)) ctx.reportParseError("invalid-leading-dot-in-key", token);
21394
+ const keyNode = {
21395
+ type: "TOMLKey",
21396
+ keys: [],
21397
+ parent,
21398
+ range: cloneRange(token.range),
21399
+ loc: cloneLoc(token.loc)
21400
+ };
21401
+ parent.key = keyNode;
21402
+ let targetToken = token;
21403
+ let dotToken = null;
21404
+ do {
21405
+ if (isBare(targetToken)) this.processBareKey(targetToken, keyNode);
21406
+ else if (isString(targetToken)) this.processStringKey(targetToken, keyNode);
21407
+ else break;
21408
+ dotToken = null;
21409
+ targetToken = ctx.nextToken({ needSameLine: "invalid-key-value-newline" });
21410
+ if (!isDot(targetToken)) break;
21411
+ dotToken = targetToken;
21412
+ targetToken = ctx.nextToken({ needSameLine: "invalid-key-value-newline" });
21413
+ } while (targetToken);
21414
+ if (dotToken) ctx.reportParseError(isDot(targetToken) ? "invalid-consecutive-dots-in-key" : "invalid-trailing-dot-in-key", dotToken);
21415
+ applyEndLoc(keyNode, last(keyNode.keys));
21416
+ return {
21417
+ keyNode,
21418
+ nextToken: targetToken
21419
+ };
21420
+ }
21421
+ processBareKey(token, keyNode) {
21422
+ const node = {
21423
+ type: "TOMLBare",
21424
+ name: token.value,
21425
+ parent: keyNode,
21426
+ range: cloneRange(token.range),
21427
+ loc: cloneLoc(token.loc)
21428
+ };
21429
+ keyNode.keys.push(node);
21430
+ }
21431
+ processStringKey(token, keyNode) {
21432
+ const node = {
21433
+ type: "TOMLQuoted",
21434
+ kind: "string",
21435
+ value: token.string,
21436
+ style: STRING_KEY_STYLE_MAP[token.type],
21437
+ multiline: false,
21438
+ parent: keyNode,
21439
+ range: cloneRange(token.range),
21440
+ loc: cloneLoc(token.loc)
21441
+ };
21442
+ keyNode.keys.push(node);
21443
+ }
21444
+ processStringValue(token, ctx) {
21445
+ const valueContainer = ctx.consumeValueContainer();
21446
+ const node = {
21447
+ type: "TOMLValue",
21448
+ kind: "string",
21449
+ value: token.string,
21450
+ style: STRING_VALUE_STYLE_MAP[token.type],
21451
+ multiline: isMultiLineString(token),
21452
+ parent: valueContainer.parent,
21453
+ range: cloneRange(token.range),
21454
+ loc: cloneLoc(token.loc)
21455
+ };
21456
+ return valueContainer.set(node);
21457
+ }
21458
+ processNumberValue(token, ctx) {
21459
+ const valueContainer = ctx.consumeValueContainer();
21460
+ const text = this.text;
21461
+ const [startRange, endRange] = token.range;
21462
+ let numberString = null;
21463
+ const getNumberText = () => {
21464
+ return numberString ?? (numberString = text.slice(startRange, endRange).replace(/_/g, ""));
21465
+ };
21466
+ let node;
21467
+ if (token.type === "Integer") node = {
21468
+ type: "TOMLValue",
21469
+ kind: "integer",
21470
+ value: token.number,
21471
+ bigint: token.bigint,
21472
+ get number() {
21473
+ return getNumberText();
21474
+ },
21475
+ parent: valueContainer.parent,
21476
+ range: cloneRange(token.range),
21477
+ loc: cloneLoc(token.loc)
21478
+ };
21479
+ else node = {
21480
+ type: "TOMLValue",
21481
+ kind: "float",
21482
+ value: token.number,
21483
+ get number() {
21484
+ return getNumberText();
21485
+ },
21486
+ parent: valueContainer.parent,
21487
+ range: cloneRange(token.range),
21488
+ loc: cloneLoc(token.loc)
21489
+ };
21490
+ return valueContainer.set(node);
21491
+ }
21492
+ processBooleanValue(token, ctx) {
21493
+ const valueContainer = ctx.consumeValueContainer();
21494
+ const node = {
21495
+ type: "TOMLValue",
21496
+ kind: "boolean",
21497
+ value: token.boolean,
21498
+ parent: valueContainer.parent,
21499
+ range: cloneRange(token.range),
21500
+ loc: cloneLoc(token.loc)
21501
+ };
21502
+ return valueContainer.set(node);
21503
+ }
21504
+ processDateTimeValue(token, ctx) {
21505
+ const valueContainer = ctx.consumeValueContainer();
21506
+ const node = {
21507
+ type: "TOMLValue",
21508
+ kind: DATETIME_VALUE_KIND_MAP[token.type],
21509
+ value: token.date,
21510
+ datetime: token.value,
21511
+ parent: valueContainer.parent,
21512
+ range: cloneRange(token.range),
21513
+ loc: cloneLoc(token.loc)
21514
+ };
21515
+ return valueContainer.set(node);
21516
+ }
21517
+ processArray(token, ctx) {
21518
+ const valueContainer = ctx.consumeValueContainer();
21519
+ const node = {
21520
+ type: "TOMLArray",
21521
+ elements: [],
21522
+ parent: valueContainer.parent,
21523
+ range: cloneRange(token.range),
21524
+ loc: cloneLoc(token.loc)
21525
+ };
21526
+ const nextToken = ctx.nextToken({ valuesEnabled: true });
21527
+ if (isRightBracket(nextToken)) {
21528
+ applyEndLoc(node, nextToken);
21529
+ return valueContainer.set(node);
21530
+ }
21531
+ ctx.backToken();
21532
+ return this.processArrayValue(node, valueContainer, ctx);
21533
+ }
21534
+ processArrayValue(node, valueContainer, ctx) {
21535
+ ctx.addValueContainer({
21536
+ parent: node,
21537
+ set: (valNode) => {
21538
+ node.elements.push(valNode);
21539
+ let nextToken = ctx.nextToken({ valuesEnabled: true });
21540
+ const hasComma = isComma(nextToken);
21541
+ if (hasComma) nextToken = ctx.nextToken({ valuesEnabled: true });
21542
+ if (isRightBracket(nextToken)) {
21543
+ applyEndLoc(node, nextToken);
21544
+ return valueContainer.set(node);
21545
+ }
21546
+ if (hasComma) {
21547
+ ctx.backToken();
21548
+ return this.processArrayValue(node, valueContainer, ctx);
21549
+ }
21550
+ return ctx.reportParseError(nextToken ? "missing-comma" : "unterminated-array", nextToken);
21551
+ }
21552
+ });
21553
+ return ["VALUE"];
21554
+ }
21555
+ processInlineTable(token, ctx) {
21556
+ const valueContainer = ctx.consumeValueContainer();
21557
+ const node = {
21558
+ type: "TOMLInlineTable",
21559
+ body: [],
21560
+ parent: valueContainer.parent,
21561
+ range: cloneRange(token.range),
21562
+ loc: cloneLoc(token.loc)
21563
+ };
21564
+ const needSameLine = this.tomlVersion.gte(1, 1) ? void 0 : "invalid-inline-table-newline";
21565
+ const nextToken = ctx.nextToken({ needSameLine });
21566
+ if (nextToken) {
21567
+ if (isBare(nextToken) || isString(nextToken)) return this.processInlineTableKeyValue(nextToken, node, valueContainer, ctx);
21568
+ if (isRightBrace(nextToken)) {
21569
+ applyEndLoc(node, nextToken);
21570
+ return valueContainer.set(node);
21571
+ }
21572
+ }
21573
+ return ctx.reportParseError("unexpected-token", nextToken);
21574
+ }
21575
+ processInlineTableKeyValue(token, inlineTableNode, valueContainer, ctx) {
21576
+ const keyValueNode = {
21577
+ type: "TOMLKeyValue",
21578
+ key: null,
21579
+ value: null,
21580
+ parent: inlineTableNode,
21581
+ range: cloneRange(token.range),
21582
+ loc: cloneLoc(token.loc)
21583
+ };
21584
+ inlineTableNode.body.push(keyValueNode);
21585
+ const { nextToken: targetToken } = this.processKeyNode(token, keyValueNode, ctx);
21586
+ if (!isEq(targetToken)) return ctx.reportParseError("missing-equals-sign", targetToken);
21587
+ const needSameLine = this.tomlVersion.gte(1, 1) ? void 0 : "invalid-inline-table-newline";
21588
+ ctx.addValueContainer({
21589
+ parent: keyValueNode,
21590
+ set: (valNode) => {
21591
+ keyValueNode.value = valNode;
21592
+ applyEndLoc(keyValueNode, valNode);
21593
+ let nextToken = ctx.nextToken({ needSameLine });
21594
+ if (isComma(nextToken)) {
21595
+ nextToken = ctx.nextToken({ needSameLine });
21596
+ if (nextToken && (isBare(nextToken) || isString(nextToken))) return this.processInlineTableKeyValue(nextToken, inlineTableNode, valueContainer, ctx);
21597
+ if (isRightBrace(nextToken)) {
21598
+ if (this.tomlVersion.lt(1, 1)) return ctx.reportParseError("invalid-trailing-comma-in-inline-table", nextToken);
21599
+ } else return ctx.reportParseError(nextToken ? "unexpected-token" : "unterminated-inline-table", nextToken);
21600
+ }
21601
+ if (isRightBrace(nextToken)) {
21602
+ applyEndLoc(inlineTableNode, nextToken);
21603
+ return valueContainer.set(inlineTableNode);
21604
+ }
21605
+ return ctx.reportParseError(nextToken ? "missing-comma" : "unterminated-inline-table", nextToken);
21606
+ }
21607
+ });
21608
+ ctx.needSameLine = "invalid-key-value-newline";
21609
+ return ["VALUE"];
21610
+ }
21611
+ };
21612
+ function isDot(token) {
21613
+ return isPunctuator(token) && token.value === ".";
21614
+ }
21615
+ function isEq(token) {
21616
+ return isPunctuator(token) && token.value === "=";
21617
+ }
21618
+ function isLeftBracket(token) {
21619
+ return isPunctuator(token) && token.value === "[";
21620
+ }
21621
+ function isRightBracket(token) {
21622
+ return isPunctuator(token) && token.value === "]";
21623
+ }
21624
+ function isLeftBrace(token) {
21625
+ return isPunctuator(token) && token.value === "{";
21626
+ }
21627
+ function isRightBrace(token) {
21628
+ return isPunctuator(token) && token.value === "}";
21629
+ }
21630
+ function isComma(token) {
21631
+ return isPunctuator(token) && token.value === ",";
21632
+ }
21633
+ function isPunctuator(token) {
21634
+ return Boolean(token && token.type === "Punctuator");
21635
+ }
21636
+ function isBare(token) {
21637
+ return token.type === "Bare";
21638
+ }
21639
+ function isString(token) {
21640
+ return token.type === "BasicString" || token.type === "LiteralString";
21641
+ }
21642
+ function isMultiLineString(token) {
21643
+ return token.type === "MultiLineBasicString" || token.type === "MultiLineLiteralString";
21644
+ }
21645
+ function isNumber(token) {
21646
+ return token.type === "Integer" || token.type === "Float";
21647
+ }
21648
+ function isBoolean(token) {
21649
+ return token.type === "Boolean";
21650
+ }
21651
+ function isDateTime(token) {
21652
+ return token.type === "OffsetDateTime" || token.type === "LocalDateTime" || token.type === "LocalDate" || token.type === "LocalTime";
21653
+ }
21654
+ function applyEndLoc(node, child) {
21655
+ if (child) {
21656
+ node.range[1] = child.range[1];
21657
+ node.loc.end = clonePos(child.loc.end);
21658
+ }
21659
+ }
21660
+ function cloneRange(range) {
21661
+ return [range[0], range[1]];
21662
+ }
21663
+ function cloneLoc(loc) {
21664
+ return {
21665
+ start: clonePos(loc.start),
21666
+ end: clonePos(loc.end)
21667
+ };
21668
+ }
21669
+ function clonePos(pos) {
21670
+ return {
21671
+ line: pos.line,
21672
+ column: pos.column
21673
+ };
21674
+ }
21675
+ var tomlKeys = {
21676
+ Program: ["body"],
21677
+ TOMLTopLevelTable: ["body"],
21678
+ TOMLTable: ["key", "body"],
21679
+ TOMLKeyValue: ["key", "value"],
21680
+ TOMLKey: ["keys"],
21681
+ TOMLArray: ["elements"],
21682
+ TOMLInlineTable: ["body"],
21683
+ TOMLBare: [],
21684
+ TOMLQuoted: [],
21685
+ TOMLValue: []
21686
+ };
21687
+ var KEYS3 = unionWith(tomlKeys);
21688
+ function parseForESLint(code, options) {
21689
+ return {
21690
+ ast: new TOMLParser(code, options).parse(),
21691
+ visitorKeys: KEYS3,
21692
+ services: { isTOML: true }
21693
+ };
21694
+ }
21695
+ var getStaticTOMLValue = generateConvertTOMLValue((node) => node.value);
21696
+ function generateConvertTOMLValue(convertValue) {
21697
+ function resolveValue(node, baseTable) {
21698
+ return resolver[node.type](node, baseTable);
21699
+ }
21700
+ const resolver = {
21701
+ Program(node, baseTable = {}) {
21702
+ return resolveValue(node.body[0], baseTable);
21703
+ },
21704
+ TOMLTopLevelTable(node, baseTable = {}) {
21705
+ for (const body of node.body) resolveValue(body, baseTable);
21706
+ return baseTable;
21707
+ },
21708
+ TOMLKeyValue(node, baseTable = {}) {
21709
+ const value = resolveValue(node.value);
21710
+ set2(baseTable, resolveValue(node.key), value);
21711
+ return baseTable;
21712
+ },
21713
+ TOMLTable(node, baseTable = {}) {
21714
+ const table = getTable(baseTable, resolveValue(node.key), node.kind === "array");
21715
+ for (const body of node.body) resolveValue(body, table);
21716
+ return baseTable;
21717
+ },
21718
+ TOMLArray(node) {
21719
+ return node.elements.map((e) => resolveValue(e));
21720
+ },
21721
+ TOMLInlineTable(node) {
21722
+ const table = {};
21723
+ for (const body of node.body) resolveValue(body, table);
21724
+ return table;
21725
+ },
21726
+ TOMLKey(node) {
21727
+ return node.keys.map((key) => resolveValue(key));
21728
+ },
21729
+ TOMLBare(node) {
21730
+ return node.name;
21731
+ },
21732
+ TOMLQuoted(node) {
21733
+ return node.value;
21734
+ },
21735
+ TOMLValue(node) {
21736
+ return convertValue(node);
21737
+ }
21738
+ };
21739
+ return (node) => resolveValue(node);
21740
+ }
21741
+ function getTable(baseTable, keys, array2) {
21742
+ let target = baseTable;
21743
+ for (let index = 0; index < keys.length - 1; index++) {
21744
+ const key = keys[index];
21745
+ target = getNextTargetFromKey(target, key);
21746
+ }
21747
+ const lastKey = last(keys);
21748
+ const lastTarget = target[lastKey];
21749
+ if (lastTarget == null) {
21750
+ const tableValue$1 = {};
21751
+ target[lastKey] = array2 ? [tableValue$1] : tableValue$1;
21752
+ return tableValue$1;
21753
+ }
21754
+ if (isValue(lastTarget)) {
21755
+ const tableValue$1 = {};
21756
+ target[lastKey] = array2 ? [tableValue$1] : tableValue$1;
21757
+ return tableValue$1;
21758
+ }
21759
+ if (!array2) {
21760
+ if (Array.isArray(lastTarget)) {
21761
+ const tableValue$1 = {};
21762
+ target[lastKey] = tableValue$1;
21763
+ return tableValue$1;
21764
+ }
21765
+ return lastTarget;
21766
+ }
21767
+ if (Array.isArray(lastTarget)) {
21768
+ const tableValue$1 = {};
21769
+ lastTarget.push(tableValue$1);
21770
+ return tableValue$1;
21771
+ }
21772
+ const tableValue = {};
21773
+ target[lastKey] = [tableValue];
21774
+ return tableValue;
21775
+ function getNextTargetFromKey(currTarget, key) {
21776
+ const nextTarget = currTarget[key];
21777
+ if (nextTarget == null) {
21778
+ const val = {};
21779
+ currTarget[key] = val;
21780
+ return val;
21781
+ }
21782
+ if (isValue(nextTarget)) {
21783
+ const val = {};
21784
+ currTarget[key] = val;
21785
+ return val;
21786
+ }
21787
+ let resultTarget = nextTarget;
21788
+ while (Array.isArray(resultTarget)) {
21789
+ const lastIndex = resultTarget.length - 1;
21790
+ const nextElement = resultTarget[lastIndex];
21791
+ if (isValue(nextElement)) {
21792
+ const val = {};
21793
+ resultTarget[lastIndex] = val;
21794
+ return val;
21795
+ }
21796
+ resultTarget = nextElement;
21797
+ }
21798
+ return resultTarget;
21799
+ }
21800
+ }
21801
+ function set2(baseTable, keys, value) {
21802
+ let target = baseTable;
21803
+ for (let index = 0; index < keys.length - 1; index++) {
21804
+ const key = keys[index];
21805
+ const nextTarget = target[key];
21806
+ if (nextTarget == null) {
21807
+ const val = {};
21808
+ target[key] = val;
21809
+ target = val;
21810
+ } else if (isValue(nextTarget) || Array.isArray(nextTarget)) {
21811
+ const val = {};
21812
+ target[key] = val;
21813
+ target = val;
21814
+ } else target = nextTarget;
21815
+ }
21816
+ target[last(keys)] = value;
21817
+ }
21818
+ function isValue(value) {
21819
+ return typeof value !== "object" || value instanceof Date;
21820
+ }
21821
+ function parseTOML(code, options) {
21822
+ return parseForESLint(code, options).ast;
21823
+ }
21824
+
21825
+ // src/core/ops/atomic-file.ts
21826
+ import { mkdirSync as mkdirSync3, renameSync, unlinkSync, writeFileSync } from "node:fs";
21827
+ import path3 from "node:path";
21828
+ function sleepSync(ms) {
21829
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
21830
+ }
21831
+ function errCode(e) {
21832
+ return e.code;
21833
+ }
21834
+ function renameWithRetry(from, to, opts = {}) {
21835
+ const rename = opts.rename ?? renameSync;
21836
+ const sleep = opts.sleep ?? sleepSync;
21837
+ const win = (opts.platform ?? process.platform) === "win32";
21838
+ for (let attempt = 0; ; attempt += 1) {
21839
+ try {
21840
+ rename(from, to);
21841
+ return;
21842
+ } catch (e) {
21843
+ const busy = win && ATOMIC_RENAME_BUSY_CODES.includes(errCode(e) ?? "");
21844
+ if (!busy || attempt >= ATOMIC_RENAME_RETRIES) throw e;
21845
+ sleep(ATOMIC_RENAME_DELAY_MS);
21846
+ }
21847
+ }
21848
+ }
21849
+ function unlinkWithRetry(file2, opts = {}) {
21850
+ const unlink = opts.unlink ?? unlinkSync;
21851
+ const sleep = opts.sleep ?? sleepSync;
21852
+ const win = (opts.platform ?? process.platform) === "win32";
21853
+ for (let attempt = 0; ; attempt += 1) {
21854
+ try {
21855
+ unlink(file2);
21856
+ return;
21857
+ } catch (e) {
21858
+ if (errCode(e) === "ENOENT") return;
21859
+ const busy = win && ATOMIC_RENAME_BUSY_CODES.includes(errCode(e) ?? "");
21860
+ if (!busy || attempt >= ATOMIC_RENAME_RETRIES) throw replaceFailure(file2, e);
21861
+ sleep(ATOMIC_RENAME_DELAY_MS);
21862
+ }
21863
+ }
21864
+ }
21865
+ function replaceFailure(file2, e) {
21866
+ const busy = ATOMIC_RENAME_BUSY_CODES.includes(errCode(e) ?? "");
21867
+ const cause = e.message;
21868
+ return new Error(busy ? `Could not replace ${file2}: ${cause}. Fix: close the program using ${file2}, then re-run` : `Could not write ${file2}: ${cause}. Fix: check the path and its permissions, then re-run`, { cause: e });
21869
+ }
21870
+ function removeTmpFile(tmp, opts = {}) {
21871
+ try {
21872
+ unlinkWithRetry(tmp, opts);
21873
+ } catch {
21874
+ }
21875
+ }
21876
+ function atomicWriteFile(file2, text, opts = {}) {
21877
+ mkdirSync3(path3.dirname(file2), { recursive: true });
21878
+ const tmp = path3.join(path3.dirname(file2), `${ATOMIC_TMP_PREFIX}${path3.basename(file2)}${ATOMIC_TMP_MARK}${process.pid}`);
21879
+ try {
21880
+ writeFileSync(tmp, text);
21881
+ renameWithRetry(tmp, file2, opts);
21882
+ } catch (e) {
21883
+ removeTmpFile(tmp, opts);
21884
+ throw replaceFailure(file2, e);
19908
21885
  }
19909
- scanAll(home, scope.tmp ?? tmpdir(), out);
19910
- return out;
19911
21886
  }
19912
21887
 
19913
21888
  // src/core/ops/host-config.ts
19914
- import { existsSync as existsSync4, readFileSync as readFileSync7, renameSync, writeFileSync } from "node:fs";
19915
- import { dirname as dirname4, join as join8 } from "node:path";
19916
- function formatOf(path4) {
19917
- if (path4.endsWith(JSONC_EXT)) return "jsonc";
19918
- if (path4.endsWith(TOML_EXT)) return "toml";
21889
+ function formatOf(path5) {
21890
+ if (path5.endsWith(JSONC_EXT)) return "jsonc";
21891
+ if (path5.endsWith(TOML_EXT)) return "toml";
19919
21892
  return "json";
19920
21893
  }
19921
- function readHostConfig(agent, path4) {
19922
- let file2 = path4;
21894
+ function readHostConfig(agent, path5) {
21895
+ let file2 = path5;
19923
21896
  if (agent === "opencode") {
19924
- const jsonc = join8(dirname4(path4), OPENCODE_CONFIG_FILES[0]);
19925
- if (existsSync4(jsonc)) file2 = jsonc;
21897
+ const jsonc = join7(dirname4(path5), OPENCODE_CONFIG_FILES[0]);
21898
+ if (existsSync3(jsonc)) file2 = jsonc;
19926
21899
  }
19927
- const text = existsSync4(file2) ? readFileSync7(file2, "utf8") : "";
19928
- return { agent, text, format: formatOf(file2), path: file2 };
21900
+ const raw = existsSync3(file2) ? readFileSync6(file2, "utf8") : "";
21901
+ return { agent, text: hostText(raw), format: agent === "opencode" && !file2.endsWith(TOML_EXT) ? "jsonc" : formatOf(file2), path: file2, layout: hostLayout(raw) };
19929
21902
  }
19930
21903
  function stripJsonComments(text) {
19931
21904
  let out = "";
@@ -20059,354 +22032,567 @@ function scanJson(text, format) {
20059
22032
  if (sc.i !== clean.length) sc.fail();
20060
22033
  return { clean, root, value };
20061
22034
  }
20062
- function tomlKeyPath(s) {
20063
- const out = [];
20064
- let i = 0;
20065
- for (; ; ) {
20066
- while (s[i] === " " || s[i] === " ") i += 1;
20067
- let seg = "";
20068
- if (s[i] === '"' || s[i] === "'") {
20069
- const q = s[i];
20070
- let j = i + 1;
20071
- while (j < s.length && s[j] !== q) j += q === '"' && s[j] === "\\" ? 2 : 1;
20072
- if (j >= s.length) throw new SyntaxError("key");
20073
- seg = q === '"' ? JSON.parse(s.slice(i, j + 1)) : s.slice(i + 1, j);
20074
- i = j + 1;
20075
- } else {
20076
- while (i < s.length && !" .".includes(s[i])) {
20077
- seg += s[i];
20078
- i += 1;
20079
- }
20080
- if (seg === "") throw new SyntaxError("key");
22035
+ function keyNames(key) {
22036
+ return key.keys.map((k) => k.type === "TOMLBare" ? k.name : k.value);
22037
+ }
22038
+ function lineStartOf(text, at2) {
22039
+ return at2 === 0 ? 0 : text.lastIndexOf("\n", at2 - 1) + 1;
22040
+ }
22041
+ function lineEndOf(text, at2) {
22042
+ const nl = text.indexOf("\n", at2);
22043
+ return nl < 0 ? text.length : nl + 1;
22044
+ }
22045
+ function tomlValue(text) {
22046
+ return getStaticTOMLValue(parseTOML(text));
22047
+ }
22048
+ function scanToml(text) {
22049
+ const program = parseTOML(text);
22050
+ const tables = [];
22051
+ const keys = [];
22052
+ const addKey = (base, kv) => {
22053
+ keys.push({ base, full: [...base, ...keyNames(kv.key)], start: kv.range[0], end: kv.range[1], inline: kv.value.type === "TOMLInlineTable" });
22054
+ };
22055
+ for (const node of program.body[0].body) {
22056
+ if (node.type === "TOMLKeyValue") {
22057
+ addKey([], node);
22058
+ continue;
20081
22059
  }
20082
- out.push(seg);
20083
- while (s[i] === " " || s[i] === " ") i += 1;
20084
- if (i >= s.length) return out;
20085
- if (s[i] !== ".") throw new SyntaxError("key");
20086
- i += 1;
22060
+ if (!node.resolvedKey.every((seg) => typeof seg === "string")) continue;
22061
+ const path5 = node.resolvedKey;
22062
+ for (const kv of node.body) addKey(path5, kv);
22063
+ if (node.kind !== "standard") continue;
22064
+ const start = lineStartOf(text, node.range[0]);
22065
+ const headEnd = lineEndOf(text, node.key.range[1]);
22066
+ const last2 = node.body[node.body.length - 1];
22067
+ tables.push({
22068
+ path: path5,
22069
+ header: text.slice(start, text[headEnd - 1] === "\n" ? headEnd - 1 : headEnd),
22070
+ start,
22071
+ end: last2 === void 0 ? headEnd : lineEndOf(text, last2.range[1])
22072
+ });
20087
22073
  }
22074
+ return { value: getStaticTOMLValue(program), tables, keys };
20088
22075
  }
20089
- var TomlValue = class {
20090
- i = 0;
20091
- s;
20092
- constructor(s) {
20093
- this.s = s;
22076
+ function tomlTableSpans(text) {
22077
+ return scanToml(text).tables;
22078
+ }
22079
+ function tomlHeaderText(path5) {
22080
+ return "[" + path5.map(tomlHeaderKey).join(".") + "]";
22081
+ }
22082
+ function parseHostConfig(agent, path5, text, format) {
22083
+ try {
22084
+ return format === "toml" ? scanToml(text).value : scanJson(text, format).value;
22085
+ } catch {
22086
+ throw new CtxError("CONFIG_PARSE_FAILED", { agent, path: path5, format });
20094
22087
  }
20095
- ws() {
20096
- for (; ; ) {
20097
- while (this.i < this.s.length && " \r\n".includes(this.s[this.i])) this.i += 1;
20098
- if (this.s[this.i] !== "#") return;
20099
- while (this.i < this.s.length && this.s[this.i] !== "\n") this.i += 1;
20100
- }
22088
+ }
22089
+ function hostConfigValueAt(value, path5) {
22090
+ let cur = value;
22091
+ for (const seg of path5) {
22092
+ if (!isPlainObject3(cur)) return void 0;
22093
+ cur = cur[seg];
20101
22094
  }
20102
- read() {
20103
- this.ws();
20104
- const c = this.s[this.i];
20105
- if (c === '"' || c === "'") {
20106
- let j2 = this.i + 1;
20107
- while (j2 < this.s.length && this.s[j2] !== c && this.s[j2] !== "\n") j2 += c === '"' && this.s[j2] === "\\" ? 2 : 1;
20108
- if (this.s[j2] !== c) throw new SyntaxError("string");
20109
- const raw = this.s.slice(this.i, j2 + 1);
20110
- this.i = j2 + 1;
20111
- return c === '"' ? JSON.parse(raw) : raw.slice(1, -1);
22095
+ return cur;
22096
+ }
22097
+ function isPlainObject3(v) {
22098
+ return typeof v === "object" && v !== null && !Array.isArray(v);
22099
+ }
22100
+ function sameValue(a, b) {
22101
+ if (a === b) return true;
22102
+ if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((x, k) => sameValue(x, b[k]));
22103
+ if (isPlainObject3(a) && isPlainObject3(b)) {
22104
+ const ka = Object.keys(a);
22105
+ return ka.length === Object.keys(b).length && ka.every((k) => sameValue(a[k], b[k]));
22106
+ }
22107
+ return false;
22108
+ }
22109
+ function lineIndent(text, at2) {
22110
+ let s = at2;
22111
+ while (s > 0 && text[s - 1] !== "\n") s -= 1;
22112
+ let e = s;
22113
+ while (text[e] === " " || text[e] === " ") e += 1;
22114
+ return text.slice(s, e);
22115
+ }
22116
+ function indentUnit(root, clean) {
22117
+ if (root === null || root.kind !== "object" || root.members.length === 0) return JSON_INDENT_UNIT;
22118
+ const own2 = lineIndent(clean, root.members[0].keyStart);
22119
+ return own2 === "" ? JSON_INDENT_UNIT : own2;
22120
+ }
22121
+ function render(value, unit, base) {
22122
+ return JSON.stringify(value, null, unit).split("\n").join("\n" + base);
22123
+ }
22124
+ function nest(path5, value) {
22125
+ let out = value;
22126
+ for (let k = path5.length - 1; k >= 0; k -= 1) out = { [path5[k]]: out };
22127
+ return out;
22128
+ }
22129
+ function setJsonText(text, format, path5, value) {
22130
+ const doc = scanJson(text, format);
22131
+ const unit = indentUnit(doc.root, doc.clean);
22132
+ if (doc.root === null) return render(nest(path5, value), unit, "") + "\n";
22133
+ let node = doc.root;
22134
+ let depth = 0;
22135
+ while (depth < path5.length && node.kind === "object") {
22136
+ const hit = node.members.find((m) => m.key === path5[depth]);
22137
+ if (hit === void 0) break;
22138
+ node = hit.node;
22139
+ depth += 1;
22140
+ }
22141
+ if (depth === path5.length) {
22142
+ return text.slice(0, node.start) + render(value, unit, lineIndent(doc.clean, node.start)) + text.slice(node.end);
22143
+ }
22144
+ if (node.kind !== "object") throw new SyntaxError("not an object at " + path5.slice(0, depth).join("."));
22145
+ const rest = nest(path5.slice(depth + 1), value);
22146
+ const last2 = node.members[node.members.length - 1];
22147
+ if (last2 === void 0) {
22148
+ const base2 = lineIndent(doc.clean, node.start);
22149
+ const member2 = "\n" + base2 + unit + JSON.stringify(path5[depth]) + ": " + render(rest, unit, base2 + unit) + "\n" + base2;
22150
+ return text.slice(0, node.start + 1) + member2 + text.slice(node.end - 1);
22151
+ }
22152
+ const base = lineIndent(doc.clean, last2.keyStart);
22153
+ let at2 = last2.node.end;
22154
+ while (" \r\n".includes(doc.clean[at2])) at2 += 1;
22155
+ const trailing = doc.clean[at2] === ",";
22156
+ const insertAt = trailing ? at2 + 1 : last2.node.end;
22157
+ const member = (trailing ? "" : ",") + "\n" + base + JSON.stringify(path5[depth]) + ": " + render(rest, unit, base);
22158
+ return text.slice(0, insertAt) + member + text.slice(insertAt);
22159
+ }
22160
+ function tomlScalar(v) {
22161
+ if (Array.isArray(v)) return "[" + v.map(tomlScalar).join(", ") + "]";
22162
+ if (isPlainObject3(v)) return "{ " + Object.entries(v).map(([k, x]) => tomlHeaderKey(k) + " = " + tomlScalar(x)).join(", ") + " }";
22163
+ if (typeof v === "string") return JSON.stringify(v);
22164
+ if (typeof v === "number" || typeof v === "boolean") return String(v);
22165
+ throw new SyntaxError("unsupported TOML value");
22166
+ }
22167
+ function tomlHeaderKey(seg) {
22168
+ if (seg === "") return '""';
22169
+ for (const ch of seg) {
22170
+ const bare2 = ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "_" || ch === "-";
22171
+ if (!bare2) return JSON.stringify(seg);
22172
+ }
22173
+ return seg;
22174
+ }
22175
+ function tomlBlock(path5, value) {
22176
+ let out = "[" + path5.map(tomlHeaderKey).join(".") + "]\n";
22177
+ const subs = [];
22178
+ for (const [k, v] of Object.entries(value)) {
22179
+ if (isPlainObject3(v)) subs.push(tomlBlock([...path5, k], v));
22180
+ else out += tomlHeaderKey(k) + " = " + tomlScalar(v) + "\n";
22181
+ }
22182
+ return [out, ...subs].join("\n");
22183
+ }
22184
+ function under(path5, prefix) {
22185
+ return path5.length >= prefix.length && prefix.every((seg, k) => path5[k] === seg);
22186
+ }
22187
+ function keyLineRange(text, k) {
22188
+ const ls = lineStartOf(text, k.start);
22189
+ const le = lineEndOf(text, k.end);
22190
+ const rest = text.slice(k.end, le).trim();
22191
+ const alone = text.slice(ls, k.start).trim() === "" && (rest === "" || rest.startsWith("#"));
22192
+ return alone ? [ls, le] : [k.start, k.end];
22193
+ }
22194
+ function withValueAt(root, rel, value) {
22195
+ if (rel.length === 0) return value;
22196
+ const base = isPlainObject3(root) ? { ...root } : {};
22197
+ const next = withValueAt(base[rel[0]], rel.slice(1), value);
22198
+ if (next === void 0) delete base[rel[0]];
22199
+ else base[rel[0]] = next;
22200
+ return base;
22201
+ }
22202
+ function replaceToml(text, doc, path5, value) {
22203
+ const block = value === void 0 ? "" : tomlBlock(path5, value);
22204
+ const owned = doc.tables.filter((t) => under(t.path, path5));
22205
+ const cuts = doc.keys.filter((k) => under(k.full, path5) && !under(k.base, path5)).map((k) => [...keyLineRange(text, k), ""]);
22206
+ owned.forEach((t, n) => cuts.push([t.start, t.end, n === 0 ? block : ""]));
22207
+ cuts.sort((a, b) => b[0] - a[0]);
22208
+ let out = text;
22209
+ for (const [s, e, put] of cuts) out = out.slice(0, s) + put + out.slice(e);
22210
+ if (owned.length > 0 || block === "") return out;
22211
+ const sep3 = out === "" ? "" : out.endsWith("\n\n") ? "" : out.endsWith("\n") ? "\n" : "\n\n";
22212
+ return out + sep3 + block;
22213
+ }
22214
+ var tableLike = (v) => v === void 0 || isPlainObject3(v);
22215
+ function setTomlText(text, path5, value) {
22216
+ if (value !== void 0 && !isPlainObject3(value)) throw new SyntaxError("TOML edits replace a whole table");
22217
+ const doc = scanToml(text);
22218
+ const cur = hostConfigValueAt(doc.value, path5);
22219
+ if (sameValue(cur, value)) return text;
22220
+ const inline = doc.keys.find((k) => k.inline && k.full.length < path5.length && under(path5, k.full));
22221
+ if (inline !== void 0) {
22222
+ const whole = withValueAt(hostConfigValueAt(doc.value, inline.full), path5.slice(inline.full.length), value);
22223
+ return replaceToml(text, doc, inline.full, whole);
22224
+ }
22225
+ if (isPlainObject3(cur) && isPlainObject3(value)) {
22226
+ const names = [.../* @__PURE__ */ new Set([...Object.keys(cur), ...Object.keys(value)])].filter((k) => !sameValue(cur[k], value[k]));
22227
+ if (names.every((k) => tableLike(cur[k]) && tableLike(value[k]))) {
22228
+ let out = text;
22229
+ for (const k of names) out = setTomlText(out, [...path5, k], value[k]);
22230
+ return out;
20112
22231
  }
20113
- if (c === "[") {
20114
- this.i += 1;
20115
- const out = [];
20116
- for (; ; ) {
20117
- this.ws();
20118
- if (this.s[this.i] === "]") {
20119
- this.i += 1;
20120
- return out;
20121
- }
20122
- out.push(this.read());
20123
- this.ws();
20124
- if (this.s[this.i] === ",") {
20125
- this.i += 1;
20126
- continue;
20127
- }
20128
- if (this.s[this.i] !== "]") throw new SyntaxError("array");
20129
- }
22232
+ }
22233
+ return replaceToml(text, doc, path5, value);
22234
+ }
22235
+ function setText(agent, path5, text, format, key, value) {
22236
+ try {
22237
+ if (format !== "toml") return setJsonText(text, format, key, value);
22238
+ const out = setTomlText(text, key, value);
22239
+ const landed = hostConfigValueAt(tomlValue(out), key);
22240
+ const emptyTable = isPlainObject3(value) && Object.keys(value).length === 0;
22241
+ if (!sameValue(landed, value) && !(emptyTable && landed === void 0)) throw new SyntaxError("edit did not land");
22242
+ return out;
22243
+ } catch {
22244
+ throw new CtxError("CONFIG_PARSE_FAILED", { agent, path: path5, format });
22245
+ }
22246
+ }
22247
+ function serverScript() {
22248
+ return join7(dirname4(process.argv[1] ?? ""), SERVER_ENTRY_FILE);
22249
+ }
22250
+ function listTarget(key, own2, v1) {
22251
+ return {
22252
+ key: [key],
22253
+ next(current) {
22254
+ const list3 = Array.isArray(current) ? current.filter((x) => x !== v1) : [];
22255
+ return list3.includes(own2) ? list3 : [...list3, own2];
20130
22256
  }
20131
- if (c === "{") {
20132
- this.i += 1;
20133
- const out = {};
20134
- for (; ; ) {
20135
- this.ws();
20136
- if (this.s[this.i] === "}") {
20137
- this.i += 1;
20138
- return out;
20139
- }
20140
- const eq = this.s.indexOf("=", this.i);
20141
- if (eq < 0) throw new SyntaxError("inline table");
20142
- const key = tomlKeyPath(this.s.slice(this.i, eq));
20143
- this.i = eq + 1;
20144
- setPath(out, key, this.read());
20145
- this.ws();
20146
- if (this.s[this.i] === ",") {
20147
- this.i += 1;
20148
- continue;
20149
- }
20150
- if (this.s[this.i] !== "}") throw new SyntaxError("inline table");
22257
+ };
22258
+ }
22259
+ function ownTargets(agent) {
22260
+ const mcp = OWN_MCP_ENTRY[agent];
22261
+ if (mcp !== void 0) {
22262
+ return [{
22263
+ key: mcp.key,
22264
+ next(current) {
22265
+ const keep = isPlainObject3(current) ? current : {};
22266
+ return { ...keep, ...mcp.fields, [MCP_COMMAND_FIELD]: HOST_NODE_COMMAND, [MCP_ARGS_FIELD]: [serverScript(), AGENT_ARG, agent] };
20151
22267
  }
20152
- }
20153
- let j = this.i;
20154
- while (j < this.s.length && !" \r\n,]}#".includes(this.s[j])) j += 1;
20155
- const word = this.s.slice(this.i, j);
20156
- this.i = j;
20157
- if (word === "true") return true;
20158
- if (word === "false") return false;
20159
- const n = Number(word.split("_").join(""));
20160
- if (word === "" || Number.isNaN(n)) throw new SyntaxError("value");
20161
- return n;
22268
+ }, ...(mcp.also ?? []).map(([key, value]) => ({ key, next: () => value }))];
20162
22269
  }
20163
- };
20164
- function setPath(target, path4, value) {
20165
- let cur = target;
20166
- for (let k = 0; k < path4.length - 1; k += 1) {
20167
- const next = cur[path4[k]];
20168
- if (next === void 0) cur[path4[k]] = {};
20169
- else if (!isPlainObject3(next)) throw new SyntaxError("key conflict");
20170
- cur = cur[path4[k]];
22270
+ if (agent === "opencode") return [listTarget(OPENCODE_PLUGIN_KEY, OPENCODE_GIT_SPEC, V1_OPENCODE_PLUGIN_SPEC)];
22271
+ if (agent === "pi") return [listTarget(PI_PACKAGES_KEY, PI_GIT_PACKAGE, V1_PI_PACKAGE)];
22272
+ return [];
22273
+ }
22274
+ function applyEdits(agent, path5, text, format, wanted) {
22275
+ const parsed = parseHostConfig(agent, path5, text, format);
22276
+ let out = text;
22277
+ const edits = [];
22278
+ for (const [key, after] of wanted) {
22279
+ const before = hostConfigValueAt(parsed, key);
22280
+ if (sameValue(before, after)) continue;
22281
+ out = setText(agent, path5, out, format, key, after);
22282
+ edits.push({ path: key.join("."), before, after });
20171
22283
  }
20172
- if (cur[path4[path4.length - 1]] !== void 0) throw new SyntaxError("duplicate key");
20173
- cur[path4[path4.length - 1]] = value;
22284
+ return { text: out, format, edits };
20174
22285
  }
20175
- function scanToml(text) {
20176
- const value = {};
20177
- const tables = [];
20178
- let table = value;
20179
- let i = 0;
20180
- while (i < text.length) {
20181
- const lineEnd = text.indexOf("\n", i) < 0 ? text.length : text.indexOf("\n", i) + 1;
20182
- const line = text.slice(i, lineEnd).trim();
20183
- if (line === "" || line.startsWith("#")) {
20184
- i = lineEnd;
22286
+ function mergeOwnEntries(agent, current, format, row5) {
22287
+ const parsed = parseHostConfig(row5.id, HOST_CONFIG_TEXT_PATH, current, format);
22288
+ const wanted = ownTargets(agent).map((t) => [t.key, t.next(hostConfigValueAt(parsed, t.key))]);
22289
+ return applyEdits(agent, HOST_CONFIG_TEXT_PATH, current, format, wanted);
22290
+ }
22291
+ function writeHostConfigEdit(_requested, current, patch) {
22292
+ const wanted = Object.entries(patch).map(([k, v]) => [[k], v]);
22293
+ const result = applyEdits(current.agent, current.path, current.text, current.format, wanted);
22294
+ if (result.edits.length === 0) return [];
22295
+ atomicWriteFile(current.path, current.layout === void 0 ? result.text : withLayout(result.text, current.layout));
22296
+ return result.edits;
22297
+ }
22298
+
22299
+ // src/core/ops/detect-v1.ts
22300
+ var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
22301
+ var keyPath = (...parts) => parts.join(".");
22302
+ var finding = (file2, path5, reason) => ({ file: file2, path: path5, reason });
22303
+ function stripJsonc(text) {
22304
+ let out = "";
22305
+ let inStr = false;
22306
+ let esc2 = false;
22307
+ for (let i = 0; i < text.length; i++) {
22308
+ const c = text[i];
22309
+ if (inStr) {
22310
+ out += c;
22311
+ if (esc2) esc2 = false;
22312
+ else if (c === "\\") esc2 = true;
22313
+ else if (c === '"') inStr = false;
20185
22314
  continue;
20186
22315
  }
20187
- if (line.startsWith("[")) {
20188
- if (line.startsWith("[[")) throw new SyntaxError("array of tables");
20189
- const close = line.indexOf("]");
20190
- if (close < 0) throw new SyntaxError("header");
20191
- const path4 = tomlKeyPath(line.slice(1, close));
20192
- if (tables.length > 0) tables[tables.length - 1].end = i;
20193
- tables.push({ path: path4, start: i, end: text.length });
20194
- let cur = value;
20195
- for (const seg of path4) {
20196
- if (cur[seg] === void 0) cur[seg] = {};
20197
- if (!isPlainObject3(cur[seg])) throw new SyntaxError("table conflict");
20198
- cur = cur[seg];
20199
- }
20200
- table = cur;
20201
- i = lineEnd;
22316
+ if (c === '"') {
22317
+ inStr = true;
22318
+ out += c;
20202
22319
  continue;
20203
22320
  }
20204
- const eq = text.indexOf("=", i);
20205
- if (eq < 0 || eq >= lineEnd) throw new SyntaxError("key/value");
20206
- const key = tomlKeyPath(text.slice(i, eq));
20207
- const reader = new TomlValue(text);
20208
- reader.i = eq + 1;
20209
- setPath(table, key, reader.read());
20210
- while (reader.i < text.length && (text[reader.i] === " " || text[reader.i] === " ")) reader.i += 1;
20211
- if (text[reader.i] === "#") while (reader.i < text.length && text[reader.i] !== "\n") reader.i += 1;
20212
- if (reader.i < text.length && text[reader.i] !== "\n" && text[reader.i] !== "\r") throw new SyntaxError("trailing text");
20213
- i = text.indexOf("\n", reader.i) < 0 ? text.length : text.indexOf("\n", reader.i) + 1;
22321
+ if (c === "/" && text[i + 1] === "/") {
22322
+ while (i < text.length && text[i] !== "\n") i++;
22323
+ out += "\n";
22324
+ continue;
22325
+ }
22326
+ if (c === "/" && text[i + 1] === "*") {
22327
+ const end = text.indexOf("*/", i + 2);
22328
+ i = end === -1 ? text.length : end + 1;
22329
+ continue;
22330
+ }
22331
+ if (c === ",") {
22332
+ let j = i + 1;
22333
+ while (j < text.length && " \r\n".includes(text[j])) j++;
22334
+ if (text[j] === "}" || text[j] === "]") continue;
22335
+ }
22336
+ out += c;
22337
+ }
22338
+ return out;
22339
+ }
22340
+ function readJson(file2) {
22341
+ try {
22342
+ return JSON.parse(stripJsonc(hostText(readFileSync7(file2, "utf8"))));
22343
+ } catch {
22344
+ return void 0;
22345
+ }
22346
+ }
22347
+ function readText(file2) {
22348
+ try {
22349
+ return hostText(readFileSync7(file2, "utf8"));
22350
+ } catch {
22351
+ return "";
22352
+ }
22353
+ }
22354
+ function readTomlTables(file2) {
22355
+ try {
22356
+ return tomlTableSpans(readText(file2));
22357
+ } catch {
22358
+ return [];
20214
22359
  }
20215
- return { value, tables };
20216
22360
  }
20217
- function parseHostConfig(agent, path4, text, format) {
20218
- try {
20219
- return format === "toml" ? scanToml(text).value : scanJson(text, format).value;
20220
- } catch {
20221
- throw new CtxError("CONFIG_PARSE_FAILED", { agent, path: path4, format });
22361
+ var listOf = (v) => Array.isArray(v) ? v : [];
22362
+ var commandOf = (v) => isObj(v) && typeof v.command === "string" ? v.command : null;
22363
+ function nestedCommands(doc) {
22364
+ const out = [];
22365
+ if (!isObj(doc) || !isObj(doc[HOOKS_KEY])) return out;
22366
+ for (const [event, groups] of Object.entries(doc[HOOKS_KEY])) {
22367
+ listOf(groups).forEach((group, i) => {
22368
+ if (!isObj(group)) return;
22369
+ listOf(group[HOOKS_KEY]).forEach((inner, j) => {
22370
+ const command = commandOf(inner);
22371
+ if (command !== null) out.push({ path: keyPath(HOOKS_KEY, event, i, HOOKS_KEY, j), command });
22372
+ });
22373
+ });
22374
+ }
22375
+ return out;
22376
+ }
22377
+ function flatCommands(events, prefix) {
22378
+ const out = [];
22379
+ if (!isObj(events)) return out;
22380
+ for (const [event, entries] of Object.entries(events)) {
22381
+ listOf(entries).forEach((entry, i) => {
22382
+ const command = commandOf(entry);
22383
+ if (command !== null) out.push({ path: keyPath(...prefix, event, i), command });
22384
+ });
22385
+ }
22386
+ return out;
22387
+ }
22388
+ var isV1Hook = (cmd) => cmd.includes(SERVER_KEY) && (V1_SCRIPT_NAMES.some((name) => cmd.includes(name)) || cmd.includes(V1_HOOK_COMMAND));
22389
+ var isCodexScript = (cmd) => cmd.includes(V1_SCRIPT_EXT) && V1_PATH_SEPS.some((sep3) => cmd.includes(V1_CODEX_HOOKS_DIR.join(sep3) + sep3));
22390
+ function dataDir(dir, reason, out) {
22391
+ if (existsSync4(dir)) out.push(finding(dir, "", reason));
22392
+ }
22393
+ function mcpEntry(file2, doc, out) {
22394
+ if (isObj(doc) && isObj(doc[MCP_SERVERS_KEY]) && Object.hasOwn(doc[MCP_SERVERS_KEY], SERVER_KEY)) {
22395
+ out.push(finding(file2, keyPath(MCP_SERVERS_KEY, SERVER_KEY), V1_REASON.mcpEntry));
20222
22396
  }
20223
22397
  }
20224
- function hostConfigValueAt(value, path4) {
20225
- let cur = value;
20226
- for (const seg of path4) {
20227
- if (!isPlainObject3(cur)) return void 0;
20228
- cur = cur[seg];
22398
+ function claudeShapeSettings(agentHome, out) {
22399
+ const file2 = join8(agentHome, SETTINGS_FILE);
22400
+ const doc = readJson(file2);
22401
+ for (const c of nestedCommands(doc)) {
22402
+ if (c.command.includes(V1_CACHE_HEAL_NAME)) out.push(finding(file2, c.path, V1_REASON.cacheHealHook));
22403
+ else if (isV1Hook(c.command)) out.push(finding(file2, c.path, V1_REASON.hook));
20229
22404
  }
20230
- return cur;
22405
+ const status = isObj(doc) ? commandOf(doc[STATUS_LINE_KEY]) : null;
22406
+ if (status !== null && status.includes(V1_STATUSLINE_COMMAND)) {
22407
+ out.push(finding(file2, STATUS_LINE_KEY, V1_REASON.statusLine));
22408
+ }
22409
+ mcpEntry(file2, doc, out);
20231
22410
  }
20232
- function isPlainObject3(v) {
20233
- return typeof v === "object" && v !== null && !Array.isArray(v);
22411
+ function v1HookFile(file2, out) {
22412
+ const doc = readJson(file2);
22413
+ const cmds = isObj(doc) ? flatCommands(doc[HOOKS_KEY], [HOOKS_KEY]) : [];
22414
+ if (cmds.some((c) => c.command.includes(V1_HOOK_COMMAND))) out.push(finding(file2, "", V1_REASON.hookFile));
20234
22415
  }
20235
- function sameValue(a, b) {
20236
- if (a === b) return true;
20237
- if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((x, k) => sameValue(x, b[k]));
20238
- if (isPlainObject3(a) && isPlainObject3(b)) {
20239
- const ka = Object.keys(a);
20240
- return ka.length === Object.keys(b).length && ka.every((k) => sameValue(a[k], b[k]));
22416
+ function scanClaudeCode(home, agentHome, out) {
22417
+ claudeShapeSettings(agentHome, out);
22418
+ for (const ext of V1_CACHE_HEAL_EXTS) {
22419
+ const file2 = join8(agentHome, V1_HOOKS_DIR_NAME, V1_CACHE_HEAL_NAME + ext);
22420
+ if (existsSync4(file2)) out.push(finding(file2, "", V1_REASON.cacheHealFile));
20241
22421
  }
20242
- return false;
20243
- }
20244
- function lineIndent(text, at2) {
20245
- let s = at2;
20246
- while (s > 0 && text[s - 1] !== "\n") s -= 1;
20247
- let e = s;
20248
- while (text[e] === " " || text[e] === " ") e += 1;
20249
- return text.slice(s, e);
22422
+ const userFile = join8(home, CLAUDE_USER_CONFIG_FILE);
22423
+ mcpEntry(userFile, readJson(userFile), out);
22424
+ dataDir(join8(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
20250
22425
  }
20251
- function indentUnit(root, clean) {
20252
- if (root === null || root.kind !== "object" || root.members.length === 0) return JSON_INDENT_UNIT;
20253
- const own2 = lineIndent(clean, root.members[0].keyStart);
20254
- return own2 === "" ? JSON_INDENT_UNIT : own2;
22426
+ function scanCodex(agentHome, out) {
22427
+ const hooksFile = join8(agentHome, HOOKS_JSON_FILE);
22428
+ for (const c of nestedCommands(readJson(hooksFile))) {
22429
+ if (c.command.includes(V1_CODEX_HOOK_COMMAND) || isCodexScript(c.command)) {
22430
+ out.push(finding(hooksFile, c.path, V1_REASON.codexHook));
22431
+ }
22432
+ }
22433
+ const tomlFile = join8(agentHome, CONFIG_TOML_FILE);
22434
+ for (const span of readTomlTables(tomlFile)) {
22435
+ if (tomlHeaderText(span.path).startsWith(V1_TOML_SECTION_PREFIX)) out.push(finding(tomlFile, span.header.trim(), V1_REASON.codexToml));
22436
+ }
22437
+ dataDir(join8(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
20255
22438
  }
20256
- function render(value, unit, base) {
20257
- return JSON.stringify(value, null, unit).split("\n").join("\n" + base);
22439
+ function scanGemini(agentHome, out) {
22440
+ const file2 = join8(agentHome, SETTINGS_FILE);
22441
+ for (const c of nestedCommands(readJson(file2))) {
22442
+ if (c.command.includes(SERVER_KEY)) out.push(finding(file2, c.path, V1_REASON.hook));
22443
+ }
22444
+ dataDir(join8(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDirShared, out);
20258
22445
  }
20259
- function nest(path4, value) {
20260
- let out = value;
20261
- for (let k = path4.length - 1; k >= 0; k -= 1) out = { [path4[k]]: out };
20262
- return out;
22446
+ function scanVscode(agentHome, project, out) {
22447
+ if (project !== void 0) {
22448
+ v1HookFile(join8(project, GITHUB_DIR_NAME, V1_HOOKS_DIR_NAME, OWN_HOOK_FILE), out);
22449
+ const mcpFile2 = join8(project, VSCODE_DIR_NAME, VSCODE_MCP_FILE);
22450
+ const doc = readJson(mcpFile2);
22451
+ const servers = isObj(doc) && isObj(doc[VSCODE_MCP_SERVERS_KEY]) ? doc[VSCODE_MCP_SERVERS_KEY] : {};
22452
+ const entry = Object.hasOwn(servers, SERVER_KEY) ? servers[SERVER_KEY] : void 0;
22453
+ if (isObj(entry) && (entry.command === V1_BIN_COMMAND || listOf(entry.args).some((a) => a === V1_BIN_COMMAND))) {
22454
+ out.push(finding(mcpFile2, keyPath(VSCODE_MCP_SERVERS_KEY, SERVER_KEY), V1_REASON.vscodeMcp));
22455
+ }
22456
+ dataDir(join8(project, GITHUB_DIR_NAME, V1_DATA_DIR_NAME, V1_SESSIONS_DIR_NAME), V1_REASON.dataDir, out);
22457
+ }
22458
+ dataDir(join8(agentHome, V1_DATA_DIR_NAME, V1_SESSIONS_DIR_NAME), V1_REASON.dataDir, out);
20263
22459
  }
20264
- function setJsonText(text, format, path4, value) {
20265
- const doc = scanJson(text, format);
20266
- const unit = indentUnit(doc.root, doc.clean);
20267
- if (doc.root === null) return render(nest(path4, value), unit, "") + "\n";
20268
- let node = doc.root;
20269
- let depth = 0;
20270
- while (depth < path4.length && node.kind === "object") {
20271
- const hit = node.members.find((m) => m.key === path4[depth]);
20272
- if (hit === void 0) break;
20273
- node = hit.node;
20274
- depth += 1;
22460
+ function jsonFiles(dir) {
22461
+ try {
22462
+ return readdirSync(dir).filter((name) => name.endsWith(KIRO_AGENT_FILE_EXT)).sort();
22463
+ } catch {
22464
+ return [];
20275
22465
  }
20276
- if (depth === path4.length) {
20277
- return text.slice(0, node.start) + render(value, unit, lineIndent(doc.clean, node.start)) + text.slice(node.end);
22466
+ }
22467
+ function scanKiro(agentHome, project, out) {
22468
+ const agentsDir = join8(agentHome, KIRO_AGENTS_DIR);
22469
+ const defaultFile = join8(agentHome, ...KIRO_AGENT_FILE);
22470
+ for (const name of jsonFiles(agentsDir)) {
22471
+ const file2 = join8(agentsDir, name);
22472
+ const doc = readJson(file2);
22473
+ if (isObj(doc) && doc[KIRO_AGENT_NAME_KEY] === SERVER_KEY) {
22474
+ out.push(finding(file2, "", V1_REASON.kiroAgentFile));
22475
+ continue;
22476
+ }
22477
+ if (file2 !== defaultFile) continue;
22478
+ for (const c of isObj(doc) ? flatCommands(doc[HOOKS_KEY], [HOOKS_KEY]) : []) {
22479
+ if (isV1Hook(c.command)) out.push(finding(file2, c.path, V1_REASON.kiroHook));
22480
+ }
20278
22481
  }
20279
- if (node.kind !== "object") throw new SyntaxError("not an object at " + path4.slice(0, depth).join("."));
20280
- const rest = nest(path4.slice(depth + 1), value);
20281
- const last = node.members[node.members.length - 1];
20282
- if (last === void 0) {
20283
- const base2 = lineIndent(doc.clean, node.start);
20284
- const member2 = "\n" + base2 + unit + JSON.stringify(path4[depth]) + ": " + render(rest, unit, base2 + unit) + "\n" + base2;
20285
- return text.slice(0, node.start + 1) + member2 + text.slice(node.end - 1);
22482
+ const steeringDocs = [join8(agentHome, ...KIRO_STEERING_FILE)];
22483
+ if (project !== void 0) steeringDocs.push(join8(project, ...AGENT_HOME_DIR.kiro, ...KIRO_STEERING_FILE));
22484
+ for (const file2 of steeringDocs) {
22485
+ if (existsSync4(file2)) out.push(finding(file2, "", V1_REASON.kiroSteering));
20286
22486
  }
20287
- const base = lineIndent(doc.clean, last.keyStart);
20288
- let at2 = last.node.end;
20289
- while (" \r\n".includes(doc.clean[at2])) at2 += 1;
20290
- const trailing = doc.clean[at2] === ",";
20291
- const insertAt = trailing ? at2 + 1 : last.node.end;
20292
- const member = (trailing ? "" : ",") + "\n" + base + JSON.stringify(path4[depth]) + ": " + render(rest, unit, base);
20293
- return text.slice(0, insertAt) + member + text.slice(insertAt);
22487
+ dataDir(join8(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
20294
22488
  }
20295
- function tomlScalar(v) {
20296
- if (Array.isArray(v)) return "[" + v.map(tomlScalar).join(", ") + "]";
20297
- if (typeof v === "string") return JSON.stringify(v);
20298
- if (typeof v === "number" || typeof v === "boolean") return String(v);
20299
- throw new SyntaxError("unsupported TOML value");
22489
+ function scanPi(piAgentDir, agentHome, out) {
22490
+ const file2 = join8(piAgentDir, SETTINGS_FILE);
22491
+ const doc = readJson(file2);
22492
+ listOf(isObj(doc) ? doc[PI_PACKAGES_KEY] : void 0).forEach((pkg, i) => {
22493
+ const spec = isObj(pkg) ? pkg[PI_PACKAGE_SOURCE_KEY] : pkg;
22494
+ if (spec === V1_PI_PACKAGE) out.push(finding(file2, keyPath(PI_PACKAGES_KEY, i), V1_REASON.piNpm));
22495
+ });
22496
+ dataDir(join8(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
20300
22497
  }
20301
- function tomlHeaderKey(seg) {
20302
- for (const ch of seg) {
20303
- const bare2 = ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "_" || ch === "-";
20304
- if (!bare2) return JSON.stringify(seg);
22498
+ function scanOpencode(agentHome, out) {
22499
+ for (const name of OPENCODE_CONFIG_FILES) {
22500
+ const file2 = join8(agentHome, name);
22501
+ const doc = readJson(file2);
22502
+ if (!isObj(doc) || !Array.isArray(doc[OPENCODE_PLUGIN_KEY])) continue;
22503
+ doc[OPENCODE_PLUGIN_KEY].forEach((spec, i) => {
22504
+ if (spec === V1_OPENCODE_PLUGIN_SPEC) out.push(finding(file2, keyPath(OPENCODE_PLUGIN_KEY, i), V1_REASON.opencodePlugin));
22505
+ });
22506
+ return;
20305
22507
  }
20306
- return seg;
20307
22508
  }
20308
- function tomlBlock(path4, value) {
20309
- let out = "[" + path4.map(tomlHeaderKey).join(".") + "]\n";
20310
- const subs = [];
20311
- for (const [k, v] of Object.entries(value)) {
20312
- if (isPlainObject3(v)) subs.push(tomlBlock([...path4, k], v));
20313
- else out += tomlHeaderKey(k) + " = " + tomlScalar(v) + "\n";
22509
+ function scanZcode(agentHome, out) {
22510
+ const configFile = join8(agentHome, ZCODE_CLI_DIR, CONFIG_JSON_FILE);
22511
+ const config2 = readJson(configFile);
22512
+ const events = isObj(config2) && isObj(config2[HOOKS_KEY]) ? config2[HOOKS_KEY][ZCODE_EVENTS_KEY] : void 0;
22513
+ for (const c of flatCommands(events, [HOOKS_KEY, ZCODE_EVENTS_KEY])) {
22514
+ if (c.command.includes(V1_HOOK_COMMAND)) out.push(finding(configFile, c.path, V1_REASON.zcodeHook));
22515
+ }
22516
+ const hooksFile = join8(agentHome, ZCODE_CLI_DIR, HOOKS_JSON_FILE);
22517
+ for (const c of nestedCommands(readJson(hooksFile))) {
22518
+ if (c.command.includes(V1_HOOK_COMMAND)) out.push(finding(hooksFile, c.path, V1_REASON.zcodeHook));
20314
22519
  }
20315
- return [out, ...subs].join("\n");
20316
22520
  }
20317
- function setTomlText(text, path4, value) {
20318
- if (!isPlainObject3(value)) throw new SyntaxError("TOML edits replace a whole table");
20319
- const doc = scanToml(text);
20320
- const owned = doc.tables.filter((t) => t.path.length >= path4.length && path4.every((seg, k) => t.path[k] === seg));
20321
- const block = tomlBlock(path4, value);
20322
- if (owned.length === 0) {
20323
- const sep3 = text === "" ? "" : text.endsWith("\n\n") ? "" : text.endsWith("\n") ? "\n" : "\n\n";
20324
- return text + sep3 + block;
20325
- }
20326
- let out = text.slice(0, owned[0].start) + block;
20327
- let cursor = owned[0].end;
20328
- for (const t of owned.slice(1)) {
20329
- out += text.slice(cursor, t.start).trim() === "" ? "" : text.slice(cursor, t.start);
20330
- cursor = t.end;
20331
- }
20332
- const tail = text.slice(cursor);
20333
- return out + (tail === "" || block.endsWith("\n\n") ? "" : "\n") + tail;
20334
- }
20335
- function setText(agent, path4, text, format, key, value) {
22521
+ function firstTmpMatch(dir) {
22522
+ let handle;
20336
22523
  try {
20337
- return format === "toml" ? setTomlText(text, key, value) : setJsonText(text, format, key, value);
22524
+ handle = opendirSync(dir);
20338
22525
  } catch {
20339
- throw new CtxError("CONFIG_PARSE_FAILED", { agent, path: path4, format });
22526
+ return null;
20340
22527
  }
20341
- }
20342
- function serverScript() {
20343
- return join8(dirname4(process.argv[1] ?? ""), SERVER_ENTRY_FILE);
20344
- }
20345
- function listTarget(key, own2, v1) {
20346
- return {
20347
- key: [key],
20348
- next(current) {
20349
- const list3 = Array.isArray(current) ? current.filter((x) => x !== v1) : [];
20350
- return list3.includes(own2) ? list3 : [...list3, own2];
22528
+ try {
22529
+ for (let e = handle.readSync(); e !== null; e = handle.readSync()) {
22530
+ if (e.name.startsWith(V1_TMP_PREFIX)) return e.name;
20351
22531
  }
20352
- };
20353
- }
20354
- function ownTargets(agent) {
20355
- const mcp = OWN_MCP_ENTRY[agent];
20356
- if (mcp !== void 0) {
20357
- return [{
20358
- key: mcp.key,
20359
- next(current) {
20360
- const keep = isPlainObject3(current) ? current : {};
20361
- return { ...keep, ...mcp.fields, [MCP_COMMAND_FIELD]: HOST_NODE_COMMAND, [MCP_ARGS_FIELD]: [serverScript(), AGENT_ARG, agent] };
20362
- }
20363
- }, ...(mcp.also ?? []).map(([key, value]) => ({ key, next: () => value }))];
20364
- }
20365
- if (agent === "opencode") return [listTarget(OPENCODE_PLUGIN_KEY, OPENCODE_GIT_SPEC, V1_OPENCODE_PLUGIN_SPEC)];
20366
- if (agent === "pi") return [listTarget(PI_PACKAGES_KEY, PI_GIT_PACKAGE, V1_PI_PACKAGE)];
20367
- return [];
20368
- }
20369
- function applyEdits(agent, path4, text, format, wanted) {
20370
- const parsed = parseHostConfig(agent, path4, text, format);
20371
- let out = text;
20372
- const edits = [];
20373
- for (const [key, after] of wanted) {
20374
- const before = hostConfigValueAt(parsed, key);
20375
- if (sameValue(before, after)) continue;
20376
- out = setText(agent, path4, out, format, key, after);
20377
- edits.push({ path: key.join("."), before, after });
22532
+ return null;
22533
+ } catch {
22534
+ return null;
22535
+ } finally {
22536
+ handle.closeSync();
20378
22537
  }
20379
- return { text: out, format, edits };
20380
22538
  }
20381
- function mergeOwnEntries(agent, current, format, row5) {
20382
- const parsed = parseHostConfig(row5.id, HOST_CONFIG_TEXT_PATH, current, format);
20383
- const wanted = ownTargets(agent).map((t) => [t.key, t.next(hostConfigValueAt(parsed, t.key))]);
20384
- return applyEdits(agent, HOST_CONFIG_TEXT_PATH, current, format, wanted);
22539
+ function scanAll(home, tmp, out) {
22540
+ const root = join8(home, DATA_ROOT.slice(1));
22541
+ for (const name of V1_DATA_ROOT_ENTRIES) dataDir(join8(root, name), V1_REASON.dataRoot, out);
22542
+ if (firstTmpMatch(tmp) !== null) out.push(finding(tmp, V1_TMP_PREFIX + "*", V1_REASON.tmpFile));
20385
22543
  }
20386
- function writeHostConfigEdit(_requested, current, patch) {
20387
- const wanted = Object.entries(patch).map(([k, v]) => [[k], v]);
20388
- const result = applyEdits(current.agent, current.path, current.text, current.format, wanted);
20389
- if (result.edits.length === 0) return [];
20390
- const tmp = current.path + HOST_CONFIG_TMP_SUFFIX;
20391
- writeFileSync(tmp, result.text, "utf8");
20392
- renameSync(tmp, current.path);
20393
- return result.edits;
22544
+ function detectV1(agent, home, scope = {}) {
22545
+ const out = [];
22546
+ const project = scope.project;
22547
+ const agentHome = agent === "claude-code" && scope.claudeDir !== void 0 ? scope.claudeDir : agent === "copilot-cli" && scope.copilotDir !== void 0 ? scope.copilotDir : agent === "kiro" && scope.kiroDir !== void 0 ? scope.kiroDir : agent === "opencode" && scope.opencodeDir !== void 0 ? scope.opencodeDir : join8(home, ...AGENT_HOME_DIR[agent]);
22548
+ switch (agent) {
22549
+ case "claude-code":
22550
+ scanClaudeCode(home, agentHome, out);
22551
+ break;
22552
+ case "codex":
22553
+ scanCodex(agentHome, out);
22554
+ break;
22555
+ case "gemini":
22556
+ scanGemini(agentHome, out);
22557
+ break;
22558
+ case "qwen":
22559
+ claudeShapeSettings(agentHome, out);
22560
+ dataDir(join8(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
22561
+ break;
22562
+ case "copilot-cli":
22563
+ v1HookFile(join8(agentHome, V1_HOOKS_DIR_NAME, OWN_HOOK_FILE), out);
22564
+ dataDir(join8(agentHome, V1_DATA_DIR_NAME), V1_REASON.dataDir, out);
22565
+ break;
22566
+ case "vscode":
22567
+ scanVscode(agentHome, project, out);
22568
+ break;
22569
+ case "kiro":
22570
+ scanKiro(agentHome, project, out);
22571
+ break;
22572
+ case "pi":
22573
+ scanPi(scope.piAgentDir !== void 0 && scope.piAgentDir !== "" ? scope.piAgentDir : join8(agentHome, PI_AGENT_DIR), agentHome, out);
22574
+ break;
22575
+ // D-WIN-PIDIR-1: empty is unset
22576
+ case "opencode":
22577
+ scanOpencode(agentHome, out);
22578
+ break;
22579
+ case "zcode":
22580
+ scanZcode(agentHome, out);
22581
+ break;
22582
+ }
22583
+ scanAll(home, scope.tmp ?? tmpdir(), out);
22584
+ return out;
20394
22585
  }
20395
22586
 
20396
22587
  // src/core/ops/plugin-root.ts
20397
22588
  import { existsSync as existsSync5, readdirSync as readdirSync2, realpathSync as realpathSync4 } from "node:fs";
20398
22589
  import { dirname as dirname5, isAbsolute as isAbsolute2, join as join9 } from "node:path";
20399
22590
  import { fileURLToPath } from "node:url";
20400
- function homeOf2(env) {
20401
- const home = homeDirOf(env);
20402
- if (home === null) throw new CtxError("NO_HOME", { name: process.platform === "win32" ? "USERPROFILE" : "HOME" });
20403
- return home;
20404
- }
20405
- function missing(agent, path4) {
20406
- return new CtxError("PLUGIN_ROOT_MISSING", { agent, path: path4 });
22591
+ function missing(agent, path5) {
22592
+ return new CtxError("PLUGIN_ROOT_MISSING", { agent, path: path5 });
20407
22593
  }
20408
22594
  function marketplaceRoot(adapter, env) {
20409
- const cache = join9(homeOf2(env), HOST_CONFIG_DIR_NAME, HOST_PLUGINS_DIR_NAME, PLUGIN_CACHE_DIR_NAME);
22595
+ const cache = join9(claudeDirOf(env, requireHomeDir(env)), HOST_PLUGINS_DIR_NAME, PLUGIN_CACHE_DIR_NAME);
20410
22596
  const pattern = join9(cache, "*", PLUGIN_NAME);
20411
22597
  if (!existsSync5(cache)) throw missing(adapter.id, pattern);
20412
22598
  const found = readdirSync2(cache).sort().map((marketplace) => join9(cache, marketplace, PLUGIN_NAME)).filter((dir) => existsSync5(dir));
@@ -20416,7 +22602,7 @@ function marketplaceRoot(adapter, env) {
20416
22602
  function configEntryRoot(adapter, env) {
20417
22603
  const spec = OWN_MCP_ENTRY[adapter.id];
20418
22604
  if (spec === void 0) throw missing(adapter.id, SERVER_KEY);
20419
- const file2 = join9(homeOf2(env), ...spec.file);
22605
+ const file2 = ownMcpFileOf(adapter.id, spec.file, env, requireHomeDir(env));
20420
22606
  if (!existsSync5(file2)) throw missing(adapter.id, file2);
20421
22607
  const current = readHostConfig(adapter.id, file2);
20422
22608
  const value = parseHostConfig(adapter.id, file2, current.text, current.format);
@@ -20434,7 +22620,7 @@ function candidate(adapter, env) {
20434
22620
  case "hooks+mcp":
20435
22621
  return configEntryRoot(adapter, env);
20436
22622
  case "extension":
20437
- return join9(homeOf2(env), ...AGENT_HOME_DIR[adapter.id], EXTENSIONS_DIR_NAME, PLUGIN_NAME);
22623
+ return join9(requireHomeDir(env), ...AGENT_HOME_DIR[adapter.id], EXTENSIONS_DIR_NAME, PLUGIN_NAME);
20438
22624
  case "plugin":
20439
22625
  return join9(resolveConfigDir(env), DATA_PLUGINS_DIR_NAME, adapter.id, PLUGIN_CURRENT_LINK);
20440
22626
  case "in-process":
@@ -20442,11 +22628,11 @@ function candidate(adapter, env) {
20442
22628
  }
20443
22629
  }
20444
22630
  function resolvePluginRoot(adapter, env) {
20445
- const path4 = candidate(adapter, env);
22631
+ const path5 = candidate(adapter, env);
20446
22632
  try {
20447
- return realpathSync4.native(path4);
22633
+ return realpathSync4.native(path5);
20448
22634
  } catch {
20449
- throw missing(adapter.id, path4);
22635
+ throw missing(adapter.id, path5);
20450
22636
  }
20451
22637
  }
20452
22638
 
@@ -20472,14 +22658,31 @@ function composeMatcher(row5, event) {
20472
22658
  if (event === POST_TOOL_USE && hasReplace(row5)) alts.push(MCP_ANY_MATCH);
20473
22659
  return MATCHER_OPEN + alts.join(MATCHER_ALT) + MATCHER_CLOSE;
20474
22660
  }
22661
+ var lastSegment = (p) => {
22662
+ let at2 = -1;
22663
+ for (const sep3 of V1_PATH_SEPS) at2 = Math.max(at2, p.lastIndexOf(sep3));
22664
+ return p.slice(at2 + 1);
22665
+ };
22666
+ function splitHead(command) {
22667
+ if (command.startsWith(SHELL_QUOTE)) {
22668
+ const close = command.indexOf(SHELL_QUOTE, 1);
22669
+ if (close < 0 || command.slice(close + 1, close + 1 + HOOK_COMMAND_SEP.length) !== HOOK_COMMAND_SEP) return null;
22670
+ return { head: command.slice(1, close), rest: command.slice(close + 1 + HOOK_COMMAND_SEP.length) };
22671
+ }
22672
+ const end = command.indexOf(HOOK_COMMAND_SEP);
22673
+ return end < 0 ? null : { head: command.slice(0, end), rest: command.slice(end + HOOK_COMMAND_SEP.length) };
22674
+ }
20475
22675
  function isOwnCommand(command, agent) {
20476
22676
  if (typeof command !== "string") return false;
20477
- const head = HOST_NODE_COMMAND + HOOK_COMMAND_SEP;
22677
+ const split = splitHead(command);
22678
+ if (split === null) return false;
22679
+ const exe = lastSegment(split.head).toLowerCase();
22680
+ if (exe !== HOST_NODE_COMMAND && exe !== HOST_NODE_COMMAND + EXE_SUFFIX) return false;
20478
22681
  const tail = HOOK_COMMAND_SEP + AGENT_ARG + HOOK_COMMAND_SEP + agent;
20479
- if (!command.startsWith(head) || !command.endsWith(tail) || command.length <= head.length + tail.length) return false;
20480
- let script = command.slice(head.length, command.length - tail.length);
22682
+ if (!split.rest.endsWith(tail) || split.rest.length <= tail.length) return false;
22683
+ let script = split.rest.slice(0, split.rest.length - tail.length);
20481
22684
  if (script.startsWith(SHELL_QUOTE) && script.endsWith(SHELL_QUOTE) && script.length > 1) script = script.slice(1, -1);
20482
- return script === HOOK_ENTRY_FILE || V1_PATH_SEPS.some((sep3) => script.endsWith(sep3 + HOOK_ENTRY_FILE));
22685
+ return script === HOOK_ENTRY_FILE || HOOK_SCRIPT_SEPS.some((sep3) => script.endsWith(sep3 + HOOK_ENTRY_FILE));
20483
22686
  }
20484
22687
  function ownHooks(block, shape, timeoutKey, native, agent) {
20485
22688
  const out = [];
@@ -20511,11 +22714,10 @@ var validTimeout = (v) => typeof v === "number" && Number.isFinite(v) && v > 0;
20511
22714
  function mcpFile(row5, home, env) {
20512
22715
  const spec = OWN_MCP_ENTRY[row5.id];
20513
22716
  if (row5.id === "codex") return join10(codexDirOf(env, home), CONFIG_TOML_FILE);
20514
- if (spec !== void 0) return join10(home, ...spec.file);
20515
- if (row5.id === "opencode") return join10(home, ...AGENT_HOME_DIR.opencode, OPENCODE_BASE_CONFIG_FILE);
22717
+ if (spec !== void 0) return ownMcpFileOf(row5.id, spec.file, env, home);
22718
+ if (row5.id === "opencode") return join10(opencodeDirOf(env, home), OPENCODE_BASE_CONFIG_FILE);
20516
22719
  if (row5.id === "pi") {
20517
- const dir = env[PI_AGENT_DIR_ENV];
20518
- return join10(dir !== void 0 && dir !== "" ? dir : join10(home, ...AGENT_HOME_DIR.pi, PI_AGENT_DIR), SETTINGS_FILE);
22720
+ return join10(piAgentDirOf(env, home), SETTINGS_FILE);
20519
22721
  }
20520
22722
  return null;
20521
22723
  }
@@ -20538,7 +22740,7 @@ function hookParts(row5, home, env, worktree) {
20538
22740
  let block;
20539
22741
  try {
20540
22742
  const root = spec.root === "plugin" ? resolvePluginRoot(row5, env) : spec.root === "home" ? home : worktree;
20541
- const file2 = row5.id === "codex" ? join10(codexDirOf(env, home), HOOKS_JSON_FILE) : join10(root, ...spec.file);
22743
+ const file2 = row5.id === "codex" ? join10(codexDirOf(env, home), HOOKS_JSON_FILE) : row5.id === "copilot-cli" ? join10(copilotDirOf(env, home), ...spec.file.slice(1)) : row5.id === "kiro" ? join10(kiroDirOf(env, home), ...spec.file.slice(1)) : join10(root, ...spec.file);
20542
22744
  block = hostConfigValueAt(readParsed(row5.id, file2).value, spec.key);
20543
22745
  if (row5.id === "codex") {
20544
22746
  const config2 = readParsed(row5.id, join10(codexDirOf(env, home), CONFIG_TOML_FILE)).value;
@@ -20620,8 +22822,8 @@ async function loadSqlite2() {
20620
22822
  return null;
20621
22823
  }
20622
22824
  }
20623
- function openRead(sqlite, path4) {
20624
- return new sqlite.DatabaseSync(path4, { timeout: DB_TIMEOUT_MS, readOnly: true });
22825
+ function openRead(sqlite, path5) {
22826
+ return new sqlite.DatabaseSync(path5, { timeout: DB_TIMEOUT_MS, readOnly: true });
20625
22827
  }
20626
22828
  var cell = (row5) => Object.values(row5)[0];
20627
22829
  function readSchema(raw) {
@@ -20755,20 +22957,26 @@ function checkProject(i) {
20755
22957
  function checkMode(adapter) {
20756
22958
  return pass3("D10", D10_DETAIL(adapter.denyChannel));
20757
22959
  }
22960
+ function checkShell(env) {
22961
+ const win = process.platform === "win32";
22962
+ const shell = findRuntime("shell", env);
22963
+ if (shell !== null) return pass3("D11", D11_PASS_DETAIL(shell, win));
22964
+ return win ? fail4("D11", D11_WIN_DETAIL, D11_WIN_FIX) : fail4("D11", D11_POSIX_DETAIL, D11_POSIX_FIX);
22965
+ }
20758
22966
 
20759
22967
  // src/core/ops/doctor-hook.ts
20760
22968
  import { existsSync as existsSync8, readFileSync as readFileSync8 } from "node:fs";
20761
- import path3 from "node:path";
22969
+ import path4 from "node:path";
20762
22970
  var row = (status, detail, fixCommand) => fixCommand === void 0 ? { id: "D5", label: DOCTOR_LABEL.D5, status, detail } : { id: "D5", label: DOCTOR_LABEL.D5, status, detail, fixCommand };
20763
22971
  function isObject5(v) {
20764
22972
  return typeof v === "object" && v !== null && !Array.isArray(v);
20765
22973
  }
20766
22974
  function loadFixture(bundleDir2, agent) {
20767
- const file2 = path3.join(bundleDir2, HOOK_FIXTURE_DIR, HOOK_FIXTURE_FILE);
22975
+ const file2 = path4.join(bundleDir2, HOOK_FIXTURE_DIR, HOOK_FIXTURE_FILE);
20768
22976
  if (!existsSync8(file2)) return null;
20769
22977
  let all;
20770
22978
  try {
20771
- all = JSON.parse(readFileSync8(file2, "utf8"));
22979
+ all = JSON.parse(hostText(readFileSync8(file2, "utf8")));
20772
22980
  } catch {
20773
22981
  return null;
20774
22982
  }
@@ -20793,14 +23001,14 @@ function codexHookJournaled(db) {
20793
23001
  return db.raw.prepare("SELECT 1 FROM events WHERE agent = ? LIMIT 1").get("codex") !== void 0;
20794
23002
  }
20795
23003
  async function checkHookRoundTrip(i) {
20796
- if (i.agent === "codex" && existsSync8(path3.join(i.codexConfigDir, HOOKS_JSON_FILE)) && !codexHookJournaled(i.db)) {
23004
+ if (i.agent === "codex" && existsSync8(path4.join(i.codexConfigDir, HOOKS_JSON_FILE)) && !codexHookJournaled(i.db)) {
20797
23005
  return row("UNKNOWN", D5_CODEX_UNTRUSTED_DETAIL);
20798
23006
  }
20799
23007
  const fixture = loadFixture(i.bundleDir, i.agent);
20800
23008
  if (fixture === null) return row("UNKNOWN", D5_NO_FIXTURE_DETAIL(i.agent));
20801
23009
  const now = i.now ?? (() => performance.now());
20802
23010
  const start = now();
20803
- const r = await runProcess([process.execPath, path3.join(i.bundleDir, HOOK_ENTRY_FILE), AGENT_ARG, i.agent], {
23011
+ const r = await runProcess([process.execPath, path4.join(i.bundleDir, HOOK_ENTRY_FILE), AGENT_ARG, i.agent], {
20804
23012
  cwd: i.bundleDir,
20805
23013
  env: i.env,
20806
23014
  signal: i.signal,
@@ -20814,15 +23022,15 @@ async function checkHookRoundTrip(i) {
20814
23022
  }
20815
23023
 
20816
23024
  // src/core/ops/db-heal.ts
20817
- import { existsSync as existsSync9, renameSync as renameSync2, rmSync as rmSync3 } from "node:fs";
23025
+ import { existsSync as existsSync9, rmSync as rmSync3 } from "node:fs";
20818
23026
 
20819
23027
  // src/core/store/owners.ts
20820
- import { mkdirSync as mkdirSync3, readdirSync as readdirSync3, readFileSync as readFileSync9, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
23028
+ import { mkdirSync as mkdirSync4, readdirSync as readdirSync3, readFileSync as readFileSync9, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
20821
23029
  import { basename as basename2, join as join11 } from "node:path";
20822
23030
  function ownersDir(configDir, projectKey) {
20823
23031
  return join11(configDir, PROJECTS_DIR_NAME, projectKey, OWNERS_DIR_NAME);
20824
23032
  }
20825
- function errCode(err) {
23033
+ function errCode2(err) {
20826
23034
  return err.code;
20827
23035
  }
20828
23036
  function isLive(pid) {
@@ -20831,8 +23039,8 @@ function isLive(pid) {
20831
23039
  process.kill(pid, 0);
20832
23040
  return true;
20833
23041
  } catch (err) {
20834
- if (errCode(err) === "ESRCH") return false;
20835
- if (errCode(err) === "EPERM") return true;
23042
+ if (errCode2(err) === "ESRCH") return false;
23043
+ if (errCode2(err) === "EPERM") return true;
20836
23044
  throw err;
20837
23045
  }
20838
23046
  }
@@ -20842,7 +23050,7 @@ function listLiveOwners(configDir, projectKey) {
20842
23050
  try {
20843
23051
  names = readdirSync3(dir);
20844
23052
  } catch (err) {
20845
- if (errCode(err) === "ENOENT") return [];
23053
+ if (errCode2(err) === "ENOENT") return [];
20846
23054
  throw err;
20847
23055
  }
20848
23056
  const live = [];
@@ -20853,7 +23061,7 @@ function listLiveOwners(configDir, projectKey) {
20853
23061
  try {
20854
23062
  text = readFileSync9(file2, "utf8");
20855
23063
  } catch (err) {
20856
- if (errCode(err) === "ENOENT") continue;
23064
+ if (errCode2(err) === "ENOENT") continue;
20857
23065
  throw err;
20858
23066
  }
20859
23067
  const serverId = basename2(name, OWNER_PID_EXT);
@@ -20888,7 +23096,7 @@ async function healLossless(dbPath) {
20888
23096
  }
20889
23097
  rmSync3(dbPath + DB_WAL_SUFFIX, { force: true });
20890
23098
  rmSync3(dbPath + DB_SHM_SUFFIX, { force: true });
20891
- renameSync2(tmp, dbPath);
23099
+ renameWithRetry(tmp, dbPath);
20892
23100
  } finally {
20893
23101
  rmSync3(tmp, { force: true });
20894
23102
  }
@@ -20897,7 +23105,7 @@ function renameAside(dbPath) {
20897
23105
  const ts = String(Date.now());
20898
23106
  for (const suffix of DB_SIBLING_SUFFIXES) {
20899
23107
  const file2 = dbPath + suffix;
20900
- if (existsSync9(file2)) renameSync2(file2, file2 + HEAL_TS_SEP + ts + HEAL_BACKUP_SUFFIX);
23108
+ if (existsSync9(file2)) renameWithRetry(file2, file2 + HEAL_TS_SEP + ts + HEAL_BACKUP_SUFFIX);
20901
23109
  }
20902
23110
  return ts;
20903
23111
  }
@@ -20965,11 +23173,6 @@ async function guard(id2, run) {
20965
23173
  return { id: id2, label: DOCTOR_LABEL[id2], status: "UNKNOWN", detail: lineOf2(err) };
20966
23174
  }
20967
23175
  }
20968
- function needHome(env) {
20969
- const home = homeDirOf(env);
20970
- if (home === null) throw new CtxError("NO_HOME", { name: "HOME" });
20971
- return home;
20972
- }
20973
23176
  async function codexDb(ctx, adapter) {
20974
23177
  if (adapter.id !== "codex" || !existsSync10(ctx.project.dbPath)) return null;
20975
23178
  try {
@@ -20986,7 +23189,7 @@ async function hookRow(ctx, adapter, host) {
20986
23189
  bundleDir: host.bundleDir,
20987
23190
  env: buildChildEnv(host.env),
20988
23191
  signal: ctx.signal,
20989
- codexConfigDir: codexDirOf(host.env, needHome(host.env)),
23192
+ codexConfigDir: codexDirOf(host.env, requireHomeDir(host.env)),
20990
23193
  // same Codex dir D3 reads (D-N6-CODEX-HOME-2)
20991
23194
  db
20992
23195
  });
@@ -21011,7 +23214,7 @@ async function runDoctorChecks(ctx, adapter, host) {
21011
23214
  D1: () => checkVersion({ bundleSha: BUNDLE_SHA, env: buildChildEnv(env), cwd: project.worktree, signal: ctx.signal }),
21012
23215
  D2: () => checkNode({ nodeVersion: process.version, bunVersion: process.versions.bun }),
21013
23216
  D3: () => checkHostConfig(adapter, env, project.worktree),
21014
- D4: () => checkV1Leftovers(adapter.id, needHome(env), { project: project.worktree, piAgentDir: env[PI_AGENT_DIR_ENV] }),
23217
+ D4: () => checkV1Leftovers(adapter.id, requireHomeDir(env), { project: project.worktree, piAgentDir: piAgentDirOf(env, requireHomeDir(env)), claudeDir: claudeDirOf(env, requireHomeDir(env)), copilotDir: copilotDirOf(env, requireHomeDir(env)), kiroDir: kiroDirOf(env, requireHomeDir(env)), opencodeDir: opencodeDirOf(env, requireHomeDir(env)) }),
21015
23218
  D5: () => hookRow(ctx, adapter, host),
21016
23219
  D5b: () => checkDoubleFire(adapter.id, project.worktree),
21017
23220
  D6: () => checkMcp(ctx),
@@ -21022,7 +23225,8 @@ async function runDoctorChecks(ctx, adapter, host) {
21022
23225
  return r.row;
21023
23226
  },
21024
23227
  D9: () => checkIndex(project),
21025
- D10: () => checkMode(adapter)
23228
+ D10: () => checkMode(adapter),
23229
+ D11: () => checkShell(env)
21026
23230
  };
21027
23231
  const rows = [];
21028
23232
  for (const id2 of DOCTOR_CHECK_ORDER) rows.push(await guard(id2, checks[id2]));
@@ -21214,7 +23418,7 @@ async function handler3(raw, ctx) {
21214
23418
  extra.CTX_FILE = abs;
21215
23419
  }
21216
23420
  const runtime = findRuntime(input.language);
21217
- if (runtime === null) return fail5(new CtxError("NO_RUNTIME", { lang: input.language }).toLine());
23421
+ if (runtime === null) return fail5(noRuntimeError(input.language).toLine());
21218
23422
  const env = buildChildEnv(process.env, extra);
21219
23423
  const timeoutMs = input.timeoutMs ?? EXEC_TIMEOUT_MS;
21220
23424
  const journal = { kind: "cmd", key: canonicalKey(TOOL2, input.code), path: input.file ?? null, exit_code: null };
@@ -21287,14 +23491,14 @@ function visit(abs, rel, parent, contain, seen, found) {
21287
23491
  const rules = entries.some((e) => e.name === GITIGNORE && e.isFile()) ? parent.concat(readRules(join14(abs, GITIGNORE), rel)) : parent;
21288
23492
  for (const e of entries) {
21289
23493
  if (e.name === GIT_DIR) continue;
21290
- const path4 = join14(abs, e.name);
23494
+ const path5 = join14(abs, e.name);
21291
23495
  let isDir = e.isDirectory();
21292
23496
  let isFile = e.isFile();
21293
- let target = path4;
23497
+ let target = path5;
21294
23498
  if (e.isSymbolicLink()) {
21295
23499
  let resolved;
21296
23500
  try {
21297
- resolved = realpathSync6(path4);
23501
+ resolved = realpathSync6(path5);
21298
23502
  } catch {
21299
23503
  continue;
21300
23504
  }
@@ -21307,12 +23511,12 @@ function visit(abs, rel, parent, contain, seen, found) {
21307
23511
  const segs = rel.concat(e.name);
21308
23512
  if (ignored(rules, segs, isDir)) continue;
21309
23513
  if (isFile) {
21310
- found.push({ dir: rel, name: e.name, absPath: path4 });
23514
+ found.push({ dir: rel, name: e.name, absPath: path5 });
21311
23515
  } else if (isDir) {
21312
- const key = e.isSymbolicLink() ? target : realpathSync6(path4);
23516
+ const key = e.isSymbolicLink() ? target : realpathSync6(path5);
21313
23517
  if (seen.has(key)) continue;
21314
23518
  seen.add(key);
21315
- visit(path4, segs, rules, contain, seen, found);
23519
+ visit(path5, segs, rules, contain, seen, found);
21316
23520
  }
21317
23521
  }
21318
23522
  }
@@ -21503,12 +23707,12 @@ function tlsName(host) {
21503
23707
  function request(u, conn, proxy, signal) {
21504
23708
  const host = bare(u.hostname);
21505
23709
  const port = u.port === "" ? defaultPort(u.protocol) : Number(u.port);
21506
- const path4 = u.pathname + u.search;
23710
+ const path5 = u.pathname + u.search;
21507
23711
  return new Promise((resolve5, reject) => {
21508
23712
  const onErr = (err) => reject(fail6(causeCode(err)));
21509
23713
  if (proxy === void 0) {
21510
23714
  const mod = u.protocol === "https:" ? https : http;
21511
- const req = mod.request({ host: conn.address, port, path: path4, signal, servername: tlsName(host), headers: { host: u.host } });
23715
+ const req = mod.request({ host: conn.address, port, path: path5, signal, servername: tlsName(host), headers: { host: u.host } });
21512
23716
  req.on("response", resolve5).on("error", onErr).end();
21513
23717
  return;
21514
23718
  }
@@ -21530,7 +23734,7 @@ function request(u, conn, proxy, signal) {
21530
23734
  const req = https.request({
21531
23735
  host,
21532
23736
  port,
21533
- path: path4,
23737
+ path: path5,
21534
23738
  signal,
21535
23739
  headers: { host: u.host },
21536
23740
  createConnection: () => tlsConnect({ socket, host, servername: tlsName(host) })
@@ -21702,12 +23906,12 @@ function reply2(text, isError) {
21702
23906
  return { text, isError, sandboxBytes: 0 };
21703
23907
  }
21704
23908
  function scopesOf(input) {
21705
- const set2 = {
23909
+ const set3 = {
21706
23910
  session: input.session !== void 0,
21707
23911
  source: input.source !== void 0,
21708
23912
  project: input.project === true
21709
23913
  };
21710
- return PURGE_SCOPES.filter((s) => set2[s]);
23914
+ return PURGE_SCOPES.filter((s) => set3[s]);
21711
23915
  }
21712
23916
  function changes(raw, sql, ...args) {
21713
23917
  return Number(raw.prepare(sql).run(...args).changes);
@@ -21777,8 +23981,8 @@ async function handler6(input, ctx) {
21777
23981
  if (newest === void 0) return reply3(RESUME_EMPTY_LINE, false);
21778
23982
  const sources = listSessionSources(db, sessionId, MAX_CANDIDATES).map((r) => "source " + sourceHandle(r.id) + ": " + r.label + " (" + r.bytes + " B)");
21779
23983
  const goal = readFirstPrompt(db, sessionId);
21780
- const last = readLastPrompt(db, sessionId);
21781
- const units = queryUnits(db, sessionId, recallQueryText(last, goal), RECALL_UNIT_CANDIDATES).map((u) => ({ ...u, label: sourceHandle(u.sourceId) }));
23984
+ const last2 = readLastPrompt(db, sessionId);
23985
+ const units = queryUnits(db, sessionId, recallQueryText(last2, goal), RECALL_UNIT_CANDIDATES).map((u) => ({ ...u, label: sourceHandle(u.sourceId) }));
21782
23986
  const block = renderState(rows, newest.turn, { sources, units });
21783
23987
  if (Buffer.byteLength(block, "utf8") > RESUME_CAP) throw new Error("ctx_resume: state block over RESUME_CAP (render bug).");
21784
23988
  return reply3(block, false);
@@ -21820,8 +24024,8 @@ function reductionPct(t) {
21820
24024
  return Number((t.saved * PERCENT_SCALE / Math.max(1, t.produced)).toFixed(1));
21821
24025
  }
21822
24026
  function tableRow(label, t) {
21823
- const last = t.calls === 0 ? STATS_NO_DATA : String(reductionPct(t));
21824
- return "| " + [label, t.produced + " B", t.returned + " B", t.saved + " B", last].join(" | ") + " |";
24027
+ const last2 = t.calls === 0 ? STATS_NO_DATA : String(reductionPct(t));
24028
+ return "| " + [label, t.produced + " B", t.returned + " B", t.saved + " B", last2].join(" | ") + " |";
21825
24029
  }
21826
24030
  async function handler7(_input, ctx) {
21827
24031
  const db = await openDb(ctx.project, { readOnly: true });
@@ -21855,23 +24059,24 @@ var ctxStats = Object.freeze({
21855
24059
  });
21856
24060
 
21857
24061
  // src/core/tools/upgrade.ts
21858
- import { existsSync as existsSync18, realpathSync as realpathSync7, rmSync as rmSync10 } from "node:fs";
24062
+ import { existsSync as existsSync18, realpathSync as realpathSync7, rmSync as rmSync9 } from "node:fs";
21859
24063
  import { basename as basename5, dirname as dirname10, join as join21 } from "node:path";
21860
24064
 
21861
24065
  // src/core/ops/host-write.ts
21862
- import { copyFileSync, existsSync as existsSync13, mkdirSync as mkdirSync4, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync4 } from "node:fs";
24066
+ import { copyFileSync, existsSync as existsSync13, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "node:fs";
21863
24067
  import { dirname as dirname9, join as join16 } from "node:path";
21864
24068
  function defaultWrite(file2, text) {
21865
24069
  writeFileSync4(file2, text, "utf8");
21866
24070
  }
21867
24071
  function hostConfigPath(agent, home, env) {
21868
24072
  const own2 = OWN_MCP_ENTRY[agent];
21869
- if (own2 !== void 0) return join16(home, ...own2.file);
24073
+ if (own2 !== void 0) return ownMcpFileOf(agent, own2.file, env, home);
21870
24074
  switch (agent) {
21871
24075
  case "opencode":
21872
- return join16(home, ...AGENT_HOME_DIR.opencode, OPENCODE_BASE_CONFIG_FILE);
24076
+ return join16(opencodeDirOf(env, home), OPENCODE_BASE_CONFIG_FILE);
24077
+ // D-WIN-OPENCODE-DIR-1
21873
24078
  case "pi":
21874
- return join16(env[PI_AGENT_DIR_ENV] ?? join16(home, ...AGENT_HOME_DIR.pi, PI_AGENT_DIR), SETTINGS_FILE);
24079
+ return join16(piAgentDirOf(env, home), SETTINGS_FILE);
21875
24080
  case "copilot-cli":
21876
24081
  return null;
21877
24082
  default:
@@ -21884,22 +24089,32 @@ function cell2(value) {
21884
24089
  function toRow(file2, edit) {
21885
24090
  return { area: file2 + UPGRADE_AREA_KEY_SEP + edit.path, before: cell2(edit.before), after: cell2(edit.after) };
21886
24091
  }
21887
- function writeWithRollback(file2, text, write2) {
24092
+ function writeWithRollback(file2, text, write2, atomic) {
21888
24093
  const trash = file2 + UPGRADE_TRASH_SUFFIX;
21889
- const tmp = file2 + HOST_CONFIG_TMP_SUFFIX;
24094
+ const tmp = `${file2}${HOST_CONFIG_TMP_SUFFIX}.${process.pid}`;
21890
24095
  const had = existsSync13(file2);
21891
- mkdirSync4(dirname9(file2), { recursive: true });
24096
+ mkdirSync5(dirname9(file2), { recursive: true });
21892
24097
  if (had) copyFileSync(file2, trash);
21893
24098
  try {
21894
24099
  write2(tmp, text);
21895
- renameSync3(tmp, file2);
24100
+ renameWithRetry(tmp, file2, atomic);
21896
24101
  } catch (err) {
21897
- rmSync5(tmp, { force: true });
21898
- if (had) renameSync3(trash, file2);
21899
- else rmSync5(file2, { force: true });
21900
- throw err;
24102
+ removeTmpFile(tmp, atomic);
24103
+ if (!had) {
24104
+ removeTmpFile(file2, atomic);
24105
+ throw replaceFailure(file2, err);
24106
+ }
24107
+ try {
24108
+ renameWithRetry(trash, file2, atomic);
24109
+ } catch (restoreErr) {
24110
+ throw new Error(`${replaceFailure(file2, err).message}. The original is kept at ${trash}`, { cause: restoreErr });
24111
+ }
24112
+ throw replaceFailure(file2, err);
24113
+ }
24114
+ try {
24115
+ unlinkWithRetry(trash, atomic);
24116
+ } catch {
21901
24117
  }
21902
- rmSync5(trash, { force: true });
21903
24118
  }
21904
24119
  function regenerateHostConfig(row5, home, opts = {}) {
21905
24120
  const env = opts.env ?? process.env;
@@ -21910,29 +24125,31 @@ function regenerateHostConfig(row5, home, opts = {}) {
21910
24125
  const exists = existsSync13(current.path);
21911
24126
  if (exists && result.text === current.text) return [];
21912
24127
  const text = result.text === "" && current.format !== "toml" ? JSON.stringify({}) : result.text;
21913
- writeWithRollback(current.path, text, opts.write ?? defaultWrite);
24128
+ writeWithRollback(current.path, current.layout === void 0 ? text : withLayout(text, current.layout), opts.write ?? defaultWrite, opts.atomic ?? {});
21914
24129
  return result.edits.map((e) => toRow(current.path, e));
21915
24130
  }
21916
24131
 
21917
24132
  // src/core/ops/plugin-swap.ts
21918
- import { existsSync as existsSync14, lstatSync, readdirSync as readdirSync6, readlinkSync, renameSync as renameSync4, rmSync as rmSync6, symlinkSync, unlinkSync } from "node:fs";
21919
- import { basename as basename4, join as join17 } from "node:path";
21920
- function linkTarget(path4) {
21921
- return isLink(path4) ? readlinkSync(path4) : null;
24133
+ import { existsSync as existsSync14, lstatSync, readdirSync as readdirSync6, readlinkSync, rmSync as rmSync5, symlinkSync, unlinkSync as unlinkSync2 } from "node:fs";
24134
+ import { basename as basename4, join as join17, win32 as win322 } from "node:path";
24135
+ function linkTarget(path5, win) {
24136
+ if (!isLink(path5)) return null;
24137
+ const target = readlinkSync(path5);
24138
+ return win ? win322.basename(target) : target;
21922
24139
  }
21923
- function isLink(path4) {
21924
- return lstatSync(path4, { throwIfNoEntry: false })?.isSymbolicLink() === true;
24140
+ function isLink(path5) {
24141
+ return lstatSync(path5, { throwIfNoEntry: false })?.isSymbolicLink() === true;
21925
24142
  }
21926
24143
  function generations(agentDir) {
21927
24144
  return readdirSync6(agentDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).filter((name) => !name.startsWith(UPGRADE_FETCH_DIR_PREFIX) && !name.endsWith(UPGRADE_TRASH_SUFFIX)).sort();
21928
24145
  }
21929
- function settleLinks(link, tmp, old) {
21930
- if (isLink(tmp)) unlinkSync(tmp);
24146
+ function settleLinks(link, tmp, old, opts) {
24147
+ if (isLink(tmp)) unlinkSync2(tmp);
21931
24148
  if (!isLink(old)) return;
21932
- if (isLink(link)) unlinkSync(old);
21933
- else renameSync4(old, link);
24149
+ if (isLink(link)) unlinkSync2(old);
24150
+ else renameWithRetry(old, link, opts);
21934
24151
  }
21935
- function swapPluginCurrent(agentDir, sha) {
24152
+ function swapPluginCurrent(agentDir, sha, opts = {}) {
21936
24153
  const next = join17(agentDir, sha);
21937
24154
  if (!existsSync14(next) || !lstatSync(next).isDirectory()) {
21938
24155
  throw new CtxError("PLUGIN_ROOT_MISSING", { agent: basename4(agentDir), path: next });
@@ -21940,23 +24157,26 @@ function swapPluginCurrent(agentDir, sha) {
21940
24157
  const link = join17(agentDir, PLUGIN_CURRENT_LINK);
21941
24158
  const tmp = link + PLUGIN_LINK_TMP_SUFFIX;
21942
24159
  const old = link + PLUGIN_LINK_OLD_SUFFIX;
21943
- settleLinks(link, tmp, old);
21944
- const before = linkTarget(link);
24160
+ settleLinks(link, tmp, old, opts);
24161
+ const win = (opts.platform ?? process.platform) === "win32";
24162
+ const before = linkTarget(link, win);
21945
24163
  if (before === sha) return { current: next, previous: null, removed: [] };
21946
- symlinkSync(sha, tmp, PLUGIN_LINK_TYPE);
21947
- if (before !== null) renameSync4(link, old);
21948
- renameSync4(tmp, link);
21949
- if (before !== null) unlinkSync(old);
24164
+ const symlink = opts.symlink ?? symlinkSync;
24165
+ if (win) symlink(next, tmp, PLUGIN_LINK_TYPE_WIN32);
24166
+ else symlink(sha, tmp, PLUGIN_LINK_TYPE);
24167
+ if (before !== null) renameWithRetry(link, old, opts);
24168
+ renameWithRetry(tmp, link, opts);
24169
+ if (before !== null) unlinkSync2(old);
21950
24170
  const keep = /* @__PURE__ */ new Set([sha]);
21951
24171
  if (before !== null) keep.add(before);
21952
24172
  const removed = generations(agentDir).filter((name) => !keep.has(name)).map((name) => join17(agentDir, name));
21953
- for (const dir of removed) rmSync6(dir, { recursive: true, force: true });
24173
+ for (const dir of removed) rmSync5(dir, { recursive: true, force: true });
21954
24174
  const previous = before !== null && existsSync14(join17(agentDir, before)) ? join17(agentDir, before) : null;
21955
24175
  return { current: next, previous, removed };
21956
24176
  }
21957
24177
 
21958
24178
  // src/core/ops/release-fetch.ts
21959
- import { existsSync as existsSync15, mkdirSync as mkdirSync5, renameSync as renameSync5, rmSync as rmSync7 } from "node:fs";
24179
+ import { existsSync as existsSync15, mkdirSync as mkdirSync6, rmSync as rmSync6 } from "node:fs";
21960
24180
  import { join as join18 } from "node:path";
21961
24181
  function failed(r) {
21962
24182
  if (r.exitCode === null && r.killed === null) return new CtxError("FETCH_FAILED", { code: GIT_NOT_STARTED });
@@ -21968,11 +24188,11 @@ async function git2(bin, args, cwd, env, signal) {
21968
24188
  if (r.exitCode !== 0 || r.killed !== null) throw failed(r);
21969
24189
  return r.stdout.toString().trim();
21970
24190
  }
21971
- async function fetchRelease(agent, url2, env, signal) {
24191
+ async function fetchRelease(agent, url2, env, signal, opts = {}) {
21972
24192
  const agentDir = join18(resolveConfigDir(env), DATA_PLUGINS_DIR_NAME, agent);
21973
- mkdirSync5(agentDir, { recursive: true });
24193
+ mkdirSync6(agentDir, { recursive: true });
21974
24194
  const fetchDir = join18(agentDir, UPGRADE_FETCH_DIR_PREFIX + process.pid);
21975
- rmSync7(fetchDir, { recursive: true, force: true });
24195
+ rmSync6(fetchDir, { recursive: true, force: true });
21976
24196
  const gitBin = findRuntime(GIT_BIN, env);
21977
24197
  if (gitBin === null) throw new CtxError("FETCH_FAILED", { code: GIT_NOT_STARTED });
21978
24198
  const childEnv = buildChildEnv(env, { ...GIT_NO_PROMPT_ENV, ...GIT_NO_CRLF_ENV });
@@ -21980,26 +24200,21 @@ async function fetchRelease(agent, url2, env, signal) {
21980
24200
  await git2(gitBin, [...GIT_CLONE_ARGS, RELEASE_BRANCH, url2, fetchDir], agentDir, childEnv, signal);
21981
24201
  const sha = await git2(gitBin, GIT_HEAD_SHA_ARGS, fetchDir, childEnv, signal);
21982
24202
  const dir = join18(agentDir, sha);
21983
- if (existsSync15(dir)) rmSync7(fetchDir, { recursive: true, force: true });
21984
- else renameSync5(fetchDir, dir);
24203
+ if (existsSync15(dir)) rmSync6(fetchDir, { recursive: true, force: true });
24204
+ else renameWithRetry(fetchDir, dir, opts);
21985
24205
  return { sha, dir };
21986
24206
  } catch (e) {
21987
- rmSync7(fetchDir, { recursive: true, force: true });
24207
+ rmSync6(fetchDir, { recursive: true, force: true });
21988
24208
  throw e;
21989
24209
  }
21990
24210
  }
21991
24211
 
21992
24212
  // src/core/ops/uninstall.ts
21993
- import { existsSync as existsSync16, readdirSync as readdirSync7, rmSync as rmSync8, writeFileSync as writeFileSync5 } from "node:fs";
24213
+ import { existsSync as existsSync16, readdirSync as readdirSync7, rmSync as rmSync7, writeFileSync as writeFileSync5 } from "node:fs";
21994
24214
  import { join as join19 } from "node:path";
21995
24215
  function row2(area, before, after) {
21996
24216
  return { area, before, after };
21997
24217
  }
21998
- function homeOf3(env) {
21999
- const home = homeDirOf(env);
22000
- if (home === null) throw new CtxError("NO_HOME", { name: process.platform === "win32" ? "USERPROFILE" : "HOME" });
22001
- return home;
22002
- }
22003
24218
  function stopServers(configDir, projectKey) {
22004
24219
  const stopped = listLiveOwners(configDir, projectKey);
22005
24220
  const dir = join19(configDir, PROJECTS_DIR_NAME, projectKey, OWNERS_DIR_NAME);
@@ -22020,13 +24235,13 @@ function removeCache(adapter, env, configDir) {
22020
24235
  case "extension": {
22021
24236
  const root = rootOrNull(adapter, env);
22022
24237
  if (root === null) return row2(UPGRADE_CACHE_AREA, "", UPGRADE_NOT_FOUND);
22023
- rmSync8(root, { recursive: true, force: true });
24238
+ rmSync7(root, { recursive: true, force: true });
22024
24239
  return row2(UPGRADE_CACHE_AREA, root, UPGRADE_REMOVED);
22025
24240
  }
22026
24241
  case "plugin": {
22027
24242
  const agentDir = join19(configDir, DATA_PLUGINS_DIR_NAME, adapter.id);
22028
24243
  if (!existsSync16(agentDir)) return row2(UPGRADE_CACHE_AREA, "", UPGRADE_NOT_FOUND);
22029
- rmSync8(agentDir, { recursive: true, force: true });
24244
+ rmSync7(agentDir, { recursive: true, force: true });
22030
24245
  return row2(UPGRADE_CACHE_AREA, agentDir, UPGRADE_REMOVED);
22031
24246
  }
22032
24247
  case "config-mcp":
@@ -22045,20 +24260,20 @@ function piSource(entry) {
22045
24260
  return isObj2(entry) ? entry[PI_PACKAGE_SOURCE_KEY] : entry;
22046
24261
  }
22047
24262
  function ownEntries(agent, env) {
22048
- const home = homeOf3(env);
24263
+ const home = requireHomeDir(env);
22049
24264
  const mcp = OWN_MCP_ENTRY[agent];
22050
24265
  if (mcp !== void 0) {
22051
24266
  const top = mcp.key[0];
22052
24267
  const inner = mcp.key.slice(1, -1);
22053
24268
  const own2 = mcp.key[mcp.key.length - 1];
22054
24269
  const holder = (v) => inner.reduce((cur, k) => isObj2(cur) ? cur[k] : void 0, v);
22055
- const without = (v, path4) => {
24270
+ const without = (v, path5) => {
22056
24271
  const o = v;
22057
- if (path4.length === 0) return Object.fromEntries(Object.entries(o).filter(([k]) => k !== own2));
22058
- return { ...o, [path4[0]]: without(o[path4[0]], path4.slice(1)) };
24272
+ if (path5.length === 0) return Object.fromEntries(Object.entries(o).filter(([k]) => k !== own2));
24273
+ return { ...o, [path5[0]]: without(o[path5[0]], path5.slice(1)) };
22059
24274
  };
22060
24275
  return [{
22061
- file: join19(home, ...mcp.file),
24276
+ file: ownMcpFileOf(agent, mcp.file, env, home),
22062
24277
  key: top,
22063
24278
  shown: mcp.key.join(V1_KEY_PATH_SEP),
22064
24279
  has: (v) => {
@@ -22070,7 +24285,8 @@ function ownEntries(agent, env) {
22070
24285
  }
22071
24286
  if (agent === "opencode") {
22072
24287
  return [{
22073
- file: join19(home, ...AGENT_HOME_DIR.opencode, OPENCODE_BASE_CONFIG_FILE),
24288
+ file: join19(opencodeDirOf(env, home), OPENCODE_BASE_CONFIG_FILE),
24289
+ // D-WIN-OPENCODE-DIR-1
22074
24290
  key: OPENCODE_PLUGIN_KEY,
22075
24291
  shown: OPENCODE_PLUGIN_KEY,
22076
24292
  has: (v) => Array.isArray(v) && v.includes(OPENCODE_GIT_SPEC),
@@ -22078,7 +24294,7 @@ function ownEntries(agent, env) {
22078
24294
  }];
22079
24295
  }
22080
24296
  if (agent === "pi") {
22081
- const agentDir = env[PI_AGENT_DIR_ENV] ?? join19(home, ...AGENT_HOME_DIR.pi, PI_AGENT_DIR);
24297
+ const agentDir = piAgentDirOf(env, home);
22082
24298
  return [{
22083
24299
  file: join19(agentDir, SETTINGS_FILE),
22084
24300
  key: PI_PACKAGES_KEY,
@@ -22107,7 +24323,7 @@ function removeProjectData(configDir, projectKey) {
22107
24323
  if (!existsSync16(dir)) return row2(UPGRADE_DATA_AREA, "", UPGRADE_NOT_FOUND);
22108
24324
  if (dir === projects || !isInside(projects, dir)) throw new CtxError("OUTSIDE_ROOT", { p: dir, root: projects });
22109
24325
  for (const name of readdirSync7(dir)) {
22110
- if (name !== OWNERS_DIR_NAME) rmSync8(join19(dir, name), { recursive: true, force: true });
24326
+ if (name !== OWNERS_DIR_NAME) rmSync7(join19(dir, name), { recursive: true, force: true });
22111
24327
  }
22112
24328
  return row2(UPGRADE_DATA_AREA, dir, UPGRADE_DATA_DELETED);
22113
24329
  }
@@ -22120,52 +24336,52 @@ function runUninstall(input) {
22120
24336
  }
22121
24337
 
22122
24338
  // src/core/ops/v1-remove.ts
22123
- import { copyFileSync as copyFileSync2, existsSync as existsSync17, readFileSync as readFileSync13, renameSync as renameSync6, rmSync as rmSync9, writeFileSync as writeFileSync6 } from "node:fs";
24339
+ import { copyFileSync as copyFileSync2, existsSync as existsSync17, readFileSync as readFileSync13, rmSync as rmSync8 } from "node:fs";
22124
24340
  var isObj3 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
22125
24341
  var areaOf = (f) => f.path === "" ? f.file : f.file + UPGRADE_AREA_KEY_SEP + f.path;
22126
24342
  var row3 = (f, after) => ({ area: areaOf(f), before: f.reason, after });
22127
24343
  function moveAside(target, undo) {
22128
24344
  const trash = target + UPGRADE_TRASH_SUFFIX;
22129
- rmSync9(trash, { recursive: true, force: true });
22130
- renameSync6(target, trash);
24345
+ rmSync8(trash, { recursive: true, force: true });
24346
+ renameWithRetry(target, trash);
22131
24347
  undo.push({ trash, target });
22132
24348
  }
22133
24349
  function keepOriginal(file2, kept, undo) {
22134
24350
  if (kept.has(file2)) return;
22135
24351
  const trash = file2 + UPGRADE_TRASH_SUFFIX;
22136
- rmSync9(trash, { recursive: true, force: true });
24352
+ rmSync8(trash, { recursive: true, force: true });
22137
24353
  copyFileSync2(file2, trash);
22138
24354
  kept.add(file2);
22139
24355
  undo.push({ trash, target: file2 });
22140
24356
  }
22141
24357
  function cutTomlTable(text, header) {
22142
- const lines = text.split("\n");
22143
- const start = lines.findIndex((l) => l.trim() === header);
22144
- if (start === -1) return null;
22145
- let end = start + 1;
22146
- while (end < lines.length && !lines[end].trim().startsWith(TOML_TABLE_OPEN)) end += 1;
22147
- return [...lines.slice(0, start), ...lines.slice(end)].join("\n");
24358
+ let span;
24359
+ try {
24360
+ span = tomlTableSpans(text).find((t) => t.header.trim() === header);
24361
+ } catch {
24362
+ return null;
24363
+ }
24364
+ return span === void 0 ? null : text.slice(0, span.start) + text.slice(span.end);
22148
24365
  }
22149
24366
  function writeAtomic(file2, text) {
22150
- const tmp = file2 + HOST_CONFIG_TMP_SUFFIX;
22151
- writeFileSync6(tmp, text, "utf8");
22152
- renameSync6(tmp, file2);
24367
+ atomicWriteFile(file2, text);
22153
24368
  }
22154
- function locate(doc, path4) {
22155
- const segs = path4.split(V1_KEY_PATH_SEP);
24369
+ function locate(doc, path5) {
24370
+ const segs = path5.split(V1_KEY_PATH_SEP);
22156
24371
  let cur = doc;
22157
24372
  for (const seg of segs.slice(0, -1)) {
22158
24373
  if (Array.isArray(cur)) cur = cur[Number(seg)];
22159
24374
  else if (isObj3(cur)) cur = cur[seg];
22160
24375
  else return null;
22161
24376
  }
22162
- const last = segs[segs.length - 1];
22163
- if (Array.isArray(cur)) return Number(last) < cur.length ? [cur, last] : null;
22164
- if (isObj3(cur)) return Object.hasOwn(cur, last) ? [cur, last] : null;
24377
+ const last2 = segs[segs.length - 1];
24378
+ if (Array.isArray(cur)) return Number(last2) < cur.length ? [cur, last2] : null;
24379
+ if (isObj3(cur)) return Object.hasOwn(cur, last2) ? [cur, last2] : null;
22165
24380
  return null;
22166
24381
  }
22167
24382
  function stripJsonEntries(agent, file2, findings, kept, undo) {
22168
- const text = readFileSync13(file2, "utf8");
24383
+ const layout = hostLayout(readFileSync13(file2, "utf8"));
24384
+ const text = hostText(readFileSync13(file2, "utf8"));
22169
24385
  const doc = parseHostConfig(agent, file2, text, "jsonc");
22170
24386
  const hit = /* @__PURE__ */ new Set();
22171
24387
  const byContainer = /* @__PURE__ */ new Map();
@@ -22190,7 +24406,7 @@ function stripJsonEntries(agent, file2, findings, kept, undo) {
22190
24406
  const patch = {};
22191
24407
  for (const k of topKeys) patch[k] = doc[k];
22192
24408
  keepOriginal(file2, kept, undo);
22193
- writeHostConfigEdit(file2, { agent, text, format: "jsonc", path: file2 }, patch);
24409
+ writeHostConfigEdit(file2, { agent, text, format: "jsonc", path: file2, layout }, patch);
22194
24410
  return hit;
22195
24411
  }
22196
24412
  function removeV1(agent, findings) {
@@ -22213,7 +24429,9 @@ function removeV1(agent, findings) {
22213
24429
  continue;
22214
24430
  }
22215
24431
  if (file2.endsWith(TOML_EXT)) {
22216
- let text = readFileSync13(file2, "utf8");
24432
+ const rawToml = readFileSync13(file2, "utf8");
24433
+ const tomlLayout = hostLayout(rawToml);
24434
+ let text = hostText(rawToml);
22217
24435
  for (const f of list3) {
22218
24436
  const next = cutTomlTable(text, f.path);
22219
24437
  if (next === null) {
@@ -22225,7 +24443,7 @@ function removeV1(agent, findings) {
22225
24443
  }
22226
24444
  if (list3.some((f) => done.get(f) === UPGRADE_REMOVED)) {
22227
24445
  keepOriginal(file2, kept, undo);
22228
- writeAtomic(file2, text);
24446
+ writeAtomic(file2, withLayout(text, tomlLayout));
22229
24447
  }
22230
24448
  continue;
22231
24449
  }
@@ -22235,13 +24453,13 @@ function removeV1(agent, findings) {
22235
24453
  return {
22236
24454
  rows: findings.map((f) => row3(f, done.get(f) ?? UPGRADE_NOT_FOUND)),
22237
24455
  commit() {
22238
- for (const u of undo.splice(0)) rmSync9(u.trash, { recursive: true, force: true });
24456
+ for (const u of undo.splice(0)) rmSync8(u.trash, { recursive: true, force: true });
22239
24457
  },
22240
24458
  rollback() {
22241
24459
  for (const u of undo.splice(0).reverse()) {
22242
24460
  if (!existsSync17(u.trash)) continue;
22243
- rmSync9(u.target, { recursive: true, force: true });
22244
- renameSync6(u.trash, u.target);
24461
+ rmSync8(u.target, { recursive: true, force: true });
24462
+ renameWithRetry(u.trash, u.target);
22245
24463
  }
22246
24464
  }
22247
24465
  };
@@ -22301,11 +24519,6 @@ var ctxUpgradeSchema = external_exports.object({
22301
24519
  function row4(area, before, after) {
22302
24520
  return { area, before, after };
22303
24521
  }
22304
- function homeOf4(env) {
22305
- const home = homeDirOf(env);
22306
- if (home === null) throw new CtxError("NO_HOME", { name: process.platform === "win32" ? "USERPROFILE" : "HOME" });
22307
- return home;
22308
- }
22309
24522
  function bundleDir() {
22310
24523
  return dirname10(process.argv[1] ?? "");
22311
24524
  }
@@ -22330,7 +24543,7 @@ async function checkout(adapter, deps) {
22330
24543
  try {
22331
24544
  verifySums(fetched.dir);
22332
24545
  } catch (err) {
22333
- if (!isCurrent(agentDir, fetched.dir)) rmSync10(fetched.dir, { recursive: true, force: true });
24546
+ if (!isCurrent(agentDir, fetched.dir)) rmSync9(fetched.dir, { recursive: true, force: true });
22334
24547
  throw err;
22335
24548
  }
22336
24549
  const swap = swapPluginCurrent(agentDir, fetched.sha);
@@ -22347,7 +24560,7 @@ async function upgrade(adapter, deps, home) {
22347
24560
  try {
22348
24561
  const step4 = UPGRADE_GIT_CHECKOUT_AGENTS.includes(adapter.id) ? (done = await checkout(adapter, deps)).rows : [hostRow(adapter)];
22349
24562
  const step5 = regenerateHostConfig(adapter, home, { env: deps.env, write: deps.write });
22350
- const findings = detectV1(adapter.id, home, { project: deps.project.worktree, piAgentDir: deps.env[PI_AGENT_DIR_ENV] });
24563
+ const findings = detectV1(adapter.id, home, { project: deps.project.worktree, piAgentDir: piAgentDirOf(deps.env, home), claudeDir: claudeDirOf(deps.env, home), copilotDir: copilotDirOf(deps.env, home), kiroDir: kiroDirOf(deps.env, home), opencodeDir: opencodeDirOf(deps.env, home) });
22351
24564
  removal = removeV1(adapter.id, findings);
22352
24565
  const rows = [...step4, ...step5, ...removal.rows];
22353
24566
  removal.commit();
@@ -22368,7 +24581,7 @@ function renderTable(rows) {
22368
24581
  }
22369
24582
  async function runUpgrade(input, deps) {
22370
24583
  const adapter = getAdapter(deps.project.agent);
22371
- const home = homeOf4(deps.env);
24584
+ const home = requireHomeDir(deps.env);
22372
24585
  const rows = pluginRootRow(adapter, deps.env);
22373
24586
  if ((input.mode ?? UPGRADE_DEFAULT_MODE) === "uninstall") {
22374
24587
  const result = runUninstall({ adapter, project: deps.project, env: deps.env, confirmDelete: input.confirmDelete === true });