@dexto/core 1.6.0 → 1.6.2

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 (188) hide show
  1. package/dist/agent/DextoAgent.cjs +79 -5
  2. package/dist/agent/DextoAgent.d.ts +24 -2
  3. package/dist/agent/DextoAgent.d.ts.map +1 -1
  4. package/dist/agent/DextoAgent.js +79 -5
  5. package/dist/agent/agent-options.d.ts +6 -1
  6. package/dist/agent/agent-options.d.ts.map +1 -1
  7. package/dist/agent/schemas.d.ts +18 -18
  8. package/dist/approval/manager.cjs +87 -27
  9. package/dist/approval/manager.d.ts +10 -1
  10. package/dist/approval/manager.d.ts.map +1 -1
  11. package/dist/approval/manager.js +87 -27
  12. package/dist/approval/schemas.cjs +22 -8
  13. package/dist/approval/schemas.d.ts +276 -102
  14. package/dist/approval/schemas.d.ts.map +1 -1
  15. package/dist/approval/schemas.js +22 -8
  16. package/dist/context/manager.cjs +2 -2
  17. package/dist/context/manager.d.ts +2 -1
  18. package/dist/context/manager.d.ts.map +1 -1
  19. package/dist/context/manager.js +2 -2
  20. package/dist/context/types.d.ts +3 -2
  21. package/dist/context/types.d.ts.map +1 -1
  22. package/dist/events/index.d.ts +26 -13
  23. package/dist/events/index.d.ts.map +1 -1
  24. package/dist/hooks/index.d.ts +1 -1
  25. package/dist/hooks/index.d.ts.map +1 -1
  26. package/dist/hooks/types.d.ts +1 -22
  27. package/dist/hooks/types.d.ts.map +1 -1
  28. package/dist/llm/executor/provider-options.cjs +223 -28
  29. package/dist/llm/executor/provider-options.d.ts +3 -37
  30. package/dist/llm/executor/provider-options.d.ts.map +1 -1
  31. package/dist/llm/executor/provider-options.js +227 -27
  32. package/dist/llm/executor/stream-processor.cjs +57 -34
  33. package/dist/llm/executor/stream-processor.d.ts +12 -4
  34. package/dist/llm/executor/stream-processor.d.ts.map +1 -1
  35. package/dist/llm/executor/stream-processor.js +55 -32
  36. package/dist/llm/executor/turn-executor.cjs +66 -44
  37. package/dist/llm/executor/turn-executor.d.ts +3 -3
  38. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  39. package/dist/llm/executor/turn-executor.js +56 -34
  40. package/dist/llm/formatters/vercel.cjs +15 -3
  41. package/dist/llm/formatters/vercel.d.ts +1 -0
  42. package/dist/llm/formatters/vercel.d.ts.map +1 -1
  43. package/dist/llm/formatters/vercel.js +15 -3
  44. package/dist/llm/index.cjs +8 -0
  45. package/dist/llm/index.d.ts +2 -1
  46. package/dist/llm/index.d.ts.map +1 -1
  47. package/dist/llm/index.js +7 -0
  48. package/dist/llm/providers/local/schemas.d.ts +2 -2
  49. package/dist/llm/providers/openrouter-model-registry.cjs +66 -11
  50. package/dist/llm/providers/openrouter-model-registry.d.ts +26 -0
  51. package/dist/llm/providers/openrouter-model-registry.d.ts.map +1 -1
  52. package/dist/llm/providers/openrouter-model-registry.js +65 -11
  53. package/dist/llm/reasoning/anthropic-betas.cjs +31 -0
  54. package/dist/llm/reasoning/anthropic-betas.d.ts +3 -0
  55. package/dist/llm/reasoning/anthropic-betas.d.ts.map +1 -0
  56. package/dist/llm/reasoning/anthropic-betas.js +7 -0
  57. package/dist/llm/reasoning/anthropic-thinking.cjs +79 -0
  58. package/dist/llm/reasoning/anthropic-thinking.d.ts +15 -0
  59. package/dist/llm/reasoning/anthropic-thinking.d.ts.map +1 -0
  60. package/dist/llm/reasoning/anthropic-thinking.js +52 -0
  61. package/dist/llm/reasoning/openai-reasoning-effort.cjs +86 -0
  62. package/dist/llm/reasoning/openai-reasoning-effort.d.ts +5 -0
  63. package/dist/llm/reasoning/openai-reasoning-effort.d.ts.map +1 -0
  64. package/dist/llm/reasoning/openai-reasoning-effort.js +61 -0
  65. package/dist/llm/reasoning/profile.cjs +113 -0
  66. package/dist/llm/reasoning/profile.d.ts +13 -0
  67. package/dist/llm/reasoning/profile.d.ts.map +1 -0
  68. package/dist/llm/reasoning/profile.js +92 -0
  69. package/dist/llm/reasoning/profiles/anthropic.cjs +61 -0
  70. package/dist/llm/reasoning/profiles/anthropic.d.ts +8 -0
  71. package/dist/llm/reasoning/profiles/anthropic.d.ts.map +1 -0
  72. package/dist/llm/reasoning/profiles/anthropic.js +45 -0
  73. package/dist/llm/reasoning/profiles/bedrock.cjs +54 -0
  74. package/dist/llm/reasoning/profiles/bedrock.d.ts +3 -0
  75. package/dist/llm/reasoning/profiles/bedrock.d.ts.map +1 -0
  76. package/dist/llm/reasoning/profiles/bedrock.js +36 -0
  77. package/dist/llm/reasoning/profiles/google.cjs +45 -0
  78. package/dist/llm/reasoning/profiles/google.d.ts +9 -0
  79. package/dist/llm/reasoning/profiles/google.d.ts.map +1 -0
  80. package/dist/llm/reasoning/profiles/google.js +21 -0
  81. package/dist/llm/reasoning/profiles/openai-compatible.cjs +39 -0
  82. package/dist/llm/reasoning/profiles/openai-compatible.d.ts +3 -0
  83. package/dist/llm/reasoning/profiles/openai-compatible.d.ts.map +1 -0
  84. package/dist/llm/reasoning/profiles/openai-compatible.js +16 -0
  85. package/dist/llm/reasoning/profiles/openai.cjs +41 -0
  86. package/dist/llm/reasoning/profiles/openai.d.ts +3 -0
  87. package/dist/llm/reasoning/profiles/openai.d.ts.map +1 -0
  88. package/dist/llm/reasoning/profiles/openai.js +18 -0
  89. package/dist/llm/reasoning/profiles/openrouter.cjs +83 -0
  90. package/dist/llm/reasoning/profiles/openrouter.d.ts +10 -0
  91. package/dist/llm/reasoning/profiles/openrouter.d.ts.map +1 -0
  92. package/dist/llm/reasoning/profiles/openrouter.js +59 -0
  93. package/dist/llm/reasoning/profiles/shared.cjs +80 -0
  94. package/dist/llm/reasoning/profiles/shared.d.ts +25 -0
  95. package/dist/llm/reasoning/profiles/shared.d.ts.map +1 -0
  96. package/dist/llm/reasoning/profiles/shared.js +53 -0
  97. package/dist/llm/reasoning/profiles/vertex.cjs +46 -0
  98. package/dist/llm/reasoning/profiles/vertex.d.ts +3 -0
  99. package/dist/llm/reasoning/profiles/vertex.d.ts.map +1 -0
  100. package/dist/llm/reasoning/profiles/vertex.js +23 -0
  101. package/dist/llm/registry/auto-update.cjs +18 -0
  102. package/dist/llm/registry/auto-update.d.ts.map +1 -1
  103. package/dist/llm/registry/auto-update.js +18 -0
  104. package/dist/llm/registry/index.cjs +126 -26
  105. package/dist/llm/registry/index.d.ts +48 -4
  106. package/dist/llm/registry/index.d.ts.map +1 -1
  107. package/dist/llm/registry/index.js +136 -28
  108. package/dist/llm/registry/models.generated.cjs +5198 -59
  109. package/dist/llm/registry/models.generated.d.ts +1893 -76
  110. package/dist/llm/registry/models.generated.d.ts.map +1 -1
  111. package/dist/llm/registry/models.generated.js +5196 -58
  112. package/dist/llm/registry/sync.cjs +72 -1
  113. package/dist/llm/registry/sync.d.ts +21 -1
  114. package/dist/llm/registry/sync.d.ts.map +1 -1
  115. package/dist/llm/registry/sync.js +72 -1
  116. package/dist/llm/resolver.cjs +13 -1
  117. package/dist/llm/resolver.d.ts.map +1 -1
  118. package/dist/llm/resolver.js +13 -1
  119. package/dist/llm/schemas.cjs +75 -14
  120. package/dist/llm/schemas.d.ts +84 -27
  121. package/dist/llm/schemas.d.ts.map +1 -1
  122. package/dist/llm/schemas.js +75 -14
  123. package/dist/llm/services/factory.cjs +55 -8
  124. package/dist/llm/services/factory.d.ts +1 -1
  125. package/dist/llm/services/factory.d.ts.map +1 -1
  126. package/dist/llm/services/factory.js +58 -8
  127. package/dist/llm/services/vercel.cjs +2 -2
  128. package/dist/llm/services/vercel.js +2 -2
  129. package/dist/llm/types.d.ts +9 -0
  130. package/dist/llm/types.d.ts.map +1 -1
  131. package/dist/logger/default-logger-factory.d.ts +12 -12
  132. package/dist/logger/v2/dexto-logger.cjs +35 -0
  133. package/dist/logger/v2/dexto-logger.d.ts +19 -0
  134. package/dist/logger/v2/dexto-logger.d.ts.map +1 -1
  135. package/dist/logger/v2/dexto-logger.js +35 -0
  136. package/dist/logger/v2/schemas.d.ts +6 -6
  137. package/dist/logger/v2/test-utils.cjs +2 -0
  138. package/dist/logger/v2/test-utils.d.ts.map +1 -1
  139. package/dist/logger/v2/test-utils.js +2 -0
  140. package/dist/logger/v2/types.d.ts +14 -1
  141. package/dist/logger/v2/types.d.ts.map +1 -1
  142. package/dist/mcp/schemas.d.ts +15 -15
  143. package/dist/memory/schemas.d.ts +4 -4
  144. package/dist/prompts/index.cjs +9 -0
  145. package/dist/prompts/index.d.ts +1 -0
  146. package/dist/prompts/index.d.ts.map +1 -1
  147. package/dist/prompts/index.js +10 -0
  148. package/dist/prompts/prompt-manager.cjs +2 -0
  149. package/dist/prompts/prompt-manager.d.ts.map +1 -1
  150. package/dist/prompts/prompt-manager.js +2 -0
  151. package/dist/prompts/providers/config-prompt-provider.cjs +11 -1
  152. package/dist/prompts/providers/config-prompt-provider.d.ts.map +1 -1
  153. package/dist/prompts/providers/config-prompt-provider.js +11 -1
  154. package/dist/prompts/schemas.cjs +2 -2
  155. package/dist/prompts/schemas.d.ts +7 -7
  156. package/dist/prompts/schemas.js +2 -2
  157. package/dist/prompts/types.d.ts +6 -2
  158. package/dist/prompts/types.d.ts.map +1 -1
  159. package/dist/systemPrompt/in-built-prompts.cjs +5 -5
  160. package/dist/systemPrompt/in-built-prompts.d.ts +1 -1
  161. package/dist/systemPrompt/in-built-prompts.d.ts.map +1 -1
  162. package/dist/systemPrompt/in-built-prompts.js +5 -5
  163. package/dist/systemPrompt/schemas.d.ts +5 -5
  164. package/dist/systemPrompt/types.d.ts +11 -0
  165. package/dist/systemPrompt/types.d.ts.map +1 -1
  166. package/dist/tools/display-types.d.ts +10 -0
  167. package/dist/tools/display-types.d.ts.map +1 -1
  168. package/dist/tools/index.cjs +3 -1
  169. package/dist/tools/index.d.ts +1 -0
  170. package/dist/tools/index.d.ts.map +1 -1
  171. package/dist/tools/index.js +1 -0
  172. package/dist/tools/presentation.cjs +49 -0
  173. package/dist/tools/presentation.d.ts +11 -0
  174. package/dist/tools/presentation.d.ts.map +1 -0
  175. package/dist/tools/presentation.js +24 -0
  176. package/dist/tools/tool-manager.cjs +389 -136
  177. package/dist/tools/tool-manager.d.ts +36 -24
  178. package/dist/tools/tool-manager.d.ts.map +1 -1
  179. package/dist/tools/tool-manager.js +389 -136
  180. package/dist/tools/types.d.ts +134 -55
  181. package/dist/tools/types.d.ts.map +1 -1
  182. package/dist/utils/path.cjs +10 -1
  183. package/dist/utils/path.d.ts +5 -2
  184. package/dist/utils/path.d.ts.map +1 -1
  185. package/dist/utils/path.js +10 -1
  186. package/dist/utils/service-initializer.d.ts +1 -0
  187. package/dist/utils/service-initializer.d.ts.map +1 -1
  188. package/package.json +7 -5
