context-mode 2.0.0-next.5 → 2.0.0-next.6

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.
@@ -25,9 +25,11 @@ var REPLACE_TRIGGER_BYTES = 4096;
25
25
  var REPLACE_RETURN_BYTES = 96;
26
26
  var SHAPE_RETURN_BYTES = 256;
27
27
  var REPLACE_CHUNK_BYTES = 48;
28
- function REPLACE_HANDLE_LINE(intent, handle, bytes4, prefix = "") {
29
- return prefix + "ctx_search({queries:[" + JSON.stringify(intent) + "], source:" + JSON.stringify(handle) + "}) searches the whole output (" + bytes4 + " B).";
28
+ function REPLACE_HANDLE_LINE(intent, handle, bytes4, prefix = "", asked = "") {
29
+ const queries = asked === "" ? [intent] : [intent, asked];
30
+ return prefix + "ctx_search({queries:[" + queries.map((q) => JSON.stringify(q)).join(",") + "], source:" + JSON.stringify(handle) + "}) searches the whole output (" + bytes4 + " B).";
30
31
  }
32
+ var HANDLE_PROMPT_WORDS = 3;
31
33
  var MAX_CHUNK_BYTES = 4096;
32
34
  var SEARCH_PAGE_SIZE = 20;
33
35
  var SNIPPET_MAX_BYTES = 800;
@@ -328,7 +330,7 @@ var DECISION_OPTION_KEY = "option";
328
330
  var DECISION_LABEL_JOIN = " | ";
329
331
  var RELEASE_REPO_URL = "https://github.com/mksglu/context-mode.git";
330
332
  var RELEASE_BRANCH = "release";
331
- var BUNDLE_SHA = true ? "0bf5734278463ea178b282436a39ba81347dadab" : void 0;
333
+ var BUNDLE_SHA = true ? "3374b3ce2faee35730f5c335678ca40b405e923c" : void 0;
332
334
  var DOCTOR_CHECK_ORDER = Object.freeze(["D1", "D2", "D3", "D4", "D5", "D5b", "D6", "D7", "D8", "D9", "D10"]);
333
335
  var DOCTOR_LABEL = Object.freeze({
334
336
  D1: "version",
@@ -566,6 +568,7 @@ var V1_HOOKS_DIR_NAME = "hooks";
566
568
  var SETTINGS_FILE = "settings.json";
567
569
  var CLAUDE_USER_CONFIG_FILE = ".claude.json";
568
570
  var HOOKS_JSON_FILE = "hooks.json";
571
+ var CODEX_HOME_ENV = "CODEX_HOME";
569
572
  var CONFIG_TOML_FILE = "config.toml";
570
573
  var CONFIG_JSON_FILE = "config.json";
571
574
  var ZCODE_CLI_DIR = "cli";
@@ -632,8 +635,10 @@ var JSON_INDENT_UNIT = " ";
632
635
  var MCP_COMMAND_FIELD = "command";
633
636
  var MCP_ARGS_FIELD = "args";
634
637
  var ZCODE_MCP_FEATURE_KEY = Object.freeze(["features", "mcp"]);
638
+ var CODEX_OMIT_TOOLS_FROM_FIELD = "omit_tools_from";
639
+ var CODEX_OMIT_DEFERRED = Object.freeze(["deferred"]);
635
640
  var OWN_MCP_ENTRY = Object.freeze({
636
- codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY] },
641
+ codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY], fields: { [CODEX_OMIT_TOOLS_FROM_FIELD]: CODEX_OMIT_DEFERRED } },
637
642
  vscode: { file: [".vscode", "mcp.json"], key: ["servers", SERVER_KEY] },
638
643
  kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
639
644
  zcode: {
@@ -1518,6 +1523,10 @@ var REPLACE_ROWS = /* @__PURE__ */ new Set(["claude-code", "gemini", "copilot-cl
1518
1523
  function hasReplace(row5) {
1519
1524
  return REPLACE_ROWS.has(row5.id);
1520
1525
  }
1526
+ var DUMP_REPLACE_ROWS = /* @__PURE__ */ new Set(["claude-code", "copilot-cli", "pi"]);
1527
+ function dumpRunsThenReplaces(row5) {
1528
+ return DUMP_REPLACE_ROWS.has(row5.id) && hasReplace(row5);
1529
+ }
1521
1530
  var RECALL_ROWS = /* @__PURE__ */ new Set(["claude-code", "codex", "gemini", "qwen", "copilot-cli", "vscode", "zcode"]);
1522
1531
  function hasRecall(row5) {
1523
1532
  return RECALL_ROWS.has(row5.id);
@@ -2480,6 +2489,10 @@ function homeDirOf(env) {
2480
2489
  if (profile !== void 0 && profile !== "") return profile;
2481
2490
  return null;
2482
2491
  }
2492
+ function codexDirOf(env, home) {
2493
+ const dir = env[CODEX_HOME_ENV];
2494
+ return dir !== void 0 && dir !== "" ? dir : join(home, ...AGENT_HOME_DIR.codex);
2495
+ }
2483
2496
  function homeOf(env) {
2484
2497
  const home = homeDirOf(env);
2485
2498
  if (home !== null) return home;
@@ -3136,7 +3149,7 @@ function read(ev, row5, input) {
3136
3149
  return ALLOW;
3137
3150
  }
3138
3151
  function shellDump(cmds, cwd, row5) {
3139
- if (row5.nativeTools.read !== void 0 && row5.nativeTools.read.length > 0 && hasReplace(row5)) return null;
3152
+ if (row5.nativeTools.read !== void 0 && row5.nativeTools.read.length > 0 && dumpRunsThenReplaces(row5)) return null;
3140
3153
  if (cmds.length !== 1) return null;
3141
3154
  const c = cmds[0];
3142
3155
  if (c.redirectsToFile || c.endsInBoundedSink) return null;
@@ -6057,16 +6070,23 @@ var TYPO_MIN_LEN = 5;
6057
6070
  var TYPO_MAX_DIST = 2;
6058
6071
  function typoTerms(db, words) {
6059
6072
  const has2 = stmt(db.raw, "SELECT 1 AS x FROM chunks_vocab WHERE term = ?");
6060
- const near = stmt(db.raw, "SELECT term, doc FROM chunks_vocab WHERE length(term) BETWEEN ? AND ?");
6073
+ const near = stmt(db.raw, "SELECT term, doc, length(term) AS n FROM chunks_vocab WHERE length(term) BETWEEN ? AND ?");
6074
+ const stems = queryStems(words.join(" "));
6075
+ const miss = stems.map((stem) => has2.get(stem) === void 0 && [...stem].length >= TYPO_MIN_LEN);
6076
+ if (!miss.includes(true)) return null;
6077
+ const lens = stems.filter((_, i) => miss[i]).map((stem) => stem.length);
6078
+ const rows = near.all(Math.min(...lens) - TYPO_MAX_DIST, Math.max(...lens) + TYPO_MAX_DIST);
6061
6079
  let changed = false;
6062
6080
  const out = [];
6063
- for (const stem of queryStems(words.join(" "))) {
6064
- if (has2.get(stem) !== void 0 || [...stem].length < TYPO_MIN_LEN) {
6081
+ stems.forEach((stem, i) => {
6082
+ if (!miss[i]) {
6065
6083
  out.push(stem);
6066
- continue;
6084
+ return;
6067
6085
  }
6068
6086
  let best = null;
6069
- for (const r of near.all(stem.length - TYPO_MAX_DIST, stem.length + TYPO_MAX_DIST)) {
6087
+ for (const r of rows) {
6088
+ const n = Number(r.n);
6089
+ if (n < stem.length - TYPO_MAX_DIST || n > stem.length + TYPO_MAX_DIST) continue;
6070
6090
  const d = editDistance(stem, r.term, TYPO_MAX_DIST);
6071
6091
  if (d > TYPO_MAX_DIST) continue;
6072
6092
  if (best === null || d < best.d || d === best.d && (r.doc > best.doc || r.doc === best.doc && r.term < best.term)) {
@@ -6077,7 +6097,7 @@ function typoTerms(db, words) {
6077
6097
  out.push(best.term);
6078
6098
  changed = true;
6079
6099
  }
6080
- }
6100
+ });
6081
6101
  return changed ? out.map((t) => `"${t.replaceAll('"', '""')}"*`) : null;
6082
6102
  }
6083
6103
  function ftsQuery(db, q, scope, ctx, sessionId, limit, offset, source) {
@@ -7258,6 +7278,19 @@ function appendDetached(project, sessionId, row5) {
7258
7278
  void write(project, row5);
7259
7279
  }
7260
7280
 
7281
+ // src/core/hooks/handle-query.ts
7282
+ function askedWords(intent, prompt, text) {
7283
+ const want = new Set(wordTokens(prompt.toLowerCase()));
7284
+ for (const w of wordTokens(intent.toLowerCase())) want.delete(w);
7285
+ if (want.size === 0) return "";
7286
+ const counts = /* @__PURE__ */ new Map();
7287
+ for (const w of wordTokens(text.toLowerCase())) {
7288
+ if (want.has(w)) counts.set(w, (counts.get(w) ?? 0) + 1);
7289
+ }
7290
+ const picked = [...counts.entries()].sort((a, b) => a[1] - b[1] || (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)).slice(0, HANDLE_PROMPT_WORDS).map((e) => e[0]);
7291
+ return picked.join(" ");
7292
+ }
7293
+
7261
7294
  // src/core/hooks/decision.ts
7262
7295
  function isObject2(v) {
7263
7296
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -7668,7 +7701,7 @@ async function postToolUse(ev, row5, project, env) {
7668
7701
  const handle = sourceHandle(sourceId);
7669
7702
  const prompt = await lastPrompt(project, ev.sessionId);
7670
7703
  const rankQuery = prompt.trim() === "" ? void 0 : intent + " " + prompt;
7671
- const handleLine = REPLACE_HANDLE_LINE(intent, handle, result.bytes, row5.toolNamePrefix);
7704
+ const handleLine = REPLACE_HANDLE_LINE(intent, handle, result.bytes, row5.toolNamePrefix, askedWords(intent, prompt, text));
7672
7705
  const budget = replaceBudget(handleLine, moreLine2(intent, label));
7673
7706
  const digest = shapeDigest(text, rankQuery ?? intent, SHAPE_RETURN_BYTES);
7674
7707
  if (digest !== null) return { kind: "replace", output: replaceOutput(digest, handleLine) };
@@ -20420,6 +20453,7 @@ function ownHooks(block, shape, timeoutKey, native, agent) {
20420
20453
  var validTimeout = (v) => typeof v === "number" && Number.isFinite(v) && v > 0;
20421
20454
  function mcpFile(row5, home, env) {
20422
20455
  const spec = OWN_MCP_ENTRY[row5.id];
20456
+ if (row5.id === "codex") return join10(codexDirOf(env, home), CONFIG_TOML_FILE);
20423
20457
  if (spec !== void 0) return join10(home, ...spec.file);
20424
20458
  if (row5.id === "opencode") return join10(home, ...AGENT_HOME_DIR.opencode, OPENCODE_BASE_CONFIG_FILE);
20425
20459
  if (row5.id === "pi") {
@@ -20447,9 +20481,10 @@ function hookParts(row5, home, env, worktree) {
20447
20481
  let block;
20448
20482
  try {
20449
20483
  const root = spec.root === "plugin" ? resolvePluginRoot(row5, env) : spec.root === "home" ? home : worktree;
20450
- block = hostConfigValueAt(readParsed(row5.id, join10(root, ...spec.file)).value, spec.key);
20484
+ const file2 = row5.id === "codex" ? join10(codexDirOf(env, home), HOOKS_JSON_FILE) : join10(root, ...spec.file);
20485
+ block = hostConfigValueAt(readParsed(row5.id, file2).value, spec.key);
20451
20486
  if (row5.id === "codex") {
20452
- const config2 = readParsed(row5.id, join10(home, ...AGENT_HOME_DIR.codex, CONFIG_TOML_FILE)).value;
20487
+ const config2 = readParsed(row5.id, join10(codexDirOf(env, home), CONFIG_TOML_FILE)).value;
20453
20488
  if (hostConfigValueAt(config2, CODEX_FEATURES_HOOKS_KEY) === false) return [PART_HOOKS];
20454
20489
  }
20455
20490
  } catch {
@@ -20894,8 +20929,8 @@ async function hookRow(ctx, adapter, host) {
20894
20929
  bundleDir: host.bundleDir,
20895
20930
  env: buildChildEnv(host.env),
20896
20931
  signal: ctx.signal,
20897
- codexConfigDir: join12(needHome(host.env), ...AGENT_HOME_DIR.codex),
20898
- // same Codex dir D3 reads
20932
+ codexConfigDir: codexDirOf(host.env, needHome(host.env)),
20933
+ // same Codex dir D3 reads (D-N6-CODEX-HOME-2)
20899
20934
  db
20900
20935
  });
20901
20936
  } finally {
package/package.json CHANGED
@@ -7,9 +7,11 @@
7
7
  },
8
8
  "files": [
9
9
  ".claude-plugin",
10
+ ".codex-plugin",
10
11
  "SHA256SUMS",
11
12
  "claude-code",
12
13
  "cli.mjs",
14
+ "codex",
13
15
  "copilot",
14
16
  "fixtures",
15
17
  "gemini-extension.json",
@@ -23,6 +25,7 @@
23
25
  "server.mjs",
24
26
  "skills"
25
27
  ],
28
+ "main": "./opencode/plugin.js",
26
29
  "name": "context-mode",
27
30
  "pi": {
28
31
  "extensions": [
@@ -37,5 +40,5 @@
37
40
  "url": "git+https://github.com/mksglu/context-mode.git"
38
41
  },
39
42
  "type": "module",
40
- "version": "2.0.0-next.5"
43
+ "version": "2.0.0-next.6"
41
44
  }
package/pi/index.js CHANGED
@@ -11164,9 +11164,11 @@ var REPLACE_TRIGGER_BYTES = 4096;
11164
11164
  var REPLACE_RETURN_BYTES = 96;
11165
11165
  var SHAPE_RETURN_BYTES = 256;
11166
11166
  var REPLACE_CHUNK_BYTES = 48;
11167
- function REPLACE_HANDLE_LINE(intent, handle, bytes4, prefix = "") {
11168
- return prefix + "ctx_search({queries:[" + JSON.stringify(intent) + "], source:" + JSON.stringify(handle) + "}) searches the whole output (" + bytes4 + " B).";
11167
+ function REPLACE_HANDLE_LINE(intent, handle, bytes4, prefix = "", asked = "") {
11168
+ const queries = asked === "" ? [intent] : [intent, asked];
11169
+ return prefix + "ctx_search({queries:[" + queries.map((q) => JSON.stringify(q)).join(",") + "], source:" + JSON.stringify(handle) + "}) searches the whole output (" + bytes4 + " B).";
11169
11170
  }
11171
+ var HANDLE_PROMPT_WORDS = 3;
11170
11172
  var MAX_CHUNK_BYTES = 4096;
11171
11173
  var SEARCH_PAGE_SIZE = 20;
11172
11174
  var SNIPPET_MAX_BYTES = 800;
@@ -11474,7 +11476,7 @@ var DECISION_OPTION_KEY = "option";
11474
11476
  var DECISION_LABEL_JOIN = " | ";
11475
11477
  var RELEASE_REPO_URL = "https://github.com/mksglu/context-mode.git";
11476
11478
  var RELEASE_BRANCH = "release";
11477
- var BUNDLE_SHA = true ? "0bf5734278463ea178b282436a39ba81347dadab" : void 0;
11479
+ var BUNDLE_SHA = true ? "3374b3ce2faee35730f5c335678ca40b405e923c" : void 0;
11478
11480
  var DOCTOR_CHECK_ORDER = Object.freeze(["D1", "D2", "D3", "D4", "D5", "D5b", "D6", "D7", "D8", "D9", "D10"]);
11479
11481
  var DOCTOR_LABEL = Object.freeze({
11480
11482
  D1: "version",
@@ -11713,6 +11715,7 @@ var V1_HOOKS_DIR_NAME = "hooks";
11713
11715
  var SETTINGS_FILE = "settings.json";
11714
11716
  var CLAUDE_USER_CONFIG_FILE = ".claude.json";
11715
11717
  var HOOKS_JSON_FILE = "hooks.json";
11718
+ var CODEX_HOME_ENV = "CODEX_HOME";
11716
11719
  var CONFIG_TOML_FILE = "config.toml";
11717
11720
  var CONFIG_JSON_FILE = "config.json";
11718
11721
  var ZCODE_CLI_DIR = "cli";
@@ -11778,8 +11781,10 @@ var JSON_INDENT_UNIT = " ";
11778
11781
  var MCP_COMMAND_FIELD = "command";
11779
11782
  var MCP_ARGS_FIELD = "args";
11780
11783
  var ZCODE_MCP_FEATURE_KEY = Object.freeze(["features", "mcp"]);
11784
+ var CODEX_OMIT_TOOLS_FROM_FIELD = "omit_tools_from";
11785
+ var CODEX_OMIT_DEFERRED = Object.freeze(["deferred"]);
11781
11786
  var OWN_MCP_ENTRY = Object.freeze({
11782
- codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY] },
11787
+ codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY], fields: { [CODEX_OMIT_TOOLS_FROM_FIELD]: CODEX_OMIT_DEFERRED } },
11783
11788
  vscode: { file: [".vscode", "mcp.json"], key: ["servers", SERVER_KEY] },
11784
11789
  kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
11785
11790
  zcode: {
@@ -12664,6 +12669,10 @@ var REPLACE_ROWS = /* @__PURE__ */ new Set(["claude-code", "gemini", "copilot-cl
12664
12669
  function hasReplace(row5) {
12665
12670
  return REPLACE_ROWS.has(row5.id);
12666
12671
  }
12672
+ var DUMP_REPLACE_ROWS = /* @__PURE__ */ new Set(["claude-code", "copilot-cli", "pi"]);
12673
+ function dumpRunsThenReplaces(row5) {
12674
+ return DUMP_REPLACE_ROWS.has(row5.id) && hasReplace(row5);
12675
+ }
12667
12676
  var RECALL_ROWS = /* @__PURE__ */ new Set(["claude-code", "codex", "gemini", "qwen", "copilot-cli", "vscode", "zcode"]);
12668
12677
  function hasRecall(row5) {
12669
12678
  return RECALL_ROWS.has(row5.id);
@@ -13626,6 +13635,10 @@ function homeDirOf(env) {
13626
13635
  if (profile !== void 0 && profile !== "") return profile;
13627
13636
  return null;
13628
13637
  }
13638
+ function codexDirOf(env, home) {
13639
+ const dir = env[CODEX_HOME_ENV];
13640
+ return dir !== void 0 && dir !== "" ? dir : join(home, ...AGENT_HOME_DIR.codex);
13641
+ }
13629
13642
  function homeOf(env) {
13630
13643
  const home = homeDirOf(env);
13631
13644
  if (home !== null) return home;
@@ -14282,7 +14295,7 @@ function read(ev, row5, input) {
14282
14295
  return ALLOW;
14283
14296
  }
14284
14297
  function shellDump(cmds, cwd, row5) {
14285
- if (row5.nativeTools.read !== void 0 && row5.nativeTools.read.length > 0 && hasReplace(row5)) return null;
14298
+ if (row5.nativeTools.read !== void 0 && row5.nativeTools.read.length > 0 && dumpRunsThenReplaces(row5)) return null;
14286
14299
  if (cmds.length !== 1) return null;
14287
14300
  const c = cmds[0];
14288
14301
  if (c.redirectsToFile || c.endsInBoundedSink) return null;
@@ -17203,16 +17216,23 @@ var TYPO_MIN_LEN = 5;
17203
17216
  var TYPO_MAX_DIST = 2;
17204
17217
  function typoTerms(db, words) {
17205
17218
  const has2 = stmt(db.raw, "SELECT 1 AS x FROM chunks_vocab WHERE term = ?");
17206
- const near = stmt(db.raw, "SELECT term, doc FROM chunks_vocab WHERE length(term) BETWEEN ? AND ?");
17219
+ const near = stmt(db.raw, "SELECT term, doc, length(term) AS n FROM chunks_vocab WHERE length(term) BETWEEN ? AND ?");
17220
+ const stems = queryStems(words.join(" "));
17221
+ const miss = stems.map((stem) => has2.get(stem) === void 0 && [...stem].length >= TYPO_MIN_LEN);
17222
+ if (!miss.includes(true)) return null;
17223
+ const lens = stems.filter((_, i) => miss[i]).map((stem) => stem.length);
17224
+ const rows = near.all(Math.min(...lens) - TYPO_MAX_DIST, Math.max(...lens) + TYPO_MAX_DIST);
17207
17225
  let changed = false;
17208
17226
  const out = [];
17209
- for (const stem of queryStems(words.join(" "))) {
17210
- if (has2.get(stem) !== void 0 || [...stem].length < TYPO_MIN_LEN) {
17227
+ stems.forEach((stem, i) => {
17228
+ if (!miss[i]) {
17211
17229
  out.push(stem);
17212
- continue;
17230
+ return;
17213
17231
  }
17214
17232
  let best = null;
17215
- for (const r of near.all(stem.length - TYPO_MAX_DIST, stem.length + TYPO_MAX_DIST)) {
17233
+ for (const r of rows) {
17234
+ const n = Number(r.n);
17235
+ if (n < stem.length - TYPO_MAX_DIST || n > stem.length + TYPO_MAX_DIST) continue;
17216
17236
  const d = editDistance(stem, r.term, TYPO_MAX_DIST);
17217
17237
  if (d > TYPO_MAX_DIST) continue;
17218
17238
  if (best === null || d < best.d || d === best.d && (r.doc > best.doc || r.doc === best.doc && r.term < best.term)) {
@@ -17223,7 +17243,7 @@ function typoTerms(db, words) {
17223
17243
  out.push(best.term);
17224
17244
  changed = true;
17225
17245
  }
17226
- }
17246
+ });
17227
17247
  return changed ? out.map((t) => `"${t.replaceAll('"', '""')}"*`) : null;
17228
17248
  }
17229
17249
  function ftsQuery(db, q, scope, ctx, sessionId, limit, offset, source) {
@@ -18404,6 +18424,19 @@ function appendDetached(project, sessionId, row5) {
18404
18424
  void write(project, row5);
18405
18425
  }
18406
18426
 
18427
+ // src/core/hooks/handle-query.ts
18428
+ function askedWords(intent, prompt, text) {
18429
+ const want = new Set(wordTokens(prompt.toLowerCase()));
18430
+ for (const w of wordTokens(intent.toLowerCase())) want.delete(w);
18431
+ if (want.size === 0) return "";
18432
+ const counts = /* @__PURE__ */ new Map();
18433
+ for (const w of wordTokens(text.toLowerCase())) {
18434
+ if (want.has(w)) counts.set(w, (counts.get(w) ?? 0) + 1);
18435
+ }
18436
+ const picked = [...counts.entries()].sort((a, b) => a[1] - b[1] || (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)).slice(0, HANDLE_PROMPT_WORDS).map((e) => e[0]);
18437
+ return picked.join(" ");
18438
+ }
18439
+
18407
18440
  // src/core/hooks/decision.ts
18408
18441
  function isObject3(v) {
18409
18442
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -18814,7 +18847,7 @@ async function postToolUse(ev, row5, project, env) {
18814
18847
  const handle = sourceHandle(sourceId);
18815
18848
  const prompt = await lastPrompt(project, ev.sessionId);
18816
18849
  const rankQuery = prompt.trim() === "" ? void 0 : intent + " " + prompt;
18817
- const handleLine = REPLACE_HANDLE_LINE(intent, handle, result.bytes, row5.toolNamePrefix);
18850
+ const handleLine = REPLACE_HANDLE_LINE(intent, handle, result.bytes, row5.toolNamePrefix, askedWords(intent, prompt, text));
18818
18851
  const budget = replaceBudget(handleLine, moreLine2(intent, label));
18819
18852
  const digest = shapeDigest(text, rankQuery ?? intent, SHAPE_RETURN_BYTES);
18820
18853
  if (digest !== null) return { kind: "replace", output: replaceOutput(digest, handleLine) };
@@ -20427,6 +20460,7 @@ function ownHooks(block, shape, timeoutKey, native, agent) {
20427
20460
  var validTimeout = (v) => typeof v === "number" && Number.isFinite(v) && v > 0;
20428
20461
  function mcpFile(row5, home, env) {
20429
20462
  const spec = OWN_MCP_ENTRY[row5.id];
20463
+ if (row5.id === "codex") return join10(codexDirOf(env, home), CONFIG_TOML_FILE);
20430
20464
  if (spec !== void 0) return join10(home, ...spec.file);
20431
20465
  if (row5.id === "opencode") return join10(home, ...AGENT_HOME_DIR.opencode, OPENCODE_BASE_CONFIG_FILE);
20432
20466
  if (row5.id === "pi") {
@@ -20454,9 +20488,10 @@ function hookParts(row5, home, env, worktree) {
20454
20488
  let block;
20455
20489
  try {
20456
20490
  const root = spec.root === "plugin" ? resolvePluginRoot(row5, env) : spec.root === "home" ? home : worktree;
20457
- block = hostConfigValueAt(readParsed(row5.id, join10(root, ...spec.file)).value, spec.key);
20491
+ const file2 = row5.id === "codex" ? join10(codexDirOf(env, home), HOOKS_JSON_FILE) : join10(root, ...spec.file);
20492
+ block = hostConfigValueAt(readParsed(row5.id, file2).value, spec.key);
20458
20493
  if (row5.id === "codex") {
20459
- const config4 = readParsed(row5.id, join10(home, ...AGENT_HOME_DIR.codex, CONFIG_TOML_FILE)).value;
20494
+ const config4 = readParsed(row5.id, join10(codexDirOf(env, home), CONFIG_TOML_FILE)).value;
20460
20495
  if (hostConfigValueAt(config4, CODEX_FEATURES_HOOKS_KEY) === false) return [PART_HOOKS];
20461
20496
  }
20462
20497
  } catch {
@@ -20911,8 +20946,8 @@ async function hookRow(ctx, adapter, host) {
20911
20946
  bundleDir: host.bundleDir,
20912
20947
  env: buildChildEnv(host.env),
20913
20948
  signal: ctx.signal,
20914
- codexConfigDir: join12(needHome(host.env), ...AGENT_HOME_DIR.codex),
20915
- // same Codex dir D3 reads
20949
+ codexConfigDir: codexDirOf(host.env, needHome(host.env)),
20950
+ // same Codex dir D3 reads (D-N6-CODEX-HOME-2)
20916
20951
  db
20917
20952
  });
20918
20953
  } finally {
@@ -11,5 +11,5 @@
11
11
  }
12
12
  },
13
13
  "name": "context-mode",
14
- "version": "2.0.0-next.5"
14
+ "version": "2.0.0-next.6"
15
15
  }
package/run.mjs CHANGED
@@ -354,8 +354,10 @@ var V1_REASON = Object.freeze({
354
354
  var UPGRADE_REPORT_ONLY_REASONS = Object.freeze([V1_REASON.statusLine, V1_REASON.vscodeMcp, V1_REASON.dataDirShared, V1_REASON.tmpFile, V1_REASON.kiroSteering]);
355
355
  var OPENCODE_TOOL_PREFIX = SERVER_KEY + "_";
356
356
  var ZCODE_MCP_FEATURE_KEY = Object.freeze(["features", "mcp"]);
357
+ var CODEX_OMIT_TOOLS_FROM_FIELD = "omit_tools_from";
358
+ var CODEX_OMIT_DEFERRED = Object.freeze(["deferred"]);
357
359
  var OWN_MCP_ENTRY = Object.freeze({
358
- codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY] },
360
+ codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY], fields: { [CODEX_OMIT_TOOLS_FROM_FIELD]: CODEX_OMIT_DEFERRED } },
359
361
  vscode: { file: [".vscode", "mcp.json"], key: ["servers", SERVER_KEY] },
360
362
  kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
361
363
  zcode: {
@@ -1168,6 +1170,10 @@ var REPLACE_ROWS = /* @__PURE__ */ new Set(["claude-code", "gemini", "copilot-cl
1168
1170
  function hasReplace(row) {
1169
1171
  return REPLACE_ROWS.has(row.id);
1170
1172
  }
1173
+ var DUMP_REPLACE_ROWS = /* @__PURE__ */ new Set(["claude-code", "copilot-cli", "pi"]);
1174
+ function dumpRunsThenReplaces(row) {
1175
+ return DUMP_REPLACE_ROWS.has(row.id) && hasReplace(row);
1176
+ }
1171
1177
  function getAdapter(id) {
1172
1178
  return BY_ID.get(id);
1173
1179
  }
@@ -4642,7 +4648,7 @@ function read(ev, row, input) {
4642
4648
  return ALLOW;
4643
4649
  }
4644
4650
  function shellDump(cmds, cwd, row) {
4645
- if (row.nativeTools.read !== void 0 && row.nativeTools.read.length > 0 && hasReplace(row)) return null;
4651
+ if (row.nativeTools.read !== void 0 && row.nativeTools.read.length > 0 && dumpRunsThenReplaces(row)) return null;
4646
4652
  if (cmds.length !== 1) return null;
4647
4653
  const c = cmds[0];
4648
4654
  if (c.redirectsToFile || c.endsInBoundedSink) return null;
package/search.mjs CHANGED
@@ -354,8 +354,10 @@ var V1_REASON = Object.freeze({
354
354
  var UPGRADE_REPORT_ONLY_REASONS = Object.freeze([V1_REASON.statusLine, V1_REASON.vscodeMcp, V1_REASON.dataDirShared, V1_REASON.tmpFile, V1_REASON.kiroSteering]);
355
355
  var OPENCODE_TOOL_PREFIX = SERVER_KEY + "_";
356
356
  var ZCODE_MCP_FEATURE_KEY = Object.freeze(["features", "mcp"]);
357
+ var CODEX_OMIT_TOOLS_FROM_FIELD = "omit_tools_from";
358
+ var CODEX_OMIT_DEFERRED = Object.freeze(["deferred"]);
357
359
  var OWN_MCP_ENTRY = Object.freeze({
358
- codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY] },
360
+ codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY], fields: { [CODEX_OMIT_TOOLS_FROM_FIELD]: CODEX_OMIT_DEFERRED } },
359
361
  vscode: { file: [".vscode", "mcp.json"], key: ["servers", SERVER_KEY] },
360
362
  kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
361
363
  zcode: {
@@ -1168,6 +1170,10 @@ var REPLACE_ROWS = /* @__PURE__ */ new Set(["claude-code", "gemini", "copilot-cl
1168
1170
  function hasReplace(row) {
1169
1171
  return REPLACE_ROWS.has(row.id);
1170
1172
  }
1173
+ var DUMP_REPLACE_ROWS = /* @__PURE__ */ new Set(["claude-code", "copilot-cli", "pi"]);
1174
+ function dumpRunsThenReplaces(row) {
1175
+ return DUMP_REPLACE_ROWS.has(row.id) && hasReplace(row);
1176
+ }
1171
1177
  function getAdapter(id) {
1172
1178
  return BY_ID.get(id);
1173
1179
  }
@@ -4642,7 +4648,7 @@ function read(ev, row, input) {
4642
4648
  return ALLOW;
4643
4649
  }
4644
4650
  function shellDump(cmds, cwd, row) {
4645
- if (row.nativeTools.read !== void 0 && row.nativeTools.read.length > 0 && hasReplace(row)) return null;
4651
+ if (row.nativeTools.read !== void 0 && row.nativeTools.read.length > 0 && dumpRunsThenReplaces(row)) return null;
4646
4652
  if (cmds.length !== 1) return null;
4647
4653
  const c = cmds[0];
4648
4654
  if (c.redirectsToFile || c.endsInBoundedSink) return null;
package/server.mjs CHANGED
@@ -28312,7 +28312,7 @@ var DECISION_SOURCE = "decision";
28312
28312
  var DECISION_USER_LABEL = "decision (user)";
28313
28313
  var RELEASE_REPO_URL = "https://github.com/mksglu/context-mode.git";
28314
28314
  var RELEASE_BRANCH = "release";
28315
- var BUNDLE_SHA = true ? "0bf5734278463ea178b282436a39ba81347dadab" : void 0;
28315
+ var BUNDLE_SHA = true ? "3374b3ce2faee35730f5c335678ca40b405e923c" : void 0;
28316
28316
  var DOCTOR_CHECK_ORDER = Object.freeze(["D1", "D2", "D3", "D4", "D5", "D5b", "D6", "D7", "D8", "D9", "D10"]);
28317
28317
  var DOCTOR_LABEL = Object.freeze({
28318
28318
  D1: "version",
@@ -28551,6 +28551,7 @@ var V1_HOOKS_DIR_NAME = "hooks";
28551
28551
  var SETTINGS_FILE = "settings.json";
28552
28552
  var CLAUDE_USER_CONFIG_FILE = ".claude.json";
28553
28553
  var HOOKS_JSON_FILE = "hooks.json";
28554
+ var CODEX_HOME_ENV = "CODEX_HOME";
28554
28555
  var CONFIG_TOML_FILE = "config.toml";
28555
28556
  var CONFIG_JSON_FILE = "config.json";
28556
28557
  var ZCODE_CLI_DIR = "cli";
@@ -28616,8 +28617,10 @@ var JSON_INDENT_UNIT = " ";
28616
28617
  var MCP_COMMAND_FIELD = "command";
28617
28618
  var MCP_ARGS_FIELD = "args";
28618
28619
  var ZCODE_MCP_FEATURE_KEY = Object.freeze(["features", "mcp"]);
28620
+ var CODEX_OMIT_TOOLS_FROM_FIELD = "omit_tools_from";
28621
+ var CODEX_OMIT_DEFERRED = Object.freeze(["deferred"]);
28619
28622
  var OWN_MCP_ENTRY = Object.freeze({
28620
- codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY] },
28623
+ codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY], fields: { [CODEX_OMIT_TOOLS_FROM_FIELD]: CODEX_OMIT_DEFERRED } },
28621
28624
  vscode: { file: [".vscode", "mcp.json"], key: ["servers", SERVER_KEY] },
28622
28625
  kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
28623
28626
  zcode: {
@@ -29057,6 +29060,10 @@ function homeDirOf(env) {
29057
29060
  if (profile !== void 0 && profile !== "") return profile;
29058
29061
  return null;
29059
29062
  }
29063
+ function codexDirOf(env, home) {
29064
+ const dir = env[CODEX_HOME_ENV];
29065
+ return dir !== void 0 && dir !== "" ? dir : join(home, ...AGENT_HOME_DIR.codex);
29066
+ }
29060
29067
  function homeOf(env) {
29061
29068
  const home = homeDirOf(env);
29062
29069
  if (home !== null) return home;
@@ -31536,16 +31543,23 @@ var TYPO_MIN_LEN = 5;
31536
31543
  var TYPO_MAX_DIST = 2;
31537
31544
  function typoTerms(db, words) {
31538
31545
  const has = stmt(db.raw, "SELECT 1 AS x FROM chunks_vocab WHERE term = ?");
31539
- const near = stmt(db.raw, "SELECT term, doc FROM chunks_vocab WHERE length(term) BETWEEN ? AND ?");
31546
+ const near = stmt(db.raw, "SELECT term, doc, length(term) AS n FROM chunks_vocab WHERE length(term) BETWEEN ? AND ?");
31547
+ const stems = queryStems(words.join(" "));
31548
+ const miss = stems.map((stem) => has.get(stem) === void 0 && [...stem].length >= TYPO_MIN_LEN);
31549
+ if (!miss.includes(true)) return null;
31550
+ const lens = stems.filter((_, i) => miss[i]).map((stem) => stem.length);
31551
+ const rows = near.all(Math.min(...lens) - TYPO_MAX_DIST, Math.max(...lens) + TYPO_MAX_DIST);
31540
31552
  let changed = false;
31541
31553
  const out = [];
31542
- for (const stem of queryStems(words.join(" "))) {
31543
- if (has.get(stem) !== void 0 || [...stem].length < TYPO_MIN_LEN) {
31554
+ stems.forEach((stem, i) => {
31555
+ if (!miss[i]) {
31544
31556
  out.push(stem);
31545
- continue;
31557
+ return;
31546
31558
  }
31547
31559
  let best = null;
31548
- for (const r of near.all(stem.length - TYPO_MAX_DIST, stem.length + TYPO_MAX_DIST)) {
31560
+ for (const r of rows) {
31561
+ const n = Number(r.n);
31562
+ if (n < stem.length - TYPO_MAX_DIST || n > stem.length + TYPO_MAX_DIST) continue;
31549
31563
  const d = editDistance(stem, r.term, TYPO_MAX_DIST);
31550
31564
  if (d > TYPO_MAX_DIST) continue;
31551
31565
  if (best === null || d < best.d || d === best.d && (r.doc > best.doc || r.doc === best.doc && r.term < best.term)) {
@@ -31556,7 +31570,7 @@ function typoTerms(db, words) {
31556
31570
  out.push(best.term);
31557
31571
  changed = true;
31558
31572
  }
31559
- }
31573
+ });
31560
31574
  return changed ? out.map((t) => `"${t.replaceAll('"', '""')}"*`) : null;
31561
31575
  }
31562
31576
  function ftsQuery(db, q, scope, ctx, sessionId, limit, offset, source) {
@@ -45805,6 +45819,7 @@ function ownHooks(block, shape, timeoutKey, native, agent) {
45805
45819
  var validTimeout = (v) => typeof v === "number" && Number.isFinite(v) && v > 0;
45806
45820
  function mcpFile(row5, home, env) {
45807
45821
  const spec = OWN_MCP_ENTRY[row5.id];
45822
+ if (row5.id === "codex") return join9(codexDirOf(env, home), CONFIG_TOML_FILE);
45808
45823
  if (spec !== void 0) return join9(home, ...spec.file);
45809
45824
  if (row5.id === "opencode") return join9(home, ...AGENT_HOME_DIR.opencode, OPENCODE_BASE_CONFIG_FILE);
45810
45825
  if (row5.id === "pi") {
@@ -45832,9 +45847,10 @@ function hookParts(row5, home, env, worktree) {
45832
45847
  let block;
45833
45848
  try {
45834
45849
  const root = spec.root === "plugin" ? resolvePluginRoot(row5, env) : spec.root === "home" ? home : worktree;
45835
- block = hostConfigValueAt(readParsed(row5.id, join9(root, ...spec.file)).value, spec.key);
45850
+ const file2 = row5.id === "codex" ? join9(codexDirOf(env, home), HOOKS_JSON_FILE) : join9(root, ...spec.file);
45851
+ block = hostConfigValueAt(readParsed(row5.id, file2).value, spec.key);
45836
45852
  if (row5.id === "codex") {
45837
- const config4 = readParsed(row5.id, join9(home, ...AGENT_HOME_DIR.codex, CONFIG_TOML_FILE)).value;
45853
+ const config4 = readParsed(row5.id, join9(codexDirOf(env, home), CONFIG_TOML_FILE)).value;
45838
45854
  if (hostConfigValueAt(config4, CODEX_FEATURES_HOOKS_KEY) === false) return [PART_HOOKS];
45839
45855
  }
45840
45856
  } catch {
@@ -46230,8 +46246,8 @@ async function hookRow(ctx, adapter, host) {
46230
46246
  bundleDir: host.bundleDir,
46231
46247
  env: buildChildEnv(host.env),
46232
46248
  signal: ctx.signal,
46233
- codexConfigDir: join10(needHome(host.env), ...AGENT_HOME_DIR.codex),
46234
- // same Codex dir D3 reads
46249
+ codexConfigDir: codexDirOf(host.env, needHome(host.env)),
46250
+ // same Codex dir D3 reads (D-N6-CODEX-HOME-2)
46235
46251
  db
46236
46252
  });
46237
46253
  } finally {