context-mode 1.0.106 → 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 (42) 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 +154 -7
  25. package/build/pi-extension.js +123 -29
  26. package/build/server.d.ts +1 -0
  27. package/build/server.js +19 -1
  28. package/build/session/extract.d.ts +1 -1
  29. package/build/session/extract.js +46 -1
  30. package/cli.bundle.mjs +125 -125
  31. package/hooks/core/platform-detect.mjs +49 -0
  32. package/hooks/core/routing.mjs +13 -1
  33. package/hooks/cursor/afteragentresponse.mjs +74 -0
  34. package/hooks/gemini-cli/beforeagent.mjs +99 -0
  35. package/hooks/kiro/agentspawn.mjs +97 -0
  36. package/hooks/kiro/userpromptsubmit.mjs +88 -0
  37. package/hooks/session-extract.bundle.mjs +2 -2
  38. package/hooks/sessionstart.mjs +3 -1
  39. package/hooks/vscode-copilot/sessionstart.mjs +13 -14
  40. package/openclaw.plugin.json +1 -1
  41. package/package.json +1 -1
  42. package/server.bundle.mjs +68 -68
@@ -0,0 +1,198 @@
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
+ /** Wrap any handler so failures become a well-formed text error rather than crashing. */
26
+ function safe(handler) {
27
+ return async (_id, params) => {
28
+ try {
29
+ return await handler(params ?? {});
30
+ }
31
+ catch (err) {
32
+ const message = err instanceof Error ? err.message : String(err);
33
+ return {
34
+ content: [
35
+ {
36
+ type: "text",
37
+ text: `[context-mode] tool error: ${message}`,
38
+ },
39
+ ],
40
+ };
41
+ }
42
+ };
43
+ }
44
+ /** Stub handler — points users at the bundled CLI for full functionality. */
45
+ function cliRedirect(toolName) {
46
+ return safe(async () => ({
47
+ content: [
48
+ {
49
+ type: "text",
50
+ text: `[context-mode] ${toolName} is exposed via the bundled context-mode CLI. Run 'context-mode ${toolName}' or invoke the MCP server directly. This OpenClaw stub registers the tool name so the routing block remains valid; full execution requires the standalone MCP transport.`,
51
+ },
52
+ ],
53
+ }));
54
+ }
55
+ /**
56
+ * The 11 ctx_* tool definitions registered into OpenClaw via api.registerTool.
57
+ * Names + descriptions mirror src/server.ts registerTool blocks 1:1 so prompts
58
+ * referencing them (routing block, AGENTS.md) resolve to real callable tools.
59
+ */
60
+ export const OPENCLAW_TOOL_DEFS = [
61
+ {
62
+ name: "ctx_execute",
63
+ description: "Execute code in a sandboxed subprocess. Only stdout enters context. Prefer over Bash for any command producing >20 lines.",
64
+ parameters: {
65
+ type: "object",
66
+ properties: {
67
+ language: { type: "string", description: "Runtime language" },
68
+ code: { type: "string", description: "Source code to execute" },
69
+ timeout: { type: "number", description: "Max execution time in ms" },
70
+ },
71
+ required: ["language", "code"],
72
+ additionalProperties: true,
73
+ },
74
+ execute: cliRedirect("ctx_execute"),
75
+ },
76
+ {
77
+ name: "ctx_execute_file",
78
+ description: "Execute code with a file path. Only printed summary enters context — raw file stays in sandbox.",
79
+ parameters: {
80
+ type: "object",
81
+ properties: {
82
+ path: { type: "string", description: "File path" },
83
+ language: { type: "string", description: "Runtime language" },
84
+ code: { type: "string", description: "Source code" },
85
+ },
86
+ required: ["path", "language", "code"],
87
+ additionalProperties: true,
88
+ },
89
+ execute: cliRedirect("ctx_execute_file"),
90
+ },
91
+ {
92
+ name: "ctx_index",
93
+ description: "Store content in the FTS5 knowledge base for later search.",
94
+ parameters: {
95
+ type: "object",
96
+ properties: {
97
+ content: { type: "string", description: "Text to index" },
98
+ source: { type: "string", description: "Descriptive source label" },
99
+ },
100
+ required: ["content", "source"],
101
+ additionalProperties: true,
102
+ },
103
+ execute: cliRedirect("ctx_index"),
104
+ },
105
+ {
106
+ name: "ctx_search",
107
+ description: "Query indexed content via FTS5. Pass all questions as an array in ONE call.",
108
+ parameters: {
109
+ type: "object",
110
+ properties: {
111
+ queries: { type: "array", description: "Search queries" },
112
+ source: { type: "string", description: "Optional source filter" },
113
+ sort: { type: "string", description: "relevance | timeline" },
114
+ },
115
+ additionalProperties: true,
116
+ },
117
+ execute: cliRedirect("ctx_search"),
118
+ },
119
+ {
120
+ name: "ctx_fetch_and_index",
121
+ description: "Fetch a URL, chunk it, and index — raw HTML never enters context.",
122
+ parameters: {
123
+ type: "object",
124
+ properties: {
125
+ url: { type: "string", description: "URL to fetch" },
126
+ source: { type: "string", description: "Source label for indexed chunks" },
127
+ },
128
+ required: ["url"],
129
+ additionalProperties: true,
130
+ },
131
+ execute: cliRedirect("ctx_fetch_and_index"),
132
+ },
133
+ {
134
+ name: "ctx_batch_execute",
135
+ description: "Run multiple commands and search queries in ONE call. Primary research tool — replaces 30+ individual calls.",
136
+ parameters: {
137
+ type: "object",
138
+ properties: {
139
+ commands: { type: "array", description: "Array of {label, command} objects" },
140
+ queries: { type: "array", description: "Search queries to run after indexing" },
141
+ },
142
+ additionalProperties: true,
143
+ },
144
+ execute: cliRedirect("ctx_batch_execute"),
145
+ },
146
+ {
147
+ name: "ctx_stats",
148
+ description: "Show context-mode session statistics — token consumption and per-tool breakdown.",
149
+ parameters: {
150
+ type: "object",
151
+ properties: {},
152
+ additionalProperties: true,
153
+ },
154
+ execute: cliRedirect("ctx_stats"),
155
+ },
156
+ {
157
+ name: "ctx_doctor",
158
+ description: "Run context-mode diagnostics — runtimes, hooks, FTS5, plugin registration.",
159
+ parameters: {
160
+ type: "object",
161
+ properties: {},
162
+ additionalProperties: true,
163
+ },
164
+ execute: cliRedirect("ctx_doctor"),
165
+ },
166
+ {
167
+ name: "ctx_upgrade",
168
+ description: "Upgrade context-mode to the latest version.",
169
+ parameters: {
170
+ type: "object",
171
+ properties: {},
172
+ additionalProperties: true,
173
+ },
174
+ execute: cliRedirect("ctx_upgrade"),
175
+ },
176
+ {
177
+ name: "ctx_purge",
178
+ description: "Permanently delete all indexed content and reset session stats. Destructive.",
179
+ parameters: {
180
+ type: "object",
181
+ properties: {},
182
+ additionalProperties: true,
183
+ },
184
+ execute: cliRedirect("ctx_purge"),
185
+ },
186
+ {
187
+ name: "ctx_insight",
188
+ description: "Open the context-mode Insight analytics dashboard in the browser.",
189
+ parameters: {
190
+ type: "object",
191
+ properties: {},
192
+ additionalProperties: true,
193
+ },
194
+ execute: cliRedirect("ctx_insight"),
195
+ },
196
+ ];
197
+ /** Stable list of tool names — used by tests and manifest validation. */
198
+ export const OPENCLAW_TOOL_NAMES = OPENCLAW_TOOL_DEFS.map((def) => def.name);
@@ -28,6 +28,7 @@
28
28
  * - api.registerCommand() for auto-reply slash commands