@@ -89,6 +89,7 @@ let _ToolManager = class _ToolManager {
89
89
  agentEventBus;
90
90
  toolPolicies;
91
91
  toolExecutionContextFactory;
92
+ contributorContextFactory;
92
93
  // Hook support - set after construction to avoid circular dependencies
93
94
  hookManager;
94
95
  sessionManager;
@@ -165,6 +166,20 @@ let _ToolManager = class _ToolManager {
165
166
  }
166
167
  this.invalidateCache();
167
168
  }
169
+ addTools(tools) {
170
+ const added = [];
171
+ for (const tool of tools) {
172
+ if (this.agentTools.has(tool.id)) {
173
+ continue;
174
+ }
175
+ this.agentTools.set(tool.id, tool);
176
+ added.push(tool.id);
177
+ }
178
+ if (added.length > 0) {
179
+ this.invalidateCache();
180
+ }
181
+ return added;
182
+ }
168
183
  setToolExecutionContextFactory(factory) {
169
184
  this.toolExecutionContextFactory = factory;
170
185
  }
@@ -254,6 +269,37 @@ let _ToolManager = class _ToolManager {
254
269
  );
255
270
  this.logger.debug(`Auto-approve tools: ${normalized.join(", ")}`);
256
271
  }
272
+ /**
273
+ * Add session-level auto-approve tools.
274
+ * Merges into the existing list instead of replacing it.
275
+ *
276
+ * @param sessionId The session ID
277
+ * @param autoApproveTools Array of tool names to auto-approve (e.g., ['bash_exec', 'mcp--read_file'])
278
+ */
279
+ addSessionAutoApproveTools(sessionId, autoApproveTools) {
280
+ if (autoApproveTools.length === 0) {
281
+ return;
282
+ }
283
+ const normalized = autoApproveTools.map(
284
+ (pattern) => this.normalizeToolPolicyPattern(pattern)
285
+ );
286
+ const existing = this.sessionAutoApproveTools.get(sessionId) ?? [];
287
+ const merged = [...existing];
288
+ const seen = new Set(existing);
289
+ for (const toolName of normalized) {
290
+ if (seen.has(toolName)) {
291
+ continue;
292
+ }
293
+ merged.push(toolName);
294
+ seen.add(toolName);
295
+ }
296
+ const actuallyAdded = Math.max(0, merged.length - existing.length);
297
+ this.sessionAutoApproveTools.set(sessionId, merged);
298
+ this.logger.info(
299
+ `Session auto-approve tools updated for '${sessionId}': +${actuallyAdded} tools`
300
+ );
301
+ this.logger.debug(`Auto-approve tools: ${merged.join(", ")}`);
302
+ }
257
303
  /**
258
304
  * Set session-level auto-approve tools chosen by the user.
259
305
  */
