@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.
- package/dist/agent/DextoAgent.cjs +189 -30
- package/dist/agent/DextoAgent.d.ts +44 -9
- package/dist/agent/DextoAgent.d.ts.map +1 -1
- package/dist/agent/DextoAgent.js +190 -31
- package/dist/agent/schemas.cjs +5 -0
- package/dist/agent/schemas.d.ts +456 -66
- package/dist/agent/schemas.d.ts.map +1 -1
- package/dist/agent/schemas.js +5 -0
- package/dist/context/manager.cjs +1 -1
- package/dist/context/manager.js +1 -1
- package/dist/context/utils.cjs +90 -17
- package/dist/context/utils.d.ts.map +1 -1
- package/dist/context/utils.js +90 -17
- package/dist/errors/types.cjs +2 -1
- package/dist/errors/types.d.ts +2 -1
- package/dist/errors/types.d.ts.map +1 -1
- package/dist/errors/types.js +2 -1
- package/dist/events/index.cjs +4 -1
- package/dist/events/index.d.ts +37 -2
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +4 -1
- package/dist/image/types.d.ts +15 -0
- package/dist/image/types.d.ts.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/llm/curation-config.cjs +82 -0
- package/dist/llm/curation-config.d.ts +13 -0
- package/dist/llm/curation-config.d.ts.map +1 -0
- package/dist/llm/curation-config.js +59 -0
- package/dist/llm/curation.cjs +57 -0
- package/dist/llm/curation.d.ts +16 -0
- package/dist/llm/curation.d.ts.map +1 -0
- package/dist/llm/curation.js +34 -0
- package/dist/llm/error-codes.cjs +1 -0
- package/dist/llm/error-codes.d.ts +1 -0
- package/dist/llm/error-codes.d.ts.map +1 -1
- package/dist/llm/error-codes.js +1 -0
- package/dist/llm/errors.cjs +16 -1
- package/dist/llm/errors.d.ts +15 -8
- package/dist/llm/errors.d.ts.map +1 -1
- package/dist/llm/errors.js +16 -1
- package/dist/llm/executor/provider-options.cjs +1 -1
- package/dist/llm/executor/provider-options.js +1 -1
- package/dist/llm/executor/turn-executor.cjs +35 -2
- package/dist/llm/executor/turn-executor.d.ts.map +1 -1
- package/dist/llm/executor/turn-executor.js +35 -2
- package/dist/llm/index.cjs +14 -3
- package/dist/llm/index.d.ts +3 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +13 -2
- package/dist/llm/registry/auto-update.cjs +263 -0
- package/dist/llm/registry/auto-update.d.ts +27 -0
- package/dist/llm/registry/auto-update.d.ts.map +1 -0
- package/dist/llm/registry/auto-update.js +227 -0
- package/dist/llm/registry/index.cjs +806 -0
- package/dist/llm/{registry.d.ts → registry/index.d.ts} +67 -13
- package/dist/llm/registry/index.d.ts.map +1 -0
- package/dist/llm/registry/index.js +756 -0
- package/dist/llm/registry/models.generated.cjs +4861 -0
- package/dist/llm/registry/models.generated.d.ts +431 -0
- package/dist/llm/registry/models.generated.d.ts.map +1 -0
- package/dist/llm/registry/models.generated.js +4838 -0
- package/dist/llm/registry/models.manual.cjs +44 -0
- package/dist/llm/registry/models.manual.d.ts +22 -0
- package/dist/llm/registry/models.manual.d.ts.map +1 -0
- package/dist/llm/registry/models.manual.js +21 -0
- package/dist/llm/registry/sync.cjs +354 -0
- package/dist/llm/registry/sync.d.ts +41 -0
- package/dist/llm/registry/sync.d.ts.map +1 -0
- package/dist/llm/registry/sync.js +328 -0
- package/dist/llm/resolver.cjs +29 -7
- package/dist/llm/resolver.d.ts +1 -1
- package/dist/llm/resolver.d.ts.map +1 -1
- package/dist/llm/resolver.js +31 -8
- package/dist/llm/schemas.cjs +13 -1
- package/dist/llm/schemas.d.ts +59 -59
- package/dist/llm/schemas.d.ts.map +1 -1
- package/dist/llm/schemas.js +14 -1
- package/dist/llm/services/factory.cjs +43 -27
- package/dist/llm/services/factory.d.ts +20 -1
- package/dist/llm/services/factory.d.ts.map +1 -1
- package/dist/llm/services/factory.js +44 -28
- package/dist/llm/services/test-utils.integration.cjs +5 -1
- package/dist/llm/services/test-utils.integration.d.ts.map +1 -1
- package/dist/llm/services/test-utils.integration.js +5 -1
- package/dist/llm/services/vercel.cjs +4 -1
- package/dist/llm/services/vercel.d.ts +1 -0
- package/dist/llm/services/vercel.d.ts.map +1 -1
- package/dist/llm/services/vercel.js +4 -1
- package/dist/llm/types.cjs +5 -2
- package/dist/llm/types.d.ts +1 -1
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/llm/types.js +5 -2
- package/dist/llm/validation.cjs +1 -1
- package/dist/llm/validation.js +1 -1
- package/dist/logger/v2/dexto-logger.cjs +4 -0
- package/dist/logger/v2/dexto-logger.d.ts +3 -0
- package/dist/logger/v2/dexto-logger.d.ts.map +1 -1
- package/dist/logger/v2/dexto-logger.js +4 -0
- package/dist/logger/v2/types.d.ts +2 -0
- package/dist/logger/v2/types.d.ts.map +1 -1
- package/dist/mcp/error-codes.cjs +1 -0
- package/dist/mcp/error-codes.d.ts +1 -0
- package/dist/mcp/error-codes.d.ts.map +1 -1
- package/dist/mcp/error-codes.js +1 -0
- package/dist/mcp/errors.cjs +13 -0
- package/dist/mcp/errors.d.ts +7 -0
- package/dist/mcp/errors.d.ts.map +1 -1
- package/dist/mcp/errors.js +13 -0
- package/dist/mcp/manager.cjs +46 -4
- package/dist/mcp/manager.d.ts +10 -2
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +46 -4
- package/dist/mcp/mcp-client.cjs +89 -5
- package/dist/mcp/mcp-client.d.ts +5 -1
- package/dist/mcp/mcp-client.d.ts.map +1 -1
- package/dist/mcp/mcp-client.js +89 -5
- package/dist/mcp/schemas.cjs +6 -1
- package/dist/mcp/schemas.d.ts +1 -1
- package/dist/mcp/schemas.d.ts.map +1 -1
- package/dist/mcp/schemas.js +6 -1
- package/dist/mcp/types.d.ts +5 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/prompt-manager.cjs +90 -4
- package/dist/prompts/prompt-manager.d.ts +16 -6
- package/dist/prompts/prompt-manager.d.ts.map +1 -1
- package/dist/prompts/prompt-manager.js +90 -4
- package/dist/prompts/providers/config-prompt-provider.cjs +104 -10
- package/dist/prompts/providers/config-prompt-provider.d.ts.map +1 -1
- package/dist/prompts/providers/config-prompt-provider.js +105 -11
- package/dist/prompts/providers/custom-prompt-provider.cjs +1 -0
- package/dist/prompts/providers/custom-prompt-provider.d.ts.map +1 -1
- package/dist/prompts/providers/custom-prompt-provider.js +1 -0
- package/dist/prompts/providers/mcp-prompt-provider.cjs +1 -0
- package/dist/prompts/providers/mcp-prompt-provider.d.ts.map +1 -1
- package/dist/prompts/providers/mcp-prompt-provider.js +1 -0
- package/dist/prompts/schemas.cjs +28 -2
- package/dist/prompts/schemas.d.ts +130 -0
- package/dist/prompts/schemas.d.ts.map +1 -1
- package/dist/prompts/schemas.js +28 -2
- package/dist/prompts/types.d.ts +55 -3
- package/dist/prompts/types.d.ts.map +1 -1
- package/dist/resources/handlers/filesystem-handler.cjs +25 -0
- package/dist/resources/handlers/filesystem-handler.d.ts +1 -0
- package/dist/resources/handlers/filesystem-handler.d.ts.map +1 -1
- package/dist/resources/handlers/filesystem-handler.js +25 -0
- package/dist/session/chat-session.cjs +1 -1
- package/dist/session/chat-session.d.ts +1 -1
- package/dist/session/chat-session.d.ts.map +1 -1
- package/dist/session/chat-session.js +1 -1
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/message-queue.cjs +29 -5
- package/dist/session/message-queue.d.ts +3 -1
- package/dist/session/message-queue.d.ts.map +1 -1
- package/dist/session/message-queue.js +29 -5
- package/dist/session/session-manager.cjs +84 -3
- package/dist/session/session-manager.d.ts +12 -0
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +74 -3
- package/dist/session/types.d.ts +1 -0
- package/dist/session/types.d.ts.map +1 -1
- package/dist/systemPrompt/contributors.cjs +42 -0
- package/dist/systemPrompt/contributors.d.ts +13 -0
- package/dist/systemPrompt/contributors.d.ts.map +1 -1
- package/dist/systemPrompt/contributors.js +41 -0
- package/dist/tools/errors.cjs +7 -3
- package/dist/tools/errors.d.ts +5 -1
- package/dist/tools/errors.d.ts.map +1 -1
- package/dist/tools/errors.js +7 -3
- package/dist/tools/internal-tools/constants.cjs +2 -1
- package/dist/tools/internal-tools/constants.d.ts +1 -1
- package/dist/tools/internal-tools/constants.d.ts.map +1 -1
- package/dist/tools/internal-tools/constants.js +2 -1
- package/dist/tools/internal-tools/implementations/invoke-skill-tool.cjs +140 -0
- package/dist/tools/internal-tools/implementations/invoke-skill-tool.d.ts +24 -0
- package/dist/tools/internal-tools/implementations/invoke-skill-tool.d.ts.map +1 -0
- package/dist/tools/internal-tools/implementations/invoke-skill-tool.js +117 -0
- package/dist/tools/internal-tools/provider.cjs +15 -0
- package/dist/tools/internal-tools/provider.d.ts +15 -1
- package/dist/tools/internal-tools/provider.d.ts.map +1 -1
- package/dist/tools/internal-tools/provider.js +15 -0
- package/dist/tools/internal-tools/registry.cjs +6 -0
- package/dist/tools/internal-tools/registry.d.ts +35 -1
- package/dist/tools/internal-tools/registry.d.ts.map +1 -1
- package/dist/tools/internal-tools/registry.js +6 -0
- package/dist/tools/schemas.d.ts +1 -1
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/tool-call-metadata.cjs +75 -0
- package/dist/tools/tool-call-metadata.d.ts +16 -0
- package/dist/tools/tool-call-metadata.d.ts.map +1 -0
- package/dist/tools/tool-call-metadata.js +51 -0
- package/dist/tools/tool-manager.cjs +481 -103
- package/dist/tools/tool-manager.d.ts +131 -9
- package/dist/tools/tool-manager.d.ts.map +1 -1
- package/dist/tools/tool-manager.js +482 -104
- package/dist/utils/api-key-resolver.cjs +5 -2
- package/dist/utils/api-key-resolver.d.ts.map +1 -1
- package/dist/utils/api-key-resolver.js +5 -2
- package/dist/utils/env.cjs +49 -0
- package/dist/utils/env.d.ts +4 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +24 -0
- package/dist/utils/index.cjs +3 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/service-initializer.cjs +25 -7
- package/dist/utils/service-initializer.d.ts +24 -1
- package/dist/utils/service-initializer.d.ts.map +1 -1
- package/dist/utils/service-initializer.js +25 -7
- package/package.json +6 -2
- package/dist/llm/registry.cjs +0 -1631
- package/dist/llm/registry.d.ts.map +0 -1
- package/dist/llm/registry.js +0 -1586
|
@@ -73,7 +73,9 @@ var import_errors2 = require("../errors/index.js");
|
|
|
73
73
|
var import_types2 = require("../logger/v2/types.js");
|
|
74
74
|
var import_types3 = require("../approval/types.js");
|
|
75
75
|
var import_decorators = require("../telemetry/decorators.js");
|
|
76
|
+
var import_tool_call_metadata = require("./tool-call-metadata.js");
|
|
76
77
|
var import_bash_pattern_utils = require("./bash-pattern-utils.js");
|
|
78
|
+
var import_env = require("../utils/env.js");
|
|
77
79
|
var _ToolManager_decorators, _init;
|
|
78
80
|
_ToolManager_decorators = [(0, import_decorators.InstrumentClass)({
|
|
79
81
|
prefix: "tool",
|
|
@@ -104,6 +106,14 @@ let _ToolManager = class _ToolManager {
|
|
|
104
106
|
toolsCache = {};
|
|
105
107
|
cacheValid = false;
|
|
106
108
|
logger;
|
|
109
|
+
// Session-level auto-approve tools for skills
|
|
110
|
+
// When a skill with allowedTools is invoked, those tools are auto-approved (skip confirmation)
|
|
111
|
+
// This is ADDITIVE - other tools are NOT blocked, they just go through normal approval flow
|
|
112
|
+
sessionAutoApproveTools = /* @__PURE__ */ new Map();
|
|
113
|
+
// Session-level auto-approve tools set by users (UI)
|
|
114
|
+
sessionUserAutoApproveTools = /* @__PURE__ */ new Map();
|
|
115
|
+
sessionDisabledTools = /* @__PURE__ */ new Map();
|
|
116
|
+
globalDisabledTools = [];
|
|
107
117
|
constructor(mcpManager, approvalManager, allowedToolsProvider, approvalMode, agentEventBus, toolPolicies, options, logger) {
|
|
108
118
|
this.mcpManager = mcpManager;
|
|
109
119
|
this.approvalManager = approvalManager;
|
|
@@ -155,6 +165,204 @@ let _ToolManager = class _ToolManager {
|
|
|
155
165
|
this.logger.debug("Agent reference configured for custom tools");
|
|
156
166
|
}
|
|
157
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Set prompt manager for invoke_skill tool (called after construction to avoid circular dependencies)
|
|
170
|
+
* Must be called before initialize() if invoke_skill tool is enabled
|
|
171
|
+
*/
|
|
172
|
+
setPromptManager(promptManager) {
|
|
173
|
+
if (this.internalToolsProvider) {
|
|
174
|
+
this.internalToolsProvider.setPromptManager(promptManager);
|
|
175
|
+
this.logger.debug("PromptManager reference configured for invoke_skill tool");
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Set task forker for context:fork skill execution (late-binding)
|
|
180
|
+
* Called by agent-spawner custom tool provider after RuntimeService is created.
|
|
181
|
+
* This enables invoke_skill to fork execution to an isolated subagent.
|
|
182
|
+
*/
|
|
183
|
+
setTaskForker(taskForker) {
|
|
184
|
+
if (this.internalToolsProvider) {
|
|
185
|
+
this.internalToolsProvider.setTaskForker(taskForker);
|
|
186
|
+
this.logger.debug(
|
|
187
|
+
"TaskForker reference configured for invoke_skill (context:fork support)"
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// ============= SESSION AUTO-APPROVE TOOLS =============
|
|
192
|
+
/**
|
|
193
|
+
* Set session-level auto-approve tools.
|
|
194
|
+
* When set, these tools will skip confirmation prompts for this session.
|
|
195
|
+
* This is ADDITIVE - other tools are NOT blocked, they just go through normal approval flow.
|
|
196
|
+
*
|
|
197
|
+
* @param sessionId The session ID
|
|
198
|
+
* @param autoApproveTools Array of tool names to auto-approve (e.g., ['custom--bash_exec', 'custom--read_file'])
|
|
199
|
+
*/
|
|
200
|
+
setSessionAutoApproveTools(sessionId, autoApproveTools) {
|
|
201
|
+
if (autoApproveTools.length === 0) {
|
|
202
|
+
this.clearSessionAutoApproveTools(sessionId);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
this.sessionAutoApproveTools.set(sessionId, autoApproveTools);
|
|
206
|
+
this.logger.info(
|
|
207
|
+
`Session auto-approve tools set for '${sessionId}': ${autoApproveTools.length} tools`
|
|
208
|
+
);
|
|
209
|
+
this.logger.debug(`Auto-approve tools: ${autoApproveTools.join(", ")}`);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Set session-level auto-approve tools chosen by the user.
|
|
213
|
+
*/
|
|
214
|
+
setSessionUserAutoApproveTools(sessionId, autoApproveTools) {
|
|
215
|
+
if (autoApproveTools.length === 0) {
|
|
216
|
+
this.clearSessionUserAutoApproveTools(sessionId);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
this.sessionUserAutoApproveTools.set(sessionId, autoApproveTools);
|
|
220
|
+
this.logger.info(
|
|
221
|
+
`Session user auto-approve tools set for '${sessionId}': ${autoApproveTools.length} tools`
|
|
222
|
+
);
|
|
223
|
+
this.logger.debug(`User auto-approve tools: ${autoApproveTools.join(", ")}`);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Clear session-level auto-approve tools chosen by the user.
|
|
227
|
+
*/
|
|
228
|
+
clearSessionUserAutoApproveTools(sessionId) {
|
|
229
|
+
const hadAutoApprove = this.sessionUserAutoApproveTools.has(sessionId);
|
|
230
|
+
this.sessionUserAutoApproveTools.delete(sessionId);
|
|
231
|
+
if (hadAutoApprove) {
|
|
232
|
+
this.logger.info(`Session user auto-approve tools cleared for '${sessionId}'`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Clear session-level auto-approve tools.
|
|
237
|
+
* Call this when the session ends or when the skill completes.
|
|
238
|
+
*
|
|
239
|
+
* @param sessionId The session ID to clear auto-approve tools for
|
|
240
|
+
*/
|
|
241
|
+
clearSessionAutoApproveTools(sessionId) {
|
|
242
|
+
const hadAutoApprove = this.sessionAutoApproveTools.has(sessionId);
|
|
243
|
+
this.sessionAutoApproveTools.delete(sessionId);
|
|
244
|
+
if (hadAutoApprove) {
|
|
245
|
+
this.logger.info(`Session auto-approve tools cleared for '${sessionId}'`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
hasSessionUserAutoApproveTools(sessionId) {
|
|
249
|
+
return this.sessionUserAutoApproveTools.has(sessionId);
|
|
250
|
+
}
|
|
251
|
+
// ============= ENABLED/DISABLED TOOLS =============
|
|
252
|
+
/**
|
|
253
|
+
* Set global disabled tools (agent-level preferences).
|
|
254
|
+
*/
|
|
255
|
+
setGlobalDisabledTools(toolNames) {
|
|
256
|
+
this.globalDisabledTools = [...toolNames];
|
|
257
|
+
this.logger.info("Global disabled tools updated", {
|
|
258
|
+
count: toolNames.length
|
|
259
|
+
});
|
|
260
|
+
this.agentEventBus.emit("tools:enabled-updated", {
|
|
261
|
+
scope: "global",
|
|
262
|
+
disabledTools: [...this.globalDisabledTools]
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
getGlobalDisabledTools() {
|
|
266
|
+
return [...this.globalDisabledTools];
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Set session-level disabled tools (overrides global list).
|
|
270
|
+
*/
|
|
271
|
+
setSessionDisabledTools(sessionId, toolNames) {
|
|
272
|
+
if (toolNames.length === 0) {
|
|
273
|
+
this.clearSessionDisabledTools(sessionId);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
this.sessionDisabledTools.set(sessionId, [...toolNames]);
|
|
277
|
+
this.logger.info("Session disabled tools updated", {
|
|
278
|
+
sessionId,
|
|
279
|
+
count: toolNames.length
|
|
280
|
+
});
|
|
281
|
+
this.agentEventBus.emit("tools:enabled-updated", {
|
|
282
|
+
scope: "session",
|
|
283
|
+
sessionId,
|
|
284
|
+
disabledTools: [...toolNames]
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Clear session-level disabled tools.
|
|
289
|
+
*/
|
|
290
|
+
clearSessionDisabledTools(sessionId) {
|
|
291
|
+
const hadOverrides = this.sessionDisabledTools.has(sessionId);
|
|
292
|
+
this.sessionDisabledTools.delete(sessionId);
|
|
293
|
+
if (hadOverrides) {
|
|
294
|
+
this.logger.info("Session disabled tools cleared", { sessionId });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Get disabled tools for a session (session override wins).
|
|
299
|
+
*/
|
|
300
|
+
getDisabledTools(sessionId) {
|
|
301
|
+
if (sessionId && this.sessionDisabledTools.has(sessionId)) {
|
|
302
|
+
return this.sessionDisabledTools.get(sessionId) ?? [];
|
|
303
|
+
}
|
|
304
|
+
return this.globalDisabledTools;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Filter a tool set based on disabled tools for a session.
|
|
308
|
+
*/
|
|
309
|
+
filterToolsForSession(toolSet, sessionId) {
|
|
310
|
+
const disabled = new Set(this.getDisabledTools(sessionId));
|
|
311
|
+
if (disabled.size === 0) {
|
|
312
|
+
return toolSet;
|
|
313
|
+
}
|
|
314
|
+
return Object.fromEntries(
|
|
315
|
+
Object.entries(toolSet).filter(([toolName]) => !disabled.has(toolName))
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Check if a session has auto-approve tools set.
|
|
320
|
+
*
|
|
321
|
+
* @param sessionId The session ID to check
|
|
322
|
+
* @returns true if the session has auto-approve tools
|
|
323
|
+
*/
|
|
324
|
+
hasSessionAutoApproveTools(sessionId) {
|
|
325
|
+
return this.sessionAutoApproveTools.has(sessionId);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Get the auto-approve tools for a session (skill-provided list).
|
|
329
|
+
*
|
|
330
|
+
* @param sessionId The session ID to check
|
|
331
|
+
* @returns Array of auto-approve tool names, or undefined if none set
|
|
332
|
+
*/
|
|
333
|
+
getSessionAutoApproveTools(sessionId) {
|
|
334
|
+
return this.sessionAutoApproveTools.get(sessionId);
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Get the user auto-approve tools for a session.
|
|
338
|
+
*/
|
|
339
|
+
getSessionUserAutoApproveTools(sessionId) {
|
|
340
|
+
return this.sessionUserAutoApproveTools.get(sessionId);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Combined auto-approve list for a session.
|
|
344
|
+
*/
|
|
345
|
+
getCombinedSessionAutoApproveTools(sessionId) {
|
|
346
|
+
return [
|
|
347
|
+
...this.sessionAutoApproveTools.get(sessionId) ?? [],
|
|
348
|
+
...this.sessionUserAutoApproveTools.get(sessionId) ?? []
|
|
349
|
+
];
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Check if a tool should be auto-approved for a session.
|
|
353
|
+
* Returns true if the tool is in the session's auto-approve list.
|
|
354
|
+
*
|
|
355
|
+
* @param sessionId The session ID
|
|
356
|
+
* @param toolName The tool name to check
|
|
357
|
+
* @returns true if the tool should be auto-approved
|
|
358
|
+
*/
|
|
359
|
+
isToolAutoApprovedForSession(sessionId, toolName) {
|
|
360
|
+
const autoApproveTools = this.getCombinedSessionAutoApproveTools(sessionId);
|
|
361
|
+
if (autoApproveTools.length === 0) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
return autoApproveTools.some((pattern) => this.matchesToolPolicy(toolName, pattern));
|
|
365
|
+
}
|
|
158
366
|
/**
|
|
159
367
|
* Invalidate the tools cache when tool sources change
|
|
160
368
|
*/
|
|
@@ -180,6 +388,14 @@ let _ToolManager = class _ToolManager {
|
|
|
180
388
|
);
|
|
181
389
|
this.invalidateCache();
|
|
182
390
|
});
|
|
391
|
+
this.agentEventBus.on("run:complete", (payload) => {
|
|
392
|
+
if (this.hasSessionAutoApproveTools(payload.sessionId)) {
|
|
393
|
+
this.logger.debug(
|
|
394
|
+
`\u{1F513} Run complete, clearing session auto-approve tools for '${payload.sessionId}'`
|
|
395
|
+
);
|
|
396
|
+
this.clearSessionAutoApproveTools(payload.sessionId);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
183
399
|
}
|
|
184
400
|
// ==================== Bash Pattern Approval Helpers ====================
|
|
185
401
|
/**
|
|
@@ -339,7 +555,8 @@ let _ToolManager = class _ToolManager {
|
|
|
339
555
|
allTools[qualifiedName] = {
|
|
340
556
|
...toolDef,
|
|
341
557
|
name: qualifiedName,
|
|
342
|
-
description: `${toolDef.description || "No description provided"} (internal tool)
|
|
558
|
+
description: `${toolDef.description || "No description provided"} (internal tool)`,
|
|
559
|
+
parameters: (0, import_tool_call_metadata.wrapToolParametersSchema)(toolDef.parameters)
|
|
343
560
|
};
|
|
344
561
|
}
|
|
345
562
|
for (const [toolName, toolDef] of Object.entries(customTools)) {
|
|
@@ -347,7 +564,8 @@ let _ToolManager = class _ToolManager {
|
|
|
347
564
|
allTools[qualifiedName] = {
|
|
348
565
|
...toolDef,
|
|
349
566
|
name: qualifiedName,
|
|
350
|
-
description: `${toolDef.description || "No description provided"} (custom tool)
|
|
567
|
+
description: `${toolDef.description || "No description provided"} (custom tool)`,
|
|
568
|
+
parameters: (0, import_tool_call_metadata.wrapToolParametersSchema)(toolDef.parameters)
|
|
351
569
|
};
|
|
352
570
|
}
|
|
353
571
|
for (const [toolName, toolDef] of Object.entries(mcpTools)) {
|
|
@@ -355,7 +573,8 @@ let _ToolManager = class _ToolManager {
|
|
|
355
573
|
allTools[qualifiedName] = {
|
|
356
574
|
...toolDef,
|
|
357
575
|
name: qualifiedName,
|
|
358
|
-
description: `${toolDef.description || "No description provided"} (via MCP servers)
|
|
576
|
+
description: `${toolDef.description || "No description provided"} (via MCP servers)`,
|
|
577
|
+
parameters: (0, import_tool_call_metadata.wrapToolParametersSchema)(toolDef.parameters)
|
|
359
578
|
};
|
|
360
579
|
}
|
|
361
580
|
const totalTools = Object.keys(allTools).length;
|
|
@@ -391,21 +610,25 @@ let _ToolManager = class _ToolManager {
|
|
|
391
610
|
* @param abortSignal Optional abort signal for cancellation support
|
|
392
611
|
*/
|
|
393
612
|
async executeTool(toolName, args, toolCallId, sessionId, abortSignal) {
|
|
613
|
+
const { toolArgs: rawToolArgs, meta } = (0, import_tool_call_metadata.extractToolCallMeta)(args);
|
|
614
|
+
let toolArgs = rawToolArgs;
|
|
615
|
+
const backgroundTasksEnabled = (0, import_env.isBackgroundTasksEnabled)();
|
|
394
616
|
this.logger.debug(`\u{1F527} Tool execution requested: '${toolName}' (toolCallId: ${toolCallId})`);
|
|
395
|
-
this.logger.debug(`Tool args: ${JSON.stringify(
|
|
617
|
+
this.logger.debug(`Tool args: ${JSON.stringify(toolArgs, null, 2)}`);
|
|
396
618
|
if (sessionId) {
|
|
397
619
|
this.agentEventBus.emit("llm:tool-call", {
|
|
398
620
|
toolName,
|
|
399
|
-
args,
|
|
621
|
+
args: toolArgs,
|
|
400
622
|
callId: toolCallId,
|
|
401
623
|
sessionId
|
|
402
624
|
});
|
|
403
625
|
}
|
|
404
626
|
const { requireApproval, approvalStatus } = await this.handleToolApproval(
|
|
405
627
|
toolName,
|
|
406
|
-
|
|
628
|
+
toolArgs,
|
|
407
629
|
toolCallId,
|
|
408
|
-
sessionId
|
|
630
|
+
sessionId,
|
|
631
|
+
meta.callDescription
|
|
409
632
|
);
|
|
410
633
|
this.logger.debug(`\u2705 Tool execution approved: ${toolName}`);
|
|
411
634
|
this.logger.info(
|
|
@@ -422,7 +645,7 @@ let _ToolManager = class _ToolManager {
|
|
|
422
645
|
if (this.pluginManager && this.sessionManager && this.stateManager) {
|
|
423
646
|
const beforePayload = {
|
|
424
647
|
toolName,
|
|
425
|
-
args,
|
|
648
|
+
args: toolArgs,
|
|
426
649
|
...sessionId !== void 0 && { sessionId }
|
|
427
650
|
};
|
|
428
651
|
const modifiedPayload = await this.pluginManager.executePlugins(
|
|
@@ -436,10 +659,21 @@ let _ToolManager = class _ToolManager {
|
|
|
436
659
|
...sessionId !== void 0 && { sessionId }
|
|
437
660
|
}
|
|
438
661
|
);
|
|
439
|
-
|
|
662
|
+
toolArgs = modifiedPayload.args;
|
|
440
663
|
}
|
|
441
664
|
try {
|
|
442
665
|
let result;
|
|
666
|
+
const registerBackgroundTask = (promise, description) => {
|
|
667
|
+
const fallbackId = `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
668
|
+
return {
|
|
669
|
+
result: {
|
|
670
|
+
taskId: toolCallId ?? fallbackId,
|
|
671
|
+
status: "running",
|
|
672
|
+
description
|
|
673
|
+
},
|
|
674
|
+
promise
|
|
675
|
+
};
|
|
676
|
+
};
|
|
443
677
|
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
444
678
|
this.logger.debug(`\u{1F527} Detected MCP tool: '${toolName}'`);
|
|
445
679
|
const actualToolName = toolName.substring(_ToolManager.MCP_TOOL_PREFIX.length);
|
|
@@ -447,7 +681,34 @@ let _ToolManager = class _ToolManager {
|
|
|
447
681
|
throw import_errors.ToolError.invalidName(toolName, "tool name cannot be empty after prefix");
|
|
448
682
|
}
|
|
449
683
|
this.logger.debug(`\u{1F3AF} MCP routing: '${toolName}' -> '${actualToolName}'`);
|
|
450
|
-
|
|
684
|
+
const runInBackground = backgroundTasksEnabled && meta.runInBackground === true && sessionId !== void 0;
|
|
685
|
+
if (meta.runInBackground === true && !backgroundTasksEnabled) {
|
|
686
|
+
this.logger.debug(
|
|
687
|
+
"Background tool execution disabled; running synchronously instead.",
|
|
688
|
+
{ toolName }
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
if (runInBackground) {
|
|
692
|
+
const backgroundSessionId = sessionId;
|
|
693
|
+
const { result: backgroundResult, promise } = registerBackgroundTask(
|
|
694
|
+
this.mcpManager.executeTool(actualToolName, toolArgs, backgroundSessionId),
|
|
695
|
+
`MCP tool ${actualToolName}`
|
|
696
|
+
);
|
|
697
|
+
this.agentEventBus.emit("tool:background", {
|
|
698
|
+
toolName,
|
|
699
|
+
toolCallId: backgroundResult.taskId,
|
|
700
|
+
sessionId: backgroundSessionId,
|
|
701
|
+
description: backgroundResult.description,
|
|
702
|
+
promise,
|
|
703
|
+
...meta.timeoutMs !== void 0 && { timeoutMs: meta.timeoutMs },
|
|
704
|
+
...meta.notifyOnComplete !== void 0 && {
|
|
705
|
+
notifyOnComplete: meta.notifyOnComplete
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
result = backgroundResult;
|
|
709
|
+
} else {
|
|
710
|
+
result = await this.mcpManager.executeTool(actualToolName, toolArgs, sessionId);
|
|
711
|
+
}
|
|
451
712
|
} else if (toolName.startsWith(_ToolManager.INTERNAL_TOOL_PREFIX)) {
|
|
452
713
|
this.logger.debug(`\u{1F527} Detected internal tool: '${toolName}'`);
|
|
453
714
|
const actualToolName = toolName.substring(_ToolManager.INTERNAL_TOOL_PREFIX.length);
|
|
@@ -458,13 +719,46 @@ let _ToolManager = class _ToolManager {
|
|
|
458
719
|
throw import_errors.ToolError.internalToolsNotInitialized(toolName);
|
|
459
720
|
}
|
|
460
721
|
this.logger.debug(`\u{1F3AF} Internal routing: '${toolName}' -> '${actualToolName}'`);
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
722
|
+
const runInBackground = backgroundTasksEnabled && meta.runInBackground === true && sessionId !== void 0;
|
|
723
|
+
if (meta.runInBackground === true && !backgroundTasksEnabled) {
|
|
724
|
+
this.logger.debug(
|
|
725
|
+
"Background tool execution disabled; running synchronously instead.",
|
|
726
|
+
{ toolName }
|
|
727
|
+
);
|
|
728
|
+
}
|
|
729
|
+
if (runInBackground) {
|
|
730
|
+
const backgroundSessionId = sessionId;
|
|
731
|
+
const { result: backgroundResult, promise } = registerBackgroundTask(
|
|
732
|
+
this.internalToolsProvider.executeTool(
|
|
733
|
+
actualToolName,
|
|
734
|
+
toolArgs,
|
|
735
|
+
backgroundSessionId,
|
|
736
|
+
abortSignal,
|
|
737
|
+
toolCallId
|
|
738
|
+
),
|
|
739
|
+
`Internal tool ${actualToolName}`
|
|
740
|
+
);
|
|
741
|
+
this.agentEventBus.emit("tool:background", {
|
|
742
|
+
toolName,
|
|
743
|
+
toolCallId: backgroundResult.taskId,
|
|
744
|
+
sessionId: backgroundSessionId,
|
|
745
|
+
description: backgroundResult.description,
|
|
746
|
+
promise,
|
|
747
|
+
...meta.timeoutMs !== void 0 && { timeoutMs: meta.timeoutMs },
|
|
748
|
+
...meta.notifyOnComplete !== void 0 && {
|
|
749
|
+
notifyOnComplete: meta.notifyOnComplete
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
result = backgroundResult;
|
|
753
|
+
} else {
|
|
754
|
+
result = await this.internalToolsProvider.executeTool(
|
|
755
|
+
actualToolName,
|
|
756
|
+
toolArgs,
|
|
757
|
+
sessionId,
|
|
758
|
+
abortSignal,
|
|
759
|
+
toolCallId
|
|
760
|
+
);
|
|
761
|
+
}
|
|
468
762
|
} else if (toolName.startsWith(_ToolManager.CUSTOM_TOOL_PREFIX)) {
|
|
469
763
|
this.logger.debug(`\u{1F527} Detected custom tool: '${toolName}'`);
|
|
470
764
|
const actualToolName = toolName.substring(_ToolManager.CUSTOM_TOOL_PREFIX.length);
|
|
@@ -475,13 +769,46 @@ let _ToolManager = class _ToolManager {
|
|
|
475
769
|
throw import_errors.ToolError.internalToolsNotInitialized(toolName);
|
|
476
770
|
}
|
|
477
771
|
this.logger.debug(`\u{1F3AF} Custom routing: '${toolName}' -> '${actualToolName}'`);
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
772
|
+
const runInBackground = backgroundTasksEnabled && meta.runInBackground === true && sessionId !== void 0;
|
|
773
|
+
if (meta.runInBackground === true && !backgroundTasksEnabled) {
|
|
774
|
+
this.logger.debug(
|
|
775
|
+
"Background tool execution disabled; running synchronously instead.",
|
|
776
|
+
{ toolName }
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
if (runInBackground) {
|
|
780
|
+
const backgroundSessionId = sessionId;
|
|
781
|
+
const { result: backgroundResult, promise } = registerBackgroundTask(
|
|
782
|
+
this.internalToolsProvider.executeTool(
|
|
783
|
+
actualToolName,
|
|
784
|
+
toolArgs,
|
|
785
|
+
backgroundSessionId,
|
|
786
|
+
abortSignal,
|
|
787
|
+
toolCallId
|
|
788
|
+
),
|
|
789
|
+
`Custom tool ${actualToolName}`
|
|
790
|
+
);
|
|
791
|
+
this.agentEventBus.emit("tool:background", {
|
|
792
|
+
toolName,
|
|
793
|
+
toolCallId: backgroundResult.taskId,
|
|
794
|
+
sessionId: backgroundSessionId,
|
|
795
|
+
description: backgroundResult.description,
|
|
796
|
+
promise,
|
|
797
|
+
...meta.timeoutMs !== void 0 && { timeoutMs: meta.timeoutMs },
|
|
798
|
+
...meta.notifyOnComplete !== void 0 && {
|
|
799
|
+
notifyOnComplete: meta.notifyOnComplete
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
result = backgroundResult;
|
|
803
|
+
} else {
|
|
804
|
+
result = await this.internalToolsProvider.executeTool(
|
|
805
|
+
actualToolName,
|
|
806
|
+
toolArgs,
|
|
807
|
+
sessionId,
|
|
808
|
+
abortSignal,
|
|
809
|
+
toolCallId
|
|
810
|
+
);
|
|
811
|
+
}
|
|
485
812
|
} else {
|
|
486
813
|
this.logger.debug(`\u{1F527} Detected tool without proper prefix: '${toolName}'`);
|
|
487
814
|
const stats = await this.getToolStats();
|
|
@@ -731,21 +1058,34 @@ let _ToolManager = class _ToolManager {
|
|
|
731
1058
|
throw import_errors.ToolError.executionDenied(toolName, sessionId);
|
|
732
1059
|
}
|
|
733
1060
|
/**
|
|
734
|
-
* Handle tool approval
|
|
735
|
-
*
|
|
736
|
-
|
|
1061
|
+
* Handle tool approval flow. Checks various precedence levels to determine
|
|
1062
|
+
* if a tool should be auto-approved, denied, or requires manual approval.
|
|
1063
|
+
*/
|
|
1064
|
+
async handleToolApproval(toolName, args, toolCallId, sessionId, callDescription) {
|
|
1065
|
+
const quickResult = await this.tryQuickApprovalResolution(toolName, args, sessionId);
|
|
1066
|
+
if (quickResult !== null) {
|
|
1067
|
+
return quickResult;
|
|
1068
|
+
}
|
|
1069
|
+
return this.requestManualApproval(toolName, args, toolCallId, sessionId, callDescription);
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Try to resolve tool approval quickly based on policies and cached permissions.
|
|
1073
|
+
* Returns null if manual approval is needed.
|
|
737
1074
|
*
|
|
738
|
-
*
|
|
739
|
-
*
|
|
740
|
-
*
|
|
741
|
-
*
|
|
1075
|
+
* Precedence order (highest to lowest):
|
|
1076
|
+
* 1. Static deny list (security - always blocks)
|
|
1077
|
+
* 2. Custom approval override (tool-specific approval flows)
|
|
1078
|
+
* 3. Session auto-approve (skill allowed-tools)
|
|
1079
|
+
* 4. Static allow list
|
|
1080
|
+
* 5. Dynamic "remembered" allowed list
|
|
1081
|
+
* 6. Bash command patterns
|
|
1082
|
+
* 7. Approval mode (auto-approve/auto-deny)
|
|
742
1083
|
*/
|
|
743
|
-
async
|
|
1084
|
+
async tryQuickApprovalResolution(toolName, args, sessionId) {
|
|
744
1085
|
if (this.isInAlwaysDenyList(toolName)) {
|
|
745
1086
|
this.logger.info(
|
|
746
1087
|
`Tool '${toolName}' is in static deny list \u2013 blocking execution (session: ${sessionId ?? "global"})`
|
|
747
1088
|
);
|
|
748
|
-
this.logger.debug(`\u{1F6AB} Tool execution blocked by policy: ${toolName}`);
|
|
749
1089
|
throw import_errors.ToolError.executionDenied(toolName, sessionId);
|
|
750
1090
|
}
|
|
751
1091
|
const customApprovalResult = await this.checkCustomApprovalOverride(
|
|
@@ -756,25 +1096,29 @@ let _ToolManager = class _ToolManager {
|
|
|
756
1096
|
if (customApprovalResult.handled) {
|
|
757
1097
|
return { requireApproval: true, approvalStatus: "approved" };
|
|
758
1098
|
}
|
|
1099
|
+
if (sessionId && this.isToolAutoApprovedForSession(sessionId, toolName)) {
|
|
1100
|
+
this.logger.info(
|
|
1101
|
+
`Tool '${toolName}' is in session's auto-approve list \u2013 skipping confirmation (session: ${sessionId})`
|
|
1102
|
+
);
|
|
1103
|
+
return { requireApproval: false };
|
|
1104
|
+
}
|
|
759
1105
|
if (this.isInAlwaysAllowList(toolName)) {
|
|
760
1106
|
this.logger.info(
|
|
761
1107
|
`Tool '${toolName}' is in static allow list \u2013 skipping confirmation (session: ${sessionId ?? "global"})`
|
|
762
1108
|
);
|
|
763
1109
|
return { requireApproval: false };
|
|
764
1110
|
}
|
|
765
|
-
|
|
766
|
-
if (isAllowed) {
|
|
1111
|
+
if (await this.allowedToolsProvider.isToolAllowed(toolName, sessionId)) {
|
|
767
1112
|
this.logger.info(
|
|
768
1113
|
`Tool '${toolName}' already allowed for session '${sessionId ?? "global"}' \u2013 skipping confirmation.`
|
|
769
1114
|
);
|
|
770
1115
|
return { requireApproval: false };
|
|
771
1116
|
}
|
|
772
|
-
let bashPatternResult;
|
|
773
1117
|
if (this.isBashTool(toolName)) {
|
|
774
1118
|
const command = args.command;
|
|
775
1119
|
if (command) {
|
|
776
|
-
|
|
777
|
-
if (
|
|
1120
|
+
const bashResult = this.checkBashPatternApproval(command);
|
|
1121
|
+
if (bashResult.approved) {
|
|
778
1122
|
this.logger.info(
|
|
779
1123
|
`Bash command '${command}' matched approved pattern \u2013 skipping confirmation.`
|
|
780
1124
|
);
|
|
@@ -790,79 +1134,38 @@ let _ToolManager = class _ToolManager {
|
|
|
790
1134
|
this.logger.debug(`\u{1F6AB} Auto-denying tool execution: ${toolName}`);
|
|
791
1135
|
throw import_errors.ToolError.executionDenied(toolName, sessionId);
|
|
792
1136
|
}
|
|
1137
|
+
return null;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Request manual approval from the user for a tool execution.
|
|
1141
|
+
* Generates preview, sends approval request, and handles the response.
|
|
1142
|
+
*/
|
|
1143
|
+
async requestManualApproval(toolName, args, toolCallId, sessionId, callDescription) {
|
|
793
1144
|
this.logger.info(
|
|
794
1145
|
`Tool confirmation requested for ${toolName}, sessionId: ${sessionId ?? "global"}`
|
|
795
1146
|
);
|
|
796
1147
|
try {
|
|
797
|
-
|
|
798
|
-
const actualToolName = toolName.replace(/^internal--/, "").replace(/^custom--/, "");
|
|
799
|
-
const internalTool = this.internalToolsProvider?.getTool(actualToolName);
|
|
800
|
-
if (internalTool?.generatePreview) {
|
|
801
|
-
try {
|
|
802
|
-
const context = { sessionId, toolCallId };
|
|
803
|
-
const preview = await internalTool.generatePreview(args, context);
|
|
804
|
-
displayPreview = preview ?? void 0;
|
|
805
|
-
this.logger.debug(`Generated preview for ${toolName}`);
|
|
806
|
-
} catch (previewError) {
|
|
807
|
-
if (previewError instanceof import_errors2.DextoRuntimeError && previewError.code === import_error_codes.ToolErrorCode.VALIDATION_FAILED) {
|
|
808
|
-
this.logger.debug(
|
|
809
|
-
`Validation failed for ${toolName}: ${previewError.message}`
|
|
810
|
-
);
|
|
811
|
-
throw previewError;
|
|
812
|
-
}
|
|
813
|
-
this.logger.debug(
|
|
814
|
-
`Preview generation failed for ${toolName}: ${previewError instanceof Error ? previewError.message : String(previewError)}`
|
|
815
|
-
);
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
const requestData = {
|
|
1148
|
+
const displayPreview = await this.generateToolPreview(
|
|
819
1149
|
toolName,
|
|
1150
|
+
args,
|
|
820
1151
|
toolCallId,
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
1152
|
+
sessionId
|
|
1153
|
+
);
|
|
1154
|
+
const suggestedPatterns = this.getBashSuggestedPatterns(toolName, args);
|
|
1155
|
+
const response = await this.approvalManager.requestToolConfirmation({
|
|
1156
|
+
toolName,
|
|
1157
|
+
toolCallId,
|
|
1158
|
+
args,
|
|
1159
|
+
...callDescription !== void 0 && { description: callDescription },
|
|
1160
|
+
...sessionId !== void 0 && { sessionId },
|
|
1161
|
+
...displayPreview !== void 0 && { displayPreview },
|
|
1162
|
+
...suggestedPatterns !== void 0 && { suggestedPatterns }
|
|
1163
|
+
});
|
|
833
1164
|
if (response.status === import_types3.ApprovalStatus.APPROVED && response.data) {
|
|
834
|
-
|
|
835
|
-
const rememberPattern = "rememberPattern" in response.data ? response.data.rememberPattern : void 0;
|
|
836
|
-
if (rememberChoice) {
|
|
837
|
-
const allowSessionId = sessionId ?? response.sessionId;
|
|
838
|
-
await this.allowedToolsProvider.allowTool(toolName, allowSessionId);
|
|
839
|
-
this.logger.info(
|
|
840
|
-
`Tool '${toolName}' added to allowed tools for session '${allowSessionId ?? "global"}' (remember choice selected)`
|
|
841
|
-
);
|
|
842
|
-
this.autoApprovePendingToolRequests(toolName, allowSessionId);
|
|
843
|
-
} else if (rememberPattern && typeof rememberPattern === "string" && this.isBashTool(toolName)) {
|
|
844
|
-
this.approvalManager.addBashPattern(rememberPattern);
|
|
845
|
-
this.logger.info(
|
|
846
|
-
`Bash pattern '${rememberPattern}' added for session approval`
|
|
847
|
-
);
|
|
848
|
-
this.autoApprovePendingBashRequests(rememberPattern, sessionId);
|
|
849
|
-
}
|
|
1165
|
+
await this.handleRememberChoice(toolName, response, sessionId);
|
|
850
1166
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
if (response.status === import_types3.ApprovalStatus.CANCELLED && response.reason === "timeout") {
|
|
854
|
-
this.logger.info(
|
|
855
|
-
`Tool confirmation timed out for ${toolName}, sessionId: ${sessionId ?? "global"}`
|
|
856
|
-
);
|
|
857
|
-
this.logger.debug(`\u23F1\uFE0F Tool execution timed out: ${toolName}`);
|
|
858
|
-
const timeoutMs = response.timeoutMs ?? 0;
|
|
859
|
-
throw import_errors.ToolError.executionTimeout(toolName, timeoutMs, sessionId);
|
|
860
|
-
}
|
|
861
|
-
this.logger.info(
|
|
862
|
-
`Tool confirmation denied for ${toolName}, sessionId: ${sessionId ?? "global"}, reason: ${response.reason ?? "unknown"}`
|
|
863
|
-
);
|
|
864
|
-
this.logger.debug(`\u{1F6AB} Tool execution denied: ${toolName}`);
|
|
865
|
-
throw import_errors.ToolError.executionDenied(toolName, sessionId);
|
|
1167
|
+
if (response.status !== import_types3.ApprovalStatus.APPROVED) {
|
|
1168
|
+
this.handleApprovalDenied(toolName, response, sessionId);
|
|
866
1169
|
}
|
|
867
1170
|
this.logger.info(
|
|
868
1171
|
`Tool confirmation approved for ${toolName}, sessionId: ${sessionId ?? "global"}`
|
|
@@ -875,6 +1178,81 @@ let _ToolManager = class _ToolManager {
|
|
|
875
1178
|
throw error;
|
|
876
1179
|
}
|
|
877
1180
|
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Generate a preview for the tool approval UI if the tool supports it.
|
|
1183
|
+
*/
|
|
1184
|
+
async generateToolPreview(toolName, args, toolCallId, sessionId) {
|
|
1185
|
+
const actualToolName = toolName.replace(/^internal--/, "").replace(/^custom--/, "");
|
|
1186
|
+
const internalTool = this.internalToolsProvider?.getTool(actualToolName);
|
|
1187
|
+
if (!internalTool?.generatePreview) {
|
|
1188
|
+
return void 0;
|
|
1189
|
+
}
|
|
1190
|
+
try {
|
|
1191
|
+
const context = { sessionId, toolCallId };
|
|
1192
|
+
const preview = await internalTool.generatePreview(args, context);
|
|
1193
|
+
this.logger.debug(`Generated preview for ${toolName}`);
|
|
1194
|
+
return preview ?? void 0;
|
|
1195
|
+
} catch (previewError) {
|
|
1196
|
+
if (previewError instanceof import_errors2.DextoRuntimeError && previewError.code === import_error_codes.ToolErrorCode.VALIDATION_FAILED) {
|
|
1197
|
+
this.logger.debug(`Validation failed for ${toolName}: ${previewError.message}`);
|
|
1198
|
+
throw previewError;
|
|
1199
|
+
}
|
|
1200
|
+
this.logger.debug(
|
|
1201
|
+
`Preview generation failed for ${toolName}: ${previewError instanceof Error ? previewError.message : String(previewError)}`
|
|
1202
|
+
);
|
|
1203
|
+
return void 0;
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
/**
|
|
1207
|
+
* Get suggested bash patterns for the approval UI.
|
|
1208
|
+
*/
|
|
1209
|
+
getBashSuggestedPatterns(toolName, args) {
|
|
1210
|
+
if (!this.isBashTool(toolName)) {
|
|
1211
|
+
return void 0;
|
|
1212
|
+
}
|
|
1213
|
+
const command = args.command;
|
|
1214
|
+
if (!command) {
|
|
1215
|
+
return void 0;
|
|
1216
|
+
}
|
|
1217
|
+
const result = this.checkBashPatternApproval(command);
|
|
1218
|
+
return result.suggestedPatterns?.length ? result.suggestedPatterns : void 0;
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* Handle "remember choice" or "remember pattern" when user approves a tool.
|
|
1222
|
+
*/
|
|
1223
|
+
async handleRememberChoice(toolName, response, sessionId) {
|
|
1224
|
+
const data = response.data;
|
|
1225
|
+
if (!data) return;
|
|
1226
|
+
const rememberChoice = data.rememberChoice;
|
|
1227
|
+
const rememberPattern = data.rememberPattern;
|
|
1228
|
+
if (rememberChoice) {
|
|
1229
|
+
const allowSessionId = sessionId ?? response.sessionId;
|
|
1230
|
+
await this.allowedToolsProvider.allowTool(toolName, allowSessionId);
|
|
1231
|
+
this.logger.info(
|
|
1232
|
+
`Tool '${toolName}' added to allowed tools for session '${allowSessionId ?? "global"}' (remember choice selected)`
|
|
1233
|
+
);
|
|
1234
|
+
this.autoApprovePendingToolRequests(toolName, allowSessionId);
|
|
1235
|
+
} else if (rememberPattern && this.isBashTool(toolName)) {
|
|
1236
|
+
this.approvalManager.addBashPattern(rememberPattern);
|
|
1237
|
+
this.logger.info(`Bash pattern '${rememberPattern}' added for session approval`);
|
|
1238
|
+
this.autoApprovePendingBashRequests(rememberPattern, sessionId);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
/**
|
|
1242
|
+
* Handle approval denied/timeout - throws appropriate error.
|
|
1243
|
+
*/
|
|
1244
|
+
handleApprovalDenied(toolName, response, sessionId) {
|
|
1245
|
+
if (response.status === import_types3.ApprovalStatus.CANCELLED && response.reason === import_types3.DenialReason.TIMEOUT) {
|
|
1246
|
+
this.logger.info(
|
|
1247
|
+
`Tool confirmation timed out for ${toolName}, sessionId: ${sessionId ?? "global"}`
|
|
1248
|
+
);
|
|
1249
|
+
throw import_errors.ToolError.executionTimeout(toolName, response.timeoutMs ?? 0, sessionId);
|
|
1250
|
+
}
|
|
1251
|
+
this.logger.info(
|
|
1252
|
+
`Tool confirmation denied for ${toolName}, sessionId: ${sessionId ?? "global"}, reason: ${response.reason ?? "unknown"}`
|
|
1253
|
+
);
|
|
1254
|
+
throw import_errors.ToolError.executionDenied(toolName, sessionId, response.message);
|
|
1255
|
+
}
|
|
878
1256
|
/**
|
|
879
1257
|
* Refresh tool discovery (call when MCP servers change)
|
|
880
1258
|
* Refreshes both MCPManager's cache (server capabilities) and ToolManager's cache (combined tools)
|