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.
- 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/build/adapters/copilot-base.d.ts +3 -3
- package/build/adapters/cursor/hooks.js +8 -0
- package/build/adapters/cursor/index.js +4 -1
- package/build/adapters/gemini-cli/hooks.d.ts +6 -1
- package/build/adapters/gemini-cli/hooks.js +7 -1
- package/build/adapters/gemini-cli/index.js +12 -0
- package/build/adapters/kiro/hooks.js +4 -0
- package/build/adapters/kiro/index.d.ts +9 -2
- package/build/adapters/kiro/index.js +49 -27
- package/build/adapters/opencode/index.js +6 -0
- package/build/adapters/qwen-code/index.js +18 -0
- package/build/adapters/vscode-copilot/hooks.d.ts +0 -4
- package/build/adapters/vscode-copilot/hooks.js +6 -6
- package/build/cli.js +1 -0
- package/build/openclaw/mcp-tools.d.ts +54 -0
- package/build/openclaw/mcp-tools.js +198 -0
- package/build/openclaw-plugin.d.ts +9 -0
- package/build/openclaw-plugin.js +132 -16
- package/build/opencode-plugin.d.ts +29 -4
- package/build/opencode-plugin.js +185 -11
- package/build/pi-extension.js +123 -29
- package/build/server.d.ts +1 -0
- package/build/server.js +28 -2
- package/build/session/db.d.ts +12 -3
- package/build/session/db.js +19 -4
- package/build/session/extract.d.ts +1 -1
- package/build/session/extract.js +46 -1
- package/cli.bundle.mjs +128 -127
- package/hooks/core/platform-detect.mjs +49 -0
- package/hooks/core/routing.mjs +13 -1
- package/hooks/cursor/afteragentresponse.mjs +74 -0
- package/hooks/gemini-cli/beforeagent.mjs +99 -0
- package/hooks/kiro/agentspawn.mjs +97 -0
- package/hooks/kiro/userpromptsubmit.mjs +88 -0
- package/hooks/session-db.bundle.mjs +4 -3
- package/hooks/session-extract.bundle.mjs +2 -2
- package/hooks/sessionstart.mjs +3 -1
- package/hooks/vscode-copilot/sessionstart.mjs +13 -14
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- 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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
38
|
-
readonly SUBAGENT_START
|
|
39
|
-
readonly SUBAGENT_STOP
|
|
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
|
|
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(
|
|
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(
|
|
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:
|
|
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:
|
|
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(
|
|
73
|
-
|
|
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(
|
|
95
|
-
|
|
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: {
|
|
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
|
-
//
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
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
|
-
|
|
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[];
|