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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/hooks.json +50 -0
- package/.codex-plugin/mcp.json +14 -0
- package/.codex-plugin/plugin.json +12 -0
- package/SHA256SUMS +19 -13
- package/cli.mjs +125 -10
- package/codex/skills/ctx-doctor/SKILL.md +6 -0
- package/codex/skills/ctx-stats/SKILL.md +6 -0
- package/codex/skills/ctx-upgrade/SKILL.md +6 -0
- package/copilot/plugin.json +1 -1
- package/gemini-extension.json +1 -1
- package/hook.mjs +79 -79
- package/opencode/plugin.js +51 -16
- package/package.json +4 -1
- package/pi/index.js +51 -16
- package/qwen-extension.json +1 -1
- package/run.mjs +8 -2
- package/search.mjs +8 -2
- package/server.mjs +28 -12
package/opencode/plugin.js
CHANGED
|
@@ -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
|
-
|
|
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 ? "
|
|
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 &&
|
|
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
|
-
|
|
6064
|
-
if (
|
|
6081
|
+
stems.forEach((stem, i) => {
|
|
6082
|
+
if (!miss[i]) {
|
|
6065
6083
|
out.push(stem);
|
|
6066
|
-
|
|
6084
|
+
return;
|
|
6067
6085
|
}
|
|
6068
6086
|
let best = null;
|
|
6069
|
-
for (const r of
|
|
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
|
-
|
|
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(
|
|
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:
|
|
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.
|
|
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
|
-
|
|
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 ? "
|
|
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 &&
|
|
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
|
-
|
|
17210
|
-
if (
|
|
17227
|
+
stems.forEach((stem, i) => {
|
|
17228
|
+
if (!miss[i]) {
|
|
17211
17229
|
out.push(stem);
|
|
17212
|
-
|
|
17230
|
+
return;
|
|
17213
17231
|
}
|
|
17214
17232
|
let best = null;
|
|
17215
|
-
for (const r of
|
|
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
|
-
|
|
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(
|
|
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:
|
|
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 {
|
package/qwen-extension.json
CHANGED
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 &&
|
|
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 &&
|
|
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 ? "
|
|
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
|
-
|
|
31543
|
-
if (
|
|
31554
|
+
stems.forEach((stem, i) => {
|
|
31555
|
+
if (!miss[i]) {
|
|
31544
31556
|
out.push(stem);
|
|
31545
|
-
|
|
31557
|
+
return;
|
|
31546
31558
|
}
|
|
31547
31559
|
let best = null;
|
|
31548
|
-
for (const r of
|
|
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
|
-
|
|
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(
|
|
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:
|
|
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 {
|