@nghyane/arcane 0.1.16 → 0.1.18

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 (74) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/package.json +7 -15
  3. package/src/cli/setup-cli.ts +2 -62
  4. package/src/commands/setup.ts +1 -1
  5. package/src/config/keybindings.ts +1 -4
  6. package/src/config/settings-schema.ts +23 -98
  7. package/src/config/settings.ts +0 -1
  8. package/src/exa/mcp-client.ts +57 -2
  9. package/src/extensibility/custom-tools/types.ts +2 -2
  10. package/src/extensibility/custom-tools/wrapper.ts +1 -1
  11. package/src/extensibility/extensions/wrapper.ts +1 -1
  12. package/src/extensibility/hooks/tool-wrapper.ts +1 -1
  13. package/src/internal-urls/docs-index.generated.ts +1 -2
  14. package/src/internal-urls/index.ts +2 -4
  15. package/src/internal-urls/router.ts +2 -2
  16. package/src/internal-urls/types.ts +2 -2
  17. package/src/mcp/oauth-flow.ts +1 -1
  18. package/src/modes/components/custom-editor.ts +6 -2
  19. package/src/modes/controllers/command-controller.ts +4 -46
  20. package/src/modes/controllers/input-controller.ts +123 -6
  21. package/src/modes/interactive-mode.ts +1 -84
  22. package/src/modes/types.ts +0 -1
  23. package/src/patch/edit-tool.ts +2 -11
  24. package/src/patch/hashline.ts +42 -0
  25. package/src/prompts/agents/explore.md +4 -2
  26. package/src/prompts/agents/librarian.md +4 -6
  27. package/src/prompts/agents/reviewer.md +1 -1
  28. package/src/prompts/agents/task.md +5 -1
  29. package/src/prompts/system/system-prompt.md +29 -18
  30. package/src/prompts/thread-extract.md +16 -0
  31. package/src/prompts/tools/render-mermaid.md +9 -0
  32. package/src/sdk.ts +12 -37
  33. package/src/session/agent-session.ts +5 -10
  34. package/src/session/retry-utils.ts +1 -1
  35. package/src/session/session-index.ts +329 -0
  36. package/src/session/session-manager.ts +0 -30
  37. package/src/session/streaming-edit.ts +1 -36
  38. package/src/slash-commands/builtin-registry.ts +0 -16
  39. package/src/task/index.ts +1 -1
  40. package/src/tools/ask.ts +9 -6
  41. package/src/tools/bash-skill-urls.ts +3 -3
  42. package/src/tools/bash.ts +2 -1
  43. package/src/tools/create-tools.ts +28 -33
  44. package/src/tools/fetch.ts +1 -1
  45. package/src/tools/find-thread.ts +120 -0
  46. package/src/tools/grep.ts +2 -1
  47. package/src/tools/index.ts +5 -0
  48. package/src/tools/python.ts +53 -1
  49. package/src/tools/read-thread.ts +409 -0
  50. package/src/tools/read.ts +4 -3
  51. package/src/tools/render-mermaid.ts +68 -0
  52. package/src/tools/save-memory.ts +182 -0
  53. package/src/tools/write.ts +1 -1
  54. package/src/web/search/index.ts +4 -1
  55. package/src/web/search/provider.ts +3 -0
  56. package/src/web/search/providers/anthropic.ts +1 -0
  57. package/src/web/search/providers/gemini.ts +122 -37
  58. package/src/web/search/providers/kagi.ts +163 -0
  59. package/src/web/search/types.ts +1 -0
  60. package/src/internal-urls/memory-protocol.ts +0 -133
  61. package/src/memories/index.ts +0 -1099
  62. package/src/memories/storage.ts +0 -563
  63. package/src/patch/normative.ts +0 -72
  64. package/src/prompts/memories/consolidation.md +0 -30
  65. package/src/prompts/memories/read_path.md +0 -11
  66. package/src/prompts/memories/stage_one_input.md +0 -6
  67. package/src/prompts/memories/stage_one_system.md +0 -21
  68. package/src/stt/downloader.ts +0 -68
  69. package/src/stt/index.ts +0 -3
  70. package/src/stt/recorder.ts +0 -351
  71. package/src/stt/setup.ts +0 -50
  72. package/src/stt/stt-controller.ts +0 -160
  73. package/src/stt/transcribe.py +0 -70
  74. package/src/stt/transcriber.ts +0 -91