29
29
  * - Plugins run in-process with the Gateway (trusted code)
30
30
  */
31
+ import type { OpenClawToolDef } from "./openclaw/mcp-tools.js";
31
32
  /** Context for auto-reply command handlers. */
32
33
  interface CommandContext {
33
34
  senderId?: string;
@@ -68,6 +69,14 @@ interface OpenClawPluginApi {
68
69
  }) => void, meta: {
69
70
  commands: string[];
70
71
  }): void;
72
+ /**
73
+ * Register an agent tool (OpenClaw native registerTool) — see
74
+ * refs/platforms/openclaw/docs/plugins/building-plugins.md:116. Optional in
75
+ * the type so we degrade silently on legacy hosts that pre-date this API.
76
+ */
77
+ registerTool?(tool: OpenClawToolDef, opts?: {
78
+ optional?: boolean;
79
+ }): void;
71
80
  logger?: {
72
81
  info: (...args: unknown[]) => void;
73
82
  error: (...args: unknown[]) => void;
@@ -38,6 +38,24 @@ import { extractEvents, extractUserEvents } from "./session/extract.js";
38
38
  import { buildResumeSnapshot } from "./session/snapshot.js";
39
39
  import { WorkspaceRouter } from "./openclaw/workspace-router.js";
40
40
  import { buildNodeCommand } from "./adapters/types.js";
41
+ import { OPENCLAW_TOOL_DEFS } from "./openclaw/mcp-tools.js";
42
+ // ── System-reminder filter (CCv2 — SLICE OClaw-3) ─────────
43
+ // Mirror hooks/userpromptsubmit.mjs:30-33: skip system-generated wrappers
44
+ // so before_model_resolve never inserts spurious user-prompt events.
45
+ const SYSTEM_REMINDER_PREFIXES = [
46
+ "<system-reminder>",
47
+ "<task-notification>",
48
+ "<context_guidance>",
49
+ "<tool-result>",
50
+ ];
51
+ function isSystemReminderMessage(msg) {
52
+ const trimmed = msg.trimStart();
53
+ for (const prefix of SYSTEM_REMINDER_PREFIXES) {
54
+ if (trimmed.startsWith(prefix))
55
+ return true;
56
+ }
57
+ return false;
58
+ }
41
59
  /** Plugin config schema for OpenClaw validation. */
42
60
  const configSchema = {
43
61
  type: "object",
@@ -114,27 +132,46 @@ export default {
114
132
  // Start with temp UUID — session_start will assign the real ID + sessionKey
115
133
  let sessionId = randomUUID();
116
134
  log.info("register() called, sessionId:", sessionId.slice(0, 8));
135
+ // SLICE OClaw-6 (F6 retraction): `resumeInjected` is correctly scoped
136
+ // per-register() singleton — Phase 7 confirmed F6 fabrication-as-tech-debt.
137
+ // Each OpenClaw agent session calls register() once and gets its own
138
+ // closure; the flag prevents double-injection of the resume snapshot in
139
+ // back-to-back before_prompt_build calls within the same session. Do not
140
+ // promote to module scope.
117
141
  let resumeInjected = false;
118
142
  let sessionKey;
119
143
  // Create temp session so after_tool_call events before session_start have a valid row
120
144
  db.ensureSession(sessionId, projectDir);
121
145
  const workspaceRouter = new WorkspaceRouter();
122
- // Load routing instructions synchronously for prompt injection
146
+ // Async init: load routing module + dynamic routing-block factory.
147
+ // SLICE OClaw-2: replaced static readFileSync(configs/openclaw/AGENTS.md)
148
+ // with createRoutingBlock(createToolNamer("openclaw")) so OpenClaw-specific
149
+ // MCP-prefix substitution stays in lockstep with hooks/routing-block.mjs.
123
150
  let routingInstructions = "";
124
- try {
125
- const instructionsPath = resolve(buildDir, "..", "configs", "openclaw", "AGENTS.md");
126
- if (existsSync(instructionsPath)) {
127
- routingInstructions = readFileSync(instructionsPath, "utf-8");
128
- }
129
- }
130
- catch {
131
- // best effort
132
- }
133
- // Async init: load routing module. Hooks await this.
134
151
  const initPromise = (async () => {
135
152
  const routingPath = resolve(buildDir, "..", "hooks", "core", "routing.mjs");
136
153
  const routing = await import(pathToFileURL(routingPath).href);
137
154
  await routing.initSecurity(buildDir);
155
+ try {
156
+ const blockMod = await import(pathToFileURL(resolve(buildDir, "..", "hooks", "routing-block.mjs")).href);
157
+ const namingMod = await import(pathToFileURL(resolve(buildDir, "..", "hooks", "core", "tool-naming.mjs")).href);
158
+ const toolNamer = namingMod.createToolNamer("openclaw");
159
+ routingInstructions = blockMod.createRoutingBlock(toolNamer);
160
+ }
161
+ catch (err) {
162
+ log.warn?.("failed to build dynamic routing block", err);
163
+ // Fallback: legacy disk-read of AGENTS.md (kept for resilience only —
164
+ // primary path is the dynamic factory above).
165
+ try {
166
+ const instructionsPath = resolve(buildDir, "..", "configs", "openclaw", "AGENTS.md");
167
+ if (existsSync(instructionsPath)) {
168
+ routingInstructions = readFileSync(instructionsPath, "utf-8");
169
+ }
170
+ }
171
+ catch {
172
+ // best effort
173
+ }
174
+ }
138
175
  return { routing };
139
176
  })();
140
177
  // ── 1. tool_call:before — Routing enforcement ──────────
@@ -359,6 +396,12 @@ export default {
359
396
  log.debug("before_model_resolve", { hasMessage: !!messageText });
360
397
  if (!messageText)
361
398
  return;
399
+ // SLICE OClaw-3: skip system-generated wrappers so we never
400
+ // misclassify them as user prompts. Mirrors hooks/userpromptsubmit.mjs:30-33.
401
+ if (isSystemReminderMessage(messageText)) {
402
+ log.debug("before_model_resolve[skip-system-reminder]");
403
+ return;
404
+ }
362
405
  const events = extractUserEvents(messageText);
363
406
  for (const ev of events) {
364
407
  db.insertEvent(sid, ev, "PostToolUse");
@@ -389,12 +432,85 @@ export default {
389
432
  }
390
433
  }, { priority: 10 });
391
434
  // ── 8. before_prompt_build — Routing instruction injection ──
392
- if (routingInstructions) {
393
- api.on("before_prompt_build", () => {
394
- log.debug("before_prompt_build[routing]", { hasInstructions: !!routingInstructions });
395
- return { appendSystemContext: routingInstructions };
396
- }, { priority: 5 });
435
+ // SLICE OClaw-2: register unconditionally; routingInstructions is populated
436
+ // asynchronously by initPromise. The closure resolves the latest value at
437
+ // call-time, so the first prompt-build firing after dynamic-import resolution
438
+ // sees the dynamic ROUTING_BLOCK XML (matching hooks/routing-block.mjs).
439
+ api.on("before_prompt_build", () => {
440
+ if (!routingInstructions)
441
+ return undefined;
442
+ log.debug("before_prompt_build[routing]", { hasInstructions: !!routingInstructions });
443
+ // v1.0.107 — visible marker so OpenClaw users can verify the routing
444
+ // block reached the model (Mickey-class verification path; mirrors
445
+ // OpenCode + Pi adapters).
446
+ const marker = `<!-- context-mode: routing block injected (sessionID=${String(sessionId).slice(0, 8)}) -->`;
447
+ return { appendSystemContext: marker + "\n" + routingInstructions };
448
+ }, { priority: 5 });
449
+ // ── 8b. registerTool — Expose 11 ctx_* tools (SLICE OClaw-1) ────
450
+ // Phase 7 audit (v1.0.107-adapter-openclaw.json) flagged severity=CRITICAL:
451
+ // routing block tells agents to call ctx_execute / ctx_search / etc. but
452
+ // nothing called api.registerTool, so the tools didn't exist in the
453
+ // OpenClaw session. This loop fixes that — mirrors swarmvault MCP pattern
454
+ // (refs/plugin-examples/openclaw/swarmvault/packages/engine/src/mcp.ts:46-51).
455
+ if (api.registerTool) {
456
+ for (const def of OPENCLAW_TOOL_DEFS) {
457
+ try {
458
+ api.registerTool(def);
459
+ }
460
+ catch (err) {
461
+ log.warn?.("registerTool failed", { name: def.name }, err);
462
+ }
463
+ }
464
+ log.debug("registerTool[ctx_*]", { count: OPENCLAW_TOOL_DEFS.length });
397
465
  }
466
+ else {
467
+ log.warn?.("api.registerTool unavailable — ctx_* tools not exposed in this OpenClaw build");
468
+ }
469
+ // ── 8c. session_end — Finalize resume snapshot (SLICE OClaw-4) ───
470
+ // OpenClaw fires session_end at session lifecycle boundaries (per
471
+ // refs/platforms/openclaw/docs/plugins/hooks.md:110). We persist a final
472
+ // resume snapshot so a future session_start with resumedFrom can re-attach.
473
+ api.on("session_end", async () => {
474
+ try {
475
+ const sid = sessionId;
476
+ const allEvents = db.getEvents(sid);
477
+ log.debug("session_end", { sessionId: sid.slice(0, 8), events: allEvents.length });
478
+ if (allEvents.length === 0)
479
+ return;
480
+ const freshStats = db.getSessionStats(sid);
481
+ const snapshot = buildResumeSnapshot(allEvents, {
482
+ compactCount: freshStats?.compact_count ?? 0,
483
+ });
484
+ db.upsertResume(sid, snapshot, allEvents.length);
485
+ }
486
+ catch {
487
+ // best effort — never break session shutdown
488
+ }
489
+ });
490
+ // ── 8d. subagent_spawning — Inject routing block (SLICE OClaw-5) ─
491
+ // OpenClaw's subagent lifecycle (hooks.md:116) gives us a chance to seed
492
+ // every spawned subagent with the same routing block the parent agent
493
+ // sees. Without this, subagents have no MCP-routing guidance and degrade
494
+ // back to flooding the context with raw tool output.
495
+ api.on("subagent_spawning", (event) => {
496
+ try {
497
+ const e = (event ?? {});
498
+ const basePrompt = e?.input?.prompt ?? "";
499
+ if (!routingInstructions)
500
+ return undefined;
501
+ const newPrompt = basePrompt
502
+ ? `${basePrompt}\n\n${routingInstructions}`
503
+ : routingInstructions;
504
+ log.debug("subagent_spawning[inject-routing]", {
505
+ basePromptLen: basePrompt.length,
506
+ blockLen: routingInstructions.length,
507
+ });
508
+ return { inputOverride: { ...(e.input ?? {}), prompt: newPrompt } };
509
+ }
510
+ catch {
511
+ return undefined;
512
+ }
513
+ });
398
514
  // ── 9. Context engine — Compaction management ──────────
399
515
  api.registerContextEngine("context-mode", () => ({
400
516
  info: {
@@ -1,10 +1,12 @@
1
1
  /**
2
2
  * OpenCode / KiloCode TypeScript plugin entry point for context-mode.
3
3
  *
4
- * Provides three hooks:
4
+ * Provides five hooks (v1.0.107 — Mickey OC-1..OC-4 follow-up):
5
5
  * - tool.execute.before — Routing enforcement (deny/modify/passthrough)
6
- * - tool.execute.after — Session event capture
7
- * - experimental.session.compacting — Compaction snapshot generation
6
+ * - tool.execute.after — Session event capture + first-fire AGENTS.md scan (OC-4)
7
+ * - experimental.session.compacting — Compaction snapshot + budget-capped auto-injection (OC-3)
8
+ * - experimental.chat.system.transform — ROUTING_BLOCK + resume snapshot injection (OC-1)
9
+ * - chat.message — User-prompt capture w/ CCv2 inline filter (OC-2)
8
10
  *
9
11
  * KiloCode loads this via: import("context-mode") → expects default export
10
12
  * with shape { server: (input) => Promise<Hooks> } (PluginModule).
@@ -14,7 +16,7 @@
14
16
  *
15
17
  * Constraints:
16
18
  * - No SessionStart hook (OpenCode doesn't support it — #14808, #5409)
17
- * - No context injection (canInjectSessionContext: false)
19
+ * - context injection now via chat.system.transform surrogate (OC-1)
18
20
  * - No routing file auto-write (avoid dirtying project trees)
19
21
  * - Session cleanup happens at plugin init (no SessionStart)
20
22
  */
@@ -77,6 +79,28 @@ interface SystemTransformHookInput {
77
79
  interface SystemTransformHookOutput {
78
80
  system: string[];
79
81
  }
82
+ /**
83
+ * OpenCode chat.message hook — verified against
84
+ * refs/platforms/opencode/packages/plugin/src/index.ts:233.
85
+ * input: { sessionID; agent?; model?; messageID?; variant? }
86
+ * output: { message: UserMessage; parts: Part[] }
87
+ * We read text from `parts[*].text` (the orchestrator reference at
88
+ * refs/plugin-examples/opencode/opencode-orchestrator/src/plugin-handlers/
89
+ * chat-message-handler.ts:41-65 uses the same pattern).
90
+ */
91
+ interface ChatMessageHookInput {
92
+ sessionID: string;
93
+ agent?: string;
94
+ messageID?: string;
95
+ }
96
+ interface ChatMessagePart {
97
+ type: string;
98
+ text?: string;
99
+ }
100
+ interface ChatMessageHookOutput {
101
+ message: unknown;
102
+ parts: ChatMessagePart[];
103
+ }
80
104
  /**
81
105
  * Plugin factory. Called once when KiloCode/OpenCode loads the plugin.
82
106
  * Returns an object mapping hook event names to async handler functions.
@@ -87,6 +111,7 @@ interface SystemTransformHookOutput {
87
111
  declare function createContextModePlugin(ctx: PluginContext): Promise<{
88
112
  "tool.execute.before": (input: BeforeHookInput, output: BeforeHookOutput) => Promise<void>;
89
113
  "tool.execute.after": (input: AfterHookInput, output: AfterHookOutput) => Promise<void>;
114
+ "chat.message": (input: ChatMessageHookInput, output: ChatMessageHookOutput) => Promise<void>;
90
115
  "experimental.session.compacting": (input: CompactingHookInput, output: CompactingHookOutput) => Promise<string>;
91
116
  "experimental.chat.system.transform": (input: SystemTransformHookInput, output: SystemTransformHookOutput) => Promise<void>;
92
117
  }>;