@@ -447,16 +493,175 @@ let _ToolManager = class _ToolManager {
447
493
  });
448
494
  }
449
495
  // ==================== Pattern Approval Helpers ====================
496
+ getToolApprovalPatternKeyFn(toolName) {
497
+ const tool = this.agentTools.get(toolName);
498
+ return tool?.approval?.patternKey;
499
+ }
500
+ getToolSuggestApprovalPatternsFn(toolName) {
501
+ const tool = this.agentTools.get(toolName);
502
+ return tool?.approval?.suggestPatterns;
503
+ }
504
+ getToolApprovalOverrideFn(toolName) {
505
+ const tool = this.agentTools.get(toolName);
506
+ return tool?.approval?.override;
507
+ }
508
+ getToolApprovalOnGrantedFn(toolName) {
509
+ const tool = this.agentTools.get(toolName);
510
+ return tool?.approval?.onGranted;
511
+ }
512
+ getToolPreviewFn(toolName) {
513
+ const tool = this.agentTools.get(toolName);
514
+ return tool?.presentation?.preview;
515
+ }
516
+ getToolDescribeHeaderFn(toolName) {
517
+ const tool = this.agentTools.get(toolName);
518
+ return tool?.presentation?.describeHeader;
519
+ }
520
+ getToolDescribeArgsFn(toolName) {
521
+ const tool = this.agentTools.get(toolName);
522
+ return tool?.presentation?.describeArgs;
523
+ }
524
+ getToolDescribeResultFn(toolName) {
525
+ const tool = this.agentTools.get(toolName);
526
+ return tool?.presentation?.describeResult;
527
+ }
528
+ buildGenericToolPresentationSnapshot(toolName) {
529
+ const toTitleCase = (name) => name.replace(/[_-]+/g, " ").split(" ").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
530
+ const isMcp = toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX);
531
+ const fallbackTitle = (() => {
532
+ if (!isMcp) {
533
+ return toTitleCase(toolName);
534
+ }
535
+ const actualToolName = toolName.substring(_ToolManager.MCP_TOOL_PREFIX.length);
536
+ const parts = actualToolName.split("--");
537
+ const toolPart = parts.length >= 2 ? parts.slice(1).join("--") : actualToolName;
538
+ return toTitleCase(toolPart);
539
+ })();
540
+ const snapshot = {
541
+ version: 1,
542
+ source: {
543
+ type: toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX) ? "mcp" : "local"
544
+ },
545
+ header: {
546
+ title: fallbackTitle
547
+ }
548
+ };
549
+ if (snapshot.source?.type === "mcp") {
550
+ const actualToolName = toolName.substring(_ToolManager.MCP_TOOL_PREFIX.length);
551
+ const parts = actualToolName.split("--");
552
+ if (parts.length >= 2 && parts[0]) {
553
+ snapshot.source.mcpServerName = parts[0];
554
+ }
555
+ }
556
+ return snapshot;
557
+ }
558
+ getToolPresentationSnapshotForToolCallEvent(toolName, args, toolCallId, sessionId) {
559
+ const fallback = this.buildGenericToolPresentationSnapshot(toolName);
560
+ if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
561
+ return fallback;
562
+ }
563
+ const describeHeader = this.getToolDescribeHeaderFn(toolName);
564
+ const describeArgs = this.getToolDescribeArgsFn(toolName);
565
+ if (!describeHeader && !describeArgs) {
566
+ return fallback;
567
+ }
568
+ try {
569
+ const validatedArgs = this.validateLocalToolArgs(toolName, args);
570
+ const context = this.buildToolExecutionContext({ sessionId, toolCallId });
571
+ const isPromiseLike = (value) => {
572
+ if (typeof value !== "object" || value === null) {
573
+ return false;
574
+ }
575
+ return typeof value.then === "function";
576
+ };
577
+ let nextSnapshot = fallback;
578
+ if (describeHeader) {
579
+ const header = describeHeader(validatedArgs, context);
580
+ if (!isPromiseLike(header) && header) {
581
+ nextSnapshot = {
582
+ ...nextSnapshot,
583
+ header: { ...nextSnapshot.header, ...header }
584
+ };
585
+ }
586
+ }
587
+ if (describeArgs) {
588
+ const argsPresentation = describeArgs(validatedArgs, context);
589
+ if (!isPromiseLike(argsPresentation) && argsPresentation) {
590
+ nextSnapshot = {
591
+ ...nextSnapshot,
592
+ args: argsPresentation
593
+ };
594
+ }
595
+ }
596
+ return nextSnapshot;
597
+ } catch (error) {
598
+ this.logger.debug(
599
+ `Tool presentation snapshot generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
600
+ );
601
+ return fallback;
602
+ }
603
+ }
604
+ async getToolPresentationSnapshotForCall(toolName, args, toolCallId, sessionId) {
605
+ const fallback = this.buildGenericToolPresentationSnapshot(toolName);
606
+ if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
607
+ return fallback;
608
+ }
609
+ const describeHeader = this.getToolDescribeHeaderFn(toolName);
610
+ const describeArgs = this.getToolDescribeArgsFn(toolName);
611
+ if (!describeHeader && !describeArgs) {
612
+ return fallback;
613
+ }
614
+ try {
615
+ const context = this.buildToolExecutionContext({ sessionId, toolCallId });
616
+ const describedHeader = describeHeader ? await Promise.resolve(describeHeader(args, context)) : null;
617
+ const describedArgs = describeArgs ? await Promise.resolve(describeArgs(args, context)) : null;
618
+ return {
619
+ ...fallback,
620
+ ...describedHeader ? { header: { ...fallback.header, ...describedHeader } } : {},
621
+ ...describedArgs ? { args: describedArgs } : {}
622
+ };
623
+ } catch (error) {
624
+ this.logger.debug(
625
+ `Tool presentation snapshot generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
626
+ );
627
+ return fallback;
628
+ }
629
+ }
630
+ async augmentSnapshotWithResult(toolName, snapshot, result, args, toolCallId, sessionId) {
631
+ if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
632
+ return snapshot;
633
+ }
634
+ const describeResult = this.getToolDescribeResultFn(toolName);
635
+ if (!describeResult) {
636
+ return snapshot;
637
+ }
638
+ try {
639
+ const context = this.buildToolExecutionContext({ sessionId, toolCallId });
640
+ const resultPresentation = await Promise.resolve(describeResult(result, args, context));
641
+ if (!resultPresentation) {
642
+ return snapshot;
643
+ }
644
+ return {
645
+ ...snapshot,
646
+ result: resultPresentation
647
+ };
648
+ } catch (error) {
649
+ this.logger.debug(
650
+ `Tool result presentation snapshot generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
651
+ );
652
+ return snapshot;
653
+ }
654
+ }
450
655
  getToolPatternKey(toolName, args) {
451
656
  if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
452
657
  return null;
453
658
  }
454
- const tool = this.agentTools.get(toolName);
455
- if (!tool?.getApprovalPatternKey) {
659
+ const getPatternKey = this.getToolApprovalPatternKeyFn(toolName);
660
+ if (!getPatternKey) {
456
661
  return null;
457
662
  }
458
663
  try {
459
- return tool.getApprovalPatternKey(args);
664
+ return getPatternKey(args);
460
665
  } catch (error) {
461
666
  this.logger.debug(
462
667
  `Pattern key generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
@@ -468,12 +673,12 @@ let _ToolManager = class _ToolManager {
468
673
  if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
469
674
  return void 0;
470
675
  }
471
- const tool = this.agentTools.get(toolName);
472
- if (!tool?.suggestApprovalPatterns) {
676
+ const suggestPatterns = this.getToolSuggestApprovalPatternsFn(toolName);
677
+ if (!suggestPatterns) {
473
678
  return void 0;
474
679
  }
475
680
  try {
476
- const patterns = tool.suggestApprovalPatterns(args);
681
+ const patterns = suggestPatterns(args);
477
682
  return patterns.length > 0 ? patterns : void 0;
478
683
  } catch (error) {
479
684
  this.logger.debug(
@@ -499,8 +704,10 @@ let _ToolManager = class _ToolManager {
499
704
  if (request.sessionId !== sessionId) {
500
705
  return false;
501
706
  }
502
- const metadata = request.metadata;
503
- return metadata.toolName === toolName;
707
+ if (request.metadata.toolName !== toolName) {
708
+ return false;
709
+ }
710
+ return request.metadata.directoryAccess === void 0;
504
711
  },
505
712
  { rememberChoice: false }
506
713
  // Don't propagate remember choice to auto-approved requests
@@ -519,8 +726,7 @@ let _ToolManager = class _ToolManager {
519
726
  if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
520
727
  return;
521
728
  }
522
- const tool = this.agentTools.get(toolName);
523
- const getPatternKey = tool?.getApprovalPatternKey;
729
+ const getPatternKey = this.getToolApprovalPatternKeyFn(toolName);
524
730
  if (!getPatternKey) {
525
731
  return;
526
732
  }
@@ -532,17 +738,20 @@ let _ToolManager = class _ToolManager {
532
738
  if (request.sessionId !== sessionId) {
533
739
  return false;
534
740
  }
535
- const metadata = request.metadata;
536
- if (metadata.toolName !== toolName) {
741
+ if (request.metadata.toolName !== toolName) {
537
742
  return false;
538
743
  }
539
- const args = metadata.args;
744
+ if (request.metadata.directoryAccess !== void 0) {
745
+ return false;
746
+ }
747
+ const args = request.metadata.args;
540
748
  if (typeof args !== "object" || args === null) {
541
749
  return false;
542
750
  }
751
+ const argsRecord = args;
543
752
  let patternKey;
544
753
  try {
545
- patternKey = getPatternKey(args);
754
+ patternKey = getPatternKey(argsRecord);
546
755
  } catch (error) {
547
756
  this.logger.debug(
548
757
  `Pattern key generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
@@ -562,42 +771,68 @@ let _ToolManager = class _ToolManager {
562
771
  }
563
772
  }
564
773
  /**
565
- * Auto-approve pending directory access requests that match a newly approved directory access request.
566
- *
567
- * This handles the case where parallel file operations request directory approval concurrently.
774
+ * Auto-approve pending tool approval requests that are now covered by a remembered directory.
775
+ * Called after a user selects "remember directory" for a directory-access prompt.
568
776
  */
569
- autoApprovePendingDirectoryAccessRequests(options) {
777
+ autoApprovePendingDirectoryRequests(toolName, sessionId) {
570
778
  const count = this.approvalManager.autoApprovePendingRequests(
571
779
  (request) => {
572
- if (request.type !== import_types3.ApprovalType.DIRECTORY_ACCESS) {
780
+ if (request.type !== import_types3.ApprovalType.TOOL_APPROVAL) {
573
781
  return false;
574
782
  }
575
- if (request.sessionId !== options.sessionId) {
783
+ if (request.sessionId !== sessionId) {
576
784
  return false;
577
785
  }
578
- const metadata = request.metadata;
579
- if (typeof metadata?.parentDir !== "string" || metadata.parentDir !== options.parentDir) {
786
+ if (request.metadata.toolName !== toolName) {
580
787
  return false;
581
788
  }
582
- if (options.rememberDirectory) {
583
- return true;
584
- }
585
- if (typeof metadata?.operation !== "string" || typeof metadata?.toolName !== "string") {
789
+ const directoryAccess = request.metadata.directoryAccess;
790
+ if (!directoryAccess) {
586
791
  return false;
587
792
  }
588
- return metadata.operation === options.operation && metadata.toolName === options.toolName;
793
+ return this.approvalManager.isDirectorySessionApproved(directoryAccess.parentDir);
589
794
  },
590
795
  { rememberDirectory: false }
591
796
  );
592
797
  if (count > 0) {
593
798
  this.logger.info(
594
- `Auto-approved ${count} parallel request(s) for directory '${options.parentDir}' after directory access was approved`
799
+ 'Auto-approved parallel request(s) after user selected "remember directory"',
800
+ { count, toolName }
595
801
  );
596
802
  }
597
803
  }
598
804
  getMcpManager() {
599
805
  return this.mcpManager;
600
806
  }
807
+ setContributorContextFactory(factory) {
808
+ this.contributorContextFactory = factory ?? void 0;
809
+ }
810
+ async buildContributorContext() {
811
+ const baseWorkspace = this.currentWorkspace ?? null;
812
+ const baseContext = {
813
+ mcpManager: this.mcpManager,
814
+ workspace: baseWorkspace
815
+ };
816
+ if (!this.contributorContextFactory) {
817
+ return baseContext;
818
+ }
819
+ try {
820
+ const overrides = await this.contributorContextFactory() ?? {};
821
+ const workspace = overrides.workspace !== void 0 ? overrides.workspace : baseWorkspace;
822
+ const environment = overrides.environment !== void 0 ? overrides.environment : baseContext.environment;
823
+ const mcpManager = overrides.mcpManager ?? baseContext.mcpManager;
824
+ return {
825
+ mcpManager,
826
+ workspace,
827
+ ...environment !== void 0 ? { environment } : {}
828
+ };
829
+ } catch (error) {
830
+ this.logger.warn(
831
+ `Failed to build contributor context: ${error instanceof Error ? error.message : String(error)}`
832
+ );
833
+ return baseContext;
834
+ }
835
+ }
601
836
  /**
602
837
  * Get all MCP tools (delegates to mcpManager.getAllTools())
603
838
  * This provides access to MCP tools while maintaining separation of concerns
@@ -617,7 +852,7 @@ let _ToolManager = class _ToolManager {
617
852
  };
618
853
  return this.toolExecutionContextFactory(baseContext);
619
854
  }
620
- validateLocalToolArgsOrThrow(toolName, args) {
855
+ validateLocalToolArgs(toolName, args) {
621
856
  if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
622
857
  return args;
623
858
  }
@@ -738,15 +973,22 @@ let _ToolManager = class _ToolManager {
738
973
  async executeTool(toolName, args, toolCallId, sessionId, abortSignal) {
739
974
  const { toolArgs: rawToolArgs, meta } = (0, import_tool_call_metadata.extractToolCallMeta)(args);
740
975
  let toolArgs = rawToolArgs;
976
+ const callDescription = typeof meta.callDescription === "string" ? meta.callDescription : typeof rawToolArgs.description === "string" ? rawToolArgs.description : void 0;
741
977
  const backgroundTasksEnabled = (0, import_env.isBackgroundTasksEnabled)();
742
- const toolDisplayName = this.agentTools.get(toolName)?.displayName;
743
978
  this.logger.debug(`\u{1F527} Tool execution requested: '${toolName}' (toolCallId: ${toolCallId})`);
744
979
  this.logger.debug(`Tool args: ${JSON.stringify(toolArgs, null, 2)}`);
745
980
  if (sessionId) {
981
+ const presentationSnapshot = this.getToolPresentationSnapshotForToolCallEvent(
982
+ toolName,
983
+ toolArgs,
984
+ toolCallId,
985
+ sessionId
986
+ );
746
987
  this.agentEventBus.emit("llm:tool-call", {
747
988
  toolName,
748
- ...toolDisplayName !== void 0 && { toolDisplayName },
989
+ presentationSnapshot,
749
990
  args: toolArgs,
991
+ ...callDescription !== void 0 && { callDescription },
750
992
  callId: toolCallId,
751
993
  sessionId
752
994
  });
@@ -754,13 +996,14 @@ let _ToolManager = class _ToolManager {
754
996
  const {
755
997
  requireApproval,
756
998
  approvalStatus,
757
- args: validatedToolArgs
999
+ args: validatedToolArgs,
1000
+ presentationSnapshot: callSnapshot
758
1001
  } = await this.handleToolApproval(
759
1002
  toolName,
760
1003
  toolArgs,
761
1004
  toolCallId,
762
1005
  sessionId,
763
- meta.callDescription
1006
+ callDescription
764
1007
  );
765
1008
  toolArgs = validatedToolArgs;
766
1009
  this.logger.debug(`\u2705 Tool execution approved: ${toolName}`);
@@ -794,7 +1037,7 @@ let _ToolManager = class _ToolManager {
794
1037
  );
795
1038
  toolArgs = modifiedPayload.args;
796
1039
  try {
797
- toolArgs = this.validateLocalToolArgsOrThrow(toolName, toolArgs);
1040
+ toolArgs = this.validateLocalToolArgs(toolName, toolArgs);
798
1041
  } catch (error) {
799
1042
  this.logger.error(
800
1043
  `Post-hook validation failed for tool '${toolName}': a beforeToolCall hook may have set invalid args`
@@ -917,9 +1160,17 @@ let _ToolManager = class _ToolManager {
917
1160
  );
918
1161
  result = modifiedPayload.result;
919
1162
  }
1163
+ const presentationSnapshot = await this.augmentSnapshotWithResult(
1164
+ toolName,
1165
+ callSnapshot,
1166
+ result,
1167
+ toolArgs,
1168
+ toolCallId,
1169
+ sessionId
1170
+ );
920
1171
  return {
921
1172
  result,
922
- ...toolDisplayName !== void 0 && { toolDisplayName },
1173
+ ...presentationSnapshot !== void 0 && { presentationSnapshot },
923
1174
  ...requireApproval && { requireApproval, approvalStatus }
924
1175
  };
925
1176
  } catch (error) {
@@ -1044,124 +1295,113 @@ let _ToolManager = class _ToolManager {
1044
1295
  );
1045
1296
  }
1046
1297
  /**
1047
- * Check if a tool has a custom approval override and handle it.
1048
- * Tools can implement getApprovalOverride() to request specialized approval flows
1049
- * (e.g., directory access approval for file tools) instead of default tool confirmation.
1050
- *
1051
- * @param toolName Tool name
1052
- * @param args The tool arguments
1053
- * @param sessionId Optional session ID
1054
- * @returns { handled: true } if custom approval was processed, { handled: false } to continue normal flow
1298
+ * Handle tool approval flow. Checks various precedence levels to determine
1299
+ * if a tool should be auto-approved, denied, or requires manual approval.
1055
1300
  */
1056
- async checkCustomApprovalOverride(toolName, args, toolCallId, sessionId) {
1057
- if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
1058
- return { handled: false };
1059
- }
1060
- const tool = this.agentTools.get(toolName);
1061
- if (!tool?.getApprovalOverride) {
1062
- return { handled: false };
1063
- }
1064
- const context = this.buildToolExecutionContext({ sessionId, toolCallId });
1065
- const approvalRequest = await tool.getApprovalOverride(args, context);
1066
- if (!approvalRequest) {
1067
- return { handled: false };
1068
- }
1069
- this.logger.debug(
1070
- `Tool '${toolName}' requested custom approval: type=${approvalRequest.type}`
1071
- );
1072
- if (sessionId && !approvalRequest.sessionId) {
1073
- approvalRequest.sessionId = sessionId;
1074
- }
1075
- const response = await this.approvalManager.requestApproval(approvalRequest);
1076
- if (response.status === import_types3.ApprovalStatus.APPROVED) {
1077
- if (tool.onApprovalGranted) {
1078
- tool.onApprovalGranted(response, context, approvalRequest);
1079
- }
1080
- if (approvalRequest.type === import_types3.ApprovalType.DIRECTORY_ACCESS) {
1081
- const metadata = approvalRequest.metadata;
1082
- const parentDir = typeof metadata?.parentDir === "string" ? metadata.parentDir : null;
1083
- const operation = typeof metadata?.operation === "string" ? metadata.operation : null;
1084
- if (parentDir && operation) {
1085
- const data = response.data;
1086
- const rememberDirectory = data?.rememberDirectory ?? false;
1087
- this.autoApprovePendingDirectoryAccessRequests({
1088
- parentDir,
1089
- operation,
1090
- sessionId,
1091
- toolName,
1092
- rememberDirectory
1093
- });
1094
- }
1095
- }
1301
+ async handleToolApproval(toolName, args, toolCallId, sessionId, callDescription) {
1302
+ if (this.isInAlwaysDenyList(toolName)) {
1096
1303
  this.logger.info(
1097
- `Custom approval granted for '${toolName}', type=${approvalRequest.type}, session=${sessionId ?? "global"}`
1304
+ `Tool '${toolName}' is in static deny list \u2013 blocking execution (session: ${sessionId ?? "global"})`
1098
1305
  );
1099
- return { handled: true };
1306
+ throw import_errors.ToolError.executionDenied(toolName, sessionId);
1100
1307
  }
1101
- this.logger.info(
1102
- `Custom approval denied for '${toolName}', type=${approvalRequest.type}, reason=${response.reason ?? "unknown"}`
1308
+ const validatedArgs = this.validateLocalToolArgs(toolName, args);
1309
+ const presentationSnapshot = await this.getToolPresentationSnapshotForCall(
1310
+ toolName,
1311
+ validatedArgs,
1312
+ toolCallId,
1313
+ sessionId
1103
1314
  );
1104
- if (approvalRequest.type === "directory_access") {
1105
- const metadata = approvalRequest.metadata;
1106
- throw import_errors.ToolError.directoryAccessDenied(
1107
- metadata?.parentDir ?? "unknown directory",
1108
- sessionId
1109
- );
1315
+ let directoryAccess;
1316
+ let directoryAccessApprovalRequest;
1317
+ if (!toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
1318
+ const getApprovalOverride = this.getToolApprovalOverrideFn(toolName);
1319
+ if (getApprovalOverride) {
1320
+ const context = this.buildToolExecutionContext({ sessionId, toolCallId });
1321
+ const approvalRequest = await getApprovalOverride(validatedArgs, context);
1322
+ if (approvalRequest) {
1323
+ if (approvalRequest.type === import_types3.ApprovalType.DIRECTORY_ACCESS) {
1324
+ const metadata = approvalRequest.metadata;
1325
+ if (typeof metadata !== "object" || metadata === null || typeof metadata.path !== "string" || typeof metadata.parentDir !== "string" || typeof metadata.operation !== "string" || typeof metadata.toolName !== "string") {
1326
+ throw import_errors.ToolError.configInvalid(
1327
+ `Tool '${toolName}' returned invalid directory access metadata`
1328
+ );
1329
+ }
1330
+ directoryAccess = metadata;
1331
+ directoryAccessApprovalRequest = approvalRequest;
1332
+ } else {
1333
+ this.logger.debug(
1334
+ `Tool '${toolName}' requested custom approval: type=${approvalRequest.type}`
1335
+ );
1336
+ if (sessionId && !approvalRequest.sessionId) {
1337
+ approvalRequest.sessionId = sessionId;
1338
+ }
1339
+ const response = await this.approvalManager.requestApproval(approvalRequest);
1340
+ if (response.status === import_types3.ApprovalStatus.APPROVED) {
1341
+ const onGranted = this.getToolApprovalOnGrantedFn(toolName);
1342
+ if (onGranted) {
1343
+ await Promise.resolve(
1344
+ onGranted(response, context, approvalRequest)
1345
+ );
1346
+ }
1347
+ this.logger.info(
1348
+ `Custom approval granted for '${toolName}', type=${approvalRequest.type}, session=${sessionId ?? "global"}`
1349
+ );
1350
+ return {
1351
+ requireApproval: true,
1352
+ approvalStatus: "approved",
1353
+ args: validatedArgs,
1354
+ presentationSnapshot
1355
+ };
1356
+ }
1357
+ this.logger.info(
1358
+ `Custom approval denied for '${toolName}', type=${approvalRequest.type}, reason=${response.reason ?? "unknown"}`
1359
+ );
1360
+ throw import_errors.ToolError.executionDenied(toolName, sessionId);
1361
+ }
1362
+ }
1363
+ }
1110
1364
  }
1111
- throw import_errors.ToolError.executionDenied(toolName, sessionId);
1112
- }
1113
- /**
1114
- * Handle tool approval flow. Checks various precedence levels to determine
1115
- * if a tool should be auto-approved, denied, or requires manual approval.
1116
- */
1117
- async handleToolApproval(toolName, args, toolCallId, sessionId, callDescription) {
1118
- const validatedArgs = this.validateLocalToolArgsOrThrow(toolName, args);
1119
1365
  const quickResult = await this.tryQuickApprovalResolution(
1120
1366
  toolName,
1121
1367
  validatedArgs,
1122
- toolCallId,
1123
- sessionId
1368
+ sessionId,
1369
+ directoryAccess
1124
1370
  );
1125
1371
  if (quickResult !== null) {
1126
- return { ...quickResult, args: validatedArgs };
1372
+ return { ...quickResult, args: validatedArgs, presentationSnapshot };
1127
1373
  }
1128
1374
  const manualResult = await this.requestManualApproval(
1129
1375
  toolName,
1130
1376
  validatedArgs,
1131
1377
  toolCallId,
1132
1378
  sessionId,
1133
- callDescription
1379
+ directoryAccess,
1380
+ directoryAccessApprovalRequest,
1381
+ callDescription,
1382
+ presentationSnapshot
1134
1383
  );
1135
- return { ...manualResult, args: validatedArgs };
1384
+ return { ...manualResult, args: validatedArgs, presentationSnapshot };
1136
1385
  }
1137
1386
  /**
1138
1387
  * Try to resolve tool approval quickly based on policies and cached permissions.
1139
1388
  * Returns null if manual approval is needed.
1140
1389
  *
1141
1390
  * Precedence order (highest to lowest):
1142
- * 1. Static deny list (security - always blocks)
1143
- * 2. Custom approval override (tool-specific approval flows)
1144
- * 3. Session auto-approve (skill allowed-tools)
1145
- * 4. Static allow list
1146
- * 5. Dynamic "remembered" allowed list
1147
- * 6. Tool approval patterns
1148
- * 7. Approval mode (auto-approve/auto-deny)
1391
+ * 1. Directory access requirement (outside-root paths)
1392
+ * 2. Session auto-approve (skill allowed-tools)
1393
+ * 3. Static allow list
1394
+ * 4. Dynamic "remembered" allowed list
1395
+ * 5. Tool approval patterns
1396
+ * 6. Approval mode (auto-approve/auto-deny)
1149
1397
  */
1150
- async tryQuickApprovalResolution(toolName, args, toolCallId, sessionId) {
1151
- if (this.isInAlwaysDenyList(toolName)) {
1152
- this.logger.info(
1153
- `Tool '${toolName}' is in static deny list \u2013 blocking execution (session: ${sessionId ?? "global"})`
1154
- );
1155
- throw import_errors.ToolError.executionDenied(toolName, sessionId);
1156
- }
1157
- const customApprovalResult = await this.checkCustomApprovalOverride(
1158
- toolName,
1159
- args,
1160
- toolCallId,
1161
- sessionId
1162
- );
1163
- if (customApprovalResult.handled) {
1164
- return { requireApproval: true, approvalStatus: "approved" };
1398
+ async tryQuickApprovalResolution(toolName, args, sessionId, directoryAccess) {
1399
+ if (directoryAccess) {
1400
+ if (this.approvalMode === "auto-approve") {
1401
+ this.approvalManager.addApprovedDirectory(directoryAccess.parentDir, "once");
1402
+ return { requireApproval: false };
1403
+ }
1404
+ return null;
1165
1405
  }
1166
1406
  if (sessionId && this.isToolAutoApprovedForSession(sessionId, toolName)) {
1167
1407
  this.logger.info(
@@ -1202,12 +1442,11 @@ let _ToolManager = class _ToolManager {
1202
1442
  * Request manual approval from the user for a tool execution.
1203
1443
  * Generates preview, sends approval request, and handles the response.
1204
1444
  */
1205
- async requestManualApproval(toolName, args, toolCallId, sessionId, callDescription) {
1445
+ async requestManualApproval(toolName, args, toolCallId, sessionId, directoryAccess, directoryAccessApprovalRequest, callDescription, presentationSnapshot) {
1206
1446
  this.logger.info(
1207
1447
  `Tool approval requested for ${toolName}, sessionId: ${sessionId ?? "global"}`
1208
1448
  );
1209
1449
  try {
1210
- const toolDisplayName = this.agentTools.get(toolName)?.displayName;
1211
1450
  const displayPreview = await this.generateToolPreview(
1212
1451
  toolName,
1213
1452
  args,
@@ -1217,14 +1456,24 @@ let _ToolManager = class _ToolManager {
1217
1456
  const suggestedPatterns = this.getToolSuggestedPatterns(toolName, args);
1218
1457
  const response = await this.approvalManager.requestToolApproval({
1219
1458
  toolName,
1220
- ...toolDisplayName !== void 0 && { toolDisplayName },
1459
+ ...presentationSnapshot !== void 0 && { presentationSnapshot },
1221
1460
  toolCallId,
1222
1461
  args,
1223
1462
  ...callDescription !== void 0 && { description: callDescription },
1224
1463
  ...sessionId !== void 0 && { sessionId },
1225
1464
  ...displayPreview !== void 0 && { displayPreview },
1465
+ ...directoryAccess !== void 0 && { directoryAccess },
1226
1466
  ...suggestedPatterns !== void 0 && { suggestedPatterns }
1227
1467
  });
1468
+ if (response.status === import_types3.ApprovalStatus.APPROVED && directoryAccessApprovalRequest !== void 0) {
1469
+ const onGranted = this.getToolApprovalOnGrantedFn(toolName);
1470
+ if (onGranted) {
1471
+ const context = this.buildToolExecutionContext({ sessionId, toolCallId });
1472
+ await Promise.resolve(
1473
+ onGranted(response, context, directoryAccessApprovalRequest)
1474
+ );
1475
+ }
1476
+ }
1228
1477
  if (response.status === import_types3.ApprovalStatus.APPROVED && response.data) {
1229
1478
  await this.handleRememberChoice(toolName, response, sessionId);
1230
1479
  }
@@ -1246,13 +1495,13 @@ let _ToolManager = class _ToolManager {
1246
1495
  * Generate a preview for the tool approval UI if the tool supports it.
1247
1496
  */
1248
1497
  async generateToolPreview(toolName, args, toolCallId, sessionId) {
1249
- const tool = this.agentTools.get(toolName);
1250
- if (!tool?.generatePreview) {
1498
+ const previewFn = this.getToolPreviewFn(toolName);
1499
+ if (!previewFn) {
1251
1500
  return void 0;
1252
1501
  }
1253
1502
  try {
1254
1503
  const context = this.buildToolExecutionContext({ sessionId, toolCallId });
1255
- const preview = await tool.generatePreview(args, context);
1504
+ const preview = await previewFn(args, context);
1256
1505
  this.logger.debug(`Generated preview for ${toolName}`);
1257
1506
  return preview ?? void 0;
1258
1507
  } catch (previewError) {
@@ -1267,13 +1516,14 @@ let _ToolManager = class _ToolManager {
1267
1516
  }
1268
1517
  }
1269
1518
  /**
1270
- * Handle "remember choice" or "remember pattern" when user approves a tool.
1519
+ * Handle "remember" actions when user approves a tool.
1271
1520
  */
1272
1521
  async handleRememberChoice(toolName, response, sessionId) {
1273
1522
  const data = response.data;
1274
1523
  if (!data) return;
1275
1524
  const rememberChoice = data.rememberChoice;
1276
1525
  const rememberPattern = data.rememberPattern;
1526
+ const rememberDirectory = data.rememberDirectory;
1277
1527
  if (rememberChoice) {
1278
1528
  const allowSessionId = sessionId ?? response.sessionId;
1279
1529
  await this.allowedToolsProvider.allowTool(toolName, allowSessionId);
@@ -1281,10 +1531,13 @@ let _ToolManager = class _ToolManager {
1281
1531
  `Tool '${toolName}' added to allowed tools for session '${allowSessionId ?? "global"}' (remember choice selected)`
1282
1532
  );
1283
1533
  this.autoApprovePendingToolRequests(toolName, allowSessionId);
1284
- } else if (rememberPattern && this.agentTools.get(toolName)?.getApprovalPatternKey) {
1534
+ } else if (rememberPattern && this.getToolApprovalPatternKeyFn(toolName)) {
1285
1535
  this.approvalManager.addPattern(toolName, rememberPattern);
1286
1536
  this.logger.info(`Pattern '${rememberPattern}' added for tool '${toolName}' approval`);
1287
1537
  this.autoApprovePendingPatternRequests(toolName, sessionId);
1538
+ } else if (rememberDirectory) {
1539
+ const allowSessionId = sessionId ?? response.sessionId;
1540
+ this.autoApprovePendingDirectoryRequests(toolName, allowSessionId);
1288
1541
  }
1289
1542
  }
1290
1543
  /**