@dexto/core 1.2.6 → 1.4.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/README.md +55 -13
- package/dist/agent/DextoAgent.cjs +627 -228
- package/dist/agent/DextoAgent.d.ts +157 -34
- package/dist/agent/DextoAgent.d.ts.map +1 -1
- package/dist/agent/DextoAgent.js +625 -227
- package/dist/agent/agentCard.js +1 -1
- package/dist/agent/error-codes.cjs +1 -0
- package/dist/agent/error-codes.d.ts +2 -1
- package/dist/agent/error-codes.d.ts.map +1 -1
- package/dist/agent/error-codes.js +2 -1
- package/dist/agent/errors.cjs +13 -0
- package/dist/agent/errors.d.ts +4 -0
- package/dist/agent/errors.d.ts.map +1 -1
- package/dist/agent/errors.js +14 -1
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/schemas.cjs +4 -1
- package/dist/agent/schemas.d.ts +92 -55
- package/dist/agent/schemas.d.ts.map +1 -1
- package/dist/agent/schemas.js +7 -3
- package/dist/agent/state-manager.cjs +5 -5
- package/dist/agent/state-manager.d.ts +4 -4
- package/dist/agent/state-manager.js +6 -6
- package/dist/agent/types.d.ts +24 -11
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/approval/error-codes.js +1 -1
- package/dist/approval/errors.js +1 -1
- package/dist/approval/factory.js +1 -1
- package/dist/approval/index.js +1 -1
- package/dist/approval/manager.cjs +69 -3
- package/dist/approval/manager.d.ts +41 -3
- package/dist/approval/manager.d.ts.map +1 -1
- package/dist/approval/manager.js +70 -4
- package/dist/approval/schemas.cjs +20 -5
- package/dist/approval/schemas.d.ts +127 -52
- package/dist/approval/schemas.d.ts.map +1 -1
- package/dist/approval/schemas.js +21 -6
- package/dist/approval/types.d.ts +6 -0
- package/dist/approval/types.d.ts.map +1 -1
- package/dist/approval/types.js +1 -1
- package/dist/{chunk-C6A6W6XS.js → chunk-PTJYTZNU.js} +44 -1
- package/dist/{llm/tokenizer/factory.cjs → context/compression/overflow.cjs} +20 -21
- package/dist/context/compression/overflow.d.ts +33 -0
- package/dist/context/compression/overflow.d.ts.map +1 -0
- package/dist/context/compression/overflow.js +19 -0
- package/dist/context/compression/reactive-overflow.cjs +201 -0
- package/dist/context/compression/reactive-overflow.d.ts +81 -0
- package/dist/context/compression/reactive-overflow.d.ts.map +1 -0
- package/dist/context/compression/reactive-overflow.js +178 -0
- package/dist/context/compression/types.d.ts +9 -7
- package/dist/context/compression/types.d.ts.map +1 -1
- package/dist/context/error-codes.cjs +3 -0
- package/dist/context/error-codes.d.ts +4 -1
- package/dist/context/error-codes.d.ts.map +1 -1
- package/dist/context/error-codes.js +4 -1
- package/dist/context/errors.cjs +28 -0
- package/dist/context/errors.d.ts +7 -0
- package/dist/context/errors.d.ts.map +1 -1
- package/dist/context/errors.js +29 -1
- package/dist/context/index.js +1 -1
- package/dist/context/manager.cjs +287 -323
- package/dist/context/manager.d.ts +65 -111
- package/dist/context/manager.d.ts.map +1 -1
- package/dist/context/manager.js +287 -328
- package/dist/context/media-helpers.js +1 -1
- package/dist/context/types.cjs +49 -0
- package/dist/context/types.d.ts +185 -72
- package/dist/context/types.d.ts.map +1 -1
- package/dist/context/types.js +35 -0
- package/dist/context/utils.cjs +266 -283
- package/dist/context/utils.d.ts +32 -18
- package/dist/context/utils.d.ts.map +1 -1
- package/dist/context/utils.js +266 -283
- 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.cjs +1 -0
- package/dist/errors/types.d.ts +4 -2
- package/dist/errors/types.d.ts.map +1 -1
- package/dist/errors/types.js +2 -1
- package/dist/events/index.cjs +22 -2
- package/dist/events/index.d.ts +170 -62
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +23 -3
- package/dist/filesystem/error-codes.js +1 -1
- package/dist/filesystem/errors.js +1 -1
- package/dist/filesystem/filesystem-service.js +1 -1
- package/dist/filesystem/index.js +1 -1
- package/dist/filesystem/path-validator.js +1 -1
- package/dist/index.browser.cjs +23 -8
- package/dist/index.browser.d.ts +4 -3
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +20 -3
- package/dist/index.js +1 -1
- package/dist/llm/error-codes.cjs +0 -1
- package/dist/llm/error-codes.d.ts +0 -1
- package/dist/llm/error-codes.d.ts.map +1 -1
- package/dist/llm/error-codes.js +1 -2
- package/dist/llm/errors.cjs +10 -10
- package/dist/llm/errors.d.ts +5 -6
- package/dist/llm/errors.d.ts.map +1 -1
- package/dist/llm/errors.js +12 -12
- package/dist/llm/executor/stream-processor.cjs +367 -0
- package/dist/llm/executor/stream-processor.d.ts +55 -0
- package/dist/llm/executor/stream-processor.d.ts.map +1 -0
- package/dist/llm/executor/stream-processor.js +344 -0
- package/dist/llm/executor/tool-output-truncator.cjs +75 -0
- package/dist/llm/executor/tool-output-truncator.d.ts +27 -0
- package/dist/llm/executor/tool-output-truncator.d.ts.map +1 -0
- package/dist/llm/executor/tool-output-truncator.js +48 -0
- package/dist/llm/executor/turn-executor.cjs +753 -0
- package/dist/llm/executor/turn-executor.d.ts +166 -0
- package/dist/llm/executor/turn-executor.d.ts.map +1 -0
- package/dist/llm/executor/turn-executor.js +684 -0
- package/dist/llm/executor/types.d.ts +27 -0
- package/dist/llm/executor/types.d.ts.map +1 -0
- package/dist/llm/formatters/vercel.cjs +20 -186
- package/dist/llm/formatters/vercel.d.ts +2 -14
- package/dist/llm/formatters/vercel.d.ts.map +1 -1
- package/dist/llm/formatters/vercel.js +19 -185
- package/dist/llm/registry.cjs +36 -45
- package/dist/llm/registry.d.ts +53 -39
- package/dist/llm/registry.d.ts.map +1 -1
- package/dist/llm/registry.js +34 -42
- package/dist/llm/resolver.cjs +1 -31
- package/dist/llm/resolver.d.ts.map +1 -1
- package/dist/llm/resolver.js +2 -34
- package/dist/llm/schemas.cjs +2 -17
- package/dist/llm/schemas.d.ts +10 -23
- package/dist/llm/schemas.d.ts.map +1 -1
- package/dist/llm/schemas.js +5 -22
- package/dist/llm/services/factory.cjs +3 -92
- package/dist/llm/services/factory.d.ts +14 -4
- package/dist/llm/services/factory.d.ts.map +1 -1
- package/dist/llm/services/factory.js +4 -83
- package/dist/llm/services/test-utils.integration.cjs +6 -8
- package/dist/llm/services/test-utils.integration.d.ts.map +1 -1
- package/dist/llm/services/test-utils.integration.js +7 -9
- package/dist/llm/services/types.d.ts +1 -28
- package/dist/llm/services/types.d.ts.map +1 -1
- package/dist/llm/services/vercel.cjs +54 -468
- package/dist/llm/services/vercel.d.ts +38 -21
- package/dist/llm/services/vercel.d.ts.map +1 -1
- package/dist/llm/services/vercel.js +56 -475
- package/dist/llm/types.cjs +0 -3
- package/dist/llm/types.d.ts +8 -8
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/llm/types.js +1 -3
- package/dist/llm/validation.js +1 -1
- package/dist/logger/browser.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.cjs +34 -6
- package/dist/logger/v2/dexto-logger.d.ts +20 -2
- package/dist/logger/v2/dexto-logger.d.ts.map +1 -1
- package/dist/logger/v2/dexto-logger.js +35 -7
- package/dist/logger/v2/error-codes.js +1 -1
- package/dist/logger/v2/errors.js +1 -1
- package/dist/logger/v2/schemas.cjs +1 -1
- package/dist/logger/v2/schemas.js +2 -2
- package/dist/logger/v2/test-utils.cjs +70 -0
- package/dist/logger/v2/test-utils.d.ts +17 -0
- package/dist/logger/v2/test-utils.d.ts.map +1 -0
- package/dist/logger/v2/test-utils.js +46 -0
- 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.cjs +6 -0
- package/dist/logger/v2/transports/file-transport.d.ts +4 -0
- package/dist/logger/v2/transports/file-transport.d.ts.map +1 -1
- package/dist/logger/v2/transports/file-transport.js +7 -1
- package/dist/logger/v2/types.cjs +1 -0
- package/dist/logger/v2/types.d.ts +18 -2
- package/dist/logger/v2/types.d.ts.map +1 -1
- package/dist/logger/v2/types.js +2 -1
- package/dist/mcp/error-codes.cjs +1 -0
- package/dist/mcp/error-codes.d.ts +1 -0
- package/dist/mcp/error-codes.d.ts.map +1 -1
- package/dist/mcp/error-codes.js +2 -1
- package/dist/mcp/errors.cjs +13 -0
- package/dist/mcp/errors.d.ts +7 -0
- package/dist/mcp/errors.d.ts.map +1 -1
- package/dist/mcp/errors.js +14 -1
- package/dist/mcp/manager.cjs +4 -0
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +5 -1
- package/dist/mcp/mcp-client.js +1 -1
- package/dist/mcp/resolver.js +1 -1
- package/dist/mcp/schemas.cjs +6 -0
- package/dist/mcp/schemas.d.ts +52 -0
- package/dist/mcp/schemas.d.ts.map +1 -1
- package/dist/mcp/schemas.js +6 -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.js +1 -1
- package/dist/memory/schemas.d.ts +2 -2
- package/dist/memory/schemas.js +1 -1
- package/dist/plugins/builtins/content-policy.js +1 -1
- package/dist/plugins/builtins/response-sanitizer.js +1 -1
- package/dist/plugins/error-codes.cjs +1 -0
- package/dist/plugins/error-codes.d.ts +3 -1
- package/dist/plugins/error-codes.d.ts.map +1 -1
- package/dist/plugins/error-codes.js +2 -1
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/loader.cjs +25 -5
- package/dist/plugins/loader.d.ts.map +1 -1
- package/dist/plugins/loader.js +26 -6
- package/dist/plugins/manager.js +1 -1
- package/dist/plugins/registrations/builtins.js +1 -1
- package/dist/plugins/schemas.d.ts +3 -3
- package/dist/plugins/schemas.js +1 -1
- package/dist/plugins/types.d.ts +0 -1
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/process/command-validator.js +1 -1
- package/dist/process/error-codes.js +1 -1
- package/dist/process/errors.js +1 -1
- package/dist/process/index.js +1 -1
- package/dist/process/process-service.cjs +78 -26
- package/dist/process/process-service.d.ts +6 -1
- package/dist/process/process-service.d.ts.map +1 -1
- package/dist/process/process-service.js +79 -27
- package/dist/process/types.d.ts +2 -2
- package/dist/process/types.d.ts.map +1 -1
- package/dist/prompts/error-codes.cjs +1 -0
- package/dist/prompts/error-codes.d.ts +2 -1
- package/dist/prompts/error-codes.d.ts.map +1 -1
- package/dist/prompts/error-codes.js +2 -1
- package/dist/prompts/errors.cjs +15 -0
- package/dist/prompts/errors.d.ts +4 -0
- package/dist/prompts/errors.d.ts.map +1 -1
- package/dist/prompts/errors.js +16 -1
- package/dist/prompts/index.js +1 -1
- package/dist/prompts/name-validation.js +1 -1
- package/dist/prompts/prompt-manager.cjs +13 -2
- package/dist/prompts/prompt-manager.d.ts +7 -0
- package/dist/prompts/prompt-manager.d.ts.map +1 -1
- package/dist/prompts/prompt-manager.js +14 -3
- package/dist/prompts/providers/config-prompt-provider.cjs +12 -3
- package/dist/prompts/providers/config-prompt-provider.d.ts +2 -1
- package/dist/prompts/providers/config-prompt-provider.d.ts.map +1 -1
- package/dist/prompts/providers/config-prompt-provider.js +13 -4
- package/dist/prompts/providers/custom-prompt-provider.cjs +2 -2
- package/dist/prompts/providers/custom-prompt-provider.d.ts +1 -1
- package/dist/prompts/providers/custom-prompt-provider.d.ts.map +1 -1
- package/dist/prompts/providers/custom-prompt-provider.js +3 -3
- package/dist/prompts/providers/mcp-prompt-provider.js +1 -1
- package/dist/prompts/schemas.d.ts +12 -0
- package/dist/prompts/schemas.d.ts.map +1 -1
- package/dist/prompts/schemas.js +1 -1
- package/dist/prompts/types.d.ts +2 -0
- package/dist/prompts/types.d.ts.map +1 -1
- package/dist/prompts/utils.js +1 -1
- package/dist/resources/error-codes.js +1 -1
- package/dist/resources/errors.js +1 -1
- package/dist/resources/handlers/blob-handler.js +1 -1
- package/dist/resources/handlers/factory.js +1 -1
- package/dist/resources/handlers/filesystem-handler.js +1 -1
- package/dist/resources/index.js +1 -1
- package/dist/resources/internal-provider.js +1 -1
- package/dist/resources/manager.js +1 -1
- package/dist/resources/reference-parser.js +1 -1
- package/dist/resources/schemas.js +1 -1
- package/dist/search/index.js +1 -1
- package/dist/search/search-service.js +1 -1
- package/dist/session/chat-session.cjs +149 -51
- package/dist/session/chat-session.d.ts +69 -29
- package/dist/session/chat-session.d.ts.map +1 -1
- package/dist/session/chat-session.js +150 -52
- package/dist/session/error-codes.js +1 -1
- package/dist/session/errors.js +1 -1
- package/dist/session/history/database.cjs +134 -21
- package/dist/session/history/database.d.ts +37 -8
- package/dist/session/history/database.d.ts.map +1 -1
- package/dist/session/history/database.js +135 -22
- package/dist/session/history/factory.js +1 -1
- package/dist/session/history/memory.cjs +18 -0
- package/dist/session/history/memory.d.ts +8 -0
- package/dist/session/history/memory.d.ts.map +1 -1
- package/dist/session/history/memory.js +19 -1
- package/dist/session/history/types.d.ts +13 -1
- package/dist/session/history/types.d.ts.map +1 -1
- package/dist/session/index.cjs +3 -0
- package/dist/session/index.d.ts +3 -0
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +3 -1
- package/dist/session/message-queue.cjs +201 -0
- package/dist/session/message-queue.d.ts +114 -0
- package/dist/session/message-queue.d.ts.map +1 -0
- package/dist/session/message-queue.js +178 -0
- package/dist/session/schemas.js +1 -1
- package/dist/session/session-manager.cjs +57 -7
- package/dist/session/session-manager.d.ts +18 -0
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +58 -8
- package/dist/session/title-generator.cjs +4 -8
- package/dist/session/title-generator.d.ts +1 -2
- package/dist/session/title-generator.d.ts.map +1 -1
- package/dist/session/title-generator.js +5 -9
- package/dist/session/types.cjs +16 -0
- package/dist/session/types.d.ts +14 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +0 -0
- package/dist/storage/blob/factory.js +1 -1
- package/dist/storage/blob/local-blob-store.js +1 -1
- package/dist/storage/blob/memory-blob-store.js +1 -1
- package/dist/storage/blob/schemas.js +1 -1
- package/dist/storage/cache/factory.cjs +6 -2
- package/dist/storage/cache/factory.d.ts +2 -1
- package/dist/storage/cache/factory.d.ts.map +1 -1
- package/dist/storage/cache/factory.js +7 -3
- package/dist/storage/cache/memory-cache-store.js +1 -1
- package/dist/storage/cache/redis-store.js +1 -1
- package/dist/storage/cache/schemas.js +1 -1
- package/dist/storage/database/factory.cjs +11 -17
- package/dist/storage/database/factory.d.ts +2 -1
- package/dist/storage/database/factory.d.ts.map +1 -1
- package/dist/storage/database/factory.js +12 -18
- package/dist/storage/database/memory-database-store.js +1 -1
- package/dist/storage/database/postgres-store.cjs +12 -0
- package/dist/storage/database/postgres-store.d.ts.map +1 -1
- package/dist/storage/database/postgres-store.js +13 -1
- package/dist/storage/database/schemas.js +1 -1
- package/dist/storage/database/sqlite-store.cjs +8 -0
- package/dist/storage/database/sqlite-store.d.ts.map +1 -1
- package/dist/storage/database/sqlite-store.js +9 -1
- package/dist/storage/error-codes.cjs +1 -0
- package/dist/storage/error-codes.d.ts +1 -0
- package/dist/storage/error-codes.d.ts.map +1 -1
- package/dist/storage/error-codes.js +2 -1
- package/dist/storage/errors.cjs +17 -0
- package/dist/storage/errors.d.ts +9 -0
- package/dist/storage/errors.d.ts.map +1 -1
- package/dist/storage/errors.js +18 -1
- package/dist/storage/index.js +1 -1
- package/dist/storage/schemas.js +1 -1
- package/dist/storage/storage-manager.js +1 -1
- package/dist/systemPrompt/contributors.js +1 -1
- 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.d.ts +5 -5
- package/dist/systemPrompt/schemas.js +1 -1
- package/dist/telemetry/decorators.js +1 -1
- package/dist/{llm/tokenizer/default.cjs → telemetry/error-codes.cjs} +14 -19
- package/dist/telemetry/error-codes.d.ts +13 -0
- package/dist/telemetry/error-codes.d.ts.map +1 -0
- package/dist/telemetry/error-codes.js +13 -0
- package/dist/telemetry/errors.cjs +105 -0
- package/dist/telemetry/errors.d.ts +28 -0
- package/dist/telemetry/errors.d.ts.map +1 -0
- package/dist/telemetry/errors.js +82 -0
- 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.cjs +92 -26
- package/dist/telemetry/telemetry.d.ts +1 -1
- package/dist/telemetry/telemetry.d.ts.map +1 -1
- package/dist/telemetry/telemetry.js +75 -19
- package/dist/telemetry/utils.js +1 -1
- package/dist/tools/bash-pattern-utils.cjs +91 -0
- package/dist/tools/bash-pattern-utils.d.ts +58 -0
- package/dist/tools/bash-pattern-utils.d.ts.map +1 -0
- package/dist/tools/bash-pattern-utils.js +64 -0
- package/dist/tools/confirmation/allowed-tools-provider/factory.js +1 -1
- package/dist/tools/confirmation/allowed-tools-provider/in-memory.js +1 -1
- package/dist/tools/confirmation/allowed-tools-provider/storage.js +1 -1
- package/dist/tools/display-types.cjs +60 -0
- package/dist/tools/display-types.d.ts +133 -0
- package/dist/tools/display-types.d.ts.map +1 -0
- package/dist/tools/display-types.js +32 -0
- package/dist/tools/error-codes.cjs +2 -0
- package/dist/tools/error-codes.d.ts +3 -1
- package/dist/tools/error-codes.d.ts.map +1 -1
- package/dist/tools/error-codes.js +3 -1
- package/dist/tools/errors.cjs +30 -0
- package/dist/tools/errors.d.ts +16 -0
- package/dist/tools/errors.d.ts.map +1 -1
- package/dist/tools/errors.js +31 -1
- package/dist/tools/index.cjs +2 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -1
- package/dist/tools/internal-tools/constants.js +1 -1
- package/dist/tools/internal-tools/implementations/ask-user-tool.cjs +1 -1
- package/dist/tools/internal-tools/implementations/ask-user-tool.js +2 -2
- package/dist/tools/internal-tools/implementations/bash-exec-tool.cjs +42 -18
- package/dist/tools/internal-tools/implementations/bash-exec-tool.d.ts +3 -3
- package/dist/tools/internal-tools/implementations/bash-exec-tool.d.ts.map +1 -1
- package/dist/tools/internal-tools/implementations/bash-exec-tool.js +43 -19
- package/dist/tools/internal-tools/implementations/bash-output-tool.js +1 -1
- package/dist/tools/internal-tools/implementations/delegate-to-url-tool.js +1 -1
- package/dist/tools/internal-tools/implementations/edit-file-tool.cjs +66 -1
- package/dist/tools/internal-tools/implementations/edit-file-tool.d.ts.map +1 -1
- package/dist/tools/internal-tools/implementations/edit-file-tool.js +67 -2
- package/dist/tools/internal-tools/implementations/glob-files-tool.cjs +14 -1
- package/dist/tools/internal-tools/implementations/glob-files-tool.d.ts.map +1 -1
- package/dist/tools/internal-tools/implementations/glob-files-tool.js +15 -2
- package/dist/tools/internal-tools/implementations/grep-content-tool.cjs +16 -1
- package/dist/tools/internal-tools/implementations/grep-content-tool.d.ts.map +1 -1
- package/dist/tools/internal-tools/implementations/grep-content-tool.js +17 -2
- package/dist/tools/internal-tools/implementations/kill-process-tool.js +1 -1
- package/dist/tools/internal-tools/implementations/read-file-tool.cjs +9 -1
- package/dist/tools/internal-tools/implementations/read-file-tool.d.ts.map +1 -1
- package/dist/tools/internal-tools/implementations/read-file-tool.js +10 -2
- package/dist/tools/internal-tools/implementations/search-history-tool.js +1 -1
- package/dist/tools/internal-tools/implementations/write-file-tool.cjs +69 -1
- package/dist/tools/internal-tools/implementations/write-file-tool.d.ts.map +1 -1
- package/dist/tools/internal-tools/implementations/write-file-tool.js +72 -2
- package/dist/tools/internal-tools/provider.cjs +27 -10
- package/dist/tools/internal-tools/provider.d.ts +8 -5
- package/dist/tools/internal-tools/provider.d.ts.map +1 -1
- package/dist/tools/internal-tools/provider.js +28 -11
- package/dist/tools/internal-tools/registry.cjs +4 -3
- package/dist/tools/internal-tools/registry.d.ts +28 -7
- package/dist/tools/internal-tools/registry.d.ts.map +1 -1
- package/dist/tools/internal-tools/registry.js +5 -4
- package/dist/tools/schemas.cjs +17 -7
- package/dist/tools/schemas.d.ts +31 -4
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/schemas.js +15 -7
- package/dist/tools/tool-manager.cjs +140 -18
- package/dist/tools/tool-manager.d.ts +23 -1
- package/dist/tools/tool-manager.d.ts.map +1 -1
- package/dist/tools/tool-manager.js +145 -19
- package/dist/tools/types.d.ts +20 -11
- 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/{llm/tokenizer/types.cjs → utils/defer.cjs} +19 -10
- package/dist/utils/defer.d.ts +63 -0
- package/dist/utils/defer.d.ts.map +1 -0
- package/dist/utils/defer.js +19 -0
- package/dist/utils/env-file.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/index.cjs +3 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/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-metadata.js +1 -1
- package/dist/utils/schema.d.ts +6 -0
- package/dist/utils/schema.d.ts.map +1 -1
- package/dist/utils/schema.js +1 -1
- package/dist/utils/service-initializer.cjs +6 -2
- package/dist/utils/service-initializer.d.ts.map +1 -1
- package/dist/utils/service-initializer.js +7 -3
- package/dist/utils/user-info.js +1 -1
- package/dist/utils/zod-schema-converter.js +1 -1
- package/package.json +54 -17
- package/dist/context/compression/middle-removal.cjs +0 -95
- package/dist/context/compression/middle-removal.d.ts +0 -47
- package/dist/context/compression/middle-removal.d.ts.map +0 -1
- package/dist/context/compression/middle-removal.js +0 -72
- package/dist/context/compression/oldest-removal.cjs +0 -83
- package/dist/context/compression/oldest-removal.d.ts +0 -42
- package/dist/context/compression/oldest-removal.d.ts.map +0 -1
- package/dist/context/compression/oldest-removal.js +0 -60
- package/dist/llm/formatters/anthropic.cjs +0 -257
- package/dist/llm/formatters/anthropic.d.ts +0 -46
- package/dist/llm/formatters/anthropic.d.ts.map +0 -1
- package/dist/llm/formatters/anthropic.js +0 -239
- package/dist/llm/formatters/factory.cjs +0 -50
- package/dist/llm/formatters/factory.d.ts +0 -10
- package/dist/llm/formatters/factory.d.ts.map +0 -1
- package/dist/llm/formatters/factory.js +0 -27
- package/dist/llm/formatters/openai.cjs +0 -196
- package/dist/llm/formatters/openai.d.ts +0 -39
- package/dist/llm/formatters/openai.d.ts.map +0 -1
- package/dist/llm/formatters/openai.js +0 -177
- package/dist/llm/formatters/types.d.ts +0 -41
- package/dist/llm/formatters/types.d.ts.map +0 -1
- package/dist/llm/services/anthropic.cjs +0 -511
- package/dist/llm/services/anthropic.d.ts +0 -48
- package/dist/llm/services/anthropic.d.ts.map +0 -1
- package/dist/llm/services/anthropic.js +0 -447
- package/dist/llm/services/openai.cjs +0 -611
- package/dist/llm/services/openai.d.ts +0 -48
- package/dist/llm/services/openai.d.ts.map +0 -1
- package/dist/llm/services/openai.js +0 -547
- package/dist/llm/tokenizer/anthropic.cjs +0 -43
- package/dist/llm/tokenizer/anthropic.d.ts +0 -19
- package/dist/llm/tokenizer/anthropic.d.ts.map +0 -1
- package/dist/llm/tokenizer/anthropic.js +0 -20
- package/dist/llm/tokenizer/default.d.ts +0 -14
- package/dist/llm/tokenizer/default.d.ts.map +0 -1
- package/dist/llm/tokenizer/default.js +0 -18
- package/dist/llm/tokenizer/factory.d.ts +0 -12
- package/dist/llm/tokenizer/factory.d.ts.map +0 -1
- package/dist/llm/tokenizer/factory.js +0 -21
- package/dist/llm/tokenizer/google.cjs +0 -52
- package/dist/llm/tokenizer/google.d.ts +0 -29
- package/dist/llm/tokenizer/google.d.ts.map +0 -1
- package/dist/llm/tokenizer/google.js +0 -29
- package/dist/llm/tokenizer/openai.cjs +0 -115
- package/dist/llm/tokenizer/openai.d.ts +0 -33
- package/dist/llm/tokenizer/openai.d.ts.map +0 -1
- package/dist/llm/tokenizer/openai.js +0 -91
- package/dist/llm/tokenizer/types.d.ts +0 -18
- package/dist/llm/tokenizer/types.d.ts.map +0 -1
- package/dist/llm/tokenizer/types.js +0 -10
- /package/dist/llm/{formatters → executor}/types.cjs +0 -0
- /package/dist/llm/{formatters → executor}/types.js +0 -0
package/dist/agent/DextoAgent.js
CHANGED
|
@@ -2,8 +2,10 @@ import {
|
|
|
2
2
|
__decorateElement,
|
|
3
3
|
__decoratorStart,
|
|
4
4
|
__runInitializers
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-PTJYTZNU.js";
|
|
6
6
|
var _DextoAgent_decorators, _init;
|
|
7
|
+
import { randomUUID } from "crypto";
|
|
8
|
+
import { setMaxListeners } from "events";
|
|
7
9
|
import { expandMessageReferences } from "../resources/index.js";
|
|
8
10
|
import { expandBlobReferences } from "../context/utils.js";
|
|
9
11
|
import { PromptManager } from "../prompts/index.js";
|
|
@@ -19,6 +21,7 @@ import { LLMError } from "../llm/errors.js";
|
|
|
19
21
|
import { AgentError } from "./errors.js";
|
|
20
22
|
import { MCPError } from "../mcp/errors.js";
|
|
21
23
|
import { DextoRuntimeError } from "../errors/DextoRuntimeError.js";
|
|
24
|
+
import { DextoValidationError } from "../errors/DextoValidationError.js";
|
|
22
25
|
import { ensureOk } from "../errors/result-bridge.js";
|
|
23
26
|
import { fail, zodToIssues } from "../utils/result.js";
|
|
24
27
|
import { resolveAndValidateMcpServerConfig } from "../mcp/resolver.js";
|
|
@@ -31,8 +34,7 @@ import {
|
|
|
31
34
|
import { createAgentServices } from "../utils/service-initializer.js";
|
|
32
35
|
import { AgentConfigSchema } from "./schemas.js";
|
|
33
36
|
import {
|
|
34
|
-
AgentEventBus
|
|
35
|
-
STREAMING_EVENTS
|
|
37
|
+
AgentEventBus
|
|
36
38
|
} from "../events/index.js";
|
|
37
39
|
import { safeStringify } from "../utils/safe-stringify.js";
|
|
38
40
|
import { deriveHeuristicTitle, generateSessionTitle } from "../session/title-generator.js";
|
|
@@ -104,6 +106,8 @@ class DextoAgent {
|
|
|
104
106
|
// Approval handler for manual tool confirmation and elicitation
|
|
105
107
|
// Set via setApprovalHandler() before start() if needed
|
|
106
108
|
approvalHandler;
|
|
109
|
+
// Active stream controllers per session - allows cancel() to abort iterators
|
|
110
|
+
activeStreamControllers = /* @__PURE__ */ new Map();
|
|
107
111
|
// Logger instance for this agent (dependency injection)
|
|
108
112
|
logger;
|
|
109
113
|
/**
|
|
@@ -179,10 +183,6 @@ Either:
|
|
|
179
183
|
for (const subscriber of this.eventSubscribers) {
|
|
180
184
|
subscriber.subscribe(this.agentEventBus);
|
|
181
185
|
}
|
|
182
|
-
const fileTransport = this.config.logger?.transports?.find((t) => t.type === "file");
|
|
183
|
-
if (fileTransport && "path" in fileTransport) {
|
|
184
|
-
console.log(`\u{1F4CB} Logs available at: ${fileTransport.path}`);
|
|
185
|
-
}
|
|
186
186
|
} catch (error) {
|
|
187
187
|
this.logger.error("Failed to start DextoAgent", {
|
|
188
188
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -313,173 +313,88 @@ Either:
|
|
|
313
313
|
}
|
|
314
314
|
// ============= CORE AGENT FUNCTIONALITY =============
|
|
315
315
|
/**
|
|
316
|
-
*
|
|
317
|
-
*
|
|
316
|
+
* Process user input and return the response.
|
|
317
|
+
*
|
|
318
|
+
* @deprecated Use generate() or stream() instead for multi-image support.
|
|
319
|
+
* This method is kept for backward compatibility and only supports single image/file.
|
|
318
320
|
*
|
|
319
|
-
* @param textInput - The user's text message
|
|
320
|
-
* @param imageDataInput - Optional image data
|
|
321
|
-
* @param fileDataInput - Optional file data
|
|
321
|
+
* @param textInput - The user's text message
|
|
322
|
+
* @param imageDataInput - Optional single image data
|
|
323
|
+
* @param fileDataInput - Optional single file data
|
|
322
324
|
* @param sessionId - Session ID for the conversation (required)
|
|
323
|
-
* @param
|
|
324
|
-
* @returns Promise that resolves to the AI's response text
|
|
325
|
-
* @throws Error if processing fails
|
|
325
|
+
* @param _stream - Ignored (streaming is handled internally)
|
|
326
|
+
* @returns Promise that resolves to the AI's response text
|
|
326
327
|
*/
|
|
327
|
-
async run(textInput, imageDataInput, fileDataInput, sessionId,
|
|
328
|
-
|
|
329
|
-
if (
|
|
330
|
-
|
|
328
|
+
async run(textInput, imageDataInput, fileDataInput, sessionId, _stream = false) {
|
|
329
|
+
const parts = [];
|
|
330
|
+
if (textInput) {
|
|
331
|
+
parts.push({ type: "text", text: textInput });
|
|
331
332
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
333
|
+
if (imageDataInput) {
|
|
334
|
+
parts.push({
|
|
335
|
+
type: "image",
|
|
336
|
+
image: imageDataInput.image,
|
|
337
|
+
mimeType: imageDataInput.mimeType
|
|
338
|
+
});
|
|
337
339
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
340
|
+
if (fileDataInput) {
|
|
341
|
+
parts.push({
|
|
342
|
+
type: "file",
|
|
343
|
+
data: fileDataInput.data,
|
|
344
|
+
mimeType: fileDataInput.mimeType,
|
|
345
|
+
...fileDataInput.filename && { filename: fileDataInput.filename }
|
|
343
346
|
});
|
|
344
347
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
activeContext,
|
|
348
|
-
propagation.createBaggage(baggageEntries)
|
|
349
|
-
);
|
|
350
|
-
const verifyBaggage = propagation.getBaggage(updatedContext);
|
|
351
|
-
this.logger.debug(
|
|
352
|
-
`Baggage after setting sessionId: ${JSON.stringify(
|
|
353
|
-
Array.from(verifyBaggage?.getAllEntries() || [])
|
|
354
|
-
)}`
|
|
355
|
-
);
|
|
356
|
-
return await context.with(updatedContext, async () => {
|
|
357
|
-
try {
|
|
358
|
-
const llmConfig = this.stateManager.getLLMConfig(targetSessionId);
|
|
359
|
-
const validation = validateInputForLLM(
|
|
360
|
-
{
|
|
361
|
-
text: textInput,
|
|
362
|
-
...imageDataInput && { imageData: imageDataInput },
|
|
363
|
-
...fileDataInput && { fileData: fileDataInput }
|
|
364
|
-
},
|
|
365
|
-
{
|
|
366
|
-
provider: llmConfig.provider,
|
|
367
|
-
model: llmConfig.model
|
|
368
|
-
},
|
|
369
|
-
this.logger
|
|
370
|
-
);
|
|
371
|
-
ensureOk(validation, this.logger);
|
|
372
|
-
const session = await this.sessionManager.getSession(targetSessionId) || await this.sessionManager.createSession(targetSessionId);
|
|
373
|
-
this.logger.debug(
|
|
374
|
-
`DextoAgent.run: sessionId=${targetSessionId}, textLength=${textInput?.length ?? 0}, hasImage=${Boolean(
|
|
375
|
-
imageDataInput
|
|
376
|
-
)}, hasFile=${Boolean(fileDataInput)}`
|
|
377
|
-
);
|
|
378
|
-
let finalText = textInput;
|
|
379
|
-
let finalImageData = imageDataInput;
|
|
380
|
-
if (textInput && textInput.includes("@")) {
|
|
381
|
-
try {
|
|
382
|
-
const resources = await this.resourceManager.list();
|
|
383
|
-
const expansion = await expandMessageReferences(
|
|
384
|
-
textInput,
|
|
385
|
-
resources,
|
|
386
|
-
(uri) => this.resourceManager.read(uri)
|
|
387
|
-
);
|
|
388
|
-
if (expansion.unresolvedReferences.length > 0) {
|
|
389
|
-
const unresolvedNames = expansion.unresolvedReferences.map((ref) => ref.originalRef).join(", ");
|
|
390
|
-
this.logger.warn(
|
|
391
|
-
`Could not resolve ${expansion.unresolvedReferences.length} resource reference(s): ${unresolvedNames}`
|
|
392
|
-
);
|
|
393
|
-
}
|
|
394
|
-
const MAX_EXPANDED_SIZE = 5 * 1024 * 1024;
|
|
395
|
-
const expandedSize = Buffer.byteLength(expansion.expandedMessage, "utf-8");
|
|
396
|
-
if (expandedSize > MAX_EXPANDED_SIZE) {
|
|
397
|
-
this.logger.warn(
|
|
398
|
-
`Expanded message size (${(expandedSize / 1024 / 1024).toFixed(2)}MB) exceeds limit (${MAX_EXPANDED_SIZE / 1024 / 1024}MB). Content may be truncated.`
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
|
-
finalText = expansion.expandedMessage;
|
|
402
|
-
if (expansion.extractedImages.length > 0 && !imageDataInput) {
|
|
403
|
-
const firstImage = expansion.extractedImages[0];
|
|
404
|
-
if (firstImage) {
|
|
405
|
-
finalImageData = {
|
|
406
|
-
image: firstImage.image,
|
|
407
|
-
mimeType: firstImage.mimeType
|
|
408
|
-
};
|
|
409
|
-
this.logger.debug(
|
|
410
|
-
`Using extracted image: ${firstImage.name} (${firstImage.mimeType})`
|
|
411
|
-
);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
} catch (error) {
|
|
415
|
-
this.logger.error(
|
|
416
|
-
`Failed to expand resource references: ${error instanceof Error ? error.message : String(error)}. Continuing with original message.`
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
if (!finalText.trim() && !finalImageData && !fileDataInput) {
|
|
421
|
-
this.logger.warn(
|
|
422
|
-
"Resource expansion resulted in empty content. Using original message."
|
|
423
|
-
);
|
|
424
|
-
finalText = textInput;
|
|
425
|
-
}
|
|
426
|
-
const response = await session.run(
|
|
427
|
-
finalText,
|
|
428
|
-
finalImageData,
|
|
429
|
-
fileDataInput,
|
|
430
|
-
stream
|
|
431
|
-
);
|
|
432
|
-
this.sessionManager.incrementMessageCount(session.id).catch(
|
|
433
|
-
(error) => this.logger.warn(
|
|
434
|
-
`Failed to increment message count: ${error instanceof Error ? error.message : String(error)}`
|
|
435
|
-
)
|
|
436
|
-
);
|
|
437
|
-
return response;
|
|
438
|
-
} catch (error) {
|
|
439
|
-
this.logger.error(
|
|
440
|
-
`Error during DextoAgent.run: ${error instanceof Error ? error.message : JSON.stringify(error)}`
|
|
441
|
-
);
|
|
442
|
-
throw error;
|
|
443
|
-
}
|
|
444
|
-
});
|
|
348
|
+
const response = await this.generate(parts.length > 0 ? parts : textInput, sessionId);
|
|
349
|
+
return response.content;
|
|
445
350
|
}
|
|
446
351
|
/**
|
|
447
352
|
* Generate a complete response (waits for full completion).
|
|
448
353
|
* This is the recommended method for non-streaming use cases.
|
|
449
354
|
*
|
|
450
|
-
* @param message
|
|
451
|
-
* @param
|
|
355
|
+
* @param content String message or array of content parts (text, images, files)
|
|
356
|
+
* @param sessionId Session ID for the conversation
|
|
357
|
+
* @param options Optional configuration (signal for cancellation)
|
|
452
358
|
* @returns Promise that resolves to the complete response
|
|
453
359
|
*
|
|
454
360
|
* @example
|
|
455
361
|
* ```typescript
|
|
456
|
-
*
|
|
362
|
+
* // Simple text message
|
|
363
|
+
* const response = await agent.generate('What is 2+2?', 'session-1');
|
|
457
364
|
* console.log(response.content); // "4"
|
|
458
|
-
*
|
|
365
|
+
*
|
|
366
|
+
* // Multimodal with image
|
|
367
|
+
* const response = await agent.generate(
|
|
368
|
+
* [
|
|
369
|
+
* { type: 'text', text: 'Describe this image' },
|
|
370
|
+
* { type: 'image', image: base64Data, mimeType: 'image/png' }
|
|
371
|
+
* ],
|
|
372
|
+
* 'session-1'
|
|
373
|
+
* );
|
|
459
374
|
* ```
|
|
460
375
|
*/
|
|
461
|
-
async generate(
|
|
376
|
+
async generate(content, sessionId, options) {
|
|
462
377
|
const events = [];
|
|
463
|
-
for await (const event of await this.stream(
|
|
378
|
+
for await (const event of await this.stream(content, sessionId, options)) {
|
|
464
379
|
events.push(event);
|
|
465
380
|
}
|
|
466
|
-
const
|
|
467
|
-
(e) => e.
|
|
381
|
+
const fatalErrorEvent = events.find(
|
|
382
|
+
(e) => e.name === "llm:error" && e.recoverable !== true
|
|
468
383
|
);
|
|
469
|
-
if (
|
|
470
|
-
if (
|
|
471
|
-
throw
|
|
384
|
+
if (fatalErrorEvent) {
|
|
385
|
+
if (fatalErrorEvent.error instanceof DextoRuntimeError || fatalErrorEvent.error instanceof DextoValidationError) {
|
|
386
|
+
throw fatalErrorEvent.error;
|
|
472
387
|
}
|
|
473
|
-
const llmConfig = this.stateManager.getLLMConfig(
|
|
388
|
+
const llmConfig = this.stateManager.getLLMConfig(sessionId);
|
|
474
389
|
throw LLMError.generationFailed(
|
|
475
|
-
|
|
390
|
+
fatalErrorEvent.error.message,
|
|
476
391
|
llmConfig.provider,
|
|
477
392
|
llmConfig.model
|
|
478
393
|
);
|
|
479
394
|
}
|
|
480
|
-
const responseEvent = events.find((e) => e.
|
|
481
|
-
if (!responseEvent || responseEvent.
|
|
482
|
-
const llmConfig = this.stateManager.getLLMConfig(
|
|
395
|
+
const responseEvent = events.find((e) => e.name === "llm:response");
|
|
396
|
+
if (!responseEvent || responseEvent.name !== "llm:response") {
|
|
397
|
+
const llmConfig = this.stateManager.getLLMConfig(sessionId);
|
|
483
398
|
throw LLMError.generationFailed(
|
|
484
399
|
"Stream did not complete successfully - no response received",
|
|
485
400
|
llmConfig.provider,
|
|
@@ -487,10 +402,10 @@ Either:
|
|
|
487
402
|
);
|
|
488
403
|
}
|
|
489
404
|
const toolCallEvents = events.filter(
|
|
490
|
-
(e) => e.
|
|
405
|
+
(e) => e.name === "llm:tool-call"
|
|
491
406
|
);
|
|
492
407
|
const toolResultEvents = events.filter(
|
|
493
|
-
(e) => e.
|
|
408
|
+
(e) => e.name === "llm:tool-result"
|
|
494
409
|
);
|
|
495
410
|
const toolCalls = toolCallEvents.map((tc) => {
|
|
496
411
|
const toolResult = toolResultEvents.find((tr) => tr.callId === tc.callId);
|
|
@@ -504,7 +419,6 @@ Either:
|
|
|
504
419
|
} : void 0
|
|
505
420
|
};
|
|
506
421
|
});
|
|
507
|
-
const messageId = `msg_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
508
422
|
const defaultUsage = {
|
|
509
423
|
inputTokens: 0,
|
|
510
424
|
outputTokens: 0,
|
|
@@ -516,8 +430,7 @@ Either:
|
|
|
516
430
|
reasoning: responseEvent.reasoning,
|
|
517
431
|
usage,
|
|
518
432
|
toolCalls,
|
|
519
|
-
sessionId
|
|
520
|
-
messageId
|
|
433
|
+
sessionId
|
|
521
434
|
};
|
|
522
435
|
}
|
|
523
436
|
/**
|
|
@@ -531,45 +444,51 @@ Either:
|
|
|
531
444
|
* Events are forwarded directly from the AgentEventBus with no mapping layer,
|
|
532
445
|
* providing a unified event system across all API layers.
|
|
533
446
|
*
|
|
534
|
-
* @param message
|
|
535
|
-
* @param
|
|
536
|
-
* @
|
|
447
|
+
* @param content String message or array of content parts (text, images, files)
|
|
448
|
+
* @param sessionId Session ID for the conversation
|
|
449
|
+
* @param options Optional configuration (signal for cancellation)
|
|
450
|
+
* @returns AsyncIterator that yields StreamingEvent objects (core events with name property)
|
|
537
451
|
*
|
|
538
452
|
* @example
|
|
539
453
|
* ```typescript
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
* }
|
|
544
|
-
* if (event.type === 'llm:tool-call') {
|
|
545
|
-
* console.log(`\n[Using ${event.toolName}]\n`);
|
|
546
|
-
* }
|
|
454
|
+
* // Simple text
|
|
455
|
+
* for await (const event of await agent.stream('Write a poem', 'session-1')) {
|
|
456
|
+
* if (event.name === 'llm:chunk') process.stdout.write(event.content);
|
|
547
457
|
* }
|
|
458
|
+
*
|
|
459
|
+
* // Multimodal
|
|
460
|
+
* for await (const event of await agent.stream(
|
|
461
|
+
* [{ type: 'text', text: 'Describe this' }, { type: 'image', image: data, mimeType: 'image/png' }],
|
|
462
|
+
* 'session-1'
|
|
463
|
+
* )) { ... }
|
|
548
464
|
* ```
|
|
549
465
|
*/
|
|
550
|
-
async stream(
|
|
466
|
+
async stream(content, sessionId, options) {
|
|
551
467
|
this.ensureStarted();
|
|
552
|
-
if (!
|
|
553
|
-
throw
|
|
468
|
+
if (!sessionId) {
|
|
469
|
+
throw AgentError.apiValidationError("sessionId is required");
|
|
554
470
|
}
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
const fileData = options.fileData;
|
|
558
|
-
const signal = options.signal;
|
|
471
|
+
const signal = options?.signal;
|
|
472
|
+
let contentParts = typeof content === "string" ? [{ type: "text", text: content }] : [...content];
|
|
559
473
|
const eventQueue = [];
|
|
560
474
|
let completed = false;
|
|
561
|
-
let _streamError = null;
|
|
562
475
|
const controller = new AbortController();
|
|
563
476
|
const cleanupSignal = controller.signal;
|
|
477
|
+
this.activeStreamControllers.set(sessionId, controller);
|
|
478
|
+
setMaxListeners(30, cleanupSignal);
|
|
564
479
|
const listeners = [];
|
|
565
480
|
const cleanupListeners = () => {
|
|
566
481
|
if (listeners.length === 0) {
|
|
567
482
|
return;
|
|
568
483
|
}
|
|
569
484
|
for (const { event, listener } of listeners) {
|
|
570
|
-
this.agentEventBus.off(
|
|
485
|
+
this.agentEventBus.off(
|
|
486
|
+
event,
|
|
487
|
+
listener
|
|
488
|
+
);
|
|
571
489
|
}
|
|
572
490
|
listeners.length = 0;
|
|
491
|
+
this.activeStreamControllers.delete(sessionId);
|
|
573
492
|
};
|
|
574
493
|
if (signal) {
|
|
575
494
|
const abortHandler = () => {
|
|
@@ -578,49 +497,262 @@ Either:
|
|
|
578
497
|
};
|
|
579
498
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
580
499
|
}
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
500
|
+
const thinkingListener = (data) => {
|
|
501
|
+
if (data.sessionId !== sessionId) return;
|
|
502
|
+
eventQueue.push({ name: "llm:thinking", ...data });
|
|
503
|
+
};
|
|
504
|
+
this.agentEventBus.on("llm:thinking", thinkingListener, { signal: cleanupSignal });
|
|
505
|
+
listeners.push({ event: "llm:thinking", listener: thinkingListener });
|
|
506
|
+
const chunkListener = (data) => {
|
|
507
|
+
if (data.sessionId !== sessionId) return;
|
|
508
|
+
eventQueue.push({ name: "llm:chunk", ...data });
|
|
509
|
+
};
|
|
510
|
+
this.agentEventBus.on("llm:chunk", chunkListener, { signal: cleanupSignal });
|
|
511
|
+
listeners.push({ event: "llm:chunk", listener: chunkListener });
|
|
512
|
+
const responseListener = (data) => {
|
|
513
|
+
if (data.sessionId !== sessionId) return;
|
|
514
|
+
eventQueue.push({ name: "llm:response", ...data });
|
|
515
|
+
};
|
|
516
|
+
this.agentEventBus.on("llm:response", responseListener, { signal: cleanupSignal });
|
|
517
|
+
listeners.push({ event: "llm:response", listener: responseListener });
|
|
518
|
+
const toolCallListener = (data) => {
|
|
519
|
+
if (data.sessionId !== sessionId) return;
|
|
520
|
+
eventQueue.push({ name: "llm:tool-call", ...data });
|
|
521
|
+
};
|
|
522
|
+
this.agentEventBus.on("llm:tool-call", toolCallListener, { signal: cleanupSignal });
|
|
523
|
+
listeners.push({ event: "llm:tool-call", listener: toolCallListener });
|
|
524
|
+
const toolResultListener = (data) => {
|
|
525
|
+
if (data.sessionId !== sessionId) return;
|
|
526
|
+
eventQueue.push({ name: "llm:tool-result", ...data });
|
|
527
|
+
};
|
|
528
|
+
this.agentEventBus.on("llm:tool-result", toolResultListener, { signal: cleanupSignal });
|
|
529
|
+
listeners.push({ event: "llm:tool-result", listener: toolResultListener });
|
|
530
|
+
const errorListener = (data) => {
|
|
531
|
+
if (data.sessionId !== sessionId) return;
|
|
532
|
+
eventQueue.push({ name: "llm:error", ...data });
|
|
533
|
+
if (!data.recoverable) {
|
|
534
|
+
completed = true;
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
this.agentEventBus.on("llm:error", errorListener, { signal: cleanupSignal });
|
|
538
|
+
listeners.push({ event: "llm:error", listener: errorListener });
|
|
539
|
+
const unsupportedInputListener = (data) => {
|
|
540
|
+
if (data.sessionId !== sessionId) return;
|
|
541
|
+
eventQueue.push({ name: "llm:unsupported-input", ...data });
|
|
542
|
+
};
|
|
543
|
+
this.agentEventBus.on("llm:unsupported-input", unsupportedInputListener, {
|
|
544
|
+
signal: cleanupSignal
|
|
545
|
+
});
|
|
546
|
+
listeners.push({ event: "llm:unsupported-input", listener: unsupportedInputListener });
|
|
547
|
+
const titleUpdatedListener = (data) => {
|
|
548
|
+
if (data.sessionId !== sessionId) return;
|
|
549
|
+
eventQueue.push({ name: "session:title-updated", ...data });
|
|
550
|
+
};
|
|
551
|
+
this.agentEventBus.on("session:title-updated", titleUpdatedListener, {
|
|
552
|
+
signal: cleanupSignal
|
|
553
|
+
});
|
|
554
|
+
listeners.push({ event: "session:title-updated", listener: titleUpdatedListener });
|
|
555
|
+
const approvalRequestListener = (data) => {
|
|
556
|
+
if (data.sessionId !== sessionId) return;
|
|
557
|
+
eventQueue.push({ name: "approval:request", ...data });
|
|
558
|
+
};
|
|
559
|
+
this.agentEventBus.on("approval:request", approvalRequestListener, {
|
|
560
|
+
signal: cleanupSignal
|
|
561
|
+
});
|
|
562
|
+
listeners.push({ event: "approval:request", listener: approvalRequestListener });
|
|
563
|
+
const approvalResponseListener = (data) => {
|
|
564
|
+
if (data.sessionId !== sessionId) return;
|
|
565
|
+
eventQueue.push({ name: "approval:response", ...data });
|
|
566
|
+
};
|
|
567
|
+
this.agentEventBus.on("approval:response", approvalResponseListener, {
|
|
568
|
+
signal: cleanupSignal
|
|
569
|
+
});
|
|
570
|
+
listeners.push({ event: "approval:response", listener: approvalResponseListener });
|
|
571
|
+
const toolRunningListener = (data) => {
|
|
572
|
+
if (data.sessionId !== sessionId) return;
|
|
573
|
+
eventQueue.push({ name: "tool:running", ...data });
|
|
574
|
+
};
|
|
575
|
+
this.agentEventBus.on("tool:running", toolRunningListener, {
|
|
576
|
+
signal: cleanupSignal
|
|
577
|
+
});
|
|
578
|
+
listeners.push({ event: "tool:running", listener: toolRunningListener });
|
|
579
|
+
const messageQueuedListener = (data) => {
|
|
580
|
+
if (data.sessionId !== sessionId) return;
|
|
581
|
+
eventQueue.push({ name: "message:queued", ...data });
|
|
582
|
+
};
|
|
583
|
+
this.agentEventBus.on("message:queued", messageQueuedListener, {
|
|
584
|
+
signal: cleanupSignal
|
|
585
|
+
});
|
|
586
|
+
listeners.push({ event: "message:queued", listener: messageQueuedListener });
|
|
587
|
+
const messageDequeuedListener = (data) => {
|
|
588
|
+
if (data.sessionId !== sessionId) return;
|
|
589
|
+
eventQueue.push({ name: "message:dequeued", ...data });
|
|
590
|
+
};
|
|
591
|
+
this.agentEventBus.on("message:dequeued", messageDequeuedListener, {
|
|
592
|
+
signal: cleanupSignal
|
|
593
|
+
});
|
|
594
|
+
listeners.push({ event: "message:dequeued", listener: messageDequeuedListener });
|
|
595
|
+
const runCompleteListener = (data) => {
|
|
596
|
+
if (data.sessionId !== sessionId) return;
|
|
597
|
+
eventQueue.push({ name: "run:complete", ...data });
|
|
607
598
|
completed = true;
|
|
608
|
-
|
|
609
|
-
|
|
599
|
+
};
|
|
600
|
+
this.agentEventBus.on("run:complete", runCompleteListener, {
|
|
601
|
+
signal: cleanupSignal
|
|
602
|
+
});
|
|
603
|
+
listeners.push({ event: "run:complete", listener: runCompleteListener });
|
|
604
|
+
(async () => {
|
|
605
|
+
const activeContext = context.active();
|
|
606
|
+
const activeSpan = trace.getActiveSpan();
|
|
607
|
+
if (activeSpan) {
|
|
608
|
+
activeSpan.setAttribute("sessionId", sessionId);
|
|
609
|
+
}
|
|
610
|
+
const existingBaggage = propagation.getBaggage(activeContext);
|
|
611
|
+
const baggageEntries = {};
|
|
612
|
+
if (existingBaggage) {
|
|
613
|
+
existingBaggage.getAllEntries().forEach(([key, entry]) => {
|
|
614
|
+
baggageEntries[key] = { ...entry };
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
baggageEntries.sessionId = { ...baggageEntries.sessionId, value: sessionId };
|
|
618
|
+
const updatedContext = propagation.setBaggage(
|
|
619
|
+
activeContext,
|
|
620
|
+
propagation.createBaggage(baggageEntries)
|
|
610
621
|
);
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
622
|
+
await context.with(updatedContext, async () => {
|
|
623
|
+
try {
|
|
624
|
+
const llmConfig = this.stateManager.getLLMConfig(sessionId);
|
|
625
|
+
const textParts = contentParts.filter(
|
|
626
|
+
(p) => p.type === "text"
|
|
627
|
+
);
|
|
628
|
+
const textContent = textParts.map((p) => p.text).join("\n");
|
|
629
|
+
const imageParts = contentParts.filter(
|
|
630
|
+
(p) => p.type === "image"
|
|
631
|
+
);
|
|
632
|
+
const fileParts = contentParts.filter(
|
|
633
|
+
(p) => p.type === "file"
|
|
634
|
+
);
|
|
635
|
+
this.logger.debug(
|
|
636
|
+
`DextoAgent.stream: sessionId=${sessionId}, textLength=${textContent?.length ?? 0}, imageCount=${imageParts.length}, fileCount=${fileParts.length}`
|
|
637
|
+
);
|
|
638
|
+
const textValidation = validateInputForLLM(
|
|
639
|
+
{ text: textContent },
|
|
640
|
+
{ provider: llmConfig.provider, model: llmConfig.model },
|
|
641
|
+
this.logger
|
|
642
|
+
);
|
|
643
|
+
ensureOk(textValidation, this.logger);
|
|
644
|
+
for (const imagePart of imageParts) {
|
|
645
|
+
const imageValidation = validateInputForLLM(
|
|
646
|
+
{
|
|
647
|
+
imageData: {
|
|
648
|
+
image: typeof imagePart.image === "string" ? imagePart.image : imagePart.image.toString(),
|
|
649
|
+
mimeType: imagePart.mimeType || "image/png"
|
|
650
|
+
}
|
|
651
|
+
},
|
|
652
|
+
{ provider: llmConfig.provider, model: llmConfig.model },
|
|
653
|
+
this.logger
|
|
654
|
+
);
|
|
655
|
+
ensureOk(imageValidation, this.logger);
|
|
656
|
+
}
|
|
657
|
+
for (const filePart of fileParts) {
|
|
658
|
+
const fileValidation = validateInputForLLM(
|
|
659
|
+
{
|
|
660
|
+
fileData: {
|
|
661
|
+
data: typeof filePart.data === "string" ? filePart.data : filePart.data.toString(),
|
|
662
|
+
mimeType: filePart.mimeType
|
|
663
|
+
}
|
|
664
|
+
},
|
|
665
|
+
{ provider: llmConfig.provider, model: llmConfig.model },
|
|
666
|
+
this.logger
|
|
667
|
+
);
|
|
668
|
+
ensureOk(fileValidation, this.logger);
|
|
669
|
+
}
|
|
670
|
+
if (textContent.includes("@")) {
|
|
671
|
+
try {
|
|
672
|
+
const resources = await this.resourceManager.list();
|
|
673
|
+
const expansion = await expandMessageReferences(
|
|
674
|
+
textContent,
|
|
675
|
+
resources,
|
|
676
|
+
(uri) => this.resourceManager.read(uri)
|
|
677
|
+
);
|
|
678
|
+
if (expansion.unresolvedReferences.length > 0) {
|
|
679
|
+
const unresolvedNames = expansion.unresolvedReferences.map((ref) => ref.originalRef).join(", ");
|
|
680
|
+
this.logger.warn(
|
|
681
|
+
`Could not resolve ${expansion.unresolvedReferences.length} resource reference(s): ${unresolvedNames}`
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
const MAX_EXPANDED_SIZE = 5 * 1024 * 1024;
|
|
685
|
+
const expandedSize = Buffer.byteLength(
|
|
686
|
+
expansion.expandedMessage,
|
|
687
|
+
"utf-8"
|
|
688
|
+
);
|
|
689
|
+
if (expandedSize > MAX_EXPANDED_SIZE) {
|
|
690
|
+
this.logger.warn(
|
|
691
|
+
`Expanded message size (${(expandedSize / 1024 / 1024).toFixed(2)}MB) exceeds limit (${MAX_EXPANDED_SIZE / 1024 / 1024}MB). Content may be truncated.`
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
contentParts = contentParts.filter((p) => p.type !== "text");
|
|
695
|
+
if (expansion.expandedMessage.trim()) {
|
|
696
|
+
contentParts.unshift({
|
|
697
|
+
type: "text",
|
|
698
|
+
text: expansion.expandedMessage
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
for (const img of expansion.extractedImages) {
|
|
702
|
+
contentParts.push({
|
|
703
|
+
type: "image",
|
|
704
|
+
image: img.image,
|
|
705
|
+
mimeType: img.mimeType
|
|
706
|
+
});
|
|
707
|
+
this.logger.debug(
|
|
708
|
+
`Added extracted image: ${img.name} (${img.mimeType})`
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
} catch (error) {
|
|
712
|
+
this.logger.error(
|
|
713
|
+
`Failed to expand resource references: ${error instanceof Error ? error.message : String(error)}. Continuing with original message.`
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
const hasTextContent = contentParts.some(
|
|
718
|
+
(p) => p.type === "text" && p.text.trim()
|
|
719
|
+
);
|
|
720
|
+
const hasMediaContent = contentParts.some(
|
|
721
|
+
(p) => p.type === "image" || p.type === "file"
|
|
722
|
+
);
|
|
723
|
+
if (!hasTextContent && !hasMediaContent) {
|
|
724
|
+
this.logger.warn(
|
|
725
|
+
"Resource expansion resulted in empty content. Using original message."
|
|
726
|
+
);
|
|
727
|
+
contentParts = [{ type: "text", text: textContent }];
|
|
728
|
+
}
|
|
729
|
+
const session = await this.sessionManager.getSession(sessionId) || await this.sessionManager.createSession(sessionId);
|
|
730
|
+
await session.stream(contentParts, signal ? { signal } : void 0);
|
|
731
|
+
this.sessionManager.incrementMessageCount(session.id).catch(
|
|
732
|
+
(error) => this.logger.warn(
|
|
733
|
+
`Failed to increment message count: ${error instanceof Error ? error.message : String(error)}`
|
|
734
|
+
)
|
|
735
|
+
);
|
|
736
|
+
} catch (err) {
|
|
737
|
+
const error = err instanceof DextoRuntimeError || err instanceof DextoValidationError ? err : err instanceof Error ? err : AgentError.streamFailed(String(err));
|
|
738
|
+
completed = true;
|
|
739
|
+
this.logger.error(`Error in DextoAgent.stream: ${error.message}`);
|
|
740
|
+
const errorEvent = {
|
|
741
|
+
name: "llm:error",
|
|
742
|
+
error,
|
|
743
|
+
recoverable: false,
|
|
744
|
+
context: "run_failed",
|
|
745
|
+
sessionId
|
|
746
|
+
};
|
|
747
|
+
eventQueue.push(errorEvent);
|
|
748
|
+
}
|
|
617
749
|
});
|
|
618
|
-
});
|
|
750
|
+
})();
|
|
619
751
|
const iterator = {
|
|
620
752
|
async next() {
|
|
621
753
|
while (!completed && eventQueue.length === 0) {
|
|
622
754
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
623
|
-
if (signal?.aborted) {
|
|
755
|
+
if (signal?.aborted || cleanupSignal.aborted) {
|
|
624
756
|
cleanupListeners();
|
|
625
757
|
controller.abort();
|
|
626
758
|
return { done: true, value: void 0 };
|
|
@@ -648,6 +780,73 @@ Either:
|
|
|
648
780
|
};
|
|
649
781
|
return iterator;
|
|
650
782
|
}
|
|
783
|
+
/**
|
|
784
|
+
* Check if a session is currently processing a message.
|
|
785
|
+
* @param sessionId Session id
|
|
786
|
+
* @returns true if the session is busy processing; false otherwise
|
|
787
|
+
*/
|
|
788
|
+
async isSessionBusy(sessionId) {
|
|
789
|
+
this.ensureStarted();
|
|
790
|
+
const session = await this.sessionManager.getSession(sessionId, false);
|
|
791
|
+
return session?.isBusy() ?? false;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Queue a message for processing when a session is busy.
|
|
795
|
+
* The message will be injected into the conversation when the current turn completes.
|
|
796
|
+
*
|
|
797
|
+
* @param sessionId Session id
|
|
798
|
+
* @param message The user message to queue
|
|
799
|
+
* @returns Queue position and message ID
|
|
800
|
+
* @throws Error if session doesn't support message queueing
|
|
801
|
+
*/
|
|
802
|
+
async queueMessage(sessionId, message) {
|
|
803
|
+
this.ensureStarted();
|
|
804
|
+
const session = await this.sessionManager.getSession(sessionId, false);
|
|
805
|
+
if (!session) {
|
|
806
|
+
throw SessionError.notFound(sessionId);
|
|
807
|
+
}
|
|
808
|
+
return session.queueMessage(message);
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Get all queued messages for a session.
|
|
812
|
+
* @param sessionId Session id
|
|
813
|
+
* @returns Array of queued messages
|
|
814
|
+
*/
|
|
815
|
+
async getQueuedMessages(sessionId) {
|
|
816
|
+
this.ensureStarted();
|
|
817
|
+
const session = await this.sessionManager.getSession(sessionId, false);
|
|
818
|
+
if (!session) {
|
|
819
|
+
throw SessionError.notFound(sessionId);
|
|
820
|
+
}
|
|
821
|
+
return session.getQueuedMessages();
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Remove a queued message.
|
|
825
|
+
* @param sessionId Session id
|
|
826
|
+
* @param messageId The ID of the queued message to remove
|
|
827
|
+
* @returns true if message was found and removed, false otherwise
|
|
828
|
+
*/
|
|
829
|
+
async removeQueuedMessage(sessionId, messageId) {
|
|
830
|
+
this.ensureStarted();
|
|
831
|
+
const session = await this.sessionManager.getSession(sessionId, false);
|
|
832
|
+
if (!session) {
|
|
833
|
+
throw SessionError.notFound(sessionId);
|
|
834
|
+
}
|
|
835
|
+
return session.removeQueuedMessage(messageId);
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Clear all queued messages for a session.
|
|
839
|
+
* @param sessionId Session id
|
|
840
|
+
* @returns Number of messages that were cleared
|
|
841
|
+
*/
|
|
842
|
+
async clearMessageQueue(sessionId) {
|
|
843
|
+
this.ensureStarted();
|
|
844
|
+
const session = await this.sessionManager.getSession(sessionId, false);
|
|
845
|
+
if (!session) {
|
|
846
|
+
throw SessionError.notFound(sessionId);
|
|
847
|
+
}
|
|
848
|
+
return session.clearMessageQueue();
|
|
849
|
+
}
|
|
651
850
|
/**
|
|
652
851
|
* Cancels the currently running turn for a session.
|
|
653
852
|
* Safe to call even if no run is in progress.
|
|
@@ -657,13 +856,20 @@ Either:
|
|
|
657
856
|
async cancel(sessionId) {
|
|
658
857
|
this.ensureStarted();
|
|
659
858
|
if (!sessionId || typeof sessionId !== "string") {
|
|
660
|
-
throw
|
|
859
|
+
throw AgentError.apiValidationError(
|
|
860
|
+
"sessionId is required and must be a non-empty string"
|
|
861
|
+
);
|
|
862
|
+
}
|
|
863
|
+
const streamController = this.activeStreamControllers.get(sessionId);
|
|
864
|
+
if (streamController) {
|
|
865
|
+
streamController.abort();
|
|
866
|
+
this.activeStreamControllers.delete(sessionId);
|
|
661
867
|
}
|
|
662
868
|
const existing = await this.sessionManager.getSession(sessionId, false);
|
|
663
869
|
if (existing) {
|
|
664
870
|
return existing.cancel();
|
|
665
871
|
}
|
|
666
|
-
return
|
|
872
|
+
return !!streamController;
|
|
667
873
|
}
|
|
668
874
|
// ============= SESSION MANAGEMENT =============
|
|
669
875
|
/**
|
|
@@ -770,7 +976,6 @@ Either:
|
|
|
770
976
|
const llmConfig = this.getEffectiveConfig(sessionId).llm;
|
|
771
977
|
const result = await generateSessionTitle(
|
|
772
978
|
llmConfig,
|
|
773
|
-
llmConfig.router,
|
|
774
979
|
this.toolManager,
|
|
775
980
|
this.systemPromptManager,
|
|
776
981
|
this.resourceManager,
|
|
@@ -853,7 +1058,9 @@ Either:
|
|
|
853
1058
|
async resetConversation(sessionId) {
|
|
854
1059
|
this.ensureStarted();
|
|
855
1060
|
if (!sessionId || typeof sessionId !== "string") {
|
|
856
|
-
throw
|
|
1061
|
+
throw AgentError.apiValidationError(
|
|
1062
|
+
"sessionId is required and must be a non-empty string"
|
|
1063
|
+
);
|
|
857
1064
|
}
|
|
858
1065
|
try {
|
|
859
1066
|
await this.sessionManager.resetSession(sessionId);
|
|
@@ -868,6 +1075,37 @@ Either:
|
|
|
868
1075
|
throw error;
|
|
869
1076
|
}
|
|
870
1077
|
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Clears the context window for a session without deleting history.
|
|
1080
|
+
*
|
|
1081
|
+
* This adds a "context clear" marker to the conversation history. When the
|
|
1082
|
+
* context is loaded for LLM, messages before this marker are filtered out
|
|
1083
|
+
* (via filterCompacted). The full history remains in the database for
|
|
1084
|
+
* review via /resume or session history.
|
|
1085
|
+
*
|
|
1086
|
+
* Use this for /clear command - it preserves history but gives a fresh
|
|
1087
|
+
* context window to the LLM.
|
|
1088
|
+
*
|
|
1089
|
+
* @param sessionId Session ID (required)
|
|
1090
|
+
*/
|
|
1091
|
+
async clearContext(sessionId) {
|
|
1092
|
+
this.ensureStarted();
|
|
1093
|
+
if (!sessionId || typeof sessionId !== "string") {
|
|
1094
|
+
throw AgentError.apiValidationError(
|
|
1095
|
+
"sessionId is required and must be a non-empty string"
|
|
1096
|
+
);
|
|
1097
|
+
}
|
|
1098
|
+
const session = await this.sessionManager.getSession(sessionId);
|
|
1099
|
+
if (!session) {
|
|
1100
|
+
throw SessionError.notFound(sessionId);
|
|
1101
|
+
}
|
|
1102
|
+
const contextManager = session.getContextManager();
|
|
1103
|
+
await contextManager.clearContext();
|
|
1104
|
+
this.logger.info(`Context cleared for session: ${sessionId}`);
|
|
1105
|
+
this.agentEventBus.emit("context:cleared", {
|
|
1106
|
+
sessionId
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
871
1109
|
// ============= LLM MANAGEMENT =============
|
|
872
1110
|
/**
|
|
873
1111
|
* Gets the current LLM configuration with all defaults applied.
|
|
@@ -882,7 +1120,7 @@ Either:
|
|
|
882
1120
|
* This is a comprehensive method that handles ALL validation, configuration building, and switching internally.
|
|
883
1121
|
*
|
|
884
1122
|
* Design:
|
|
885
|
-
* - Input: Partial<LLMConfig> (allows optional fields like maxIterations
|
|
1123
|
+
* - Input: Partial<LLMConfig> (allows optional fields like maxIterations?)
|
|
886
1124
|
* - Output: LLMConfig (user-friendly type with all defaults applied)
|
|
887
1125
|
*
|
|
888
1126
|
* Key features:
|
|
@@ -907,8 +1145,8 @@ Either:
|
|
|
907
1145
|
* // Switch to a different provider with explicit API key
|
|
908
1146
|
* await agent.switchLLM({ provider: 'anthropic', model: 'claude-4-sonnet-20250514', apiKey: 'sk-ant-...' });
|
|
909
1147
|
*
|
|
910
|
-
* // Switch with
|
|
911
|
-
* await agent.switchLLM({ provider: 'anthropic', model: 'claude-4-sonnet-20250514'
|
|
1148
|
+
* // Switch with session options
|
|
1149
|
+
* await agent.switchLLM({ provider: 'anthropic', model: 'claude-4-sonnet-20250514' }, 'user-123');
|
|
912
1150
|
*
|
|
913
1151
|
* // Switch for all sessions
|
|
914
1152
|
* await agent.switchLLM({ model: 'gpt-5' }, '*');
|
|
@@ -1060,19 +1298,23 @@ Either:
|
|
|
1060
1298
|
}
|
|
1061
1299
|
// ============= MCP SERVER MANAGEMENT =============
|
|
1062
1300
|
/**
|
|
1063
|
-
*
|
|
1301
|
+
* Adds a new MCP server to the runtime configuration and connects it if enabled.
|
|
1064
1302
|
* This method handles validation, state management, and establishing the connection.
|
|
1065
1303
|
*
|
|
1066
|
-
* @param name The name of the server to
|
|
1304
|
+
* @param name The name of the server to add.
|
|
1067
1305
|
* @param config The configuration object for the server.
|
|
1068
1306
|
* @throws DextoError if validation fails or connection fails
|
|
1069
1307
|
*/
|
|
1070
|
-
async
|
|
1308
|
+
async addMcpServer(name, config) {
|
|
1071
1309
|
this.ensureStarted();
|
|
1072
1310
|
const existingServerNames = Object.keys(this.stateManager.getRuntimeConfig().mcpServers);
|
|
1073
1311
|
const validation = resolveAndValidateMcpServerConfig(name, config, existingServerNames);
|
|
1074
1312
|
const validatedConfig = ensureOk(validation, this.logger);
|
|
1075
|
-
this.stateManager.
|
|
1313
|
+
this.stateManager.setMcpServer(name, validatedConfig);
|
|
1314
|
+
if (validatedConfig.enabled === false) {
|
|
1315
|
+
this.logger.info(`MCP server '${name}' added but not connected (disabled)`);
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
1076
1318
|
try {
|
|
1077
1319
|
await this.mcpManager.connectServer(name, validatedConfig);
|
|
1078
1320
|
await this.toolManager.refresh();
|
|
@@ -1084,9 +1326,7 @@ Either:
|
|
|
1084
1326
|
tools: Object.keys(await this.toolManager.getAllTools()),
|
|
1085
1327
|
source: "mcp"
|
|
1086
1328
|
});
|
|
1087
|
-
this.logger.info(
|
|
1088
|
-
`DextoAgent: Successfully added and connected to MCP server '${name}'.`
|
|
1089
|
-
);
|
|
1329
|
+
this.logger.info(`MCP server '${name}' added and connected successfully`);
|
|
1090
1330
|
const warnings = validation.issues.filter((i) => i.severity === "warning");
|
|
1091
1331
|
if (warnings.length > 0) {
|
|
1092
1332
|
this.logger.warn(
|
|
@@ -1095,9 +1335,7 @@ Either:
|
|
|
1095
1335
|
}
|
|
1096
1336
|
} catch (error) {
|
|
1097
1337
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1098
|
-
this.logger.error(
|
|
1099
|
-
`DextoAgent: Failed to connect to MCP server '${name}': ${errorMessage}`
|
|
1100
|
-
);
|
|
1338
|
+
this.logger.error(`Failed to connect MCP server '${name}': ${errorMessage}`);
|
|
1101
1339
|
this.stateManager.removeMcpServer(name);
|
|
1102
1340
|
this.agentEventBus.emit("mcp:server-connected", {
|
|
1103
1341
|
name,
|
|
@@ -1108,14 +1346,81 @@ Either:
|
|
|
1108
1346
|
}
|
|
1109
1347
|
}
|
|
1110
1348
|
/**
|
|
1111
|
-
*
|
|
1349
|
+
* @deprecated Use `addMcpServer` instead. This method will be removed in a future version.
|
|
1350
|
+
*/
|
|
1351
|
+
async connectMcpServer(name, config) {
|
|
1352
|
+
return this.addMcpServer(name, config);
|
|
1353
|
+
}
|
|
1354
|
+
/**
|
|
1355
|
+
* Enables a disabled MCP server and connects it.
|
|
1356
|
+
* Updates the runtime state to enabled=true and establishes the connection.
|
|
1357
|
+
*
|
|
1358
|
+
* @param name The name of the server to enable.
|
|
1359
|
+
* @throws MCPError if server is not found or connection fails
|
|
1360
|
+
*/
|
|
1361
|
+
async enableMcpServer(name) {
|
|
1362
|
+
this.ensureStarted();
|
|
1363
|
+
const currentConfig = this.stateManager.getRuntimeConfig().mcpServers[name];
|
|
1364
|
+
if (!currentConfig) {
|
|
1365
|
+
throw MCPError.serverNotFound(name);
|
|
1366
|
+
}
|
|
1367
|
+
const updatedConfig = { ...currentConfig, enabled: true };
|
|
1368
|
+
this.stateManager.setMcpServer(name, updatedConfig);
|
|
1369
|
+
try {
|
|
1370
|
+
await this.mcpManager.connectServer(name, updatedConfig);
|
|
1371
|
+
await this.toolManager.refresh();
|
|
1372
|
+
this.agentEventBus.emit("mcp:server-connected", { name, success: true });
|
|
1373
|
+
this.logger.info(`MCP server '${name}' enabled and connected`);
|
|
1374
|
+
} catch (error) {
|
|
1375
|
+
this.stateManager.setMcpServer(name, currentConfig);
|
|
1376
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1377
|
+
this.logger.error(`Failed to enable MCP server '${name}': ${errorMessage}`);
|
|
1378
|
+
throw MCPError.connectionFailed(name, errorMessage);
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
/**
|
|
1382
|
+
* Disables an MCP server and disconnects it.
|
|
1383
|
+
* Updates the runtime state to enabled=false and closes the connection.
|
|
1384
|
+
*
|
|
1385
|
+
* @param name The name of the server to disable.
|
|
1386
|
+
* @throws MCPError if server is not found or disconnect fails
|
|
1387
|
+
*/
|
|
1388
|
+
async disableMcpServer(name) {
|
|
1389
|
+
this.ensureStarted();
|
|
1390
|
+
const currentConfig = this.stateManager.getRuntimeConfig().mcpServers[name];
|
|
1391
|
+
if (!currentConfig) {
|
|
1392
|
+
throw MCPError.serverNotFound(name);
|
|
1393
|
+
}
|
|
1394
|
+
const updatedConfig = { ...currentConfig, enabled: false };
|
|
1395
|
+
this.stateManager.setMcpServer(name, updatedConfig);
|
|
1396
|
+
try {
|
|
1397
|
+
await this.mcpManager.removeClient(name);
|
|
1398
|
+
await this.toolManager.refresh();
|
|
1399
|
+
this.logger.info(`MCP server '${name}' disabled and disconnected`);
|
|
1400
|
+
} catch (error) {
|
|
1401
|
+
this.stateManager.setMcpServer(name, currentConfig);
|
|
1402
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1403
|
+
this.logger.error(`Failed to disable MCP server '${name}': ${errorMessage}`);
|
|
1404
|
+
throw MCPError.disconnectionFailed(name, errorMessage);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
/**
|
|
1408
|
+
* Removes and disconnects an MCP server completely.
|
|
1409
|
+
* Use this for deleting a server - removes from both runtime state and disconnects.
|
|
1112
1410
|
* @param name The name of the server to remove.
|
|
1411
|
+
* @throws MCPError if disconnection fails
|
|
1113
1412
|
*/
|
|
1114
1413
|
async removeMcpServer(name) {
|
|
1115
1414
|
this.ensureStarted();
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1415
|
+
try {
|
|
1416
|
+
await this.mcpManager.removeClient(name);
|
|
1417
|
+
this.stateManager.removeMcpServer(name);
|
|
1418
|
+
await this.toolManager.refresh();
|
|
1419
|
+
} catch (error) {
|
|
1420
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1421
|
+
this.logger.error(`Failed to remove MCP server '${name}': ${errorMessage}`);
|
|
1422
|
+
throw MCPError.disconnectionFailed(name, errorMessage);
|
|
1423
|
+
}
|
|
1119
1424
|
}
|
|
1120
1425
|
/**
|
|
1121
1426
|
* Restarts an MCP server by disconnecting and reconnecting with its original configuration.
|
|
@@ -1148,13 +1453,18 @@ Either:
|
|
|
1148
1453
|
/**
|
|
1149
1454
|
* Executes a tool from any source (MCP servers, custom tools, or internal tools).
|
|
1150
1455
|
* This is the unified interface for tool execution that can handle all tool types.
|
|
1456
|
+
*
|
|
1457
|
+
* Note: This is for direct/programmatic tool execution outside of LLM flow.
|
|
1458
|
+
* A toolCallId is generated automatically for tracking purposes.
|
|
1459
|
+
*
|
|
1151
1460
|
* @param toolName The name of the tool to execute
|
|
1152
1461
|
* @param args The arguments to pass to the tool
|
|
1153
1462
|
* @returns The result of the tool execution
|
|
1154
1463
|
*/
|
|
1155
1464
|
async executeTool(toolName, args) {
|
|
1156
1465
|
this.ensureStarted();
|
|
1157
|
-
|
|
1466
|
+
const toolCallId = `direct-${randomUUID()}`;
|
|
1467
|
+
return await this.toolManager.executeTool(toolName, args, toolCallId);
|
|
1158
1468
|
}
|
|
1159
1469
|
/**
|
|
1160
1470
|
* Gets all available tools from all connected MCP servers.
|
|
@@ -1192,6 +1502,79 @@ Either:
|
|
|
1192
1502
|
this.ensureStarted();
|
|
1193
1503
|
return this.mcpManager.getFailedConnections();
|
|
1194
1504
|
}
|
|
1505
|
+
/**
|
|
1506
|
+
* Gets the connection status of a single MCP server.
|
|
1507
|
+
* @param name The server name
|
|
1508
|
+
* @returns The connection status, or undefined if server not configured
|
|
1509
|
+
*
|
|
1510
|
+
* TODO: Move to MCPManager once it has access to server configs (enabled state).
|
|
1511
|
+
* Currently here because MCPManager only tracks connections, not config.
|
|
1512
|
+
*/
|
|
1513
|
+
getMcpServerStatus(name) {
|
|
1514
|
+
this.ensureStarted();
|
|
1515
|
+
const config = this.stateManager.getRuntimeConfig();
|
|
1516
|
+
const serverConfig = config.mcpServers[name];
|
|
1517
|
+
if (!serverConfig) return void 0;
|
|
1518
|
+
const enabled = serverConfig.enabled !== false;
|
|
1519
|
+
const connectedClients = this.mcpManager.getClients();
|
|
1520
|
+
const failedConnections = this.mcpManager.getFailedConnections();
|
|
1521
|
+
let status;
|
|
1522
|
+
if (!enabled) {
|
|
1523
|
+
status = "disconnected";
|
|
1524
|
+
} else if (connectedClients.has(name)) {
|
|
1525
|
+
status = "connected";
|
|
1526
|
+
} else {
|
|
1527
|
+
status = "error";
|
|
1528
|
+
}
|
|
1529
|
+
const result = {
|
|
1530
|
+
name,
|
|
1531
|
+
type: serverConfig.type,
|
|
1532
|
+
enabled,
|
|
1533
|
+
status
|
|
1534
|
+
};
|
|
1535
|
+
if (failedConnections[name]) {
|
|
1536
|
+
result.error = failedConnections[name];
|
|
1537
|
+
}
|
|
1538
|
+
return result;
|
|
1539
|
+
}
|
|
1540
|
+
/**
|
|
1541
|
+
* Gets all configured MCP servers with their connection status.
|
|
1542
|
+
* Centralizes the status computation logic used by CLI, server, and webui.
|
|
1543
|
+
* @returns Array of server info with computed status
|
|
1544
|
+
*
|
|
1545
|
+
* TODO: Move to MCPManager once it has access to server configs (enabled state).
|
|
1546
|
+
* Currently here because MCPManager only tracks connections, not config.
|
|
1547
|
+
*/
|
|
1548
|
+
getMcpServersWithStatus() {
|
|
1549
|
+
this.ensureStarted();
|
|
1550
|
+
const config = this.stateManager.getRuntimeConfig();
|
|
1551
|
+
const mcpServers = config.mcpServers || {};
|
|
1552
|
+
const connectedClients = this.mcpManager.getClients();
|
|
1553
|
+
const failedConnections = this.mcpManager.getFailedConnections();
|
|
1554
|
+
const servers = [];
|
|
1555
|
+
for (const [name, serverConfig] of Object.entries(mcpServers)) {
|
|
1556
|
+
const enabled = serverConfig.enabled !== false;
|
|
1557
|
+
let status;
|
|
1558
|
+
if (!enabled) {
|
|
1559
|
+
status = "disconnected";
|
|
1560
|
+
} else if (connectedClients.has(name)) {
|
|
1561
|
+
status = "connected";
|
|
1562
|
+
} else {
|
|
1563
|
+
status = "error";
|
|
1564
|
+
}
|
|
1565
|
+
const server = {
|
|
1566
|
+
name,
|
|
1567
|
+
type: serverConfig.type,
|
|
1568
|
+
enabled,
|
|
1569
|
+
status
|
|
1570
|
+
};
|
|
1571
|
+
if (failedConnections[name]) {
|
|
1572
|
+
server.error = failedConnections[name];
|
|
1573
|
+
}
|
|
1574
|
+
servers.push(server);
|
|
1575
|
+
}
|
|
1576
|
+
return servers;
|
|
1577
|
+
}
|
|
1195
1578
|
// ============= RESOURCE MANAGEMENT =============
|
|
1196
1579
|
/**
|
|
1197
1580
|
* Lists all available resources with their info.
|
|
@@ -1287,6 +1670,21 @@ Either:
|
|
|
1287
1670
|
this.ensureStarted();
|
|
1288
1671
|
return await this.promptManager.has(name);
|
|
1289
1672
|
}
|
|
1673
|
+
/**
|
|
1674
|
+
* Refreshes the prompts cache, reloading from all providers.
|
|
1675
|
+
* Call this after adding/deleting prompts to make them immediately available.
|
|
1676
|
+
*
|
|
1677
|
+
* @param newPrompts Optional - if provided, updates the config prompts before refreshing.
|
|
1678
|
+
* Use this when you've modified the agent config file and need to
|
|
1679
|
+
* update both the runtime config and refresh the cache.
|
|
1680
|
+
*/
|
|
1681
|
+
async refreshPrompts(newPrompts) {
|
|
1682
|
+
this.ensureStarted();
|
|
1683
|
+
if (newPrompts) {
|
|
1684
|
+
this.promptManager.updateConfigPrompts(newPrompts);
|
|
1685
|
+
}
|
|
1686
|
+
await this.promptManager.refresh();
|
|
1687
|
+
}
|
|
1290
1688
|
/**
|
|
1291
1689
|
* Gets a prompt with its messages.
|
|
1292
1690
|
* @param name The name of the prompt
|