context-mode 1.0.121 → 1.0.122
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 +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.openclaw-plugin/openclaw.plugin.json +1 -1
- package/.openclaw-plugin/package.json +1 -1
- package/README.md +4 -4
- package/build/adapters/claude-code/hooks.d.ts +16 -1
- package/build/adapters/claude-code/hooks.js +16 -0
- package/build/adapters/claude-code/index.js +2 -11
- package/build/adapters/codex/hooks.d.ts +19 -0
- package/build/adapters/codex/hooks.js +22 -0
- package/build/adapters/codex/index.js +8 -1
- package/build/adapters/copilot-base.d.ts +17 -1
- package/build/adapters/copilot-base.js +18 -2
- package/build/adapters/cursor/hooks.d.ts +14 -1
- package/build/adapters/cursor/hooks.js +14 -0
- package/build/adapters/detect.d.ts +12 -2
- package/build/adapters/detect.js +70 -3
- package/build/adapters/gemini-cli/hooks.d.ts +16 -0
- package/build/adapters/gemini-cli/hooks.js +19 -0
- package/build/adapters/gemini-cli/index.js +4 -2
- package/build/adapters/kiro/hooks.d.ts +16 -1
- package/build/adapters/kiro/hooks.js +19 -0
- package/build/adapters/pi/extension.d.ts +9 -0
- package/build/adapters/pi/extension.js +47 -0
- package/build/adapters/qwen-code/hooks.d.ts +26 -0
- package/build/adapters/qwen-code/hooks.js +29 -0
- package/build/adapters/qwen-code/index.js +6 -0
- package/build/cli.js +26 -1
- package/build/executor.js +18 -3
- package/build/lifecycle.d.ts +15 -0
- package/build/lifecycle.js +24 -1
- package/build/runtime.js +34 -13
- package/build/session/extract.js +150 -48
- package/build/session/snapshot.js +46 -0
- package/cli.bundle.mjs +137 -136
- package/configs/codex/hooks.json +1 -1
- package/configs/cursor/hooks.json +1 -1
- package/configs/kiro/agent.json +1 -1
- package/hooks/core/routing.mjs +56 -1
- package/hooks/cursor/hooks.json +1 -1
- package/hooks/ensure-deps.mjs +22 -3
- package/hooks/hooks.json +9 -0
- package/hooks/routing-block.mjs +5 -0
- package/hooks/session-extract.bundle.mjs +2 -2
- package/hooks/session-snapshot.bundle.mjs +21 -20
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -3
- package/scripts/heal-better-sqlite3.mjs +188 -10
- package/scripts/heal-installed-plugins.mjs +111 -0
- package/scripts/postinstall.mjs +18 -2
- package/server.bundle.mjs +111 -111
- package/start.mjs +14 -1
- package/.mcp.json +0 -8
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Claude Code plugins by Mert Koseoğlu",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.122"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "context-mode",
|
|
14
14
|
"source": "./",
|
|
15
15
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
16
|
-
"version": "1.0.
|
|
16
|
+
"version": "1.0.122",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "Mert Koseoğlu"
|
|
19
19
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mode",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.122",
|
|
4
4
|
"description": "MCP server that saves 98% of your context window with session continuity. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and automatic state restore across compactions.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mert Koseoğlu",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "Context Mode",
|
|
4
4
|
"kind": "tool",
|
|
5
5
|
"description": "OpenClaw plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.122",
|
|
7
7
|
"sandbox": {
|
|
8
8
|
"mode": "permissive",
|
|
9
9
|
"filesystem_access": "full",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mode",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.122",
|
|
4
4
|
"description": "OpenClaw plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mert Koseoğlu",
|
package/README.md
CHANGED
|
@@ -146,7 +146,7 @@ This gives you all 11 MCP tools without automatic routing. The model can still u
|
|
|
146
146
|
"hooks": {
|
|
147
147
|
"BeforeTool": [
|
|
148
148
|
{
|
|
149
|
-
"matcher": "run_shell_command|read_file|read_many_files|grep_search|search_file_content|web_fetch|activate_skill|mcp__plugin_context-mode",
|
|
149
|
+
"matcher": "run_shell_command|read_file|read_many_files|grep_search|search_file_content|web_fetch|activate_skill|mcp__plugin_context-mode|mcp__context-mode|mcp__(?!.*context-mode)",
|
|
150
150
|
"hooks": [{ "type": "command", "command": "context-mode hook gemini-cli beforetool" }]
|
|
151
151
|
}
|
|
152
152
|
],
|
|
@@ -570,7 +570,7 @@ Full documentation: [`docs/adapters/openclaw.md`](docs/adapters/openclaw.md)
|
|
|
570
570
|
```json
|
|
571
571
|
{
|
|
572
572
|
"hooks": {
|
|
573
|
-
"PreToolUse": [{ "matcher": "local_shell|shell|shell_command|exec_command|container.exec|functions\\.exec_command|Bash|Shell|apply_patch|functions\\.apply_patch|Edit|Write|grep_files|ctx_execute|ctx_execute_file|ctx_batch_execute|ctx_fetch_and_index|ctx_search|ctx_index|mcp__.*__ctx_execute|mcp__.*__ctx_execute_file|mcp__.*__ctx_batch_execute|mcp__.*__ctx_fetch_and_index|mcp__.*__ctx_search|mcp__.*__ctx_index", "hooks": [{ "type": "command", "command": "context-mode hook codex pretooluse" }] }],
|
|
573
|
+
"PreToolUse": [{ "matcher": "local_shell|shell|shell_command|exec_command|container.exec|functions\\.exec_command|Bash|Shell|apply_patch|functions\\.apply_patch|Edit|Write|grep_files|ctx_execute|ctx_execute_file|ctx_batch_execute|ctx_fetch_and_index|ctx_search|ctx_index|mcp__.*__ctx_execute|mcp__.*__ctx_execute_file|mcp__.*__ctx_batch_execute|mcp__.*__ctx_fetch_and_index|mcp__.*__ctx_search|mcp__.*__ctx_index|mcp__(?!.*context-mode)", "hooks": [{ "type": "command", "command": "context-mode hook codex pretooluse" }] }],
|
|
574
574
|
"PostToolUse": [{ "hooks": [{ "type": "command", "command": "context-mode hook codex posttooluse" }] }],
|
|
575
575
|
"SessionStart": [{ "hooks": [{ "type": "command", "command": "context-mode hook codex sessionstart" }] }],
|
|
576
576
|
"PreCompact": [{ "hooks": [{ "type": "command", "command": "context-mode hook codex precompact" }] }],
|
|
@@ -632,7 +632,7 @@ Full documentation: [`docs/adapters/openclaw.md`](docs/adapters/openclaw.md)
|
|
|
632
632
|
```json
|
|
633
633
|
{
|
|
634
634
|
"hooks": {
|
|
635
|
-
"PreToolUse": [{ "matcher": "run_shell_command|read_file|read_many_files|grep_search|web_fetch|agent|mcp__plugin_context-mode_context-mode__ctx_execute|mcp__plugin_context-mode_context-mode__ctx_execute_file|mcp__plugin_context-mode_context-mode__ctx_batch_execute", "hooks": [{ "type": "command", "command": "context-mode hook qwen-code pretooluse" }] }],
|
|
635
|
+
"PreToolUse": [{ "matcher": "run_shell_command|read_file|read_many_files|grep_search|web_fetch|agent|mcp__plugin_context-mode_context-mode__ctx_execute|mcp__plugin_context-mode_context-mode__ctx_execute_file|mcp__plugin_context-mode_context-mode__ctx_batch_execute|mcp__(?!.*context-mode)", "hooks": [{ "type": "command", "command": "context-mode hook qwen-code pretooluse" }] }],
|
|
636
636
|
"PostToolUse": [{ "matcher": "", "hooks": [{ "type": "command", "command": "context-mode hook qwen-code posttooluse" }] }],
|
|
637
637
|
"SessionStart": [{ "matcher": "", "hooks": [{ "type": "command", "command": "context-mode hook qwen-code sessionstart" }] }],
|
|
638
638
|
"PreCompact": [{ "matcher": "", "hooks": [{ "type": "command", "command": "context-mode hook qwen-code precompact" }] }],
|
|
@@ -731,7 +731,7 @@ Full configs: [`configs/antigravity/mcp_config.json`](configs/antigravity/mcp_co
|
|
|
731
731
|
"description": "Context-mode hooks for context window protection",
|
|
732
732
|
"hooks": {
|
|
733
733
|
"preToolUse": [
|
|
734
|
-
{ "matcher": "execute_bash|fs_read|@context-mode/ctx_execute|@context-mode/ctx_execute_file|@context-mode/ctx_batch_execute", "command": "context-mode hook kiro pretooluse" }
|
|
734
|
+
{ "matcher": "execute_bash|fs_read|@context-mode/ctx_execute|@context-mode/ctx_execute_file|@context-mode/ctx_batch_execute|@(?!context-mode/)", "command": "context-mode hook kiro pretooluse" }
|
|
735
735
|
],
|
|
736
736
|
"postToolUse": [
|
|
737
737
|
{ "matcher": "*", "command": "context-mode hook kiro posttooluse" }
|
|
@@ -24,8 +24,23 @@ export declare const HOOK_TYPES: {
|
|
|
24
24
|
readonly USER_PROMPT_SUBMIT: "UserPromptSubmit";
|
|
25
25
|
};
|
|
26
26
|
export type HookType = (typeof HOOK_TYPES)[keyof typeof HOOK_TYPES];
|
|
27
|
+
/**
|
|
28
|
+
* Negative-lookahead matcher for external MCP tool namespaces (#529).
|
|
29
|
+
*
|
|
30
|
+
* Claude Code's hook matcher engine evaluates each entry as a regex against
|
|
31
|
+
* the tool name. This pattern fires on any `mcp__<server>__<tool>` whose
|
|
32
|
+
* server segment is NOT context-mode's own (`plugin_context-mode_...`).
|
|
33
|
+
* Without it, large payloads from external MCPs (slack channel history,
|
|
34
|
+
* telegram messages, gdrive content, notion pages, …) bypass PreToolUse
|
|
35
|
+
* routing and flood the model's context window — PostToolUse runs too late
|
|
36
|
+
* to keep the raw data out.
|
|
37
|
+
*
|
|
38
|
+
* The negative lookahead prevents this entry from double-firing on
|
|
39
|
+
* context-mode's own ctx_* tools, which already have dedicated entries above.
|
|
40
|
+
*/
|
|
41
|
+
export declare const EXTERNAL_MCP_MATCHER_PATTERN = "mcp__(?!plugin_context-mode_)";
|
|
27
42
|
/** Tools that context-mode's PreToolUse hook intercepts. */
|
|
28
|
-
export declare const PRE_TOOL_USE_MATCHERS: readonly ["Bash", "WebFetch", "Read", "Grep", "Agent", "mcp__plugin_context-mode_context-mode__ctx_execute", "mcp__plugin_context-mode_context-mode__ctx_execute_file", "mcp__plugin_context-mode_context-mode__ctx_batch_execute"];
|
|
43
|
+
export declare const PRE_TOOL_USE_MATCHERS: readonly ["Bash", "WebFetch", "Read", "Grep", "Agent", "mcp__plugin_context-mode_context-mode__ctx_execute", "mcp__plugin_context-mode_context-mode__ctx_execute_file", "mcp__plugin_context-mode_context-mode__ctx_batch_execute", "mcp__(?!plugin_context-mode_)"];
|
|
29
44
|
/**
|
|
30
45
|
* Combined matcher pattern for settings.json (pipe-separated).
|
|
31
46
|
* Used by the upgrade command when writing a single consolidated entry.
|
|
@@ -30,6 +30,21 @@ export const HOOK_TYPES = {
|
|
|
30
30
|
// ─────────────────────────────────────────────────────────
|
|
31
31
|
// PreToolUse matchers
|
|
32
32
|
// ─────────────────────────────────────────────────────────
|
|
33
|
+
/**
|
|
34
|
+
* Negative-lookahead matcher for external MCP tool namespaces (#529).
|
|
35
|
+
*
|
|
36
|
+
* Claude Code's hook matcher engine evaluates each entry as a regex against
|
|
37
|
+
* the tool name. This pattern fires on any `mcp__<server>__<tool>` whose
|
|
38
|
+
* server segment is NOT context-mode's own (`plugin_context-mode_...`).
|
|
39
|
+
* Without it, large payloads from external MCPs (slack channel history,
|
|
40
|
+
* telegram messages, gdrive content, notion pages, …) bypass PreToolUse
|
|
41
|
+
* routing and flood the model's context window — PostToolUse runs too late
|
|
42
|
+
* to keep the raw data out.
|
|
43
|
+
*
|
|
44
|
+
* The negative lookahead prevents this entry from double-firing on
|
|
45
|
+
* context-mode's own ctx_* tools, which already have dedicated entries above.
|
|
46
|
+
*/
|
|
47
|
+
export const EXTERNAL_MCP_MATCHER_PATTERN = "mcp__(?!plugin_context-mode_)";
|
|
33
48
|
/** Tools that context-mode's PreToolUse hook intercepts. */
|
|
34
49
|
export const PRE_TOOL_USE_MATCHERS = [
|
|
35
50
|
"Bash",
|
|
@@ -40,6 +55,7 @@ export const PRE_TOOL_USE_MATCHERS = [
|
|
|
40
55
|
"mcp__plugin_context-mode_context-mode__ctx_execute",
|
|
41
56
|
"mcp__plugin_context-mode_context-mode__ctx_execute_file",
|
|
42
57
|
"mcp__plugin_context-mode_context-mode__ctx_batch_execute",
|
|
58
|
+
EXTERNAL_MCP_MATCHER_PATTERN,
|
|
43
59
|
];
|
|
44
60
|
/**
|
|
45
61
|
* Combined matcher pattern for settings.json (pipe-separated).
|
|
@@ -16,7 +16,7 @@ import { resolve, join } from "node:path";
|
|
|
16
16
|
import { homedir } from "node:os";
|
|
17
17
|
import { ClaudeCodeBaseAdapter } from "../claude-code-base.js";
|
|
18
18
|
import { resolveClaudeConfigDir } from "../../util/claude-config.js";
|
|
19
|
-
import { HOOK_TYPES, HOOK_SCRIPTS, REQUIRED_HOOKS, PRE_TOOL_USE_MATCHER_PATTERN, isContextModeHook, isAnyContextModeHook, extractHookScriptPath, buildHookCommand, } from "./hooks.js";
|
|
19
|
+
import { HOOK_TYPES, HOOK_SCRIPTS, REQUIRED_HOOKS, PRE_TOOL_USE_MATCHERS, PRE_TOOL_USE_MATCHER_PATTERN, isContextModeHook, isAnyContextModeHook, extractHookScriptPath, buildHookCommand, } from "./hooks.js";
|
|
20
20
|
// ─────────────────────────────────────────────────────────
|
|
21
21
|
// Adapter implementation
|
|
22
22
|
// ─────────────────────────────────────────────────────────
|
|
@@ -68,16 +68,7 @@ export class ClaudeCodeAdapter extends ClaudeCodeBaseAdapter {
|
|
|
68
68
|
}
|
|
69
69
|
generateHookConfig(pluginRoot) {
|
|
70
70
|
const preToolUseCommand = `node ${pluginRoot}/hooks/pretooluse.mjs`;
|
|
71
|
-
const preToolUseMatchers = [
|
|
72
|
-
"Bash",
|
|
73
|
-
"WebFetch",
|
|
74
|
-
"Read",
|
|
75
|
-
"Grep",
|
|
76
|
-
"Task",
|
|
77
|
-
"mcp__plugin_context-mode_context-mode__ctx_execute",
|
|
78
|
-
"mcp__plugin_context-mode_context-mode__ctx_execute_file",
|
|
79
|
-
"mcp__plugin_context-mode_context-mode__ctx_batch_execute",
|
|
80
|
-
];
|
|
71
|
+
const preToolUseMatchers = [...PRE_TOOL_USE_MATCHERS];
|
|
81
72
|
return {
|
|
82
73
|
PreToolUse: preToolUseMatchers.map((matcher) => ({
|
|
83
74
|
matcher,
|
|
@@ -26,6 +26,25 @@ export declare const HOOK_TYPES: {
|
|
|
26
26
|
readonly USER_PROMPT_SUBMIT: "UserPromptSubmit";
|
|
27
27
|
readonly STOP: "Stop";
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Negative-lookahead matcher for external MCP tool namespaces on Codex CLI (#529).
|
|
31
|
+
*
|
|
32
|
+
* Codex CLI's hook `tool_name` payload uses `mcp__<server>__<tool>` for any
|
|
33
|
+
* MCP-namespaced tool — verified by configs/codex/hooks.json which already
|
|
34
|
+
* matches `mcp__.*__ctx_execute` style for context-mode's OWN MCP tools. This
|
|
35
|
+
* pattern fires PreToolUse for any external `mcp__<server>__<tool>` whose
|
|
36
|
+
* server segment does NOT contain `context-mode`. Without it, large payloads
|
|
37
|
+
* from slack / telegram / gdrive / notion-style MCPs bypass the routing nudge
|
|
38
|
+
* and flood the model's context — PostToolUse runs too late to keep raw data
|
|
39
|
+
* out.
|
|
40
|
+
*
|
|
41
|
+
* The negative lookahead `(?!.*context-mode)` covers both naming variants
|
|
42
|
+
* Codex sees in practice: the canonical `mcp__context-mode__ctx_*` AND the
|
|
43
|
+
* Claude Code plugin shim `mcp__plugin_context-mode_context-mode__ctx_*`.
|
|
44
|
+
* Codex own bare names (ctx_execute, local_shell, …) are not `mcp__`-prefixed
|
|
45
|
+
* and are unaffected.
|
|
46
|
+
*/
|
|
47
|
+
export declare const EXTERNAL_MCP_MATCHER_PATTERN = "mcp__(?!.*context-mode)";
|
|
29
48
|
/**
|
|
30
49
|
* Path to the routing instructions file for Codex CLI.
|
|
31
50
|
* Used as fallback routing awareness alongside hook-based enforcement.
|
|
@@ -30,6 +30,28 @@ export const HOOK_TYPES = {
|
|
|
30
30
|
STOP: "Stop",
|
|
31
31
|
};
|
|
32
32
|
// ─────────────────────────────────────────────────────────
|
|
33
|
+
// External MCP routing matcher (#529)
|
|
34
|
+
// ─────────────────────────────────────────────────────────
|
|
35
|
+
/**
|
|
36
|
+
* Negative-lookahead matcher for external MCP tool namespaces on Codex CLI (#529).
|
|
37
|
+
*
|
|
38
|
+
* Codex CLI's hook `tool_name` payload uses `mcp__<server>__<tool>` for any
|
|
39
|
+
* MCP-namespaced tool — verified by configs/codex/hooks.json which already
|
|
40
|
+
* matches `mcp__.*__ctx_execute` style for context-mode's OWN MCP tools. This
|
|
41
|
+
* pattern fires PreToolUse for any external `mcp__<server>__<tool>` whose
|
|
42
|
+
* server segment does NOT contain `context-mode`. Without it, large payloads
|
|
43
|
+
* from slack / telegram / gdrive / notion-style MCPs bypass the routing nudge
|
|
44
|
+
* and flood the model's context — PostToolUse runs too late to keep raw data
|
|
45
|
+
* out.
|
|
46
|
+
*
|
|
47
|
+
* The negative lookahead `(?!.*context-mode)` covers both naming variants
|
|
48
|
+
* Codex sees in practice: the canonical `mcp__context-mode__ctx_*` AND the
|
|
49
|
+
* Claude Code plugin shim `mcp__plugin_context-mode_context-mode__ctx_*`.
|
|
50
|
+
* Codex own bare names (ctx_execute, local_shell, …) are not `mcp__`-prefixed
|
|
51
|
+
* and are unaffected.
|
|
52
|
+
*/
|
|
53
|
+
export const EXTERNAL_MCP_MATCHER_PATTERN = "mcp__(?!.*context-mode)";
|
|
54
|
+
// ─────────────────────────────────────────────────────────
|
|
33
55
|
// Routing instructions
|
|
34
56
|
// ─────────────────────────────────────────────────────────
|
|
35
57
|
/**
|
|
@@ -18,7 +18,14 @@ import { resolve, dirname, join } from "node:path";
|
|
|
18
18
|
import { fileURLToPath } from "node:url";
|
|
19
19
|
import { BaseAdapter } from "../base.js";
|
|
20
20
|
import { resolveCodexConfigDir } from "./paths.js";
|
|
21
|
-
|
|
21
|
+
// PreToolUse matcher: canonical Codex tool names + context-mode own MCP tools
|
|
22
|
+
// (both bare and `mcp__<server>__<tool>` forms) + external MCP catch-all (#529).
|
|
23
|
+
// The final `mcp__(?!.*context-mode)` segment uses a negative lookahead that
|
|
24
|
+
// excludes any `mcp__` tool whose server segment contains `context-mode` so
|
|
25
|
+
// context-mode's own MCP tools (already wired by the explicit entries above)
|
|
26
|
+
// are not double-routed. Keep this as a single string literal — `codex.test.ts`
|
|
27
|
+
// drift-guard parses the source with a `"([^"]+)"` regex.
|
|
28
|
+
const PRE_TOOL_USE_MATCHER_PATTERN = "local_shell|shell|shell_command|exec_command|container.exec|functions\\.exec_command|Bash|Shell|apply_patch|functions\\.apply_patch|Edit|Write|grep_files|ctx_execute|ctx_execute_file|ctx_batch_execute|ctx_fetch_and_index|ctx_search|ctx_index|mcp__.*__ctx_execute|mcp__.*__ctx_execute_file|mcp__.*__ctx_batch_execute|mcp__.*__ctx_fetch_and_index|mcp__.*__ctx_search|mcp__.*__ctx_index|mcp__(?!.*context-mode)";
|
|
22
29
|
const CODEX_HOOK_COMMANDS = {
|
|
23
30
|
PreToolUse: "context-mode hook codex pretooluse",
|
|
24
31
|
PostToolUse: "context-mode hook codex posttooluse",
|
|
@@ -68,7 +68,23 @@ export declare abstract class CopilotBaseAdapter extends BaseAdapter implements
|
|
|
68
68
|
formatPostToolUseResponse(response: PostToolUseResponse): unknown;
|
|
69
69
|
formatPreCompactResponse(response: PreCompactResponse): unknown;
|
|
70
70
|
formatSessionStartResponse(response: SessionStartResponse): unknown;
|
|
71
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Resolve the absolute path to the Copilot-style hook settings file.
|
|
73
|
+
*
|
|
74
|
+
* Issue #539 fix: previously this returned `resolve(".github", ...)`
|
|
75
|
+
* — a CWD-relative path. `doctor` (validateHooks) and `upgrade`
|
|
76
|
+
* (configureAllHooks) could legitimately run from different working
|
|
77
|
+
* directories (CLI invoked from a subdir, MCP server cwd=projectDir),
|
|
78
|
+
* so each saw a DIFFERENT settings path and the diagnose/repair loop
|
|
79
|
+
* never converged on the same file.
|
|
80
|
+
*
|
|
81
|
+
* Now anchors on `projectDir` when supplied (matching the sibling
|
|
82
|
+
* `getConfigDir(projectDir?: string)` signature in
|
|
83
|
+
* vscode-copilot/index.ts:93). Falls back to `process.cwd()` to keep
|
|
84
|
+
* existing callers source-compatible — the slice-5 follow-up will
|
|
85
|
+
* thread projectDir through `cli.ts doctor`/`upgrade`.
|
|
86
|
+
*/
|
|
87
|
+
getSettingsPath(projectDir?: string): string;
|
|
72
88
|
generateHookConfig(pluginRoot: string): HookRegistration;
|
|
73
89
|
readSettings(): Record<string, unknown> | null;
|
|
74
90
|
writeSettings(settings: Record<string, unknown>): void;
|
|
@@ -149,8 +149,24 @@ export class CopilotBaseAdapter extends BaseAdapter {
|
|
|
149
149
|
return response.context ?? "";
|
|
150
150
|
}
|
|
151
151
|
// ── Configuration (shared) ─────────────────────────────
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Resolve the absolute path to the Copilot-style hook settings file.
|
|
154
|
+
*
|
|
155
|
+
* Issue #539 fix: previously this returned `resolve(".github", ...)`
|
|
156
|
+
* — a CWD-relative path. `doctor` (validateHooks) and `upgrade`
|
|
157
|
+
* (configureAllHooks) could legitimately run from different working
|
|
158
|
+
* directories (CLI invoked from a subdir, MCP server cwd=projectDir),
|
|
159
|
+
* so each saw a DIFFERENT settings path and the diagnose/repair loop
|
|
160
|
+
* never converged on the same file.
|
|
161
|
+
*
|
|
162
|
+
* Now anchors on `projectDir` when supplied (matching the sibling
|
|
163
|
+
* `getConfigDir(projectDir?: string)` signature in
|
|
164
|
+
* vscode-copilot/index.ts:93). Falls back to `process.cwd()` to keep
|
|
165
|
+
* existing callers source-compatible — the slice-5 follow-up will
|
|
166
|
+
* thread projectDir through `cli.ts doctor`/`upgrade`.
|
|
167
|
+
*/
|
|
168
|
+
getSettingsPath(projectDir) {
|
|
169
|
+
return resolve(projectDir ?? process.cwd(), ".github", "hooks", "context-mode.json");
|
|
154
170
|
}
|
|
155
171
|
generateHookConfig(pluginRoot) {
|
|
156
172
|
const { HOOK_TYPES, buildHookCommand } = this.hookModule;
|
|
@@ -16,8 +16,21 @@ export declare const HOOK_TYPES: {
|
|
|
16
16
|
export type HookType = (typeof HOOK_TYPES)[keyof typeof HOOK_TYPES];
|
|
17
17
|
/** Map of hook types that have actual script files. */
|
|
18
18
|
export declare const HOOK_SCRIPTS: Partial<Record<HookType, string>>;
|
|
19
|
+
/**
|
|
20
|
+
* Negative-lookahead matcher for external MCP tool namespaces on Cursor (#529).
|
|
21
|
+
*
|
|
22
|
+
* Cursor MCP wire shape: `MCP:<tool>` (verified in
|
|
23
|
+
* tests/fixtures/cursor/pretooluse-mcp.json, hooks/cursor/posttooluse.mjs:19-25).
|
|
24
|
+
* Context-mode's own tools surface as `MCP:ctx_<...>`. The negative lookahead
|
|
25
|
+
* on the `ctx_` prefix fires for every other MCP tool whose payload would
|
|
26
|
+
* otherwise flood the model's context window before PostToolUse can act.
|
|
27
|
+
*
|
|
28
|
+
* Routing.mjs `isExternalMcpTool` is extended to recognise the `MCP:` prefix
|
|
29
|
+
* so the routing branch returns external-MCP guidance instead of passthrough.
|
|
30
|
+
*/
|
|
31
|
+
export declare const EXTERNAL_MCP_MATCHER_PATTERN = "MCP:(?!ctx_)";
|
|
19
32
|
/** Canonical Cursor-native matchers for tools context-mode routes proactively. */
|
|
20
|
-
export declare const PRE_TOOL_USE_MATCHERS: readonly ["Shell", "Read", "Grep", "WebFetch", "mcp_web_fetch", "mcp_fetch_tool", "Task", "MCP:ctx_execute", "MCP:ctx_execute_file", "MCP:ctx_batch_execute"];
|
|
33
|
+
export declare const PRE_TOOL_USE_MATCHERS: readonly ["Shell", "Read", "Grep", "WebFetch", "mcp_web_fetch", "mcp_fetch_tool", "Task", "MCP:ctx_execute", "MCP:ctx_execute_file", "MCP:ctx_batch_execute", "MCP:(?!ctx_)"];
|
|
21
34
|
export declare const PRE_TOOL_USE_MATCHER_PATTERN: string;
|
|
22
35
|
/** Required hooks for native Cursor support. */
|
|
23
36
|
export declare const REQUIRED_HOOKS: HookType[];
|
|
@@ -21,6 +21,19 @@ export const HOOK_SCRIPTS = {
|
|
|
21
21
|
[HOOK_TYPES.STOP]: "stop.mjs",
|
|
22
22
|
[HOOK_TYPES.AFTER_AGENT_RESPONSE]: "afteragentresponse.mjs",
|
|
23
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Negative-lookahead matcher for external MCP tool namespaces on Cursor (#529).
|
|
26
|
+
*
|
|
27
|
+
* Cursor MCP wire shape: `MCP:<tool>` (verified in
|
|
28
|
+
* tests/fixtures/cursor/pretooluse-mcp.json, hooks/cursor/posttooluse.mjs:19-25).
|
|
29
|
+
* Context-mode's own tools surface as `MCP:ctx_<...>`. The negative lookahead
|
|
30
|
+
* on the `ctx_` prefix fires for every other MCP tool whose payload would
|
|
31
|
+
* otherwise flood the model's context window before PostToolUse can act.
|
|
32
|
+
*
|
|
33
|
+
* Routing.mjs `isExternalMcpTool` is extended to recognise the `MCP:` prefix
|
|
34
|
+
* so the routing branch returns external-MCP guidance instead of passthrough.
|
|
35
|
+
*/
|
|
36
|
+
export const EXTERNAL_MCP_MATCHER_PATTERN = "MCP:(?!ctx_)";
|
|
24
37
|
/** Canonical Cursor-native matchers for tools context-mode routes proactively. */
|
|
25
38
|
// NOTE (Cursor-3, deferred): Cursor is closed-source and does not currently
|
|
26
39
|
// publish the exact tool name it uses for sub-agent dispatch (the analogue of
|
|
@@ -40,6 +53,7 @@ export const PRE_TOOL_USE_MATCHERS = [
|
|
|
40
53
|
"MCP:ctx_execute",
|
|
41
54
|
"MCP:ctx_execute_file",
|
|
42
55
|
"MCP:ctx_batch_execute",
|
|
56
|
+
EXTERNAL_MCP_MATCHER_PATTERN,
|
|
43
57
|
];
|
|
44
58
|
export const PRE_TOOL_USE_MATCHER_PATTERN = PRE_TOOL_USE_MATCHERS.join("|");
|
|
45
59
|
/** Required hooks for native Cursor support. */
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* 3. Fallback to Claude Code (low confidence — most common)
|
|
8
8
|
*
|
|
9
9
|
* Verified env vars per platform (from source code audit):
|
|
10
|
-
* - Claude Code:
|
|
10
|
+
* - Claude Code: CLAUDE_CODE_ENTRYPOINT, CLAUDE_PLUGIN_ROOT,
|
|
11
|
+
* CLAUDE_PROJECT_DIR, CLAUDE_SESSION_ID | ~/.claude/
|
|
11
12
|
* - Gemini CLI: GEMINI_PROJECT_DIR (hooks), GEMINI_CLI (MCP) | ~/.gemini/
|
|
12
13
|
* - KiloCode: KILO, KILO_PID | ~/.config/kilo/
|
|
13
14
|
* - OpenCode: OPENCODE, OPENCODE_PID | ~/.config/opencode/
|
|
@@ -18,12 +19,21 @@
|
|
|
18
19
|
* - JetBrains Copilot: IDEA_INITIAL_DIRECTORY, IDEA_HOME, JETBRAINS_CLIENT_ID | ~/.config/JetBrains/
|
|
19
20
|
*/
|
|
20
21
|
import type { PlatformId, DetectionSignal, HookAdapter } from "./types.js";
|
|
22
|
+
/** Test-only: reset the installed_plugins.json memo so each test starts cold. */
|
|
23
|
+
export declare function __resetClaudeCodePluginCacheForTests(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Test-only: pretend installed_plugins.json does not exist (or has no
|
|
26
|
+
* context-mode entry). Lets tests that exercise the genuine vscode-copilot
|
|
27
|
+
* env-var path run on a developer machine that actually has context-mode
|
|
28
|
+
* installed as a Claude Code plugin.
|
|
29
|
+
*/
|
|
30
|
+
export declare function __seedClaudeCodePluginCacheMissForTests(): void;
|
|
21
31
|
/**
|
|
22
32
|
* High-confidence env vars per platform, checked in priority order.
|
|
23
33
|
* Single source of truth — consumed by detectPlatform() below and by
|
|
24
34
|
* tests that need to clear platform-related env vars deterministically.
|
|
25
35
|
*/
|
|
26
|
-
export declare const PLATFORM_ENV_VARS: readonly [readonly ["claude-code", readonly ["CLAUDE_PROJECT_DIR", "CLAUDE_SESSION_ID"]], readonly ["antigravity", readonly ["ANTIGRAVITY_CLI_ALIAS"]], readonly ["cursor", readonly ["CURSOR_TRACE_ID", "CURSOR_CLI"]], readonly ["kilo", readonly ["KILO", "KILO_PID"]], readonly ["opencode", readonly ["OPENCODE", "OPENCODE_PID"]], readonly ["zed", readonly ["ZED_SESSION_ID", "ZED_TERM"]], readonly ["codex", readonly ["CODEX_THREAD_ID", "CODEX_CI"]], readonly ["gemini-cli", readonly ["GEMINI_PROJECT_DIR", "GEMINI_CLI"]], readonly ["vscode-copilot", readonly ["VSCODE_PID", "VSCODE_CWD"]], readonly ["jetbrains-copilot", readonly ["IDEA_INITIAL_DIRECTORY"]], readonly ["qwen-code", readonly ["QWEN_PROJECT_DIR"]], readonly ["omp", readonly ["PI_CODING_AGENT_DIR"]], readonly ["pi", readonly ["PI_PROJECT_DIR"]]];
|
|
36
|
+
export declare const PLATFORM_ENV_VARS: readonly [readonly ["claude-code", readonly ["CLAUDE_CODE_ENTRYPOINT", "CLAUDE_PLUGIN_ROOT", "CLAUDE_PROJECT_DIR", "CLAUDE_SESSION_ID"]], readonly ["antigravity", readonly ["ANTIGRAVITY_CLI_ALIAS"]], readonly ["cursor", readonly ["CURSOR_TRACE_ID", "CURSOR_CLI"]], readonly ["kilo", readonly ["KILO", "KILO_PID"]], readonly ["opencode", readonly ["OPENCODE", "OPENCODE_PID"]], readonly ["zed", readonly ["ZED_SESSION_ID", "ZED_TERM"]], readonly ["codex", readonly ["CODEX_THREAD_ID", "CODEX_CI"]], readonly ["gemini-cli", readonly ["GEMINI_PROJECT_DIR", "GEMINI_CLI"]], readonly ["vscode-copilot", readonly ["VSCODE_PID", "VSCODE_CWD"]], readonly ["jetbrains-copilot", readonly ["IDEA_INITIAL_DIRECTORY"]], readonly ["qwen-code", readonly ["QWEN_PROJECT_DIR"]], readonly ["omp", readonly ["PI_CODING_AGENT_DIR"]], readonly ["pi", readonly ["PI_PROJECT_DIR"]]];
|
|
27
37
|
/**
|
|
28
38
|
* Sync map from platform identifier → home-relative path segments where that
|
|
29
39
|
* platform stores its config. Mirrors the `super([...])` argument passed by
|
package/build/adapters/detect.js
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* 3. Fallback to Claude Code (low confidence — most common)
|
|
8
8
|
*
|
|
9
9
|
* Verified env vars per platform (from source code audit):
|
|
10
|
-
* - Claude Code:
|
|
10
|
+
* - Claude Code: CLAUDE_CODE_ENTRYPOINT, CLAUDE_PLUGIN_ROOT,
|
|
11
|
+
* CLAUDE_PROJECT_DIR, CLAUDE_SESSION_ID | ~/.claude/
|
|
11
12
|
* - Gemini CLI: GEMINI_PROJECT_DIR (hooks), GEMINI_CLI (MCP) | ~/.gemini/
|
|
12
13
|
* - KiloCode: KILO, KILO_PID | ~/.config/kilo/
|
|
13
14
|
* - OpenCode: OPENCODE, OPENCODE_PID | ~/.config/opencode/
|
|
@@ -17,10 +18,45 @@
|
|
|
17
18
|
* - VS Code Copilot: VSCODE_PID, VSCODE_CWD | ~/.vscode/
|
|
18
19
|
* - JetBrains Copilot: IDEA_INITIAL_DIRECTORY, IDEA_HOME, JETBRAINS_CLIENT_ID | ~/.config/JetBrains/
|
|
19
20
|
*/
|
|
20
|
-
import { existsSync } from "node:fs";
|
|
21
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
21
22
|
import { resolve } from "node:path";
|
|
22
23
|
import { homedir } from "node:os";
|
|
23
24
|
import { CLIENT_NAME_TO_PLATFORM } from "./client-map.js";
|
|
25
|
+
let claudeCodePluginCache = null;
|
|
26
|
+
function claudeCodeHasContextModePlugin() {
|
|
27
|
+
if (claudeCodePluginCache !== null) {
|
|
28
|
+
return claudeCodePluginCache !== "miss" && claudeCodePluginCache.hasCM;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const path = resolve(homedir(), ".claude", "plugins", "installed_plugins.json");
|
|
32
|
+
const raw = readFileSync(path, "utf-8");
|
|
33
|
+
const parsed = JSON.parse(raw);
|
|
34
|
+
const keys = [
|
|
35
|
+
...Object.keys(parsed.plugins ?? {}),
|
|
36
|
+
...Object.keys(parsed.enabledPlugins ?? {}),
|
|
37
|
+
];
|
|
38
|
+
const hasCM = keys.some((k) => k.includes("context-mode"));
|
|
39
|
+
claudeCodePluginCache = { hasCM };
|
|
40
|
+
return hasCM;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
claudeCodePluginCache = "miss";
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Test-only: reset the installed_plugins.json memo so each test starts cold. */
|
|
48
|
+
export function __resetClaudeCodePluginCacheForTests() {
|
|
49
|
+
claudeCodePluginCache = null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Test-only: pretend installed_plugins.json does not exist (or has no
|
|
53
|
+
* context-mode entry). Lets tests that exercise the genuine vscode-copilot
|
|
54
|
+
* env-var path run on a developer machine that actually has context-mode
|
|
55
|
+
* installed as a Claude Code plugin.
|
|
56
|
+
*/
|
|
57
|
+
export function __seedClaudeCodePluginCacheMissForTests() {
|
|
58
|
+
claudeCodePluginCache = "miss";
|
|
59
|
+
}
|
|
24
60
|
/**
|
|
25
61
|
* High-confidence env vars per platform, checked in priority order.
|
|
26
62
|
* Single source of truth — consumed by detectPlatform() below and by
|
|
@@ -30,7 +66,22 @@ export const PLATFORM_ENV_VARS = [
|
|
|
30
66
|
// Order matters: forks listed BEFORE the fork's parent so collision
|
|
31
67
|
// detection works. Every entry verified against platform's own runtime
|
|
32
68
|
// source code (PR #376 follow-up: full audit, May 2026 — see git blame).
|
|
33
|
-
|
|
69
|
+
// Claude Code — verified against a live `env` dump (2026-05-11):
|
|
70
|
+
// CLAUDE_CODE_ENTRYPOINT=cli (set on every CC session)
|
|
71
|
+
// CLAUDE_PLUGIN_ROOT=/Users/.../<version> (set when a plugin is loaded)
|
|
72
|
+
// CLAUDE_PROJECT_DIR=/Users/.../project (set in hooks context)
|
|
73
|
+
// CLAUDE_SESSION_ID=<uuid> (legacy session marker)
|
|
74
|
+
// CLAUDE_CODE_ENTRYPOINT and CLAUDE_PLUGIN_ROOT are CC-exclusive — they
|
|
75
|
+
// are the disambiguators for issue #539 (Claude Code running inside a
|
|
76
|
+
// VS Code integrated terminal that has VSCODE_PID set). They MUST be
|
|
77
|
+
// checked here so detect resolves to claude-code BEFORE falling through
|
|
78
|
+
// to vscode-copilot at line 70 below.
|
|
79
|
+
["claude-code", [
|
|
80
|
+
"CLAUDE_CODE_ENTRYPOINT",
|
|
81
|
+
"CLAUDE_PLUGIN_ROOT",
|
|
82
|
+
"CLAUDE_PROJECT_DIR",
|
|
83
|
+
"CLAUDE_SESSION_ID",
|
|
84
|
+
]],
|
|
34
85
|
// antigravity (Electron/VSCode fork) — google-gemini/gemini-cli
|
|
35
86
|
// packages/core/src/ide/detect-ide.ts checks ANTIGRAVITY_CLI_ALIAS as the
|
|
36
87
|
// canonical Antigravity marker. Listed before vscode-copilot.
|
|
@@ -148,6 +199,22 @@ export function detectPlatform(clientInfo) {
|
|
|
148
199
|
// ── High confidence: environment variables ─────────────
|
|
149
200
|
for (const [platform, vars] of PLATFORM_ENV_VARS) {
|
|
150
201
|
if (vars.some((v) => process.env[v])) {
|
|
202
|
+
// Issue #539 belt-and-suspenders: VSCODE_PID/VSCODE_CWD are exported
|
|
203
|
+
// by VS Code into EVERY child process — including a Claude Code CLI
|
|
204
|
+
// launched from the integrated terminal. If env vars alone want to
|
|
205
|
+
// resolve to vscode-copilot, but ~/.claude/plugins/installed_plugins.json
|
|
206
|
+
// lists context-mode as a Claude Code plugin, the runtime must be
|
|
207
|
+
// Claude Code (VS Code Copilot has no plugin concept). The env-var
|
|
208
|
+
// tier above already handles the common case via CLAUDE_CODE_ENTRYPOINT
|
|
209
|
+
// / CLAUDE_PLUGIN_ROOT; this branch covers MCP-server-only boots where
|
|
210
|
+
// those vars have not propagated yet.
|
|
211
|
+
if (platform === "vscode-copilot" && claudeCodeHasContextModePlugin()) {
|
|
212
|
+
return {
|
|
213
|
+
platform: "claude-code",
|
|
214
|
+
confidence: "high",
|
|
215
|
+
reason: "VSCODE_PID set but ~/.claude/plugins/installed_plugins.json lists context-mode (issue #539 fallback)",
|
|
216
|
+
};
|
|
217
|
+
}
|
|
151
218
|
return {
|
|
152
219
|
platform,
|
|
153
220
|
confidence: "high",
|
|
@@ -27,6 +27,22 @@ export declare const HOOK_TYPES: {
|
|
|
27
27
|
readonly SESSION_START: "SessionStart";
|
|
28
28
|
};
|
|
29
29
|
export type HookType = (typeof HOOK_TYPES)[keyof typeof HOOK_TYPES];
|
|
30
|
+
/**
|
|
31
|
+
* Negative-lookahead matcher for external MCP tool namespaces on Gemini CLI (#529).
|
|
32
|
+
*
|
|
33
|
+
* Gemini CLI MCP wire shape: `mcp__<server>__<tool>` (verified in
|
|
34
|
+
* hooks/core/tool-naming.mjs — context-mode's own tools surface as
|
|
35
|
+
* `mcp__context-mode__<tool>`). This pattern fires BeforeTool for any
|
|
36
|
+
* external `mcp__<server>__<tool>` whose server segment does NOT contain
|
|
37
|
+
* `context-mode`. Without it, large payloads from slack / telegram / gdrive /
|
|
38
|
+
* notion-style MCPs bypass the routing nudge and flood the model's context.
|
|
39
|
+
*
|
|
40
|
+
* The negative lookahead `(?!.*context-mode)` covers both the canonical
|
|
41
|
+
* `mcp__context-mode__*` and any Claude shim `mcp__plugin_context-mode_*`
|
|
42
|
+
* names. Gemini native bare tool names (run_shell_command, read_file, …)
|
|
43
|
+
* are not `mcp__`-prefixed and are unaffected.
|
|
44
|
+
*/
|
|
45
|
+
export declare const EXTERNAL_MCP_MATCHER_PATTERN = "mcp__(?!.*context-mode)";
|
|
30
46
|
/** Map of hook types to their script file names. */
|
|
31
47
|
export declare const HOOK_SCRIPTS: Record<HookType, string>;
|
|
32
48
|
/** Required hooks that must be configured for context-mode to function. */
|
|
@@ -31,6 +31,25 @@ export const HOOK_TYPES = {
|
|
|
31
31
|
SESSION_START: "SessionStart",
|
|
32
32
|
};
|
|
33
33
|
// ─────────────────────────────────────────────────────────
|
|
34
|
+
// External MCP routing matcher (#529)
|
|
35
|
+
// ─────────────────────────────────────────────────────────
|
|
36
|
+
/**
|
|
37
|
+
* Negative-lookahead matcher for external MCP tool namespaces on Gemini CLI (#529).
|
|
38
|
+
*
|
|
39
|
+
* Gemini CLI MCP wire shape: `mcp__<server>__<tool>` (verified in
|
|
40
|
+
* hooks/core/tool-naming.mjs — context-mode's own tools surface as
|
|
41
|
+
* `mcp__context-mode__<tool>`). This pattern fires BeforeTool for any
|
|
42
|
+
* external `mcp__<server>__<tool>` whose server segment does NOT contain
|
|
43
|
+
* `context-mode`. Without it, large payloads from slack / telegram / gdrive /
|
|
44
|
+
* notion-style MCPs bypass the routing nudge and flood the model's context.
|
|
45
|
+
*
|
|
46
|
+
* The negative lookahead `(?!.*context-mode)` covers both the canonical
|
|
47
|
+
* `mcp__context-mode__*` and any Claude shim `mcp__plugin_context-mode_*`
|
|
48
|
+
* names. Gemini native bare tool names (run_shell_command, read_file, …)
|
|
49
|
+
* are not `mcp__`-prefixed and are unaffected.
|
|
50
|
+
*/
|
|
51
|
+
export const EXTERNAL_MCP_MATCHER_PATTERN = "mcp__(?!.*context-mode)";
|
|
52
|
+
// ─────────────────────────────────────────────────────────
|
|
34
53
|
// Hook script file names
|
|
35
54
|
// ─────────────────────────────────────────────────────────
|
|
36
55
|
/** Map of hook types to their script file names. */
|
|
@@ -25,7 +25,7 @@ import { BaseAdapter } from "../base.js";
|
|
|
25
25
|
// ─────────────────────────────────────────────────────────
|
|
26
26
|
// Hook constants (re-exported from hooks.ts)
|
|
27
27
|
// ─────────────────────────────────────────────────────────
|
|
28
|
-
import { HOOK_TYPES as GEMINI_HOOK_NAMES, HOOK_SCRIPTS as GEMINI_HOOK_SCRIPTS, buildHookCommand as buildGeminiHookCommand, } from "./hooks.js";
|
|
28
|
+
import { HOOK_TYPES as GEMINI_HOOK_NAMES, HOOK_SCRIPTS as GEMINI_HOOK_SCRIPTS, buildHookCommand as buildGeminiHookCommand, EXTERNAL_MCP_MATCHER_PATTERN, } from "./hooks.js";
|
|
29
29
|
// ─────────────────────────────────────────────────────────
|
|
30
30
|
// Adapter implementation
|
|
31
31
|
// ─────────────────────────────────────────────────────────
|
|
@@ -178,7 +178,9 @@ export class GeminiCLIAdapter extends BaseAdapter {
|
|
|
178
178
|
],
|
|
179
179
|
[GEMINI_HOOK_NAMES.BEFORE_TOOL]: [
|
|
180
180
|
{
|
|
181
|
-
|
|
181
|
+
// Gemini native tools + context-mode own MCP (both canonical and Claude
|
|
182
|
+
// shim prefixes) + external MCP catch-all (#529).
|
|
183
|
+
matcher: `run_shell_command|read_file|read_many_files|grep_search|search_file_content|web_fetch|activate_skill|mcp__plugin_context-mode|mcp__context-mode|${EXTERNAL_MCP_MATCHER_PATTERN}`,
|
|
182
184
|
hooks: [
|
|
183
185
|
{
|
|
184
186
|
type: "command",
|
|
@@ -18,6 +18,21 @@ export declare const HOOK_TYPES: {
|
|
|
18
18
|
};
|
|
19
19
|
export type HookType = (typeof HOOK_TYPES)[keyof typeof HOOK_TYPES];
|
|
20
20
|
export declare const HOOK_SCRIPTS: Record<string, string>;
|
|
21
|
+
/**
|
|
22
|
+
* Negative-lookahead matcher for external MCP tool namespaces on Kiro (#529).
|
|
23
|
+
*
|
|
24
|
+
* Kiro MCP wire shape: `@<server>/<tool>` (verified in
|
|
25
|
+
* hooks/core/tool-naming.mjs — context-mode's own tools surface as
|
|
26
|
+
* `@context-mode/<tool>`). This pattern fires PreToolUse for any external
|
|
27
|
+
* `@<server>/<tool>` whose server segment is NOT `context-mode`. Without it,
|
|
28
|
+
* large payloads from slack / telegram / gdrive / notion-style MCPs bypass
|
|
29
|
+
* the routing nudge and flood the model's context window — PostToolUse runs
|
|
30
|
+
* too late to keep the raw data out.
|
|
31
|
+
*
|
|
32
|
+
* Routing.mjs `isExternalMcpTool` is extended to recognise the `@<server>/`
|
|
33
|
+
* prefix shape so the routing branch returns external-MCP guidance.
|
|
34
|
+
*/
|
|
35
|
+
export declare const EXTERNAL_MCP_MATCHER_PATTERN = "@(?!context-mode/)";
|
|
21
36
|
/**
|
|
22
37
|
* Tools that context-mode's PreToolUse hook intercepts on Kiro.
|
|
23
38
|
*
|
|
@@ -26,7 +41,7 @@ export declare const HOOK_SCRIPTS: Record<string, string>;
|
|
|
26
41
|
*
|
|
27
42
|
* MCP tools surface as @context-mode/ctx_* in Kiro.
|
|
28
43
|
*/
|
|
29
|
-
export declare const PRE_TOOL_USE_MATCHERS: readonly ["execute_bash", "fs_read", "@context-mode/ctx_execute", "@context-mode/ctx_execute_file", "@context-mode/ctx_batch_execute"];
|
|
44
|
+
export declare const PRE_TOOL_USE_MATCHERS: readonly ["execute_bash", "fs_read", "@context-mode/ctx_execute", "@context-mode/ctx_execute_file", "@context-mode/ctx_batch_execute", "@(?!context-mode/)"];
|
|
30
45
|
/**
|
|
31
46
|
* Combined matcher pattern for Kiro hook config (pipe-separated).
|
|
32
47
|
* Used by generateHookConfig and configureAllHooks.
|
|
@@ -24,6 +24,24 @@ export const HOOK_SCRIPTS = {
|
|
|
24
24
|
[HOOK_TYPES.AGENT_SPAWN]: "agentspawn.mjs",
|
|
25
25
|
};
|
|
26
26
|
// ─────────────────────────────────────────────────────────
|
|
27
|
+
// External MCP routing matcher (#529)
|
|
28
|
+
// ─────────────────────────────────────────────────────────
|
|
29
|
+
/**
|
|
30
|
+
* Negative-lookahead matcher for external MCP tool namespaces on Kiro (#529).
|
|
31
|
+
*
|
|
32
|
+
* Kiro MCP wire shape: `@<server>/<tool>` (verified in
|
|
33
|
+
* hooks/core/tool-naming.mjs — context-mode's own tools surface as
|
|
34
|
+
* `@context-mode/<tool>`). This pattern fires PreToolUse for any external
|
|
35
|
+
* `@<server>/<tool>` whose server segment is NOT `context-mode`. Without it,
|
|
36
|
+
* large payloads from slack / telegram / gdrive / notion-style MCPs bypass
|
|
37
|
+
* the routing nudge and flood the model's context window — PostToolUse runs
|
|
38
|
+
* too late to keep the raw data out.
|
|
39
|
+
*
|
|
40
|
+
* Routing.mjs `isExternalMcpTool` is extended to recognise the `@<server>/`
|
|
41
|
+
* prefix shape so the routing branch returns external-MCP guidance.
|
|
42
|
+
*/
|
|
43
|
+
export const EXTERNAL_MCP_MATCHER_PATTERN = "@(?!context-mode/)";
|
|
44
|
+
// ─────────────────────────────────────────────────────────
|
|
27
45
|
// PreToolUse matchers
|
|
28
46
|
// ─────────────────────────────────────────────────────────
|
|
29
47
|
/**
|
|
@@ -40,6 +58,7 @@ export const PRE_TOOL_USE_MATCHERS = [
|
|
|
40
58
|
"@context-mode/ctx_execute",
|
|
41
59
|
"@context-mode/ctx_execute_file",
|
|
42
60
|
"@context-mode/ctx_batch_execute",
|
|
61
|
+
EXTERNAL_MCP_MATCHER_PATTERN,
|
|
43
62
|
];
|
|
44
63
|
/**
|
|
45
64
|
* Combined matcher pattern for Kiro hook config (pipe-separated).
|