package/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.1.17] - 2026-03-02
6
+
7
+ ### Added
8
+
9
+ - Thread search and retrieval tools (find-thread, read-thread)
10
+ - Save-memory tool for cross-session fact storage
11
+ - Mermaid diagram rendering tool (render-mermaid)
12
+ - Kagi web search provider
13
+ - Codex OAuth authentication support
14
+ - AST auto-inclusion in subagent context
15
+ - Ask tool abort support
16
+
17
+ ### Changed
18
+
19
+ - Improved Gemini provider retry logic
20
+ - Enhanced hashline tab handling
21
+
22
+ ### Removed
23
+
24
+ - Memory system (replaced by thread/save-memory tools)
25
+
5
26
  ## [0.1.14] - 2026-03-02
6
27
 
7
28
  ### Removed
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@nghyane/arcane",
4
- "version": "0.1.16",
4
+ "version": "0.1.18",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/nghyane/arcane",
7
7
  "author": "Can Bölük",
@@ -44,12 +44,12 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@mozilla/readability": "0.6.0",
47
- "@nghyane/arcane-stats": "^0.1.9",
48
- "@nghyane/arcane-agent": "^0.1.12",
49
- "@nghyane/arcane-ai": "^0.1.9",
50
- "@nghyane/arcane-natives": "^0.1.7",
51
- "@nghyane/arcane-tui": "^0.1.11",
52
- "@nghyane/arcane-utils": "^0.1.6",
47
+ "@nghyane/arcane-stats": "^0.1.11",
48
+ "@nghyane/arcane-agent": "^0.1.14",
49
+ "@nghyane/arcane-ai": "^0.1.11",
50
+ "@nghyane/arcane-natives": "^0.1.9",
51
+ "@nghyane/arcane-tui": "^0.1.13",
52
+ "@nghyane/arcane-utils": "^0.1.7",
53
53
  "@sinclair/typebox": "^0.34.48",
54
54
  "@xterm/headless": "^6.0.0",
55
55
  "ajv": "^8.18.0",
@@ -242,14 +242,6 @@
242
242
  "types": "./src/mcp/transports/*.ts",
243
243
  "import": "./src/mcp/transports/*.ts"
244
244
  },
245
- "./memories": {
246
- "types": "./src/memories/index.ts",
247
- "import": "./src/memories/index.ts"
248
- },
249
- "./memories/*": {
250
- "types": "./src/memories/*.ts",
251
- "import": "./src/memories/*.ts"
252
- },
253
245
  "./modes": {
254
246
  "types": "./src/modes/index.ts",
255
247
  "import": "./src/modes/index.ts"
@@ -9,7 +9,7 @@ import { $ } from "bun";
9
9
  import chalk from "chalk";
10
10
  import { theme } from "../theme/theme";
11
11
 
12
- export type SetupComponent = "python" | "stt";
12
+ export type SetupComponent = "python";
13
13
 
14
14
  export interface SetupCommandArgs {
15
15
  component: SetupComponent;
@@ -19,7 +19,7 @@ export interface SetupCommandArgs {
19
19
  };
20
20
  }
21
21
 
22
- const VALID_COMPONENTS: SetupComponent[] = ["python", "stt"];
22
+ const VALID_COMPONENTS: SetupComponent[] = ["python"];
23
23
 
24
24
  const PYTHON_PACKAGES = ["jupyter_kernel_gateway", "ipykernel"];
25
25
  const MANAGED_PYTHON_ENV = getPythonEnvDir();
@@ -206,9 +206,6 @@ export async function runSetupCommand(cmd: SetupCommandArgs): Promise<void> {
206
206
  case "python":
207
207
  await handlePythonSetup(cmd.flags);
208
208
  break;
209
- case "stt":
210
- await handleSttSetup(cmd.flags);
211
- break;
212
209
  }
213
210
  }
