@strands-agents/sdk 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +175 -0
- package/README.md +185 -0
- package/dist/__fixtures__/model-test-helpers.d.ts +56 -0
- package/dist/__fixtures__/model-test-helpers.d.ts.map +1 -0
- package/dist/__fixtures__/model-test-helpers.js +85 -0
- package/dist/__fixtures__/model-test-helpers.js.map +1 -0
- package/dist/__fixtures__/tool-helpers.d.ts +15 -0
- package/dist/__fixtures__/tool-helpers.d.ts.map +1 -0
- package/dist/__fixtures__/tool-helpers.js +22 -0
- package/dist/__fixtures__/tool-helpers.js.map +1 -0
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +20 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/index.test.d.ts +2 -0
- package/dist/__tests__/index.test.d.ts.map +1 -0
- package/dist/__tests__/index.test.js +27 -0
- package/dist/__tests__/index.test.js.map +1 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/models/__tests__/bedrock.test.d.ts +2 -0
- package/dist/models/__tests__/bedrock.test.d.ts.map +1 -0
- package/dist/models/__tests__/bedrock.test.js +1161 -0
- package/dist/models/__tests__/bedrock.test.js.map +1 -0
- package/dist/models/__tests__/model.test.d.ts +2 -0
- package/dist/models/__tests__/model.test.d.ts.map +1 -0
- package/dist/models/__tests__/model.test.js +297 -0
- package/dist/models/__tests__/model.test.js.map +1 -0
- package/dist/models/__tests__/openai.test.d.ts +2 -0
- package/dist/models/__tests__/openai.test.d.ts.map +1 -0
- package/dist/models/__tests__/openai.test.js +1016 -0
- package/dist/models/__tests__/openai.test.js.map +1 -0
- package/dist/models/__tests__/test-utils.d.ts +10 -0
- package/dist/models/__tests__/test-utils.d.ts.map +1 -0
- package/dist/models/__tests__/test-utils.js +17 -0
- package/dist/models/__tests__/test-utils.js.map +1 -0
- package/dist/models/bedrock.d.ts +272 -0
- package/dist/models/bedrock.d.ts.map +1 -0
- package/dist/models/bedrock.js +679 -0
- package/dist/models/bedrock.js.map +1 -0
- package/dist/models/model.d.ts +89 -0
- package/dist/models/model.d.ts.map +1 -0
- package/dist/models/model.js +122 -0
- package/dist/models/model.js.map +1 -0
- package/dist/models/openai.d.ts +262 -0
- package/dist/models/openai.d.ts.map +1 -0
- package/dist/models/openai.js +625 -0
- package/dist/models/openai.js.map +1 -0
- package/dist/models/streaming.d.ts +226 -0
- package/dist/models/streaming.d.ts.map +1 -0
- package/dist/models/streaming.js +2 -0
- package/dist/models/streaming.js.map +1 -0
- package/dist/src/__fixtures__/agent-helpers.d.ts +29 -0
- package/dist/src/__fixtures__/agent-helpers.d.ts.map +1 -0
- package/dist/src/__fixtures__/agent-helpers.js +19 -0
- package/dist/src/__fixtures__/agent-helpers.js.map +1 -0
- package/dist/src/__fixtures__/environment.d.ts +12 -0
- package/dist/src/__fixtures__/environment.d.ts.map +1 -0
- package/dist/src/__fixtures__/environment.js +12 -0
- package/dist/src/__fixtures__/environment.js.map +1 -0
- package/dist/src/__fixtures__/mock-hook-provider.d.ts +14 -0
- package/dist/src/__fixtures__/mock-hook-provider.d.ts.map +1 -0
- package/dist/src/__fixtures__/mock-hook-provider.js +33 -0
- package/dist/src/__fixtures__/mock-hook-provider.js.map +1 -0
- package/dist/src/__fixtures__/mock-message-model.d.ts +93 -0
- package/dist/src/__fixtures__/mock-message-model.d.ts.map +1 -0
- package/dist/src/__fixtures__/mock-message-model.js +226 -0
- package/dist/src/__fixtures__/mock-message-model.js.map +1 -0
- package/dist/src/__fixtures__/model-test-helpers.d.ts +56 -0
- package/dist/src/__fixtures__/model-test-helpers.d.ts.map +1 -0
- package/dist/src/__fixtures__/model-test-helpers.js +85 -0
- package/dist/src/__fixtures__/model-test-helpers.js.map +1 -0
- package/dist/src/__fixtures__/tool-helpers.d.ts +37 -0
- package/dist/src/__fixtures__/tool-helpers.d.ts.map +1 -0
- package/dist/src/__fixtures__/tool-helpers.js +78 -0
- package/dist/src/__fixtures__/tool-helpers.js.map +1 -0
- package/dist/src/__tests__/errors.test.d.ts +2 -0
- package/dist/src/__tests__/errors.test.d.ts.map +1 -0
- package/dist/src/__tests__/errors.test.js +64 -0
- package/dist/src/__tests__/errors.test.js.map +1 -0
- package/dist/src/__tests__/index.test.d.ts +2 -0
- package/dist/src/__tests__/index.test.d.ts.map +1 -0
- package/dist/src/__tests__/index.test.js +27 -0
- package/dist/src/__tests__/index.test.js.map +1 -0
- package/dist/src/__tests__/mcp.test.d.ts +2 -0
- package/dist/src/__tests__/mcp.test.d.ts.map +1 -0
- package/dist/src/__tests__/mcp.test.js +166 -0
- package/dist/src/__tests__/mcp.test.js.map +1 -0
- package/dist/src/agent/__tests__/agent.hook.test.d.ts +2 -0
- package/dist/src/agent/__tests__/agent.hook.test.d.ts.map +1 -0
- package/dist/src/agent/__tests__/agent.hook.test.js +250 -0
- package/dist/src/agent/__tests__/agent.hook.test.js.map +1 -0
- package/dist/src/agent/__tests__/agent.test.d.ts +2 -0
- package/dist/src/agent/__tests__/agent.test.d.ts.map +1 -0
- package/dist/src/agent/__tests__/agent.test.js +414 -0
- package/dist/src/agent/__tests__/agent.test.js.map +1 -0
- package/dist/src/agent/__tests__/printer.test.d.ts +2 -0
- package/dist/src/agent/__tests__/printer.test.d.ts.map +1 -0
- package/dist/src/agent/__tests__/printer.test.js +152 -0
- package/dist/src/agent/__tests__/printer.test.js.map +1 -0
- package/dist/src/agent/__tests__/state.test.d.ts +2 -0
- package/dist/src/agent/__tests__/state.test.d.ts.map +1 -0
- package/dist/src/agent/__tests__/state.test.js +231 -0
- package/dist/src/agent/__tests__/state.test.js.map +1 -0
- package/dist/src/agent/agent.d.ts +207 -0
- package/dist/src/agent/agent.d.ts.map +1 -0
- package/dist/src/agent/agent.js +481 -0
- package/dist/src/agent/agent.js.map +1 -0
- package/dist/src/agent/printer.d.ts +73 -0
- package/dist/src/agent/printer.d.ts.map +1 -0
- package/dist/src/agent/printer.js +145 -0
- package/dist/src/agent/printer.js.map +1 -0
- package/dist/src/agent/state.d.ts +102 -0
- package/dist/src/agent/state.d.ts.map +1 -0
- package/dist/src/agent/state.js +73 -0
- package/dist/src/agent/state.js.map +1 -0
- package/dist/src/agent/streaming.d.ts +91 -0
- package/dist/src/agent/streaming.d.ts.map +1 -0
- package/dist/src/agent/streaming.js +2 -0
- package/dist/src/agent/streaming.js.map +1 -0
- package/dist/src/conversation-manager/__tests__/conversation-manager.test.d.ts +2 -0
- package/dist/src/conversation-manager/__tests__/conversation-manager.test.d.ts.map +1 -0
- package/dist/src/conversation-manager/__tests__/conversation-manager.test.js +10 -0
- package/dist/src/conversation-manager/__tests__/conversation-manager.test.js.map +1 -0
- package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.d.ts +2 -0
- package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.d.ts.map +1 -0
- package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.js +35 -0
- package/dist/src/conversation-manager/__tests__/null-conversation-manager.test.js.map +1 -0
- package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.d.ts +2 -0
- package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.d.ts.map +1 -0
- package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.js +553 -0
- package/dist/src/conversation-manager/__tests__/sliding-window-conversation-manager.test.js.map +1 -0
- package/dist/src/conversation-manager/conversation-manager.d.ts +73 -0
- package/dist/src/conversation-manager/conversation-manager.d.ts.map +1 -0
- package/dist/src/conversation-manager/conversation-manager.js +24 -0
- package/dist/src/conversation-manager/conversation-manager.js.map +1 -0
- package/dist/src/conversation-manager/index.d.ts +8 -0
- package/dist/src/conversation-manager/index.d.ts.map +1 -0
- package/dist/src/conversation-manager/index.js +8 -0
- package/dist/src/conversation-manager/index.js.map +1 -0
- package/dist/src/conversation-manager/null-conversation-manager.d.ts +23 -0
- package/dist/src/conversation-manager/null-conversation-manager.d.ts.map +1 -0
- package/dist/src/conversation-manager/null-conversation-manager.js +23 -0
- package/dist/src/conversation-manager/null-conversation-manager.js.map +1 -0
- package/dist/src/conversation-manager/sliding-window-conversation-manager.d.ts +105 -0
- package/dist/src/conversation-manager/sliding-window-conversation-manager.d.ts.map +1 -0
- package/dist/src/conversation-manager/sliding-window-conversation-manager.js +212 -0
- package/dist/src/conversation-manager/sliding-window-conversation-manager.js.map +1 -0
- package/dist/src/errors.d.ts +83 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +97 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/hooks/__tests__/events.test.d.ts +2 -0
- package/dist/src/hooks/__tests__/events.test.d.ts.map +1 -0
- package/dist/src/hooks/__tests__/events.test.js +347 -0
- package/dist/src/hooks/__tests__/events.test.js.map +1 -0
- package/dist/src/hooks/__tests__/registry.test.d.ts +2 -0
- package/dist/src/hooks/__tests__/registry.test.d.ts.map +1 -0
- package/dist/src/hooks/__tests__/registry.test.js +154 -0
- package/dist/src/hooks/__tests__/registry.test.js.map +1 -0
- package/dist/src/hooks/events.d.ts +199 -0
- package/dist/src/hooks/events.d.ts.map +1 -0
- package/dist/src/hooks/events.js +191 -0
- package/dist/src/hooks/events.js.map +1 -0
- package/dist/src/hooks/index.d.ts +11 -0
- package/dist/src/hooks/index.d.ts.map +1 -0
- package/dist/src/hooks/index.js +11 -0
- package/dist/src/hooks/index.js.map +1 -0
- package/dist/src/hooks/registry.d.ts +65 -0
- package/dist/src/hooks/registry.d.ts.map +1 -0
- package/dist/src/hooks/registry.js +65 -0
- package/dist/src/hooks/registry.js.map +1 -0
- package/dist/src/hooks/types.d.ts +49 -0
- package/dist/src/hooks/types.d.ts.map +1 -0
- package/dist/src/hooks/types.js +2 -0
- package/dist/src/hooks/types.js.map +1 -0
- package/dist/src/index.d.ts +32 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +29 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp.d.ts +51 -0
- package/dist/src/mcp.d.ts.map +1 -0
- package/dist/src/mcp.js +91 -0
- package/dist/src/mcp.js.map +1 -0
- package/dist/src/models/__tests__/bedrock.test.d.ts +2 -0
- package/dist/src/models/__tests__/bedrock.test.d.ts.map +1 -0
- package/dist/src/models/__tests__/bedrock.test.js +1388 -0
- package/dist/src/models/__tests__/bedrock.test.js.map +1 -0
- package/dist/src/models/__tests__/model.test.d.ts +2 -0
- package/dist/src/models/__tests__/model.test.d.ts.map +1 -0
- package/dist/src/models/__tests__/model.test.js +342 -0
- package/dist/src/models/__tests__/model.test.js.map +1 -0
- package/dist/src/models/__tests__/openai.test.d.ts +2 -0
- package/dist/src/models/__tests__/openai.test.d.ts.map +1 -0
- package/dist/src/models/__tests__/openai.test.js +1189 -0
- package/dist/src/models/__tests__/openai.test.js.map +1 -0
- package/dist/src/models/__tests__/test-utils.d.ts +10 -0
- package/dist/src/models/__tests__/test-utils.d.ts.map +1 -0
- package/dist/src/models/__tests__/test-utils.js +17 -0
- package/dist/src/models/__tests__/test-utils.js.map +1 -0
- package/dist/src/models/bedrock.d.ts +289 -0
- package/dist/src/models/bedrock.d.ts.map +1 -0
- package/dist/src/models/bedrock.js +804 -0
- package/dist/src/models/bedrock.js.map +1 -0
- package/dist/src/models/model.d.ts +99 -0
- package/dist/src/models/model.d.ts.map +1 -0
- package/dist/src/models/model.js +169 -0
- package/dist/src/models/model.js.map +1 -0
- package/dist/src/models/openai.d.ts +262 -0
- package/dist/src/models/openai.d.ts.map +1 -0
- package/dist/src/models/openai.js +752 -0
- package/dist/src/models/openai.js.map +1 -0
- package/dist/src/models/streaming.d.ts +318 -0
- package/dist/src/models/streaming.d.ts.map +1 -0
- package/dist/src/models/streaming.js +122 -0
- package/dist/src/models/streaming.js.map +1 -0
- package/dist/src/registry/registry.d.ts +117 -0
- package/dist/src/registry/registry.d.ts.map +1 -0
- package/dist/src/registry/registry.js +298 -0
- package/dist/src/registry/registry.js.map +1 -0
- package/dist/src/registry/tool-registry.d.ts +34 -0
- package/dist/src/registry/tool-registry.d.ts.map +1 -0
- package/dist/src/registry/tool-registry.js +178 -0
- package/dist/src/registry/tool-registry.js.map +1 -0
- package/dist/src/tools/__tests__/tool.test.d.ts +2 -0
- package/dist/src/tools/__tests__/tool.test.d.ts.map +1 -0
- package/dist/src/tools/__tests__/tool.test.js +877 -0
- package/dist/src/tools/__tests__/tool.test.js.map +1 -0
- package/dist/src/tools/__tests__/zod-tool.test-d.d.ts +2 -0
- package/dist/src/tools/__tests__/zod-tool.test-d.d.ts.map +1 -0
- package/dist/src/tools/__tests__/zod-tool.test-d.js +227 -0
- package/dist/src/tools/__tests__/zod-tool.test-d.js.map +1 -0
- package/dist/src/tools/__tests__/zod-tool.test.d.ts +2 -0
- package/dist/src/tools/__tests__/zod-tool.test.d.ts.map +1 -0
- package/dist/src/tools/__tests__/zod-tool.test.js +372 -0
- package/dist/src/tools/__tests__/zod-tool.test.js.map +1 -0
- package/dist/src/tools/function-tool.d.ts +146 -0
- package/dist/src/tools/function-tool.d.ts.map +1 -0
- package/dist/src/tools/function-tool.js +188 -0
- package/dist/src/tools/function-tool.js.map +1 -0
- package/dist/src/tools/mcp-tool.d.ts +36 -0
- package/dist/src/tools/mcp-tool.d.ts.map +1 -0
- package/dist/src/tools/mcp-tool.js +78 -0
- package/dist/src/tools/mcp-tool.js.map +1 -0
- package/dist/src/tools/tool.d.ts +167 -0
- package/dist/src/tools/tool.d.ts.map +1 -0
- package/dist/src/tools/tool.js +68 -0
- package/dist/src/tools/tool.js.map +1 -0
- package/dist/src/tools/types.d.ts +62 -0
- package/dist/src/tools/types.d.ts.map +1 -0
- package/dist/src/tools/types.js +2 -0
- package/dist/src/tools/types.js.map +1 -0
- package/dist/src/tools/zod-tool.d.ts +70 -0
- package/dist/src/tools/zod-tool.d.ts.map +1 -0
- package/dist/src/tools/zod-tool.js +149 -0
- package/dist/src/tools/zod-tool.js.map +1 -0
- package/dist/src/types/__tests__/agent.test.d.ts +2 -0
- package/dist/src/types/__tests__/agent.test.d.ts.map +1 -0
- package/dist/src/types/__tests__/agent.test.js +155 -0
- package/dist/src/types/__tests__/agent.test.js.map +1 -0
- package/dist/src/types/__tests__/json.test.d.ts +2 -0
- package/dist/src/types/__tests__/json.test.d.ts.map +1 -0
- package/dist/src/types/__tests__/json.test.js +298 -0
- package/dist/src/types/__tests__/json.test.js.map +1 -0
- package/dist/src/types/__tests__/media.test.d.ts +2 -0
- package/dist/src/types/__tests__/media.test.d.ts.map +1 -0
- package/dist/src/types/__tests__/media.test.js +257 -0
- package/dist/src/types/__tests__/media.test.js.map +1 -0
- package/dist/src/types/__tests__/messages.test.d.ts +2 -0
- package/dist/src/types/__tests__/messages.test.d.ts.map +1 -0
- package/dist/src/types/__tests__/messages.test.js +364 -0
- package/dist/src/types/__tests__/messages.test.js.map +1 -0
- package/dist/src/types/__tests__/validation.test.d.ts +2 -0
- package/dist/src/types/__tests__/validation.test.d.ts.map +1 -0
- package/dist/src/types/__tests__/validation.test.js +30 -0
- package/dist/src/types/__tests__/validation.test.js.map +1 -0
- package/dist/src/types/agent.d.ts +57 -0
- package/dist/src/types/agent.d.ts.map +1 -0
- package/dist/src/types/agent.js +47 -0
- package/dist/src/types/agent.js.map +1 -0
- package/dist/src/types/json.d.ts +55 -0
- package/dist/src/types/json.d.ts.map +1 -0
- package/dist/src/types/json.js +72 -0
- package/dist/src/types/json.js.map +1 -0
- package/dist/src/types/media.d.ts +249 -0
- package/dist/src/types/media.d.ts.map +1 -0
- package/dist/src/types/media.js +173 -0
- package/dist/src/types/media.js.map +1 -0
- package/dist/src/types/messages.d.ts +438 -0
- package/dist/src/types/messages.d.ts.map +1 -0
- package/dist/src/types/messages.js +286 -0
- package/dist/src/types/messages.js.map +1 -0
- package/dist/src/types/validation.d.ts +10 -0
- package/dist/src/types/validation.d.ts.map +1 -0
- package/dist/src/types/validation.js +15 -0
- package/dist/src/types/validation.js.map +1 -0
- package/dist/tools/__tests__/registry.test.d.ts +2 -0
- package/dist/tools/__tests__/registry.test.d.ts.map +1 -0
- package/dist/tools/__tests__/registry.test.js +253 -0
- package/dist/tools/__tests__/registry.test.js.map +1 -0
- package/dist/tools/__tests__/tool.test.d.ts +2 -0
- package/dist/tools/__tests__/tool.test.d.ts.map +1 -0
- package/dist/tools/__tests__/tool.test.js +761 -0
- package/dist/tools/__tests__/tool.test.js.map +1 -0
- package/dist/tools/__tests__/zod-tool.test-d.d.ts +2 -0
- package/dist/tools/__tests__/zod-tool.test-d.d.ts.map +1 -0
- package/dist/tools/__tests__/zod-tool.test-d.js +227 -0
- package/dist/tools/__tests__/zod-tool.test-d.js.map +1 -0
- package/dist/tools/__tests__/zod-tool.test.d.ts +2 -0
- package/dist/tools/__tests__/zod-tool.test.d.ts.map +1 -0
- package/dist/tools/__tests__/zod-tool.test.js +342 -0
- package/dist/tools/__tests__/zod-tool.test.js.map +1 -0
- package/dist/tools/function-tool.d.ts +156 -0
- package/dist/tools/function-tool.d.ts.map +1 -0
- package/dist/tools/function-tool.js +237 -0
- package/dist/tools/function-tool.js.map +1 -0
- package/dist/tools/registry.d.ts +43 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +82 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/tool.d.ts +157 -0
- package/dist/tools/tool.d.ts.map +1 -0
- package/dist/tools/tool.js +2 -0
- package/dist/tools/tool.js.map +1 -0
- package/dist/tools/types.d.ts +119 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/zod-tool.d.ts +70 -0
- package/dist/tools/zod-tool.d.ts.map +1 -0
- package/dist/tools/zod-tool.js +96 -0
- package/dist/tools/zod-tool.js.map +1 -0
- package/dist/types/__tests__/json.test.d.ts +2 -0
- package/dist/types/__tests__/json.test.d.ts.map +1 -0
- package/dist/types/__tests__/json.test.js +129 -0
- package/dist/types/__tests__/json.test.js.map +1 -0
- package/dist/types/__tests__/validation.test.d.ts +2 -0
- package/dist/types/__tests__/validation.test.d.ts.map +1 -0
- package/dist/types/__tests__/validation.test.js +30 -0
- package/dist/types/__tests__/validation.test.js.map +1 -0
- package/dist/types/json.d.ts +45 -0
- package/dist/types/json.d.ts.map +1 -0
- package/dist/types/json.js +17 -0
- package/dist/types/json.js.map +1 -0
- package/dist/types/messages.d.ts +160 -0
- package/dist/types/messages.d.ts.map +1 -0
- package/dist/types/messages.js +2 -0
- package/dist/types/messages.js.map +1 -0
- package/dist/types/validation.d.ts +10 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/dist/types/validation.js +15 -0
- package/dist/types/validation.js.map +1 -0
- package/dist/vended_tools/bash/__tests__/bash.test.d.ts +2 -0
- package/dist/vended_tools/bash/__tests__/bash.test.d.ts.map +1 -0
- package/dist/vended_tools/bash/__tests__/bash.test.js +333 -0
- package/dist/vended_tools/bash/__tests__/bash.test.js.map +1 -0
- package/dist/vended_tools/bash/bash.d.ts +33 -0
- package/dist/vended_tools/bash/bash.d.ts.map +1 -0
- package/dist/vended_tools/bash/bash.js +264 -0
- package/dist/vended_tools/bash/bash.js.map +1 -0
- package/dist/vended_tools/bash/index.d.ts +7 -0
- package/dist/vended_tools/bash/index.d.ts.map +1 -0
- package/dist/vended_tools/bash/index.js +6 -0
- package/dist/vended_tools/bash/index.js.map +1 -0
- package/dist/vended_tools/bash/types.d.ts +65 -0
- package/dist/vended_tools/bash/types.d.ts.map +1 -0
- package/dist/vended_tools/bash/types.js +22 -0
- package/dist/vended_tools/bash/types.js.map +1 -0
- package/dist/vended_tools/file_editor/__tests__/file-editor.test.d.ts +2 -0
- package/dist/vended_tools/file_editor/__tests__/file-editor.test.d.ts.map +1 -0
- package/dist/vended_tools/file_editor/__tests__/file-editor.test.js +359 -0
- package/dist/vended_tools/file_editor/__tests__/file-editor.test.js.map +1 -0
- package/dist/vended_tools/file_editor/file-editor.d.ts +31 -0
- package/dist/vended_tools/file_editor/file-editor.d.ts.map +1 -0
- package/dist/vended_tools/file_editor/file-editor.js +353 -0
- package/dist/vended_tools/file_editor/file-editor.js.map +1 -0
- package/dist/vended_tools/file_editor/index.d.ts +6 -0
- package/dist/vended_tools/file_editor/index.d.ts.map +1 -0
- package/dist/vended_tools/file_editor/index.js +5 -0
- package/dist/vended_tools/file_editor/index.js.map +1 -0
- package/dist/vended_tools/file_editor/types.d.ts +61 -0
- package/dist/vended_tools/file_editor/types.d.ts.map +1 -0
- package/dist/vended_tools/file_editor/types.js +2 -0
- package/dist/vended_tools/file_editor/types.js.map +1 -0
- package/dist/vended_tools/http_request/__tests__/http-request.test.d.ts +2 -0
- package/dist/vended_tools/http_request/__tests__/http-request.test.d.ts.map +1 -0
- package/dist/vended_tools/http_request/__tests__/http-request.test.js +189 -0
- package/dist/vended_tools/http_request/__tests__/http-request.test.js.map +1 -0
- package/dist/vended_tools/http_request/http-request.d.ts +35 -0
- package/dist/vended_tools/http_request/http-request.d.ts.map +1 -0
- package/dist/vended_tools/http_request/http-request.js +95 -0
- package/dist/vended_tools/http_request/http-request.js.map +1 -0
- package/dist/vended_tools/http_request/index.d.ts +6 -0
- package/dist/vended_tools/http_request/index.d.ts.map +1 -0
- package/dist/vended_tools/http_request/index.js +5 -0
- package/dist/vended_tools/http_request/index.js.map +1 -0
- package/dist/vended_tools/http_request/types.d.ts +47 -0
- package/dist/vended_tools/http_request/types.d.ts.map +1 -0
- package/dist/vended_tools/http_request/types.js +2 -0
- package/dist/vended_tools/http_request/types.js.map +1 -0
- package/dist/vended_tools/notebook/__tests__/notebook.test.d.ts +2 -0
- package/dist/vended_tools/notebook/__tests__/notebook.test.d.ts.map +1 -0
- package/dist/vended_tools/notebook/__tests__/notebook.test.js +371 -0
- package/dist/vended_tools/notebook/__tests__/notebook.test.js.map +1 -0
- package/dist/vended_tools/notebook/index.d.ts +6 -0
- package/dist/vended_tools/notebook/index.d.ts.map +1 -0
- package/dist/vended_tools/notebook/index.js +5 -0
- package/dist/vended_tools/notebook/index.js.map +1 -0
- package/dist/vended_tools/notebook/notebook.d.ts +29 -0
- package/dist/vended_tools/notebook/notebook.d.ts.map +1 -0
- package/dist/vended_tools/notebook/notebook.js +215 -0
- package/dist/vended_tools/notebook/notebook.js.map +1 -0
- package/dist/vended_tools/notebook/types.d.ts +79 -0
- package/dist/vended_tools/notebook/types.d.ts.map +1 -0
- package/dist/vended_tools/notebook/types.js +2 -0
- package/dist/vended_tools/notebook/types.js.map +1 -0
- package/package.json +112 -0
|
@@ -0,0 +1,1388 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { BedrockRuntimeClient } from '@aws-sdk/client-bedrock-runtime';
|
|
3
|
+
import { isNode } from '../../__fixtures__/environment.js';
|
|
4
|
+
import { BedrockModel } from '../bedrock.js';
|
|
5
|
+
import { ContextWindowOverflowError } from '../../errors.js';
|
|
6
|
+
import { TextBlock, GuardContentBlock, CachePointBlock } from '../../types/messages.js';
|
|
7
|
+
import { collectIterator } from '../../__fixtures__/model-test-helpers.js';
|
|
8
|
+
/**
|
|
9
|
+
* Helper function to setup mock send with custom stream generator.
|
|
10
|
+
*/
|
|
11
|
+
function setupMockSend(streamGenerator) {
|
|
12
|
+
vi.clearAllMocks();
|
|
13
|
+
const mockSend = vi.fn(async () => ({
|
|
14
|
+
stream: streamGenerator(),
|
|
15
|
+
}));
|
|
16
|
+
vi.mocked(BedrockRuntimeClient).mockImplementation(function () {
|
|
17
|
+
return { send: mockSend };
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// Mock the AWS SDK
|
|
21
|
+
vi.mock('@aws-sdk/client-bedrock-runtime', async (importOriginal) => {
|
|
22
|
+
const originalModule = await importOriginal();
|
|
23
|
+
// Mock command classes that the code under test will instantiate
|
|
24
|
+
const ConverseStreamCommand = vi.fn();
|
|
25
|
+
const ConverseCommand = vi.fn();
|
|
26
|
+
const mockSend = vi.fn(async (command) => {
|
|
27
|
+
// Check which constructor was used to create the command object
|
|
28
|
+
if (command instanceof ConverseStreamCommand) {
|
|
29
|
+
// Return a streaming response
|
|
30
|
+
return {
|
|
31
|
+
stream: (async function* () {
|
|
32
|
+
yield { messageStart: { role: 'assistant' } };
|
|
33
|
+
yield { contentBlockStart: {} };
|
|
34
|
+
yield { contentBlockDelta: { delta: { text: 'Hello' } } };
|
|
35
|
+
yield { contentBlockStop: {} };
|
|
36
|
+
yield { messageStop: { stopReason: 'end_turn' } };
|
|
37
|
+
yield {
|
|
38
|
+
metadata: {
|
|
39
|
+
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
40
|
+
metrics: { latencyMs: 100 },
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
})(),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (command instanceof ConverseCommand) {
|
|
47
|
+
// Return a non-streaming (full) response for the non-streaming API
|
|
48
|
+
return {
|
|
49
|
+
output: {
|
|
50
|
+
message: {
|
|
51
|
+
role: 'assistant',
|
|
52
|
+
content: [{ text: 'Hello' }],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
stopReason: 'end_turn',
|
|
56
|
+
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
57
|
+
metrics: { latencyMs: 100 },
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
throw new Error('Unhandled command type in mock');
|
|
61
|
+
});
|
|
62
|
+
// Create a mock ValidationException class
|
|
63
|
+
class MockValidationException extends Error {
|
|
64
|
+
constructor(opts) {
|
|
65
|
+
super(opts.message);
|
|
66
|
+
this.name = 'ValidationException';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
...originalModule,
|
|
71
|
+
BedrockRuntimeClient: vi.fn(function () {
|
|
72
|
+
return {
|
|
73
|
+
send: mockSend,
|
|
74
|
+
};
|
|
75
|
+
}),
|
|
76
|
+
ConverseStreamCommand,
|
|
77
|
+
ConverseCommand,
|
|
78
|
+
ValidationException: MockValidationException,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
describe('BedrockModel', () => {
|
|
82
|
+
beforeEach(() => {
|
|
83
|
+
vi.clearAllMocks();
|
|
84
|
+
// Clean up AWS_REGION env var in Node.js only
|
|
85
|
+
if (isNode && process.env) {
|
|
86
|
+
delete process.env.AWS_REGION;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
afterEach(() => {
|
|
90
|
+
vi.clearAllMocks();
|
|
91
|
+
});
|
|
92
|
+
describe('constructor', () => {
|
|
93
|
+
it('creates an instance with default configuration', () => {
|
|
94
|
+
const provider = new BedrockModel();
|
|
95
|
+
const config = provider.getConfig();
|
|
96
|
+
expect(config.modelId).toBeDefined();
|
|
97
|
+
});
|
|
98
|
+
it('uses provided model ID ', () => {
|
|
99
|
+
const customModelId = 'us.anthropic.claude-3-5-sonnet-20241022-v2:0';
|
|
100
|
+
const provider = new BedrockModel({ modelId: customModelId });
|
|
101
|
+
expect(provider.getConfig()).toStrictEqual({
|
|
102
|
+
modelId: customModelId,
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
it('uses provided region', () => {
|
|
106
|
+
const customRegion = 'eu-west-1';
|
|
107
|
+
new BedrockModel({ region: customRegion });
|
|
108
|
+
expect(BedrockRuntimeClient).toHaveBeenCalledWith({
|
|
109
|
+
region: customRegion,
|
|
110
|
+
customUserAgent: 'strands-agents-ts-sdk',
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
it('extends custom user agent if provided', () => {
|
|
114
|
+
const customAgent = 'my-app/1.0';
|
|
115
|
+
new BedrockModel({ region: 'us-west-2', clientConfig: { customUserAgent: customAgent } });
|
|
116
|
+
expect(BedrockRuntimeClient).toHaveBeenCalledWith({
|
|
117
|
+
region: 'us-west-2',
|
|
118
|
+
customUserAgent: 'my-app/1.0 strands-agents-ts-sdk',
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
it('passes custom endpoint to client', () => {
|
|
122
|
+
const endpoint = 'https://vpce-abc.bedrock-runtime.us-west-2.vpce.amazonaws.com';
|
|
123
|
+
const region = 'us-west-2';
|
|
124
|
+
new BedrockModel({ region, clientConfig: { endpoint } });
|
|
125
|
+
expect(BedrockRuntimeClient).toHaveBeenCalledWith({
|
|
126
|
+
region,
|
|
127
|
+
endpoint,
|
|
128
|
+
customUserAgent: 'strands-agents-ts-sdk',
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
it('passes custom credentials to client', () => {
|
|
132
|
+
const credentials = {
|
|
133
|
+
accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
|
|
134
|
+
secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
|
|
135
|
+
};
|
|
136
|
+
const region = 'us-west-2';
|
|
137
|
+
new BedrockModel({ region, clientConfig: { credentials } });
|
|
138
|
+
expect(BedrockRuntimeClient).toHaveBeenCalledWith({
|
|
139
|
+
region,
|
|
140
|
+
credentials,
|
|
141
|
+
customUserAgent: 'strands-agents-ts-sdk',
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
describe('updateConfig', () => {
|
|
146
|
+
it('merges new config with existing config', () => {
|
|
147
|
+
const provider = new BedrockModel({ region: 'us-west-2', temperature: 0.5 });
|
|
148
|
+
provider.updateConfig({ temperature: 0.8, maxTokens: 2048 });
|
|
149
|
+
expect(provider.getConfig()).toStrictEqual({
|
|
150
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
151
|
+
temperature: 0.8,
|
|
152
|
+
maxTokens: 2048,
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
it('preserves fields not included in the update', () => {
|
|
156
|
+
const provider = new BedrockModel({
|
|
157
|
+
region: 'us-west-2',
|
|
158
|
+
modelId: 'custom-model',
|
|
159
|
+
temperature: 0.5,
|
|
160
|
+
maxTokens: 1024,
|
|
161
|
+
});
|
|
162
|
+
provider.updateConfig({ temperature: 0.8 });
|
|
163
|
+
expect(provider.getConfig()).toStrictEqual({
|
|
164
|
+
modelId: 'custom-model',
|
|
165
|
+
temperature: 0.8,
|
|
166
|
+
maxTokens: 1024,
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe('getConfig', () => {
|
|
171
|
+
it('returns the current configuration', () => {
|
|
172
|
+
const provider = new BedrockModel({
|
|
173
|
+
region: 'us-west-2',
|
|
174
|
+
modelId: 'test-model',
|
|
175
|
+
maxTokens: 1024,
|
|
176
|
+
temperature: 0.7,
|
|
177
|
+
});
|
|
178
|
+
expect(provider.getConfig()).toStrictEqual({
|
|
179
|
+
modelId: 'test-model',
|
|
180
|
+
maxTokens: 1024,
|
|
181
|
+
temperature: 0.7,
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
describe('format_message', async () => {
|
|
186
|
+
const { ConverseStreamCommand } = await import('@aws-sdk/client-bedrock-runtime');
|
|
187
|
+
const mockConverseStreamCommand = vi.mocked(ConverseStreamCommand);
|
|
188
|
+
it('formats the request to bedrock properly', async () => {
|
|
189
|
+
const provider = new BedrockModel({
|
|
190
|
+
region: 'us-west-2',
|
|
191
|
+
modelId: 'test-model',
|
|
192
|
+
maxTokens: 1024,
|
|
193
|
+
temperature: 0.7,
|
|
194
|
+
topP: 0.9,
|
|
195
|
+
stopSequences: ['STOP'],
|
|
196
|
+
cachePrompt: 'default',
|
|
197
|
+
cacheTools: 'default',
|
|
198
|
+
additionalResponseFieldPaths: ['Hello!'],
|
|
199
|
+
additionalRequestFields: ['World!'],
|
|
200
|
+
additionalArgs: {
|
|
201
|
+
MyExtraArg: 'ExtraArg',
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
205
|
+
const options = {
|
|
206
|
+
systemPrompt: 'You are a helpful assistant',
|
|
207
|
+
toolSpecs: [
|
|
208
|
+
{
|
|
209
|
+
name: 'calculator',
|
|
210
|
+
description: 'Perform calculations',
|
|
211
|
+
inputSchema: { type: 'object', properties: { expression: { type: 'string' } } },
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
toolChoice: { auto: {} },
|
|
215
|
+
};
|
|
216
|
+
// Trigger the stream to make the request, but ignore the events for now
|
|
217
|
+
collectIterator(provider.stream(messages, options));
|
|
218
|
+
// Verify ConverseStreamCommand was called with properly formatted request
|
|
219
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
220
|
+
MyExtraArg: 'ExtraArg',
|
|
221
|
+
additionalModelRequestFields: ['World!'],
|
|
222
|
+
additionalModelResponseFieldPaths: ['Hello!'],
|
|
223
|
+
modelId: 'test-model',
|
|
224
|
+
messages: [
|
|
225
|
+
{
|
|
226
|
+
role: 'user',
|
|
227
|
+
content: [{ text: 'Hello' }],
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
system: [{ text: 'You are a helpful assistant' }, { cachePoint: { type: 'default' } }],
|
|
231
|
+
toolConfig: {
|
|
232
|
+
toolChoice: { auto: {} },
|
|
233
|
+
tools: [
|
|
234
|
+
{
|
|
235
|
+
toolSpec: {
|
|
236
|
+
name: 'calculator',
|
|
237
|
+
description: 'Perform calculations',
|
|
238
|
+
inputSchema: { json: { type: 'object', properties: { expression: { type: 'string' } } } },
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
{ cachePoint: { type: 'default' } },
|
|
242
|
+
],
|
|
243
|
+
},
|
|
244
|
+
inferenceConfig: {
|
|
245
|
+
maxTokens: 1024,
|
|
246
|
+
temperature: 0.7,
|
|
247
|
+
topP: 0.9,
|
|
248
|
+
stopSequences: ['STOP'],
|
|
249
|
+
},
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
it('formats tool use messages', async () => {
|
|
253
|
+
const { ConverseStreamCommand } = await import('@aws-sdk/client-bedrock-runtime');
|
|
254
|
+
const mockConverseStreamCommand = vi.mocked(ConverseStreamCommand);
|
|
255
|
+
const provider = new BedrockModel();
|
|
256
|
+
const messages = [
|
|
257
|
+
{
|
|
258
|
+
type: 'message',
|
|
259
|
+
role: 'assistant',
|
|
260
|
+
content: [
|
|
261
|
+
{
|
|
262
|
+
type: 'toolUseBlock',
|
|
263
|
+
name: 'calculator',
|
|
264
|
+
toolUseId: 'tool-123',
|
|
265
|
+
input: { a: 5, b: 3 },
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
},
|
|
269
|
+
];
|
|
270
|
+
// Run the stream but ignore the output
|
|
271
|
+
collectIterator(provider.stream(messages));
|
|
272
|
+
// Verify ConverseStreamCommand was called with properly formatted request
|
|
273
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
274
|
+
messages: expect.arrayContaining([
|
|
275
|
+
expect.objectContaining({
|
|
276
|
+
role: 'assistant',
|
|
277
|
+
content: expect.arrayContaining([
|
|
278
|
+
expect.objectContaining({
|
|
279
|
+
toolUse: expect.objectContaining({
|
|
280
|
+
name: 'calculator',
|
|
281
|
+
toolUseId: 'tool-123',
|
|
282
|
+
input: { a: 5, b: 3 },
|
|
283
|
+
}),
|
|
284
|
+
}),
|
|
285
|
+
]),
|
|
286
|
+
}),
|
|
287
|
+
]),
|
|
288
|
+
}));
|
|
289
|
+
});
|
|
290
|
+
it('formats tool result messages', async () => {
|
|
291
|
+
const provider = new BedrockModel();
|
|
292
|
+
const messages = [
|
|
293
|
+
{
|
|
294
|
+
type: 'message',
|
|
295
|
+
role: 'user',
|
|
296
|
+
content: [
|
|
297
|
+
{
|
|
298
|
+
type: 'toolResultBlock',
|
|
299
|
+
toolUseId: 'tool-123',
|
|
300
|
+
status: 'success',
|
|
301
|
+
content: [
|
|
302
|
+
{ type: 'textBlock', text: 'Result: 8' },
|
|
303
|
+
{ type: 'jsonBlock', json: { hello: 'world' } },
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
],
|
|
307
|
+
},
|
|
308
|
+
];
|
|
309
|
+
// Start the stream
|
|
310
|
+
collectIterator(provider.stream(messages));
|
|
311
|
+
// Verify ConverseStreamCommand was called with properly formatted request
|
|
312
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
313
|
+
messages: [
|
|
314
|
+
{
|
|
315
|
+
content: [
|
|
316
|
+
{
|
|
317
|
+
toolResult: {
|
|
318
|
+
content: [
|
|
319
|
+
{
|
|
320
|
+
text: 'Result: 8',
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
json: {
|
|
324
|
+
hello: 'world',
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
],
|
|
328
|
+
status: 'success',
|
|
329
|
+
toolUseId: 'tool-123',
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
],
|
|
333
|
+
role: 'user',
|
|
334
|
+
},
|
|
335
|
+
],
|
|
336
|
+
modelId: expect.any(String),
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
it('formats reasoning messages properly', async () => {
|
|
340
|
+
const provider = new BedrockModel();
|
|
341
|
+
const messages = [
|
|
342
|
+
{
|
|
343
|
+
type: 'message',
|
|
344
|
+
role: 'user',
|
|
345
|
+
content: [
|
|
346
|
+
{
|
|
347
|
+
type: 'reasoningBlock',
|
|
348
|
+
text: 'Hello',
|
|
349
|
+
signature: 'World',
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
type: 'reasoningBlock',
|
|
353
|
+
redactedContent: new Uint8Array(1),
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
},
|
|
357
|
+
];
|
|
358
|
+
// Start the stream but don't await it
|
|
359
|
+
collectIterator(provider.stream(messages));
|
|
360
|
+
// Verify ConverseStreamCommand was called with properly formatted request
|
|
361
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
362
|
+
messages: [
|
|
363
|
+
{
|
|
364
|
+
role: 'user',
|
|
365
|
+
content: [
|
|
366
|
+
{
|
|
367
|
+
reasoningContent: {
|
|
368
|
+
reasoningText: {
|
|
369
|
+
signature: 'World',
|
|
370
|
+
text: 'Hello',
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
reasoningContent: {
|
|
376
|
+
redactedContent: new Uint8Array(1),
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
},
|
|
381
|
+
],
|
|
382
|
+
modelId: expect.any(String),
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
it('formats cache point blocks in messages', async () => {
|
|
386
|
+
const provider = new BedrockModel();
|
|
387
|
+
const messages = [
|
|
388
|
+
{
|
|
389
|
+
type: 'message',
|
|
390
|
+
role: 'user',
|
|
391
|
+
content: [
|
|
392
|
+
{ type: 'textBlock', text: 'Message with cache point' },
|
|
393
|
+
{ type: 'cachePointBlock', cacheType: 'default' },
|
|
394
|
+
],
|
|
395
|
+
},
|
|
396
|
+
];
|
|
397
|
+
collectIterator(provider.stream(messages));
|
|
398
|
+
// Verify ConverseStreamCommand was called with properly formatted request
|
|
399
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
400
|
+
messages: [
|
|
401
|
+
{
|
|
402
|
+
role: 'user',
|
|
403
|
+
content: [{ text: 'Message with cache point' }, { cachePoint: { type: 'default' } }],
|
|
404
|
+
},
|
|
405
|
+
],
|
|
406
|
+
modelId: expect.any(String),
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
describe.each([
|
|
411
|
+
{ mode: 'streaming', stream: true },
|
|
412
|
+
{ mode: 'non-streaming', stream: false },
|
|
413
|
+
])('BedrockModel in $mode mode', ({ stream }) => {
|
|
414
|
+
it('yields and validates text events correctly', async () => {
|
|
415
|
+
const mockSend = vi.fn(async () => {
|
|
416
|
+
if (stream) {
|
|
417
|
+
return {
|
|
418
|
+
stream: (async function* () {
|
|
419
|
+
yield { messageStart: { role: 'assistant' } };
|
|
420
|
+
yield { contentBlockStart: {} };
|
|
421
|
+
yield { contentBlockDelta: { delta: { text: 'Hello' } } };
|
|
422
|
+
yield { contentBlockStop: {} };
|
|
423
|
+
yield { messageStop: { stopReason: 'end_turn' } };
|
|
424
|
+
yield {
|
|
425
|
+
metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 }, metrics: { latencyMs: 100 } },
|
|
426
|
+
};
|
|
427
|
+
})(),
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
return {
|
|
432
|
+
output: { message: { role: 'assistant', content: [{ text: 'Hello' }] } },
|
|
433
|
+
stopReason: 'end_turn',
|
|
434
|
+
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
435
|
+
metrics: { latencyMs: 100 },
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
vi.mocked(BedrockRuntimeClient).mockImplementation(function () {
|
|
440
|
+
return { send: mockSend };
|
|
441
|
+
});
|
|
442
|
+
const provider = new BedrockModel({ stream });
|
|
443
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
444
|
+
const events = await collectIterator(provider.stream(messages));
|
|
445
|
+
expect(events).toContainEqual({ role: 'assistant', type: 'modelMessageStartEvent' });
|
|
446
|
+
expect(events).toContainEqual({ type: 'modelContentBlockStartEvent' });
|
|
447
|
+
expect(events).toContainEqual({
|
|
448
|
+
type: 'modelContentBlockDeltaEvent',
|
|
449
|
+
delta: { type: 'textDelta', text: 'Hello' },
|
|
450
|
+
});
|
|
451
|
+
expect(events).toContainEqual({ type: 'modelContentBlockStopEvent' });
|
|
452
|
+
expect(events).toContainEqual({ type: 'modelMessageStopEvent', stopReason: 'endTurn' });
|
|
453
|
+
expect(events).toContainEqual({
|
|
454
|
+
type: 'modelMetadataEvent',
|
|
455
|
+
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
456
|
+
metrics: { latencyMs: 100 },
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
it('yields and validates toolUse events correctly', async () => {
|
|
460
|
+
const mockSend = vi.fn(async () => {
|
|
461
|
+
if (stream) {
|
|
462
|
+
return {
|
|
463
|
+
stream: (async function* () {
|
|
464
|
+
yield { messageStart: { role: 'assistant' } };
|
|
465
|
+
yield {
|
|
466
|
+
contentBlockStart: {
|
|
467
|
+
start: { toolUse: { toolUseId: 'tool-use-123', name: 'get_weather' } },
|
|
468
|
+
},
|
|
469
|
+
};
|
|
470
|
+
yield {
|
|
471
|
+
contentBlockDelta: {
|
|
472
|
+
delta: { toolUse: { input: '{"location":"San Francisco"}' } },
|
|
473
|
+
},
|
|
474
|
+
};
|
|
475
|
+
yield { contentBlockStop: {} };
|
|
476
|
+
yield { messageStop: { stopReason: 'tool_use' } };
|
|
477
|
+
yield {
|
|
478
|
+
metadata: {
|
|
479
|
+
usage: { inputTokens: 10, outputTokens: 25, totalTokens: 35 },
|
|
480
|
+
metrics: { latencyMs: 120 },
|
|
481
|
+
},
|
|
482
|
+
};
|
|
483
|
+
})(),
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
return {
|
|
488
|
+
output: {
|
|
489
|
+
message: {
|
|
490
|
+
role: 'assistant',
|
|
491
|
+
content: [
|
|
492
|
+
{ toolUse: { toolUseId: 'tool-use-123', name: 'get_weather', input: { location: 'San Francisco' } } },
|
|
493
|
+
],
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
stopReason: 'tool_use',
|
|
497
|
+
usage: { inputTokens: 10, outputTokens: 25, totalTokens: 35 },
|
|
498
|
+
metrics: { latencyMs: 120 },
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
vi.mocked(BedrockRuntimeClient).mockImplementation(function () {
|
|
503
|
+
return { send: mockSend };
|
|
504
|
+
});
|
|
505
|
+
const provider = new BedrockModel({ stream });
|
|
506
|
+
const messages = [
|
|
507
|
+
{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Weather?' }] },
|
|
508
|
+
];
|
|
509
|
+
const events = await collectIterator(provider.stream(messages));
|
|
510
|
+
const startEvent = events.find((e) => e.type === 'modelContentBlockStartEvent');
|
|
511
|
+
const inputDeltaEvent = events.find((e) => e.type === 'modelContentBlockDeltaEvent' && e.delta.type === 'toolUseInputDelta');
|
|
512
|
+
expect(events).toContainEqual({ role: 'assistant', type: 'modelMessageStartEvent' });
|
|
513
|
+
expect(startEvent).toStrictEqual({
|
|
514
|
+
type: 'modelContentBlockStartEvent',
|
|
515
|
+
start: { type: 'toolUseStart', name: 'get_weather', toolUseId: 'tool-use-123' },
|
|
516
|
+
});
|
|
517
|
+
expect(inputDeltaEvent).toStrictEqual({
|
|
518
|
+
type: 'modelContentBlockDeltaEvent',
|
|
519
|
+
delta: { type: 'toolUseInputDelta', input: '{"location":"San Francisco"}' },
|
|
520
|
+
});
|
|
521
|
+
expect(events).toContainEqual({ type: 'modelContentBlockStopEvent' });
|
|
522
|
+
expect(events).toContainEqual({ stopReason: 'toolUse', type: 'modelMessageStopEvent' });
|
|
523
|
+
expect(events).toContainEqual({
|
|
524
|
+
type: 'modelMetadataEvent',
|
|
525
|
+
usage: { inputTokens: 10, outputTokens: 25, totalTokens: 35 },
|
|
526
|
+
metrics: { latencyMs: 120 },
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
it('yields and validates reasoningText events correctly', async () => {
|
|
530
|
+
const mockSend = vi.fn(async () => {
|
|
531
|
+
if (stream) {
|
|
532
|
+
return {
|
|
533
|
+
stream: (async function* () {
|
|
534
|
+
yield { messageStart: { role: 'assistant' } };
|
|
535
|
+
yield { contentBlockStart: {} };
|
|
536
|
+
yield {
|
|
537
|
+
contentBlockDelta: { delta: { reasoningContent: { text: 'Thinking...' } } },
|
|
538
|
+
};
|
|
539
|
+
yield { contentBlockStop: {} };
|
|
540
|
+
yield { messageStop: { stopReason: 'end_turn' } };
|
|
541
|
+
yield {
|
|
542
|
+
metadata: {
|
|
543
|
+
usage: { inputTokens: 15, outputTokens: 30, totalTokens: 45 },
|
|
544
|
+
metrics: { latencyMs: 150 },
|
|
545
|
+
},
|
|
546
|
+
};
|
|
547
|
+
})(),
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
return {
|
|
552
|
+
output: {
|
|
553
|
+
message: {
|
|
554
|
+
role: 'assistant',
|
|
555
|
+
content: [{ reasoningContent: { reasoningText: { text: 'Thinking...' } } }],
|
|
556
|
+
},
|
|
557
|
+
},
|
|
558
|
+
stopReason: 'end_turn',
|
|
559
|
+
usage: { inputTokens: 15, outputTokens: 30, totalTokens: 45 },
|
|
560
|
+
metrics: { latencyMs: 150 },
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
vi.mocked(BedrockRuntimeClient).mockImplementation(function () {
|
|
565
|
+
return { send: mockSend };
|
|
566
|
+
});
|
|
567
|
+
const provider = new BedrockModel({ stream });
|
|
568
|
+
const messages = [
|
|
569
|
+
{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'A question.' }] },
|
|
570
|
+
];
|
|
571
|
+
const events = await collectIterator(provider.stream(messages));
|
|
572
|
+
expect(events).toContainEqual({ role: 'assistant', type: 'modelMessageStartEvent' });
|
|
573
|
+
expect(events).toContainEqual({ type: 'modelContentBlockStartEvent' });
|
|
574
|
+
expect(events).toContainEqual({
|
|
575
|
+
type: 'modelContentBlockDeltaEvent',
|
|
576
|
+
delta: { type: 'reasoningContentDelta', text: 'Thinking...' },
|
|
577
|
+
});
|
|
578
|
+
expect(events).toContainEqual({ type: 'modelContentBlockStopEvent' });
|
|
579
|
+
expect(events).toContainEqual({ stopReason: 'endTurn', type: 'modelMessageStopEvent' });
|
|
580
|
+
expect(events).toContainEqual({
|
|
581
|
+
type: 'modelMetadataEvent',
|
|
582
|
+
usage: { inputTokens: 15, outputTokens: 30, totalTokens: 45 },
|
|
583
|
+
metrics: { latencyMs: 150 },
|
|
584
|
+
});
|
|
585
|
+
});
|
|
586
|
+
it('yields and validates redactedContent events correctly', async () => {
|
|
587
|
+
const redactedBytes = new Uint8Array([1, 2, 3]);
|
|
588
|
+
const mockSend = vi.fn(async () => {
|
|
589
|
+
if (stream) {
|
|
590
|
+
return {
|
|
591
|
+
stream: (async function* () {
|
|
592
|
+
yield { messageStart: { role: 'assistant' } };
|
|
593
|
+
yield { contentBlockStart: {} };
|
|
594
|
+
yield {
|
|
595
|
+
contentBlockDelta: {
|
|
596
|
+
delta: { reasoningContent: { redactedContent: redactedBytes } },
|
|
597
|
+
},
|
|
598
|
+
};
|
|
599
|
+
yield { contentBlockStop: {} };
|
|
600
|
+
yield { messageStop: { stopReason: 'end_turn' } };
|
|
601
|
+
yield {
|
|
602
|
+
metadata: { usage: { inputTokens: 15, outputTokens: 5, totalTokens: 20 }, metrics: { latencyMs: 110 } },
|
|
603
|
+
};
|
|
604
|
+
})(),
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
else {
|
|
608
|
+
return {
|
|
609
|
+
output: {
|
|
610
|
+
message: {
|
|
611
|
+
role: 'assistant',
|
|
612
|
+
content: [{ reasoningContent: { redactedContent: redactedBytes } }],
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
stopReason: 'end_turn',
|
|
616
|
+
usage: { inputTokens: 15, outputTokens: 5, totalTokens: 20 },
|
|
617
|
+
metrics: { latencyMs: 110 },
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
vi.mocked(BedrockRuntimeClient).mockImplementation(function () {
|
|
622
|
+
return { send: mockSend };
|
|
623
|
+
});
|
|
624
|
+
const provider = new BedrockModel({ stream });
|
|
625
|
+
const messages = [
|
|
626
|
+
{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'A sensitive question.' }] },
|
|
627
|
+
];
|
|
628
|
+
const events = await collectIterator(provider.stream(messages));
|
|
629
|
+
expect(events).toContainEqual({ role: 'assistant', type: 'modelMessageStartEvent' });
|
|
630
|
+
expect(events).toContainEqual({ type: 'modelContentBlockStartEvent' });
|
|
631
|
+
expect(events).toContainEqual({
|
|
632
|
+
type: 'modelContentBlockDeltaEvent',
|
|
633
|
+
delta: { type: 'reasoningContentDelta', redactedContent: redactedBytes },
|
|
634
|
+
});
|
|
635
|
+
expect(events).toContainEqual({ type: 'modelContentBlockStopEvent' });
|
|
636
|
+
expect(events).toContainEqual({ stopReason: 'endTurn', type: 'modelMessageStopEvent' });
|
|
637
|
+
expect(events).toContainEqual({
|
|
638
|
+
type: 'modelMetadataEvent',
|
|
639
|
+
usage: { inputTokens: 15, outputTokens: 5, totalTokens: 20 },
|
|
640
|
+
metrics: { latencyMs: 110 },
|
|
641
|
+
});
|
|
642
|
+
});
|
|
643
|
+
describe('error handling', async () => {
|
|
644
|
+
const { ValidationException } = await import('@aws-sdk/client-bedrock-runtime');
|
|
645
|
+
it.each([
|
|
646
|
+
{
|
|
647
|
+
name: 'ContextWindowOverflowError for context overflow',
|
|
648
|
+
error: new Error('Input is too long for requested model'),
|
|
649
|
+
expected: ContextWindowOverflowError,
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
name: 'ValidationException for invalid input',
|
|
653
|
+
error: new ValidationException({ message: 'ValidationException', $metadata: {} }),
|
|
654
|
+
expected: ValidationException,
|
|
655
|
+
},
|
|
656
|
+
])('throws $name', async ({ error, expected }) => {
|
|
657
|
+
vi.clearAllMocks();
|
|
658
|
+
const mockSendError = vi.fn().mockRejectedValue(error);
|
|
659
|
+
vi.mocked(BedrockRuntimeClient).mockImplementation(function () {
|
|
660
|
+
return { send: mockSendError };
|
|
661
|
+
});
|
|
662
|
+
const provider = new BedrockModel();
|
|
663
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
664
|
+
await expect(collectIterator(provider.stream(messages))).rejects.toThrow(expected);
|
|
665
|
+
});
|
|
666
|
+
});
|
|
667
|
+
});
|
|
668
|
+
describe('stream', () => {
|
|
669
|
+
it('handles tool use input delta', async () => {
|
|
670
|
+
setupMockSend(async function* () {
|
|
671
|
+
yield { messageStart: { role: 'assistant' } };
|
|
672
|
+
yield {
|
|
673
|
+
contentBlockStart: { start: { toolUse: { name: 'calc', toolUseId: 'id' } } },
|
|
674
|
+
};
|
|
675
|
+
yield { contentBlockDelta: { delta: { toolUse: { input: '{"a": 1}' } } } };
|
|
676
|
+
yield { contentBlockStop: {} };
|
|
677
|
+
yield { messageStop: { stopReason: 'tool_use' } };
|
|
678
|
+
yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
|
|
679
|
+
});
|
|
680
|
+
const provider = new BedrockModel();
|
|
681
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
682
|
+
const events = await collectIterator(provider.stream(messages));
|
|
683
|
+
expect(events).toContainEqual({
|
|
684
|
+
type: 'modelContentBlockDeltaEvent',
|
|
685
|
+
delta: {
|
|
686
|
+
type: 'toolUseInputDelta',
|
|
687
|
+
input: '{"a": 1}',
|
|
688
|
+
},
|
|
689
|
+
});
|
|
690
|
+
});
|
|
691
|
+
it('handles reasoning content delta with both text and signature, as well as redactedContent', async () => {
|
|
692
|
+
setupMockSend(async function* () {
|
|
693
|
+
yield { messageStart: { role: 'assistant' } };
|
|
694
|
+
yield { contentBlockStart: {} };
|
|
695
|
+
yield {
|
|
696
|
+
contentBlockDelta: {
|
|
697
|
+
delta: { reasoningContent: { text: 'thinking...', signature: 'sig123' } },
|
|
698
|
+
},
|
|
699
|
+
};
|
|
700
|
+
yield {
|
|
701
|
+
contentBlockDelta: {
|
|
702
|
+
delta: { reasoningContent: { redactedContent: new Uint8Array(1) } },
|
|
703
|
+
},
|
|
704
|
+
};
|
|
705
|
+
yield { contentBlockStop: {} };
|
|
706
|
+
yield { messageStop: { stopReason: 'end_turn' } };
|
|
707
|
+
yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
|
|
708
|
+
});
|
|
709
|
+
const provider = new BedrockModel();
|
|
710
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
711
|
+
const events = await collectIterator(provider.stream(messages));
|
|
712
|
+
expect(events).toContainEqual({
|
|
713
|
+
type: 'modelContentBlockDeltaEvent',
|
|
714
|
+
delta: {
|
|
715
|
+
type: 'reasoningContentDelta',
|
|
716
|
+
text: 'thinking...',
|
|
717
|
+
signature: 'sig123',
|
|
718
|
+
},
|
|
719
|
+
});
|
|
720
|
+
expect(events).toContainEqual({
|
|
721
|
+
type: 'modelContentBlockDeltaEvent',
|
|
722
|
+
delta: {
|
|
723
|
+
type: 'reasoningContentDelta',
|
|
724
|
+
redactedContent: new Uint8Array(1),
|
|
725
|
+
},
|
|
726
|
+
});
|
|
727
|
+
});
|
|
728
|
+
it('handles reasoning content delta with only text, skips unsupported types', async () => {
|
|
729
|
+
setupMockSend(async function* () {
|
|
730
|
+
yield { messageStart: { role: 'assistant' } };
|
|
731
|
+
yield { contentBlockStart: {} };
|
|
732
|
+
yield {
|
|
733
|
+
contentBlockDelta: {
|
|
734
|
+
delta: { reasoningContent: { text: 'thinking...' } },
|
|
735
|
+
},
|
|
736
|
+
};
|
|
737
|
+
yield {
|
|
738
|
+
contentBlockDelta: {
|
|
739
|
+
delta: { unknown: 'type' },
|
|
740
|
+
},
|
|
741
|
+
};
|
|
742
|
+
yield { contentBlockStop: {} };
|
|
743
|
+
yield { messageStop: { stopReason: 'end_turn' } };
|
|
744
|
+
yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
|
|
745
|
+
yield { unknown: 'type' };
|
|
746
|
+
});
|
|
747
|
+
const provider = new BedrockModel();
|
|
748
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
749
|
+
const events = await collectIterator(provider.stream(messages));
|
|
750
|
+
const reasoningDelta = events.find((e) => e.type === 'modelContentBlockDeltaEvent' && e.delta.type === 'reasoningContentDelta');
|
|
751
|
+
expect(reasoningDelta).toBeDefined();
|
|
752
|
+
if (reasoningDelta?.type === 'modelContentBlockDeltaEvent' &&
|
|
753
|
+
reasoningDelta.delta.type === 'reasoningContentDelta') {
|
|
754
|
+
expect(reasoningDelta.delta.text).toBe('thinking...');
|
|
755
|
+
expect(reasoningDelta.delta.signature).toBeUndefined();
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
it('handles reasoning content delta with only signature', async () => {
|
|
759
|
+
setupMockSend(async function* () {
|
|
760
|
+
yield { messageStart: { role: 'assistant' } };
|
|
761
|
+
yield { contentBlockStart: {} };
|
|
762
|
+
yield {
|
|
763
|
+
contentBlockDelta: {
|
|
764
|
+
delta: { reasoningContent: { signature: 'sig123' } },
|
|
765
|
+
},
|
|
766
|
+
};
|
|
767
|
+
yield { contentBlockStop: {} };
|
|
768
|
+
yield { messageStop: { stopReason: 'end_turn' } };
|
|
769
|
+
yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
|
|
770
|
+
});
|
|
771
|
+
const provider = new BedrockModel();
|
|
772
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
773
|
+
const events = await collectIterator(provider.stream(messages));
|
|
774
|
+
const reasoningDelta = events.find((e) => e.type === 'modelContentBlockDeltaEvent' && e.delta.type === 'reasoningContentDelta');
|
|
775
|
+
expect(reasoningDelta).toBeDefined();
|
|
776
|
+
if (reasoningDelta?.type === 'modelContentBlockDeltaEvent' &&
|
|
777
|
+
reasoningDelta.delta.type === 'reasoningContentDelta') {
|
|
778
|
+
expect(reasoningDelta.delta.text).toBeUndefined();
|
|
779
|
+
expect(reasoningDelta.delta.signature).toBe('sig123');
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
it('handles cache usage metrics', async () => {
|
|
783
|
+
setupMockSend(async function* () {
|
|
784
|
+
yield { messageStart: { role: 'assistant' } };
|
|
785
|
+
yield { contentBlockStart: {} };
|
|
786
|
+
yield { contentBlockDelta: { delta: { text: 'Hello' } } };
|
|
787
|
+
yield { contentBlockStop: {} };
|
|
788
|
+
yield { messageStop: { stopReason: 'end_turn' } };
|
|
789
|
+
yield {
|
|
790
|
+
metadata: {
|
|
791
|
+
usage: {
|
|
792
|
+
inputTokens: 100,
|
|
793
|
+
outputTokens: 50,
|
|
794
|
+
totalTokens: 150,
|
|
795
|
+
cacheReadInputTokens: 80,
|
|
796
|
+
cacheWriteInputTokens: 20,
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
};
|
|
800
|
+
});
|
|
801
|
+
const provider = new BedrockModel();
|
|
802
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
803
|
+
const events = await collectIterator(provider.stream(messages));
|
|
804
|
+
const metadataEvent = events.find((e) => e.type === 'modelMetadataEvent');
|
|
805
|
+
expect(metadataEvent).toBeDefined();
|
|
806
|
+
if (metadataEvent?.type === 'modelMetadataEvent') {
|
|
807
|
+
expect(metadataEvent.usage?.cacheReadInputTokens).toBe(80);
|
|
808
|
+
expect(metadataEvent.usage?.cacheWriteInputTokens).toBe(20);
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
it('handles trace in metadata', async () => {
|
|
812
|
+
setupMockSend(async function* () {
|
|
813
|
+
yield { messageStart: { role: 'assistant' } };
|
|
814
|
+
yield { contentBlockStart: {} };
|
|
815
|
+
yield { contentBlockDelta: { delta: { text: 'Hello' } } };
|
|
816
|
+
yield { contentBlockStop: {} };
|
|
817
|
+
yield { messageStop: { stopReason: 'end_turn' } };
|
|
818
|
+
yield {
|
|
819
|
+
metadata: {
|
|
820
|
+
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
821
|
+
trace: { guardrail: { action: 'INTERVENED' } },
|
|
822
|
+
},
|
|
823
|
+
};
|
|
824
|
+
});
|
|
825
|
+
const provider = new BedrockModel();
|
|
826
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
827
|
+
const events = await collectIterator(provider.stream(messages));
|
|
828
|
+
const metadataEvent = events.find((e) => e.type === 'modelMetadataEvent');
|
|
829
|
+
expect(metadataEvent).toBeDefined();
|
|
830
|
+
if (metadataEvent?.type === 'modelMetadataEvent') {
|
|
831
|
+
expect(metadataEvent.trace).toBeDefined();
|
|
832
|
+
}
|
|
833
|
+
});
|
|
834
|
+
it('handles additionalModelResponseFields', async () => {
|
|
835
|
+
setupMockSend(async function* () {
|
|
836
|
+
yield { messageStart: { role: 'assistant' } };
|
|
837
|
+
yield { contentBlockStart: {} };
|
|
838
|
+
yield { contentBlockDelta: { delta: { text: 'Hello' } } };
|
|
839
|
+
yield { contentBlockStop: {} };
|
|
840
|
+
yield { messageStop: { stopReason: 'end_turn', additionalModelResponseFields: { customField: 'value' } } };
|
|
841
|
+
yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
|
|
842
|
+
});
|
|
843
|
+
const provider = new BedrockModel();
|
|
844
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
845
|
+
const events = await collectIterator(provider.stream(messages));
|
|
846
|
+
const stopEvent = events.find((e) => e.type === 'modelMessageStopEvent');
|
|
847
|
+
expect(stopEvent).toBeDefined();
|
|
848
|
+
if (stopEvent?.type === 'modelMessageStopEvent') {
|
|
849
|
+
expect(stopEvent.additionalModelResponseFields).toStrictEqual({ customField: 'value' });
|
|
850
|
+
}
|
|
851
|
+
});
|
|
852
|
+
describe('handles all stop reason types', () => {
|
|
853
|
+
const stopReasons = [
|
|
854
|
+
['end_turn', 'endTurn'],
|
|
855
|
+
['tool_use', 'toolUse'],
|
|
856
|
+
['max_tokens', 'maxTokens'],
|
|
857
|
+
['stop_sequence', 'stopSequence'],
|
|
858
|
+
['content_filtered', 'contentFiltered'],
|
|
859
|
+
['guardrail_intervened', 'guardrailIntervened'],
|
|
860
|
+
['model_context_window_exceeded', 'modelContextWindowExceeded'],
|
|
861
|
+
['new_stop_reason', 'newStopReason'],
|
|
862
|
+
];
|
|
863
|
+
for (const [bedrockReason, expectedReason] of stopReasons) {
|
|
864
|
+
it(`handles ${bedrockReason} stop reason types`, async () => {
|
|
865
|
+
setupMockSend(async function* () {
|
|
866
|
+
yield { messageStart: { role: 'assistant' } };
|
|
867
|
+
yield { messageStop: { stopReason: bedrockReason } };
|
|
868
|
+
yield { metadata: { usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 } } };
|
|
869
|
+
});
|
|
870
|
+
const provider = new BedrockModel();
|
|
871
|
+
const messages = [
|
|
872
|
+
{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] },
|
|
873
|
+
];
|
|
874
|
+
const events = [];
|
|
875
|
+
for await (const event of provider.stream(messages)) {
|
|
876
|
+
events.push(event);
|
|
877
|
+
}
|
|
878
|
+
const stopEvent = events.find((e) => e.type === 'modelMessageStopEvent');
|
|
879
|
+
expect(stopEvent).toBeDefined();
|
|
880
|
+
if (stopEvent?.type === 'modelMessageStopEvent') {
|
|
881
|
+
expect(stopEvent.stopReason).toBe(expectedReason);
|
|
882
|
+
}
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
});
|
|
887
|
+
describe('system prompt formatting', async () => {
|
|
888
|
+
const { ConverseStreamCommand } = await import('@aws-sdk/client-bedrock-runtime');
|
|
889
|
+
const mockConverseStreamCommand = vi.mocked(ConverseStreamCommand);
|
|
890
|
+
beforeEach(() => {
|
|
891
|
+
vi.clearAllMocks();
|
|
892
|
+
});
|
|
893
|
+
it('formats string system prompt with cachePrompt config', async () => {
|
|
894
|
+
const provider = new BedrockModel({ cachePrompt: 'default' });
|
|
895
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
896
|
+
const options = {
|
|
897
|
+
systemPrompt: 'You are a helpful assistant',
|
|
898
|
+
};
|
|
899
|
+
collectIterator(provider.stream(messages, options));
|
|
900
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
901
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
902
|
+
messages: [
|
|
903
|
+
{
|
|
904
|
+
role: 'user',
|
|
905
|
+
content: [{ text: 'Hello' }],
|
|
906
|
+
},
|
|
907
|
+
],
|
|
908
|
+
system: [{ text: 'You are a helpful assistant' }, { cachePoint: { type: 'default' } }],
|
|
909
|
+
});
|
|
910
|
+
});
|
|
911
|
+
it('formats array system prompt with text blocks only', async () => {
|
|
912
|
+
const provider = new BedrockModel();
|
|
913
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
914
|
+
const options = {
|
|
915
|
+
systemPrompt: [
|
|
916
|
+
{ type: 'textBlock', text: 'You are a helpful assistant' },
|
|
917
|
+
{ type: 'textBlock', text: 'Additional context here' },
|
|
918
|
+
],
|
|
919
|
+
};
|
|
920
|
+
collectIterator(provider.stream(messages, options));
|
|
921
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
922
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
923
|
+
messages: [
|
|
924
|
+
{
|
|
925
|
+
role: 'user',
|
|
926
|
+
content: [{ text: 'Hello' }],
|
|
927
|
+
},
|
|
928
|
+
],
|
|
929
|
+
system: [{ text: 'You are a helpful assistant' }, { text: 'Additional context here' }],
|
|
930
|
+
});
|
|
931
|
+
});
|
|
932
|
+
it('formats array system prompt with cache points', async () => {
|
|
933
|
+
const provider = new BedrockModel();
|
|
934
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
935
|
+
const options = {
|
|
936
|
+
systemPrompt: [
|
|
937
|
+
{ type: 'textBlock', text: 'You are a helpful assistant' },
|
|
938
|
+
{ type: 'textBlock', text: 'Large context document' },
|
|
939
|
+
{ type: 'cachePointBlock', cacheType: 'default' },
|
|
940
|
+
],
|
|
941
|
+
};
|
|
942
|
+
collectIterator(provider.stream(messages, options));
|
|
943
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
944
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
945
|
+
messages: [
|
|
946
|
+
{
|
|
947
|
+
role: 'user',
|
|
948
|
+
content: [{ text: 'Hello' }],
|
|
949
|
+
},
|
|
950
|
+
],
|
|
951
|
+
system: [
|
|
952
|
+
{ text: 'You are a helpful assistant' },
|
|
953
|
+
{ text: 'Large context document' },
|
|
954
|
+
{ cachePoint: { type: 'default' } },
|
|
955
|
+
],
|
|
956
|
+
});
|
|
957
|
+
});
|
|
958
|
+
it('warns when both array system prompt and cachePrompt config are provided', async () => {
|
|
959
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
960
|
+
const provider = new BedrockModel({ cachePrompt: 'default' });
|
|
961
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
962
|
+
const options = {
|
|
963
|
+
systemPrompt: [
|
|
964
|
+
{ type: 'textBlock', text: 'You are a helpful assistant' },
|
|
965
|
+
{ type: 'cachePointBlock', cacheType: 'default' },
|
|
966
|
+
],
|
|
967
|
+
};
|
|
968
|
+
collectIterator(provider.stream(messages, options));
|
|
969
|
+
// Verify warning was logged
|
|
970
|
+
expect(warnSpy).toHaveBeenCalledWith('cachePrompt config is ignored when systemPrompt is an array. Use explicit cache points in the array instead.');
|
|
971
|
+
// Verify array is used as-is (cachePrompt config ignored)
|
|
972
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
973
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
974
|
+
messages: [
|
|
975
|
+
{
|
|
976
|
+
role: 'user',
|
|
977
|
+
content: [{ text: 'Hello' }],
|
|
978
|
+
},
|
|
979
|
+
],
|
|
980
|
+
system: [{ text: 'You are a helpful assistant' }, { cachePoint: { type: 'default' } }],
|
|
981
|
+
});
|
|
982
|
+
warnSpy.mockRestore();
|
|
983
|
+
});
|
|
984
|
+
it('handles empty array system prompt', async () => {
|
|
985
|
+
const provider = new BedrockModel();
|
|
986
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
987
|
+
const options = {
|
|
988
|
+
systemPrompt: [],
|
|
989
|
+
};
|
|
990
|
+
collectIterator(provider.stream(messages, options));
|
|
991
|
+
// Empty array should not set system field
|
|
992
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
993
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
994
|
+
messages: [
|
|
995
|
+
{
|
|
996
|
+
role: 'user',
|
|
997
|
+
content: [{ text: 'Hello' }],
|
|
998
|
+
},
|
|
999
|
+
],
|
|
1000
|
+
});
|
|
1001
|
+
});
|
|
1002
|
+
it('formats array system prompt with guard content', async () => {
|
|
1003
|
+
const provider = new BedrockModel();
|
|
1004
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
1005
|
+
const options = {
|
|
1006
|
+
systemPrompt: [
|
|
1007
|
+
new TextBlock('You are a helpful assistant'),
|
|
1008
|
+
new GuardContentBlock({
|
|
1009
|
+
text: {
|
|
1010
|
+
qualifiers: ['grounding_source'],
|
|
1011
|
+
text: 'This content should be evaluated for grounding.',
|
|
1012
|
+
},
|
|
1013
|
+
}),
|
|
1014
|
+
],
|
|
1015
|
+
};
|
|
1016
|
+
collectIterator(provider.stream(messages, options));
|
|
1017
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
1018
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
1019
|
+
messages: [
|
|
1020
|
+
{
|
|
1021
|
+
role: 'user',
|
|
1022
|
+
content: [{ text: 'Hello' }],
|
|
1023
|
+
},
|
|
1024
|
+
],
|
|
1025
|
+
system: [
|
|
1026
|
+
{ text: 'You are a helpful assistant' },
|
|
1027
|
+
{
|
|
1028
|
+
guardContent: {
|
|
1029
|
+
text: {
|
|
1030
|
+
text: 'This content should be evaluated for grounding.',
|
|
1031
|
+
qualifiers: ['grounding_source'],
|
|
1032
|
+
},
|
|
1033
|
+
},
|
|
1034
|
+
},
|
|
1035
|
+
],
|
|
1036
|
+
});
|
|
1037
|
+
});
|
|
1038
|
+
it('formats mixed system prompt with text, guard content, and cache points', async () => {
|
|
1039
|
+
const provider = new BedrockModel();
|
|
1040
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
1041
|
+
const options = {
|
|
1042
|
+
systemPrompt: [
|
|
1043
|
+
new TextBlock('You are a helpful assistant'),
|
|
1044
|
+
new GuardContentBlock({
|
|
1045
|
+
text: {
|
|
1046
|
+
qualifiers: ['grounding_source', 'query'],
|
|
1047
|
+
text: 'Guard content',
|
|
1048
|
+
},
|
|
1049
|
+
}),
|
|
1050
|
+
new TextBlock('Additional context'),
|
|
1051
|
+
new CachePointBlock({ cacheType: 'default' }),
|
|
1052
|
+
],
|
|
1053
|
+
};
|
|
1054
|
+
collectIterator(provider.stream(messages, options));
|
|
1055
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
1056
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
1057
|
+
messages: [
|
|
1058
|
+
{
|
|
1059
|
+
role: 'user',
|
|
1060
|
+
content: [{ text: 'Hello' }],
|
|
1061
|
+
},
|
|
1062
|
+
],
|
|
1063
|
+
system: [
|
|
1064
|
+
{ text: 'You are a helpful assistant' },
|
|
1065
|
+
{
|
|
1066
|
+
guardContent: {
|
|
1067
|
+
text: {
|
|
1068
|
+
text: 'Guard content',
|
|
1069
|
+
qualifiers: ['grounding_source', 'query'],
|
|
1070
|
+
},
|
|
1071
|
+
},
|
|
1072
|
+
},
|
|
1073
|
+
{ text: 'Additional context' },
|
|
1074
|
+
{ cachePoint: { type: 'default' } },
|
|
1075
|
+
],
|
|
1076
|
+
});
|
|
1077
|
+
});
|
|
1078
|
+
it('formats guard content with all qualifier types', async () => {
|
|
1079
|
+
const provider = new BedrockModel();
|
|
1080
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
1081
|
+
const options = {
|
|
1082
|
+
systemPrompt: [
|
|
1083
|
+
new GuardContentBlock({
|
|
1084
|
+
text: {
|
|
1085
|
+
qualifiers: ['grounding_source', 'query', 'guard_content'],
|
|
1086
|
+
text: 'Multi-qualifier guard content',
|
|
1087
|
+
},
|
|
1088
|
+
}),
|
|
1089
|
+
],
|
|
1090
|
+
};
|
|
1091
|
+
collectIterator(provider.stream(messages, options));
|
|
1092
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
1093
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
1094
|
+
messages: [
|
|
1095
|
+
{
|
|
1096
|
+
role: 'user',
|
|
1097
|
+
content: [{ text: 'Hello' }],
|
|
1098
|
+
},
|
|
1099
|
+
],
|
|
1100
|
+
system: [
|
|
1101
|
+
{
|
|
1102
|
+
guardContent: {
|
|
1103
|
+
text: {
|
|
1104
|
+
text: 'Multi-qualifier guard content',
|
|
1105
|
+
qualifiers: ['grounding_source', 'query', 'guard_content'],
|
|
1106
|
+
},
|
|
1107
|
+
},
|
|
1108
|
+
},
|
|
1109
|
+
],
|
|
1110
|
+
});
|
|
1111
|
+
});
|
|
1112
|
+
it('formats guard content with image in system prompt', async () => {
|
|
1113
|
+
const provider = new BedrockModel();
|
|
1114
|
+
const messages = [{ type: 'message', role: 'user', content: [{ type: 'textBlock', text: 'Hello' }] }];
|
|
1115
|
+
const imageBytes = new Uint8Array([1, 2, 3, 4]);
|
|
1116
|
+
const options = {
|
|
1117
|
+
systemPrompt: [
|
|
1118
|
+
new GuardContentBlock({
|
|
1119
|
+
image: {
|
|
1120
|
+
format: 'jpeg',
|
|
1121
|
+
source: { bytes: imageBytes },
|
|
1122
|
+
},
|
|
1123
|
+
}),
|
|
1124
|
+
],
|
|
1125
|
+
};
|
|
1126
|
+
collectIterator(provider.stream(messages, options));
|
|
1127
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
1128
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
1129
|
+
messages: [
|
|
1130
|
+
{
|
|
1131
|
+
role: 'user',
|
|
1132
|
+
content: [{ text: 'Hello' }],
|
|
1133
|
+
},
|
|
1134
|
+
],
|
|
1135
|
+
system: [
|
|
1136
|
+
{
|
|
1137
|
+
guardContent: {
|
|
1138
|
+
image: {
|
|
1139
|
+
format: 'jpeg',
|
|
1140
|
+
source: { bytes: imageBytes },
|
|
1141
|
+
},
|
|
1142
|
+
},
|
|
1143
|
+
},
|
|
1144
|
+
],
|
|
1145
|
+
});
|
|
1146
|
+
});
|
|
1147
|
+
});
|
|
1148
|
+
describe('guard content in messages', async () => {
|
|
1149
|
+
const { ConverseStreamCommand } = await import('@aws-sdk/client-bedrock-runtime');
|
|
1150
|
+
const mockConverseStreamCommand = vi.mocked(ConverseStreamCommand);
|
|
1151
|
+
beforeEach(() => {
|
|
1152
|
+
vi.clearAllMocks();
|
|
1153
|
+
});
|
|
1154
|
+
it('formats guard content with text in message', async () => {
|
|
1155
|
+
const provider = new BedrockModel();
|
|
1156
|
+
const messages = [
|
|
1157
|
+
{
|
|
1158
|
+
type: 'message',
|
|
1159
|
+
role: 'user',
|
|
1160
|
+
content: [
|
|
1161
|
+
new TextBlock('Verify this information:'),
|
|
1162
|
+
new GuardContentBlock({
|
|
1163
|
+
text: {
|
|
1164
|
+
qualifiers: ['grounding_source'],
|
|
1165
|
+
text: 'The capital of France is Paris.',
|
|
1166
|
+
},
|
|
1167
|
+
}),
|
|
1168
|
+
],
|
|
1169
|
+
},
|
|
1170
|
+
];
|
|
1171
|
+
collectIterator(provider.stream(messages));
|
|
1172
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
1173
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
1174
|
+
messages: [
|
|
1175
|
+
{
|
|
1176
|
+
role: 'user',
|
|
1177
|
+
content: [
|
|
1178
|
+
{ text: 'Verify this information:' },
|
|
1179
|
+
{
|
|
1180
|
+
guardContent: {
|
|
1181
|
+
text: {
|
|
1182
|
+
text: 'The capital of France is Paris.',
|
|
1183
|
+
qualifiers: ['grounding_source'],
|
|
1184
|
+
},
|
|
1185
|
+
},
|
|
1186
|
+
},
|
|
1187
|
+
],
|
|
1188
|
+
},
|
|
1189
|
+
],
|
|
1190
|
+
});
|
|
1191
|
+
});
|
|
1192
|
+
it('formats guard content with image in message', async () => {
|
|
1193
|
+
const provider = new BedrockModel();
|
|
1194
|
+
const imageBytes = new Uint8Array([1, 2, 3, 4]);
|
|
1195
|
+
const messages = [
|
|
1196
|
+
{
|
|
1197
|
+
type: 'message',
|
|
1198
|
+
role: 'user',
|
|
1199
|
+
content: [
|
|
1200
|
+
new TextBlock('Is this image safe?'),
|
|
1201
|
+
new GuardContentBlock({
|
|
1202
|
+
image: {
|
|
1203
|
+
format: 'jpeg',
|
|
1204
|
+
source: { bytes: imageBytes },
|
|
1205
|
+
},
|
|
1206
|
+
}),
|
|
1207
|
+
],
|
|
1208
|
+
},
|
|
1209
|
+
];
|
|
1210
|
+
collectIterator(provider.stream(messages));
|
|
1211
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
1212
|
+
modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
1213
|
+
messages: [
|
|
1214
|
+
{
|
|
1215
|
+
role: 'user',
|
|
1216
|
+
content: [
|
|
1217
|
+
{ text: 'Is this image safe?' },
|
|
1218
|
+
{
|
|
1219
|
+
guardContent: {
|
|
1220
|
+
image: {
|
|
1221
|
+
format: 'jpeg',
|
|
1222
|
+
source: { bytes: imageBytes },
|
|
1223
|
+
},
|
|
1224
|
+
},
|
|
1225
|
+
},
|
|
1226
|
+
],
|
|
1227
|
+
},
|
|
1228
|
+
],
|
|
1229
|
+
});
|
|
1230
|
+
});
|
|
1231
|
+
});
|
|
1232
|
+
describe('includeToolResultStatus configuration', async () => {
|
|
1233
|
+
const { ConverseStreamCommand } = await import('@aws-sdk/client-bedrock-runtime');
|
|
1234
|
+
const mockConverseStreamCommand = vi.mocked(ConverseStreamCommand);
|
|
1235
|
+
describe('when includeToolResultStatus is true', () => {
|
|
1236
|
+
it('always includes status field in tool results', async () => {
|
|
1237
|
+
const provider = new BedrockModel({ includeToolResultStatus: true });
|
|
1238
|
+
const messages = [
|
|
1239
|
+
{
|
|
1240
|
+
type: 'message',
|
|
1241
|
+
role: 'user',
|
|
1242
|
+
content: [
|
|
1243
|
+
{
|
|
1244
|
+
type: 'toolResultBlock',
|
|
1245
|
+
toolUseId: 'tool-123',
|
|
1246
|
+
status: 'success',
|
|
1247
|
+
content: [{ type: 'textBlock', text: 'Result' }],
|
|
1248
|
+
},
|
|
1249
|
+
],
|
|
1250
|
+
},
|
|
1251
|
+
];
|
|
1252
|
+
collectIterator(provider.stream(messages));
|
|
1253
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
1254
|
+
messages: [
|
|
1255
|
+
{
|
|
1256
|
+
content: [
|
|
1257
|
+
{
|
|
1258
|
+
toolResult: {
|
|
1259
|
+
content: [{ text: 'Result' }],
|
|
1260
|
+
status: 'success',
|
|
1261
|
+
toolUseId: 'tool-123',
|
|
1262
|
+
},
|
|
1263
|
+
},
|
|
1264
|
+
],
|
|
1265
|
+
role: 'user',
|
|
1266
|
+
},
|
|
1267
|
+
],
|
|
1268
|
+
modelId: expect.any(String),
|
|
1269
|
+
});
|
|
1270
|
+
});
|
|
1271
|
+
});
|
|
1272
|
+
describe('when includeToolResultStatus is false', () => {
|
|
1273
|
+
it('never includes status field in tool results', async () => {
|
|
1274
|
+
const provider = new BedrockModel({ includeToolResultStatus: false });
|
|
1275
|
+
const messages = [
|
|
1276
|
+
{
|
|
1277
|
+
type: 'message',
|
|
1278
|
+
role: 'user',
|
|
1279
|
+
content: [
|
|
1280
|
+
{
|
|
1281
|
+
type: 'toolResultBlock',
|
|
1282
|
+
toolUseId: 'tool-123',
|
|
1283
|
+
status: 'success',
|
|
1284
|
+
content: [{ type: 'textBlock', text: 'Result' }],
|
|
1285
|
+
},
|
|
1286
|
+
],
|
|
1287
|
+
},
|
|
1288
|
+
];
|
|
1289
|
+
collectIterator(provider.stream(messages));
|
|
1290
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
1291
|
+
messages: [
|
|
1292
|
+
{
|
|
1293
|
+
content: [
|
|
1294
|
+
{
|
|
1295
|
+
toolResult: {
|
|
1296
|
+
content: [{ text: 'Result' }],
|
|
1297
|
+
toolUseId: 'tool-123',
|
|
1298
|
+
},
|
|
1299
|
+
},
|
|
1300
|
+
],
|
|
1301
|
+
role: 'user',
|
|
1302
|
+
},
|
|
1303
|
+
],
|
|
1304
|
+
modelId: expect.any(String),
|
|
1305
|
+
});
|
|
1306
|
+
});
|
|
1307
|
+
});
|
|
1308
|
+
describe('when includeToolResultStatus is auto', () => {
|
|
1309
|
+
it('includes status field for Claude models', async () => {
|
|
1310
|
+
const provider = new BedrockModel({
|
|
1311
|
+
modelId: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
|
|
1312
|
+
includeToolResultStatus: 'auto',
|
|
1313
|
+
});
|
|
1314
|
+
const messages = [
|
|
1315
|
+
{
|
|
1316
|
+
type: 'message',
|
|
1317
|
+
role: 'user',
|
|
1318
|
+
content: [
|
|
1319
|
+
{
|
|
1320
|
+
type: 'toolResultBlock',
|
|
1321
|
+
toolUseId: 'tool-123',
|
|
1322
|
+
status: 'success',
|
|
1323
|
+
content: [{ type: 'textBlock', text: 'Result' }],
|
|
1324
|
+
},
|
|
1325
|
+
],
|
|
1326
|
+
},
|
|
1327
|
+
];
|
|
1328
|
+
collectIterator(provider.stream(messages));
|
|
1329
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
1330
|
+
messages: [
|
|
1331
|
+
{
|
|
1332
|
+
content: [
|
|
1333
|
+
{
|
|
1334
|
+
toolResult: {
|
|
1335
|
+
content: [{ text: 'Result' }],
|
|
1336
|
+
status: 'success',
|
|
1337
|
+
toolUseId: 'tool-123',
|
|
1338
|
+
},
|
|
1339
|
+
},
|
|
1340
|
+
],
|
|
1341
|
+
role: 'user',
|
|
1342
|
+
},
|
|
1343
|
+
],
|
|
1344
|
+
modelId: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
|
|
1345
|
+
});
|
|
1346
|
+
});
|
|
1347
|
+
});
|
|
1348
|
+
describe('when includeToolResultStatus is undefined (default)', () => {
|
|
1349
|
+
it('follows auto logic for non-Claude models', async () => {
|
|
1350
|
+
const provider = new BedrockModel({
|
|
1351
|
+
modelId: 'amazon.nova-lite-v1:0',
|
|
1352
|
+
});
|
|
1353
|
+
const messages = [
|
|
1354
|
+
{
|
|
1355
|
+
type: 'message',
|
|
1356
|
+
role: 'user',
|
|
1357
|
+
content: [
|
|
1358
|
+
{
|
|
1359
|
+
type: 'toolResultBlock',
|
|
1360
|
+
toolUseId: 'tool-123',
|
|
1361
|
+
status: 'success',
|
|
1362
|
+
content: [{ type: 'textBlock', text: 'Result' }],
|
|
1363
|
+
},
|
|
1364
|
+
],
|
|
1365
|
+
},
|
|
1366
|
+
];
|
|
1367
|
+
collectIterator(provider.stream(messages));
|
|
1368
|
+
expect(mockConverseStreamCommand).toHaveBeenLastCalledWith({
|
|
1369
|
+
messages: [
|
|
1370
|
+
{
|
|
1371
|
+
content: [
|
|
1372
|
+
{
|
|
1373
|
+
toolResult: {
|
|
1374
|
+
content: [{ text: 'Result' }],
|
|
1375
|
+
toolUseId: 'tool-123',
|
|
1376
|
+
},
|
|
1377
|
+
},
|
|
1378
|
+
],
|
|
1379
|
+
role: 'user',
|
|
1380
|
+
},
|
|
1381
|
+
],
|
|
1382
|
+
modelId: 'amazon.nova-lite-v1:0',
|
|
1383
|
+
});
|
|
1384
|
+
});
|
|
1385
|
+
});
|
|
1386
|
+
});
|
|
1387
|
+
});
|
|
1388
|
+
//# sourceMappingURL=bedrock.test.js.map
|