@strands-agents/sdk 1.2.0 → 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.
Files changed (231) hide show
  1. package/README.md +13 -13
  2. package/dist/src/__fixtures__/test-sandbox.node.d.ts +15 -0
  3. package/dist/src/__fixtures__/test-sandbox.node.d.ts.map +1 -0
  4. package/dist/src/__fixtures__/test-sandbox.node.js +22 -0
  5. package/dist/src/__fixtures__/test-sandbox.node.js.map +1 -0
  6. package/dist/src/__tests__/mcp.test.js +14 -14
  7. package/dist/src/__tests__/mcp.test.js.map +1 -1
  8. package/dist/src/agent/__tests__/agent.test.js +195 -0
  9. package/dist/src/agent/__tests__/agent.test.js.map +1 -1
  10. package/dist/src/agent/__tests__/printer.test.js +58 -18
  11. package/dist/src/agent/__tests__/printer.test.js.map +1 -1
  12. package/dist/src/agent/__tests__/tool-caller.test.d.ts +2 -0
  13. package/dist/src/agent/__tests__/tool-caller.test.d.ts.map +1 -0
  14. package/dist/src/agent/__tests__/tool-caller.test.js +459 -0
  15. package/dist/src/agent/__tests__/tool-caller.test.js.map +1 -0
  16. package/dist/src/agent/agent.d.ts +68 -2
  17. package/dist/src/agent/agent.d.ts.map +1 -1
  18. package/dist/src/agent/agent.js +125 -66
  19. package/dist/src/agent/agent.js.map +1 -1
  20. package/dist/src/agent/printer.d.ts +14 -1
  21. package/dist/src/agent/printer.d.ts.map +1 -1
  22. package/dist/src/agent/printer.js +33 -5
  23. package/dist/src/agent/printer.js.map +1 -1
  24. package/dist/src/agent/tool-caller.d.ts +149 -0
  25. package/dist/src/agent/tool-caller.d.ts.map +1 -0
  26. package/dist/src/agent/tool-caller.js +198 -0
  27. package/dist/src/agent/tool-caller.js.map +1 -0
  28. package/dist/src/errors.d.ts +17 -0
  29. package/dist/src/errors.d.ts.map +1 -1
  30. package/dist/src/errors.js +21 -0
  31. package/dist/src/errors.js.map +1 -1
  32. package/dist/src/hooks/types.d.ts +2 -0
  33. package/dist/src/hooks/types.d.ts.map +1 -1
  34. package/dist/src/hooks/types.js +2 -0
  35. package/dist/src/hooks/types.js.map +1 -1
  36. package/dist/src/index.d.ts +10 -3
  37. package/dist/src/index.d.ts.map +1 -1
  38. package/dist/src/index.js +6 -1
  39. package/dist/src/index.js.map +1 -1
  40. package/dist/src/interventions/__tests__/handler.test.d.ts +2 -0
  41. package/dist/src/interventions/__tests__/handler.test.d.ts.map +1 -0
  42. package/dist/src/interventions/__tests__/handler.test.js +35 -0
  43. package/dist/src/interventions/__tests__/handler.test.js.map +1 -0
  44. package/dist/src/interventions/__tests__/registry.test.d.ts +2 -0
  45. package/dist/src/interventions/__tests__/registry.test.d.ts.map +1 -0
  46. package/dist/src/interventions/__tests__/registry.test.js +692 -0
  47. package/dist/src/interventions/__tests__/registry.test.js.map +1 -0
  48. package/dist/src/interventions/actions.d.ts +186 -0
  49. package/dist/src/interventions/actions.d.ts.map +1 -0
  50. package/dist/src/interventions/actions.js +56 -0
  51. package/dist/src/interventions/actions.js.map +1 -0
  52. package/dist/src/interventions/handler.d.ts +43 -0
  53. package/dist/src/interventions/handler.d.ts.map +1 -0
  54. package/dist/src/interventions/handler.js +41 -0
  55. package/dist/src/interventions/handler.js.map +1 -0
  56. package/dist/src/interventions/index.d.ts +12 -0
  57. package/dist/src/interventions/index.d.ts.map +1 -0
  58. package/dist/src/interventions/index.js +4 -0
  59. package/dist/src/interventions/index.js.map +1 -0
  60. package/dist/src/interventions/registry.d.ts +36 -0
  61. package/dist/src/interventions/registry.d.ts.map +1 -0
  62. package/dist/src/interventions/registry.js +252 -0
  63. package/dist/src/interventions/registry.js.map +1 -0
  64. package/dist/src/mcp.d.ts +20 -15
  65. package/dist/src/mcp.d.ts.map +1 -1
  66. package/dist/src/mcp.js +15 -8
  67. package/dist/src/mcp.js.map +1 -1
  68. package/dist/src/models/__tests__/anthropic.test.js +72 -8
  69. package/dist/src/models/__tests__/anthropic.test.js.map +1 -1
  70. package/dist/src/models/__tests__/bedrock.test.js +142 -0
  71. package/dist/src/models/__tests__/bedrock.test.js.map +1 -1
  72. package/dist/src/models/anthropic.d.ts +10 -0
  73. package/dist/src/models/anthropic.d.ts.map +1 -1
  74. package/dist/src/models/anthropic.js +24 -8
  75. package/dist/src/models/anthropic.js.map +1 -1
  76. package/dist/src/models/bedrock.d.ts +26 -1
  77. package/dist/src/models/bedrock.d.ts.map +1 -1
  78. package/dist/src/models/bedrock.js +22 -4
  79. package/dist/src/models/bedrock.js.map +1 -1
  80. package/dist/src/models/openai/__tests__/chat.test.js +2 -10
  81. package/dist/src/models/openai/__tests__/chat.test.js.map +1 -1
  82. package/dist/src/models/openai/__tests__/errors.test.d.ts +2 -0
  83. package/dist/src/models/openai/__tests__/errors.test.d.ts.map +1 -0
  84. package/dist/src/models/openai/__tests__/errors.test.js +30 -0
  85. package/dist/src/models/openai/__tests__/errors.test.js.map +1 -0
  86. package/dist/src/models/openai/__tests__/mantle.test.d.ts +2 -0
  87. package/dist/src/models/openai/__tests__/mantle.test.d.ts.map +1 -0
  88. package/dist/src/models/openai/__tests__/mantle.test.js +189 -0
  89. package/dist/src/models/openai/__tests__/mantle.test.js.map +1 -0
  90. package/dist/src/models/openai/__tests__/responses.test.js +0 -19
  91. package/dist/src/models/openai/__tests__/responses.test.js.map +1 -1
  92. package/dist/src/models/openai/errors.d.ts.map +1 -1
  93. package/dist/src/models/openai/errors.js +5 -3
  94. package/dist/src/models/openai/errors.js.map +1 -1
  95. package/dist/src/models/openai/index.d.ts +1 -0
  96. package/dist/src/models/openai/index.d.ts.map +1 -1
  97. package/dist/src/models/openai/mantle.d.ts +77 -0
  98. package/dist/src/models/openai/mantle.d.ts.map +1 -0
  99. package/dist/src/models/openai/mantle.js +83 -0
  100. package/dist/src/models/openai/mantle.js.map +1 -0
  101. package/dist/src/models/openai/model.d.ts.map +1 -1
  102. package/dist/src/models/openai/model.js +29 -1
  103. package/dist/src/models/openai/model.js.map +1 -1
  104. package/dist/src/models/openai/types.d.ts +11 -0
  105. package/dist/src/models/openai/types.d.ts.map +1 -1
  106. package/dist/src/multiagent/__tests__/nodes.test.js +50 -0
  107. package/dist/src/multiagent/__tests__/nodes.test.js.map +1 -1
  108. package/dist/src/multiagent/nodes.d.ts +23 -2
  109. package/dist/src/multiagent/nodes.d.ts.map +1 -1
  110. package/dist/src/multiagent/nodes.js +18 -4
  111. package/dist/src/multiagent/nodes.js.map +1 -1
  112. package/dist/src/registry/__tests__/tool-registry.test.js +50 -1
  113. package/dist/src/registry/__tests__/tool-registry.test.js.map +1 -1
  114. package/dist/src/registry/tool-registry.d.ts +13 -0
  115. package/dist/src/registry/tool-registry.d.ts.map +1 -1
  116. package/dist/src/registry/tool-registry.js +35 -1
  117. package/dist/src/registry/tool-registry.js.map +1 -1
  118. package/dist/src/sandbox/__tests__/posix-shell.test.node.d.ts +2 -0
  119. package/dist/src/sandbox/__tests__/posix-shell.test.node.d.ts.map +1 -0
  120. package/dist/src/sandbox/__tests__/posix-shell.test.node.js +252 -0
  121. package/dist/src/sandbox/__tests__/posix-shell.test.node.js.map +1 -0
  122. package/dist/src/sandbox/base.d.ts +138 -0
  123. package/dist/src/sandbox/base.d.ts.map +1 -0
  124. package/dist/src/sandbox/base.js +84 -0
  125. package/dist/src/sandbox/base.js.map +1 -0
  126. package/dist/src/sandbox/constants.d.ts +7 -0
  127. package/dist/src/sandbox/constants.d.ts.map +1 -0
  128. package/dist/src/sandbox/constants.js +7 -0
  129. package/dist/src/sandbox/constants.js.map +1 -0
  130. package/dist/src/sandbox/posix-shell.d.ts +32 -0
  131. package/dist/src/sandbox/posix-shell.d.ts.map +1 -0
  132. package/dist/src/sandbox/posix-shell.js +78 -0
  133. package/dist/src/sandbox/posix-shell.js.map +1 -0
  134. package/dist/src/sandbox/stream-process.d.ts +32 -0
  135. package/dist/src/sandbox/stream-process.d.ts.map +1 -0
  136. package/dist/src/sandbox/stream-process.js +160 -0
  137. package/dist/src/sandbox/stream-process.js.map +1 -0
  138. package/dist/src/sandbox/types.d.ts +57 -0
  139. package/dist/src/sandbox/types.d.ts.map +1 -0
  140. package/dist/src/sandbox/types.js +8 -0
  141. package/dist/src/sandbox/types.js.map +1 -0
  142. package/dist/src/telemetry/__tests__/meter.test.js +11 -0
  143. package/dist/src/telemetry/__tests__/meter.test.js.map +1 -1
  144. package/dist/src/telemetry/meter.d.ts +10 -6
  145. package/dist/src/telemetry/meter.d.ts.map +1 -1
  146. package/dist/src/telemetry/meter.js +16 -3
  147. package/dist/src/telemetry/meter.js.map +1 -1
  148. package/dist/src/tsconfig.tsbuildinfo +1 -1
  149. package/dist/src/types/__tests__/messages.test.js +28 -0
  150. package/dist/src/types/__tests__/messages.test.js.map +1 -1
  151. package/dist/src/types/agent.d.ts +51 -0
  152. package/dist/src/types/agent.d.ts.map +1 -1
  153. package/dist/src/types/agent.js.map +1 -1
  154. package/dist/src/types/lifecycle-observer.d.ts +18 -0
  155. package/dist/src/types/lifecycle-observer.d.ts.map +1 -0
  156. package/dist/src/types/lifecycle-observer.js +2 -0
  157. package/dist/src/types/lifecycle-observer.js.map +1 -0
  158. package/dist/src/types/messages.d.ts +20 -2
  159. package/dist/src/types/messages.d.ts.map +1 -1
  160. package/dist/src/types/messages.js +9 -0
  161. package/dist/src/types/messages.js.map +1 -1
  162. package/dist/src/utils/shell-quote.d.ts +12 -0
  163. package/dist/src/utils/shell-quote.d.ts.map +1 -0
  164. package/dist/src/utils/shell-quote.js +14 -0
  165. package/dist/src/utils/shell-quote.js.map +1 -0
  166. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.d.ts +2 -0
  167. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.d.ts.map +1 -0
  168. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.js +358 -0
  169. package/dist/src/vended-interventions/hitl/__tests__/hitl.test.js.map +1 -0
  170. package/dist/src/vended-interventions/hitl/hitl.d.ts +115 -0
  171. package/dist/src/vended-interventions/hitl/hitl.d.ts.map +1 -0
  172. package/dist/src/vended-interventions/hitl/hitl.js +138 -0
  173. package/dist/src/vended-interventions/hitl/hitl.js.map +1 -0
  174. package/dist/src/vended-interventions/hitl/index.d.ts +24 -0
  175. package/dist/src/vended-interventions/hitl/index.d.ts.map +1 -0
  176. package/dist/src/vended-interventions/hitl/index.js +23 -0
  177. package/dist/src/vended-interventions/hitl/index.js.map +1 -0
  178. package/dist/src/vended-interventions/steering/__tests__/handler.test.d.ts +2 -0
  179. package/dist/src/vended-interventions/steering/__tests__/handler.test.d.ts.map +1 -0
  180. package/dist/src/vended-interventions/steering/__tests__/handler.test.js +163 -0
  181. package/dist/src/vended-interventions/steering/__tests__/handler.test.js.map +1 -0
  182. package/dist/src/vended-interventions/steering/__tests__/llm.test.d.ts +2 -0
  183. package/dist/src/vended-interventions/steering/__tests__/llm.test.d.ts.map +1 -0
  184. package/dist/src/vended-interventions/steering/__tests__/llm.test.js +60 -0
  185. package/dist/src/vended-interventions/steering/__tests__/llm.test.js.map +1 -0
  186. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.d.ts +2 -0
  187. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.d.ts.map +1 -0
  188. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.js +94 -0
  189. package/dist/src/vended-interventions/steering/__tests__/tool-ledger.test.js.map +1 -0
  190. package/dist/src/vended-interventions/steering/handlers/handler.d.ts +64 -0
  191. package/dist/src/vended-interventions/steering/handlers/handler.d.ts.map +1 -0
  192. package/dist/src/vended-interventions/steering/handlers/handler.js +71 -0
  193. package/dist/src/vended-interventions/steering/handlers/handler.js.map +1 -0
  194. package/dist/src/vended-interventions/steering/handlers/llm.d.ts +72 -0
  195. package/dist/src/vended-interventions/steering/handlers/llm.d.ts.map +1 -0
  196. package/dist/src/vended-interventions/steering/handlers/llm.js +177 -0
  197. package/dist/src/vended-interventions/steering/handlers/llm.js.map +1 -0
  198. package/dist/src/vended-interventions/steering/index.d.ts +31 -0
  199. package/dist/src/vended-interventions/steering/index.d.ts.map +1 -0
  200. package/dist/src/vended-interventions/steering/index.js +32 -0
  201. package/dist/src/vended-interventions/steering/index.js.map +1 -0
  202. package/dist/src/vended-interventions/steering/providers/context-provider.d.ts +55 -0
  203. package/dist/src/vended-interventions/steering/providers/context-provider.d.ts.map +1 -0
  204. package/dist/src/vended-interventions/steering/providers/context-provider.js +8 -0
  205. package/dist/src/vended-interventions/steering/providers/context-provider.js.map +1 -0
  206. package/dist/src/vended-interventions/steering/providers/tool-ledger.d.ts +49 -0
  207. package/dist/src/vended-interventions/steering/providers/tool-ledger.d.ts.map +1 -0
  208. package/dist/src/vended-interventions/steering/providers/tool-ledger.js +75 -0
  209. package/dist/src/vended-interventions/steering/providers/tool-ledger.js.map +1 -0
  210. package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.js +208 -0
  211. package/dist/src/vended-plugins/context-offloader/__tests__/plugin.test.js.map +1 -1
  212. package/dist/src/vended-plugins/context-offloader/__tests__/search.test.d.ts +2 -0
  213. package/dist/src/vended-plugins/context-offloader/__tests__/search.test.d.ts.map +1 -0
  214. package/dist/src/vended-plugins/context-offloader/__tests__/search.test.js +149 -0
  215. package/dist/src/vended-plugins/context-offloader/__tests__/search.test.js.map +1 -0
  216. package/dist/src/vended-plugins/context-offloader/plugin.d.ts.map +1 -1
  217. package/dist/src/vended-plugins/context-offloader/plugin.js +57 -10
  218. package/dist/src/vended-plugins/context-offloader/plugin.js.map +1 -1
  219. package/dist/src/vended-plugins/context-offloader/search.d.ts +25 -0
  220. package/dist/src/vended-plugins/context-offloader/search.d.ts.map +1 -0
  221. package/dist/src/vended-plugins/context-offloader/search.js +120 -0
  222. package/dist/src/vended-plugins/context-offloader/search.js.map +1 -0
  223. package/dist/src/vended-plugins/index.d.ts +11 -0
  224. package/dist/src/vended-plugins/index.d.ts.map +1 -0
  225. package/dist/src/vended-plugins/index.js +11 -0
  226. package/dist/src/vended-plugins/index.js.map +1 -0
  227. package/dist/src/vended-tools/index.d.ts +17 -0
  228. package/dist/src/vended-tools/index.d.ts.map +1 -0
  229. package/dist/src/vended-tools/index.js +17 -0
  230. package/dist/src/vended-tools/index.js.map +1 -0
  231. package/package.json +37 -11