214
211
 
@@ -295,60 +292,6 @@ async function handlePythonSetup(flags: { json?: boolean; check?: boolean }): Pr
295
292
  }
296
293
  }
297
294
 
298
- async function handleSttSetup(flags: { json?: boolean; check?: boolean }): Promise<void> {
299
- const { checkDependencies, formatDependencyStatus } = await import("../stt/setup");
300
- const status = await checkDependencies();
301
-
302
- if (flags.json) {
303
- console.log(JSON.stringify(status, null, 2));
304
- if (!status.recorder.available || !status.python.available || !status.whisper.available) process.exit(1);
305
- return;
306
- }
307
-
308
- console.log(formatDependencyStatus(status));
309
-
310
- if (status.recorder.available && status.python.available && status.whisper.available) {
311
- console.log(chalk.green(`\n${theme.status.success} Speech-to-text is ready`));
312
- return;
313
- }
314
-
315
- if (flags.check) {
316
- process.exit(1);
317
- }
318
-
319
- if (!status.python.available) {
320
- console.error(chalk.red(`\n${theme.status.error} Python not found`));
321
- console.error(chalk.dim("Install Python 3.8+ and ensure it's in your PATH"));
322
- process.exit(1);
323
- }
324
-
325
- if (!status.recorder.available) {
326
- console.error(chalk.yellow(`\n${theme.status.warning} No recording tool found`));
327
- console.error(chalk.dim(status.recorder.installHint));
328
- }
329
-
330
- if (!status.whisper.available) {
331
- console.log(chalk.dim(`\nInstalling openai-whisper...`));
332
- const { resolvePython } = await import("../stt/transcriber");
333
- const pythonCmd = resolvePython()!;
334
- const result = await $`${pythonCmd} -m pip install -q openai-whisper`.nothrow();
335
- if (result.exitCode !== 0) {
336
- console.error(chalk.red(`\n${theme.status.error} Failed to install openai-whisper`));
337
- console.error(chalk.dim("Try manually: pip install openai-whisper"));
338
- process.exit(1);
339
- }
340
- }
341
-
342
- const recheck = await checkDependencies();
343
- if (recheck.recorder.available && recheck.python.available && recheck.whisper.available) {
344
- console.log(chalk.green(`\n${theme.status.success} Speech-to-text is ready`));
345
- } else {
346
- console.error(chalk.red(`\n${theme.status.error} Setup incomplete`));
347
- console.log(formatDependencyStatus(recheck));
348
- process.exit(1);
349
- }
350
- }
351
-
352
295
  /**
353
296
  * Print setup command help.
354
297
  */
@@ -360,7 +303,6 @@ ${chalk.bold("Usage:")}
360
303
 
361
304
  ${chalk.bold("Components:")}
362
305
  python Install Jupyter kernel dependencies for Python code execution
363
- stt Install speech-to-text dependencies (openai-whisper, recording tools)
364
306
  Packages: ${PYTHON_PACKAGES.join(", ")}
365
307
 
366
308
  ${chalk.bold("Options:")}
@@ -369,8 +311,6 @@ ${chalk.bold("Options:")}
369
311
 
370
312
  ${chalk.bold("Examples:")}
371
313
  ${APP_NAME} setup python Install Python execution dependencies
372
- ${APP_NAME} setup stt Install speech-to-text dependencies
373
- ${APP_NAME} setup stt --check Check if STT dependencies are available
374
314
  ${APP_NAME} setup python --check Check if Python execution is available
