context-mode 1.0.105 → 1.0.107

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.
Files changed (45) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.openclaw-plugin/openclaw.plugin.json +1 -1
  4. package/.openclaw-plugin/package.json +1 -1
  5. package/build/adapters/copilot-base.d.ts +3 -3
  6. package/build/adapters/cursor/hooks.js +8 -0
  7. package/build/adapters/cursor/index.js +4 -1
  8. package/build/adapters/gemini-cli/hooks.d.ts +6 -1
  9. package/build/adapters/gemini-cli/hooks.js +7 -1
  10. package/build/adapters/gemini-cli/index.js +12 -0
  11. package/build/adapters/kiro/hooks.js +4 -0
  12. package/build/adapters/kiro/index.d.ts +9 -2
  13. package/build/adapters/kiro/index.js +49 -27
  14. package/build/adapters/opencode/index.js +6 -0
  15. package/build/adapters/qwen-code/index.js +18 -0
  16. package/build/adapters/vscode-copilot/hooks.d.ts +0 -4
  17. package/build/adapters/vscode-copilot/hooks.js +6 -6
  18. package/build/cli.js +1 -0
  19. package/build/openclaw/mcp-tools.d.ts +54 -0
  20. package/build/openclaw/mcp-tools.js +198 -0
  21. package/build/openclaw-plugin.d.ts +9 -0
  22. package/build/openclaw-plugin.js +132 -16
  23. package/build/opencode-plugin.d.ts +29 -4
  24. package/build/opencode-plugin.js +185 -11
  25. package/build/pi-extension.js +123 -29
  26. package/build/server.d.ts +1 -0
  27. package/build/server.js +28 -2
  28. package/build/session/db.d.ts +12 -3
  29. package/build/session/db.js +19 -4
  30. package/build/session/extract.d.ts +1 -1
  31. package/build/session/extract.js +46 -1
  32. package/cli.bundle.mjs +128 -127
  33. package/hooks/core/platform-detect.mjs +49 -0
  34. package/hooks/core/routing.mjs +13 -1
  35. package/hooks/cursor/afteragentresponse.mjs +74 -0
  36. package/hooks/gemini-cli/beforeagent.mjs +99 -0
  37. package/hooks/kiro/agentspawn.mjs +97 -0
  38. package/hooks/kiro/userpromptsubmit.mjs +88 -0
  39. package/hooks/session-db.bundle.mjs +4 -3
  40. package/hooks/session-extract.bundle.mjs +2 -2
  41. package/hooks/sessionstart.mjs +3 -1
  42. package/hooks/vscode-copilot/sessionstart.mjs +13 -14
  43. package/openclaw.plugin.json +1 -1
  44. package/package.json +1 -1
  45. package/server.bundle.mjs +72 -71
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Claude Code plugins by Mert Koseoğlu",
9
- "version": "1.0.105"
9
+ "version": "1.0.107"
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.105",
16
+ "version": "1.0.107",
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.105",
3
+ "version": "1.0.107",
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.105",
6
+ "version": "1.0.107",
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.105",
3
+ "version": "1.0.107",
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",
@@ -34,9 +34,9 @@ export interface CopilotHookModule {
34
34
  readonly POST_TOOL_USE: string;
35
35
  readonly PRE_COMPACT: string;
36
36
  readonly SESSION_START: string;
37
- readonly STOP: string;
38
- readonly SUBAGENT_START: string;
39
- readonly SUBAGENT_STOP: string;
37
+ readonly STOP?: string;
38
+ readonly SUBAGENT_START?: string;
39
+ readonly SUBAGENT_STOP?: string;
40
40
  };
41
41
  HOOK_SCRIPTS: Record<string, string>;
42
42
  buildHookCommand: (hookType: any, pluginRoot?: string) => string;
@@ -19,8 +19,16 @@ export const HOOK_SCRIPTS = {
19
19
  [HOOK_TYPES.POST_TOOL_USE]: "posttooluse.mjs",
20
20
  [HOOK_TYPES.SESSION_START]: "sessionstart.mjs",
21
21
  [HOOK_TYPES.STOP]: "stop.mjs",
22
+ [HOOK_TYPES.AFTER_AGENT_RESPONSE]: "afteragentresponse.mjs",
22
23
  };
23
24
  /** Canonical Cursor-native matchers for tools context-mode routes proactively. */
