@dexto/core 1.7.2 → 1.8.0
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 +157 -62
- package/dist/agent/DextoAgent.d.ts +71 -17
- package/dist/agent/DextoAgent.d.ts.map +1 -1
- package/dist/agent/DextoAgent.js +161 -63
- package/dist/agent/agent-options.d.ts +6 -10
- package/dist/agent/agent-options.d.ts.map +1 -1
- package/dist/agent/agentCard.js +1 -1
- package/dist/agent/error-codes.js +1 -1
- package/dist/agent/errors.js +1 -1
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/schemas.d.ts +2 -2
- package/dist/agent/schemas.js +1 -1
- package/dist/agent/state-manager.js +1 -1
- package/dist/approval/error-codes.cjs +1 -1
- package/dist/approval/error-codes.d.ts +1 -1
- package/dist/approval/error-codes.d.ts.map +1 -1
- package/dist/approval/error-codes.js +2 -2
- package/dist/approval/errors.cjs +2 -5
- package/dist/approval/errors.d.ts.map +1 -1
- package/dist/approval/errors.js +3 -6
- package/dist/approval/factory.cjs +19 -4
- package/dist/approval/factory.d.ts +4 -1
- package/dist/approval/factory.d.ts.map +1 -1
- package/dist/approval/factory.js +19 -5
- package/dist/approval/index.d.ts +1 -1
- package/dist/approval/index.d.ts.map +1 -1
- package/dist/approval/index.js +1 -1
- package/dist/approval/manager.cjs +168 -26
- package/dist/approval/manager.d.ts +46 -12
- package/dist/approval/manager.d.ts.map +1 -1
- package/dist/approval/manager.js +177 -29
- package/dist/approval/schemas.cjs +26 -26
- package/dist/approval/schemas.d.ts +29 -29
- package/dist/approval/schemas.d.ts.map +1 -1
- package/dist/approval/schemas.js +23 -23
- package/dist/approval/types.cjs +5 -5
- package/dist/approval/types.d.ts +18 -18
- package/dist/approval/types.d.ts.map +1 -1
- package/dist/approval/types.js +6 -6
- package/dist/{chunk-PTJYTZNU.js → chunk-C6A6W6XS.js} +1 -44
- package/dist/config/index.cjs +75 -0
- package/dist/config/index.d.ts +15 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +50 -0
- package/dist/context/compaction/overflow.js +1 -1
- package/dist/context/compaction/strategies/noop.js +1 -1
- package/dist/context/compaction/strategies/reactive-overflow-compaction.js +1 -1
- package/dist/context/content-clone.cjs +131 -0
- package/dist/context/content-clone.d.ts +7 -0
- package/dist/context/content-clone.d.ts.map +1 -0
- package/dist/context/content-clone.js +104 -0
- package/dist/context/error-codes.js +1 -1
- package/dist/context/errors.js +1 -1
- package/dist/context/index.cjs +2 -0
- package/dist/context/index.d.ts +1 -0
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +2 -1
- package/dist/context/manager.cjs +44 -33
- package/dist/context/manager.d.ts +7 -7
- package/dist/context/manager.d.ts.map +1 -1
- package/dist/context/manager.js +45 -34
- package/dist/context/media-helpers.js +1 -1
- package/dist/context/schemas.cjs +77 -0
- package/dist/context/schemas.d.ts +5 -0
- package/dist/context/schemas.d.ts.map +1 -0
- package/dist/context/schemas.js +53 -0
- package/dist/context/types.js +1 -1
- package/dist/context/utils.cjs +70 -69
- package/dist/context/utils.d.ts +3 -3
- package/dist/context/utils.d.ts.map +1 -1
- package/dist/context/utils.js +71 -70
- package/dist/errors/DextoBaseError.js +1 -1
- package/dist/errors/DextoRuntimeError.js +1 -1
- package/dist/errors/DextoValidationError.js +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/errors/result-bridge.js +1 -1
- package/dist/errors/types.js +1 -1
- package/dist/events/index.cjs +9 -1
- package/dist/events/index.d.ts +20 -8
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +10 -2
- package/dist/hooks/builtins/content-policy.js +1 -1
- package/dist/hooks/builtins/response-sanitizer.js +1 -1
- package/dist/hooks/error-codes.js +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/manager.cjs +1 -1
- package/dist/hooks/manager.d.ts +2 -2
- package/dist/hooks/manager.d.ts.map +1 -1
- package/dist/hooks/manager.js +2 -2
- package/dist/hooks/types.d.ts +2 -2
- package/dist/hooks/types.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/llm/curation-config.js +1 -1
- package/dist/llm/curation.js +1 -1
- package/dist/llm/error-codes.js +1 -1
- package/dist/llm/errors.js +1 -1
- package/dist/llm/executor/index.cjs +32 -0
- package/dist/llm/executor/index.d.ts +2 -0
- package/dist/llm/executor/index.d.ts.map +1 -0
- package/dist/llm/executor/index.js +11 -0
- package/dist/llm/executor/provider-options.js +1 -1
- package/dist/llm/executor/stream-processor.cjs +28 -139
- package/dist/llm/executor/stream-processor.d.ts +2 -13
- package/dist/llm/executor/stream-processor.d.ts.map +1 -1
- package/dist/llm/executor/stream-processor.js +29 -140
- package/dist/{session/history/memory.cjs → llm/executor/tool-definitions.cjs} +21 -33
- package/dist/llm/executor/tool-definitions.d.ts +4 -0
- package/dist/llm/executor/tool-definitions.d.ts.map +1 -0
- package/dist/llm/executor/tool-definitions.js +22 -0
- package/dist/llm/executor/tool-output-truncator.js +1 -1
- package/dist/llm/executor/turn-executor.cjs +1093 -458
- package/dist/llm/executor/turn-executor.d.ts +269 -43
- package/dist/llm/executor/turn-executor.d.ts.map +1 -1
- package/dist/llm/executor/turn-executor.js +1079 -405
- package/dist/llm/executor/types.d.ts +6 -0
- package/dist/llm/executor/types.d.ts.map +1 -1
- package/dist/llm/formatters/vercel.js +1 -1
- package/dist/llm/index.cjs +2 -0
- package/dist/llm/index.d.ts +1 -0
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +2 -1
- package/dist/llm/providers/codex-app-server.cjs +22 -2
- package/dist/llm/providers/codex-app-server.d.ts.map +1 -1
- package/dist/llm/providers/codex-app-server.js +23 -3
- package/dist/llm/providers/codex-base-url.js +1 -1
- package/dist/llm/providers/local/ai-sdk-adapter.js +1 -1
- package/dist/llm/providers/local/downloader.js +1 -1
- package/dist/llm/providers/local/error-codes.js +1 -1
- package/dist/llm/providers/local/errors.js +1 -1
- package/dist/llm/providers/local/gpu-detector.js +1 -1
- package/dist/llm/providers/local/index.js +1 -1
- package/dist/llm/providers/local/node-llama-provider.js +1 -1
- package/dist/llm/providers/local/ollama-provider.js +1 -1
- package/dist/llm/providers/local/registry.js +1 -1
- package/dist/llm/providers/local/schemas.js +1 -1
- package/dist/llm/providers/openrouter-model-registry.js +1 -1
- package/dist/llm/reasoning/anthropic-betas.js +1 -1
- package/dist/llm/reasoning/anthropic-thinking.js +1 -1
- package/dist/llm/reasoning/openai-reasoning-effort.js +1 -1
- package/dist/llm/reasoning/profile.js +1 -1
- package/dist/llm/reasoning/profiles/anthropic.js +1 -1
- package/dist/llm/reasoning/profiles/bedrock.js +1 -1
- package/dist/llm/reasoning/profiles/google.js +1 -1
- package/dist/llm/reasoning/profiles/openai-compatible.js +1 -1
- package/dist/llm/reasoning/profiles/openai.js +1 -1
- package/dist/llm/reasoning/profiles/openrouter.js +1 -1
- package/dist/llm/reasoning/profiles/shared.js +1 -1
- package/dist/llm/reasoning/profiles/vertex.js +1 -1
- package/dist/llm/registry/auto-update.js +1 -1
- package/dist/llm/registry/index.js +1 -1
- package/dist/llm/registry/models.generated.js +1 -1
- package/dist/llm/registry/models.manual.js +1 -1
- package/dist/llm/registry/sync.js +1 -1
- package/dist/llm/resolver.js +1 -1
- package/dist/llm/schemas.js +1 -1
- package/dist/llm/services/factory.cjs +5 -4
- package/dist/llm/services/factory.d.ts +3 -3
- package/dist/llm/services/factory.d.ts.map +1 -1
- package/dist/llm/services/factory.js +6 -5
- package/dist/llm/services/types.d.ts +10 -1
- package/dist/llm/services/types.d.ts.map +1 -1
- package/dist/llm/services/vercel.cjs +23 -8
- package/dist/llm/services/vercel.d.ts +11 -7
- package/dist/llm/services/vercel.d.ts.map +1 -1
- package/dist/llm/services/vercel.js +24 -9
- package/dist/llm/types.js +1 -1
- package/dist/llm/usage-metadata.cjs +20 -3
- package/dist/llm/usage-metadata.d.ts +1 -0
- package/dist/llm/usage-metadata.d.ts.map +1 -1
- package/dist/llm/usage-metadata.js +19 -3
- package/dist/llm/usage-scope.js +1 -1
- package/dist/llm/usage-summary.js +1 -1
- package/dist/llm/validation.js +1 -1
- package/dist/logger/browser.js +1 -1
- package/dist/logger/default-logger-factory.js +1 -1
- package/dist/logger/factory.js +1 -1
- package/dist/logger/index.js +1 -1
- package/dist/logger/logger.js +1 -1
- package/dist/logger/v2/dexto-logger.js +1 -1
- package/dist/logger/v2/error-codes.js +1 -1
- package/dist/logger/v2/errors.js +1 -1
- package/dist/logger/v2/schemas.js +1 -1
- package/dist/logger/v2/test-utils.js +1 -1
- package/dist/logger/v2/transport-factory.js +1 -1
- package/dist/logger/v2/transports/console-transport.js +1 -1
- package/dist/logger/v2/transports/file-transport.js +1 -1
- package/dist/logger/v2/transports/silent-transport.js +1 -1
- package/dist/logger/v2/types.js +1 -1
- package/dist/mcp/bundled-config.js +1 -1
- package/dist/mcp/error-codes.js +1 -1
- package/dist/mcp/errors.js +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/manager.js +1 -1
- package/dist/mcp/mcp-client.js +1 -1
- package/dist/mcp/resolver.js +1 -1
- package/dist/mcp/schemas.js +1 -1
- package/dist/memory/error-codes.js +1 -1
- package/dist/memory/errors.js +1 -1
- package/dist/memory/index.js +1 -1
- package/dist/memory/manager.cjs +7 -27
- package/dist/memory/manager.d.ts +4 -12
- package/dist/memory/manager.d.ts.map +1 -1
- package/dist/memory/manager.js +8 -28
- package/dist/memory/schemas.js +1 -1
- package/dist/prompts/error-codes.js +1 -1
- package/dist/prompts/errors.js +1 -1
- package/dist/prompts/index.js +1 -1
- package/dist/prompts/name-validation.js +1 -1
- package/dist/prompts/prompt-manager.cjs +9 -38
- package/dist/prompts/prompt-manager.d.ts +2 -10
- package/dist/prompts/prompt-manager.d.ts.map +1 -1
- package/dist/prompts/prompt-manager.js +10 -39
- package/dist/prompts/providers/config-prompt-provider.cjs +8 -87
- package/dist/prompts/providers/config-prompt-provider.d.ts.map +1 -1
- package/dist/prompts/providers/config-prompt-provider.js +9 -88
- package/dist/prompts/providers/custom-prompt-provider.cjs +21 -22
- package/dist/prompts/providers/custom-prompt-provider.d.ts +19 -4
- package/dist/prompts/providers/custom-prompt-provider.d.ts.map +1 -1
- package/dist/prompts/providers/custom-prompt-provider.js +22 -23
- package/dist/prompts/providers/mcp-prompt-provider.js +1 -1
- package/dist/prompts/schemas.cjs +2 -24
- package/dist/prompts/schemas.d.ts +0 -52
- package/dist/prompts/schemas.d.ts.map +1 -1
- package/dist/prompts/schemas.js +3 -25
- package/dist/prompts/types.d.ts +5 -32
- package/dist/prompts/types.d.ts.map +1 -1
- package/dist/prompts/utils.js +1 -1
- package/dist/resources/agent-resources-provider.js +1 -1
- package/dist/resources/error-codes.js +1 -1
- package/dist/resources/errors.js +1 -1
- package/dist/resources/handlers/blob-handler.cjs +14 -11
- package/dist/resources/handlers/blob-handler.d.ts +4 -4
- package/dist/resources/handlers/blob-handler.d.ts.map +1 -1
- package/dist/resources/handlers/blob-handler.js +15 -12
- package/dist/resources/handlers/factory.cjs +3 -3
- package/dist/resources/handlers/factory.js +4 -4
- package/dist/resources/handlers/filesystem-handler.js +1 -1
- package/dist/resources/handlers/types.d.ts +2 -2
- package/dist/resources/handlers/types.d.ts.map +1 -1
- package/dist/resources/index.js +1 -1
- package/dist/resources/manager.cjs +10 -7
- package/dist/resources/manager.d.ts +4 -4
- package/dist/resources/manager.d.ts.map +1 -1
- package/dist/resources/manager.js +11 -8
- package/dist/resources/reference-parser.js +1 -1
- package/dist/resources/schemas.cjs +1 -1
- package/dist/resources/schemas.d.ts +2 -2
- package/dist/resources/schemas.js +2 -2
- package/dist/runtime/host-runtime.js +1 -1
- package/dist/runtime/index.cjs +3 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +3 -1
- package/dist/runtime/run-context.js +1 -1
- package/dist/search/index.js +1 -1
- package/dist/search/search-service.cjs +6 -13
- package/dist/search/search-service.d.ts +5 -3
- package/dist/search/search-service.d.ts.map +1 -1
- package/dist/search/search-service.js +7 -14
- package/dist/session/chat-session.cjs +264 -108
- package/dist/session/chat-session.d.ts +75 -21
- package/dist/session/chat-session.d.ts.map +1 -1
- package/dist/session/chat-session.js +268 -108
- package/dist/session/error-codes.js +1 -1
- package/dist/session/errors.js +1 -1
- package/dist/session/index.cjs +19 -2
- package/dist/session/index.d.ts +4 -3
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +19 -3
- package/dist/session/message-queue.cjs +82 -51
- package/dist/session/message-queue.d.ts +13 -8
- package/dist/session/message-queue.d.ts.map +1 -1
- package/dist/session/message-queue.js +83 -52
- package/dist/session/queue-clone.cjs +50 -0
- package/dist/session/queue-clone.d.ts +5 -0
- package/dist/session/queue-clone.d.ts.map +1 -0
- package/dist/session/queue-clone.js +25 -0
- package/dist/session/schemas.cjs +74 -2
- package/dist/session/schemas.d.ts +94 -0
- package/dist/session/schemas.d.ts.map +1 -1
- package/dist/session/schemas.js +69 -2
- package/dist/session/session-manager.cjs +107 -123
- package/dist/session/session-manager.d.ts +7 -6
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +108 -124
- package/dist/session/title-generator.cjs +14 -26
- package/dist/session/title-generator.d.ts +4 -6
- package/dist/session/title-generator.d.ts.map +1 -1
- package/dist/session/title-generator.js +16 -28
- package/dist/session/types.cjs +28 -0
- package/dist/session/types.d.ts +5 -1
- package/dist/session/types.d.ts.map +1 -1
- package/dist/session/types.js +19 -0
- package/dist/{session/history/factory.cjs → skills/index.cjs} +9 -9
- package/dist/skills/index.d.ts +4 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +7 -0
- package/dist/skills/skill-manager.cjs +76 -0
- package/dist/skills/skill-manager.d.ts +13 -0
- package/dist/skills/skill-manager.d.ts.map +1 -0
- package/dist/skills/skill-manager.js +53 -0
- package/dist/skills/types.d.ts +24 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/workspace-skill-source.cjs +120 -0
- package/dist/skills/workspace-skill-source.d.ts +16 -0
- package/dist/skills/workspace-skill-source.d.ts.map +1 -0
- package/dist/skills/workspace-skill-source.js +97 -0
- package/dist/storage/approvals/types.cjs +38 -0
- package/dist/storage/approvals/types.d.ts +54 -0
- package/dist/storage/approvals/types.d.ts.map +1 -0
- package/dist/storage/approvals/types.js +14 -0
- package/dist/storage/artifacts/types.d.ts +73 -0
- package/dist/storage/artifacts/types.d.ts.map +1 -0
- package/dist/storage/conversation/database.cjs +233 -0
- package/dist/storage/conversation/database.d.ts +38 -0
- package/dist/storage/conversation/database.d.ts.map +1 -0
- package/dist/storage/conversation/database.js +210 -0
- package/dist/storage/conversation/types.cjs +16 -0
- package/dist/storage/conversation/types.d.ts +21 -0
- package/dist/storage/conversation/types.d.ts.map +1 -0
- package/dist/storage/conversation/types.js +0 -0
- package/dist/storage/database/types.d.ts +4 -0
- package/dist/storage/database/types.d.ts.map +1 -1
- package/dist/storage/error-codes.js +1 -1
- package/dist/storage/errors.cjs +6 -6
- package/dist/storage/errors.d.ts +2 -2
- package/dist/storage/errors.js +7 -7
- package/dist/storage/index.cjs +42 -5
- package/dist/storage/index.d.ts +19 -8
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +39 -4
- package/dist/storage/memories/types.cjs +16 -0
- package/dist/storage/memories/types.d.ts +17 -0
- package/dist/storage/memories/types.d.ts.map +1 -0
- package/dist/storage/memories/types.js +0 -0
- package/dist/storage/message-queue/types.cjs +16 -0
- package/dist/storage/message-queue/types.d.ts +15 -0
- package/dist/storage/message-queue/types.d.ts.map +1 -0
- package/dist/storage/message-queue/types.js +0 -0
- package/dist/storage/prompts/types.cjs +16 -0
- package/dist/storage/prompts/types.d.ts +14 -0
- package/dist/storage/prompts/types.d.ts.map +1 -0
- package/dist/storage/prompts/types.js +0 -0
- package/dist/storage/runtime-events/types.cjs +16 -0
- package/dist/storage/runtime-events/types.d.ts +19 -0
- package/dist/storage/runtime-events/types.d.ts.map +1 -0
- package/dist/storage/runtime-events/types.js +0 -0
- package/dist/storage/sessions/types.cjs +16 -0
- package/dist/storage/sessions/types.d.ts +19 -0
- package/dist/storage/sessions/types.d.ts.map +1 -0
- package/dist/storage/sessions/types.js +0 -0
- package/dist/storage/stores/backend.cjs +702 -0
- package/dist/storage/stores/backend.d.ts +303 -0
- package/dist/storage/stores/backend.d.ts.map +1 -0
- package/dist/storage/stores/backend.js +677 -0
- package/dist/storage/stores/in-memory.cjs +510 -0
- package/dist/storage/stores/in-memory.d.ts +11 -0
- package/dist/storage/stores/in-memory.d.ts.map +1 -0
- package/dist/storage/stores/in-memory.js +487 -0
- package/dist/storage/stores/types.cjs +16 -0
- package/dist/storage/stores/types.d.ts +36 -0
- package/dist/storage/stores/types.d.ts.map +1 -0
- package/dist/storage/stores/types.js +0 -0
- package/dist/storage/tool-executions/types.cjs +127 -0
- package/dist/storage/tool-executions/types.d.ts +193 -0
- package/dist/storage/tool-executions/types.d.ts.map +1 -0
- package/dist/storage/tool-executions/types.js +96 -0
- package/dist/storage/tool-preferences/types.cjs +16 -0
- package/dist/storage/tool-preferences/types.d.ts +29 -0
- package/dist/storage/tool-preferences/types.d.ts.map +1 -0
- package/dist/storage/tool-preferences/types.js +0 -0
- package/dist/storage/tool-state/types.cjs +16 -0
- package/dist/storage/tool-state/types.d.ts +20 -0
- package/dist/storage/tool-state/types.d.ts.map +1 -0
- package/dist/storage/tool-state/types.js +0 -0
- package/dist/storage/workspaces/types.cjs +16 -0
- package/dist/storage/workspaces/types.d.ts +19 -0
- package/dist/storage/workspaces/types.d.ts.map +1 -0
- package/dist/storage/workspaces/types.js +0 -0
- package/dist/systemPrompt/contributors.cjs +10 -14
- package/dist/systemPrompt/contributors.d.ts +3 -3
- package/dist/systemPrompt/contributors.d.ts.map +1 -1
- package/dist/systemPrompt/contributors.js +11 -15
- package/dist/systemPrompt/error-codes.js +1 -1
- package/dist/systemPrompt/errors.js +1 -1
- package/dist/systemPrompt/in-built-prompts.js +1 -1
- package/dist/systemPrompt/index.js +1 -1
- package/dist/systemPrompt/manager.js +1 -1
- package/dist/systemPrompt/registry.js +1 -1
- package/dist/systemPrompt/schemas.js +1 -1
- package/dist/telemetry/decorators.js +1 -1
- package/dist/telemetry/error-codes.js +1 -1
- package/dist/telemetry/errors.js +1 -1
- package/dist/telemetry/exporters.js +1 -1
- package/dist/telemetry/index.js +1 -1
- package/dist/telemetry/schemas.js +1 -1
- package/dist/telemetry/telemetry.js +1 -1
- package/dist/telemetry/utils.js +1 -1
- package/dist/test-utils/in-memory-storage.cjs +9 -17
- package/dist/test-utils/in-memory-storage.js +9 -16
- package/dist/test-utils/session-state-stores.cjs +21 -24
- package/dist/test-utils/session-state-stores.js +22 -24
- package/dist/tools/{confirmation → approval}/allowed-tools-provider/factory.cjs +1 -1
- package/dist/tools/{confirmation → approval}/allowed-tools-provider/factory.d.ts +2 -2
- package/dist/tools/approval/allowed-tools-provider/factory.d.ts.map +1 -0
- package/dist/tools/{confirmation → approval}/allowed-tools-provider/factory.js +2 -2
- package/dist/tools/approval/allowed-tools-provider/in-memory.d.ts.map +1 -0
- package/dist/tools/{confirmation → approval}/allowed-tools-provider/in-memory.js +1 -1
- package/dist/tools/approval/allowed-tools-provider/storage.cjs +66 -0
- package/dist/tools/{confirmation → approval}/allowed-tools-provider/storage.d.ts +4 -10
- package/dist/tools/approval/allowed-tools-provider/storage.d.ts.map +1 -0
- package/dist/tools/approval/allowed-tools-provider/storage.js +43 -0
- package/dist/tools/approval/allowed-tools-provider/types.cjs +16 -0
- package/dist/tools/approval/allowed-tools-provider/types.d.ts.map +1 -0
- package/dist/tools/approval/allowed-tools-provider/types.js +0 -0
- package/dist/tools/approval/session-tool-policy.cjs +269 -0
- package/dist/tools/approval/session-tool-policy.d.ts +43 -0
- package/dist/tools/approval/session-tool-policy.d.ts.map +1 -0
- package/dist/tools/approval/session-tool-policy.js +245 -0
- package/dist/tools/define-tool.js +1 -1
- package/dist/tools/display-types.js +1 -1
- package/dist/tools/error-codes.cjs +3 -3
- package/dist/tools/error-codes.d.ts +4 -4
- package/dist/tools/error-codes.d.ts.map +1 -1
- package/dist/tools/error-codes.js +4 -4
- package/dist/tools/errors.cjs +12 -12
- package/dist/tools/errors.d.ts +6 -6
- package/dist/tools/errors.d.ts.map +1 -1
- package/dist/tools/errors.js +13 -13
- package/dist/tools/index.cjs +3 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -1
- package/dist/tools/pattern-utils.js +1 -1
- package/dist/tools/presentation/tool-presentation.cjs +182 -0
- package/dist/tools/presentation/tool-presentation.d.ts +51 -0
- package/dist/tools/presentation/tool-presentation.d.ts.map +1 -0
- package/dist/tools/presentation/tool-presentation.js +159 -0
- package/dist/tools/presentation.js +1 -1
- package/dist/tools/schemas.cjs +5 -10
- package/dist/tools/schemas.d.ts +1 -4
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/schemas.js +6 -11
- package/dist/tools/session-tool-preferences-store.cjs +12 -28
- package/dist/tools/session-tool-preferences-store.d.ts +4 -7
- package/dist/tools/session-tool-preferences-store.d.ts.map +1 -1
- package/dist/tools/session-tool-preferences-store.js +12 -29
- package/dist/tools/tool-call-metadata.js +1 -1
- package/dist/tools/tool-manager.cjs +871 -834
- package/dist/tools/tool-manager.d.ts +94 -96
- package/dist/tools/tool-manager.d.ts.map +1 -1
- package/dist/tools/tool-manager.js +876 -833
- package/dist/tools/types.d.ts +10 -14
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/utils/api-key-resolver.js +1 -1
- package/dist/utils/async-context.js +1 -1
- package/dist/utils/debug.js +1 -1
- package/dist/utils/defer.js +1 -1
- package/dist/utils/env.js +1 -1
- package/dist/utils/error-conversion.js +1 -1
- package/dist/utils/execution-context.js +1 -1
- package/dist/utils/fs-walk.js +1 -1
- package/dist/utils/path.js +1 -1
- package/dist/utils/redactor.js +1 -1
- package/dist/utils/result.js +1 -1
- package/dist/utils/safe-stringify.js +1 -1
- package/dist/utils/schema.js +1 -1
- package/dist/utils/service-initializer.cjs +37 -33
- package/dist/utils/service-initializer.d.ts +9 -5
- package/dist/utils/service-initializer.d.ts.map +1 -1
- package/dist/utils/service-initializer.js +38 -34
- package/dist/utils/zod-schema-converter.js +1 -1
- package/dist/workspace/error-codes.cjs +5 -1
- package/dist/workspace/error-codes.d.ts +4 -0
- package/dist/workspace/error-codes.d.ts.map +1 -1
- package/dist/workspace/error-codes.js +6 -2
- package/dist/workspace/errors.cjs +43 -0
- package/dist/workspace/errors.d.ts +9 -0
- package/dist/workspace/errors.d.ts.map +1 -1
- package/dist/workspace/errors.js +44 -1
- package/dist/workspace/index.d.ts +1 -1
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/index.js +1 -1
- package/dist/workspace/manager.cjs +21 -29
- package/dist/workspace/manager.d.ts +6 -6
- package/dist/workspace/manager.d.ts.map +1 -1
- package/dist/workspace/manager.js +22 -30
- package/dist/workspace/types.d.ts +47 -0
- package/dist/workspace/types.d.ts.map +1 -1
- package/package.json +114 -2
- package/dist/approval/session-approval-store.cjs +0 -91
- package/dist/approval/session-approval-store.d.ts +0 -37
- package/dist/approval/session-approval-store.d.ts.map +0 -1
- package/dist/approval/session-approval-store.js +0 -68
- package/dist/session/history/database.cjs +0 -232
- package/dist/session/history/database.d.ts +0 -41
- package/dist/session/history/database.d.ts.map +0 -1
- package/dist/session/history/database.js +0 -209
- package/dist/session/history/factory.d.ts +0 -11
- package/dist/session/history/factory.d.ts.map +0 -1
- package/dist/session/history/factory.js +0 -8
- package/dist/session/history/memory.d.ts +0 -22
- package/dist/session/history/memory.d.ts.map +0 -1
- package/dist/session/history/memory.js +0 -34
- package/dist/session/history/types.d.ts +0 -26
- package/dist/session/history/types.d.ts.map +0 -1
- package/dist/session/message-queue-store.cjs +0 -75
- package/dist/session/message-queue-store.d.ts +0 -16
- package/dist/session/message-queue-store.d.ts.map +0 -1
- package/dist/session/message-queue-store.js +0 -52
- package/dist/storage/storage-manager.cjs +0 -209
- package/dist/storage/storage-manager.d.ts +0 -77
- package/dist/storage/storage-manager.d.ts.map +0 -1
- package/dist/storage/storage-manager.js +0 -186
- package/dist/tools/confirmation/allowed-tools-provider/factory.d.ts.map +0 -1
- package/dist/tools/confirmation/allowed-tools-provider/in-memory.d.ts.map +0 -1
- package/dist/tools/confirmation/allowed-tools-provider/storage.cjs +0 -69
- package/dist/tools/confirmation/allowed-tools-provider/storage.d.ts.map +0 -1
- package/dist/tools/confirmation/allowed-tools-provider/storage.js +0 -46
- package/dist/tools/confirmation/allowed-tools-provider/types.d.ts.map +0 -1
- /package/dist/{session/history → skills}/types.cjs +0 -0
- /package/dist/{session/history → skills}/types.js +0 -0
- /package/dist/{tools/confirmation/allowed-tools-provider → storage/artifacts}/types.cjs +0 -0
- /package/dist/{tools/confirmation/allowed-tools-provider → storage/artifacts}/types.js +0 -0
- /package/dist/tools/{confirmation → approval}/allowed-tools-provider/in-memory.cjs +0 -0
- /package/dist/tools/{confirmation → approval}/allowed-tools-provider/in-memory.d.ts +0 -0
- /package/dist/tools/{confirmation → approval}/allowed-tools-provider/types.d.ts +0 -0
|
@@ -2,27 +2,41 @@ import {
|
|
|
2
2
|
__decorateElement,
|
|
3
3
|
__decoratorStart,
|
|
4
4
|
__runInitializers
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-C6A6W6XS.js";
|
|
6
6
|
var _ToolManager_decorators, _init;
|
|
7
|
+
import { isDeepStrictEqual } from "node:util";
|
|
7
8
|
import { ToolError } from "./errors.js";
|
|
8
|
-
import { ToolErrorCode } from "./error-codes.js";
|
|
9
9
|
import { DextoRuntimeError, ErrorScope, ErrorType } from "../errors/index.js";
|
|
10
10
|
import { DextoLogComponent } from "../logger/v2/types.js";
|
|
11
11
|
import { convertZodSchemaToJsonSchema } from "../utils/schema.js";
|
|
12
12
|
import { ApprovalStatus, ApprovalType, DenialReason } from "../approval/types.js";
|
|
13
|
+
import {
|
|
14
|
+
DirectoryAccessMetadataSchema,
|
|
15
|
+
ToolApprovalResponseDataSchema
|
|
16
|
+
} from "../approval/schemas.js";
|
|
17
|
+
import { matchesToolPolicyPattern, SessionToolPolicy } from "./approval/session-tool-policy.js";
|
|
18
|
+
import { ToolPresentation } from "./presentation/tool-presentation.js";
|
|
13
19
|
import { InstrumentClass } from "../telemetry/decorators.js";
|
|
20
|
+
import {
|
|
21
|
+
completedToolExecutionToResult,
|
|
22
|
+
createToolExecutionId
|
|
23
|
+
} from "../storage/tool-executions/types.js";
|
|
14
24
|
import {
|
|
15
25
|
extractToolCallMeta,
|
|
16
26
|
wrapToolParametersSchema
|
|
17
27
|
} from "./tool-call-metadata.js";
|
|
18
28
|
import { isBackgroundTasksEnabled } from "../utils/env.js";
|
|
29
|
+
function isRecord(value) {
|
|
30
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31
|
+
}
|
|
19
32
|
_ToolManager_decorators = [InstrumentClass({
|
|
20
33
|
prefix: "tool",
|
|
21
34
|
excludeMethods: ["setHookSupport", "getApprovalManager", "getAllowedToolsProvider"]
|
|
22
35
|
})];
|
|
23
36
|
let _ToolManager = class _ToolManager {
|
|
24
|
-
constructor(mcpManager, approvalManager, allowedToolsProvider, approvalMode, agentEventBus, toolPolicies, tools, logger, sessionToolPreferencesStore) {
|
|
37
|
+
constructor(mcpManager, approvalManager, allowedToolsProvider, approvalMode, agentEventBus, toolPolicies, tools, logger, sessionToolPreferencesStore, toolExecutionStore) {
|
|
25
38
|
this.sessionToolPreferencesStore = sessionToolPreferencesStore;
|
|
39
|
+
this.toolExecutionStore = toolExecutionStore;
|
|
26
40
|
this.mcpManager = mcpManager;
|
|
27
41
|
this.approvalManager = approvalManager;
|
|
28
42
|
this.allowedToolsProvider = allowedToolsProvider;
|
|
@@ -30,6 +44,17 @@ let _ToolManager = class _ToolManager {
|
|
|
30
44
|
this.agentEventBus = agentEventBus;
|
|
31
45
|
this.toolPolicies = toolPolicies;
|
|
32
46
|
this.logger = logger.createChild(DextoLogComponent.TOOLS);
|
|
47
|
+
this.sessionToolPolicy = new SessionToolPolicy(
|
|
48
|
+
sessionToolPreferencesStore,
|
|
49
|
+
this.logger,
|
|
50
|
+
(pattern) => this.normalizeToolPolicyPattern(pattern)
|
|
51
|
+
);
|
|
52
|
+
this.toolPresentation = new ToolPresentation(
|
|
53
|
+
(toolName) => this.agentTools.get(toolName),
|
|
54
|
+
(toolName, args) => this.validateLocalToolArgs(toolName, args),
|
|
55
|
+
(options) => this.buildToolExecutionContext(options),
|
|
56
|
+
this.logger
|
|
57
|
+
);
|
|
33
58
|
this.setTools(tools);
|
|
34
59
|
this.toolExecutionContextFactory = () => {
|
|
35
60
|
throw ToolError.configInvalid(
|
|
@@ -64,16 +89,8 @@ let _ToolManager = class _ToolManager {
|
|
|
64
89
|
toolsCache = {};
|
|
65
90
|
cacheValid = false;
|
|
66
91
|
logger;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// This is ADDITIVE - other tools are NOT blocked, they just go through normal approval flow
|
|
70
|
-
sessionAutoApproveTools = /* @__PURE__ */ new Map();
|
|
71
|
-
// Session-level auto-approve tools set by users (UI)
|
|
72
|
-
sessionUserAutoApproveTools = /* @__PURE__ */ new Map();
|
|
73
|
-
sessionDisabledTools = /* @__PURE__ */ new Map();
|
|
74
|
-
restoredSessionPreferences = /* @__PURE__ */ new Set();
|
|
75
|
-
sessionPreferenceLocks = /* @__PURE__ */ new Map();
|
|
76
|
-
globalDisabledTools = [];
|
|
92
|
+
sessionToolPolicy;
|
|
93
|
+
toolPresentation;
|
|
77
94
|
cleanupHandlers = /* @__PURE__ */ new Set();
|
|
78
95
|
cleanupStarted = false;
|
|
79
96
|
resolveLocalToolIdOrAlias(name) {
|
|
@@ -96,76 +113,14 @@ let _ToolManager = class _ToolManager {
|
|
|
96
113
|
}
|
|
97
114
|
return this.resolveLocalToolIdOrAlias(pattern) ?? pattern;
|
|
98
115
|
}
|
|
99
|
-
async runWithSessionPreferenceLock(sessionId, fn) {
|
|
100
|
-
const previousLock = this.sessionPreferenceLocks.get(sessionId) ?? Promise.resolve();
|
|
101
|
-
const currentResult = previousLock.catch(() => {
|
|
102
|
-
}).then(() => fn());
|
|
103
|
-
const currentLock = currentResult.then(
|
|
104
|
-
() => void 0,
|
|
105
|
-
() => void 0
|
|
106
|
-
);
|
|
107
|
-
this.sessionPreferenceLocks.set(sessionId, currentLock);
|
|
108
|
-
try {
|
|
109
|
-
return await currentResult;
|
|
110
|
-
} finally {
|
|
111
|
-
if (this.sessionPreferenceLocks.get(sessionId) === currentLock) {
|
|
112
|
-
this.sessionPreferenceLocks.delete(sessionId);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
applySessionToolPreferences(sessionId, preferences) {
|
|
117
|
-
if (preferences.userAutoApproveTools.length > 0) {
|
|
118
|
-
this.sessionUserAutoApproveTools.set(sessionId, [...preferences.userAutoApproveTools]);
|
|
119
|
-
} else {
|
|
120
|
-
this.sessionUserAutoApproveTools.delete(sessionId);
|
|
121
|
-
}
|
|
122
|
-
if (preferences.disabledTools.length > 0) {
|
|
123
|
-
this.sessionDisabledTools.set(sessionId, [...preferences.disabledTools]);
|
|
124
|
-
} else {
|
|
125
|
-
this.sessionDisabledTools.delete(sessionId);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
getSessionToolPreferencesSnapshot(sessionId) {
|
|
129
|
-
return {
|
|
130
|
-
userAutoApproveTools: [...this.sessionUserAutoApproveTools.get(sessionId) ?? []],
|
|
131
|
-
disabledTools: [...this.sessionDisabledTools.get(sessionId) ?? []]
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
116
|
async restoreSessionState(sessionId) {
|
|
135
|
-
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
await this.runWithSessionPreferenceLock(sessionId, async () => {
|
|
139
|
-
if (this.restoredSessionPreferences.has(sessionId)) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
const preferences = await this.sessionToolPreferencesStore.load(sessionId);
|
|
143
|
-
this.applySessionToolPreferences(sessionId, preferences);
|
|
144
|
-
this.restoredSessionPreferences.add(sessionId);
|
|
145
|
-
this.logger.debug("Restored persisted session tool preferences", {
|
|
146
|
-
sessionId,
|
|
147
|
-
autoApproveCount: preferences.userAutoApproveTools.length,
|
|
148
|
-
disabledCount: preferences.disabledTools.length
|
|
149
|
-
});
|
|
150
|
-
});
|
|
117
|
+
await this.sessionToolPolicy.restoreSessionState(sessionId);
|
|
151
118
|
}
|
|
152
119
|
evictSessionState(sessionId) {
|
|
153
|
-
this.
|
|
154
|
-
this.sessionUserAutoApproveTools.delete(sessionId);
|
|
155
|
-
this.sessionDisabledTools.delete(sessionId);
|
|
156
|
-
this.restoredSessionPreferences.delete(sessionId);
|
|
120
|
+
this.sessionToolPolicy.evictSessionState(sessionId);
|
|
157
121
|
}
|
|
158
122
|
async deleteSessionState(sessionId) {
|
|
159
|
-
await this.
|
|
160
|
-
this.evictSessionState(sessionId);
|
|
161
|
-
await this.sessionToolPreferencesStore.delete(sessionId);
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
async persistSessionToolPreferences(sessionId) {
|
|
165
|
-
await this.sessionToolPreferencesStore.save(
|
|
166
|
-
sessionId,
|
|
167
|
-
this.getSessionToolPreferencesSnapshot(sessionId)
|
|
168
|
-
);
|
|
123
|
+
await this.sessionToolPolicy.deleteSessionState(sessionId);
|
|
169
124
|
}
|
|
170
125
|
/**
|
|
171
126
|
* Initialize the ToolManager and its components
|
|
@@ -268,25 +223,14 @@ let _ToolManager = class _ToolManager {
|
|
|
268
223
|
// ============= SESSION AUTO-APPROVE TOOLS =============
|
|
269
224
|
/**
|
|
270
225
|
* Set session-level auto-approve tools.
|
|
271
|
-
* When set, these tools will skip
|
|
226
|
+
* When set, these tools will skip approval prompts for this session.
|
|
272
227
|
* This is ADDITIVE - other tools are NOT blocked, they just go through normal approval flow.
|
|
273
228
|
*
|
|
274
229
|
* @param sessionId The session ID
|
|
275
230
|
* @param autoApproveTools Array of tool names to auto-approve (e.g., ['bash_exec', 'mcp--read_file'])
|
|
276
231
|
*/
|
|
277
232
|
setSessionAutoApproveTools(sessionId, autoApproveTools) {
|
|
278
|
-
|
|
279
|
-
this.clearSessionAutoApproveTools(sessionId);
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
const normalized = autoApproveTools.map(
|
|
283
|
-
(pattern) => this.normalizeToolPolicyPattern(pattern)
|
|
284
|
-
);
|
|
285
|
-
this.sessionAutoApproveTools.set(sessionId, normalized);
|
|
286
|
-
this.logger.info(
|
|
287
|
-
`Session auto-approve tools set for '${sessionId}': ${autoApproveTools.length} tools`
|
|
288
|
-
);
|
|
289
|
-
this.logger.debug(`Auto-approve tools: ${normalized.join(", ")}`);
|
|
233
|
+
this.sessionToolPolicy.setSessionAutoApproveTools(sessionId, autoApproveTools);
|
|
290
234
|
}
|
|
291
235
|
/**
|
|
292
236
|
* Add session-level auto-approve tools.
|
|
@@ -296,64 +240,19 @@ let _ToolManager = class _ToolManager {
|
|
|
296
240
|
* @param autoApproveTools Array of tool names to auto-approve (e.g., ['bash_exec', 'mcp--read_file'])
|
|
297
241
|
*/
|
|
298
242
|
addSessionAutoApproveTools(sessionId, autoApproveTools) {
|
|
299
|
-
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
const normalized = autoApproveTools.map(
|
|
303
|
-
(pattern) => this.normalizeToolPolicyPattern(pattern)
|
|
304
|
-
);
|
|
305
|
-
const existing = this.sessionAutoApproveTools.get(sessionId) ?? [];
|
|
306
|
-
const merged = [...existing];
|
|
307
|
-
const seen = new Set(existing);
|
|
308
|
-
for (const toolName of normalized) {
|
|
309
|
-
if (seen.has(toolName)) {
|
|
310
|
-
continue;
|
|
311
|
-
}
|
|
312
|
-
merged.push(toolName);
|
|
313
|
-
seen.add(toolName);
|
|
314
|
-
}
|
|
315
|
-
const actuallyAdded = Math.max(0, merged.length - existing.length);
|
|
316
|
-
this.sessionAutoApproveTools.set(sessionId, merged);
|
|
317
|
-
this.logger.info(
|
|
318
|
-
`Session auto-approve tools updated for '${sessionId}': +${actuallyAdded} tools`
|
|
319
|
-
);
|
|
320
|
-
this.logger.debug(`Auto-approve tools: ${merged.join(", ")}`);
|
|
243
|
+
this.sessionToolPolicy.addSessionAutoApproveTools(sessionId, autoApproveTools);
|
|
321
244
|
}
|
|
322
245
|
/**
|
|
323
246
|
* Set session-level auto-approve tools chosen by the user.
|
|
324
247
|
*/
|
|
325
248
|
async setSessionUserAutoApproveTools(sessionId, autoApproveTools) {
|
|
326
|
-
await this.
|
|
327
|
-
if (autoApproveTools.length === 0) {
|
|
328
|
-
await this.clearSessionUserAutoApproveTools(sessionId);
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
const normalized = autoApproveTools.map(
|
|
332
|
-
(pattern) => this.normalizeToolPolicyPattern(pattern)
|
|
333
|
-
);
|
|
334
|
-
await this.runWithSessionPreferenceLock(sessionId, async () => {
|
|
335
|
-
this.sessionUserAutoApproveTools.set(sessionId, normalized);
|
|
336
|
-
await this.persistSessionToolPreferences(sessionId);
|
|
337
|
-
});
|
|
338
|
-
this.logger.info(
|
|
339
|
-
`Session user auto-approve tools set for '${sessionId}': ${autoApproveTools.length} tools`
|
|
340
|
-
);
|
|
341
|
-
this.logger.debug(`User auto-approve tools: ${normalized.join(", ")}`);
|
|
249
|
+
await this.sessionToolPolicy.setSessionUserAutoApproveTools(sessionId, autoApproveTools);
|
|
342
250
|
}
|
|
343
251
|
/**
|
|
344
252
|
* Clear session-level auto-approve tools chosen by the user.
|
|
345
253
|
*/
|
|
346
254
|
async clearSessionUserAutoApproveTools(sessionId) {
|
|
347
|
-
await this.
|
|
348
|
-
let hadAutoApprove = false;
|
|
349
|
-
await this.runWithSessionPreferenceLock(sessionId, async () => {
|
|
350
|
-
hadAutoApprove = this.sessionUserAutoApproveTools.has(sessionId);
|
|
351
|
-
this.sessionUserAutoApproveTools.delete(sessionId);
|
|
352
|
-
await this.persistSessionToolPreferences(sessionId);
|
|
353
|
-
});
|
|
354
|
-
if (hadAutoApprove) {
|
|
355
|
-
this.logger.info(`Session user auto-approve tools cleared for '${sessionId}'`);
|
|
356
|
-
}
|
|
255
|
+
await this.sessionToolPolicy.clearSessionUserAutoApproveTools(sessionId);
|
|
357
256
|
}
|
|
358
257
|
/**
|
|
359
258
|
* Clear session-level auto-approve tools.
|
|
@@ -362,49 +261,30 @@ let _ToolManager = class _ToolManager {
|
|
|
362
261
|
* @param sessionId The session ID to clear auto-approve tools for
|
|
363
262
|
*/
|
|
364
263
|
clearSessionAutoApproveTools(sessionId) {
|
|
365
|
-
|
|
366
|
-
this.sessionAutoApproveTools.delete(sessionId);
|
|
367
|
-
if (hadAutoApprove) {
|
|
368
|
-
this.logger.info(`Session auto-approve tools cleared for '${sessionId}'`);
|
|
369
|
-
}
|
|
264
|
+
this.sessionToolPolicy.clearSessionAutoApproveTools(sessionId);
|
|
370
265
|
}
|
|
371
266
|
hasSessionUserAutoApproveTools(sessionId) {
|
|
372
|
-
return this.
|
|
267
|
+
return this.sessionToolPolicy.hasSessionUserAutoApproveTools(sessionId);
|
|
373
268
|
}
|
|
374
269
|
// ============= ENABLED/DISABLED TOOLS =============
|
|
375
270
|
/**
|
|
376
271
|
* Set global disabled tools (agent-level preferences).
|
|
377
272
|
*/
|
|
378
273
|
setGlobalDisabledTools(toolNames) {
|
|
379
|
-
this.
|
|
380
|
-
this.logger.info("Global disabled tools updated", {
|
|
381
|
-
count: toolNames.length
|
|
382
|
-
});
|
|
274
|
+
this.sessionToolPolicy.setGlobalDisabledTools(toolNames);
|
|
383
275
|
this.agentEventBus.emit("tools:enabled-updated", {
|
|
384
276
|
scope: "global",
|
|
385
|
-
disabledTools:
|
|
277
|
+
disabledTools: this.sessionToolPolicy.getGlobalDisabledTools()
|
|
386
278
|
});
|
|
387
279
|
}
|
|
388
280
|
getGlobalDisabledTools() {
|
|
389
|
-
return
|
|
281
|
+
return this.sessionToolPolicy.getGlobalDisabledTools();
|
|
390
282
|
}
|
|
391
283
|
/**
|
|
392
284
|
* Set session-level disabled tools (overrides global list).
|
|
393
285
|
*/
|
|
394
286
|
async setSessionDisabledTools(sessionId, toolNames) {
|
|
395
|
-
await this.
|
|
396
|
-
if (toolNames.length === 0) {
|
|
397
|
-
await this.clearSessionDisabledTools(sessionId);
|
|
398
|
-
return;
|
|
399
|
-
}
|
|
400
|
-
await this.runWithSessionPreferenceLock(sessionId, async () => {
|
|
401
|
-
this.sessionDisabledTools.set(sessionId, [...toolNames]);
|
|
402
|
-
await this.persistSessionToolPreferences(sessionId);
|
|
403
|
-
});
|
|
404
|
-
this.logger.info("Session disabled tools updated", {
|
|
405
|
-
sessionId,
|
|
406
|
-
count: toolNames.length
|
|
407
|
-
});
|
|
287
|
+
await this.sessionToolPolicy.setSessionDisabledTools(sessionId, toolNames);
|
|
408
288
|
this.agentEventBus.emit("tools:enabled-updated", {
|
|
409
289
|
scope: "session",
|
|
410
290
|
sessionId,
|
|
@@ -415,37 +295,19 @@ let _ToolManager = class _ToolManager {
|
|
|
415
295
|
* Clear session-level disabled tools.
|
|
416
296
|
*/
|
|
417
297
|
async clearSessionDisabledTools(sessionId) {
|
|
418
|
-
await this.
|
|
419
|
-
let hadOverrides = false;
|
|
420
|
-
await this.runWithSessionPreferenceLock(sessionId, async () => {
|
|
421
|
-
hadOverrides = this.sessionDisabledTools.has(sessionId);
|
|
422
|
-
this.sessionDisabledTools.delete(sessionId);
|
|
423
|
-
await this.persistSessionToolPreferences(sessionId);
|
|
424
|
-
});
|
|
425
|
-
if (hadOverrides) {
|
|
426
|
-
this.logger.info("Session disabled tools cleared", { sessionId });
|
|
427
|
-
}
|
|
298
|
+
await this.sessionToolPolicy.clearSessionDisabledTools(sessionId);
|
|
428
299
|
}
|
|
429
300
|
/**
|
|
430
301
|
* Get disabled tools for a session (session override wins).
|
|
431
302
|
*/
|
|
432
303
|
getDisabledTools(sessionId) {
|
|
433
|
-
|
|
434
|
-
return this.sessionDisabledTools.get(sessionId) ?? [];
|
|
435
|
-
}
|
|
436
|
-
return this.globalDisabledTools;
|
|
304
|
+
return this.sessionToolPolicy.getDisabledTools(sessionId);
|
|
437
305
|
}
|
|
438
306
|
/**
|
|
439
307
|
* Filter a tool set based on disabled tools for a session.
|
|
440
308
|
*/
|
|
441
309
|
filterToolsForSession(toolSet, sessionId) {
|
|
442
|
-
|
|
443
|
-
if (disabled.size === 0) {
|
|
444
|
-
return toolSet;
|
|
445
|
-
}
|
|
446
|
-
return Object.fromEntries(
|
|
447
|
-
Object.entries(toolSet).filter(([toolName]) => !disabled.has(toolName))
|
|
448
|
-
);
|
|
310
|
+
return this.sessionToolPolicy.filterToolsForSession(toolSet, sessionId);
|
|
449
311
|
}
|
|
450
312
|
/**
|
|
451
313
|
* Check if a session has auto-approve tools set.
|
|
@@ -454,7 +316,7 @@ let _ToolManager = class _ToolManager {
|
|
|
454
316
|
* @returns true if the session has auto-approve tools
|
|
455
317
|
*/
|
|
456
318
|
hasSessionAutoApproveTools(sessionId) {
|
|
457
|
-
return this.
|
|
319
|
+
return this.sessionToolPolicy.hasSessionAutoApproveTools(sessionId);
|
|
458
320
|
}
|
|
459
321
|
/**
|
|
460
322
|
* Get the auto-approve tools for a session (skill-provided list).
|
|
@@ -463,22 +325,19 @@ let _ToolManager = class _ToolManager {
|
|
|
463
325
|
* @returns Array of auto-approve tool names, or undefined if none set
|
|
464
326
|
*/
|
|
465
327
|
getSessionAutoApproveTools(sessionId) {
|
|
466
|
-
return this.
|
|
328
|
+
return this.sessionToolPolicy.getSessionAutoApproveTools(sessionId);
|
|
467
329
|
}
|
|
468
330
|
/**
|
|
469
331
|
* Get the user auto-approve tools for a session.
|
|
470
332
|
*/
|
|
471
333
|
getSessionUserAutoApproveTools(sessionId) {
|
|
472
|
-
return this.
|
|
334
|
+
return this.sessionToolPolicy.getSessionUserAutoApproveTools(sessionId);
|
|
473
335
|
}
|
|
474
336
|
/**
|
|
475
337
|
* Combined auto-approve list for a session.
|
|
476
338
|
*/
|
|
477
339
|
getCombinedSessionAutoApproveTools(sessionId) {
|
|
478
|
-
return
|
|
479
|
-
...this.sessionAutoApproveTools.get(sessionId) ?? [],
|
|
480
|
-
...this.sessionUserAutoApproveTools.get(sessionId) ?? []
|
|
481
|
-
];
|
|
340
|
+
return this.sessionToolPolicy.getCombinedSessionAutoApproveTools(sessionId);
|
|
482
341
|
}
|
|
483
342
|
/**
|
|
484
343
|
* Check if a tool should be auto-approved for a session.
|
|
@@ -489,11 +348,7 @@ let _ToolManager = class _ToolManager {
|
|
|
489
348
|
* @returns true if the tool should be auto-approved
|
|
490
349
|
*/
|
|
491
350
|
isToolAutoApprovedForSession(sessionId, toolName) {
|
|
492
|
-
|
|
493
|
-
if (autoApproveTools.length === 0) {
|
|
494
|
-
return false;
|
|
495
|
-
}
|
|
496
|
-
return autoApproveTools.some((pattern) => this.matchesToolPolicy(toolName, pattern));
|
|
351
|
+
return this.sessionToolPolicy.isToolAutoApprovedForSession(sessionId, toolName);
|
|
497
352
|
}
|
|
498
353
|
/**
|
|
499
354
|
* Invalidate the tools cache when tool sources change
|
|
@@ -571,149 +426,6 @@ let _ToolManager = class _ToolManager {
|
|
|
571
426
|
const tool = this.agentTools.get(toolName);
|
|
572
427
|
return tool?.approval?.onGranted;
|
|
573
428
|
}
|
|
574
|
-
getToolPreviewFn(toolName) {
|
|
575
|
-
const tool = this.agentTools.get(toolName);
|
|
576
|
-
return tool?.presentation?.preview;
|
|
577
|
-
}
|
|
578
|
-
getToolDescribeHeaderFn(toolName) {
|
|
579
|
-
const tool = this.agentTools.get(toolName);
|
|
580
|
-
return tool?.presentation?.describeHeader;
|
|
581
|
-
}
|
|
582
|
-
getToolDescribeArgsFn(toolName) {
|
|
583
|
-
const tool = this.agentTools.get(toolName);
|
|
584
|
-
return tool?.presentation?.describeArgs;
|
|
585
|
-
}
|
|
586
|
-
getToolDescribeResultFn(toolName) {
|
|
587
|
-
const tool = this.agentTools.get(toolName);
|
|
588
|
-
return tool?.presentation?.describeResult;
|
|
589
|
-
}
|
|
590
|
-
buildGenericToolPresentationSnapshot(toolName) {
|
|
591
|
-
const toTitleCase = (name) => name.replace(/[_-]+/g, " ").split(" ").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
592
|
-
const isMcp = toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX);
|
|
593
|
-
const fallbackTitle = (() => {
|
|
594
|
-
if (!isMcp) {
|
|
595
|
-
return toTitleCase(toolName);
|
|
596
|
-
}
|
|
597
|
-
const actualToolName = toolName.substring(_ToolManager.MCP_TOOL_PREFIX.length);
|
|
598
|
-
const parts = actualToolName.split("--");
|
|
599
|
-
const toolPart = parts.length >= 2 ? parts.slice(1).join("--") : actualToolName;
|
|
600
|
-
return toTitleCase(toolPart);
|
|
601
|
-
})();
|
|
602
|
-
const snapshot = {
|
|
603
|
-
version: 1,
|
|
604
|
-
source: {
|
|
605
|
-
type: toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX) ? "mcp" : "local"
|
|
606
|
-
},
|
|
607
|
-
header: {
|
|
608
|
-
title: fallbackTitle
|
|
609
|
-
}
|
|
610
|
-
};
|
|
611
|
-
if (snapshot.source?.type === "mcp") {
|
|
612
|
-
const actualToolName = toolName.substring(_ToolManager.MCP_TOOL_PREFIX.length);
|
|
613
|
-
const parts = actualToolName.split("--");
|
|
614
|
-
if (parts.length >= 2 && parts[0]) {
|
|
615
|
-
snapshot.source.mcpServerName = parts[0];
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
return snapshot;
|
|
619
|
-
}
|
|
620
|
-
getToolPresentationSnapshotForToolCallEvent(toolName, args, toolCallId, sessionId, runContext) {
|
|
621
|
-
const fallback = this.buildGenericToolPresentationSnapshot(toolName);
|
|
622
|
-
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
623
|
-
return fallback;
|
|
624
|
-
}
|
|
625
|
-
const describeHeader = this.getToolDescribeHeaderFn(toolName);
|
|
626
|
-
const describeArgs = this.getToolDescribeArgsFn(toolName);
|
|
627
|
-
if (!describeHeader && !describeArgs) {
|
|
628
|
-
return fallback;
|
|
629
|
-
}
|
|
630
|
-
try {
|
|
631
|
-
const validatedArgs = this.validateLocalToolArgs(toolName, args);
|
|
632
|
-
const context = this.buildToolExecutionContext({ sessionId, toolCallId, runContext });
|
|
633
|
-
const isPromiseLike = (value) => {
|
|
634
|
-
if (typeof value !== "object" || value === null) {
|
|
635
|
-
return false;
|
|
636
|
-
}
|
|
637
|
-
return typeof value.then === "function";
|
|
638
|
-
};
|
|
639
|
-
let nextSnapshot = fallback;
|
|
640
|
-
if (describeHeader) {
|
|
641
|
-
const header = describeHeader(validatedArgs, context);
|
|
642
|
-
if (!isPromiseLike(header) && header) {
|
|
643
|
-
nextSnapshot = {
|
|
644
|
-
...nextSnapshot,
|
|
645
|
-
header: { ...nextSnapshot.header, ...header }
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
if (describeArgs) {
|
|
650
|
-
const argsPresentation = describeArgs(validatedArgs, context);
|
|
651
|
-
if (!isPromiseLike(argsPresentation) && argsPresentation) {
|
|
652
|
-
nextSnapshot = {
|
|
653
|
-
...nextSnapshot,
|
|
654
|
-
args: argsPresentation
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
return nextSnapshot;
|
|
659
|
-
} catch (error) {
|
|
660
|
-
this.logger.debug(
|
|
661
|
-
`Tool presentation snapshot generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
|
|
662
|
-
);
|
|
663
|
-
return fallback;
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
async getToolPresentationSnapshotForCall(toolName, args, toolCallId, sessionId, runContext) {
|
|
667
|
-
const fallback = this.buildGenericToolPresentationSnapshot(toolName);
|
|
668
|
-
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
669
|
-
return fallback;
|
|
670
|
-
}
|
|
671
|
-
const describeHeader = this.getToolDescribeHeaderFn(toolName);
|
|
672
|
-
const describeArgs = this.getToolDescribeArgsFn(toolName);
|
|
673
|
-
if (!describeHeader && !describeArgs) {
|
|
674
|
-
return fallback;
|
|
675
|
-
}
|
|
676
|
-
try {
|
|
677
|
-
const context = this.buildToolExecutionContext({ sessionId, toolCallId, runContext });
|
|
678
|
-
const describedHeader = describeHeader ? await Promise.resolve(describeHeader(args, context)) : null;
|
|
679
|
-
const describedArgs = describeArgs ? await Promise.resolve(describeArgs(args, context)) : null;
|
|
680
|
-
return {
|
|
681
|
-
...fallback,
|
|
682
|
-
...describedHeader ? { header: { ...fallback.header, ...describedHeader } } : {},
|
|
683
|
-
...describedArgs ? { args: describedArgs } : {}
|
|
684
|
-
};
|
|
685
|
-
} catch (error) {
|
|
686
|
-
this.logger.debug(
|
|
687
|
-
`Tool presentation snapshot generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
|
|
688
|
-
);
|
|
689
|
-
return fallback;
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
async augmentSnapshotWithResult(toolName, snapshot, result, args, toolCallId, sessionId, runContext) {
|
|
693
|
-
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
694
|
-
return snapshot;
|
|
695
|
-
}
|
|
696
|
-
const describeResult = this.getToolDescribeResultFn(toolName);
|
|
697
|
-
if (!describeResult) {
|
|
698
|
-
return snapshot;
|
|
699
|
-
}
|
|
700
|
-
try {
|
|
701
|
-
const context = this.buildToolExecutionContext({ sessionId, toolCallId, runContext });
|
|
702
|
-
const resultPresentation = await Promise.resolve(describeResult(result, args, context));
|
|
703
|
-
if (!resultPresentation) {
|
|
704
|
-
return snapshot;
|
|
705
|
-
}
|
|
706
|
-
return {
|
|
707
|
-
...snapshot,
|
|
708
|
-
result: resultPresentation
|
|
709
|
-
};
|
|
710
|
-
} catch (error) {
|
|
711
|
-
this.logger.debug(
|
|
712
|
-
`Tool result presentation snapshot generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
|
|
713
|
-
);
|
|
714
|
-
return snapshot;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
429
|
getToolPatternKey(toolName, args) {
|
|
718
430
|
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
719
431
|
return null;
|
|
@@ -806,14 +518,9 @@ let _ToolManager = class _ToolManager {
|
|
|
806
518
|
if (request.metadata.directoryAccess !== void 0) {
|
|
807
519
|
return false;
|
|
808
520
|
}
|
|
809
|
-
const args = request.metadata.args;
|
|
810
|
-
if (typeof args !== "object" || args === null) {
|
|
811
|
-
return false;
|
|
812
|
-
}
|
|
813
|
-
const argsRecord = args;
|
|
814
521
|
let patternKey;
|
|
815
522
|
try {
|
|
816
|
-
patternKey = getPatternKey(
|
|
523
|
+
patternKey = getPatternKey(request.metadata.args);
|
|
817
524
|
} catch (error) {
|
|
818
525
|
this.logger.debug(
|
|
819
526
|
`Pattern key generation failed for '${toolName}': ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -942,22 +649,52 @@ let _ToolManager = class _ToolManager {
|
|
|
942
649
|
};
|
|
943
650
|
return this.toolExecutionContextFactory(baseContext);
|
|
944
651
|
}
|
|
945
|
-
resolveToolExecutionInvocation(
|
|
946
|
-
if (typeof
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
652
|
+
resolveToolExecutionInvocation(invocation) {
|
|
653
|
+
if (typeof invocation !== "object" && invocation !== void 0) {
|
|
654
|
+
throw new TypeError("Tool execution invocation must be an object");
|
|
655
|
+
}
|
|
656
|
+
const options = invocation ?? {};
|
|
657
|
+
const sessionId = options.runContext?.sessionId ?? options.sessionId;
|
|
658
|
+
return { ...options, sessionId, hostRuntime: options.runContext?.hostRuntime };
|
|
659
|
+
}
|
|
660
|
+
resolveToolExecutionIdentity(invocation, toolCallId) {
|
|
661
|
+
if (invocation.executionIdentity !== void 0) {
|
|
662
|
+
return invocation.executionIdentity;
|
|
663
|
+
}
|
|
664
|
+
const ids = invocation.runContext?.hostRuntime?.ids;
|
|
665
|
+
if (!ids) {
|
|
666
|
+
return void 0;
|
|
667
|
+
}
|
|
668
|
+
const runId = ids.runId;
|
|
669
|
+
const turnId = ids.turnId;
|
|
670
|
+
const modelStepId = ids.modelStepId;
|
|
671
|
+
if (runId === void 0 || turnId === void 0 || modelStepId === void 0) {
|
|
672
|
+
return void 0;
|
|
952
673
|
}
|
|
953
|
-
const invocation = invocationOrSessionId ?? {};
|
|
954
|
-
const sessionId = invocation.runContext?.sessionId ?? invocation.sessionId;
|
|
955
674
|
return {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
675
|
+
runId,
|
|
676
|
+
turnId,
|
|
677
|
+
modelStepId,
|
|
678
|
+
toolCallId
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
assertToolExecutionRecordMatches(input) {
|
|
682
|
+
const expected = {
|
|
683
|
+
identity: input.identity,
|
|
684
|
+
toolName: input.toolName,
|
|
685
|
+
input: input.toolInput
|
|
686
|
+
};
|
|
687
|
+
const actual = {
|
|
688
|
+
identity: input.record.identity,
|
|
689
|
+
toolName: input.record.toolName,
|
|
690
|
+
input: input.record.input
|
|
960
691
|
};
|
|
692
|
+
if (!isDeepStrictEqual(actual, expected)) {
|
|
693
|
+
throw ToolError.executionFailed(
|
|
694
|
+
input.toolName,
|
|
695
|
+
"Tool execution record does not match the current tool call"
|
|
696
|
+
);
|
|
697
|
+
}
|
|
961
698
|
}
|
|
962
699
|
validateLocalToolArgs(toolName, args) {
|
|
963
700
|
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
@@ -1087,205 +824,782 @@ let _ToolManager = class _ToolManager {
|
|
|
1087
824
|
this.cacheValid = true;
|
|
1088
825
|
return this.toolsCache;
|
|
1089
826
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
827
|
+
async prepareToolCall(input) {
|
|
828
|
+
const sessionId = input.runContext?.sessionId ?? input.sessionId;
|
|
829
|
+
const source = await this.resolveExecutableToolSource(input.toolName);
|
|
830
|
+
if (source === "unknown") {
|
|
831
|
+
return this.createPreparedToolError(
|
|
832
|
+
"unknown-tool",
|
|
833
|
+
input.toolName,
|
|
834
|
+
`Tool '${input.toolName}' not found`
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
if (!isRecord(input.input)) {
|
|
838
|
+
return this.createPreparedToolError(
|
|
839
|
+
"invalid-input",
|
|
840
|
+
input.toolName,
|
|
841
|
+
"Invalid arguments: expected an object"
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
const { toolArgs: rawToolArgs, meta } = extractToolCallMeta(input.input);
|
|
1105
845
|
const eventMeta = Object.keys(meta).length > 0 ? meta : void 0;
|
|
1106
|
-
let toolArgs = rawToolArgs;
|
|
1107
846
|
const callDescription = typeof meta.callDescription === "string" ? meta.callDescription : typeof rawToolArgs.description === "string" ? rawToolArgs.description : void 0;
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
sessionId,
|
|
1117
|
-
runContext
|
|
847
|
+
let validatedArgs;
|
|
848
|
+
try {
|
|
849
|
+
validatedArgs = this.validateLocalToolArgs(input.toolName, rawToolArgs);
|
|
850
|
+
} catch (error) {
|
|
851
|
+
return this.createPreparedToolError(
|
|
852
|
+
"invalid-input",
|
|
853
|
+
input.toolName,
|
|
854
|
+
error instanceof Error ? error.message : String(error)
|
|
1118
855
|
);
|
|
1119
|
-
this.agentEventBus.emit("llm:tool-call", {
|
|
1120
|
-
toolName,
|
|
1121
|
-
presentationSnapshot,
|
|
1122
|
-
args: toolArgs,
|
|
1123
|
-
...eventMeta !== void 0 ? { meta: eventMeta } : {},
|
|
1124
|
-
...callDescription !== void 0 && { callDescription },
|
|
1125
|
-
callId: toolCallId,
|
|
1126
|
-
sessionId,
|
|
1127
|
-
...hostRuntime !== void 0 && { hostRuntime }
|
|
1128
|
-
});
|
|
1129
856
|
}
|
|
1130
|
-
const {
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
857
|
+
const presentationSnapshot = await this.toolPresentation.snapshotForCall({
|
|
858
|
+
toolName: input.toolName,
|
|
859
|
+
args: validatedArgs,
|
|
860
|
+
toolCallId: input.toolCallId,
|
|
861
|
+
...sessionId !== void 0 ? { sessionId } : {},
|
|
862
|
+
...input.runContext !== void 0 ? { runContext: input.runContext } : {}
|
|
863
|
+
});
|
|
864
|
+
const call = {
|
|
865
|
+
input: validatedArgs,
|
|
866
|
+
presentationSnapshot,
|
|
867
|
+
source,
|
|
868
|
+
toolCallId: input.toolCallId,
|
|
869
|
+
toolName: input.toolName,
|
|
870
|
+
...callDescription !== void 0 ? { callDescription } : {},
|
|
871
|
+
...eventMeta !== void 0 ? { meta: eventMeta } : {}
|
|
872
|
+
};
|
|
873
|
+
const overrideRequest = await this.getToolApprovalOverrideRequest(
|
|
874
|
+
input.toolName,
|
|
875
|
+
validatedArgs,
|
|
876
|
+
input.toolCallId,
|
|
1139
877
|
sessionId,
|
|
1140
|
-
runContext
|
|
1141
|
-
callDescription
|
|
878
|
+
input.runContext
|
|
1142
879
|
);
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
880
|
+
if (overrideRequest) {
|
|
881
|
+
if (!overrideRequest.directoryAccess) {
|
|
882
|
+
return {
|
|
883
|
+
kind: "approval-required",
|
|
884
|
+
call,
|
|
885
|
+
onGrantedRequestDetails: overrideRequest.onGrantedRequestDetails,
|
|
886
|
+
requestDetails: overrideRequest.requestDetails
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
const quickResult2 = await this.classifyQuickApprovalRequirement(
|
|
890
|
+
input.toolName,
|
|
891
|
+
validatedArgs,
|
|
1152
892
|
sessionId,
|
|
1153
|
-
|
|
893
|
+
overrideRequest.directoryAccess
|
|
894
|
+
);
|
|
895
|
+
if (quickResult2 === "ready") {
|
|
896
|
+
return { kind: "ready", call };
|
|
897
|
+
}
|
|
898
|
+
const displayPreview2 = await this.toolPresentation.preview({
|
|
899
|
+
toolName: input.toolName,
|
|
900
|
+
args: validatedArgs,
|
|
901
|
+
toolCallId: input.toolCallId,
|
|
902
|
+
...sessionId !== void 0 ? { sessionId } : {},
|
|
903
|
+
...input.runContext !== void 0 ? { runContext: input.runContext } : {}
|
|
1154
904
|
});
|
|
905
|
+
const suggestedPatterns2 = this.getToolSuggestedPatterns(input.toolName, validatedArgs);
|
|
906
|
+
return {
|
|
907
|
+
kind: "approval-required",
|
|
908
|
+
call,
|
|
909
|
+
onGrantedRequestDetails: overrideRequest.onGrantedRequestDetails,
|
|
910
|
+
requestDetails: {
|
|
911
|
+
...overrideRequest.requestDetails,
|
|
912
|
+
metadata: {
|
|
913
|
+
...overrideRequest.requestDetails.metadata,
|
|
914
|
+
presentationSnapshot,
|
|
915
|
+
...callDescription !== void 0 ? { description: callDescription } : {},
|
|
916
|
+
...displayPreview2 !== void 0 ? { displayPreview: displayPreview2 } : {},
|
|
917
|
+
...suggestedPatterns2 !== void 0 ? { suggestedPatterns: suggestedPatterns2 } : {}
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
};
|
|
1155
921
|
}
|
|
1156
|
-
const
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
922
|
+
const quickResult = await this.classifyQuickApprovalRequirement(
|
|
923
|
+
input.toolName,
|
|
924
|
+
validatedArgs,
|
|
925
|
+
sessionId
|
|
926
|
+
);
|
|
927
|
+
if (quickResult === "ready") {
|
|
928
|
+
return { kind: "ready", call };
|
|
929
|
+
}
|
|
930
|
+
const displayPreview = await this.toolPresentation.preview({
|
|
931
|
+
toolName: input.toolName,
|
|
932
|
+
args: validatedArgs,
|
|
933
|
+
toolCallId: input.toolCallId,
|
|
934
|
+
...sessionId !== void 0 ? { sessionId } : {},
|
|
935
|
+
...input.runContext !== void 0 ? { runContext: input.runContext } : {}
|
|
936
|
+
});
|
|
937
|
+
const suggestedPatterns = this.getToolSuggestedPatterns(input.toolName, validatedArgs);
|
|
938
|
+
const hostRuntime = input.runContext?.hostRuntime;
|
|
939
|
+
const requestDetails = {
|
|
940
|
+
type: ApprovalType.TOOL_APPROVAL,
|
|
941
|
+
...sessionId !== void 0 ? { sessionId } : {},
|
|
942
|
+
...hostRuntime !== void 0 ? { hostRuntime } : {},
|
|
943
|
+
metadata: {
|
|
944
|
+
toolName: input.toolName,
|
|
945
|
+
presentationSnapshot,
|
|
946
|
+
toolCallId: input.toolCallId,
|
|
947
|
+
args: validatedArgs,
|
|
948
|
+
...callDescription !== void 0 ? { description: callDescription } : {},
|
|
949
|
+
...displayPreview !== void 0 ? { displayPreview } : {},
|
|
950
|
+
...suggestedPatterns !== void 0 ? { suggestedPatterns } : {}
|
|
951
|
+
}
|
|
952
|
+
};
|
|
953
|
+
return {
|
|
954
|
+
kind: "approval-required",
|
|
955
|
+
call,
|
|
956
|
+
onGrantedRequestDetails: requestDetails,
|
|
957
|
+
requestDetails
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
async recordApprovalRequest(prepared, identity) {
|
|
961
|
+
this.assertOnGrantedRequestMatchesPreparedCall(prepared);
|
|
962
|
+
const request = await this.approvalManager.recordApprovalRequest(prepared.requestDetails, {
|
|
963
|
+
...identity,
|
|
964
|
+
toolCallId: prepared.call.toolCallId
|
|
965
|
+
});
|
|
966
|
+
this.assertRecordedApprovalMatchesPreparedCall(prepared, request);
|
|
967
|
+
return { prepared, request };
|
|
968
|
+
}
|
|
969
|
+
async applyApprovalDecision(recorded, decision, runContext) {
|
|
970
|
+
if (decision.approvalId !== recorded.request.approvalId) {
|
|
971
|
+
throw ToolError.executionFailed(
|
|
972
|
+
recorded.prepared.call.toolName,
|
|
973
|
+
"Approval decision does not match the recorded approval request"
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
this.assertOnGrantedRequestMatchesPreparedCall(recorded.prepared);
|
|
977
|
+
this.assertRecordedApprovalMatchesPreparedCall(recorded.prepared, recorded.request);
|
|
978
|
+
const record = await this.approvalManager.recordApprovalResponseRecord(
|
|
979
|
+
decision,
|
|
980
|
+
recorded.request
|
|
981
|
+
);
|
|
982
|
+
if (record.response.status !== ApprovalStatus.APPROVED) {
|
|
983
|
+
return {
|
|
984
|
+
kind: "terminal",
|
|
985
|
+
modelVisibleResult: this.createApprovalTerminalResult(
|
|
986
|
+
recorded.prepared.call,
|
|
987
|
+
record.response
|
|
988
|
+
),
|
|
989
|
+
response: record.response
|
|
1162
990
|
};
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
...sessionId !== void 0 && { sessionId }
|
|
991
|
+
}
|
|
992
|
+
await this.applyApprovalGrantedEffects(recorded.prepared, record.response, runContext);
|
|
993
|
+
return {
|
|
994
|
+
kind: "ready",
|
|
995
|
+
call: {
|
|
996
|
+
...recorded.prepared.call,
|
|
997
|
+
approval: {
|
|
998
|
+
requireApproval: true,
|
|
999
|
+
approvalStatus: "approved"
|
|
1173
1000
|
}
|
|
1001
|
+
},
|
|
1002
|
+
response: record.response
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
async requestApprovalDecision(recorded) {
|
|
1006
|
+
return this.approvalManager.requestApprovalDecision(recorded.request);
|
|
1007
|
+
}
|
|
1008
|
+
assertRecordedApprovalMatchesPreparedCall(prepared, request) {
|
|
1009
|
+
const expected = {
|
|
1010
|
+
type: prepared.requestDetails.type,
|
|
1011
|
+
sessionId: prepared.requestDetails.sessionId,
|
|
1012
|
+
hostRuntime: prepared.requestDetails.hostRuntime,
|
|
1013
|
+
metadata: prepared.requestDetails.metadata
|
|
1014
|
+
};
|
|
1015
|
+
const actual = {
|
|
1016
|
+
type: request.type,
|
|
1017
|
+
sessionId: request.sessionId,
|
|
1018
|
+
hostRuntime: request.hostRuntime,
|
|
1019
|
+
metadata: request.metadata
|
|
1020
|
+
};
|
|
1021
|
+
if (!isDeepStrictEqual(actual, expected)) {
|
|
1022
|
+
throw ToolError.executionFailed(
|
|
1023
|
+
prepared.call.toolName,
|
|
1024
|
+
"Recorded approval request does not match the prepared tool call"
|
|
1174
1025
|
);
|
|
1175
|
-
toolArgs = modifiedPayload.args;
|
|
1176
|
-
try {
|
|
1177
|
-
toolArgs = this.validateLocalToolArgs(toolName, toolArgs);
|
|
1178
|
-
} catch (error) {
|
|
1179
|
-
this.logger.error(
|
|
1180
|
-
`Post-hook validation failed for tool '${toolName}': a beforeToolCall hook may have set invalid args`
|
|
1181
|
-
);
|
|
1182
|
-
throw error;
|
|
1183
|
-
}
|
|
1184
1026
|
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
};
|
|
1027
|
+
}
|
|
1028
|
+
assertOnGrantedRequestMatchesPreparedCall(prepared) {
|
|
1029
|
+
const approvalDetails = prepared.requestDetails;
|
|
1030
|
+
const grantedDetails = prepared.onGrantedRequestDetails;
|
|
1031
|
+
const directoryAccess = approvalDetails.type === ApprovalType.TOOL_APPROVAL && "directoryAccess" in approvalDetails.metadata ? DirectoryAccessMetadataSchema.parse(approvalDetails.metadata.directoryAccess) : void 0;
|
|
1032
|
+
if (directoryAccess !== void 0) {
|
|
1033
|
+
const expected = {
|
|
1034
|
+
type: ApprovalType.DIRECTORY_ACCESS,
|
|
1035
|
+
sessionId: approvalDetails.sessionId,
|
|
1036
|
+
hostRuntime: approvalDetails.hostRuntime,
|
|
1037
|
+
metadata: directoryAccess
|
|
1197
1038
|
};
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
toolArgs,
|
|
1209
|
-
sessionId,
|
|
1210
|
-
runContext
|
|
1039
|
+
const actual = {
|
|
1040
|
+
type: grantedDetails.type,
|
|
1041
|
+
sessionId: grantedDetails.sessionId,
|
|
1042
|
+
hostRuntime: grantedDetails.hostRuntime,
|
|
1043
|
+
metadata: grantedDetails.metadata
|
|
1044
|
+
};
|
|
1045
|
+
if (!isDeepStrictEqual(actual, expected)) {
|
|
1046
|
+
throw ToolError.executionFailed(
|
|
1047
|
+
prepared.call.toolName,
|
|
1048
|
+
"Approval granted-effects request does not match the prepared tool call"
|
|
1211
1049
|
);
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1050
|
+
}
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
if (!isDeepStrictEqual(grantedDetails, approvalDetails)) {
|
|
1054
|
+
throw ToolError.executionFailed(
|
|
1055
|
+
prepared.call.toolName,
|
|
1056
|
+
"Approval granted-effects request does not match the prepared tool call"
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
async applyApprovalGrantedEffects(prepared, response, runContext) {
|
|
1061
|
+
const requestDetails = prepared.onGrantedRequestDetails;
|
|
1062
|
+
const approvalRequestDetails = prepared.requestDetails;
|
|
1063
|
+
const sessionId = approvalRequestDetails.sessionId;
|
|
1064
|
+
const onGranted = this.getToolApprovalOnGrantedFn(prepared.call.toolName);
|
|
1065
|
+
if (onGranted) {
|
|
1066
|
+
const context = this.buildToolExecutionContext({
|
|
1067
|
+
sessionId,
|
|
1068
|
+
toolCallId: prepared.call.toolCallId,
|
|
1069
|
+
runContext
|
|
1070
|
+
});
|
|
1071
|
+
await Promise.resolve(onGranted(response, context, requestDetails));
|
|
1072
|
+
}
|
|
1073
|
+
if (approvalRequestDetails.type === ApprovalType.TOOL_APPROVAL && response.data) {
|
|
1074
|
+
await this.handleRememberChoice(
|
|
1075
|
+
prepared.call.toolName,
|
|
1076
|
+
{
|
|
1077
|
+
data: ToolApprovalResponseDataSchema.parse(response.data),
|
|
1078
|
+
...response.sessionId !== void 0 ? { sessionId: response.sessionId } : {}
|
|
1079
|
+
},
|
|
1080
|
+
sessionId
|
|
1081
|
+
);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
createApprovalTerminalResult(call, response) {
|
|
1085
|
+
return {
|
|
1086
|
+
result: {
|
|
1087
|
+
error: this.formatApprovalTerminalMessage(call.toolName, response)
|
|
1088
|
+
},
|
|
1089
|
+
presentationSnapshot: call.presentationSnapshot,
|
|
1090
|
+
...call.meta !== void 0 ? { meta: call.meta } : {},
|
|
1091
|
+
requireApproval: true,
|
|
1092
|
+
approvalStatus: "rejected"
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
formatApprovalTerminalMessage(toolName, response) {
|
|
1096
|
+
if (response.status === ApprovalStatus.CANCELLED && response.reason === DenialReason.TIMEOUT) {
|
|
1097
|
+
return `Tool '${toolName}' was not executed because approval timed out${response.timeoutMs !== void 0 ? ` after ${response.timeoutMs}ms` : ""}.`;
|
|
1098
|
+
}
|
|
1099
|
+
const outcome = response.status === ApprovalStatus.DENIED ? "approval was denied" : "approval was cancelled";
|
|
1100
|
+
return `Tool '${toolName}' was not executed because ${outcome}${response.message ? `: ${response.message}` : ""}.`;
|
|
1101
|
+
}
|
|
1102
|
+
async resolveExecutableToolSource(toolName) {
|
|
1103
|
+
if (this.agentTools.has(toolName)) {
|
|
1104
|
+
return "local";
|
|
1105
|
+
}
|
|
1106
|
+
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX) && toolName.length > _ToolManager.MCP_TOOL_PREFIX.length) {
|
|
1107
|
+
return "mcp";
|
|
1108
|
+
}
|
|
1109
|
+
return "unknown";
|
|
1110
|
+
}
|
|
1111
|
+
createPreparedToolError(kind, toolName, error) {
|
|
1112
|
+
return {
|
|
1113
|
+
kind: "terminal",
|
|
1114
|
+
reason: kind,
|
|
1115
|
+
modelVisibleResult: {
|
|
1116
|
+
result: { error },
|
|
1117
|
+
presentationSnapshot: this.toolPresentation.buildGenericSnapshot(toolName)
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
createPreparedToolTerminal(reason, toolName, call) {
|
|
1122
|
+
return {
|
|
1123
|
+
kind: "terminal",
|
|
1124
|
+
reason,
|
|
1125
|
+
call,
|
|
1126
|
+
modelVisibleResult: {
|
|
1127
|
+
result: {
|
|
1128
|
+
error: `Tool '${toolName}' was not executed because policy denied it.`
|
|
1129
|
+
},
|
|
1130
|
+
presentationSnapshot: call.presentationSnapshot,
|
|
1131
|
+
...call.meta !== void 0 ? { meta: call.meta } : {}
|
|
1132
|
+
}
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
async getToolApprovalOverrideRequest(toolName, args, toolCallId, sessionId, runContext) {
|
|
1136
|
+
if (toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
1137
|
+
return null;
|
|
1138
|
+
}
|
|
1139
|
+
const getApprovalOverride = this.getToolApprovalOverrideFn(toolName);
|
|
1140
|
+
if (!getApprovalOverride) {
|
|
1141
|
+
return null;
|
|
1142
|
+
}
|
|
1143
|
+
const context = this.buildToolExecutionContext({ sessionId, toolCallId, runContext });
|
|
1144
|
+
const approvalRequest = await getApprovalOverride(args, context);
|
|
1145
|
+
if (!approvalRequest) {
|
|
1146
|
+
return null;
|
|
1147
|
+
}
|
|
1148
|
+
const requestDetails = {
|
|
1149
|
+
...approvalRequest,
|
|
1150
|
+
...sessionId && !approvalRequest.sessionId ? { sessionId } : {},
|
|
1151
|
+
...runContext?.hostRuntime !== void 0 && approvalRequest.hostRuntime === void 0 ? { hostRuntime: runContext.hostRuntime } : {}
|
|
1152
|
+
};
|
|
1153
|
+
if (requestDetails.type !== ApprovalType.DIRECTORY_ACCESS) {
|
|
1154
|
+
return { requestDetails, onGrantedRequestDetails: requestDetails };
|
|
1155
|
+
}
|
|
1156
|
+
const parseResult = DirectoryAccessMetadataSchema.safeParse(requestDetails.metadata);
|
|
1157
|
+
if (!parseResult.success) {
|
|
1158
|
+
throw ToolError.configInvalid(
|
|
1159
|
+
`Tool '${toolName}' returned invalid directory access metadata`
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
const directoryAccess = parseResult.data;
|
|
1163
|
+
return {
|
|
1164
|
+
directoryAccess,
|
|
1165
|
+
onGrantedRequestDetails: requestDetails,
|
|
1166
|
+
requestDetails: {
|
|
1167
|
+
type: ApprovalType.TOOL_APPROVAL,
|
|
1168
|
+
...requestDetails.sessionId !== void 0 ? { sessionId: requestDetails.sessionId } : {},
|
|
1169
|
+
...requestDetails.hostRuntime !== void 0 ? { hostRuntime: requestDetails.hostRuntime } : {},
|
|
1170
|
+
metadata: {
|
|
1171
|
+
toolName,
|
|
1172
|
+
toolCallId,
|
|
1173
|
+
args,
|
|
1174
|
+
directoryAccess
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
async classifyQuickApprovalRequirement(toolName, args, sessionId, directoryAccess) {
|
|
1180
|
+
if (directoryAccess) {
|
|
1181
|
+
return this.approvalMode === "auto-approve" ? "ready" : "approval-required";
|
|
1182
|
+
}
|
|
1183
|
+
if (sessionId && this.isToolAutoApprovedForSession(sessionId, toolName)) {
|
|
1184
|
+
return "ready";
|
|
1185
|
+
}
|
|
1186
|
+
if (this.isInAlwaysAllowList(toolName)) {
|
|
1187
|
+
return "ready";
|
|
1188
|
+
}
|
|
1189
|
+
if (await this.allowedToolsProvider.isToolAllowed(toolName, sessionId)) {
|
|
1190
|
+
return "ready";
|
|
1191
|
+
}
|
|
1192
|
+
const patternKey = this.getToolPatternKey(toolName, args);
|
|
1193
|
+
if (patternKey && this.approvalManager.matchesPattern(toolName, patternKey, sessionId)) {
|
|
1194
|
+
return "ready";
|
|
1195
|
+
}
|
|
1196
|
+
if (this.approvalMode === "auto-approve") {
|
|
1197
|
+
return "ready";
|
|
1198
|
+
}
|
|
1199
|
+
return "approval-required";
|
|
1200
|
+
}
|
|
1201
|
+
async executeTool(toolName, args, toolCallId, invocation) {
|
|
1202
|
+
const { sessionId, runContext, hostRuntime } = this.resolveToolExecutionInvocation(invocation);
|
|
1203
|
+
this.logger.debug(`\u{1F527} Tool execution requested: '${toolName}' (toolCallId: ${toolCallId})`);
|
|
1204
|
+
this.logger.debug(`Tool args: ${JSON.stringify(args, null, 2)}`);
|
|
1205
|
+
if (toolName === _ToolManager.MCP_TOOL_PREFIX) {
|
|
1206
|
+
throw ToolError.invalidName(toolName, "tool name cannot be empty after prefix");
|
|
1207
|
+
}
|
|
1208
|
+
const prepared = await this.prepareToolCall({
|
|
1209
|
+
toolName,
|
|
1210
|
+
input: args,
|
|
1211
|
+
toolCallId,
|
|
1212
|
+
...sessionId !== void 0 ? { sessionId } : {},
|
|
1213
|
+
...runContext !== void 0 ? { runContext } : {}
|
|
1214
|
+
});
|
|
1215
|
+
if (prepared.kind === "terminal") {
|
|
1216
|
+
this.throwPreparedTerminalResult(toolName, prepared, sessionId);
|
|
1217
|
+
}
|
|
1218
|
+
this.emitPreparedToolCallEvent(prepared.call, sessionId, runContext, hostRuntime);
|
|
1219
|
+
const replayed = await this.replayExistingDirectToolExecution(prepared.call, invocation);
|
|
1220
|
+
if (replayed !== void 0) {
|
|
1221
|
+
return replayed;
|
|
1222
|
+
}
|
|
1223
|
+
if (prepared.kind === "ready") {
|
|
1224
|
+
return this.executePreparedToolCall(prepared.call, invocation, { throwOnError: true });
|
|
1225
|
+
}
|
|
1226
|
+
let applied;
|
|
1227
|
+
try {
|
|
1228
|
+
const recorded = await this.recordApprovalRequest(
|
|
1229
|
+
prepared,
|
|
1230
|
+
this.resolveDirectApprovalIdentity(invocation, toolCallId)
|
|
1231
|
+
);
|
|
1232
|
+
const response = await this.requestApprovalDecision(recorded);
|
|
1233
|
+
applied = await this.applyApprovalDecision(
|
|
1234
|
+
recorded,
|
|
1235
|
+
{
|
|
1236
|
+
approvalId: response.approvalId,
|
|
1237
|
+
status: response.status,
|
|
1238
|
+
...response.reason !== void 0 ? { reason: response.reason } : {},
|
|
1239
|
+
...response.message !== void 0 ? { message: response.message } : {},
|
|
1240
|
+
...response.data !== void 0 ? { data: response.data } : {}
|
|
1241
|
+
},
|
|
1242
|
+
runContext
|
|
1243
|
+
);
|
|
1244
|
+
} catch (error) {
|
|
1245
|
+
await this.recordDirectToolExecutionFailure(prepared.call, invocation, error);
|
|
1246
|
+
throw error;
|
|
1247
|
+
}
|
|
1248
|
+
if (applied.kind === "terminal") {
|
|
1249
|
+
try {
|
|
1250
|
+
this.handleApprovalDenied(toolName, applied.response, sessionId);
|
|
1251
|
+
} catch (error) {
|
|
1252
|
+
await this.recordDirectToolExecutionFailure(prepared.call, invocation, error);
|
|
1253
|
+
throw error;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
return this.executePreparedToolCall(applied.call, invocation, { throwOnError: true });
|
|
1257
|
+
}
|
|
1258
|
+
emitPreparedToolCallEvent(call, sessionId, runContext, hostRuntime) {
|
|
1259
|
+
if (!sessionId) {
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
this.agentEventBus.emit("llm:tool-call", {
|
|
1263
|
+
toolName: call.toolName,
|
|
1264
|
+
presentationSnapshot: this.toolPresentation.snapshotForToolCallEvent({
|
|
1265
|
+
toolName: call.toolName,
|
|
1266
|
+
args: call.input,
|
|
1267
|
+
toolCallId: call.toolCallId,
|
|
1268
|
+
sessionId,
|
|
1269
|
+
...runContext !== void 0 ? { runContext } : {}
|
|
1270
|
+
}),
|
|
1271
|
+
args: call.input,
|
|
1272
|
+
...call.meta !== void 0 ? { meta: call.meta } : {},
|
|
1273
|
+
...call.callDescription !== void 0 ? { callDescription: call.callDescription } : {},
|
|
1274
|
+
callId: call.toolCallId,
|
|
1275
|
+
sessionId,
|
|
1276
|
+
...hostRuntime !== void 0 && { hostRuntime }
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
async replayExistingDirectToolExecution(call, invocation) {
|
|
1280
|
+
const { sessionId } = this.resolveToolExecutionInvocation(invocation);
|
|
1281
|
+
if (isBackgroundTasksEnabled() && call.meta?.runInBackground === true && sessionId !== void 0) {
|
|
1282
|
+
return void 0;
|
|
1283
|
+
}
|
|
1284
|
+
const identity = this.resolveToolExecutionIdentity(invocation ?? {}, call.toolCallId);
|
|
1285
|
+
if (identity === void 0) {
|
|
1286
|
+
return void 0;
|
|
1287
|
+
}
|
|
1288
|
+
const executionId = createToolExecutionId(identity);
|
|
1289
|
+
const record = await this.toolExecutionStore.get({ executionId });
|
|
1290
|
+
if (record === void 0) {
|
|
1291
|
+
return void 0;
|
|
1292
|
+
}
|
|
1293
|
+
this.assertToolExecutionRecordMatches({
|
|
1294
|
+
record,
|
|
1295
|
+
identity,
|
|
1296
|
+
toolName: call.toolName,
|
|
1297
|
+
toolInput: call.input
|
|
1298
|
+
});
|
|
1299
|
+
if (record.status === "completed") {
|
|
1300
|
+
this.logger.info("Replaying completed direct tool execution result", {
|
|
1301
|
+
executionId,
|
|
1302
|
+
toolName: call.toolName
|
|
1303
|
+
});
|
|
1304
|
+
return completedToolExecutionToResult(record);
|
|
1305
|
+
}
|
|
1306
|
+
if (record.status === "failed") {
|
|
1307
|
+
throw ToolError.executionFailed(
|
|
1308
|
+
call.toolName,
|
|
1309
|
+
`Tool execution already failed: ${executionId}`
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
throw ToolError.executionFailed(
|
|
1313
|
+
call.toolName,
|
|
1314
|
+
`Tool execution already ${record.status}: ${executionId}`
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
async recordDirectToolExecutionFailure(call, invocation, error) {
|
|
1318
|
+
const identity = this.resolveToolExecutionIdentity(invocation ?? {}, call.toolCallId);
|
|
1319
|
+
if (identity === void 0) {
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
const executionId = createToolExecutionId(identity);
|
|
1323
|
+
const started = await this.toolExecutionStore.start({
|
|
1324
|
+
record: {
|
|
1325
|
+
executionId,
|
|
1326
|
+
identity,
|
|
1327
|
+
input: call.input,
|
|
1328
|
+
toolName: call.toolName,
|
|
1329
|
+
status: "running",
|
|
1330
|
+
startedAt: /* @__PURE__ */ new Date(),
|
|
1331
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
if (started.status === "existing") {
|
|
1335
|
+
this.assertToolExecutionRecordMatches({
|
|
1336
|
+
record: started.record,
|
|
1337
|
+
identity,
|
|
1338
|
+
toolName: call.toolName,
|
|
1339
|
+
toolInput: call.input
|
|
1340
|
+
});
|
|
1341
|
+
if (started.record.status !== "running") {
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
await this.toolExecutionStore.fail({
|
|
1346
|
+
executionId,
|
|
1347
|
+
completedAt: /* @__PURE__ */ new Date(),
|
|
1348
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
1351
|
+
resolveDirectApprovalIdentity(invocation, toolCallId) {
|
|
1352
|
+
const executionIdentity = this.resolveToolExecutionIdentity(invocation ?? {}, toolCallId);
|
|
1353
|
+
if (executionIdentity !== void 0) {
|
|
1354
|
+
return {
|
|
1355
|
+
runId: executionIdentity.runId,
|
|
1356
|
+
turnId: executionIdentity.turnId,
|
|
1357
|
+
modelStepId: executionIdentity.modelStepId
|
|
1358
|
+
};
|
|
1359
|
+
}
|
|
1360
|
+
const ids = invocation?.runContext?.hostRuntime?.ids;
|
|
1361
|
+
const runId = ids?.runId;
|
|
1362
|
+
const turnId = ids?.turnId;
|
|
1363
|
+
const modelStepId = ids?.modelStepId;
|
|
1364
|
+
if (runId !== void 0 && turnId !== void 0 && modelStepId !== void 0) {
|
|
1365
|
+
return { runId, turnId, modelStepId };
|
|
1366
|
+
}
|
|
1367
|
+
return {
|
|
1368
|
+
runId: invocation?.sessionId ?? invocation?.runContext?.sessionId ?? "direct",
|
|
1369
|
+
turnId: "direct",
|
|
1370
|
+
modelStepId: "direct"
|
|
1371
|
+
};
|
|
1372
|
+
}
|
|
1373
|
+
throwPreparedTerminalResult(toolName, prepared, sessionId) {
|
|
1374
|
+
if (prepared.reason === "unknown-tool") {
|
|
1375
|
+
throw ToolError.notFound(toolName);
|
|
1376
|
+
}
|
|
1377
|
+
if (prepared.reason === "denied") {
|
|
1378
|
+
throw ToolError.executionDenied(toolName, sessionId);
|
|
1379
|
+
}
|
|
1380
|
+
if (prepared.reason === "invalid-input") {
|
|
1381
|
+
throw ToolError.validationFailed(
|
|
1382
|
+
toolName,
|
|
1383
|
+
this.getPreparedTerminalMessage(prepared.modelVisibleResult)
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
throw ToolError.executionFailed(
|
|
1387
|
+
toolName,
|
|
1388
|
+
this.getPreparedTerminalMessage(prepared.modelVisibleResult),
|
|
1389
|
+
sessionId
|
|
1390
|
+
);
|
|
1391
|
+
}
|
|
1392
|
+
getPreparedTerminalMessage(result) {
|
|
1393
|
+
const output = result.result;
|
|
1394
|
+
if (isRecord(output) && typeof output.error === "string") {
|
|
1395
|
+
return output.error;
|
|
1396
|
+
}
|
|
1397
|
+
return "Tool call could not be prepared for execution";
|
|
1398
|
+
}
|
|
1399
|
+
async executePreparedToolCall(call, invocation, options) {
|
|
1400
|
+
const { sessionId, abortSignal, runContext, hostRuntime } = this.resolveToolExecutionInvocation(invocation);
|
|
1401
|
+
const durableIdentity = this.resolveToolExecutionIdentity(
|
|
1402
|
+
invocation ?? {},
|
|
1403
|
+
call.toolCallId
|
|
1404
|
+
);
|
|
1405
|
+
const backgroundTasksEnabled = isBackgroundTasksEnabled();
|
|
1406
|
+
const willRunInBackground = backgroundTasksEnabled && call.meta?.runInBackground === true && sessionId !== void 0;
|
|
1407
|
+
const executionIdentity = willRunInBackground ? void 0 : durableIdentity;
|
|
1408
|
+
const executionId = executionIdentity === void 0 ? void 0 : createToolExecutionId(executionIdentity);
|
|
1409
|
+
let toolArgs = call.input;
|
|
1410
|
+
this.logger.debug(
|
|
1411
|
+
`\u{1F527} Prepared tool execution requested: '${call.toolName}' (toolCallId: ${call.toolCallId})`
|
|
1412
|
+
);
|
|
1413
|
+
if (executionIdentity !== void 0 && executionId !== void 0) {
|
|
1414
|
+
const started = await this.toolExecutionStore.start({
|
|
1415
|
+
record: {
|
|
1416
|
+
executionId,
|
|
1417
|
+
identity: executionIdentity,
|
|
1418
|
+
input: call.input,
|
|
1419
|
+
toolName: call.toolName,
|
|
1420
|
+
status: "running",
|
|
1421
|
+
startedAt: /* @__PURE__ */ new Date(),
|
|
1422
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1423
|
+
}
|
|
1424
|
+
});
|
|
1425
|
+
if (started.status === "existing") {
|
|
1426
|
+
this.assertToolExecutionRecordMatches({
|
|
1427
|
+
record: started.record,
|
|
1428
|
+
identity: executionIdentity,
|
|
1429
|
+
toolName: call.toolName,
|
|
1430
|
+
toolInput: call.input
|
|
1431
|
+
});
|
|
1432
|
+
if (started.record.status === "completed") {
|
|
1433
|
+
this.logger.info("Replaying completed prepared tool execution result", {
|
|
1434
|
+
executionId,
|
|
1435
|
+
toolName: call.toolName
|
|
1436
|
+
});
|
|
1437
|
+
return completedToolExecutionToResult(started.record);
|
|
1438
|
+
}
|
|
1439
|
+
if (started.record.status === "failed") {
|
|
1440
|
+
this.logger.info("Replaying failed prepared tool execution result", {
|
|
1441
|
+
executionId,
|
|
1442
|
+
toolName: call.toolName
|
|
1443
|
+
});
|
|
1444
|
+
if (options?.throwOnError === true) {
|
|
1445
|
+
throw ToolError.executionFailed(
|
|
1446
|
+
call.toolName,
|
|
1447
|
+
`Tool execution already failed: ${executionId}`
|
|
1448
|
+
);
|
|
1449
|
+
}
|
|
1450
|
+
return this.createFailedPreparedToolResult(call, started.record.error);
|
|
1451
|
+
}
|
|
1452
|
+
throw ToolError.executionFailed(
|
|
1453
|
+
call.toolName,
|
|
1454
|
+
`Tool execution already ${started.record.status}: ${executionId}`
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
const startTime = Date.now();
|
|
1459
|
+
try {
|
|
1460
|
+
this.logger.info(
|
|
1461
|
+
`\u{1F527} Prepared tool execution started for ${call.toolName}, sessionId: ${sessionId ?? "global"}`
|
|
1462
|
+
);
|
|
1463
|
+
if (sessionId) {
|
|
1464
|
+
this.agentEventBus.emit("tool:running", {
|
|
1465
|
+
toolName: call.toolName,
|
|
1466
|
+
toolCallId: call.toolCallId,
|
|
1467
|
+
sessionId,
|
|
1468
|
+
...hostRuntime !== void 0 && { hostRuntime }
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
if (this.hookManager && this.sessionManager && this.stateManager) {
|
|
1472
|
+
const beforePayload = {
|
|
1473
|
+
toolName: call.toolName,
|
|
1474
|
+
args: toolArgs,
|
|
1475
|
+
...sessionId !== void 0 && { sessionId }
|
|
1476
|
+
};
|
|
1477
|
+
const modifiedPayload = await this.hookManager.executeHooks(
|
|
1478
|
+
"beforeToolCall",
|
|
1479
|
+
beforePayload,
|
|
1480
|
+
{
|
|
1481
|
+
sessionManager: this.sessionManager,
|
|
1482
|
+
mcpManager: this.mcpManager,
|
|
1483
|
+
toolManager: this,
|
|
1484
|
+
stateManager: this.stateManager,
|
|
1485
|
+
...runContext !== void 0 && { runContext },
|
|
1486
|
+
...sessionId !== void 0 && { sessionId }
|
|
1487
|
+
}
|
|
1488
|
+
);
|
|
1489
|
+
toolArgs = modifiedPayload.args;
|
|
1490
|
+
try {
|
|
1491
|
+
toolArgs = this.validateLocalToolArgs(call.toolName, toolArgs);
|
|
1492
|
+
} catch (error) {
|
|
1493
|
+
this.logger.error(
|
|
1494
|
+
`Post-hook validation failed for tool '${call.toolName}': a beforeToolCall hook may have set invalid args`
|
|
1495
|
+
);
|
|
1496
|
+
throw error;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
let result;
|
|
1500
|
+
const registerBackgroundTask = (promise, description) => {
|
|
1501
|
+
return {
|
|
1502
|
+
result: {
|
|
1503
|
+
taskId: call.toolCallId,
|
|
1504
|
+
status: "running",
|
|
1505
|
+
description
|
|
1506
|
+
},
|
|
1507
|
+
promise
|
|
1508
|
+
};
|
|
1509
|
+
};
|
|
1510
|
+
if (call.source === "mcp") {
|
|
1511
|
+
const actualToolName = call.toolName.substring(_ToolManager.MCP_TOOL_PREFIX.length);
|
|
1512
|
+
if (actualToolName.length === 0) {
|
|
1513
|
+
throw ToolError.invalidName(
|
|
1514
|
+
call.toolName,
|
|
1515
|
+
"tool name cannot be empty after prefix"
|
|
1516
|
+
);
|
|
1517
|
+
}
|
|
1518
|
+
const executeMcpTool = () => runContext === void 0 ? this.mcpManager.executeTool(actualToolName, toolArgs, sessionId) : this.mcpManager.executeTool(
|
|
1519
|
+
actualToolName,
|
|
1520
|
+
toolArgs,
|
|
1521
|
+
sessionId,
|
|
1522
|
+
runContext
|
|
1523
|
+
);
|
|
1524
|
+
if (call.meta?.runInBackground === true && !backgroundTasksEnabled) {
|
|
1525
|
+
this.logger.debug(
|
|
1526
|
+
"Background tool execution disabled; running synchronously instead.",
|
|
1527
|
+
{ toolName: call.toolName }
|
|
1528
|
+
);
|
|
1529
|
+
}
|
|
1530
|
+
if (willRunInBackground) {
|
|
1531
|
+
const backgroundSessionId = sessionId;
|
|
1532
|
+
const { result: backgroundResult, promise } = registerBackgroundTask(
|
|
1533
|
+
executeMcpTool(),
|
|
1534
|
+
`MCP tool ${actualToolName}`
|
|
1535
|
+
);
|
|
1536
|
+
this.agentEventBus.emit("tool:background", {
|
|
1537
|
+
toolName: call.toolName,
|
|
1538
|
+
toolCallId: backgroundResult.taskId,
|
|
1539
|
+
sessionId: backgroundSessionId,
|
|
1540
|
+
description: backgroundResult.description,
|
|
1541
|
+
promise,
|
|
1542
|
+
...hostRuntime !== void 0 && { hostRuntime },
|
|
1543
|
+
...call.meta?.timeoutMs !== void 0 && {
|
|
1544
|
+
timeoutMs: call.meta.timeoutMs
|
|
1545
|
+
},
|
|
1546
|
+
...call.meta?.notifyOnComplete !== void 0 && {
|
|
1547
|
+
notifyOnComplete: call.meta.notifyOnComplete
|
|
1548
|
+
}
|
|
1549
|
+
});
|
|
1550
|
+
result = backgroundResult;
|
|
1551
|
+
} else {
|
|
1552
|
+
result = await executeMcpTool();
|
|
1553
|
+
}
|
|
1554
|
+
} else {
|
|
1555
|
+
if (call.meta?.runInBackground === true && !backgroundTasksEnabled) {
|
|
1556
|
+
this.logger.debug(
|
|
1557
|
+
"Background tool execution disabled; running synchronously instead.",
|
|
1558
|
+
{ toolName: call.toolName }
|
|
1559
|
+
);
|
|
1560
|
+
}
|
|
1561
|
+
if (willRunInBackground) {
|
|
1562
|
+
const backgroundSessionId = sessionId;
|
|
1563
|
+
const { result: backgroundResult, promise } = registerBackgroundTask(
|
|
1564
|
+
this.executeLocalTool(call.toolName, toolArgs, {
|
|
1252
1565
|
sessionId: backgroundSessionId,
|
|
1253
1566
|
abortSignal,
|
|
1254
|
-
toolCallId,
|
|
1567
|
+
toolCallId: call.toolCallId,
|
|
1255
1568
|
runContext
|
|
1256
1569
|
}),
|
|
1257
|
-
`Tool ${toolName}`
|
|
1570
|
+
`Tool ${call.toolName}`
|
|
1258
1571
|
);
|
|
1259
1572
|
this.agentEventBus.emit("tool:background", {
|
|
1260
|
-
toolName,
|
|
1573
|
+
toolName: call.toolName,
|
|
1261
1574
|
toolCallId: backgroundResult.taskId,
|
|
1262
1575
|
sessionId: backgroundSessionId,
|
|
1263
1576
|
description: backgroundResult.description,
|
|
1264
1577
|
promise,
|
|
1265
1578
|
...hostRuntime !== void 0 && { hostRuntime },
|
|
1266
|
-
...meta
|
|
1267
|
-
|
|
1268
|
-
|
|
1579
|
+
...call.meta?.timeoutMs !== void 0 && {
|
|
1580
|
+
timeoutMs: call.meta.timeoutMs
|
|
1581
|
+
},
|
|
1582
|
+
...call.meta?.notifyOnComplete !== void 0 && {
|
|
1583
|
+
notifyOnComplete: call.meta.notifyOnComplete
|
|
1269
1584
|
}
|
|
1270
1585
|
});
|
|
1271
1586
|
result = backgroundResult;
|
|
1272
1587
|
} else {
|
|
1273
|
-
result = await this.executeLocalTool(toolName, toolArgs, {
|
|
1588
|
+
result = await this.executeLocalTool(call.toolName, toolArgs, {
|
|
1274
1589
|
sessionId,
|
|
1275
1590
|
abortSignal,
|
|
1276
|
-
toolCallId,
|
|
1591
|
+
toolCallId: call.toolCallId,
|
|
1277
1592
|
runContext
|
|
1278
1593
|
});
|
|
1279
1594
|
}
|
|
1280
1595
|
}
|
|
1281
1596
|
const duration = Date.now() - startTime;
|
|
1282
|
-
this.logger.debug(
|
|
1283
|
-
|
|
1284
|
-
`\u2705 Tool execution completed successfully for ${toolName} in ${duration}ms, sessionId: ${sessionId ?? "global"}`
|
|
1597
|
+
this.logger.debug(
|
|
1598
|
+
`\u{1F3AF} Prepared tool execution completed in ${duration}ms: '${call.toolName}'`
|
|
1285
1599
|
);
|
|
1286
1600
|
if (this.hookManager && this.sessionManager && this.stateManager) {
|
|
1287
1601
|
const afterPayload = {
|
|
1288
|
-
toolName,
|
|
1602
|
+
toolName: call.toolName,
|
|
1289
1603
|
result,
|
|
1290
1604
|
success: true,
|
|
1291
1605
|
...sessionId !== void 0 && { sessionId }
|
|
@@ -1304,29 +1618,45 @@ let _ToolManager = class _ToolManager {
|
|
|
1304
1618
|
);
|
|
1305
1619
|
result = modifiedPayload.result;
|
|
1306
1620
|
}
|
|
1307
|
-
const presentationSnapshot = await this.
|
|
1308
|
-
toolName,
|
|
1309
|
-
|
|
1621
|
+
const presentationSnapshot = await this.toolPresentation.augmentWithResult({
|
|
1622
|
+
toolName: call.toolName,
|
|
1623
|
+
snapshot: call.presentationSnapshot,
|
|
1310
1624
|
result,
|
|
1311
|
-
toolArgs,
|
|
1312
|
-
toolCallId,
|
|
1313
|
-
sessionId,
|
|
1314
|
-
runContext
|
|
1315
|
-
);
|
|
1316
|
-
|
|
1625
|
+
args: toolArgs,
|
|
1626
|
+
toolCallId: call.toolCallId,
|
|
1627
|
+
...sessionId !== void 0 ? { sessionId } : {},
|
|
1628
|
+
...runContext !== void 0 ? { runContext } : {}
|
|
1629
|
+
});
|
|
1630
|
+
const executionResult = {
|
|
1317
1631
|
result,
|
|
1318
1632
|
...presentationSnapshot !== void 0 && { presentationSnapshot },
|
|
1319
|
-
...
|
|
1320
|
-
...
|
|
1633
|
+
...call.meta !== void 0 ? { meta: call.meta } : {},
|
|
1634
|
+
...call.approval !== void 0 ? call.approval : {}
|
|
1321
1635
|
};
|
|
1636
|
+
if (executionId !== void 0) {
|
|
1637
|
+
await this.toolExecutionStore.complete({
|
|
1638
|
+
executionId,
|
|
1639
|
+
completedAt: /* @__PURE__ */ new Date(),
|
|
1640
|
+
result: executionResult
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
return executionResult;
|
|
1322
1644
|
} catch (error) {
|
|
1323
1645
|
const duration = Date.now() - startTime;
|
|
1324
1646
|
this.logger.error(
|
|
1325
|
-
`\u274C
|
|
1647
|
+
`\u274C Prepared tool execution failed for ${call.toolName} after ${duration}ms, sessionId: ${sessionId ?? "global"}: ${error instanceof Error ? error.message : String(error)}`
|
|
1326
1648
|
);
|
|
1649
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1650
|
+
if (executionId !== void 0) {
|
|
1651
|
+
await this.toolExecutionStore.fail({
|
|
1652
|
+
executionId,
|
|
1653
|
+
completedAt: /* @__PURE__ */ new Date(),
|
|
1654
|
+
error: message
|
|
1655
|
+
});
|
|
1656
|
+
}
|
|
1327
1657
|
if (this.hookManager && this.sessionManager && this.stateManager) {
|
|
1328
1658
|
const afterPayload = {
|
|
1329
|
-
toolName,
|
|
1659
|
+
toolName: call.toolName,
|
|
1330
1660
|
result: error instanceof Error ? error.message : String(error),
|
|
1331
1661
|
success: false,
|
|
1332
1662
|
...sessionId !== void 0 && { sessionId }
|
|
@@ -1340,9 +1670,20 @@ let _ToolManager = class _ToolManager {
|
|
|
1340
1670
|
...sessionId !== void 0 && { sessionId }
|
|
1341
1671
|
});
|
|
1342
1672
|
}
|
|
1343
|
-
|
|
1673
|
+
if (options?.throwOnError === true) {
|
|
1674
|
+
throw error;
|
|
1675
|
+
}
|
|
1676
|
+
return this.createFailedPreparedToolResult(call, message);
|
|
1344
1677
|
}
|
|
1345
1678
|
}
|
|
1679
|
+
createFailedPreparedToolResult(call, error) {
|
|
1680
|
+
return {
|
|
1681
|
+
result: { error },
|
|
1682
|
+
presentationSnapshot: call.presentationSnapshot,
|
|
1683
|
+
...call.meta !== void 0 ? { meta: call.meta } : {},
|
|
1684
|
+
...call.approval !== void 0 ? call.approval : {}
|
|
1685
|
+
};
|
|
1686
|
+
}
|
|
1346
1687
|
/**
|
|
1347
1688
|
* Check if a tool exists.
|
|
1348
1689
|
*/
|
|
@@ -1388,45 +1729,6 @@ let _ToolManager = class _ToolManager {
|
|
|
1388
1729
|
}
|
|
1389
1730
|
return "unknown";
|
|
1390
1731
|
}
|
|
1391
|
-
/**
|
|
1392
|
-
* Check if a tool matches a policy pattern
|
|
1393
|
-
* Supports both exact matching and suffix matching for MCP tools with server prefixes
|
|
1394
|
-
*
|
|
1395
|
-
* Examples:
|
|
1396
|
-
* - Policy "mcp--read_file" matches "mcp--read_file" (exact)
|
|
1397
|
-
* - Policy "mcp--read_file" matches "mcp--filesystem--read_file" (suffix)
|
|
1398
|
-
* - Policy "read_file" matches "read_file" (local tool exact only)
|
|
1399
|
-
*
|
|
1400
|
-
* @param toolName The fully qualified tool name (e.g., "mcp--filesystem--read_file")
|
|
1401
|
-
* @param policyPattern The policy pattern to match against (e.g., "mcp--read_file")
|
|
1402
|
-
* @returns true if the tool matches the policy pattern
|
|
1403
|
-
*/
|
|
1404
|
-
matchesToolPolicy(toolName, policyPattern) {
|
|
1405
|
-
if (toolName === policyPattern) {
|
|
1406
|
-
return true;
|
|
1407
|
-
}
|
|
1408
|
-
if (policyPattern.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
1409
|
-
const baseName = policyPattern.substring(_ToolManager.MCP_TOOL_PREFIX.length);
|
|
1410
|
-
if (toolName.endsWith(`--${baseName}`) && toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
1411
|
-
return true;
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
return false;
|
|
1415
|
-
}
|
|
1416
|
-
/**
|
|
1417
|
-
* Check if a tool is in the static alwaysDeny list
|
|
1418
|
-
* Supports both exact and suffix matching (e.g., "mcp--read_file" matches "mcp--server--read_file")
|
|
1419
|
-
* @param toolName The fully qualified tool name to check
|
|
1420
|
-
* @returns true if the tool is in the deny list
|
|
1421
|
-
*/
|
|
1422
|
-
isInAlwaysDenyList(toolName) {
|
|
1423
|
-
if (!this.toolPolicies?.alwaysDeny) {
|
|
1424
|
-
return false;
|
|
1425
|
-
}
|
|
1426
|
-
return this.toolPolicies.alwaysDeny.some(
|
|
1427
|
-
(pattern) => this.matchesToolPolicy(toolName, pattern)
|
|
1428
|
-
);
|
|
1429
|
-
}
|
|
1430
1732
|
/**
|
|
1431
1733
|
* Check if a tool is in the static alwaysAllow list
|
|
1432
1734
|
* Supports both exact and suffix matching (e.g., "mcp--read_file" matches "mcp--server--read_file")
|
|
@@ -1438,249 +1740,8 @@ let _ToolManager = class _ToolManager {
|
|
|
1438
1740
|
return false;
|
|
1439
1741
|
}
|
|
1440
1742
|
return this.toolPolicies.alwaysAllow.some(
|
|
1441
|
-
(pattern) =>
|
|
1442
|
-
);
|
|
1443
|
-
}
|
|
1444
|
-
/**
|
|
1445
|
-
* Handle tool approval flow. Checks various precedence levels to determine
|
|
1446
|
-
* if a tool should be auto-approved, denied, or requires manual approval.
|
|
1447
|
-
*/
|
|
1448
|
-
async handleToolApproval(toolName, args, toolCallId, sessionId, runContext, callDescription) {
|
|
1449
|
-
if (this.isInAlwaysDenyList(toolName)) {
|
|
1450
|
-
this.logger.info(
|
|
1451
|
-
`Tool '${toolName}' is in static deny list \u2013 blocking execution (session: ${sessionId ?? "global"})`
|
|
1452
|
-
);
|
|
1453
|
-
throw ToolError.executionDenied(toolName, sessionId);
|
|
1454
|
-
}
|
|
1455
|
-
const validatedArgs = this.validateLocalToolArgs(toolName, args);
|
|
1456
|
-
const presentationSnapshot = await this.getToolPresentationSnapshotForCall(
|
|
1457
|
-
toolName,
|
|
1458
|
-
validatedArgs,
|
|
1459
|
-
toolCallId,
|
|
1460
|
-
sessionId,
|
|
1461
|
-
runContext
|
|
1462
|
-
);
|
|
1463
|
-
let directoryAccess;
|
|
1464
|
-
let directoryAccessApprovalRequest;
|
|
1465
|
-
if (!toolName.startsWith(_ToolManager.MCP_TOOL_PREFIX)) {
|
|
1466
|
-
const getApprovalOverride = this.getToolApprovalOverrideFn(toolName);
|
|
1467
|
-
if (getApprovalOverride) {
|
|
1468
|
-
const context = this.buildToolExecutionContext({
|
|
1469
|
-
sessionId,
|
|
1470
|
-
toolCallId,
|
|
1471
|
-
runContext
|
|
1472
|
-
});
|
|
1473
|
-
const approvalRequest = await getApprovalOverride(validatedArgs, context);
|
|
1474
|
-
if (approvalRequest) {
|
|
1475
|
-
if (approvalRequest.type === ApprovalType.DIRECTORY_ACCESS) {
|
|
1476
|
-
const metadata = approvalRequest.metadata;
|
|
1477
|
-
if (typeof metadata !== "object" || metadata === null || typeof metadata.path !== "string" || typeof metadata.parentDir !== "string" || typeof metadata.operation !== "string" || typeof metadata.toolName !== "string") {
|
|
1478
|
-
throw ToolError.configInvalid(
|
|
1479
|
-
`Tool '${toolName}' returned invalid directory access metadata`
|
|
1480
|
-
);
|
|
1481
|
-
}
|
|
1482
|
-
directoryAccess = metadata;
|
|
1483
|
-
directoryAccessApprovalRequest = approvalRequest;
|
|
1484
|
-
} else {
|
|
1485
|
-
this.logger.debug(
|
|
1486
|
-
`Tool '${toolName}' requested custom approval: type=${approvalRequest.type}`
|
|
1487
|
-
);
|
|
1488
|
-
if (sessionId && !approvalRequest.sessionId) {
|
|
1489
|
-
approvalRequest.sessionId = sessionId;
|
|
1490
|
-
}
|
|
1491
|
-
if (runContext?.hostRuntime !== void 0 && approvalRequest.hostRuntime === void 0) {
|
|
1492
|
-
approvalRequest.hostRuntime = runContext.hostRuntime;
|
|
1493
|
-
}
|
|
1494
|
-
const response = await this.approvalManager.requestApproval(approvalRequest);
|
|
1495
|
-
if (response.status === ApprovalStatus.APPROVED) {
|
|
1496
|
-
const onGranted = this.getToolApprovalOnGrantedFn(toolName);
|
|
1497
|
-
if (onGranted) {
|
|
1498
|
-
await Promise.resolve(
|
|
1499
|
-
onGranted(response, context, approvalRequest)
|
|
1500
|
-
);
|
|
1501
|
-
}
|
|
1502
|
-
this.logger.info(
|
|
1503
|
-
`Custom approval granted for '${toolName}', type=${approvalRequest.type}, session=${sessionId ?? "global"}`
|
|
1504
|
-
);
|
|
1505
|
-
return {
|
|
1506
|
-
requireApproval: true,
|
|
1507
|
-
approvalStatus: "approved",
|
|
1508
|
-
args: validatedArgs,
|
|
1509
|
-
presentationSnapshot
|
|
1510
|
-
};
|
|
1511
|
-
}
|
|
1512
|
-
this.logger.info(
|
|
1513
|
-
`Custom approval denied for '${toolName}', type=${approvalRequest.type}, reason=${response.reason ?? "unknown"}`
|
|
1514
|
-
);
|
|
1515
|
-
throw ToolError.executionDenied(toolName, sessionId);
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
const quickResult = await this.tryQuickApprovalResolution(
|
|
1521
|
-
toolName,
|
|
1522
|
-
validatedArgs,
|
|
1523
|
-
sessionId,
|
|
1524
|
-
directoryAccess
|
|
1743
|
+
(pattern) => matchesToolPolicyPattern(toolName, pattern)
|
|
1525
1744
|
);
|
|
1526
|
-
if (quickResult !== null) {
|
|
1527
|
-
return { ...quickResult, args: validatedArgs, presentationSnapshot };
|
|
1528
|
-
}
|
|
1529
|
-
const manualResult = await this.requestManualApproval(
|
|
1530
|
-
toolName,
|
|
1531
|
-
validatedArgs,
|
|
1532
|
-
toolCallId,
|
|
1533
|
-
sessionId,
|
|
1534
|
-
runContext,
|
|
1535
|
-
directoryAccess,
|
|
1536
|
-
directoryAccessApprovalRequest,
|
|
1537
|
-
callDescription,
|
|
1538
|
-
presentationSnapshot
|
|
1539
|
-
);
|
|
1540
|
-
return { ...manualResult, args: validatedArgs, presentationSnapshot };
|
|
1541
|
-
}
|
|
1542
|
-
/**
|
|
1543
|
-
* Try to resolve tool approval quickly based on policies and cached permissions.
|
|
1544
|
-
* Returns null if manual approval is needed.
|
|
1545
|
-
*
|
|
1546
|
-
* Precedence order (highest to lowest):
|
|
1547
|
-
* 1. Directory access requirement (outside-root paths)
|
|
1548
|
-
* 2. Session auto-approve (skill allowed-tools)
|
|
1549
|
-
* 3. Static allow list
|
|
1550
|
-
* 4. Dynamic "remembered" allowed list
|
|
1551
|
-
* 5. Tool approval patterns
|
|
1552
|
-
* 6. Approval mode (auto-approve/auto-deny)
|
|
1553
|
-
*/
|
|
1554
|
-
async tryQuickApprovalResolution(toolName, args, sessionId, directoryAccess) {
|
|
1555
|
-
if (directoryAccess) {
|
|
1556
|
-
if (this.approvalMode === "auto-approve") {
|
|
1557
|
-
await this.approvalManager.addApprovedDirectory(
|
|
1558
|
-
directoryAccess.parentDir,
|
|
1559
|
-
"once",
|
|
1560
|
-
sessionId
|
|
1561
|
-
);
|
|
1562
|
-
return { requireApproval: false };
|
|
1563
|
-
}
|
|
1564
|
-
return null;
|
|
1565
|
-
}
|
|
1566
|
-
if (sessionId && this.isToolAutoApprovedForSession(sessionId, toolName)) {
|
|
1567
|
-
this.logger.info(
|
|
1568
|
-
`Tool '${toolName}' is in session's auto-approve list \u2013 skipping confirmation (session: ${sessionId})`
|
|
1569
|
-
);
|
|
1570
|
-
return { requireApproval: false };
|
|
1571
|
-
}
|
|
1572
|
-
if (this.isInAlwaysAllowList(toolName)) {
|
|
1573
|
-
this.logger.info(
|
|
1574
|
-
`Tool '${toolName}' is in static allow list \u2013 skipping confirmation (session: ${sessionId ?? "global"})`
|
|
1575
|
-
);
|
|
1576
|
-
return { requireApproval: false };
|
|
1577
|
-
}
|
|
1578
|
-
if (await this.allowedToolsProvider.isToolAllowed(toolName, sessionId)) {
|
|
1579
|
-
this.logger.info(
|
|
1580
|
-
`Tool '${toolName}' already allowed for session '${sessionId ?? "global"}' \u2013 skipping confirmation.`
|
|
1581
|
-
);
|
|
1582
|
-
return { requireApproval: false };
|
|
1583
|
-
}
|
|
1584
|
-
const patternKey = this.getToolPatternKey(toolName, args);
|
|
1585
|
-
if (patternKey && this.approvalManager.matchesPattern(toolName, patternKey, sessionId)) {
|
|
1586
|
-
this.logger.info(
|
|
1587
|
-
`Tool '${toolName}' matched approved pattern key '${patternKey}' \u2013 skipping confirmation.`
|
|
1588
|
-
);
|
|
1589
|
-
return { requireApproval: false };
|
|
1590
|
-
}
|
|
1591
|
-
if (this.approvalMode === "auto-approve") {
|
|
1592
|
-
this.logger.debug(`\u{1F7E2} Auto-approving tool execution: ${toolName}`);
|
|
1593
|
-
return { requireApproval: false };
|
|
1594
|
-
}
|
|
1595
|
-
if (this.approvalMode === "auto-deny") {
|
|
1596
|
-
this.logger.debug(`\u{1F6AB} Auto-denying tool execution: ${toolName}`);
|
|
1597
|
-
throw ToolError.executionDenied(toolName, sessionId);
|
|
1598
|
-
}
|
|
1599
|
-
return null;
|
|
1600
|
-
}
|
|
1601
|
-
/**
|
|
1602
|
-
* Request manual approval from the user for a tool execution.
|
|
1603
|
-
* Generates preview, sends approval request, and handles the response.
|
|
1604
|
-
*/
|
|
1605
|
-
async requestManualApproval(toolName, args, toolCallId, sessionId, runContext, directoryAccess, directoryAccessApprovalRequest, callDescription, presentationSnapshot) {
|
|
1606
|
-
this.logger.info(
|
|
1607
|
-
`Tool approval requested for ${toolName}, sessionId: ${sessionId ?? "global"}`
|
|
1608
|
-
);
|
|
1609
|
-
try {
|
|
1610
|
-
const displayPreview = await this.generateToolPreview(
|
|
1611
|
-
toolName,
|
|
1612
|
-
args,
|
|
1613
|
-
toolCallId,
|
|
1614
|
-
sessionId,
|
|
1615
|
-
runContext
|
|
1616
|
-
);
|
|
1617
|
-
const hostRuntime = runContext?.hostRuntime ?? directoryAccessApprovalRequest?.hostRuntime;
|
|
1618
|
-
const suggestedPatterns = this.getToolSuggestedPatterns(toolName, args);
|
|
1619
|
-
const response = await this.approvalManager.requestToolApproval({
|
|
1620
|
-
toolName,
|
|
1621
|
-
...presentationSnapshot !== void 0 && { presentationSnapshot },
|
|
1622
|
-
toolCallId,
|
|
1623
|
-
args,
|
|
1624
|
-
...callDescription !== void 0 && { description: callDescription },
|
|
1625
|
-
...sessionId !== void 0 && { sessionId },
|
|
1626
|
-
...hostRuntime !== void 0 && { hostRuntime },
|
|
1627
|
-
...displayPreview !== void 0 && { displayPreview },
|
|
1628
|
-
...directoryAccess !== void 0 && { directoryAccess },
|
|
1629
|
-
...suggestedPatterns !== void 0 && { suggestedPatterns }
|
|
1630
|
-
});
|
|
1631
|
-
if (response.status === ApprovalStatus.APPROVED && directoryAccessApprovalRequest !== void 0) {
|
|
1632
|
-
const onGranted = this.getToolApprovalOnGrantedFn(toolName);
|
|
1633
|
-
if (onGranted) {
|
|
1634
|
-
const context = this.buildToolExecutionContext({
|
|
1635
|
-
sessionId,
|
|
1636
|
-
toolCallId,
|
|
1637
|
-
runContext
|
|
1638
|
-
});
|
|
1639
|
-
await Promise.resolve(
|
|
1640
|
-
onGranted(response, context, directoryAccessApprovalRequest)
|
|
1641
|
-
);
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
if (response.status === ApprovalStatus.APPROVED && response.data) {
|
|
1645
|
-
await this.handleRememberChoice(toolName, response, sessionId);
|
|
1646
|
-
}
|
|
1647
|
-
if (response.status !== ApprovalStatus.APPROVED) {
|
|
1648
|
-
this.handleApprovalDenied(toolName, response, sessionId);
|
|
1649
|
-
}
|
|
1650
|
-
this.logger.info(
|
|
1651
|
-
`Tool approval approved for ${toolName}, sessionId: ${sessionId ?? "global"}`
|
|
1652
|
-
);
|
|
1653
|
-
return { requireApproval: true, approvalStatus: "approved" };
|
|
1654
|
-
} catch (error) {
|
|
1655
|
-
this.logger.error(
|
|
1656
|
-
`Tool approval error for ${toolName}: ${error instanceof Error ? error.message : String(error)}`
|
|
1657
|
-
);
|
|
1658
|
-
throw error;
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
/**
|
|
1662
|
-
* Generate a preview for the tool approval UI if the tool supports it.
|
|
1663
|
-
*/
|
|
1664
|
-
async generateToolPreview(toolName, args, toolCallId, sessionId, runContext) {
|
|
1665
|
-
const previewFn = this.getToolPreviewFn(toolName);
|
|
1666
|
-
if (!previewFn) {
|
|
1667
|
-
return void 0;
|
|
1668
|
-
}
|
|
1669
|
-
try {
|
|
1670
|
-
const context = this.buildToolExecutionContext({ sessionId, toolCallId, runContext });
|
|
1671
|
-
const preview = await previewFn(args, context);
|
|
1672
|
-
this.logger.debug(`Generated preview for ${toolName}`);
|
|
1673
|
-
return preview ?? void 0;
|
|
1674
|
-
} catch (previewError) {
|
|
1675
|
-
if (previewError instanceof DextoRuntimeError && previewError.code === ToolErrorCode.VALIDATION_FAILED) {
|
|
1676
|
-
this.logger.debug(`Validation failed for ${toolName}: ${previewError.message}`);
|
|
1677
|
-
throw previewError;
|
|
1678
|
-
}
|
|
1679
|
-
this.logger.debug(
|
|
1680
|
-
`Preview generation failed for ${toolName}: ${previewError instanceof Error ? previewError.message : String(previewError)}`
|
|
1681
|
-
);
|
|
1682
|
-
return void 0;
|
|
1683
|
-
}
|
|
1684
1745
|
}
|
|
1685
1746
|
/**
|
|
1686
1747
|
* Handle "remember" actions when user approves a tool.
|
|
@@ -1713,12 +1774,12 @@ let _ToolManager = class _ToolManager {
|
|
|
1713
1774
|
handleApprovalDenied(toolName, response, sessionId) {
|
|
1714
1775
|
if (response.status === ApprovalStatus.CANCELLED && response.reason === DenialReason.TIMEOUT) {
|
|
1715
1776
|
this.logger.info(
|
|
1716
|
-
`Tool
|
|
1777
|
+
`Tool approval timed out for ${toolName}, sessionId: ${sessionId ?? "global"}`
|
|
1717
1778
|
);
|
|
1718
1779
|
throw ToolError.executionTimeout(toolName, response.timeoutMs ?? 0, sessionId);
|
|
1719
1780
|
}
|
|
1720
1781
|
this.logger.info(
|
|
1721
|
-
`Tool
|
|
1782
|
+
`Tool approval denied for ${toolName}, sessionId: ${sessionId ?? "global"}, reason: ${response.reason ?? "unknown"}`
|
|
1722
1783
|
);
|
|
1723
1784
|
throw ToolError.executionDenied(toolName, sessionId, response.message);
|
|
1724
1785
|
}
|
|
@@ -1731,24 +1792,6 @@ let _ToolManager = class _ToolManager {
|
|
|
1731
1792
|
this.invalidateCache();
|
|
1732
1793
|
this.logger.debug("ToolManager refreshed (including MCP server capabilities)");
|
|
1733
1794
|
}
|
|
1734
|
-
/**
|
|
1735
|
-
* Get list of pending confirmation requests
|
|
1736
|
-
*/
|
|
1737
|
-
getPendingConfirmations() {
|
|
1738
|
-
return this.approvalManager.getPendingApprovals();
|
|
1739
|
-
}
|
|
1740
|
-
/**
|
|
1741
|
-
* Cancel a pending confirmation request
|
|
1742
|
-
*/
|
|
1743
|
-
cancelConfirmation(approvalId) {
|
|
1744
|
-
this.approvalManager.cancelApproval(approvalId);
|
|
1745
|
-
}
|
|
1746
|
-
/**
|
|
1747
|
-
* Cancel all pending confirmation requests
|
|
1748
|
-
*/
|
|
1749
|
-
cancelAllConfirmations() {
|
|
1750
|
-
this.approvalManager.cancelAllApprovals();
|
|
1751
|
-
}
|
|
1752
1795
|
};
|
|
1753
1796
|
_init = __decoratorStart(null);
|
|
1754
1797
|
_ToolManager = __decorateElement(_init, 0, "ToolManager", _ToolManager_decorators, _ToolManager);
|