375
315
  `);
376
316
  }
@@ -5,7 +5,7 @@ import { Args, Command, Flags, renderCommandHelp } from "@nghyane/arcane-utils/c
5
5
  import { runSetupCommand, type SetupCommandArgs, type SetupComponent } from "../cli/setup-cli";
6
6
  import { initTheme } from "../theme/theme";
7
7
 
8
- const COMPONENTS: SetupComponent[] = ["python", "stt"];
8
+ const COMPONENTS: SetupComponent[] = ["python"];
9
9
 
10
10
  export default class Setup extends Command {
11
11
  static description = "Install dependencies for optional features";
@@ -34,8 +34,7 @@ export type AppAction =
34
34
  | "newSession"
35
35
  | "tree"
36
36
  | "fork"
37
- | "resume"
38
- | "toggleSTT";
37
+ | "resume";
39
38
 
40
39
  /**
41
40
  * All configurable actions.
@@ -73,7 +72,6 @@ export const DEFAULT_APP_KEYBINDINGS: Record<AppAction, KeyId | KeyId[]> = {
73
72
  tree: [],
74
73
  fork: [],
75
74
  resume: [],
76
- toggleSTT: "alt+h",
77
75
  };
78
76
 
79
77
  /**
@@ -106,7 +104,6 @@ const APP_ACTIONS: AppAction[] = [
106
104
  "tree",
107
105
  "fork",
108
106
  "resume",
109
- "toggleSTT",
110
107
  ];
111
108
 
112
109
  function isAppAction(action: string): action is AppAction {
@@ -204,7 +204,7 @@ export const SETTINGS_SCHEMA = {
204
204
  steeringMode: {
205
205
  type: "enum",
206
206
  values: ["all", "one-at-a-time"] as const,
207
- default: "one-at-a-time",
207
+ default: "all",
208
208
  ui: {
209
209
  tab: "agent",
210
210
  label: "Steering mode",
@@ -214,7 +214,7 @@ export const SETTINGS_SCHEMA = {
214
214
  followUpMode: {
215
215
  type: "enum",
216
216
  values: ["all", "one-at-a-time"] as const,
217
- default: "one-at-a-time",
217
+ default: "all",
218
218
  ui: {
219
219
  tab: "agent",
220
220
  label: "Follow-up mode",
@@ -253,15 +253,6 @@ export const SETTINGS_SCHEMA = {
253
253
  submenu: true,
254
254
  },
255
255
  },
256
- normativeRewrite: {
257
- type: "boolean",
258
- default: false,
259
- ui: {
260
- tab: "agent",
261
- label: "Normative rewrite",
262
- description: "Rewrite tool call arguments to normalized format in session history",
263
- },
264
- },
265
256
  readLineNumbers: {
266
257
  type: "boolean",
267
258
  default: false,
@@ -345,33 +336,6 @@ export const SETTINGS_SCHEMA = {
345
336
  },
346
337
  "branchSummary.reserveTokens": { type: "number", default: 16384 },
347
338
 
348
- // ─────────────────────────────────────────────────────────────────────────
349
- // Memories settings
350
- // ─────────────────────────────────────────────────────────────────────────
351
- "memories.enabled": {
352
- type: "boolean",
353
- default: false,
354
- ui: {
355
- tab: "agent",
356
- label: "Memories",
357
- description: "Enable autonomous memory extraction and consolidation",
358
- },
359
- },
360
- "memories.maxRolloutsPerStartup": { type: "number", default: 64 },
361
- "memories.maxRolloutAgeDays": { type: "number", default: 30 },
362
- "memories.minRolloutIdleHours": { type: "number", default: 12 },
363
- "memories.threadScanLimit": { type: "number", default: 300 },
364
- "memories.maxRawMemoriesForGlobal": { type: "number", default: 200 },
365
- "memories.stage1Concurrency": { type: "number", default: 8 },
366
- "memories.stage1LeaseSeconds": { type: "number", default: 120 },
367
- "memories.stage1RetryDelaySeconds": { type: "number", default: 120 },
368
- "memories.phase2LeaseSeconds": { type: "number", default: 180 },
369
- "memories.phase2RetryDelaySeconds": { type: "number", default: 180 },
370
- "memories.phase2HeartbeatSeconds": { type: "number", default: 30 },
371
- "memories.rolloutPayloadPercent": { type: "number", default: 0.7 },
372
- "memories.fallbackTokenLimit": { type: "number", default: 16000 },
373
- "memories.summaryInjectionTokenLimit": { type: "number", default: 5000 },
374
-
375
339
  // ─────────────────────────────────────────────────────────────────────────
376
340
  // Retry settings
377
341
  // ─────────────────────────────────────────────────────────────────────────
@@ -468,6 +432,25 @@ export const SETTINGS_SCHEMA = {
468
432
  submenu: true,
469
433
  },
470
434
  },
435
+ "astGrep.enabled": {
436
+ type: "boolean",
437
+ default: false,
438
+ ui: { tab: "tools", label: "AST Grep", description: "Enable ast_grep tool for structural code search" },
439
+ },
440
+ "astEdit.enabled": {
441
+ type: "boolean",
442
+ default: false,
443
+ ui: { tab: "tools", label: "AST Edit", description: "Enable ast_edit tool for structural code rewrites" },
444
+ },
445
+ "renderMermaid.enabled": {
446
+ type: "boolean",
447
+ default: true,
448
+ ui: {
449
+ tab: "tools",
450
+ label: "Render Mermaid",
451
+ description: "Enable the render_mermaid tool for ASCII diagram output",
452
+ },
453
+ },
471
454
  "notebook.enabled": {
472
455
  type: "boolean",
473
456
  default: true,
@@ -594,7 +577,7 @@ export const SETTINGS_SCHEMA = {
594
577
  type: "boolean",
595
578
  default: true,
596
579
  ui: {
597
- tab: "display",
580
+ tab: "input",
598
581
  label: "Auto-resize images",
599
582
  description: "Resize large images to 2000x2000 max for better model compatibility",
600
583
  },
@@ -602,7 +585,7 @@ export const SETTINGS_SCHEMA = {
602
585
  "images.blockImages": {
603
586
  type: "boolean",
604
587
  default: false,
605
- ui: { tab: "display", label: "Block images", description: "Prevent images from being sent to LLM providers" },
588
+ ui: { tab: "input", label: "Block images", description: "Prevent images from being sent to LLM providers" },
606
589
  },
607
590
 
608
591
  // ─────────────────────────────────────────────────────────────────────────
@@ -804,36 +787,6 @@ export const SETTINGS_SCHEMA = {
804
787
  },
805
788
  },
806
789
 
807
- // ─────────────────────────────────────────────────────────────────────────
808
- // STT settings
809
- // ─────────────────────────────────────────────────────────────────────────
810
- "stt.enabled": {
811
- type: "boolean",
812
- default: false,
813
- ui: { tab: "input", label: "Speech-to-text", description: "Enable speech-to-text input via microphone" },
814
- },
815
- "stt.language": {
816
- type: "string",
817
- default: "en",
818
- ui: {
819
- tab: "input",
820
- label: "STT language",
821
- description: "Language code for transcription (e.g., en, es, fr)",
822
- submenu: true,
823
- },
824
- },
825
- "stt.modelName": {
826
- type: "enum",
827
- values: ["tiny", "tiny.en", "base", "base.en", "small", "small.en", "medium", "medium.en", "large"] as const,
828
- default: "base.en",
829
- ui: {
830
- tab: "input",
831
- label: "STT model",
832
- description: "Whisper model size (larger = more accurate but slower)",
833
- submenu: true,
834
- },
835
- },
836
-
837
790
  // ─────────────────────────────────────────────────────────────────────────
838
791
  // Edit settings
839
792
  // ─────────────────────────────────────────────────────────────────────────
@@ -1061,24 +1014,6 @@ export interface RetrySettings {
1061
1014
  baseDelayMs: number;
1062
1015
  }
1063
1016
 
1064
- export interface MemoriesSettings {
1065
- enabled: boolean;
1066
- maxRolloutsPerStartup: number;
1067
- maxRolloutAgeDays: number;
1068
- minRolloutIdleHours: number;
1069
- threadScanLimit: number;
1070
- maxRawMemoriesForGlobal: number;
1071
- stage1Concurrency: number;
1072
- stage1LeaseSeconds: number;
1073
- stage1RetryDelaySeconds: number;
1074
- phase2LeaseSeconds: number;
1075
- phase2RetryDelaySeconds: number;
1076
- phase2HeartbeatSeconds: number;
1077
- rolloutPayloadPercent: number;
1078
- fallbackTokenLimit: number;
1079
- summaryInjectionTokenLimit: number;
1080
- }
1081
-
1082
1017
  export interface TodoCompletionSettings {
1083
1018
  enabled: boolean;
1084
1019
  maxReminders: number;
@@ -1135,14 +1070,6 @@ export interface ThinkingBudgetsSettings {
1135
1070
  high: number;
1136
1071
  }
1137
1072
 
1138
- export interface SttSettings {
1139
- enabled: boolean;
1140
- language: string | undefined;
1141
- modelName: string;
1142
- whisperPath: string | undefined;
1143
- modelPath: string | undefined;
1144
- }
1145
-
1146
1073
  export interface BashInterceptorRule {
1147
1074
  pattern: string;
1148
1075
  flags?: string;
@@ -1156,14 +1083,12 @@ export interface GroupTypeMap {
1156
1083
  compaction: CompactionSettings;
1157
1084
  contextPromotion: ContextPromotionSettings;
1158
1085
  retry: RetrySettings;
1159
- memories: MemoriesSettings;
1160
1086
  branchSummary: BranchSummarySettings;
1161
1087
  skills: SkillsSettings;
1162
1088
  ttsr: TtsrSettings;
1163
1089
  exa: ExaSettings;
1164
1090
  statusLine: StatusLineSettings;
1165
1091
  thinkingBudgets: ThinkingBudgetsSettings;
1166
- stt: SttSettings;
1167
1092
  modelRoles: Record<string, string>;
1168
1093
  }
1169
1094
 
@@ -42,7 +42,6 @@ export type {
42
42
  ExaSettings,
43
43
  GroupPrefix,
44
44
  GroupTypeMap,
45
- MemoriesSettings,
46
45
  RetrySettings,
47
46
  SettingPath,
48
47
  SettingValue,
@@ -17,6 +17,61 @@ export function findApiKey(): string | null {
17
17
  return $env.EXA_API_KEY;
18
18
  }
19
19
 
20
+ function asRecord(value: unknown): Record<string, unknown> | null {
21
+ if (typeof value !== "object" || value === null) return null;
22
+ return value as Record<string, unknown>;
23
+ }
24
+
25
+ function parseJsonContent(text: string): unknown | null {
26
+ try {
27
+ return JSON.parse(text);
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Normalize tools/call payloads across MCP servers.
35
+ *
36
+ * Exa currently returns different shapes depending on deployment/environment:
37
+ * - direct payload in result
38
+ * - structured payload under result.structuredContent / result.data / result.result
39
+ * - JSON payload embedded as text in result.content[]
40
+ */
41
+ function normalizeMcpToolPayload(payload: unknown): unknown {
42
+ const candidates: unknown[] = [];
43
+ const root = asRecord(payload);
44
+
45
+ if (root) {
46
+ if (root.structuredContent !== undefined) candidates.push(root.structuredContent);
47
+ if (root.data !== undefined) candidates.push(root.data);
48
+ if (root.result !== undefined) candidates.push(root.result);
49
+ candidates.push(root);
50
+
51
+ const content = root.content;
52
+ if (Array.isArray(content)) {
53
+ for (const item of content) {
54
+ const part = asRecord(item);
55
+ if (!part) continue;
56
+ const text = part.text;
57
+ if (typeof text !== "string" || text.trim().length === 0) continue;
58
+ const parsed = parseJsonContent(text);
59
+ if (parsed !== null) candidates.push(parsed);
60
+ }
61
+ }
62
+ } else {
63
+ candidates.push(payload);
64
+ }
65
+
66
+ for (const candidate of candidates) {
67
+ if (isSearchResponse(candidate)) {
68
+ return candidate;
69
+ }
70
+ }
71
+
72
+ return payload;
73
+ }
74
+
20
75
  /** Fetch available tools from Exa MCP */
21
76
  export async function fetchExaTools(apiKey: string | null, toolNames: string[]): Promise<MCPTool[]> {
22
77
  const params = new URLSearchParams();
@@ -66,7 +121,7 @@ export async function callExaTool(
66
121
  throw new Error(`MCP error: ${response.error.message}`);
67
122
  }
68
123
 
69
- return response.result;
124
+ return normalizeMcpToolPayload(response.result);
70
125
  }
71
126
 
72
127
  /** Call a tool on Websets MCP */
@@ -86,7 +141,7 @@ export async function callWebsetsTool(
86
141
  throw new Error(`MCP error: ${response.error.message}`);
87
142
  }
88
143
 
89
- return response.result;
144
+ return normalizeMcpToolPayload(response.result);
90
145
  }
91
146
 
92
147
  /** Parse Exa markdown format into SearchResponse */
@@ -178,10 +178,10 @@ export interface CustomTool<TParams extends TSchema = TSchema, TDetails = any> {
178
178
  execute(
179
179
  toolCallId: string,
180
180
  params: Static<TParams>,
181
- onUpdate: AgentToolUpdateCallback<TDetails, TParams> | undefined,
181
+ onUpdate: AgentToolUpdateCallback<TDetails> | undefined,
182
182
  ctx: CustomToolContext,
183
183
  signal?: AbortSignal,
184
- ): Promise<AgentToolResult<TDetails, TParams>>;
184
+ ): Promise<AgentToolResult<TDetails>>;
185
185
 
186
186
  /** Called on session lifecycle events - use to reconstruct state or cleanup resources */
187
187
  onSession?: (event: CustomToolSessionEvent, ctx: CustomToolContext) => void | Promise<void>;
@@ -26,7 +26,7 @@ export class CustomToolAdapter<TParams extends TSchema = TSchema, TDetails = any
26
26
  toolCallId: string,
27
27
  params: Static<TParams>,
28
28
  signal?: AbortSignal,
29
- onUpdate?: AgentToolUpdateCallback<TDetails, TParams>,
29
+ onUpdate?: AgentToolUpdateCallback<TDetails>,
30
30
  context?: CustomToolContext,
31
31
  ) {
32
32
  return this.tool.execute(toolCallId, params, onUpdate, context ?? this.getContext(), signal);
@@ -96,7 +96,7 @@ export class ExtensionToolWrapper<TParameters extends TSchema = TSchema, TDetail
96
96
  toolCallId: string,
97
97
  params: Static<TParameters>,
98
98
  signal?: AbortSignal,
99
- onUpdate?: AgentToolUpdateCallback<TDetails, TParameters>,
99
+ onUpdate?: AgentToolUpdateCallback<TDetails>,
100
100
  context?: AgentToolContext,
101
101
  ) {
102
102
  // Emit tool_call event - extensions can block execution
@@ -34,7 +34,7 @@ export class HookToolWrapper<TParameters extends TSchema = TSchema, TDetails = u
34
34
  toolCallId: string,
35
35
  params: Static<TParameters>,
36
36
  signal?: AbortSignal,
37
- onUpdate?: AgentToolUpdateCallback<TDetails, TParameters>,
37
+ onUpdate?: AgentToolUpdateCallback<TDetails>,
38
38
  context?: AgentToolContext,
39
39
  ) {
40
40
  // Emit tool_call event - hooks can block execution