@@ -5,6 +5,7 @@ import { MockMessageModel } from '../../__fixtures__/mock-message-model.js';
5
5
  import { collectGenerator } from '../../__fixtures__/model-test-helpers.js';
6
6
  import { createMockTool } from '../../__fixtures__/tool-helpers.js';
7
7
  import { TextBlock, ToolResultBlock } from '../../types/messages.js';
8
+ import { BeforeToolCallEvent, BeforeToolsEvent } from '../../hooks/events.js';
8
9
  describe('AgentPrinter', () => {
9
10
  describe('end-to-end scenarios', () => {
10
11
  it('prints simple text output', async () => {
@@ -74,7 +75,7 @@ describe('AgentPrinter', () => {
74
75
  agent._printer = new AgentPrinter(mockAppender);
75
76
  await collectGenerator(agent.stream('Test'));
76
77
  const allOutput = outputs.join('');
77
- expect(allOutput).toBe('\n🔧 Tool #1: calc\n✓ Tool completed\nResult: 4\n');
78
+ expect(allOutput).toBe('\n ⏳ calc\n\n🔧 Tool #1: calc\n✓ Tool completed\nResult: 4\n');
78
79
  });
79
80
  it('prints tool error', async () => {
80
81
  const model = new MockMessageModel()
@@ -91,7 +92,47 @@ describe('AgentPrinter', () => {
91
92
  agent._printer = new AgentPrinter(mockAppender);
92
93
  await collectGenerator(agent.stream('Test'));
93
94
  const allOutput = outputs.join('');
94
- expect(allOutput).toBe('\n🔧 Tool #1: bad_tool\n✗ Tool failed\nError handled\n');
95
+ expect(allOutput).toBe('\n ⏳ bad_tool\n\n🔧 Tool #1: bad_tool\n✗ Tool failed\nError handled\n');
96
+ });
97
+ it('prints denied tool with denied icon', async () => {
98
+ const model = new MockMessageModel()
99
+ .addTurn({ type: 'toolUseBlock', name: 'dangerous_tool', toolUseId: 'tool-1', input: {} })
100
+ .addTurn({ type: 'textBlock', text: 'Tool was denied' });
101
+ const tool = createMockTool('dangerous_tool', () => new ToolResultBlock({
102
+ toolUseId: 'tool-1',
103
+ status: 'error',
104
+ content: [new TextBlock('denied')],
105
+ }));
106
+ const outputs = [];
107
+ const mockAppender = (text) => outputs.push(text);
108
+ const agent = new Agent({ model, tools: [tool], printer: false });
109
+ agent._printer = new AgentPrinter(mockAppender);
110
+ agent.addHook(BeforeToolCallEvent, (event) => {
111
+ event.cancel = 'Tool not allowed';
112
+ });
113
+ await collectGenerator(agent.stream('Test'));
114
+ const allOutput = outputs.join('');
115
+ expect(allOutput).toBe('\n ⏳ dangerous_tool\n\n🚫 Tool #1: dangerous_tool (denied)\n✗ Tool failed\nTool was denied\n');
116
+ });
117
+ it('prints batch cancel notice when BeforeToolsEvent cancels', async () => {
118
+ const model = new MockMessageModel()
119
+ .addTurn({ type: 'toolUseBlock', name: 'tool_a', toolUseId: 'tool-1', input: {} })
120
+ .addTurn({ type: 'textBlock', text: 'Done' });
121
+ const tool = createMockTool('tool_a', () => new ToolResultBlock({
122
+ toolUseId: 'tool-1',
123
+ status: 'success',
124
+ content: [new TextBlock('ok')],
125
+ }));
126
+ const outputs = [];
127
+ const mockAppender = (text) => outputs.push(text);
128
+ const agent = new Agent({ model, tools: [tool], printer: false });
129
+ agent._printer = new AgentPrinter(mockAppender);
130
+ agent.addHook(BeforeToolsEvent, (event) => {
131
+ event.cancel = true;
132
+ });
133
+ await collectGenerator(agent.stream('Test'));
134
+ const allOutput = outputs.join('');
135
+ expect(allOutput).toBe('\n ⏳ tool_a\n\n🚫 All tools denied\n✗ Tool failed\nDone\n');
95
136
  });
96
137
  it('prints comprehensive scenario with all output types', async () => {
97
138
  const model = new MockMessageModel()
@@ -125,22 +166,21 @@ describe('AgentPrinter', () => {
125
166
  agent._printer = new AgentPrinter(mockAppender);
126
167
  await collectGenerator(agent.stream('Test'));
127
168
  const allOutput = outputs.join('');
128
- const expected = `Let me help you.
129
- 💭 Reasoning:
130
- I need to use the calculator
131
-
132
- 🔧 Tool #1: calculator
133
- ✓ Tool completed
134
- The calculation succeeded.
135
- 💭 Reasoning:
136
- Now trying validation
137
-
138
- 🔧 Tool #2: validator
139
- Tool failed
140
- All done.
141
- 💭 Reasoning:
142
- Task completed successfully
143
- \n`;
169
+ const expected = [
170
+ 'Let me help you. ',
171
+ '\n💭 Reasoning:\n I need to use the calculator\n',
172
+ '\n ⏳ calculator\n',
173
+ '\n🔧 Tool #1: calculator\n',
174
+ '✓ Tool completed\n',
175
+ 'The calculation succeeded. ',
176
+ '\n💭 Reasoning:\n Now trying validation\n',
177
+ '\n ⏳ validator\n',
178
+ '\n🔧 Tool #2: validator\n',
179
+ '✗ Tool failed\n',
180
+ 'All done. ',
181
+ '\n💭 Reasoning:\n Task completed successfully\n',
182
+ '\n',
183
+ ].join('');
144
184
  expect(allOutput).toBe(expected);
145
185
  });
146
186
  });
@@ -1 +1 @@
1
- {"version":3,"file":"printer.test.js","sourceRoot":"","sources":["../../../../src/agent/__tests__/printer.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"printer.test.js","sourceRoot":"","sources":["../../../../src/agent/__tests__/printer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tool-caller.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-caller.test.d.ts","sourceRoot":"","sources":["../../../../src/agent/__tests__/tool-caller.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,459 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { Agent } from '../agent.js';
3
+ import { MockMessageModel } from '../../__fixtures__/mock-message-model.js';
4
+ import { createMockTool } from '../../__fixtures__/tool-helpers.js';
5
+ import { Message, ToolResultBlock, TextBlock, ToolUseBlock } from '../../types/messages.js';
6
+ import { ConcurrentInvocationError, ToolNotFoundError } from '../../errors.js';
7
+ import { ToolStreamEvent } from '../../tools/tool.js';
8
+ describe('ToolCaller', () => {
9
+ describe('basic tool calling via .invoke()', () => {
10
+ it('calls a tool by name and returns the result', async () => {
11
+ const tool = createMockTool('calculator', () => new ToolResultBlock({
12
+ toolUseId: 'test-id',
13
+ status: 'success',
14
+ content: [new TextBlock('8')],
15
+ }));
16
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
17
+ const agent = new Agent({ model, tools: [tool] });
18
+ const result = await agent.tool.calculator.invoke({ a: 5, b: 3 });
19
+ expect(result).toStrictEqual(new ToolResultBlock({
20
+ toolUseId: 'test-id',
21
+ status: 'success',
22
+ content: [new TextBlock('8')],
23
+ }));
24
+ });
25
+ it('calls a tool with empty input when no input provided', async () => {
26
+ const tool = createMockTool('ping', () => new ToolResultBlock({
27
+ toolUseId: 'test-id',
28
+ status: 'success',
29
+ content: [new TextBlock('pong')],
30
+ }));
31
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
32
+ const agent = new Agent({ model, tools: [tool] });
33
+ const result = await agent.tool.ping.invoke();
34
+ expect(result).toStrictEqual(new ToolResultBlock({
35
+ toolUseId: 'test-id',
36
+ status: 'success',
37
+ content: [new TextBlock('pong')],
38
+ }));
39
+ });
40
+ it('throws when tool is not found', async () => {
41
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
42
+ const agent = new Agent({ model, tools: [] });
43
+ await expect(agent.tool.nonexistent.invoke()).rejects.toThrow(ToolNotFoundError);
44
+ await expect(agent.tool.nonexistent.invoke()).rejects.toThrow("Tool 'nonexistent' not found");
45
+ });
46
+ });
47
+ describe('underscore-to-hyphen normalization', () => {
48
+ it('resolves underscore names to hyphenated tool names', async () => {
49
+ const tool = createMockTool('my-tool', () => new ToolResultBlock({
50
+ toolUseId: 'test-id',
51
+ status: 'success',
52
+ content: [new TextBlock('ok')],
53
+ }));
54
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
55
+ const agent = new Agent({ model, tools: [tool] });
56
+ const result = await agent.tool.my_tool.invoke();
57
+ expect(result.status).toBe('success');
58
+ });
59
+ it('prefers exact name match over normalized match', async () => {
60
+ const exactTool = createMockTool('my_tool', () => new ToolResultBlock({
61
+ toolUseId: 'test-id',
62
+ status: 'success',
63
+ content: [new TextBlock('exact')],
64
+ }));
65
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
66
+ const agent = new Agent({ model, tools: [exactTool] });
67
+ const result = await agent.tool.my_tool.invoke();
68
+ expect(result).toStrictEqual(new ToolResultBlock({
69
+ toolUseId: 'test-id',
70
+ status: 'success',
71
+ content: [new TextBlock('exact')],
72
+ }));
73
+ });
74
+ });
75
+ describe('case-insensitive name resolution', () => {
76
+ it('resolves tool names case-insensitively', async () => {
77
+ const tool = createMockTool('MyTool', () => new ToolResultBlock({
78
+ toolUseId: 'test-id',
79
+ status: 'success',
80
+ content: [new TextBlock('ok')],
81
+ }));
82
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
83
+ const agent = new Agent({ model, tools: [tool] });
84
+ const result = await agent.tool.mytool.invoke();
85
+ expect(result.status).toBe('success');
86
+ });
87
+ it('prefers exact match over case-insensitive match', async () => {
88
+ const exactTool = createMockTool('myTool', () => new ToolResultBlock({
89
+ toolUseId: 'test-id',
90
+ status: 'success',
91
+ content: [new TextBlock('exact')],
92
+ }));
93
+ const upperTool = createMockTool('MYTOOL', () => new ToolResultBlock({
94
+ toolUseId: 'test-id',
95
+ status: 'success',
96
+ content: [new TextBlock('upper')],
97
+ }));
98
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
99
+ const agent = new Agent({ model, tools: [exactTool, upperTool] });
100
+ const result = await agent.tool.myTool.invoke();
101
+ expect(result.content[0]).toStrictEqual(new TextBlock('exact'));
102
+ });
103
+ });
104
+ describe('message history recording', () => {
105
+ it('records tool call in message history by default', async () => {
106
+ const tool = createMockTool('calculator', () => new ToolResultBlock({
107
+ toolUseId: 'test-id',
108
+ status: 'success',
109
+ content: [new TextBlock('8')],
110
+ }));
111
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
112
+ const agent = new Agent({ model, tools: [tool] });
113
+ await agent.tool.calculator.invoke({ a: 5, b: 3 });
114
+ // Per TESTING.md, prefer full-object assertions over per-field checks.
115
+ // toolUseId is non-deterministic (UUID), so use expect.stringMatching.
116
+ expect(agent.messages).toEqual([
117
+ new Message({
118
+ role: 'assistant',
119
+ content: [
120
+ new ToolUseBlock({
121
+ toolUseId: expect.stringMatching(/^tooluse_/),
122
+ name: 'calculator',
123
+ input: { a: 5, b: 3 },
124
+ }),
125
+ ],
126
+ }),
127
+ new Message({
128
+ role: 'user',
129
+ content: [
130
+ new ToolResultBlock({
131
+ toolUseId: 'test-id',
132
+ status: 'success',
133
+ content: [new TextBlock('8')],
134
+ }),
135
+ ],
136
+ }),
137
+ new Message({
138
+ role: 'assistant',
139
+ content: [new TextBlock('agent.tool.calculator was called.')],
140
+ }),
141
+ ]);
142
+ });
143
+ it('does not record when recordDirectToolCall is false per-call', async () => {
144
+ const tool = createMockTool('calculator', () => new ToolResultBlock({
145
+ toolUseId: 'test-id',
146
+ status: 'success',
147
+ content: [new TextBlock('8')],
148
+ }));
149
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
150
+ const agent = new Agent({ model, tools: [tool] });
151
+ await agent.tool.calculator.invoke({ a: 5, b: 3 }, { recordDirectToolCall: false });
152
+ expect(agent.messages).toHaveLength(0);
153
+ });
154
+ it('records when explicitly set to true per-call', async () => {
155
+ const tool = createMockTool('calculator', () => new ToolResultBlock({
156
+ toolUseId: 'test-id',
157
+ status: 'success',
158
+ content: [new TextBlock('8')],
159
+ }));
160
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
161
+ const agent = new Agent({ model, tools: [tool] });
162
+ await agent.tool.calculator.invoke({ a: 5, b: 3 }, { recordDirectToolCall: true });
163
+ expect(agent.messages).toHaveLength(3);
164
+ });
165
+ it('records full input without filtering', async () => {
166
+ const tool = createMockTool('my-tool', () => new ToolResultBlock({
167
+ toolUseId: 'test-id',
168
+ status: 'success',
169
+ content: [new TextBlock('ok')],
170
+ }));
171
+ Object.defineProperty(tool, 'toolSpec', {
172
+ value: {
173
+ name: 'my-tool',
174
+ description: 'Tool with strict schema',
175
+ inputSchema: {
176
+ type: 'object',
177
+ properties: {
178
+ allowed: { type: 'string' },
179
+ },
180
+ },
181
+ },
182
+ });
183
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
184
+ const agent = new Agent({ model, tools: [tool] });
185
+ await agent.tool.my_tool.invoke({ allowed: 'yes', extra: 'also-recorded' });
186
+ // Input is recorded as-is — no filtering
187
+ const recToolUseBlock = agent.messages[0].content[0];
188
+ expect(recToolUseBlock).toBeInstanceOf(ToolUseBlock);
189
+ expect(recToolUseBlock.input).toStrictEqual({ allowed: 'yes', extra: 'also-recorded' });
190
+ });
191
+ });
192
+ describe('concurrency protection', () => {
193
+ it('throws ConcurrentInvocationError when agent is invoking and recording is enabled', async () => {
194
+ const tool = createMockTool('slow-tool', () => new ToolResultBlock({
195
+ toolUseId: 'test-id',
196
+ status: 'success',
197
+ content: [new TextBlock('done')],
198
+ }));
199
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
200
+ const agent = new Agent({ model, tools: [tool] });
201
+ // Simulate the agent being in the middle of an invocation by mocking isInvoking
202
+ Object.defineProperty(agent, 'isInvoking', { get: () => true });
203
+ await expect(agent.tool.slow_tool.invoke()).rejects.toThrow(ConcurrentInvocationError);
204
+ await expect(agent.tool.slow_tool.invoke()).rejects.toThrow('Direct tool call cannot be made while the agent is in the middle of an invocation');
205
+ });
206
+ it('allows direct tool call during invocation when recordDirectToolCall is false', async () => {
207
+ const tool = createMockTool('quick-tool', () => new ToolResultBlock({
208
+ toolUseId: 'test-id',
209
+ status: 'success',
210
+ content: [new TextBlock('ok')],
211
+ }));
212
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
213
+ const agent = new Agent({ model, tools: [tool] });
214
+ // Simulate the agent being in the middle of an invocation
215
+ Object.defineProperty(agent, 'isInvoking', { get: () => true });
216
+ // Should NOT throw when recording is disabled
217
+ const result = await agent.tool.quick_tool.invoke({}, { recordDirectToolCall: false });
218
+ expect(result.status).toBe('success');
219
+ });
220
+ it('isInvoking is false on a fresh agent', () => {
221
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
222
+ const agent = new Agent({ model });
223
+ expect(agent.isInvoking).toBe(false);
224
+ });
225
+ });
226
+ describe('tool error handling', () => {
227
+ it('propagates errors when tool throws', async () => {
228
+ const throwingTool = createMockTool('thrower', () => {
229
+ throw new Error('Boom!');
230
+ });
231
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
232
+ const agent = new Agent({ model, tools: [throwingTool] });
233
+ await expect(agent.tool.thrower.invoke()).rejects.toThrow('Boom!');
234
+ });
235
+ });
236
+ describe('agent.tool accessor', () => {
237
+ it('is accessible as a property', () => {
238
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
239
+ const agent = new Agent({ model });
240
+ expect(agent.tool).toBeDefined();
241
+ });
242
+ it('returns same instance on multiple accesses', () => {
243
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
244
+ const agent = new Agent({ model });
245
+ expect(agent.tool).toBe(agent.tool);
246
+ });
247
+ it('returns a ToolHandle with invoke and stream methods', () => {
248
+ const tool = createMockTool('calculator', () => new ToolResultBlock({
249
+ toolUseId: 'test-id',
250
+ status: 'success',
251
+ content: [new TextBlock('ok')],
252
+ }));
253
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
254
+ const agent = new Agent({ model, tools: [tool] });
255
+ const handle = agent.tool.calculator;
256
+ expect(typeof handle.invoke).toBe('function');
257
+ expect(typeof handle.stream).toBe('function');
258
+ });
259
+ });
260
+ describe('tool use ID generation', () => {
261
+ it('generates unique tool use IDs using crypto.randomUUID', async () => {
262
+ const tool = createMockTool('id-tool', () => new ToolResultBlock({
263
+ toolUseId: 'test-id',
264
+ status: 'success',
265
+ content: [new TextBlock('ok')],
266
+ }));
267
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
268
+ const agent = new Agent({ model, tools: [tool] });
269
+ await agent.tool.id_tool.invoke();
270
+ await agent.tool.id_tool.invoke();
271
+ // Each call records 3 messages: [0]=assistant(toolUse), [1]=user(toolResult), [2]=assistant(ack)
272
+ // Second call: [3]=assistant(toolUse), [4]=user(toolResult), [5]=assistant(ack)
273
+ expect(agent.messages).toHaveLength(6);
274
+ const toolUse1 = agent.messages[0].content[0];
275
+ const toolUse2 = agent.messages[3].content[0];
276
+ // Verify both are ToolUseBlocks at the correct indices
277
+ expect(toolUse1).toBeInstanceOf(ToolUseBlock);
278
+ expect(toolUse2).toBeInstanceOf(ToolUseBlock);
279
+ // Verify IDs are unique and follow the expected format
280
+ expect(toolUse1.toolUseId).toMatch(/^tooluse_/);
281
+ expect(toolUse2.toolUseId).toMatch(/^tooluse_/);
282
+ expect(toolUse1.toolUseId).not.toBe(toolUse2.toolUseId);
283
+ });
284
+ });
285
+ describe('streaming via .stream()', () => {
286
+ it('yields intermediate events and returns final result', async () => {
287
+ const yields = [];
288
+ const streamingTool = {
289
+ name: 'streamer',
290
+ description: 'A tool that yields progress events',
291
+ toolSpec: {
292
+ name: 'streamer',
293
+ description: 'A tool that yields progress events',
294
+ inputSchema: { type: 'object', properties: {} },
295
+ },
296
+ async *stream() {
297
+ yields.push('first');
298
+ yield new ToolStreamEvent({ data: 'step 1' });
299
+ yields.push('second');
300
+ yield new ToolStreamEvent({ data: 'step 2' });
301
+ yields.push('third');
302
+ yield new ToolStreamEvent({ data: 'step 3' });
303
+ return new ToolResultBlock({
304
+ toolUseId: 'stream-id',
305
+ status: 'success',
306
+ content: [new TextBlock('complete')],
307
+ });
308
+ },
309
+ };
310
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
311
+ const agent = new Agent({ model, tools: [streamingTool] });
312
+ const events = [];
313
+ const gen = agent.tool.streamer.stream();
314
+ let result = await gen.next();
315
+ while (!result.done) {
316
+ events.push(result.value);
317
+ result = await gen.next();
318
+ }
319
+ const finalResult = result.value;
320
+ expect(finalResult.status).toBe('success');
321
+ expect(finalResult.content[0]).toStrictEqual(new TextBlock('complete'));
322
+ // Verify all yields were consumed (generator fully iterated)
323
+ expect(yields).toStrictEqual(['first', 'second', 'third']);
324
+ // Verify we received all 3 stream events
325
+ expect(events).toHaveLength(3);
326
+ });
327
+ it('invoke() also fully consumes multi-yield generator', async () => {
328
+ const yields = [];
329
+ const streamingTool = {
330
+ name: 'streamer',
331
+ description: 'A tool that yields progress events',
332
+ toolSpec: {
333
+ name: 'streamer',
334
+ description: 'A tool that yields progress events',
335
+ inputSchema: { type: 'object', properties: {} },
336
+ },
337
+ async *stream() {
338
+ yields.push('first');
339
+ yield new ToolStreamEvent({ data: 'step 1' });
340
+ yields.push('second');
341
+ yield new ToolStreamEvent({ data: 'step 2' });
342
+ yields.push('third');
343
+ yield new ToolStreamEvent({ data: 'step 3' });
344
+ return new ToolResultBlock({
345
+ toolUseId: 'stream-id',
346
+ status: 'success',
347
+ content: [new TextBlock('complete')],
348
+ });
349
+ },
350
+ };
351
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
352
+ const agent = new Agent({ model, tools: [streamingTool] });
353
+ const result = await agent.tool.streamer.invoke();
354
+ expect(result.status).toBe('success');
355
+ expect(result.content[0]).toStrictEqual(new TextBlock('complete'));
356
+ // Verify all yields were consumed even when using .invoke()
357
+ expect(yields).toStrictEqual(['first', 'second', 'third']);
358
+ });
359
+ });
360
+ describe('tool input passthrough', () => {
361
+ it('passes ALL parameters to tool execution', async () => {
362
+ let receivedInput = null;
363
+ const tool = createMockTool('capture-tool', () => new ToolResultBlock({
364
+ toolUseId: 'test-id',
365
+ status: 'success',
366
+ content: [new TextBlock('captured')],
367
+ }));
368
+ // Override stream to capture input
369
+ const originalStream = tool.stream.bind(tool);
370
+ tool.stream = function (context) {
371
+ receivedInput = context.toolUse.input;
372
+ return originalStream(context);
373
+ };
374
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
375
+ const agent = new Agent({ model, tools: [tool] });
376
+ await agent.tool.capture_tool.invoke({ allowed: 'yes', extra: 'should-pass-through' });
377
+ // Tool receives ALL parameters
378
+ expect(receivedInput).toStrictEqual({ allowed: 'yes', extra: 'should-pass-through' });
379
+ });
380
+ });
381
+ describe('dynamically added tools', () => {
382
+ it('can call a tool that was added after agent creation', async () => {
383
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
384
+ const agent = new Agent({ model, tools: [] });
385
+ // Add tool after creation
386
+ const laterTool = createMockTool('later-tool', () => new ToolResultBlock({
387
+ toolUseId: 'test-id',
388
+ status: 'success',
389
+ content: [new TextBlock('dynamic')],
390
+ }));
391
+ agent.toolRegistry.add(laterTool);
392
+ const result = await agent.tool.later_tool.invoke();
393
+ expect(result.status).toBe('success');
394
+ expect(result.content[0]).toStrictEqual(new TextBlock('dynamic'));
395
+ });
396
+ });
397
+ });
398
+ describe('MessageAddedEvent hooks', () => {
399
+ it('fires MessageAddedEvent for each message recorded during direct tool call', async () => {
400
+ const { MessageAddedEvent } = await import('../../hooks/events.js');
401
+ const tool = createMockTool('calculator', () => new ToolResultBlock({
402
+ toolUseId: 'test-id',
403
+ status: 'success',
404
+ content: [new TextBlock('8')],
405
+ }));
406
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
407
+ const agent = new Agent({ model, tools: [tool] });
408
+ const firedEvents = [];
409
+ agent.addHook(MessageAddedEvent, (event) => {
410
+ firedEvents.push(event);
411
+ });
412
+ await agent.tool.calculator.invoke({ a: 5, b: 3 });
413
+ // Should fire 3 MessageAddedEvents (one per recorded message).
414
+ // Use full-object assertions per TESTING.md.
415
+ expect(firedEvents).toHaveLength(3);
416
+ expect(firedEvents[0].message).toEqual(new Message({
417
+ role: 'assistant',
418
+ content: [
419
+ new ToolUseBlock({
420
+ toolUseId: expect.stringMatching(/^tooluse_/),
421
+ name: 'calculator',
422
+ input: { a: 5, b: 3 },
423
+ }),
424
+ ],
425
+ }));
426
+ expect(firedEvents[1].message).toEqual(new Message({
427
+ role: 'user',
428
+ content: [
429
+ new ToolResultBlock({
430
+ toolUseId: 'test-id',
431
+ status: 'success',
432
+ content: [new TextBlock('8')],
433
+ }),
434
+ ],
435
+ }));
436
+ expect(firedEvents[2].message).toEqual(new Message({
437
+ role: 'assistant',
438
+ content: [new TextBlock('agent.tool.calculator was called.')],
439
+ }));
440
+ });
441
+ it('does not fire MessageAddedEvent when recordDirectToolCall is false', async () => {
442
+ const { MessageAddedEvent } = await import('../../hooks/events.js');
443
+ const tool = createMockTool('calculator', () => new ToolResultBlock({
444
+ toolUseId: 'test-id',
445
+ status: 'success',
446
+ content: [new TextBlock('8')],
447
+ }));
448
+ const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
449
+ const agent = new Agent({ model, tools: [tool] });
450
+ const firedEvents = [];
451
+ agent.addHook(MessageAddedEvent, (event) => {
452
+ firedEvents.push(event);
453
+ });
454
+ await agent.tool.calculator.invoke({ a: 5, b: 3 }, { recordDirectToolCall: false });
455
+ // No events should fire when recording is disabled
456
+ expect(firedEvents).toHaveLength(0);
457
+ });
458
+ });
459
+ //# sourceMappingURL=tool-caller.test.js.map