@dexto/core 1.5.6 → 1.5.8

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 (217) hide show
  1. package/dist/agent/DextoAgent.cjs +189 -30
  2. package/dist/agent/DextoAgent.d.ts +44 -9
  3. package/dist/agent/DextoAgent.d.ts.map +1 -1
  4. package/dist/agent/DextoAgent.js +190 -31
  5. package/dist/agent/schemas.cjs +5 -0
  6. package/dist/agent/schemas.d.ts +456 -66
  7. package/dist/agent/schemas.d.ts.map +1 -1
  8. package/dist/agent/schemas.js +5 -0
  9. package/dist/context/manager.cjs +1 -1
  10. package/dist/context/manager.js +1 -1
  11. package/dist/context/utils.cjs +90 -17
  12. package/dist/context/utils.d.ts.map +1 -1
  13. package/dist/context/utils.js +90 -17
  14. package/dist/errors/types.cjs +2 -1
  15. package/dist/errors/types.d.ts +2 -1
  16. package/dist/errors/types.d.ts.map +1 -1
  17. package/dist/errors/types.js +2 -1
  18. package/dist/events/index.cjs +4 -1
  19. package/dist/events/index.d.ts +37 -2
  20. package/dist/events/index.d.ts.map +1 -1
  21. package/dist/events/index.js +4 -1
  22. package/dist/image/types.d.ts +15 -0
  23. package/dist/image/types.d.ts.map +1 -1
  24. package/dist/index.browser.d.ts +1 -1
  25. package/dist/index.browser.d.ts.map +1 -1
  26. package/dist/llm/curation-config.cjs +82 -0
  27. package/dist/llm/curation-config.d.ts +13 -0
  28. package/dist/llm/curation-config.d.ts.map +1 -0
  29. package/dist/llm/curation-config.js +59 -0
  30. package/dist/llm/curation.cjs +57 -0
  31. package/dist/llm/curation.d.ts +16 -0
  32. package/dist/llm/curation.d.ts.map +1 -0
  33. package/dist/llm/curation.js +34 -0
  34. package/dist/llm/error-codes.cjs +1 -0
  35. package/dist/llm/error-codes.d.ts +1 -0
  36. package/dist/llm/error-codes.d.ts.map +1 -1
  37. package/dist/llm/error-codes.js +1 -0
  38. package/dist/llm/errors.cjs +16 -1
  39. package/dist/llm/errors.d.ts +15 -8
  40. package/dist/llm/errors.d.ts.map +1 -1
  41. package/dist/llm/errors.js +16 -1
  42. package/dist/llm/executor/provider-options.cjs +1 -1
  43. package/dist/llm/executor/provider-options.js +1 -1
  44. package/dist/llm/executor/turn-executor.cjs +35 -2
  45. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  46. package/dist/llm/executor/turn-executor.js +35 -2
  47. package/dist/llm/index.cjs +14 -3
  48. package/dist/llm/index.d.ts +3 -1
  49. package/dist/llm/index.d.ts.map +1 -1
  50. package/dist/llm/index.js +13 -2
  51. package/dist/llm/registry/auto-update.cjs +263 -0
  52. package/dist/llm/registry/auto-update.d.ts +27 -0
  53. package/dist/llm/registry/auto-update.d.ts.map +1 -0
  54. package/dist/llm/registry/auto-update.js +227 -0
  55. package/dist/llm/registry/index.cjs +806 -0
  56. package/dist/llm/{registry.d.ts → registry/index.d.ts} +67 -13
  57. package/dist/llm/registry/index.d.ts.map +1 -0
  58. package/dist/llm/registry/index.js +756 -0
  59. package/dist/llm/registry/models.generated.cjs +4861 -0
  60. package/dist/llm/registry/models.generated.d.ts +431 -0
  61. package/dist/llm/registry/models.generated.d.ts.map +1 -0
  62. package/dist/llm/registry/models.generated.js +4838 -0
  63. package/dist/llm/registry/models.manual.cjs +44 -0
  64. package/dist/llm/registry/models.manual.d.ts +22 -0
  65. package/dist/llm/registry/models.manual.d.ts.map +1 -0
  66. package/dist/llm/registry/models.manual.js +21 -0
  67. package/dist/llm/registry/sync.cjs +354 -0
  68. package/dist/llm/registry/sync.d.ts +41 -0
  69. package/dist/llm/registry/sync.d.ts.map +1 -0
  70. package/dist/llm/registry/sync.js +328 -0
  71. package/dist/llm/resolver.cjs +29 -7
  72. package/dist/llm/resolver.d.ts +1 -1
  73. package/dist/llm/resolver.d.ts.map +1 -1
  74. package/dist/llm/resolver.js +31 -8
  75. package/dist/llm/schemas.cjs +13 -1
  76. package/dist/llm/schemas.d.ts +59 -59
  77. package/dist/llm/schemas.d.ts.map +1 -1
  78. package/dist/llm/schemas.js +14 -1
  79. package/dist/llm/services/factory.cjs +43 -27
  80. package/dist/llm/services/factory.d.ts +20 -1
  81. package/dist/llm/services/factory.d.ts.map +1 -1
  82. package/dist/llm/services/factory.js +44 -28
  83. package/dist/llm/services/test-utils.integration.cjs +5 -1
  84. package/dist/llm/services/test-utils.integration.d.ts.map +1 -1
  85. package/dist/llm/services/test-utils.integration.js +5 -1
  86. package/dist/llm/services/vercel.cjs +4 -1
  87. package/dist/llm/services/vercel.d.ts +1 -0
  88. package/dist/llm/services/vercel.d.ts.map +1 -1
  89. package/dist/llm/services/vercel.js +4 -1
  90. package/dist/llm/types.cjs +5 -2
  91. package/dist/llm/types.d.ts +1 -1
  92. package/dist/llm/types.d.ts.map +1 -1
  93. package/dist/llm/types.js +5 -2
  94. package/dist/llm/validation.cjs +1 -1
  95. package/dist/llm/validation.js +1 -1
  96. package/dist/logger/v2/dexto-logger.cjs +4 -0
  97. package/dist/logger/v2/dexto-logger.d.ts +3 -0
  98. package/dist/logger/v2/dexto-logger.d.ts.map +1 -1
  99. package/dist/logger/v2/dexto-logger.js +4 -0
  100. package/dist/logger/v2/types.d.ts +2 -0
  101. package/dist/logger/v2/types.d.ts.map +1 -1
  102. package/dist/mcp/error-codes.cjs +1 -0
  103. package/dist/mcp/error-codes.d.ts +1 -0
  104. package/dist/mcp/error-codes.d.ts.map +1 -1
  105. package/dist/mcp/error-codes.js +1 -0
  106. package/dist/mcp/errors.cjs +13 -0
  107. package/dist/mcp/errors.d.ts +7 -0
  108. package/dist/mcp/errors.d.ts.map +1 -1
  109. package/dist/mcp/errors.js +13 -0
  110. package/dist/mcp/manager.cjs +46 -4
  111. package/dist/mcp/manager.d.ts +10 -2
  112. package/dist/mcp/manager.d.ts.map +1 -1
  113. package/dist/mcp/manager.js +46 -4
  114. package/dist/mcp/mcp-client.cjs +89 -5
  115. package/dist/mcp/mcp-client.d.ts +5 -1
  116. package/dist/mcp/mcp-client.d.ts.map +1 -1
  117. package/dist/mcp/mcp-client.js +89 -5
  118. package/dist/mcp/schemas.cjs +6 -1
  119. package/dist/mcp/schemas.d.ts +1 -1
  120. package/dist/mcp/schemas.d.ts.map +1 -1
  121. package/dist/mcp/schemas.js +6 -1
  122. package/dist/mcp/types.d.ts +5 -0
  123. package/dist/mcp/types.d.ts.map +1 -1
  124. package/dist/prompts/index.d.ts +1 -1
  125. package/dist/prompts/index.d.ts.map +1 -1
  126. package/dist/prompts/prompt-manager.cjs +90 -4
  127. package/dist/prompts/prompt-manager.d.ts +16 -6
  128. package/dist/prompts/prompt-manager.d.ts.map +1 -1
  129. package/dist/prompts/prompt-manager.js +90 -4
  130. package/dist/prompts/providers/config-prompt-provider.cjs +104 -10
  131. package/dist/prompts/providers/config-prompt-provider.d.ts.map +1 -1
  132. package/dist/prompts/providers/config-prompt-provider.js +105 -11
  133. package/dist/prompts/providers/custom-prompt-provider.cjs +1 -0
  134. package/dist/prompts/providers/custom-prompt-provider.d.ts.map +1 -1
  135. package/dist/prompts/providers/custom-prompt-provider.js +1 -0
  136. package/dist/prompts/providers/mcp-prompt-provider.cjs +1 -0
  137. package/dist/prompts/providers/mcp-prompt-provider.d.ts.map +1 -1
  138. package/dist/prompts/providers/mcp-prompt-provider.js +1 -0
  139. package/dist/prompts/schemas.cjs +28 -2
  140. package/dist/prompts/schemas.d.ts +130 -0
  141. package/dist/prompts/schemas.d.ts.map +1 -1
  142. package/dist/prompts/schemas.js +28 -2
  143. package/dist/prompts/types.d.ts +55 -3
  144. package/dist/prompts/types.d.ts.map +1 -1
  145. package/dist/resources/handlers/filesystem-handler.cjs +25 -0
  146. package/dist/resources/handlers/filesystem-handler.d.ts +1 -0
  147. package/dist/resources/handlers/filesystem-handler.d.ts.map +1 -1
  148. package/dist/resources/handlers/filesystem-handler.js +25 -0
  149. package/dist/session/chat-session.cjs +1 -1
  150. package/dist/session/chat-session.d.ts +1 -1
  151. package/dist/session/chat-session.d.ts.map +1 -1
  152. package/dist/session/chat-session.js +1 -1
  153. package/dist/session/index.d.ts +1 -1
  154. package/dist/session/index.d.ts.map +1 -1
  155. package/dist/session/message-queue.cjs +29 -5
  156. package/dist/session/message-queue.d.ts +3 -1
  157. package/dist/session/message-queue.d.ts.map +1 -1
  158. package/dist/session/message-queue.js +29 -5
  159. package/dist/session/session-manager.cjs +84 -3
  160. package/dist/session/session-manager.d.ts +12 -0
  161. package/dist/session/session-manager.d.ts.map +1 -1
  162. package/dist/session/session-manager.js +74 -3
  163. package/dist/session/types.d.ts +1 -0
  164. package/dist/session/types.d.ts.map +1 -1
  165. package/dist/systemPrompt/contributors.cjs +42 -0
  166. package/dist/systemPrompt/contributors.d.ts +13 -0
  167. package/dist/systemPrompt/contributors.d.ts.map +1 -1
  168. package/dist/systemPrompt/contributors.js +41 -0
  169. package/dist/tools/errors.cjs +7 -3
  170. package/dist/tools/errors.d.ts +5 -1
  171. package/dist/tools/errors.d.ts.map +1 -1
  172. package/dist/tools/errors.js +7 -3
  173. package/dist/tools/internal-tools/constants.cjs +2 -1
  174. package/dist/tools/internal-tools/constants.d.ts +1 -1
  175. package/dist/tools/internal-tools/constants.d.ts.map +1 -1
  176. package/dist/tools/internal-tools/constants.js +2 -1
  177. package/dist/tools/internal-tools/implementations/invoke-skill-tool.cjs +140 -0
  178. package/dist/tools/internal-tools/implementations/invoke-skill-tool.d.ts +24 -0
  179. package/dist/tools/internal-tools/implementations/invoke-skill-tool.d.ts.map +1 -0
  180. package/dist/tools/internal-tools/implementations/invoke-skill-tool.js +117 -0
  181. package/dist/tools/internal-tools/provider.cjs +15 -0
  182. package/dist/tools/internal-tools/provider.d.ts +15 -1
  183. package/dist/tools/internal-tools/provider.d.ts.map +1 -1
  184. package/dist/tools/internal-tools/provider.js +15 -0
  185. package/dist/tools/internal-tools/registry.cjs +6 -0
  186. package/dist/tools/internal-tools/registry.d.ts +35 -1
  187. package/dist/tools/internal-tools/registry.d.ts.map +1 -1
  188. package/dist/tools/internal-tools/registry.js +6 -0
  189. package/dist/tools/schemas.d.ts +1 -1
  190. package/dist/tools/schemas.d.ts.map +1 -1
  191. package/dist/tools/tool-call-metadata.cjs +75 -0
  192. package/dist/tools/tool-call-metadata.d.ts +16 -0
  193. package/dist/tools/tool-call-metadata.d.ts.map +1 -0
  194. package/dist/tools/tool-call-metadata.js +51 -0
  195. package/dist/tools/tool-manager.cjs +481 -103
  196. package/dist/tools/tool-manager.d.ts +131 -9
  197. package/dist/tools/tool-manager.d.ts.map +1 -1
  198. package/dist/tools/tool-manager.js +482 -104
  199. package/dist/utils/api-key-resolver.cjs +5 -2
  200. package/dist/utils/api-key-resolver.d.ts.map +1 -1
  201. package/dist/utils/api-key-resolver.js +5 -2
  202. package/dist/utils/env.cjs +49 -0
  203. package/dist/utils/env.d.ts +4 -0
  204. package/dist/utils/env.d.ts.map +1 -0
  205. package/dist/utils/env.js +24 -0
  206. package/dist/utils/index.cjs +3 -1
  207. package/dist/utils/index.d.ts +1 -0
  208. package/dist/utils/index.d.ts.map +1 -1
  209. package/dist/utils/index.js +1 -0
  210. package/dist/utils/service-initializer.cjs +25 -7
  211. package/dist/utils/service-initializer.d.ts +24 -1
  212. package/dist/utils/service-initializer.d.ts.map +1 -1
  213. package/dist/utils/service-initializer.js +25 -7
  214. package/package.json +6 -2
  215. package/dist/llm/registry.cjs +0 -1631
  216. package/dist/llm/registry.d.ts.map +0 -1
  217. package/dist/llm/registry.js +0 -1586
