@dexto/core 1.6.0 → 1.6.1
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 +25 -5
- package/dist/agent/DextoAgent.d.ts +12 -1
- package/dist/agent/DextoAgent.d.ts.map +1 -1
- package/dist/agent/DextoAgent.js +25 -5
- package/dist/agent/schemas.d.ts +18 -18
- package/dist/approval/manager.cjs +87 -27
- package/dist/approval/manager.d.ts +10 -1
- package/dist/approval/manager.d.ts.map +1 -1
- package/dist/approval/manager.js +87 -27
- package/dist/approval/schemas.cjs +22 -8
- package/dist/approval/schemas.d.ts +276 -102
- package/dist/approval/schemas.d.ts.map +1 -1
- package/dist/approval/schemas.js +22 -8
- package/dist/context/manager.cjs +2 -2
- package/dist/context/manager.d.ts +2 -1
- package/dist/context/manager.d.ts.map +1 -1
- package/dist/context/manager.js +2 -2
- package/dist/context/types.d.ts +3 -2
- package/dist/context/types.d.ts.map +1 -1
- package/dist/events/index.d.ts +17 -12
- package/dist/events/index.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/types.d.ts +1 -22
- package/dist/hooks/types.d.ts.map +1 -1
- package/dist/llm/executor/stream-processor.cjs +3 -3
- package/dist/llm/executor/stream-processor.d.ts +3 -2
- package/dist/llm/executor/stream-processor.d.ts.map +1 -1
- package/dist/llm/executor/stream-processor.js +3 -3
- package/dist/llm/executor/turn-executor.cjs +3 -3
- package/dist/llm/executor/turn-executor.d.ts +1 -1
- package/dist/llm/executor/turn-executor.d.ts.map +1 -1
- package/dist/llm/executor/turn-executor.js +3 -3
- package/dist/llm/providers/local/schemas.d.ts +2 -2
- package/dist/llm/schemas.d.ts +4 -4
- package/dist/llm/services/vercel.cjs +1 -1
- package/dist/llm/services/vercel.js +1 -1
- package/dist/logger/default-logger-factory.d.ts +12 -12
- package/dist/logger/v2/dexto-logger.cjs +35 -0
- package/dist/logger/v2/dexto-logger.d.ts +19 -0
- package/dist/logger/v2/dexto-logger.d.ts.map +1 -1
- package/dist/logger/v2/dexto-logger.js +35 -0
- package/dist/logger/v2/schemas.d.ts +6 -6
- package/dist/logger/v2/test-utils.cjs +2 -0
- package/dist/logger/v2/test-utils.d.ts.map +1 -1
- package/dist/logger/v2/test-utils.js +2 -0
- package/dist/logger/v2/types.d.ts +14 -1
- package/dist/logger/v2/types.d.ts.map +1 -1
- package/dist/mcp/schemas.d.ts +15 -15
- package/dist/memory/schemas.d.ts +4 -4
- package/dist/prompts/schemas.d.ts +7 -7
- package/dist/systemPrompt/in-built-prompts.cjs +5 -5
- package/dist/systemPrompt/in-built-prompts.d.ts +1 -1
- package/dist/systemPrompt/in-built-prompts.d.ts.map +1 -1
- package/dist/systemPrompt/in-built-prompts.js +5 -5
- package/dist/systemPrompt/schemas.d.ts +5 -5
- package/dist/systemPrompt/types.d.ts +11 -0
- package/dist/systemPrompt/types.d.ts.map +1 -1
- package/dist/tools/display-types.d.ts +10 -0
- package/dist/tools/display-types.d.ts.map +1 -1
- package/dist/tools/index.cjs +3 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -0
- package/dist/tools/presentation.cjs +49 -0
- package/dist/tools/presentation.d.ts +11 -0
- package/dist/tools/presentation.d.ts.map +1 -0
- package/dist/tools/presentation.js +24 -0
- package/dist/tools/tool-manager.cjs +322 -155
- package/dist/tools/tool-manager.d.ts +23 -25
- package/dist/tools/tool-manager.d.ts.map +1 -1
- package/dist/tools/tool-manager.js +322 -155
- package/dist/tools/types.d.ts +134 -55
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/utils/path.cjs +10 -1
- package/dist/utils/path.d.ts +5 -2
- package/dist/utils/path.d.ts.map +1 -1
- package/dist/utils/path.js +10 -1
- package/package.json +2 -2
|
@@ -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;
|
|
@@ -447,16 +448,175 @@ let _ToolManager = class _ToolManager {
|
|
|
447
448
|
});
|
|
448
449
|
}
|
|
449
450
|
// ==================== Pattern Approval Helpers ====================
|
|
451
|
+
getToolApprovalPatternKeyFn(toolName) {
|
|
452
|
+
const tool = this.agentTools.get(toolName);
|
|
453
|
+
return tool?.approval?.patternKey;
|
|
454
|
+
}
|
|
455
|
+
getToolSuggestApprovalPatternsFn(toolName) {
|
|
456
|
+
const tool = this.agentTools.get(toolName);
|
|
457
|
+
return tool?.approval?.suggestPatterns;
|
|
458
|
+
}
|
|
459
|
+
getToolApprovalOverrideFn(toolName) {
|
|
460
|
+
const tool = this.agentTools.get(toolName);
|
|
461
|
+
return tool?.approval?.override;
|
|
462
|
+
}
|
|
463
|
+
getToolApprovalOnGrantedFn(toolName) {
|
|
464
|
+
const tool = this.agentTools.get(toolName);
|
|
465
|
+
return tool?.approval?.onGranted;
|
|
466
|
+
}
|
|
467
|
+
getToolPreviewFn(toolName) {
|
|
468
|
+
const tool = this.agentTools.get(toolName);
|
|
469
|
+
return tool?.presentation?.preview;
|
|
470
|
+
}
|
|
471
|
+
getToolDescribeHeaderFn(toolName) {
|
|
472
|
+
const tool = this.agentTools.get(toolName);
|
|
473
|
+
return tool?.presentation?.describeHeader;
|
|
474
|
+
}
|
|
475
|
+
getToolDescribeArgsFn(toolName) {
|
|
476
|
+
const tool = this.agentTools.get(toolName);
|
|
477
|
+
return tool?.presentation?.describeArgs;
|
|
478
|
+
}
|
|
479
|
+
getToolDescribeResultFn(toolName) {
|
|
480
|
+
const tool = this.agentTools.get(toolName);
|
|
481
|
+
return tool?.presentation?.describeResult;
|
|
482
|
+
}
|
|
483
|
+
buildGenericToolPresentationSnapshot(toolName) {
|
|
484
|
+
const toTitleCase = (name) => name.replace(/[_-]+/g, " ").split(" ").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
485
|
+
const isMcp = toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX);
|
|
486
|
+
const fallbackTitle = (() => {
|
|
487
|
+
if (!isMcp) {
|
|
488
|
+
return toTitleCase(toolName);
|
|
489
|
+
}
|
|
490
|
+
const actualToolName = toolName.substring(_ToolManager.MCP_TOOL_PREFIX.length);
|
|
491
|
+
const parts = actualToolName.split("--");
|
|
492
|
+
const toolPart = parts.length >= 2 ? parts.slice(1).join("--") : actualToolName;
|
|
493
|
+
return toTitleCase(toolPart);
|
|
494
|
+
})();
|
|
495
|
+
const snapshot = {
|
|
496
|
+
version: 1,
|
|
497
|
+
source: {
|
|
498
|
+
type: toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX) ? "mcp" : "local"
|
|
499
|
+
},
|
|
500
|
+
header: {
|
|
501
|
+
title: fallbackTitle
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
if (snapshot.source?.type === "mcp") {
|
|
505
|
+
const actualToolName = toolName.substring(_ToolManager.MCP_TOOL_PREFIX.length);
|
|
506
|
+
const parts = actualToolName.split("--");
|
|
507
|
+
if (parts.length >= 2 && parts[0]) {
|
|
508
|
+
snapshot.source.mcpServerName = parts[0];
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return snapshot;
|
|
512
|
+
}
|
|
513
|
+
getToolPresentationSnapshotForToolCallEvent(toolName, args, toolCallId, sessionId) {
|
|
514
|
+
const fallback = this.buildGenericToolPresentationSnapshot(toolName);
|
|
515
|
+
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
516
|
+
return fallback;
|
|
517
|
+
}
|
|
518
|
+
const describeHeader = this.getToolDescribeHeaderFn(toolName);
|
|
519
|
+
const describeArgs = this.getToolDescribeArgsFn(toolName);
|
|
520
|
+
if (!describeHeader && !describeArgs) {
|
|
521
|
+
return fallback;
|
|
522
|
+
}
|
|
523
|
+
try {
|
|
524
|
+
const validatedArgs = this.validateLocalToolArgs(toolName, args);
|
|
525
|
+
const context = this.buildToolExecutionContext({ sessionId, toolCallId });
|
|
526
|
+
const isPromiseLike = (value) => {
|
|
527
|
+
if (typeof value !== "object" || value === null) {
|
|
528
|
+
return false;
|
|
529
|
+
}
|
|
530
|
+
return typeof value.then === "function";
|
|
531
|
+
};
|
|
532
|
+
let nextSnapshot = fallback;
|
|
533
|
+
if (describeHeader) {
|
|
534
|
+
const header = describeHeader(validatedArgs, context);
|
|
535
|
+
if (!isPromiseLike(header) && header) {
|
|
536
|
+
nextSnapshot = {
|
|
537
|
+
...nextSnapshot,
|
|
538
|
+
header: { ...nextSnapshot.header, ...header }
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
if (describeArgs) {
|
|
543
|
+
const argsPresentation = describeArgs(validatedArgs, context);
|
|
544
|
+
if (!isPromiseLike(argsPresentation) && argsPresentation) {
|
|
545
|
+
nextSnapshot = {
|
|
546
|
+
...nextSnapshot,
|
|
547
|
+
args: argsPresentation
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return nextSnapshot;
|
|
552
|
+
} catch (error) {
|
|
553
|
+
this.logger.debug(
|
|
554
|
+
`Tool presentation snapshot generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
|
|
555
|
+
);
|
|
556
|
+
return fallback;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
async getToolPresentationSnapshotForCall(toolName, args, toolCallId, sessionId) {
|
|
560
|
+
const fallback = this.buildGenericToolPresentationSnapshot(toolName);
|
|
561
|
+
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
562
|
+
return fallback;
|
|
563
|
+
}
|
|
564
|
+
const describeHeader = this.getToolDescribeHeaderFn(toolName);
|
|
565
|
+
const describeArgs = this.getToolDescribeArgsFn(toolName);
|
|
566
|
+
if (!describeHeader && !describeArgs) {
|
|
567
|
+
return fallback;
|
|
568
|
+
}
|
|
569
|
+
try {
|
|
570
|
+
const context = this.buildToolExecutionContext({ sessionId, toolCallId });
|
|
571
|
+
const describedHeader = describeHeader ? await Promise.resolve(describeHeader(args, context)) : null;
|
|
572
|
+
const describedArgs = describeArgs ? await Promise.resolve(describeArgs(args, context)) : null;
|
|
573
|
+
return {
|
|
574
|
+
...fallback,
|
|
575
|
+
...describedHeader ? { header: { ...fallback.header, ...describedHeader } } : {},
|
|
576
|
+
...describedArgs ? { args: describedArgs } : {}
|
|
577
|
+
};
|
|
578
|
+
} catch (error) {
|
|
579
|
+
this.logger.debug(
|
|
580
|
+
`Tool presentation snapshot generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
|
|
581
|
+
);
|
|
582
|
+
return fallback;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
async augmentSnapshotWithResult(toolName, snapshot, result, args, toolCallId, sessionId) {
|
|
586
|
+
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
587
|
+
return snapshot;
|
|
588
|
+
}
|
|
589
|
+
const describeResult = this.getToolDescribeResultFn(toolName);
|
|
590
|
+
if (!describeResult) {
|
|
591
|
+
return snapshot;
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
const context = this.buildToolExecutionContext({ sessionId, toolCallId });
|
|
595
|
+
const resultPresentation = await Promise.resolve(describeResult(result, args, context));
|
|
596
|
+
if (!resultPresentation) {
|
|
597
|
+
return snapshot;
|
|
598
|
+
}
|
|
599
|
+
return {
|
|
600
|
+
...snapshot,
|
|
601
|
+
result: resultPresentation
|
|
602
|
+
};
|
|
603
|
+
} catch (error) {
|
|
604
|
+
this.logger.debug(
|
|
605
|
+
`Tool result presentation snapshot generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
|
|
606
|
+
);
|
|
607
|
+
return snapshot;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
450
610
|
getToolPatternKey(toolName, args) {
|
|
451
611
|
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
452
612
|
return null;
|
|
453
613
|
}
|
|
454
|
-
const
|
|
455
|
-
if (!
|
|
614
|
+
const getPatternKey = this.getToolApprovalPatternKeyFn(toolName);
|
|
615
|
+
if (!getPatternKey) {
|
|
456
616
|
return null;
|
|
457
617
|
}
|
|
458
618
|
try {
|
|
459
|
-
return
|
|
619
|
+
return getPatternKey(args);
|
|
460
620
|
} catch (error) {
|
|
461
621
|
this.logger.debug(
|
|
462
622
|
`Pattern key generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -468,12 +628,12 @@ let _ToolManager = class _ToolManager {
|
|
|
468
628
|
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
469
629
|
return void 0;
|
|
470
630
|
}
|
|
471
|
-
const
|
|
472
|
-
if (!
|
|
631
|
+
const suggestPatterns = this.getToolSuggestApprovalPatternsFn(toolName);
|
|
632
|
+
if (!suggestPatterns) {
|
|
473
633
|
return void 0;
|
|
474
634
|
}
|
|
475
635
|
try {
|
|
476
|
-
const patterns =
|
|
636
|
+
const patterns = suggestPatterns(args);
|
|
477
637
|
return patterns.length > 0 ? patterns : void 0;
|
|
478
638
|
} catch (error) {
|
|
479
639
|
this.logger.debug(
|
|
@@ -499,8 +659,7 @@ let _ToolManager = class _ToolManager {
|
|
|
499
659
|
if (request.sessionId !== sessionId) {
|
|
500
660
|
return false;
|
|
501
661
|
}
|
|
502
|
-
|
|
503
|
-
return metadata.toolName === toolName;
|
|
662
|
+
return request.metadata.toolName === toolName;
|
|
504
663
|
},
|
|
505
664
|
{ rememberChoice: false }
|
|
506
665
|
// Don't propagate remember choice to auto-approved requests
|
|
@@ -519,8 +678,7 @@ let _ToolManager = class _ToolManager {
|
|
|
519
678
|
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
520
679
|
return;
|
|
521
680
|
}
|
|
522
|
-
const
|
|
523
|
-
const getPatternKey = tool?.getApprovalPatternKey;
|
|
681
|
+
const getPatternKey = this.getToolApprovalPatternKeyFn(toolName);
|
|
524
682
|
if (!getPatternKey) {
|
|
525
683
|
return;
|
|
526
684
|
}
|
|
@@ -532,17 +690,17 @@ let _ToolManager = class _ToolManager {
|
|
|
532
690
|
if (request.sessionId !== sessionId) {
|
|
533
691
|
return false;
|
|
534
692
|
}
|
|
535
|
-
|
|
536
|
-
if (metadata.toolName !== toolName) {
|
|
693
|
+
if (request.metadata.toolName !== toolName) {
|
|
537
694
|
return false;
|
|
538
695
|
}
|
|
539
|
-
const args = metadata.args;
|
|
696
|
+
const args = request.metadata.args;
|
|
540
697
|
if (typeof args !== "object" || args === null) {
|
|
541
698
|
return false;
|
|
542
699
|
}
|
|
700
|
+
const argsRecord = args;
|
|
543
701
|
let patternKey;
|
|
544
702
|
try {
|
|
545
|
-
patternKey = getPatternKey(
|
|
703
|
+
patternKey = getPatternKey(argsRecord);
|
|
546
704
|
} catch (error) {
|
|
547
705
|
this.logger.debug(
|
|
548
706
|
`Pattern key generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -561,43 +719,38 @@ let _ToolManager = class _ToolManager {
|
|
|
561
719
|
);
|
|
562
720
|
}
|
|
563
721
|
}
|
|
564
|
-
/**
|
|
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.
|
|
568
|
-
*/
|
|
569
|
-
autoApprovePendingDirectoryAccessRequests(options) {
|
|
570
|
-
const count = this.approvalManager.autoApprovePendingRequests(
|
|
571
|
-
(request) => {
|
|
572
|
-
if (request.type !== import_types3.ApprovalType.DIRECTORY_ACCESS) {
|
|
573
|
-
return false;
|
|
574
|
-
}
|
|
575
|
-
if (request.sessionId !== options.sessionId) {
|
|
576
|
-
return false;
|
|
577
|
-
}
|
|
578
|
-
const metadata = request.metadata;
|
|
579
|
-
if (typeof metadata?.parentDir !== "string" || metadata.parentDir !== options.parentDir) {
|
|
580
|
-
return false;
|
|
581
|
-
}
|
|
582
|
-
if (options.rememberDirectory) {
|
|
583
|
-
return true;
|
|
584
|
-
}
|
|
585
|
-
if (typeof metadata?.operation !== "string" || typeof metadata?.toolName !== "string") {
|
|
586
|
-
return false;
|
|
587
|
-
}
|
|
588
|
-
return metadata.operation === options.operation && metadata.toolName === options.toolName;
|
|
589
|
-
},
|
|
590
|
-
{ rememberDirectory: false }
|
|
591
|
-
);
|
|
592
|
-
if (count > 0) {
|
|
593
|
-
this.logger.info(
|
|
594
|
-
`Auto-approved ${count} parallel request(s) for directory '${options.parentDir}' after directory access was approved`
|
|
595
|
-
);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
722
|
getMcpManager() {
|
|
599
723
|
return this.mcpManager;
|
|
600
724
|
}
|
|
725
|
+
setContributorContextFactory(factory) {
|
|
726
|
+
this.contributorContextFactory = factory ?? void 0;
|
|
727
|
+
}
|
|
728
|
+
async buildContributorContext() {
|
|
729
|
+
const baseWorkspace = this.currentWorkspace ?? null;
|
|
730
|
+
const baseContext = {
|
|
731
|
+
mcpManager: this.mcpManager,
|
|
732
|
+
workspace: baseWorkspace
|
|
733
|
+
};
|
|
734
|
+
if (!this.contributorContextFactory) {
|
|
735
|
+
return baseContext;
|
|
736
|
+
}
|
|
737
|
+
try {
|
|
738
|
+
const overrides = await this.contributorContextFactory() ?? {};
|
|
739
|
+
const workspace = overrides.workspace !== void 0 ? overrides.workspace : baseWorkspace;
|
|
740
|
+
const environment = overrides.environment !== void 0 ? overrides.environment : baseContext.environment;
|
|
741
|
+
const mcpManager = overrides.mcpManager ?? baseContext.mcpManager;
|
|
742
|
+
return {
|
|
743
|
+
mcpManager,
|
|
744
|
+
workspace,
|
|
745
|
+
...environment !== void 0 ? { environment } : {}
|
|
746
|
+
};
|
|
747
|
+
} catch (error) {
|
|
748
|
+
this.logger.warn(
|
|
749
|
+
`Failed to build contributor context: ${error instanceof Error ? error.message : String(error)}`
|
|
750
|
+
);
|
|
751
|
+
return baseContext;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
601
754
|
/**
|
|
602
755
|
* Get all MCP tools (delegates to mcpManager.getAllTools())
|
|
603
756
|
* This provides access to MCP tools while maintaining separation of concerns
|
|
@@ -617,7 +770,7 @@ let _ToolManager = class _ToolManager {
|
|
|
617
770
|
};
|
|
618
771
|
return this.toolExecutionContextFactory(baseContext);
|
|
619
772
|
}
|
|
620
|
-
|
|
773
|
+
validateLocalToolArgs(toolName, args) {
|
|
621
774
|
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
622
775
|
return args;
|
|
623
776
|
}
|
|
@@ -738,15 +891,22 @@ let _ToolManager = class _ToolManager {
|
|
|
738
891
|
async executeTool(toolName, args, toolCallId, sessionId, abortSignal) {
|
|
739
892
|
const { toolArgs: rawToolArgs, meta } = (0, import_tool_call_metadata.extractToolCallMeta)(args);
|
|
740
893
|
let toolArgs = rawToolArgs;
|
|
894
|
+
const callDescription = typeof meta.callDescription === "string" ? meta.callDescription : typeof rawToolArgs.description === "string" ? rawToolArgs.description : void 0;
|
|
741
895
|
const backgroundTasksEnabled = (0, import_env.isBackgroundTasksEnabled)();
|
|
742
|
-
const toolDisplayName = this.agentTools.get(toolName)?.displayName;
|
|
743
896
|
this.logger.debug(`\u{1F527} Tool execution requested: '${toolName}' (toolCallId: ${toolCallId})`);
|
|
744
897
|
this.logger.debug(`Tool args: ${JSON.stringify(toolArgs, null, 2)}`);
|
|
745
898
|
if (sessionId) {
|
|
899
|
+
const presentationSnapshot = this.getToolPresentationSnapshotForToolCallEvent(
|
|
900
|
+
toolName,
|
|
901
|
+
toolArgs,
|
|
902
|
+
toolCallId,
|
|
903
|
+
sessionId
|
|
904
|
+
);
|
|
746
905
|
this.agentEventBus.emit("llm:tool-call", {
|
|
747
906
|
toolName,
|
|
748
|
-
|
|
907
|
+
presentationSnapshot,
|
|
749
908
|
args: toolArgs,
|
|
909
|
+
...callDescription !== void 0 && { callDescription },
|
|
750
910
|
callId: toolCallId,
|
|
751
911
|
sessionId
|
|
752
912
|
});
|
|
@@ -754,13 +914,14 @@ let _ToolManager = class _ToolManager {
|
|
|
754
914
|
const {
|
|
755
915
|
requireApproval,
|
|
756
916
|
approvalStatus,
|
|
757
|
-
args: validatedToolArgs
|
|
917
|
+
args: validatedToolArgs,
|
|
918
|
+
presentationSnapshot: callSnapshot
|
|
758
919
|
} = await this.handleToolApproval(
|
|
759
920
|
toolName,
|
|
760
921
|
toolArgs,
|
|
761
922
|
toolCallId,
|
|
762
923
|
sessionId,
|
|
763
|
-
|
|
924
|
+
callDescription
|
|
764
925
|
);
|
|
765
926
|
toolArgs = validatedToolArgs;
|
|
766
927
|
this.logger.debug(`\u2705 Tool execution approved: ${toolName}`);
|
|
@@ -794,7 +955,7 @@ let _ToolManager = class _ToolManager {
|
|
|
794
955
|
);
|
|
795
956
|
toolArgs = modifiedPayload.args;
|
|
796
957
|
try {
|
|
797
|
-
toolArgs = this.
|
|
958
|
+
toolArgs = this.validateLocalToolArgs(toolName, toolArgs);
|
|
798
959
|
} catch (error) {
|
|
799
960
|
this.logger.error(
|
|
800
961
|
`Post-hook validation failed for tool '${toolName}': a beforeToolCall hook may have set invalid args`
|
|
@@ -917,9 +1078,17 @@ let _ToolManager = class _ToolManager {
|
|
|
917
1078
|
);
|
|
918
1079
|
result = modifiedPayload.result;
|
|
919
1080
|
}
|
|
1081
|
+
const presentationSnapshot = await this.augmentSnapshotWithResult(
|
|
1082
|
+
toolName,
|
|
1083
|
+
callSnapshot,
|
|
1084
|
+
result,
|
|
1085
|
+
toolArgs,
|
|
1086
|
+
toolCallId,
|
|
1087
|
+
sessionId
|
|
1088
|
+
);
|
|
920
1089
|
return {
|
|
921
1090
|
result,
|
|
922
|
-
...
|
|
1091
|
+
...presentationSnapshot !== void 0 && { presentationSnapshot },
|
|
923
1092
|
...requireApproval && { requireApproval, approvalStatus }
|
|
924
1093
|
};
|
|
925
1094
|
} catch (error) {
|
|
@@ -1044,124 +1213,113 @@ let _ToolManager = class _ToolManager {
|
|
|
1044
1213
|
);
|
|
1045
1214
|
}
|
|
1046
1215
|
/**
|
|
1047
|
-
*
|
|
1048
|
-
*
|
|
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
|
|
1216
|
+
* Handle tool approval flow. Checks various precedence levels to determine
|
|
1217
|
+
* if a tool should be auto-approved, denied, or requires manual approval.
|
|
1055
1218
|
*/
|
|
1056
|
-
async
|
|
1057
|
-
if (
|
|
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
|
-
}
|
|
1219
|
+
async handleToolApproval(toolName, args, toolCallId, sessionId, callDescription) {
|
|
1220
|
+
if (this.isInAlwaysDenyList(toolName)) {
|
|
1096
1221
|
this.logger.info(
|
|
1097
|
-
`
|
|
1222
|
+
`Tool '${toolName}' is in static deny list \u2013 blocking execution (session: ${sessionId ?? "global"})`
|
|
1098
1223
|
);
|
|
1099
|
-
|
|
1224
|
+
throw import_errors.ToolError.executionDenied(toolName, sessionId);
|
|
1100
1225
|
}
|
|
1101
|
-
this.
|
|
1102
|
-
|
|
1226
|
+
const validatedArgs = this.validateLocalToolArgs(toolName, args);
|
|
1227
|
+
const presentationSnapshot = await this.getToolPresentationSnapshotForCall(
|
|
1228
|
+
toolName,
|
|
1229
|
+
validatedArgs,
|
|
1230
|
+
toolCallId,
|
|
1231
|
+
sessionId
|
|
1103
1232
|
);
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1233
|
+
let directoryAccess;
|
|
1234
|
+
let directoryAccessApprovalRequest;
|
|
1235
|
+
if (!toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
1236
|
+
const getApprovalOverride = this.getToolApprovalOverrideFn(toolName);
|
|
1237
|
+
if (getApprovalOverride) {
|
|
1238
|
+
const context = this.buildToolExecutionContext({ sessionId, toolCallId });
|
|
1239
|
+
const approvalRequest = await getApprovalOverride(validatedArgs, context);
|
|
1240
|
+
if (approvalRequest) {
|
|
1241
|
+
if (approvalRequest.type === import_types3.ApprovalType.DIRECTORY_ACCESS) {
|
|
1242
|
+
const metadata = approvalRequest.metadata;
|
|
1243
|
+
if (typeof metadata !== "object" || metadata === null || typeof metadata.path !== "string" || typeof metadata.parentDir !== "string" || typeof metadata.operation !== "string" || typeof metadata.toolName !== "string") {
|
|
1244
|
+
throw import_errors.ToolError.configInvalid(
|
|
1245
|
+
`Tool '${toolName}' returned invalid directory access metadata`
|
|
1246
|
+
);
|
|
1247
|
+
}
|
|
1248
|
+
directoryAccess = metadata;
|
|
1249
|
+
directoryAccessApprovalRequest = approvalRequest;
|
|
1250
|
+
} else {
|
|
1251
|
+
this.logger.debug(
|
|
1252
|
+
`Tool '${toolName}' requested custom approval: type=${approvalRequest.type}`
|
|
1253
|
+
);
|
|
1254
|
+
if (sessionId && !approvalRequest.sessionId) {
|
|
1255
|
+
approvalRequest.sessionId = sessionId;
|
|
1256
|
+
}
|
|
1257
|
+
const response = await this.approvalManager.requestApproval(approvalRequest);
|
|
1258
|
+
if (response.status === import_types3.ApprovalStatus.APPROVED) {
|
|
1259
|
+
const onGranted = this.getToolApprovalOnGrantedFn(toolName);
|
|
1260
|
+
if (onGranted) {
|
|
1261
|
+
await Promise.resolve(
|
|
1262
|
+
onGranted(response, context, approvalRequest)
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1265
|
+
this.logger.info(
|
|
1266
|
+
`Custom approval granted for '${toolName}', type=${approvalRequest.type}, session=${sessionId ?? "global"}`
|
|
1267
|
+
);
|
|
1268
|
+
return {
|
|
1269
|
+
requireApproval: true,
|
|
1270
|
+
approvalStatus: "approved",
|
|
1271
|
+
args: validatedArgs,
|
|
1272
|
+
presentationSnapshot
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
this.logger.info(
|
|
1276
|
+
`Custom approval denied for '${toolName}', type=${approvalRequest.type}, reason=${response.reason ?? "unknown"}`
|
|
1277
|
+
);
|
|
1278
|
+
throw import_errors.ToolError.executionDenied(toolName, sessionId);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1110
1282
|
}
|
|
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
1283
|
const quickResult = await this.tryQuickApprovalResolution(
|
|
1120
1284
|
toolName,
|
|
1121
1285
|
validatedArgs,
|
|
1122
|
-
|
|
1123
|
-
|
|
1286
|
+
sessionId,
|
|
1287
|
+
directoryAccess
|
|
1124
1288
|
);
|
|
1125
1289
|
if (quickResult !== null) {
|
|
1126
|
-
return { ...quickResult, args: validatedArgs };
|
|
1290
|
+
return { ...quickResult, args: validatedArgs, presentationSnapshot };
|
|
1127
1291
|
}
|
|
1128
1292
|
const manualResult = await this.requestManualApproval(
|
|
1129
1293
|
toolName,
|
|
1130
1294
|
validatedArgs,
|
|
1131
1295
|
toolCallId,
|
|
1132
1296
|
sessionId,
|
|
1133
|
-
|
|
1297
|
+
directoryAccess,
|
|
1298
|
+
directoryAccessApprovalRequest,
|
|
1299
|
+
callDescription,
|
|
1300
|
+
presentationSnapshot
|
|
1134
1301
|
);
|
|
1135
|
-
return { ...manualResult, args: validatedArgs };
|
|
1302
|
+
return { ...manualResult, args: validatedArgs, presentationSnapshot };
|
|
1136
1303
|
}
|
|
1137
1304
|
/**
|
|
1138
1305
|
* Try to resolve tool approval quickly based on policies and cached permissions.
|
|
1139
1306
|
* Returns null if manual approval is needed.
|
|
1140
1307
|
*
|
|
1141
1308
|
* Precedence order (highest to lowest):
|
|
1142
|
-
* 1.
|
|
1143
|
-
* 2.
|
|
1144
|
-
* 3.
|
|
1145
|
-
* 4.
|
|
1146
|
-
* 5.
|
|
1147
|
-
* 6.
|
|
1148
|
-
* 7. Approval mode (auto-approve/auto-deny)
|
|
1309
|
+
* 1. Directory access requirement (outside-root paths)
|
|
1310
|
+
* 2. Session auto-approve (skill allowed-tools)
|
|
1311
|
+
* 3. Static allow list
|
|
1312
|
+
* 4. Dynamic "remembered" allowed list
|
|
1313
|
+
* 5. Tool approval patterns
|
|
1314
|
+
* 6. Approval mode (auto-approve/auto-deny)
|
|
1149
1315
|
*/
|
|
1150
|
-
async tryQuickApprovalResolution(toolName, args,
|
|
1151
|
-
if (
|
|
1152
|
-
this.
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
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" };
|
|
1316
|
+
async tryQuickApprovalResolution(toolName, args, sessionId, directoryAccess) {
|
|
1317
|
+
if (directoryAccess) {
|
|
1318
|
+
if (this.approvalMode === "auto-approve") {
|
|
1319
|
+
this.approvalManager.addApprovedDirectory(directoryAccess.parentDir, "once");
|
|
1320
|
+
return { requireApproval: false };
|
|
1321
|
+
}
|
|
1322
|
+
return null;
|
|
1165
1323
|
}
|
|
1166
1324
|
if (sessionId && this.isToolAutoApprovedForSession(sessionId, toolName)) {
|
|
1167
1325
|
this.logger.info(
|
|
@@ -1202,12 +1360,11 @@ let _ToolManager = class _ToolManager {
|
|
|
1202
1360
|
* Request manual approval from the user for a tool execution.
|
|
1203
1361
|
* Generates preview, sends approval request, and handles the response.
|
|
1204
1362
|
*/
|
|
1205
|
-
async requestManualApproval(toolName, args, toolCallId, sessionId, callDescription) {
|
|
1363
|
+
async requestManualApproval(toolName, args, toolCallId, sessionId, directoryAccess, directoryAccessApprovalRequest, callDescription, presentationSnapshot) {
|
|
1206
1364
|
this.logger.info(
|
|
1207
1365
|
`Tool approval requested for ${toolName}, sessionId: ${sessionId ?? "global"}`
|
|
1208
1366
|
);
|
|
1209
1367
|
try {
|
|
1210
|
-
const toolDisplayName = this.agentTools.get(toolName)?.displayName;
|
|
1211
1368
|
const displayPreview = await this.generateToolPreview(
|
|
1212
1369
|
toolName,
|
|
1213
1370
|
args,
|
|
@@ -1217,14 +1374,24 @@ let _ToolManager = class _ToolManager {
|
|
|
1217
1374
|
const suggestedPatterns = this.getToolSuggestedPatterns(toolName, args);
|
|
1218
1375
|
const response = await this.approvalManager.requestToolApproval({
|
|
1219
1376
|
toolName,
|
|
1220
|
-
...
|
|
1377
|
+
...presentationSnapshot !== void 0 && { presentationSnapshot },
|
|
1221
1378
|
toolCallId,
|
|
1222
1379
|
args,
|
|
1223
1380
|
...callDescription !== void 0 && { description: callDescription },
|
|
1224
1381
|
...sessionId !== void 0 && { sessionId },
|
|
1225
1382
|
...displayPreview !== void 0 && { displayPreview },
|
|
1383
|
+
...directoryAccess !== void 0 && { directoryAccess },
|
|
1226
1384
|
...suggestedPatterns !== void 0 && { suggestedPatterns }
|
|
1227
1385
|
});
|
|
1386
|
+
if (response.status === import_types3.ApprovalStatus.APPROVED && directoryAccessApprovalRequest !== void 0) {
|
|
1387
|
+
const onGranted = this.getToolApprovalOnGrantedFn(toolName);
|
|
1388
|
+
if (onGranted) {
|
|
1389
|
+
const context = this.buildToolExecutionContext({ sessionId, toolCallId });
|
|
1390
|
+
await Promise.resolve(
|
|
1391
|
+
onGranted(response, context, directoryAccessApprovalRequest)
|
|
1392
|
+
);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1228
1395
|
if (response.status === import_types3.ApprovalStatus.APPROVED && response.data) {
|
|
1229
1396
|
await this.handleRememberChoice(toolName, response, sessionId);
|
|
1230
1397
|
}
|
|
@@ -1246,13 +1413,13 @@ let _ToolManager = class _ToolManager {
|
|
|
1246
1413
|
* Generate a preview for the tool approval UI if the tool supports it.
|
|
1247
1414
|
*/
|
|
1248
1415
|
async generateToolPreview(toolName, args, toolCallId, sessionId) {
|
|
1249
|
-
const
|
|
1250
|
-
if (!
|
|
1416
|
+
const previewFn = this.getToolPreviewFn(toolName);
|
|
1417
|
+
if (!previewFn) {
|
|
1251
1418
|
return void 0;
|
|
1252
1419
|
}
|
|
1253
1420
|
try {
|
|
1254
1421
|
const context = this.buildToolExecutionContext({ sessionId, toolCallId });
|
|
1255
|
-
const preview = await
|
|
1422
|
+
const preview = await previewFn(args, context);
|
|
1256
1423
|
this.logger.debug(`Generated preview for ${toolName}`);
|
|
1257
1424
|
return preview ?? void 0;
|
|
1258
1425
|
} catch (previewError) {
|
|
@@ -1281,7 +1448,7 @@ let _ToolManager = class _ToolManager {
|
|
|
1281
1448
|
`Tool '${toolName}' added to allowed tools for session '${allowSessionId ?? "global"}' (remember choice selected)`
|
|
1282
1449
|
);
|
|
1283
1450
|
this.autoApprovePendingToolRequests(toolName, allowSessionId);
|
|
1284
|
-
} else if (rememberPattern && this.
|
|
1451
|
+
} else if (rememberPattern && this.getToolApprovalPatternKeyFn(toolName)) {
|
|
1285
1452
|
this.approvalManager.addPattern(toolName, rememberPattern);
|
|
1286
1453
|
this.logger.info(`Pattern '${rememberPattern}' added for tool '${toolName}' approval`);
|
|
1287
1454
|
this.autoApprovePendingPatternRequests(toolName, sessionId);
|