25
+ // NOTE (Cursor-3, deferred): Cursor is closed-source and does not currently
26
+ // publish the exact tool name it uses for sub-agent dispatch (the analogue of
27
+ // Claude Code's "Task" tool). The "Task" matcher below is kept as a best-guess
28
+ // placeholder until probe data from a real Cursor session confirms the wire
29
+ // name. If/when that probe lands, replace or supplement this entry — do NOT
30
+ // add unverified matchers in the meantime. See Phase 7 audit
31
+ // `/tmp/v1.0.107-adapter-cursor.json` (Cursor-3) for the full deferral note.
24
32
  export const PRE_TOOL_USE_MATCHERS = [
25
33
  "Shell",
26
34
  "Read",
@@ -21,7 +21,10 @@ export class CursorAdapter extends BaseAdapter {
21
21
  preToolUse: true,
22
22
  postToolUse: true,
23
23
  preCompact: false,
24
- sessionStart: false,
24
+ // Cursor v1 ships native sessionStart and the matching hook script
25
+ // (hooks/cursor/sessionstart.mjs) is wired through the dispatcher
26
+ // (src/cli.ts HOOK_MAP). Capability flag must reflect script presence.
27
+ sessionStart: true,
25
28
  canModifyArgs: true,
26
29
  canModifyOutput: false,
27
30
  canInjectSessionContext: true,
@@ -10,12 +10,17 @@
10
10
  * Gemini CLI hook system reference:
11
11
  * - Hooks are registered in ~/.gemini/settings.json under "hooks" key
12
12
  * - Each hook type maps to an array of { matcher, hooks } entries
13
- * - Hook names: BeforeTool, AfterTool, PreCompress, SessionStart
13
+ * - Hook names: BeforeAgent, BeforeTool, AfterTool, PreCompress, SessionStart
14
14
  * - Input: JSON on stdin
15
15
  * - Output: JSON on stdout (or empty for passthrough)
16
+ * - BeforeAgent fires when user submits a prompt — input.prompt carries
17
+ * the user message; hookSpecificOutput.additionalContext is appended
18
+ * to the prompt (hookRunner.ts:183-197). Equivalent to Claude Code's
19
+ * UserPromptSubmit for session-continuity capture.
16
20
  */
17
21
  /** Gemini CLI hook types. */
18
22
  export declare const HOOK_TYPES: {
23
+ readonly BEFORE_AGENT: "BeforeAgent";
19
24
  readonly BEFORE_TOOL: "BeforeTool";
20
25
  readonly AFTER_TOOL: "AfterTool";
21
26
  readonly PRE_COMPRESS: "PreCompress";
@@ -11,15 +11,20 @@ import { buildNodeCommand } from "../types.js";
11
11
  * Gemini CLI hook system reference:
12
12
  * - Hooks are registered in ~/.gemini/settings.json under "hooks" key
13
13
  * - Each hook type maps to an array of { matcher, hooks } entries
14
- * - Hook names: BeforeTool, AfterTool, PreCompress, SessionStart
14
+ * - Hook names: BeforeAgent, BeforeTool, AfterTool, PreCompress, SessionStart
15
15
  * - Input: JSON on stdin
16
16
  * - Output: JSON on stdout (or empty for passthrough)
17
+ * - BeforeAgent fires when user submits a prompt — input.prompt carries
18
+ * the user message; hookSpecificOutput.additionalContext is appended
19
+ * to the prompt (hookRunner.ts:183-197). Equivalent to Claude Code's
20
+ * UserPromptSubmit for session-continuity capture.
17
21
  */
18
22
  // ─────────────────────────────────────────────────────────
19
23
  // Hook type constants
20
24
  // ─────────────────────────────────────────────────────────
21
25
  /** Gemini CLI hook types. */
22
26
  export const HOOK_TYPES = {
27
+ BEFORE_AGENT: "BeforeAgent",
23
28
  BEFORE_TOOL: "BeforeTool",
24
29
  AFTER_TOOL: "AfterTool",
25
30
  PRE_COMPRESS: "PreCompress",
@@ -30,6 +35,7 @@ export const HOOK_TYPES = {
30
35
  // ─────────────────────────────────────────────────────────
31
36
  /** Map of hook types to their script file names. */
32
37
  export const HOOK_SCRIPTS = {
38
+ [HOOK_TYPES.BEFORE_AGENT]: "beforeagent.mjs",
33
39
  [HOOK_TYPES.BEFORE_TOOL]: "beforetool.mjs",
34
40
  [HOOK_TYPES.AFTER_TOOL]: "aftertool.mjs",
35
41
  [HOOK_TYPES.PRE_COMPRESS]: "precompress.mjs",
@@ -165,6 +165,17 @@ export class GeminiCLIAdapter extends BaseAdapter {
165
165
  }
166
166
  generateHookConfig(pluginRoot) {
167
167
  return {
168
+ [GEMINI_HOOK_NAMES.BEFORE_AGENT]: [
169
+ {
170
+ matcher: "",
171
+ hooks: [
172
+ {
173
+ type: "command",
174
+ command: buildGeminiHookCommand(GEMINI_HOOK_NAMES.BEFORE_AGENT, pluginRoot),
175
+ },
176
+ ],
177
+ },
178
+ ],
168
179
  [GEMINI_HOOK_NAMES.BEFORE_TOOL]: [
169
180
  {
170
181
  matcher: "run_shell_command|read_file|read_many_files|grep_search|search_file_content|web_fetch|activate_skill|mcp__plugin_context-mode",
@@ -331,6 +342,7 @@ export class GeminiCLIAdapter extends BaseAdapter {
331
342
  const hooks = (settings.hooks ?? {});
332
343
  const changes = [];
333
344
  const hookConfigs = [
345
+ { name: GEMINI_HOOK_NAMES.BEFORE_AGENT },
334
346
  { name: GEMINI_HOOK_NAMES.BEFORE_TOOL },
335
347
  { name: GEMINI_HOOK_NAMES.SESSION_START },
336
348
  ];
@@ -20,6 +20,8 @@ export const HOOK_TYPES = {
20
20
  export const HOOK_SCRIPTS = {
21
21
  [HOOK_TYPES.PRE_TOOL_USE]: "pretooluse.mjs",
22
22
  [HOOK_TYPES.POST_TOOL_USE]: "posttooluse.mjs",
23
+ [HOOK_TYPES.USER_PROMPT_SUBMIT]: "userpromptsubmit.mjs",
24
+ [HOOK_TYPES.AGENT_SPAWN]: "agentspawn.mjs",
23
25
  };
24
26
  // ─────────────────────────────────────────────────────────
25
27
  // PreToolUse matchers
@@ -46,9 +48,11 @@ export const PRE_TOOL_USE_MATCHERS = [
46
48
  export const PRE_TOOL_USE_MATCHER_PATTERN = PRE_TOOL_USE_MATCHERS.join("|");
47
49
  export const REQUIRED_HOOKS = [
48
50
  HOOK_TYPES.PRE_TOOL_USE,
51
+ HOOK_TYPES.AGENT_SPAWN,
49
52
  ];
50
53
  export const OPTIONAL_HOOKS = [
51
54
  HOOK_TYPES.POST_TOOL_USE,
55
+ HOOK_TYPES.USER_PROMPT_SUBMIT,
52
56
  ];
53
57
  /**
54
58
  * Check if a hook entry points to a context-mode hook script.
@@ -18,6 +18,13 @@
18
18
  * - CLI hooks: https://kiro.dev/docs/cli/custom-agents/configuration-reference#hooks-field
19
19
  */
20
20
  import { BaseAdapter } from "../base.js";
21
+ /**
22
+ * Steering integration: we ship a single context-mode-specific routing file
23
+ * at `configs/kiro/KIRO.md`. Users can copy it into `.kiro/steering/` to opt
24
+ * into deterministic injection. We do NOT deploy generic SDD scaffolds (e.g.
25
+ * cc-sdd's product/structure/tech + steering-custom/* templates) — those are
26
+ * project-template content, not adapter wiring.
27
+ */
21
28
  import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration } from "../types.js";
22
29
  export declare class KiroAdapter extends BaseAdapter implements HookAdapter {
23
30
  constructor();
@@ -27,11 +34,11 @@ export declare class KiroAdapter extends BaseAdapter implements HookAdapter {
27
34
  parsePreToolUseInput(raw: unknown): PreToolUseEvent;
28
35
  parsePostToolUseInput(raw: unknown): PostToolUseEvent;
29
36
  parsePreCompactInput(_raw: unknown): PreCompactEvent;
30
- parseSessionStartInput(_raw: unknown): SessionStartEvent;
37
+ parseSessionStartInput(raw: unknown): SessionStartEvent;
31
38
  formatPreToolUseResponse(response: PreToolUseResponse): unknown;
32
39
  formatPostToolUseResponse(_response: PostToolUseResponse): unknown;
33
40
  formatPreCompactResponse(_response: PreCompactResponse): unknown;
34
- formatSessionStartResponse(_response: SessionStartResponse): unknown;
41
+ formatSessionStartResponse(response: SessionStartResponse): unknown;
35
42
  getSettingsPath(): string;
36
43
  /**
37
44
  * Kiro stores per-project context under .kiro/ (steering files, etc).
@@ -36,10 +36,10 @@ export class KiroAdapter extends BaseAdapter {
36
36
  preToolUse: true,
37
37
  postToolUse: true,
38
38
  preCompact: false,
39
- sessionStart: false,
39
+ sessionStart: true, // Kiro agentSpawn = SessionStart equivalent
40
40
  canModifyArgs: false, // Kiro CLI uses exit codes, can't modify input
41
41
  canModifyOutput: false,
42
- canInjectSessionContext: false,
42
+ canInjectSessionContext: true, // agentSpawn returns additionalContext via JSON stdout
43
43
  };
44
44
  // ── Input parsing ──────────────────────────────────────
45
45
  parsePreToolUseInput(raw) {
@@ -69,8 +69,16 @@ export class KiroAdapter extends BaseAdapter {
69
69
  parsePreCompactInput(_raw) {
70
70
  throw new Error("Kiro does not support PreCompact hooks");
71
71
  }
72
- parseSessionStartInput(_raw) {
73
- throw new Error("Kiro does not support SessionStart hooks (yet)");
72
+ parseSessionStartInput(raw) {
73
+ // Kiro maps agentSpawn -> SessionStart. Stdin shape mirrors codex/CC.
74
+ const input = (raw ?? {});
75
+ const source = input.source ?? "startup";
76
+ return {
77
+ source,
78
+ sessionId: `pid-${process.ppid}`,
79
+ projectDir: input.cwd ?? process.cwd(),
80
+ raw,
81
+ };
74
82
  }
75
83
  // ── Response formatting ────────────────────────────────
76
84
  formatPreToolUseResponse(response) {
@@ -91,8 +99,16 @@ export class KiroAdapter extends BaseAdapter {
91
99
  formatPreCompactResponse(_response) {
92
100
  return undefined;
93
101
  }
94
- formatSessionStartResponse(_response) {
95
- return undefined;
102
+ formatSessionStartResponse(response) {
103
+ // Kiro agentSpawn returns the same hookSpecificOutput shape as CC SessionStart.
104
+ if (!response?.context)
105
+ return undefined;
106
+ return {
107
+ hookSpecificOutput: {
108
+ hookEventName: "agentSpawn",
109
+ additionalContext: response.context,
110
+ },
111
+ };
96
112
  }
97
113
  // ── Configuration ──────────────────────────────────────
98
114
  getSettingsPath() {
@@ -111,8 +127,8 @@ export class KiroAdapter extends BaseAdapter {
111
127
  return ["KIRO.md"];
112
128
  }
113
129
  generateHookConfig(pluginRoot) {
114
- // Kiro CLI hook config format: { preToolUse: [{ matcher, command }] }
115
- // Note: This generates the entries for agent config files
130
+ // Kiro CLI hook config format: { <hookName>: [{ matcher, command }] }
131
+ // Note: This generates the entries for agent config files (~/.kiro/agents/*.json).
116
132
  return {
117
133
  [KIRO_HOOK_TYPES.PRE_TOOL_USE]: [{
118
134
  matcher: KIRO_PRE_TOOL_USE_MATCHER_PATTERN,
@@ -122,6 +138,14 @@ export class KiroAdapter extends BaseAdapter {
122
138
  matcher: "*",
123
139
  hooks: [{ type: "command", command: buildKiroHookCommand(KIRO_HOOK_TYPES.POST_TOOL_USE, pluginRoot) }],
124
140
  }],
141
+ [KIRO_HOOK_TYPES.AGENT_SPAWN]: [{
142
+ matcher: "*",
143
+ hooks: [{ type: "command", command: buildKiroHookCommand(KIRO_HOOK_TYPES.AGENT_SPAWN, pluginRoot) }],
144
+ }],
145
+ [KIRO_HOOK_TYPES.USER_PROMPT_SUBMIT]: [{
146
+ matcher: "*",
147
+ hooks: [{ type: "command", command: buildKiroHookCommand(KIRO_HOOK_TYPES.USER_PROMPT_SUBMIT, pluginRoot) }],
148
+ }],
125
149
  };
126
150
  }
127
151
  readSettings() {
@@ -233,25 +257,23 @@ export class KiroAdapter extends BaseAdapter {
233
257
  // No existing config — create new
234
258
  }
235
259
  const hooks = (config.hooks ?? {});
236
- // Add preToolUse hook if not present
237
- const preToolUseEntries = (hooks[KIRO_HOOK_TYPES.PRE_TOOL_USE] ?? []);
238
- if (!preToolUseEntries.some(e => isKiroContextModeHook(e, KIRO_HOOK_TYPES.PRE_TOOL_USE))) {
239
- preToolUseEntries.push({
240
- matcher: KIRO_PRE_TOOL_USE_MATCHER_PATTERN,
241
- command: buildKiroHookCommand(KIRO_HOOK_TYPES.PRE_TOOL_USE, pluginRoot),
242
- });
243
- hooks[KIRO_HOOK_TYPES.PRE_TOOL_USE] = preToolUseEntries;
244
- changes.push(`Added ${KIRO_HOOK_TYPES.PRE_TOOL_USE} hook to ${defaultAgent}`);
245
- }
246
- // Add postToolUse hook if not present
247
- const postToolUseEntries = (hooks[KIRO_HOOK_TYPES.POST_TOOL_USE] ?? []);
248
- if (!postToolUseEntries.some(e => isKiroContextModeHook(e, KIRO_HOOK_TYPES.POST_TOOL_USE))) {
249
- postToolUseEntries.push({
250
- matcher: "*",
251
- command: buildKiroHookCommand(KIRO_HOOK_TYPES.POST_TOOL_USE, pluginRoot),
252
- });
253
- hooks[KIRO_HOOK_TYPES.POST_TOOL_USE] = postToolUseEntries;
254
- changes.push(`Added ${KIRO_HOOK_TYPES.POST_TOOL_USE} hook to ${defaultAgent}`);
260
+ // Hooks to add: [hookType, matcher]
261
+ const hookSpecs = [
262
+ [KIRO_HOOK_TYPES.PRE_TOOL_USE, KIRO_PRE_TOOL_USE_MATCHER_PATTERN],
263
+ [KIRO_HOOK_TYPES.POST_TOOL_USE, "*"],
264
+ [KIRO_HOOK_TYPES.AGENT_SPAWN, "*"],
265
+ [KIRO_HOOK_TYPES.USER_PROMPT_SUBMIT, "*"],
266
+ ];
267
+ for (const [hookType, matcher] of hookSpecs) {
268
+ const entries = (hooks[hookType] ?? []);
269
+ if (!entries.some(e => isKiroContextModeHook(e, hookType))) {
270
+ entries.push({
271
+ matcher,
272
+ command: buildKiroHookCommand(hookType, pluginRoot),
273
+ });
274
+ hooks[hookType] = entries;
275
+ changes.push(`Added ${hookType} hook to ${defaultAgent}`);
276
+ }
255
277
  }
256
278
  config.hooks = hooks;
257
279
  writeFileSync(defaultAgent, JSON.stringify(config, null, 2), "utf-8");
@@ -152,11 +152,17 @@ export class OpenCodeAdapter extends BaseAdapter {
152
152
  }
153
153
  paths() {
154
154
  if (this.platform === "kilo") {
155
+ // Kilo runtime accepts `.kilo/`, `.kilocode/`, and `.opencode/` as
156
+ // project config dirs (refs/platforms/kilo/packages/opencode/src/
157
+ // kilocode/config/config.ts:50,408). Mirror that here so context-mode
158
+ // discovers config regardless of which suffix the user adopted.
155
159
  return [
156
160
  resolve("kilo.json"),
157
161
  resolve("kilo.jsonc"),
158
162
  resolve(".kilo", "kilo.json"),
159
163
  resolve(".kilo", "kilo.jsonc"),
164
+ resolve(".kilocode", "kilo.json"),
165
+ resolve(".kilocode", "kilo.jsonc"),
160
166
  join(homedir(), ".config", "kilo", "kilo.json"),
161
167
  join(homedir(), ".config", "kilo", "kilo.jsonc"),
162
168
  ];
@@ -230,6 +230,9 @@ export class QwenCodeAdapter extends ClaudeCodeBaseAdapter {
230
230
  }
231
231
  }
232
232
  // ── Phase 2: Register fresh hooks ────────────────────
233
+ // All 5 hooks must be wired (z6 — capabilities declare 5 events but
234
+ // configureAllHooks previously only wrote 2). Qwen Code's hook stdin shape
235
+ // is wire-identical to Claude Code, so we reuse top-level hook scripts.
233
236
  const hookTypes = [
234
237
  {
235
238
  name: "PreToolUse",
@@ -242,11 +245,26 @@ export class QwenCodeAdapter extends ClaudeCodeBaseAdapter {
242
245
  "mcp__plugin_context-mode_context-mode__ctx_batch_execute",
243
246
  ].join("|"),
244
247
  },
248
+ {
249
+ name: "PostToolUse",
250
+ script: "posttooluse.mjs",
251
+ matcher: "run_shell_command|read_file|write_file|edit|glob|grep_search|todo_write|agent|ask_user_question|mcp__",
252
+ },
245
253
  {
246
254
  name: "SessionStart",
247
255
  script: "sessionstart.mjs",
248
256
  matcher: "",
249
257
  },
258
+ {
259
+ name: "PreCompact",
260
+ script: "precompact.mjs",
261
+ matcher: "",
262
+ },
263
+ {
264
+ name: "UserPromptSubmit",
265
+ script: "userpromptsubmit.mjs",
266
+ matcher: "",
267
+ },
250
268
  ];
251
269
  for (const { name, script, matcher } of hookTypes) {
252
270
  const entry = {
@@ -10,7 +10,6 @@
10
10
  * VS Code Copilot hook system reference:
11
11
  * - Hooks are registered in .github/hooks/*.json
12
12
  * - Hook names: PreToolUse, PostToolUse, PreCompact, SessionStart (PascalCase)
13
- * - Additional hooks: Stop, SubagentStart, SubagentStop (unique to VS Code)
14
13
  * - CRITICAL: matchers are parsed but IGNORED (all hooks fire on all tools)
15
14
  * - Input: JSON on stdin
16
15
  * - Output: JSON on stdout (or empty for passthrough)
@@ -22,9 +21,6 @@ export declare const HOOK_TYPES: {
22
21
  readonly POST_TOOL_USE: "PostToolUse";
23
22
  readonly PRE_COMPACT: "PreCompact";
24
23
  readonly SESSION_START: "SessionStart";
25
- readonly STOP: "Stop";
26
- readonly SUBAGENT_START: "SubagentStart";
27
- readonly SUBAGENT_STOP: "SubagentStop";
28
24
  };
29
25
  export type HookType = (typeof HOOK_TYPES)[keyof typeof HOOK_TYPES];
30
26
  /** Map of hook types to their script file names. */
@@ -11,7 +11,6 @@ import { buildNodeCommand } from "../types.js";
11
11
  * VS Code Copilot hook system reference:
12
12
  * - Hooks are registered in .github/hooks/*.json
13
13
  * - Hook names: PreToolUse, PostToolUse, PreCompact, SessionStart (PascalCase)
14
- * - Additional hooks: Stop, SubagentStart, SubagentStop (unique to VS Code)
15
14
  * - CRITICAL: matchers are parsed but IGNORED (all hooks fire on all tools)
16
15
  * - Input: JSON on stdin
17
16
  * - Output: JSON on stdout (or empty for passthrough)
@@ -26,10 +25,6 @@ export const HOOK_TYPES = {
26
25
  POST_TOOL_USE: "PostToolUse",
27
26
  PRE_COMPACT: "PreCompact",
28
27
  SESSION_START: "SessionStart",
29
- // Additional hooks unique to VS Code Copilot
30
- STOP: "Stop",
31
- SUBAGENT_START: "SubagentStart",
32
- SUBAGENT_STOP: "SubagentStop",
33
28
  };
34
29
  // ─────────────────────────────────────────────────────────
35
30
  // Hook script file names
@@ -77,7 +72,12 @@ export function buildHookCommand(hookType, pluginRoot) {
77
72
  throw new Error(`No script defined for hook type: ${hookType}`);
78
73
  }
79
74
  if (pluginRoot) {
80
- return buildNodeCommand(`${pluginRoot}/hooks/${scriptName}`);
75
+ // v1.0.107 fix — was `${pluginRoot}/hooks/${scriptName}` which resolved to
76
+ // the Claude-Code generic hook (`hooks/pretooluse.mjs`) instead of the
77
+ // VSCode-specific wrapper at `hooks/vscode-copilot/pretooluse.mjs`. JetBrains
78
+ // adapter already had the correct subdir (jetbrains-copilot/hooks.ts:98)
79
+ // so this brings VSCode to parity.
80
+ return buildNodeCommand(`${pluginRoot}/hooks/vscode-copilot/${scriptName}`);
81
81
  }
82
82
  return `context-mode hook vscode-copilot ${hookType.toLowerCase()}`;
83
83
  }
package/build/cli.js CHANGED
@@ -50,6 +50,7 @@ const HOOK_MAP = {
50
50
  posttooluse: "hooks/cursor/posttooluse.mjs",
51
51
  sessionstart: "hooks/cursor/sessionstart.mjs",
52
52
  stop: "hooks/cursor/stop.mjs",
53
+ afteragentresponse: "hooks/cursor/afteragentresponse.mjs",
53
54
  },
54
55
  "codex": {
55
56
  pretooluse: "hooks/codex/pretooluse.mjs",
@@ -0,0 +1,54 @@
1
+ /**
2
+ * OpenClaw MCP tool registry.
3
+ *
4
+ * Catalogs the 11 ctx_* tools that OpenClaw plugin must register via
5
+ * api.registerTool(...) so the routing block (which nudges agents toward
6
+ * ctx_execute, ctx_search, etc.) actually has tools to call. Without this,
7
+ * Phase 7 audit (v1.0.107-adapter-openclaw.json) flagged severity=CRITICAL —
8
+ * routing-block premise is broken when the named tools don't exist.
9
+ *
10
+ * Pattern mirrors the swarmvault MCP plugin
11
+ * (refs/plugin-examples/openclaw/swarmvault/packages/engine/src/mcp.ts:46-51):
12
+ * server.registerTool(name, { description, inputSchema }, handler)
13
+ *
14
+ * OpenClaw signature is slightly different — see building-plugins.md:116
15
+ * api.registerTool({ name, description, parameters: TypeBox, execute(id, params) })
16
+ *
17
+ * Tool handlers are intentionally thin shims that delegate to the bundled CLI
18
+ * (cli.bundle.mjs) — same fall-through pattern already used by ctx-doctor and
19
+ * ctx-upgrade slash commands. This keeps the plugin's blast radius minimal:
20
+ * we don't re-export the entire MCP server stack inside OpenClaw's process.
21
+ *
22
+ * The 11 tools mirror src/server.ts registerTool calls (lines 897, 1226, 1371,
23
+ * 1497, 2034, 2256, 2440, 2501, 2592, 2712, 2808).
24
+ */
25
+ /** Minimal JSON-schema-like parameter spec accepted by OpenClaw registerTool. */
26
+ export interface OpenClawToolParameters {
27
+ type: "object";
28
+ properties: Record<string, {
29
+ type: string;
30
+ description?: string;
31
+ }>;
32
+ required?: string[];
33
+ additionalProperties?: boolean;
34
+ }
35
+ /** Tool definition shape returned to OpenClaw via api.registerTool. */
36
+ export interface OpenClawToolDef {
37
+ name: string;
38
+ description: string;
39
+ parameters: OpenClawToolParameters;
40
+ execute: (id: string, params: Record<string, unknown>) => Promise<{
41
+ content: Array<{
42
+ type: "text";
43
+ text: string;
44
+ }>;
45
+ }>;
46
+ }
47
+ /**
48
+ * The 11 ctx_* tool definitions registered into OpenClaw via api.registerTool.
49
+ * Names + descriptions mirror src/server.ts registerTool blocks 1:1 so prompts
50
+ * referencing them (routing block, AGENTS.md) resolve to real callable tools.
51
+ */
52
+ export declare const OPENCLAW_TOOL_DEFS: readonly OpenClawToolDef[];
53
+ /** Stable list of tool names — used by tests and manifest validation. */
54
+ export declare const OPENCLAW_TOOL_NAMES: readonly string[];