@@ -9,13 +9,15 @@ import { ToolError } from "./errors.js";
9
9
  import { ToolErrorCode } from "./error-codes.js";
10
10
  import { DextoRuntimeError } from "../errors/index.js";
11
11
  import { DextoLogComponent } from "../logger/v2/types.js";
12
- import { ApprovalStatus, ApprovalType } from "../approval/types.js";
12
+ import { ApprovalStatus, ApprovalType, DenialReason } from "../approval/types.js";
13
13
  import { InstrumentClass } from "../telemetry/decorators.js";
14
+ import { extractToolCallMeta, wrapToolParametersSchema } from "./tool-call-metadata.js";
14
15
  import {
15
16
  generateBashPatternKey,
16
17
  generateBashPatternSuggestions,
17
18
  isDangerousCommand
18
19
  } from "./bash-pattern-utils.js";
20
+ import { isBackgroundTasksEnabled } from "../utils/env.js";
19
21
  _ToolManager_decorators = [InstrumentClass({
20
22
  prefix: "tool",
21
23
  excludeMethods: [
@@ -45,6 +47,14 @@ let _ToolManager = class _ToolManager {
45
47
  toolsCache = {};
46
48
  cacheValid = false;
47
49
  logger;
50
+ // Session-level auto-approve tools for skills
51
+ // When a skill with allowedTools is invoked, those tools are auto-approved (skip confirmation)
52
+ // This is ADDITIVE - other tools are NOT blocked, they just go through normal approval flow
53
+ sessionAutoApproveTools = /* @__PURE__ */ new Map();
54
+ // Session-level auto-approve tools set by users (UI)
55
+ sessionUserAutoApproveTools = /* @__PURE__ */ new Map();
56
+ sessionDisabledTools = /* @__PURE__ */ new Map();
57
+ globalDisabledTools = [];
48
58
  constructor(mcpManager, approvalManager, allowedToolsProvider, approvalMode, agentEventBus, toolPolicies, options, logger) {
49
59
  this.mcpManager = mcpManager;
50
60
  this.approvalManager = approvalManager;
@@ -96,6 +106,204 @@ let _ToolManager = class _ToolManager {
96
106
  this.logger.debug("Agent reference configured for custom tools");
97
107
  }
98
108
  }
109
+ /**
110
+ * Set prompt manager for invoke_skill tool (called after construction to avoid circular dependencies)
111
+ * Must be called before initialize() if invoke_skill tool is enabled
112
+ */
113
+ setPromptManager(promptManager) {
114
+ if (this.internalToolsProvider) {
115
+ this.internalToolsProvider.setPromptManager(promptManager);
116
+ this.logger.debug("PromptManager reference configured for invoke_skill tool");
117
+ }
118
+ }
119
+ /**
120
+ * Set task forker for context:fork skill execution (late-binding)
121
+ * Called by agent-spawner custom tool provider after RuntimeService is created.
122
+ * This enables invoke_skill to fork execution to an isolated subagent.
123
+ */
124
+ setTaskForker(taskForker) {
125
+ if (this.internalToolsProvider) {
126
+ this.internalToolsProvider.setTaskForker(taskForker);
127
+ this.logger.debug(
128
+ "TaskForker reference configured for invoke_skill (context:fork support)"
129
+ );
130
+ }
131
+ }
132
+ // ============= SESSION AUTO-APPROVE TOOLS =============
133
+ /**
134
+ * Set session-level auto-approve tools.
135
+ * When set, these tools will skip confirmation prompts for this session.
136
+ * This is ADDITIVE - other tools are NOT blocked, they just go through normal approval flow.
137
+ *
138
+ * @param sessionId The session ID
139
+ * @param autoApproveTools Array of tool names to auto-approve (e.g., ['custom--bash_exec', 'custom--read_file'])
140
+ */
141
+ setSessionAutoApproveTools(sessionId, autoApproveTools) {
142
+ if (autoApproveTools.length === 0) {
143
+ this.clearSessionAutoApproveTools(sessionId);
144
+ return;
145
+ }
146
+ this.sessionAutoApproveTools.set(sessionId, autoApproveTools);
147
+ this.logger.info(
148
+ `Session auto-approve tools set for '${sessionId}': ${autoApproveTools.length} tools`
149
+ );
150
+ this.logger.debug(`Auto-approve tools: ${autoApproveTools.join(", ")}`);
151
+ }
152
+ /**
153
+ * Set session-level auto-approve tools chosen by the user.
154
+ */
155
+ setSessionUserAutoApproveTools(sessionId, autoApproveTools) {
156
+ if (autoApproveTools.length === 0) {
157
+ this.clearSessionUserAutoApproveTools(sessionId);
158
+ return;
159
+ }
160
+ this.sessionUserAutoApproveTools.set(sessionId, autoApproveTools);
161
+ this.logger.info(
162
+ `Session user auto-approve tools set for '${sessionId}': ${autoApproveTools.length} tools`
163
+ );
164
+ this.logger.debug(`User auto-approve tools: ${autoApproveTools.join(", ")}`);
165
+ }
166
+ /**
167
+ * Clear session-level auto-approve tools chosen by the user.
168
+ */
169
+ clearSessionUserAutoApproveTools(sessionId) {
170
+ const hadAutoApprove = this.sessionUserAutoApproveTools.has(sessionId);
171
+ this.sessionUserAutoApproveTools.delete(sessionId);
172
+ if (hadAutoApprove) {
173
+ this.logger.info(`Session user auto-approve tools cleared for '${sessionId}'`);
174
+ }
175
+ }
176
+ /**
177
+ * Clear session-level auto-approve tools.
178
+ * Call this when the session ends or when the skill completes.
179
+ *
180
+ * @param sessionId The session ID to clear auto-approve tools for
181
+ */
182
+ clearSessionAutoApproveTools(sessionId) {
183
+ const hadAutoApprove = this.sessionAutoApproveTools.has(sessionId);
184
+ this.sessionAutoApproveTools.delete(sessionId);
185
+ if (hadAutoApprove) {
186
+ this.logger.info(`Session auto-approve tools cleared for '${sessionId}'`);
187
+ }
188
+ }
189
+ hasSessionUserAutoApproveTools(sessionId) {
190
+ return this.sessionUserAutoApproveTools.has(sessionId);
191
+ }
192
+ // ============= ENABLED/DISABLED TOOLS =============
193
+ /**
194
+ * Set global disabled tools (agent-level preferences).
195
+ */
196
+ setGlobalDisabledTools(toolNames) {
197
+ this.globalDisabledTools = [...toolNames];
198
+ this.logger.info("Global disabled tools updated", {
199
+ count: toolNames.length
200
+ });
201
+ this.agentEventBus.emit("tools:enabled-updated", {
202
+ scope: "global",
203
+ disabledTools: [...this.globalDisabledTools]
204
+ });
205
+ }
206
+ getGlobalDisabledTools() {
207
+ return [...this.globalDisabledTools];
208
+ }
209
+ /**
210
+ * Set session-level disabled tools (overrides global list).
211
+ */
212
+ setSessionDisabledTools(sessionId, toolNames) {
213
+ if (toolNames.length === 0) {
214
+ this.clearSessionDisabledTools(sessionId);
215
+ return;
216
+ }
217
+ this.sessionDisabledTools.set(sessionId, [...toolNames]);
218
+ this.logger.info("Session disabled tools updated", {
219
+ sessionId,
220
+ count: toolNames.length
221
+ });
222
+ this.agentEventBus.emit("tools:enabled-updated", {
223
+ scope: "session",
224
+ sessionId,
225
+ disabledTools: [...toolNames]
226
+ });
227
+ }
228
+ /**
229
+ * Clear session-level disabled tools.
230
+ */
231
+ clearSessionDisabledTools(sessionId) {
232
+ const hadOverrides = this.sessionDisabledTools.has(sessionId);
233
+ this.sessionDisabledTools.delete(sessionId);
234
+ if (hadOverrides) {
235
+ this.logger.info("Session disabled tools cleared", { sessionId });
236
+ }
237
+ }
238
+ /**
239
+ * Get disabled tools for a session (session override wins).
240
+ */
241
+ getDisabledTools(sessionId) {
242
+ if (sessionId && this.sessionDisabledTools.has(sessionId)) {
243
+ return this.sessionDisabledTools.get(sessionId) ?? [];
244
+ }
245
+ return this.globalDisabledTools;
246
+ }
247
+ /**
248
+ * Filter a tool set based on disabled tools for a session.
249
+ */
250
+ filterToolsForSession(toolSet, sessionId) {
251
+ const disabled = new Set(this.getDisabledTools(sessionId));
252
+ if (disabled.size === 0) {
253
+ return toolSet;
254
+ }
255
+ return Object.fromEntries(
256
+ Object.entries(toolSet).filter(([toolName]) => !disabled.has(toolName))
257
+ );
258
+ }
259
+ /**
260
+ * Check if a session has auto-approve tools set.
261
+ *
262
+ * @param sessionId The session ID to check
263
+ * @returns true if the session has auto-approve tools
264
+ */
265
+ hasSessionAutoApproveTools(sessionId) {
266
+ return this.sessionAutoApproveTools.has(sessionId);
267
+ }
268
+ /**
269
+ * Get the auto-approve tools for a session (skill-provided list).
270
+ *
271
+ * @param sessionId The session ID to check
272
+ * @returns Array of auto-approve tool names, or undefined if none set
273
+ */
274
+ getSessionAutoApproveTools(sessionId) {
275
+ return this.sessionAutoApproveTools.get(sessionId);
276
+ }
277
+ /**
278
+ * Get the user auto-approve tools for a session.
279
+ */
280
+ getSessionUserAutoApproveTools(sessionId) {
281
+ return this.sessionUserAutoApproveTools.get(sessionId);
282
+ }
283
+ /**
284
+ * Combined auto-approve list for a session.
285
+ */
286
+ getCombinedSessionAutoApproveTools(sessionId) {
287
+ return [
288
+ ...this.sessionAutoApproveTools.get(sessionId) ?? [],
289
+ ...this.sessionUserAutoApproveTools.get(sessionId) ?? []
290
+ ];
291
+ }
292
+ /**
293
+ * Check if a tool should be auto-approved for a session.
294
+ * Returns true if the tool is in the session's auto-approve list.
295
+ *
296
+ * @param sessionId The session ID
297
+ * @param toolName The tool name to check
298
+ * @returns true if the tool should be auto-approved
299
+ */
300
+ isToolAutoApprovedForSession(sessionId, toolName) {
301
+ const autoApproveTools = this.getCombinedSessionAutoApproveTools(sessionId);
302
+ if (autoApproveTools.length === 0) {
303
+ return false;
304
+ }
305
+ return autoApproveTools.some((pattern) => this.matchesToolPolicy(toolName, pattern));
306
+ }
99
307
  /**
100
308
  * Invalidate the tools cache when tool sources change
101
309
  */
@@ -121,6 +329,14 @@ let _ToolManager = class _ToolManager {
121
329
  );
122
330
  this.invalidateCache();
123
331
  });
332
+ this.agentEventBus.on("run:complete", (payload) => {
333
+ if (this.hasSessionAutoApproveTools(payload.sessionId)) {
334
+ this.logger.debug(
335
+ `\u{1F513} Run complete, clearing session auto-approve tools for '${payload.sessionId}'`
336
+ );
337
+ this.clearSessionAutoApproveTools(payload.sessionId);
338
+ }
339
+ });
124
340
  }
125
341
  // ==================== Bash Pattern Approval Helpers ====================
126
342
  /**
@@ -280,7 +496,8 @@ let _ToolManager = class _ToolManager {
280
496
  allTools[qualifiedName] = {
281
497
  ...toolDef,
282
498
  name: qualifiedName,
283
- description: `${toolDef.description || "No description provided"} (internal tool)`
499
+ description: `${toolDef.description || "No description provided"} (internal tool)`,
500
+ parameters: wrapToolParametersSchema(toolDef.parameters)
284
501
  };
285
502
  }
286
503
  for (const [toolName, toolDef] of Object.entries(customTools)) {
@@ -288,7 +505,8 @@ let _ToolManager = class _ToolManager {
288
505
  allTools[qualifiedName] = {
289
506
  ...toolDef,
290
507
  name: qualifiedName,
291
- description: `${toolDef.description || "No description provided"} (custom tool)`
508
+ description: `${toolDef.description || "No description provided"} (custom tool)`,
509
+ parameters: wrapToolParametersSchema(toolDef.parameters)
292
510
  };
293
511
  }
294
512
  for (const [toolName, toolDef] of Object.entries(mcpTools)) {
@@ -296,7 +514,8 @@ let _ToolManager = class _ToolManager {
296
514
  allTools[qualifiedName] = {
297
515
  ...toolDef,
298
516
  name: qualifiedName,
299
- description: `${toolDef.description || "No description provided"} (via MCP servers)`
517
+ description: `${toolDef.description || "No description provided"} (via MCP servers)`,
518
+ parameters: wrapToolParametersSchema(toolDef.parameters)
300
519
  };
301
520
  }
302
521
  const totalTools = Object.keys(allTools).length;
@@ -332,21 +551,25 @@ let _ToolManager = class _ToolManager {
332
551
  * @param abortSignal Optional abort signal for cancellation support
333
552
  */
334
553
  async executeTool(toolName, args, toolCallId, sessionId, abortSignal) {
554
+ const { toolArgs: rawToolArgs, meta } = extractToolCallMeta(args);
555
+ let toolArgs = rawToolArgs;
556
+ const backgroundTasksEnabled = isBackgroundTasksEnabled();
335
557
  this.logger.debug(`\u{1F527} Tool execution requested: '${toolName}' (toolCallId: ${toolCallId})`);
336
- this.logger.debug(`Tool args: ${JSON.stringify(args, null, 2)}`);
558
+ this.logger.debug(`Tool args: ${JSON.stringify(toolArgs, null, 2)}`);
337
559
  if (sessionId) {
338
560
  this.agentEventBus.emit("llm:tool-call", {
339
561
  toolName,
340
- args,
562
+ args: toolArgs,
341
563
  callId: toolCallId,
342
564
  sessionId
343
565
  });
344
566
  }
345
567
  const { requireApproval, approvalStatus } = await this.handleToolApproval(
346
568
  toolName,
347
- args,
569
+ toolArgs,
348
570
  toolCallId,
349
- sessionId
571
+ sessionId,
572
+ meta.callDescription
350
573
  );
351
574
  this.logger.debug(`\u2705 Tool execution approved: ${toolName}`);
352
575
  this.logger.info(
@@ -363,7 +586,7 @@ let _ToolManager = class _ToolManager {
363
586
  if (this.pluginManager && this.sessionManager && this.stateManager) {
364
587
  const beforePayload = {
365
588
  toolName,
366
- args,
589
+ args: toolArgs,
367
590
  ...sessionId !== void 0 && { sessionId }
368
591
  };
369
592
  const modifiedPayload = await this.pluginManager.executePlugins(
@@ -377,10 +600,21 @@ let _ToolManager = class _ToolManager {
377
600
  ...sessionId !== void 0 && { sessionId }
378
601
  }
379
602
  );
380
- args = modifiedPayload.args;
603
+ toolArgs = modifiedPayload.args;
381
604
  }
382
605
  try {
383
606
  let result;
607
+ const registerBackgroundTask = (promise, description) => {
608
+ const fallbackId = `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
609
+ return {
610
+ result: {
611
+ taskId: toolCallId ?? fallbackId,
612
+ status: "running",
613
+ description
614
+ },
615
+ promise
616
+ };
617
+ };
384
618
  if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
385
619
  this.logger.debug(`\u{1F527} Detected MCP tool: '${toolName}'`);
386
620
  const actualToolName = toolName.substring(_ToolManager.MCP_TOOL_PREFIX.length);
@@ -388,7 +622,34 @@ let _ToolManager = class _ToolManager {
388
622
  throw ToolError.invalidName(toolName, "tool name cannot be empty after prefix");
389
623
  }
390
624
  this.logger.debug(`\u{1F3AF} MCP routing: '${toolName}' -> '${actualToolName}'`);
391
- result = await this.mcpManager.executeTool(actualToolName, args, sessionId);
625
+ const runInBackground = backgroundTasksEnabled && meta.runInBackground === true && sessionId !== void 0;
626
+ if (meta.runInBackground === true && !backgroundTasksEnabled) {
627
+ this.logger.debug(
628
+ "Background tool execution disabled; running synchronously instead.",
629
+ { toolName }
630
+ );
631
+ }
632
+ if (runInBackground) {
633
+ const backgroundSessionId = sessionId;
634
+ const { result: backgroundResult, promise } = registerBackgroundTask(
635
+ this.mcpManager.executeTool(actualToolName, toolArgs, backgroundSessionId),
636
+ `MCP tool ${actualToolName}`
637
+ );
638
+ this.agentEventBus.emit("tool:background", {
639
+ toolName,
640
+ toolCallId: backgroundResult.taskId,
641
+ sessionId: backgroundSessionId,
642
+ description: backgroundResult.description,
643
+ promise,
644
+ ...meta.timeoutMs !== void 0 && { timeoutMs: meta.timeoutMs },
645
+ ...meta.notifyOnComplete !== void 0 && {
646
+ notifyOnComplete: meta.notifyOnComplete
647
+ }
648
+ });
649
+ result = backgroundResult;
650
+ } else {
651
+ result = await this.mcpManager.executeTool(actualToolName, toolArgs, sessionId);
652
+ }
392
653
  } else if (toolName.startsWith(_ToolManager.INTERNAL_TOOL_PREFIX)) {
393
654
  this.logger.debug(`\u{1F527} Detected internal tool: '${toolName}'`);
394
655
  const actualToolName = toolName.substring(_ToolManager.INTERNAL_TOOL_PREFIX.length);
@@ -399,13 +660,46 @@ let _ToolManager = class _ToolManager {
399
660
  throw ToolError.internalToolsNotInitialized(toolName);
400
661
  }
401
662
  this.logger.debug(`\u{1F3AF} Internal routing: '${toolName}' -> '${actualToolName}'`);
402
- result = await this.internalToolsProvider.executeTool(
403
- actualToolName,
404
- args,
405
- sessionId,
406
- abortSignal,
407
- toolCallId
408
- );
663
+ const runInBackground = backgroundTasksEnabled && meta.runInBackground === true && sessionId !== void 0;
664
+ if (meta.runInBackground === true && !backgroundTasksEnabled) {
665
+ this.logger.debug(
666
+ "Background tool execution disabled; running synchronously instead.",
667
+ { toolName }
668
+ );
669
+ }
670
+ if (runInBackground) {
671
+ const backgroundSessionId = sessionId;
672
+ const { result: backgroundResult, promise } = registerBackgroundTask(
673
+ this.internalToolsProvider.executeTool(
674
+ actualToolName,
675
+ toolArgs,
676
+ backgroundSessionId,
677
+ abortSignal,
678
+ toolCallId
679
+ ),
680
+ `Internal tool ${actualToolName}`
681
+ );
682
+ this.agentEventBus.emit("tool:background", {
683
+ toolName,
684
+ toolCallId: backgroundResult.taskId,
685
+ sessionId: backgroundSessionId,
686
+ description: backgroundResult.description,
687
+ promise,
688
+ ...meta.timeoutMs !== void 0 && { timeoutMs: meta.timeoutMs },
689
+ ...meta.notifyOnComplete !== void 0 && {
690
+ notifyOnComplete: meta.notifyOnComplete
691
+ }
692
+ });
693
+ result = backgroundResult;
694
+ } else {
695
+ result = await this.internalToolsProvider.executeTool(
696
+ actualToolName,
697
+ toolArgs,
698
+ sessionId,
699
+ abortSignal,
700
+ toolCallId
701
+ );
702
+ }
409
703
  } else if (toolName.startsWith(_ToolManager.CUSTOM_TOOL_PREFIX)) {
410
704
  this.logger.debug(`\u{1F527} Detected custom tool: '${toolName}'`);
411
705
  const actualToolName = toolName.substring(_ToolManager.CUSTOM_TOOL_PREFIX.length);
@@ -416,13 +710,46 @@ let _ToolManager = class _ToolManager {
416
710
  throw ToolError.internalToolsNotInitialized(toolName);
417
711
  }
418
712
  this.logger.debug(`\u{1F3AF} Custom routing: '${toolName}' -> '${actualToolName}'`);
419
- result = await this.internalToolsProvider.executeTool(
420
- actualToolName,
421
- args,
422
- sessionId,
423
- abortSignal,
424
- toolCallId
425
- );
713
+ const runInBackground = backgroundTasksEnabled && meta.runInBackground === true && sessionId !== void 0;
714
+ if (meta.runInBackground === true && !backgroundTasksEnabled) {
715
+ this.logger.debug(
716
+ "Background tool execution disabled; running synchronously instead.",
717
+ { toolName }
718
+ );
719
+ }
720
+ if (runInBackground) {
721
+ const backgroundSessionId = sessionId;
722
+ const { result: backgroundResult, promise } = registerBackgroundTask(
723
+ this.internalToolsProvider.executeTool(
724
+ actualToolName,
725
+ toolArgs,
726
+ backgroundSessionId,
727
+ abortSignal,
728
+ toolCallId
729
+ ),
730
+ `Custom tool ${actualToolName}`
731
+ );
732
+ this.agentEventBus.emit("tool:background", {
733
+ toolName,
734
+ toolCallId: backgroundResult.taskId,
735
+ sessionId: backgroundSessionId,
736
+ description: backgroundResult.description,
737
+ promise,
738
+ ...meta.timeoutMs !== void 0 && { timeoutMs: meta.timeoutMs },
739
+ ...meta.notifyOnComplete !== void 0 && {
740
+ notifyOnComplete: meta.notifyOnComplete
741
+ }
742
+ });
743
+ result = backgroundResult;
744
+ } else {
745
+ result = await this.internalToolsProvider.executeTool(
746
+ actualToolName,
747
+ toolArgs,
748
+ sessionId,
749
+ abortSignal,
750
+ toolCallId
751
+ );
752
+ }
426
753
  } else {
427
754
  this.logger.debug(`\u{1F527} Detected tool without proper prefix: '${toolName}'`);
428
755
  const stats = await this.getToolStats();
@@ -672,21 +999,34 @@ let _ToolManager = class _ToolManager {
672
999
  throw ToolError.executionDenied(toolName, sessionId);
673
1000
  }
674
1001
  /**
675
- * Handle tool approval/confirmation flow
676
- * Checks allowed list, manages approval modes (manual, auto-approve, auto-deny),
677
- * and handles remember choice logic
1002
+ * Handle tool approval flow. Checks various precedence levels to determine
1003
+ * if a tool should be auto-approved, denied, or requires manual approval.
1004
+ */
1005
+ async handleToolApproval(toolName, args, toolCallId, sessionId, callDescription) {
1006
+ const quickResult = await this.tryQuickApprovalResolution(toolName, args, sessionId);
1007
+ if (quickResult !== null) {
1008
+ return quickResult;
1009
+ }
1010
+ return this.requestManualApproval(toolName, args, toolCallId, sessionId, callDescription);
1011
+ }
1012
+ /**
1013
+ * Try to resolve tool approval quickly based on policies and cached permissions.
1014
+ * Returns null if manual approval is needed.
678
1015
  *
679
- * @param toolName The fully qualified tool name
680
- * @param args The arguments for the tool
681
- * @param toolCallId The unique tool call ID for tracking parallel tool calls
682
- * @param sessionId Optional session ID for context
1016
+ * Precedence order (highest to lowest):
1017
+ * 1. Static deny list (security - always blocks)
1018
+ * 2. Custom approval override (tool-specific approval flows)
1019
+ * 3. Session auto-approve (skill allowed-tools)
1020
+ * 4. Static allow list
1021
+ * 5. Dynamic "remembered" allowed list
1022
+ * 6. Bash command patterns
1023
+ * 7. Approval mode (auto-approve/auto-deny)
683
1024
  */
684
- async handleToolApproval(toolName, args, toolCallId, sessionId) {
1025
+ async tryQuickApprovalResolution(toolName, args, sessionId) {
685
1026
  if (this.isInAlwaysDenyList(toolName)) {
686
1027
  this.logger.info(
687
1028
  `Tool '${toolName}' is in static deny list \u2013 blocking execution (session: ${sessionId ?? "global"})`
688
1029
  );
689
- this.logger.debug(`\u{1F6AB} Tool execution blocked by policy: ${toolName}`);
690
1030
  throw ToolError.executionDenied(toolName, sessionId);
691
1031
  }
692
1032
  const customApprovalResult = await this.checkCustomApprovalOverride(
@@ -697,25 +1037,29 @@ let _ToolManager = class _ToolManager {
697
1037
  if (customApprovalResult.handled) {
698
1038
  return { requireApproval: true, approvalStatus: "approved" };
699
1039
  }
1040
+ if (sessionId && this.isToolAutoApprovedForSession(sessionId, toolName)) {
1041
+ this.logger.info(
1042
+ `Tool '${toolName}' is in session's auto-approve list \u2013 skipping confirmation (session: ${sessionId})`
1043
+ );
1044
+ return { requireApproval: false };
1045
+ }
700
1046
  if (this.isInAlwaysAllowList(toolName)) {
701
1047
  this.logger.info(
702
1048
  `Tool '${toolName}' is in static allow list \u2013 skipping confirmation (session: ${sessionId ?? "global"})`
703
1049
  );
704
1050
  return { requireApproval: false };
705
1051
  }
706
- const isAllowed = await this.allowedToolsProvider.isToolAllowed(toolName, sessionId);
707
- if (isAllowed) {
1052
+ if (await this.allowedToolsProvider.isToolAllowed(toolName, sessionId)) {
708
1053
  this.logger.info(
709
1054
  `Tool '${toolName}' already allowed for session '${sessionId ?? "global"}' \u2013 skipping confirmation.`
710
1055
  );
711
1056
  return { requireApproval: false };
712
1057
  }
713
- let bashPatternResult;
714
1058
  if (this.isBashTool(toolName)) {
715
1059
  const command = args.command;
716
1060
  if (command) {
717
- bashPatternResult = this.checkBashPatternApproval(command);
718
- if (bashPatternResult.approved) {
1061
+ const bashResult = this.checkBashPatternApproval(command);
1062
+ if (bashResult.approved) {
719
1063
  this.logger.info(
720
1064
  `Bash command '${command}' matched approved pattern \u2013 skipping confirmation.`
721
1065
  );
@@ -731,79 +1075,38 @@ let _ToolManager = class _ToolManager {
731
1075
  this.logger.debug(`\u{1F6AB} Auto-denying tool execution: ${toolName}`);
732
1076
  throw ToolError.executionDenied(toolName, sessionId);
733
1077
  }
1078
+ return null;
1079
+ }
1080
+ /**
1081
+ * Request manual approval from the user for a tool execution.
1082
+ * Generates preview, sends approval request, and handles the response.
1083
+ */
1084
+ async requestManualApproval(toolName, args, toolCallId, sessionId, callDescription) {
734
1085
  this.logger.info(
735
1086
  `Tool confirmation requested for ${toolName}, sessionId: ${sessionId ?? "global"}`
736
1087
  );
737
1088
  try {
738
- let displayPreview;
739
- const actualToolName = toolName.replace(/^internal--/, "").replace(/^custom--/, "");
740
- const internalTool = this.internalToolsProvider?.getTool(actualToolName);
741
- if (internalTool?.generatePreview) {
742
- try {
743
- const context = { sessionId, toolCallId };
744
- const preview = await internalTool.generatePreview(args, context);
745
- displayPreview = preview ?? void 0;
746
- this.logger.debug(`Generated preview for ${toolName}`);
747
- } catch (previewError) {
748
- if (previewError instanceof DextoRuntimeError && previewError.code === ToolErrorCode.VALIDATION_FAILED) {
749
- this.logger.debug(
750
- `Validation failed for ${toolName}: ${previewError.message}`
751
- );
752
- throw previewError;
753
- }
754
- this.logger.debug(
755
- `Preview generation failed for ${toolName}: ${previewError instanceof Error ? previewError.message : String(previewError)}`
756
- );
757
- }
758
- }
759
- const requestData = {
1089
+ const displayPreview = await this.generateToolPreview(
760
1090
  toolName,
1091
+ args,
761
1092
  toolCallId,
762
- args
763
- };
764
- if (sessionId !== void 0) {
765
- requestData.sessionId = sessionId;
766
- }
767
- if (displayPreview !== void 0) {
768
- requestData.displayPreview = displayPreview;
769
- }
770
- if (bashPatternResult?.suggestedPatterns && bashPatternResult.suggestedPatterns.length > 0) {
771
- requestData.suggestedPatterns = bashPatternResult.suggestedPatterns;
772
- }
773
- const response = await this.approvalManager.requestToolConfirmation(requestData);
1093
+ sessionId
1094
+ );
1095
+ const suggestedPatterns = this.getBashSuggestedPatterns(toolName, args);
1096
+ const response = await this.approvalManager.requestToolConfirmation({
1097
+ toolName,
1098
+ toolCallId,
1099
+ args,
1100
+ ...callDescription !== void 0 && { description: callDescription },
1101
+ ...sessionId !== void 0 && { sessionId },
1102
+ ...displayPreview !== void 0 && { displayPreview },
1103
+ ...suggestedPatterns !== void 0 && { suggestedPatterns }
1104
+ });
774
1105
  if (response.status === ApprovalStatus.APPROVED && response.data) {
775
- const rememberChoice = "rememberChoice" in response.data ? response.data.rememberChoice : false;
776
- const rememberPattern = "rememberPattern" in response.data ? response.data.rememberPattern : void 0;
777
- if (rememberChoice) {
778
- const allowSessionId = sessionId ?? response.sessionId;
779
- await this.allowedToolsProvider.allowTool(toolName, allowSessionId);
780
- this.logger.info(
781
- `Tool '${toolName}' added to allowed tools for session '${allowSessionId ?? "global"}' (remember choice selected)`
782
- );
783
- this.autoApprovePendingToolRequests(toolName, allowSessionId);
784
- } else if (rememberPattern && typeof rememberPattern === "string" && this.isBashTool(toolName)) {
785
- this.approvalManager.addBashPattern(rememberPattern);
786
- this.logger.info(
787
- `Bash pattern '${rememberPattern}' added for session approval`
788
- );
789
- this.autoApprovePendingBashRequests(rememberPattern, sessionId);
790
- }
1106
+ await this.handleRememberChoice(toolName, response, sessionId);
791
1107
  }
792
- const approved = response.status === ApprovalStatus.APPROVED;
793
- if (!approved) {
794
- if (response.status === ApprovalStatus.CANCELLED && response.reason === "timeout") {
795
- this.logger.info(
796
- `Tool confirmation timed out for ${toolName}, sessionId: ${sessionId ?? "global"}`
797
- );
798
- this.logger.debug(`\u23F1\uFE0F Tool execution timed out: ${toolName}`);
799
- const timeoutMs = response.timeoutMs ?? 0;
800
- throw ToolError.executionTimeout(toolName, timeoutMs, sessionId);
801
- }
802
- this.logger.info(
803
- `Tool confirmation denied for ${toolName}, sessionId: ${sessionId ?? "global"}, reason: ${response.reason ?? "unknown"}`
804
- );
805
- this.logger.debug(`\u{1F6AB} Tool execution denied: ${toolName}`);
806
- throw ToolError.executionDenied(toolName, sessionId);
1108
+ if (response.status !== ApprovalStatus.APPROVED) {
1109
+ this.handleApprovalDenied(toolName, response, sessionId);
807
1110
  }
808
1111
  this.logger.info(
809
1112
  `Tool confirmation approved for ${toolName}, sessionId: ${sessionId ?? "global"}`
@@ -816,6 +1119,81 @@ let _ToolManager = class _ToolManager {
816
1119
  throw error;
817
1120
  }
818
1121
  }
1122
+ /**
1123
+ * Generate a preview for the tool approval UI if the tool supports it.
1124
+ */
1125
+ async generateToolPreview(toolName, args, toolCallId, sessionId) {
1126
+ const actualToolName = toolName.replace(/^internal--/, "").replace(/^custom--/, "");
1127
+ const internalTool = this.internalToolsProvider?.getTool(actualToolName);
1128
+ if (!internalTool?.generatePreview) {
1129
+ return void 0;
1130
+ }
1131
+ try {
1132
+ const context = { sessionId, toolCallId };
1133
+ const preview = await internalTool.generatePreview(args, context);
1134
+ this.logger.debug(`Generated preview for ${toolName}`);
1135
+ return preview ?? void 0;
1136
+ } catch (previewError) {
1137
+ if (previewError instanceof DextoRuntimeError && previewError.code === ToolErrorCode.VALIDATION_FAILED) {
1138
+ this.logger.debug(`Validation failed for ${toolName}: ${previewError.message}`);
1139
+ throw previewError;
1140
+ }
1141
+ this.logger.debug(
1142
+ `Preview generation failed for ${toolName}: ${previewError instanceof Error ? previewError.message : String(previewError)}`
1143
+ );
1144
+ return void 0;
1145
+ }
1146
+ }
1147
+ /**
1148
+ * Get suggested bash patterns for the approval UI.
1149
+ */
1150
+ getBashSuggestedPatterns(toolName, args) {
1151
+ if (!this.isBashTool(toolName)) {
1152
+ return void 0;
1153
+ }
1154
+ const command = args.command;
1155
+ if (!command) {
1156
+ return void 0;
1157
+ }
1158
+ const result = this.checkBashPatternApproval(command);
1159
+ return result.suggestedPatterns?.length ? result.suggestedPatterns : void 0;
1160
+ }
1161
+ /**
1162
+ * Handle "remember choice" or "remember pattern" when user approves a tool.
1163
+ */
1164
+ async handleRememberChoice(toolName, response, sessionId) {
1165
+ const data = response.data;
1166
+ if (!data) return;
1167
+ const rememberChoice = data.rememberChoice;
1168
+ const rememberPattern = data.rememberPattern;
1169
+ if (rememberChoice) {
1170
+ const allowSessionId = sessionId ?? response.sessionId;
1171
+ await this.allowedToolsProvider.allowTool(toolName, allowSessionId);
1172
+ this.logger.info(
1173
+ `Tool '${toolName}' added to allowed tools for session '${allowSessionId ?? "global"}' (remember choice selected)`
1174
+ );
1175
+ this.autoApprovePendingToolRequests(toolName, allowSessionId);
1176
+ } else if (rememberPattern && this.isBashTool(toolName)) {
1177
+ this.approvalManager.addBashPattern(rememberPattern);
1178
+ this.logger.info(`Bash pattern '${rememberPattern}' added for session approval`);
1179
+ this.autoApprovePendingBashRequests(rememberPattern, sessionId);
1180
+ }
1181
+ }
1182
+ /**
1183
+ * Handle approval denied/timeout - throws appropriate error.
1184
+ */
1185
+ handleApprovalDenied(toolName, response, sessionId) {
1186
+ if (response.status === ApprovalStatus.CANCELLED && response.reason === DenialReason.TIMEOUT) {
1187
+ this.logger.info(
1188
+ `Tool confirmation timed out for ${toolName}, sessionId: ${sessionId ?? "global"}`
1189
+ );
1190
+ throw ToolError.executionTimeout(toolName, response.timeoutMs ?? 0, sessionId);
1191
+ }
1192
+ this.logger.info(
1193
+ `Tool confirmation denied for ${toolName}, sessionId: ${sessionId ?? "global"}, reason: ${response.reason ?? "unknown"}`
1194
+ );
1195
+ throw ToolError.executionDenied(toolName, sessionId, response.message);
1196
+ }
819
1197
  /**
820
1198
  * Refresh tool discovery (call when MCP servers change)
821
1199
  * Refreshes both MCPManager's cache (server capabilities) and ToolManager's cache (combined tools)