context-mode 2.0.0-next.5 → 2.0.0-next.7
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 +22 -16
- package/cli.mjs +196 -24
- 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 +81 -81
- package/opencode/plugin.js +122 -30
- package/package.json +4 -1
- package/pi/index.js +122 -30
- package/qwen-extension.json +1 -1
- package/run.mjs +79 -16
- package/search.mjs +79 -16
- package/server.mjs +99 -26
- package/skills/ctx-doctor/SKILL.md +1 -1
- package/skills/ctx-stats/SKILL.md +1 -1
- package/skills/ctx-upgrade/SKILL.md +1 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"PostToolUse": [
|
|
4
|
+
{
|
|
5
|
+
"hooks": [
|
|
6
|
+
{
|
|
7
|
+
"command": "node \"${PLUGIN_ROOT}/hook.mjs\" --agent codex",
|
|
8
|
+
"timeout": 5,
|
|
9
|
+
"type": "command"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"matcher": "^(Bash|apply_patch|mcp__context_mode__ctx_.*)$"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"PreToolUse": [
|
|
16
|
+
{
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"command": "node \"${PLUGIN_ROOT}/hook.mjs\" --agent codex",
|
|
20
|
+
"timeout": 5,
|
|
21
|
+
"type": "command"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"matcher": "^(Bash|apply_patch|mcp__context_mode__ctx_.*)$"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"SessionStart": [
|
|
28
|
+
{
|
|
29
|
+
"hooks": [
|
|
30
|
+
{
|
|
31
|
+
"command": "node \"${PLUGIN_ROOT}/hook.mjs\" --agent codex",
|
|
32
|
+
"timeout": 5,
|
|
33
|
+
"type": "command"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"UserPromptSubmit": [
|
|
39
|
+
{
|
|
40
|
+
"hooks": [
|
|
41
|
+
{
|
|
42
|
+
"command": "node \"${PLUGIN_ROOT}/hook.mjs\" --agent codex",
|
|
43
|
+
"timeout": 5,
|
|
44
|
+
"type": "command"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Context Mode for Codex",
|
|
3
|
+
"hooks": "./.codex-plugin/hooks.json",
|
|
4
|
+
"interface": {
|
|
5
|
+
"category": "Productivity",
|
|
6
|
+
"displayName": "context-mode"
|
|
7
|
+
},
|
|
8
|
+
"mcpServers": "./.codex-plugin/mcp.json",
|
|
9
|
+
"name": "context-mode",
|
|
10
|
+
"skills": "./codex/skills/",
|
|
11
|
+
"version": "2.0.0-next.7"
|
|
12
|
+
}
|
package/SHA256SUMS
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
7362028009067c6db76e755a639e87a1e3cfe4dfc8d913fcefd5169d55103080 .claude-plugin/marketplace.json
|
|
2
|
+
e5d35796110662348715d11a79e794fbbe9e61e62902cd76cd68486da635f1a3 .claude-plugin/plugin.json
|
|
3
|
+
187503e1455560d4ab5a72e3b8cd2f274abd4ccc5faa60dd66c37e44bb5f10c2 .codex-plugin/hooks.json
|
|
4
|
+
4edea851775bc3f0418f8d9cf6ead74f2767c3a9e3b8c05749eacb78ebb3b896 .codex-plugin/mcp.json
|
|
5
|
+
f96f490f057000cab1f5c56496c0fc3de446a637b6f954d6d853663e9b03197c .codex-plugin/plugin.json
|
|
3
6
|
1773e40a89384dd1af9023ba533da1908f3e2435dbaaa7cc941edf0514148313 claude-code/skills/ctx-doctor/SKILL.md
|
|
4
7
|
34fffb9c76d69c551f07036230bec0fbaca7a69177a5a47f89ddb9a9990a1fa2 claude-code/skills/ctx-stats/SKILL.md
|
|
5
8
|
d8f835d2f2b3eb70c5902f8707e7c5857977cec9e20ace76c499378a04e178e0 claude-code/skills/ctx-upgrade/SKILL.md
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
4716b2bc1bce3752f140f6b8f2b276f53b36960ac724eb7f03e1c93318fee4f1 cli.mjs
|
|
10
|
+
83c297020ed0c592fc68c9c482546a6999d41df5d06d8a329498f10edb1bd38e codex/skills/ctx-doctor/SKILL.md
|
|
11
|
+
adc2c374f699d3698110920bb48411965de09fc6e7232ce59c913f6d58c0d738 codex/skills/ctx-stats/SKILL.md
|
|
12
|
+
5c12cdd19a5e3ed7d9ba3a47b24d03864a28d36cf7006876284ee07cd4221ec4 codex/skills/ctx-upgrade/SKILL.md
|
|
13
|
+
83ba9e9cfc9ed07b404f2afd55f65c04a2716e428559c5264ceb97bdfcf3cdae copilot/plugin.json
|
|
8
14
|
832bf0d31c37a448f3904bc41c7df071777aec2f8fce9d667f1fcf5b03a52a91 fixtures/hook-roundtrip.json
|
|
9
|
-
|
|
10
|
-
|
|
15
|
+
d28e323da98711de50112f1e7a1242c22133cd3490e0109d6824732cfd494c4e gemini-extension.json
|
|
16
|
+
ccab1edf7d21b15976b3523acecca1f485f4b0822b265e27c7a0df821e097c1c hook.mjs
|
|
11
17
|
1f8d8650d2b38737522cab6b875878e8baf84a74acf98cd924c7af22852d873f hooks/claude-code.json
|
|
12
18
|
2524a0eb52683b65c65943c5097db513e9845ba14e84324b39e9a8ea2bb43193 hooks/codex.json
|
|
13
19
|
b656fed2b754ebcfd4c156bee81d5879c21a8083fc0d6b8e3241462b63a214b6 hooks/copilot-cli.json
|
|
@@ -16,16 +22,16 @@ f336d1db67de49e641687bbd41ba1a9424e31dfe2377b2284bf44358288ebd8b hooks/kiro.jso
|
|
|
16
22
|
017c9cc3997dd53231b8548b1a1609fddc51177af53501565a4f334602039860 hooks/qwen.json
|
|
17
23
|
33f69267645338d0dc392ce551dcd7c69a0b508113469d6ea637d3f34239ef1d hooks/vscode.json
|
|
18
24
|
085630bccf2073ac9a62be24ef91dfc47d106092dc82c822db70890b7d3ae1c0 hooks/zcode.json
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
8dfb464afb21d1548e5c1368fac5fd8d43838a2d8111bc3ec82cac8a09c977e3 opencode/plugin.js
|
|
26
|
+
d38b8f717169353ff603f6b22ee66d25c01e1670a64583e28ccec3862f29e215 package.json
|
|
27
|
+
d8784f4a18e478f7176189d9c45ab28843e3dbfa7e4c50103c1f20036961e8d0 pi/index.js
|
|
22
28
|
8712881622c9905aa4836af50d903042d34a91506264e459bc7839331f6f0192 pi/skills/ctx-doctor/SKILL.md
|
|
23
29
|
8d6e8e2a82eb079bddc60727f52d9f9a6e0bf9e15391357fed82ee76ab5fe76c pi/skills/ctx-stats/SKILL.md
|
|
24
30
|
db6f9c006bc864a7271f1eeffb1e316ebb537a3414f1c22f8b9de0a896e8e3c5 pi/skills/ctx-upgrade/SKILL.md
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
6a8c387c281796e0f90309e730424e60191471ea0f26585dde7a4f22124c8ed4 qwen-extension.json
|
|
32
|
+
54f4ec9ac9cc26814e7e548b8bafb05bf2610eb0ed0bab2f1e9576e2c99a799d run.mjs
|
|
33
|
+
54f4ec9ac9cc26814e7e548b8bafb05bf2610eb0ed0bab2f1e9576e2c99a799d search.mjs
|
|
34
|
+
f8929b0cb819af7a2e6989efb34da39ff46a4e3a53702e717903442bdc8874b5 server.mjs
|
|
35
|
+
e5503a22a6238901484d123efc11d2d933aa9a54c6ac2018812cfa65ec4e53e3 skills/ctx-doctor/SKILL.md
|
|
36
|
+
1044587a1906c69f2467c089a25e19819a290ea5728389bd1f086c6dfc0d0c51 skills/ctx-stats/SKILL.md
|
|
37
|
+
c1cac75b7506ee0d06089ce611ac6dc9314cf12435da318ce88ad50e2c5debbf skills/ctx-upgrade/SKILL.md
|
package/cli.mjs
CHANGED
|
@@ -442,8 +442,12 @@ var UPGRADE_REPORT_ONLY_REASONS = Object.freeze([V1_REASON.statusLine, V1_REASON
|
|
|
442
442
|
var OPENCODE_TOOL_PREFIX = SERVER_KEY + "_";
|
|
443
443
|
var JSON_INDENT_UNIT = " ";
|
|
444
444
|
var ZCODE_MCP_FEATURE_KEY = Object.freeze(["features", "mcp"]);
|
|
445
|
+
var CODEX_OMIT_TOOLS_FROM_FIELD = "omit_tools_from";
|
|
446
|
+
var CODEX_OMIT_DEFERRED = Object.freeze(["deferred"]);
|
|
447
|
+
var CODEX_APPROVAL_MODE_FIELD = "default_tools_approval_mode";
|
|
448
|
+
var CODEX_APPROVAL_APPROVE = "approve";
|
|
445
449
|
var OWN_MCP_ENTRY = Object.freeze({
|
|
446
|
-
codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY] },
|
|
450
|
+
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 } },
|
|
447
451
|
vscode: { file: [".vscode", "mcp.json"], key: ["servers", SERVER_KEY] },
|
|
448
452
|
kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
|
|
449
453
|
zcode: {
|
|
@@ -830,9 +834,62 @@ function readResult4(resp) {
|
|
|
830
834
|
const isError = typeof resp === "object" && resp !== null && resp.is_error === true;
|
|
831
835
|
return { isError, bytes: Buffer.byteLength(text2), text: text2 };
|
|
832
836
|
}
|
|
837
|
+
var CAMEL_EVENTS = {
|
|
838
|
+
sessionStart: "SessionStart",
|
|
839
|
+
userPromptSubmitted: "UserPromptSubmit",
|
|
840
|
+
preToolUse: "PreToolUse",
|
|
841
|
+
postToolUse: "PostToolUse",
|
|
842
|
+
preCompact: "PreCompact"
|
|
843
|
+
};
|
|
844
|
+
var EVENT_BY_KEY2 = [
|
|
845
|
+
["toolResult", "postToolUse"],
|
|
846
|
+
["toolName", "preToolUse"],
|
|
847
|
+
["prompt", "userPromptSubmitted"],
|
|
848
|
+
["source", "sessionStart"],
|
|
849
|
+
["trigger", "preCompact"]
|
|
850
|
+
];
|
|
851
|
+
var SESSION_SOURCES = { new: "startup", startup: "startup", resume: "resume" };
|
|
852
|
+
var RESULT_SUCCESS2 = "success";
|
|
853
|
+
function isRecord2(v) {
|
|
854
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
855
|
+
}
|
|
856
|
+
function readArgs2(v) {
|
|
857
|
+
if (isRecord2(v)) return v;
|
|
858
|
+
if (typeof v !== "string") return {};
|
|
859
|
+
try {
|
|
860
|
+
const parsed = JSON.parse(v);
|
|
861
|
+
return isRecord2(parsed) ? parsed : {};
|
|
862
|
+
} catch {
|
|
863
|
+
return {};
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
function readCamelResult(v) {
|
|
867
|
+
const r2 = isRecord2(v) ? v : {};
|
|
868
|
+
const text2 = typeof r2.textResultForLlm === "string" ? r2.textResultForLlm : "";
|
|
869
|
+
return { isError: typeof r2.resultType === "string" && r2.resultType !== RESULT_SUCCESS2, bytes: Buffer.byteLength(text2), text: text2 };
|
|
870
|
+
}
|
|
871
|
+
function decodeCamel(p3, name) {
|
|
872
|
+
const event = typeof name === "string" ? CAMEL_EVENTS[name] ?? VSCODE_EVENTS.find((e) => e === name) : void 0;
|
|
873
|
+
if (event === void 0) throw new Error("vscode: unknown hook event " + String(name));
|
|
874
|
+
const ev = { event, agent: "vscode", sessionId: String(p3.sessionId ?? ""), cwd: String(p3.cwd ?? "") };
|
|
875
|
+
if (event === "SessionStart" && typeof p3.source === "string" && SESSION_SOURCES[p3.source] !== void 0) ev.source = SESSION_SOURCES[p3.source];
|
|
876
|
+
if (event === "UserPromptSubmit" && typeof p3.prompt === "string") ev.prompt = p3.prompt;
|
|
877
|
+
if (event === "PreToolUse" || event === "PostToolUse") {
|
|
878
|
+
const toolName = String(p3.toolName ?? "");
|
|
879
|
+
ev.tool = { name: toolName, canonicalName: canonicalName4(toolName), input: readArgs2(p3.toolArgs) };
|
|
880
|
+
}
|
|
881
|
+
if (event === "PostToolUse") ev.result = readCamelResult(p3.toolResult);
|
|
882
|
+
return ev;
|
|
883
|
+
}
|
|
833
884
|
function decode6(raw) {
|
|
834
885
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new Error("vscode: hook payload is not a JSON object");
|
|
835
886
|
const p3 = raw;
|
|
887
|
+
if (p3.hookEventName !== void 0) return decodeCamel(p3, p3.hookEventName);
|
|
888
|
+
if (p3.hook_event_name === void 0) {
|
|
889
|
+
const byKey = EVENT_BY_KEY2.find(([key]) => Object.hasOwn(p3, key))?.[1];
|
|
890
|
+
if (byKey === void 0) throw new Error("vscode: missing required field hook_event_name");
|
|
891
|
+
return decodeCamel(p3, byKey);
|
|
892
|
+
}
|
|
836
893
|
const event = VSCODE_EVENTS.find((e) => e === p3.hook_event_name);
|
|
837
894
|
if (event === void 0) throw new Error("vscode: unknown hook event " + String(p3.hook_event_name));
|
|
838
895
|
const ev = { event, agent: "vscode", sessionId: String(p3.session_id ?? ""), cwd: String(p3.cwd ?? "") };
|
|
@@ -840,7 +897,7 @@ function decode6(raw) {
|
|
|
840
897
|
if (event === "UserPromptSubmit" && typeof p3.prompt === "string") ev.prompt = p3.prompt;
|
|
841
898
|
if (event === "PreToolUse" || event === "PostToolUse") {
|
|
842
899
|
const name = String(p3.tool_name ?? "");
|
|
843
|
-
const input =
|
|
900
|
+
const input = isRecord2(p3.tool_input) ? p3.tool_input : {};
|
|
844
901
|
ev.tool = { name, canonicalName: canonicalName4(name), input };
|
|
845
902
|
}
|
|
846
903
|
if (event === "PostToolUse") ev.result = readResult4(p3.tool_response);
|
|
@@ -859,12 +916,14 @@ var KIRO_EVENTS = {
|
|
|
859
916
|
PromptSubmit: "UserPromptSubmit",
|
|
860
917
|
userPromptSubmit: "UserPromptSubmit",
|
|
861
918
|
PreToolUse: "PreToolUse",
|
|
862
|
-
|
|
919
|
+
preToolUse: "PreToolUse",
|
|
920
|
+
PostToolUse: "PostToolUse",
|
|
921
|
+
postToolUse: "PostToolUse"
|
|
863
922
|
};
|
|
864
923
|
var PROMPT_ENV = "USER_PROMPT";
|
|
865
924
|
var MCP_PREFIX3 = "mcp_";
|
|
866
|
-
var
|
|
867
|
-
var NATIVE_TO_CANONICAL5 =
|
|
925
|
+
var SHELL_TOOL_NAMES = Object.freeze(["execute_bash", "execute_pwsh", "shell"]);
|
|
926
|
+
var NATIVE_TO_CANONICAL5 = Object.fromEntries(SHELL_TOOL_NAMES.map((n3) => [n3, "Bash"]));
|
|
868
927
|
var MCP_SEP3 = "_";
|
|
869
928
|
var KIRO_SOURCES = { startup: "startup", resume: "resume", clear: "clear", compact: "compact" };
|
|
870
929
|
function canonicalName5(name) {
|
|
@@ -1005,8 +1064,8 @@ var OPENCODE_EVENTS = {
|
|
|
1005
1064
|
compaction: "PreCompact",
|
|
1006
1065
|
"step-finish": "Usage"
|
|
1007
1066
|
};
|
|
1008
|
-
var
|
|
1009
|
-
var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [
|
|
1067
|
+
var SHELL_TOOL_NAME2 = "bash";
|
|
1068
|
+
var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [SHELL_TOOL_NAME2]: "Bash" };
|
|
1010
1069
|
function toCanonicalTool(name) {
|
|
1011
1070
|
if (name.startsWith(OWN_WIRE_PREFIX)) return name.slice(OWN_WIRE_PREFIX.length);
|
|
1012
1071
|
return Object.prototype.hasOwnProperty.call(NATIVE_TO_CANONICAL7, name) ? NATIVE_TO_CANONICAL7[name] : name;
|
|
@@ -1126,8 +1185,8 @@ var ADAPTERS = Object.freeze([
|
|
|
1126
1185
|
hookTimeoutMs: HOOK_TIMEOUT_MS,
|
|
1127
1186
|
denyChannel: "deny-reason",
|
|
1128
1187
|
hookChannel: { kind: "package", path: "hooks/qwen.json" },
|
|
1129
|
-
skillChannel: { kind: "
|
|
1130
|
-
// ADR-0020
|
|
1188
|
+
skillChannel: { kind: "package", path: "skills" },
|
|
1189
|
+
// ADR-0020, D-HQ-SKILLS-3: qwen loads <extension>/skills, shared with gemini
|
|
1131
1190
|
decode: decode4,
|
|
1132
1191
|
encode: encode4
|
|
1133
1192
|
},
|
|
@@ -1163,8 +1222,8 @@ var ADAPTERS = Object.freeze([
|
|
|
1163
1222
|
hookTimeoutMs: HOOK_TIMEOUT_MS,
|
|
1164
1223
|
denyChannel: "deny-reason",
|
|
1165
1224
|
hookChannel: { kind: "home-file", path: ".copilot/hooks/context-mode-vscode.json" },
|
|
1166
|
-
skillChannel: { kind: "home-dir", path: ".
|
|
1167
|
-
// ADR-0020
|
|
1225
|
+
skillChannel: { kind: "home-dir", path: ".agents/skills" },
|
|
1226
|
+
// ADR-0020, D-HQ-COPILOT-NAMES-3: Copilot CLI owns ~/.copilot/skills
|
|
1168
1227
|
decode: decode6,
|
|
1169
1228
|
encode: encode6
|
|
1170
1229
|
},
|
|
@@ -1173,9 +1232,9 @@ var ADAPTERS = Object.freeze([
|
|
|
1173
1232
|
installMode: "mcp-entry",
|
|
1174
1233
|
projectSource: "arg:--agent+cwd",
|
|
1175
1234
|
toolNamePrefix: TOOL_NAME_PREFIX7,
|
|
1176
|
-
nativeTools: { shell: [
|
|
1235
|
+
nativeTools: { shell: [...SHELL_TOOL_NAMES] },
|
|
1177
1236
|
execReadOnlyHint: false,
|
|
1178
|
-
// D-HF-KIRO-SHELL-1
|
|
1237
|
+
// D-HF-KIRO-SHELL-1, D-N7-KIRO-1
|
|
1179
1238
|
eventMap: { SessionStart: "SessionStart", UserPromptSubmit: "UserPromptSubmit", PreToolUse: "PreToolUse", PostToolUse: "PostToolUse" },
|
|
1180
1239
|
compactDelivery: "none",
|
|
1181
1240
|
compactSummary: "none",
|
|
@@ -1188,7 +1247,7 @@ var ADAPTERS = Object.freeze([
|
|
|
1188
1247
|
encode: encode7
|
|
1189
1248
|
},
|
|
1190
1249
|
{
|
|
1191
|
-
// toolNamePrefix
|
|
1250
|
+
// toolNamePrefix is the documented ZCode name mcp__<server>__<tool> (D-N7-ZCODE-NAMES-1); nativeTools are Claude names.
|
|
1192
1251
|
id: "zcode",
|
|
1193
1252
|
installMode: "hooks+mcp",
|
|
1194
1253
|
projectSource: "spawn-cwd",
|
|
@@ -1230,7 +1289,7 @@ var ADAPTERS = Object.freeze([
|
|
|
1230
1289
|
installMode: "in-process",
|
|
1231
1290
|
projectSource: "spawn-cwd",
|
|
1232
1291
|
toolNamePrefix: TOOL_NAME_PREFIX10,
|
|
1233
|
-
nativeTools: { shell: [
|
|
1292
|
+
nativeTools: { shell: [SHELL_TOOL_NAME2] },
|
|
1234
1293
|
execReadOnlyHint: false,
|
|
1235
1294
|
// D-HF-OPENCODE-SHELL-1
|
|
1236
1295
|
// Usage: step-finish cost row (DEVIATIONS D-M5-arch-2).
|
|
@@ -5151,6 +5210,7 @@ var STATE_DIR = ".context-mode";
|
|
|
5151
5210
|
var LOCK_FILE = "setup.lock";
|
|
5152
5211
|
var BACKUP_DIR = "backups";
|
|
5153
5212
|
var PLUGIN_ID = `${SERVER_KEY}@${SERVER_KEY}`;
|
|
5213
|
+
var SKILLS_DIR_NAME = "skills";
|
|
5154
5214
|
var INSTRUCTION_FILES = Object.freeze([
|
|
5155
5215
|
"CLAUDE.md",
|
|
5156
5216
|
"AGENTS.md",
|
|
@@ -5164,10 +5224,17 @@ function configEdits(c3) {
|
|
|
5164
5224
|
return [[c3.key, c3.value], ...c3.also ?? []];
|
|
5165
5225
|
}
|
|
5166
5226
|
var COMMAND_SKILLS = Object.freeze(["ctx-doctor", "ctx-stats", "ctx-upgrade"]);
|
|
5167
|
-
var SKILLS_DIR = "skills";
|
|
5168
5227
|
var SKILL_FILE = "SKILL.md";
|
|
5169
5228
|
var OPENCODE_PLUGIN = ["opencode", "plugin.js"];
|
|
5170
5229
|
var CODEX_CONFIG_FILE = "config.toml";
|
|
5230
|
+
var CODEX_HOME_ENV2 = "CODEX_HOME";
|
|
5231
|
+
var CODEX_DIR = ".codex";
|
|
5232
|
+
function agentPath(ctx, id, rel) {
|
|
5233
|
+
const segs = typeof rel === "string" ? rel.split("/") : [...rel];
|
|
5234
|
+
const codexHome = ctx.env[CODEX_HOME_ENV2];
|
|
5235
|
+
if (id === "codex" && segs[0] === CODEX_DIR && codexHome !== void 0 && codexHome !== "") return path2.join(codexHome, ...segs.slice(1));
|
|
5236
|
+
return path2.join(ctx.home, ...segs);
|
|
5237
|
+
}
|
|
5171
5238
|
function renderSkill(text2, prefix) {
|
|
5172
5239
|
const prefixes = typeof prefix === "string" ? [prefix] : prefix;
|
|
5173
5240
|
if (prefixes.length === 1 && prefixes[0] === "") return text2;
|
|
@@ -5183,6 +5250,23 @@ function skillDirPrefixes(dirPath) {
|
|
|
5183
5250
|
}
|
|
5184
5251
|
return out2;
|
|
5185
5252
|
}
|
|
5253
|
+
var EXTENSION_LIST = ["extensions", "list"];
|
|
5254
|
+
function extensionPlugin(bin, id) {
|
|
5255
|
+
return {
|
|
5256
|
+
bin,
|
|
5257
|
+
args: EXTENSION_LIST,
|
|
5258
|
+
plugin: SERVER_KEY,
|
|
5259
|
+
hooksVia: getAdapter(id).hookChannel.path,
|
|
5260
|
+
skillsVia: SKILLS_DIR_NAME,
|
|
5261
|
+
format: "extension",
|
|
5262
|
+
enable: ["extensions", "enable", SERVER_KEY]
|
|
5263
|
+
};
|
|
5264
|
+
}
|
|
5265
|
+
var NATIVE_PLUGIN = {
|
|
5266
|
+
codex: { bin: "codex", args: ["plugin", "list"], plugin: PLUGIN_ID, hooksVia: ".codex-plugin", skillsVia: path2.join("codex", SKILLS_DIR_NAME), format: "table" },
|
|
5267
|
+
qwen: extensionPlugin("qwen", "qwen"),
|
|
5268
|
+
gemini: extensionPlugin("gemini", "gemini")
|
|
5269
|
+
};
|
|
5186
5270
|
function serverCmd(ctx, id) {
|
|
5187
5271
|
return [process.execPath, path2.join(ctx.pkgDir, SERVER_BUNDLE), AGENT_FLAG, id];
|
|
5188
5272
|
}
|
|
@@ -5205,7 +5289,7 @@ function configFor(ctx, id) {
|
|
|
5205
5289
|
const [node, server, flag, agent] = serverCmd(ctx, id);
|
|
5206
5290
|
const own2 = OWN_MCP_ENTRY[id];
|
|
5207
5291
|
if (own2) {
|
|
5208
|
-
const file =
|
|
5292
|
+
const file = agentPath(ctx, id, own2.file);
|
|
5209
5293
|
const format = file.endsWith(".toml") ? "toml" : id === "vscode" ? "jsonc" : "json";
|
|
5210
5294
|
const args = id === "vscode" ? [server, flag, agent, WORKSPACE_FOLDER_FLAG, VSCODE_WORKSPACE_VAR] : [server, flag, agent];
|
|
5211
5295
|
const also = own2.also?.map(([k, v]) => [k, v]);
|
|
@@ -5255,10 +5339,11 @@ var LIST = {
|
|
|
5255
5339
|
// D-HF-OPENCODE-LIST-1: --pure skips external plugins, so a fresh HOME does not wait on the @opencode-ai/plugin install.
|
|
5256
5340
|
opencode: { bin: "opencode", args: ["mcp", "list", "--pure"] }
|
|
5257
5341
|
};
|
|
5258
|
-
function hookFilesFor(
|
|
5342
|
+
function hookFilesFor(ctx, id) {
|
|
5343
|
+
const home = ctx.home;
|
|
5259
5344
|
switch (id) {
|
|
5260
5345
|
case "codex":
|
|
5261
|
-
return [{ file:
|
|
5346
|
+
return [{ file: agentPath(ctx, id, [CODEX_DIR, "hooks.json"]), mode: "rewrite" }];
|
|
5262
5347
|
case "copilot-cli":
|
|
5263
5348
|
return [{ file: path2.join(home, ".copilot", "hooks", "context-mode.json"), mode: "rewrite" }];
|
|
5264
5349
|
case "claude-code":
|
|
@@ -5276,7 +5361,7 @@ function hookInstallFor(ctx, row, command) {
|
|
|
5276
5361
|
if (ch.kind === "home-file") {
|
|
5277
5362
|
const shape = HOOK_SHAPES[row.id];
|
|
5278
5363
|
if (!shape) throw new Error(`setup: ${row.id} has a home-file hook channel and no hook shape`);
|
|
5279
|
-
const file =
|
|
5364
|
+
const file = agentPath(ctx, row.id, ch.path);
|
|
5280
5365
|
if (row.id === "codex") return { kind: "file", file, shape: shape(row, command), command, trust: path2.join(path2.dirname(file), CODEX_CONFIG_FILE) };
|
|
5281
5366
|
return { kind: "file", file, shape: shape(row, command), command };
|
|
5282
5367
|
}
|
|
@@ -5290,13 +5375,19 @@ function hookInstallFor(ctx, row, command) {
|
|
|
5290
5375
|
}
|
|
5291
5376
|
return { kind: "package", via: ch.path };
|
|
5292
5377
|
}
|
|
5378
|
+
function bareSkillDir() {
|
|
5379
|
+
const row = ADAPTERS.find((r2) => r2.skillChannel.kind === "package" && r2.toolNamePrefix === "");
|
|
5380
|
+
if (row === void 0) throw new Error("setup: no package skill channel holds the bare tool names");
|
|
5381
|
+
return row.skillChannel.path;
|
|
5382
|
+
}
|
|
5293
5383
|
function skillInstallFor(ctx, row) {
|
|
5294
5384
|
const ch = row.skillChannel;
|
|
5295
5385
|
if (ch.kind === "package") return { kind: "package", via: ch.path };
|
|
5296
|
-
const dir =
|
|
5386
|
+
const dir = agentPath(ctx, row.id, ch.path);
|
|
5387
|
+
const src = path2.join(ctx.pkgDir, bareSkillDir());
|
|
5297
5388
|
return { kind: "dir", dir, prefixes: skillDirPrefixes(ch.path), files: COMMAND_SKILLS.map((name) => ({
|
|
5298
5389
|
name,
|
|
5299
|
-
src: path2.join(
|
|
5390
|
+
src: path2.join(src, name, SKILL_FILE),
|
|
5300
5391
|
file: path2.join(dir, name, SKILL_FILE)
|
|
5301
5392
|
})) };
|
|
5302
5393
|
}
|
|
@@ -5304,7 +5395,7 @@ function buildRegistry(ctx) {
|
|
|
5304
5395
|
return ADAPTERS.map((row) => {
|
|
5305
5396
|
const id = row.id;
|
|
5306
5397
|
const config = configFor(ctx, id);
|
|
5307
|
-
const hookFiles = hookFilesFor(ctx
|
|
5398
|
+
const hookFiles = hookFilesFor(ctx, id);
|
|
5308
5399
|
const hookCommand = [process.execPath, path2.join(ctx.pkgDir, HOOK_BUNDLE), AGENT_FLAG, id];
|
|
5309
5400
|
const command = `"${hookCommand[0]}" "${hookCommand[1]}" ${AGENT_FLAG} ${id}`;
|
|
5310
5401
|
const hookInstall = hookInstallFor(ctx, getAdapter(id), command);
|
|
@@ -5333,6 +5424,8 @@ function buildRegistry(ctx) {
|
|
|
5333
5424
|
if (row.installMode !== "in-process") out2.hookCommand = hookCommand;
|
|
5334
5425
|
const copy = copyFor(ctx, id);
|
|
5335
5426
|
if (copy) out2.copy = copy;
|
|
5427
|
+
const native = NATIVE_PLUGIN[id];
|
|
5428
|
+
if (native) out2.nativePlugin = native;
|
|
5336
5429
|
return out2;
|
|
5337
5430
|
});
|
|
5338
5431
|
}
|
|
@@ -5935,6 +6028,79 @@ function skillsCheck(row, pkgDir) {
|
|
|
5935
6028
|
const bad = s.files.filter((f2) => readOr(f2.file) !== (existsSync6(f2.src) ? renderSkill(readFileSync3(f2.src, "utf8"), s.prefixes) : void 0));
|
|
5936
6029
|
return { name: "skills", ok: bad.length === 0, detail: bad.length ? `${bad.map((f2) => f2.file).join(", ")} missing or without the ${s.prefixes.join(" / ") || "plain"} tool prefix` : void 0 };
|
|
5937
6030
|
}
|
|
6031
|
+
var PLUGIN_ENABLED = "enabled";
|
|
6032
|
+
var WORD_TRIM = ",;";
|
|
6033
|
+
var EXT_ENABLED_USER = "Enabled (User):";
|
|
6034
|
+
var EXT_TRUE = "true";
|
|
6035
|
+
function tableState(n3, text2) {
|
|
6036
|
+
const line = text2.split("\n").find((l2) => l2.split(" ").includes(n3.plugin));
|
|
6037
|
+
if (line === void 0) return void 0;
|
|
6038
|
+
return line.split(" ").map((w) => trimChars(w, WORD_TRIM)).includes(PLUGIN_ENABLED) ? "enabled" : "disabled";
|
|
6039
|
+
}
|
|
6040
|
+
function extensionState(n3, text2) {
|
|
6041
|
+
let mine = false;
|
|
6042
|
+
for (const raw of text2.split("\n")) {
|
|
6043
|
+
const line = raw.trimEnd();
|
|
6044
|
+
if (line.length && !line.startsWith(" ")) {
|
|
6045
|
+
mine = line.split(" ")[1] === n3.plugin;
|
|
6046
|
+
continue;
|
|
6047
|
+
}
|
|
6048
|
+
const t2 = line.trim();
|
|
6049
|
+
if (mine && t2.startsWith(EXT_ENABLED_USER)) return t2.slice(EXT_ENABLED_USER.length).trim() === EXT_TRUE ? "enabled" : "disabled";
|
|
6050
|
+
}
|
|
6051
|
+
return void 0;
|
|
6052
|
+
}
|
|
6053
|
+
function nativeState(row, env) {
|
|
6054
|
+
const n3 = row.nativePlugin;
|
|
6055
|
+
if (!n3 || !hostBin(n3.bin, env).file) return void 0;
|
|
6056
|
+
const r2 = runBin(n3.bin, n3.args, env);
|
|
6057
|
+
if (r2.status !== 0) return void 0;
|
|
6058
|
+
return n3.format === "extension" ? extensionState(n3, `${r2.stdout}${r2.stderr}`) : tableState(n3, `${r2.stdout}`);
|
|
6059
|
+
}
|
|
6060
|
+
function nativeRow(row, n3) {
|
|
6061
|
+
return {
|
|
6062
|
+
...row,
|
|
6063
|
+
config: void 0,
|
|
6064
|
+
cli: void 0,
|
|
6065
|
+
copy: void 0,
|
|
6066
|
+
hookFiles: [],
|
|
6067
|
+
listCommand: { bin: n3.bin, args: n3.args },
|
|
6068
|
+
hookInstall: { kind: "package", via: n3.hooksVia },
|
|
6069
|
+
skillInstall: { kind: "package", via: n3.skillsVia }
|
|
6070
|
+
};
|
|
6071
|
+
}
|
|
6072
|
+
function trimChars(w, chars) {
|
|
6073
|
+
let a2 = 0;
|
|
6074
|
+
let b3 = w.length;
|
|
6075
|
+
while (a2 < b3 && chars.includes(w.charAt(a2))) a2++;
|
|
6076
|
+
while (b3 > a2 && chars.includes(w.charAt(b3 - 1))) b3--;
|
|
6077
|
+
return w.slice(a2, b3);
|
|
6078
|
+
}
|
|
6079
|
+
async function nativeResult(row, ctx) {
|
|
6080
|
+
const n3 = row.nativePlugin;
|
|
6081
|
+
const state = nativeState(row, ctx.env);
|
|
6082
|
+
if (!n3 || state === void 0) return void 0;
|
|
6083
|
+
const bin = hostBin(n3.bin, ctx.env).file;
|
|
6084
|
+
if (state === "disabled") {
|
|
6085
|
+
if (!n3.enable) return void 0;
|
|
6086
|
+
return {
|
|
6087
|
+
id: row.id,
|
|
6088
|
+
status: "FAIL",
|
|
6089
|
+
v1: [],
|
|
6090
|
+
changes: [],
|
|
6091
|
+
checks: [],
|
|
6092
|
+
bin,
|
|
6093
|
+
reason: `context-mode is installed but disabled in ${n3.bin}, run ${n3.bin} ${n3.enable.join(" ")}`
|
|
6094
|
+
};
|
|
6095
|
+
}
|
|
6096
|
+
const res = { id: row.id, status: "PASS", v1: [], changes: [], checks: await verifyRow(nativeRow(row, n3), ctx), bin };
|
|
6097
|
+
const bad = res.checks.filter((c3) => !c3.ok);
|
|
6098
|
+
if (bad.length) {
|
|
6099
|
+
res.status = "FAIL";
|
|
6100
|
+
res.reason = bad.map((c3) => `${c3.name}: ${c3.detail}`).join("; ");
|
|
6101
|
+
}
|
|
6102
|
+
return res;
|
|
6103
|
+
}
|
|
5938
6104
|
async function verifyRow(row, ctx) {
|
|
5939
6105
|
const env = ctx.env;
|
|
5940
6106
|
const checks = [parseCheck(row)];
|
|
@@ -6042,7 +6208,7 @@ async function runSetup(opts) {
|
|
|
6042
6208
|
}
|
|
6043
6209
|
current = id;
|
|
6044
6210
|
opts.onAgent?.(id, "start");
|
|
6045
|
-
const res = await setupRow(row, ctx, run, !!opts.dryRun);
|
|
6211
|
+
const res = await nativeResult(row, ctx) ?? await setupRow(row, ctx, run, !!opts.dryRun);
|
|
6046
6212
|
current = void 0;
|
|
6047
6213
|
agents.push(res);
|
|
6048
6214
|
opts.onAgent?.(id, "done", res);
|
|
@@ -6117,6 +6283,12 @@ async function runDoctor(opts) {
|
|
|
6117
6283
|
continue;
|
|
6118
6284
|
}
|
|
6119
6285
|
opts.onAgent?.(id, "start");
|
|
6286
|
+
const native = await nativeResult(row, ctx);
|
|
6287
|
+
if (native) {
|
|
6288
|
+
agents.push(native);
|
|
6289
|
+
opts.onAgent?.(id, "done", native);
|
|
6290
|
+
continue;
|
|
6291
|
+
}
|
|
6120
6292
|
const res = await setupRow(row, ctx, run, true);
|
|
6121
6293
|
if (res.status === "PASS") {
|
|
6122
6294
|
if (res.v1.some((f2) => !UPGRADE_REPORT_ONLY_REASONS.includes(f2.reason))) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ctx-doctor
|
|
3
|
+
description: Check that context-mode is installed and working, as a table.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
Call the mcp__context_mode__ctx_doctor tool and show its table to the user unchanged. If a row failed, list the fixes it names, in order.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ctx-stats
|
|
3
|
+
description: Show how much context context-mode saved, as a table.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
Call the mcp__context_mode__ctx_stats tool and show its table to the user unchanged. Add one sentence under the table that names the largest saving.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ctx-upgrade
|
|
3
|
+
description: Update context-mode to the latest release.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
Call the mcp__context_mode__ctx_upgrade tool and show its table to the user. Then call mcp__context_mode__ctx_doctor and show its table. If a restart is needed, say so in one sentence.
|
package/copilot/plugin.json
CHANGED
package/gemini-extension.json
CHANGED