@tambo-ai/react 0.74.1 → 0.75.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -449
- package/dist/hoc/with-tambo-interactable.d.ts +8 -0
- package/dist/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/dist/hoc/with-tambo-interactable.js +5 -2
- package/dist/hoc/with-tambo-interactable.js.map +1 -1
- package/dist/hoc/with-tambo-interactable.test.js +12 -0
- package/dist/hoc/with-tambo-interactable.test.js.map +1 -1
- package/dist/hooks/use-tambo-voice.test.js +3 -0
- package/dist/hooks/use-tambo-voice.test.js.map +1 -1
- package/dist/mcp/mcp-hooks.test.js +69 -0
- package/dist/mcp/mcp-hooks.test.js.map +1 -1
- package/dist/mcp/tambo-mcp-provider.test.js +24 -0
- package/dist/mcp/tambo-mcp-provider.test.js.map +1 -1
- package/dist/mcp/use-mcp-servers.test.js +9 -0
- package/dist/mcp/use-mcp-servers.test.js.map +1 -1
- package/dist/model/component-metadata.d.ts +4 -4
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/providers/__tests__/thread-input-resource-resolution.test.js +2 -2
- package/dist/providers/__tests__/thread-input-resource-resolution.test.js.map +1 -1
- package/dist/providers/tambo-client-provider.d.ts +6 -0
- package/dist/providers/tambo-client-provider.d.ts.map +1 -1
- package/dist/providers/tambo-client-provider.js +4 -1
- package/dist/providers/tambo-client-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +8 -0
- package/dist/providers/tambo-interactable-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.test.js +47 -0
- package/dist/providers/tambo-interactable-provider.test.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js +4 -1
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-stubs.d.ts.map +1 -1
- package/dist/providers/tambo-stubs.js +3 -0
- package/dist/providers/tambo-stubs.js.map +1 -1
- package/dist/providers/tambo-thread-provider-initial-messages.test.js +3 -0
- package/dist/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/dist/providers/tambo-thread-provider.test.js +3 -0
- package/dist/providers/tambo-thread-provider.test.js.map +1 -1
- package/dist/util/registry-validators.js +1 -1
- package/dist/util/registry-validators.js.map +1 -1
- package/dist/util/resource-content-resolver.test.js +1 -1
- package/dist/util/resource-content-resolver.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-auth-state.d.ts +11 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.js +48 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.d.ts +2 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.js +105 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.js +68 -21
- package/dist/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.test.js +100 -0
- package/dist/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.test.js +8 -0
- package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +19 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.js +86 -9
- package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js +273 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts +2 -2
- package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.js +2 -2
- package/dist/v1/hooks/use-tambo-v1-stream-status.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.js +11 -11
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +13 -0
- package/dist/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.js +4 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +6 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.js +4 -0
- package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.test.js +6 -0
- package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.d.ts +11 -0
- package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.js +5 -0
- package/dist/v1/hooks/use-tambo-v1.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.test.js +13 -0
- package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/dist/v1/index.d.ts +4 -1
- package/dist/v1/index.d.ts.map +1 -1
- package/dist/v1/index.js +5 -2
- package/dist/v1/index.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.d.ts +16 -1
- package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.js +42 -5
- package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.test.js +19 -2
- package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.d.ts +6 -0
- package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.js +50 -11
- package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.test.js +9 -0
- package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.js +4 -0
- package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +11 -0
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.js +10 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
- package/dist/v1/types/auth.d.ts +24 -0
- package/dist/v1/types/auth.d.ts.map +1 -0
- package/dist/v1/types/auth.js +3 -0
- package/dist/v1/types/auth.js.map +1 -0
- package/dist/v1/types/message.d.ts +12 -0
- package/dist/v1/types/message.d.ts.map +1 -1
- package/dist/v1/types/message.js.map +1 -1
- package/dist/v1/types/tool-choice.d.ts +8 -0
- package/dist/v1/types/tool-choice.d.ts.map +1 -0
- package/dist/v1/types/tool-choice.js +3 -0
- package/dist/v1/types/tool-choice.js.map +1 -0
- package/dist/v1/utils/event-accumulator.d.ts +28 -2
- package/dist/v1/utils/event-accumulator.d.ts.map +1 -1
- package/dist/v1/utils/event-accumulator.js +67 -15
- package/dist/v1/utils/event-accumulator.js.map +1 -1
- package/dist/v1/utils/event-accumulator.test.js +106 -0
- package/dist/v1/utils/event-accumulator.test.js.map +1 -1
- package/dist/v1/utils/keyed-throttle.d.ts +42 -0
- package/dist/v1/utils/keyed-throttle.d.ts.map +1 -0
- package/dist/v1/utils/keyed-throttle.js +86 -0
- package/dist/v1/utils/keyed-throttle.js.map +1 -0
- package/dist/v1/utils/keyed-throttle.test.d.ts +2 -0
- package/dist/v1/utils/keyed-throttle.test.d.ts.map +1 -0
- package/dist/v1/utils/keyed-throttle.test.js +147 -0
- package/dist/v1/utils/keyed-throttle.test.js.map +1 -0
- package/dist/v1/utils/registry-conversion.d.ts.map +1 -1
- package/dist/v1/utils/registry-conversion.js +2 -0
- package/dist/v1/utils/registry-conversion.js.map +1 -1
- package/dist/v1/utils/registry-conversion.test.js +23 -0
- package/dist/v1/utils/registry-conversion.test.js.map +1 -1
- package/dist/v1/utils/tool-call-tracker.d.ts +10 -0
- package/dist/v1/utils/tool-call-tracker.d.ts.map +1 -1
- package/dist/v1/utils/tool-call-tracker.js +13 -0
- package/dist/v1/utils/tool-call-tracker.js.map +1 -1
- package/dist/v1/utils/tool-call-tracker.test.d.ts +2 -0
- package/dist/v1/utils/tool-call-tracker.test.d.ts.map +1 -0
- package/dist/v1/utils/tool-call-tracker.test.js +67 -0
- package/dist/v1/utils/tool-call-tracker.test.js.map +1 -0
- package/dist/v1/utils/tool-executor.d.ts +34 -0
- package/dist/v1/utils/tool-executor.d.ts.map +1 -1
- package/dist/v1/utils/tool-executor.js +55 -0
- package/dist/v1/utils/tool-executor.js.map +1 -1
- package/dist/v1/utils/tool-executor.test.js +211 -0
- package/dist/v1/utils/tool-executor.test.js.map +1 -1
- package/esm/hoc/with-tambo-interactable.d.ts +8 -0
- package/esm/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/esm/hoc/with-tambo-interactable.js +5 -2
- package/esm/hoc/with-tambo-interactable.js.map +1 -1
- package/esm/hoc/with-tambo-interactable.test.js +12 -0
- package/esm/hoc/with-tambo-interactable.test.js.map +1 -1
- package/esm/hooks/use-tambo-voice.test.js +3 -0
- package/esm/hooks/use-tambo-voice.test.js.map +1 -1
- package/esm/mcp/mcp-hooks.test.js +69 -0
- package/esm/mcp/mcp-hooks.test.js.map +1 -1
- package/esm/mcp/tambo-mcp-provider.test.js +24 -0
- package/esm/mcp/tambo-mcp-provider.test.js.map +1 -1
- package/esm/mcp/use-mcp-servers.test.js +9 -0
- package/esm/mcp/use-mcp-servers.test.js.map +1 -1
- package/esm/model/component-metadata.d.ts +4 -4
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js +2 -2
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js.map +1 -1
- package/esm/providers/tambo-client-provider.d.ts +6 -0
- package/esm/providers/tambo-client-provider.d.ts.map +1 -1
- package/esm/providers/tambo-client-provider.js +4 -1
- package/esm/providers/tambo-client-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/esm/providers/tambo-interactable-provider.js +8 -0
- package/esm/providers/tambo-interactable-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.test.js +47 -0
- package/esm/providers/tambo-interactable-provider.test.js.map +1 -1
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js +4 -1
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-stubs.d.ts.map +1 -1
- package/esm/providers/tambo-stubs.js +3 -0
- package/esm/providers/tambo-stubs.js.map +1 -1
- package/esm/providers/tambo-thread-provider-initial-messages.test.js +3 -0
- package/esm/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/esm/providers/tambo-thread-provider.test.js +3 -0
- package/esm/providers/tambo-thread-provider.test.js.map +1 -1
- package/esm/util/registry-validators.js +1 -1
- package/esm/util/registry-validators.js.map +1 -1
- package/esm/util/resource-content-resolver.test.js +1 -1
- package/esm/util/resource-content-resolver.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-auth-state.d.ts +11 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.js +45 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.d.ts +2 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.js +100 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.js +68 -21
- package/esm/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.test.js +100 -0
- package/esm/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.test.js +8 -0
- package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +19 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.js +87 -10
- package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js +273 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts +2 -2
- package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.js +2 -2
- package/esm/v1/hooks/use-tambo-v1-stream-status.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.js +11 -11
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +13 -0
- package/esm/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.js +4 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +6 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.js +4 -0
- package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.test.js +6 -0
- package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.d.ts +11 -0
- package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.js +5 -0
- package/esm/v1/hooks/use-tambo-v1.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.test.js +13 -0
- package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/esm/v1/index.d.ts +4 -1
- package/esm/v1/index.d.ts.map +1 -1
- package/esm/v1/index.js +3 -1
- package/esm/v1/index.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.d.ts +16 -1
- package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.js +43 -6
- package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.test.js +19 -2
- package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.d.ts +6 -0
- package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.js +51 -12
- package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.test.js +9 -0
- package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.js +4 -0
- package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +11 -0
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.js +10 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
- package/esm/v1/types/auth.d.ts +24 -0
- package/esm/v1/types/auth.d.ts.map +1 -0
- package/esm/v1/types/auth.js +2 -0
- package/esm/v1/types/auth.js.map +1 -0
- package/esm/v1/types/message.d.ts +12 -0
- package/esm/v1/types/message.d.ts.map +1 -1
- package/esm/v1/types/message.js.map +1 -1
- package/esm/v1/types/tool-choice.d.ts +8 -0
- package/esm/v1/types/tool-choice.d.ts.map +1 -0
- package/esm/v1/types/tool-choice.js +2 -0
- package/esm/v1/types/tool-choice.js.map +1 -0
- package/esm/v1/utils/event-accumulator.d.ts +28 -2
- package/esm/v1/utils/event-accumulator.d.ts.map +1 -1
- package/esm/v1/utils/event-accumulator.js +66 -15
- package/esm/v1/utils/event-accumulator.js.map +1 -1
- package/esm/v1/utils/event-accumulator.test.js +106 -0
- package/esm/v1/utils/event-accumulator.test.js.map +1 -1
- package/esm/v1/utils/keyed-throttle.d.ts +42 -0
- package/esm/v1/utils/keyed-throttle.d.ts.map +1 -0
- package/esm/v1/utils/keyed-throttle.js +83 -0
- package/esm/v1/utils/keyed-throttle.js.map +1 -0
- package/esm/v1/utils/keyed-throttle.test.d.ts +2 -0
- package/esm/v1/utils/keyed-throttle.test.d.ts.map +1 -0
- package/esm/v1/utils/keyed-throttle.test.js +145 -0
- package/esm/v1/utils/keyed-throttle.test.js.map +1 -0
- package/esm/v1/utils/registry-conversion.d.ts.map +1 -1
- package/esm/v1/utils/registry-conversion.js +2 -0
- package/esm/v1/utils/registry-conversion.js.map +1 -1
- package/esm/v1/utils/registry-conversion.test.js +23 -0
- package/esm/v1/utils/registry-conversion.test.js.map +1 -1
- package/esm/v1/utils/tool-call-tracker.d.ts +10 -0
- package/esm/v1/utils/tool-call-tracker.d.ts.map +1 -1
- package/esm/v1/utils/tool-call-tracker.js +13 -0
- package/esm/v1/utils/tool-call-tracker.js.map +1 -1
- package/esm/v1/utils/tool-call-tracker.test.d.ts +2 -0
- package/esm/v1/utils/tool-call-tracker.test.d.ts.map +1 -0
- package/esm/v1/utils/tool-call-tracker.test.js +65 -0
- package/esm/v1/utils/tool-call-tracker.test.js.map +1 -0
- package/esm/v1/utils/tool-executor.d.ts +34 -0
- package/esm/v1/utils/tool-executor.d.ts.map +1 -1
- package/esm/v1/utils/tool-executor.js +53 -0
- package/esm/v1/utils/tool-executor.js.map +1 -1
- package/esm/v1/utils/tool-executor.test.js +212 -1
- package/esm/v1/utils/tool-executor.test.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@ag-ui/core");
|
|
4
|
+
const tool_call_tracker_1 = require("./tool-call-tracker");
|
|
5
|
+
describe("ToolCallTracker", () => {
|
|
6
|
+
describe("getAccumulatingToolCall", () => {
|
|
7
|
+
it("returns undefined for unknown tool call ID", () => {
|
|
8
|
+
const tracker = new tool_call_tracker_1.ToolCallTracker();
|
|
9
|
+
expect(tracker.getAccumulatingToolCall("nonexistent")).toBeUndefined();
|
|
10
|
+
});
|
|
11
|
+
it("returns name and empty accumulated args after TOOL_CALL_START", () => {
|
|
12
|
+
const tracker = new tool_call_tracker_1.ToolCallTracker();
|
|
13
|
+
tracker.handleEvent({
|
|
14
|
+
type: core_1.EventType.TOOL_CALL_START,
|
|
15
|
+
toolCallId: "call_1",
|
|
16
|
+
toolCallName: "write_story",
|
|
17
|
+
parentMessageId: "msg_1",
|
|
18
|
+
});
|
|
19
|
+
const result = tracker.getAccumulatingToolCall("call_1");
|
|
20
|
+
expect(result).toEqual({ name: "write_story", accumulatedArgs: "" });
|
|
21
|
+
});
|
|
22
|
+
it("returns name and accumulated args after START + ARGS events", () => {
|
|
23
|
+
const tracker = new tool_call_tracker_1.ToolCallTracker();
|
|
24
|
+
tracker.handleEvent({
|
|
25
|
+
type: core_1.EventType.TOOL_CALL_START,
|
|
26
|
+
toolCallId: "call_1",
|
|
27
|
+
toolCallName: "write_story",
|
|
28
|
+
parentMessageId: "msg_1",
|
|
29
|
+
});
|
|
30
|
+
tracker.handleEvent({
|
|
31
|
+
type: core_1.EventType.TOOL_CALL_ARGS,
|
|
32
|
+
toolCallId: "call_1",
|
|
33
|
+
delta: '{"title":"Once',
|
|
34
|
+
});
|
|
35
|
+
const result = tracker.getAccumulatingToolCall("call_1");
|
|
36
|
+
expect(result).toEqual({
|
|
37
|
+
name: "write_story",
|
|
38
|
+
accumulatedArgs: '{"title":"Once',
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
it("accumulates multiple ARGS deltas", () => {
|
|
42
|
+
const tracker = new tool_call_tracker_1.ToolCallTracker();
|
|
43
|
+
tracker.handleEvent({
|
|
44
|
+
type: core_1.EventType.TOOL_CALL_START,
|
|
45
|
+
toolCallId: "call_1",
|
|
46
|
+
toolCallName: "write_story",
|
|
47
|
+
parentMessageId: "msg_1",
|
|
48
|
+
});
|
|
49
|
+
tracker.handleEvent({
|
|
50
|
+
type: core_1.EventType.TOOL_CALL_ARGS,
|
|
51
|
+
toolCallId: "call_1",
|
|
52
|
+
delta: '{"title":',
|
|
53
|
+
});
|
|
54
|
+
tracker.handleEvent({
|
|
55
|
+
type: core_1.EventType.TOOL_CALL_ARGS,
|
|
56
|
+
toolCallId: "call_1",
|
|
57
|
+
delta: '"Hello"}',
|
|
58
|
+
});
|
|
59
|
+
const result = tracker.getAccumulatingToolCall("call_1");
|
|
60
|
+
expect(result).toEqual({
|
|
61
|
+
name: "write_story",
|
|
62
|
+
accumulatedArgs: '{"title":"Hello"}',
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=tool-call-tracker.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-call-tracker.test.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-call-tracker.test.ts"],"names":[],"mappings":";;AAAA,sCAAwC;AACxC,2DAAsD;AAEtD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,OAAO,GAAG,IAAI,mCAAe,EAAE,CAAC;YACtC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACzE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;YACvE,MAAM,OAAO,GAAG,IAAI,mCAAe,EAAE,CAAC;YACtC,OAAO,CAAC,WAAW,CAAC;gBAClB,IAAI,EAAE,gBAAS,CAAC,eAAe;gBAC/B,UAAU,EAAE,QAAQ;gBACpB,YAAY,EAAE,aAAa;gBAC3B,eAAe,EAAE,OAAO;aACzB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;YACrE,MAAM,OAAO,GAAG,IAAI,mCAAe,EAAE,CAAC;YACtC,OAAO,CAAC,WAAW,CAAC;gBAClB,IAAI,EAAE,gBAAS,CAAC,eAAe;gBAC/B,UAAU,EAAE,QAAQ;gBACpB,YAAY,EAAE,aAAa;gBAC3B,eAAe,EAAE,OAAO;aACzB,CAAC,CAAC;YACH,OAAO,CAAC,WAAW,CAAC;gBAClB,IAAI,EAAE,gBAAS,CAAC,cAAc;gBAC9B,UAAU,EAAE,QAAQ;gBACpB,KAAK,EAAE,gBAAgB;aACxB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;gBACrB,IAAI,EAAE,aAAa;gBACnB,eAAe,EAAE,gBAAgB;aAClC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,OAAO,GAAG,IAAI,mCAAe,EAAE,CAAC;YACtC,OAAO,CAAC,WAAW,CAAC;gBAClB,IAAI,EAAE,gBAAS,CAAC,eAAe;gBAC/B,UAAU,EAAE,QAAQ;gBACpB,YAAY,EAAE,aAAa;gBAC3B,eAAe,EAAE,OAAO;aACzB,CAAC,CAAC;YACH,OAAO,CAAC,WAAW,CAAC;gBAClB,IAAI,EAAE,gBAAS,CAAC,cAAc;gBAC9B,UAAU,EAAE,QAAQ;gBACpB,KAAK,EAAE,WAAW;aACnB,CAAC,CAAC;YACH,OAAO,CAAC,WAAW,CAAC;gBAClB,IAAI,EAAE,gBAAS,CAAC,cAAc;gBAC9B,UAAU,EAAE,QAAQ;gBACpB,KAAK,EAAE,UAAU;aAClB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;gBACrB,IAAI,EAAE,aAAa;gBACnB,eAAe,EAAE,mBAAmB;aACrC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { EventType } from \"@ag-ui/core\";\nimport { ToolCallTracker } from \"./tool-call-tracker\";\n\ndescribe(\"ToolCallTracker\", () => {\n describe(\"getAccumulatingToolCall\", () => {\n it(\"returns undefined for unknown tool call ID\", () => {\n const tracker = new ToolCallTracker();\n expect(tracker.getAccumulatingToolCall(\"nonexistent\")).toBeUndefined();\n });\n\n it(\"returns name and empty accumulated args after TOOL_CALL_START\", () => {\n const tracker = new ToolCallTracker();\n tracker.handleEvent({\n type: EventType.TOOL_CALL_START,\n toolCallId: \"call_1\",\n toolCallName: \"write_story\",\n parentMessageId: \"msg_1\",\n });\n\n const result = tracker.getAccumulatingToolCall(\"call_1\");\n expect(result).toEqual({ name: \"write_story\", accumulatedArgs: \"\" });\n });\n\n it(\"returns name and accumulated args after START + ARGS events\", () => {\n const tracker = new ToolCallTracker();\n tracker.handleEvent({\n type: EventType.TOOL_CALL_START,\n toolCallId: \"call_1\",\n toolCallName: \"write_story\",\n parentMessageId: \"msg_1\",\n });\n tracker.handleEvent({\n type: EventType.TOOL_CALL_ARGS,\n toolCallId: \"call_1\",\n delta: '{\"title\":\"Once',\n });\n\n const result = tracker.getAccumulatingToolCall(\"call_1\");\n expect(result).toEqual({\n name: \"write_story\",\n accumulatedArgs: '{\"title\":\"Once',\n });\n });\n\n it(\"accumulates multiple ARGS deltas\", () => {\n const tracker = new ToolCallTracker();\n tracker.handleEvent({\n type: EventType.TOOL_CALL_START,\n toolCallId: \"call_1\",\n toolCallName: \"write_story\",\n parentMessageId: \"msg_1\",\n });\n tracker.handleEvent({\n type: EventType.TOOL_CALL_ARGS,\n toolCallId: \"call_1\",\n delta: '{\"title\":',\n });\n tracker.handleEvent({\n type: EventType.TOOL_CALL_ARGS,\n toolCallId: \"call_1\",\n delta: '\"Hello\"}',\n });\n\n const result = tracker.getAccumulatingToolCall(\"call_1\");\n expect(result).toEqual({\n name: \"write_story\",\n accumulatedArgs: '{\"title\":\"Hello\"}',\n });\n });\n });\n});\n"]}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { TamboTool } from "../../model/component-metadata";
|
|
8
8
|
import type { ToolResultContent } from "@tambo-ai/typescript-sdk/resources/threads/threads";
|
|
9
|
+
import type { ToolCallTracker } from "./tool-call-tracker";
|
|
10
|
+
import { type KeyedThrottle } from "./keyed-throttle";
|
|
9
11
|
/**
|
|
10
12
|
* Pending tool call from the stream accumulator
|
|
11
13
|
*/
|
|
@@ -13,6 +15,38 @@ export interface PendingToolCall {
|
|
|
13
15
|
name: string;
|
|
14
16
|
input: Record<string, unknown>;
|
|
15
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Execute a streamable tool call during streaming with pre-parsed partial args.
|
|
20
|
+
*
|
|
21
|
+
* Called on each TOOL_CALL_ARGS event for tools annotated with
|
|
22
|
+
* `tamboStreamableHint: true`. Enables incremental UI updates while
|
|
23
|
+
* the model is still generating arguments.
|
|
24
|
+
*
|
|
25
|
+
* Errors are caught silently — streaming tool execution is non-fatal since
|
|
26
|
+
* the final execution via `awaiting_input` is what matters.
|
|
27
|
+
* @param toolCallId - The tool call ID being accumulated
|
|
28
|
+
* @param parsedArgs - Pre-parsed partial JSON args
|
|
29
|
+
* @param toolTracker - Tracker holding pending tool call state
|
|
30
|
+
* @param toolRegistry - Record of tool name to tool definition
|
|
31
|
+
*/
|
|
32
|
+
export declare function executeStreamableToolCall(toolCallId: string, parsedArgs: Record<string, unknown>, toolTracker: ToolCallTracker, toolRegistry: Record<string, TamboTool>): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a throttled wrapper around executeStreamableToolCall.
|
|
35
|
+
*
|
|
36
|
+
* Each tool call ID gets its own independent leading+trailing throttle via
|
|
37
|
+
* {@link createKeyedThrottle}. The first call for a tool ID fires immediately
|
|
38
|
+
* (leading edge). Subsequent calls during the cooldown window update the
|
|
39
|
+
* stored args. After `delay` ms, if new args arrived, the tool re-executes
|
|
40
|
+
* with the latest args (trailing edge). This repeats as long as new args
|
|
41
|
+
* keep arriving — roughly one execution per `delay` ms during streaming.
|
|
42
|
+
*
|
|
43
|
+
* Call `flush()` to force-execute all pending trailing calls and reset to idle.
|
|
44
|
+
* @param toolTracker - Tracker holding pending tool call state
|
|
45
|
+
* @param toolRegistry - Record of tool name to tool definition
|
|
46
|
+
* @param delay - Throttle interval in milliseconds
|
|
47
|
+
* @returns Keyed throttle controller (schedule / flush)
|
|
48
|
+
*/
|
|
49
|
+
export declare function createThrottledStreamableExecutor(toolTracker: ToolCallTracker, toolRegistry: Record<string, TamboTool>, delay?: number): KeyedThrottle<Record<string, unknown>>;
|
|
16
50
|
/**
|
|
17
51
|
* Execute a single client-side tool and return the result.
|
|
18
52
|
* @param tool - The tool definition from the registry
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-executor.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,oDAAoD,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-executor.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,oDAAoD,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,WAAW,EAAE,eAAe,EAC5B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAiBf;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iCAAiC,CAC/C,WAAW,EAAE,eAAe,EAC5B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EACvC,KAAK,SAAiC,GACrC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAIxC;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,iBAAiB,CAAC,CAiD5B;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACvC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAC3D,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAiC9B"}
|
|
@@ -6,8 +6,63 @@
|
|
|
6
6
|
* requests them via `tambo.run.awaiting_input` events.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.executeStreamableToolCall = executeStreamableToolCall;
|
|
10
|
+
exports.createThrottledStreamableExecutor = createThrottledStreamableExecutor;
|
|
9
11
|
exports.executeClientTool = executeClientTool;
|
|
10
12
|
exports.executeAllPendingTools = executeAllPendingTools;
|
|
13
|
+
const keyed_throttle_1 = require("./keyed-throttle");
|
|
14
|
+
/**
|
|
15
|
+
* Execute a streamable tool call during streaming with pre-parsed partial args.
|
|
16
|
+
*
|
|
17
|
+
* Called on each TOOL_CALL_ARGS event for tools annotated with
|
|
18
|
+
* `tamboStreamableHint: true`. Enables incremental UI updates while
|
|
19
|
+
* the model is still generating arguments.
|
|
20
|
+
*
|
|
21
|
+
* Errors are caught silently — streaming tool execution is non-fatal since
|
|
22
|
+
* the final execution via `awaiting_input` is what matters.
|
|
23
|
+
* @param toolCallId - The tool call ID being accumulated
|
|
24
|
+
* @param parsedArgs - Pre-parsed partial JSON args
|
|
25
|
+
* @param toolTracker - Tracker holding pending tool call state
|
|
26
|
+
* @param toolRegistry - Record of tool name to tool definition
|
|
27
|
+
*/
|
|
28
|
+
async function executeStreamableToolCall(toolCallId, parsedArgs, toolTracker, toolRegistry) {
|
|
29
|
+
const accumulating = toolTracker.getAccumulatingToolCall(toolCallId);
|
|
30
|
+
if (!accumulating)
|
|
31
|
+
return;
|
|
32
|
+
const tool = toolRegistry[accumulating.name];
|
|
33
|
+
if (!tool?.annotations?.tamboStreamableHint)
|
|
34
|
+
return;
|
|
35
|
+
try {
|
|
36
|
+
await tool.tool(parsedArgs);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.warn(`[ToolExecutor] Non-fatal error in streamable tool "${accumulating.name}" ` +
|
|
40
|
+
`(toolCallId: ${toolCallId}). This likely indicates a bug in the tool ` +
|
|
41
|
+
`implementation; fix the tool to avoid repeated warnings.`, error);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const DEFAULT_STREAMABLE_THROTTLE_MS = 100;
|
|
45
|
+
/**
|
|
46
|
+
* Creates a throttled wrapper around executeStreamableToolCall.
|
|
47
|
+
*
|
|
48
|
+
* Each tool call ID gets its own independent leading+trailing throttle via
|
|
49
|
+
* {@link createKeyedThrottle}. The first call for a tool ID fires immediately
|
|
50
|
+
* (leading edge). Subsequent calls during the cooldown window update the
|
|
51
|
+
* stored args. After `delay` ms, if new args arrived, the tool re-executes
|
|
52
|
+
* with the latest args (trailing edge). This repeats as long as new args
|
|
53
|
+
* keep arriving — roughly one execution per `delay` ms during streaming.
|
|
54
|
+
*
|
|
55
|
+
* Call `flush()` to force-execute all pending trailing calls and reset to idle.
|
|
56
|
+
* @param toolTracker - Tracker holding pending tool call state
|
|
57
|
+
* @param toolRegistry - Record of tool name to tool definition
|
|
58
|
+
* @param delay - Throttle interval in milliseconds
|
|
59
|
+
* @returns Keyed throttle controller (schedule / flush)
|
|
60
|
+
*/
|
|
61
|
+
function createThrottledStreamableExecutor(toolTracker, toolRegistry, delay = DEFAULT_STREAMABLE_THROTTLE_MS) {
|
|
62
|
+
return (0, keyed_throttle_1.createKeyedThrottle)((toolCallId, args) => {
|
|
63
|
+
void executeStreamableToolCall(toolCallId, args, toolTracker, toolRegistry);
|
|
64
|
+
}, delay);
|
|
65
|
+
}
|
|
11
66
|
/**
|
|
12
67
|
* Execute a single client-side tool and return the result.
|
|
13
68
|
* @param tool - The tool definition from the registry
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-executor.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;
|
|
1
|
+
{"version":3,"file":"tool-executor.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tool Executor for v1 API\n *\n * Handles automatic execution of client-side tools when the model\n * requests them via `tambo.run.awaiting_input` events.\n */\n\nimport type { TamboTool } from \"../../model/component-metadata\";\nimport type {\n ToolResultContent,\n TextContent,\n ResourceContent,\n} from \"@tambo-ai/typescript-sdk/resources/threads/threads\";\nimport type { ToolCallTracker } from \"./tool-call-tracker\";\nimport { createKeyedThrottle, type KeyedThrottle } from \"./keyed-throttle\";\n\n/**\n * Pending tool call from the stream accumulator\n */\nexport interface PendingToolCall {\n name: string;\n input: Record<string, unknown>;\n}\n\n/**\n * Execute a streamable tool call during streaming with pre-parsed partial args.\n *\n * Called on each TOOL_CALL_ARGS event for tools annotated with\n * `tamboStreamableHint: true`. Enables incremental UI updates while\n * the model is still generating arguments.\n *\n * Errors are caught silently — streaming tool execution is non-fatal since\n * the final execution via `awaiting_input` is what matters.\n * @param toolCallId - The tool call ID being accumulated\n * @param parsedArgs - Pre-parsed partial JSON args\n * @param toolTracker - Tracker holding pending tool call state\n * @param toolRegistry - Record of tool name to tool definition\n */\nexport async function executeStreamableToolCall(\n toolCallId: string,\n parsedArgs: Record<string, unknown>,\n toolTracker: ToolCallTracker,\n toolRegistry: Record<string, TamboTool>,\n): Promise<void> {\n const accumulating = toolTracker.getAccumulatingToolCall(toolCallId);\n if (!accumulating) return;\n\n const tool = toolRegistry[accumulating.name];\n if (!tool?.annotations?.tamboStreamableHint) return;\n\n try {\n await tool.tool(parsedArgs);\n } catch (error) {\n console.warn(\n `[ToolExecutor] Non-fatal error in streamable tool \"${accumulating.name}\" ` +\n `(toolCallId: ${toolCallId}). This likely indicates a bug in the tool ` +\n `implementation; fix the tool to avoid repeated warnings.`,\n error,\n );\n }\n}\n\nconst DEFAULT_STREAMABLE_THROTTLE_MS = 100;\n\n/**\n * Creates a throttled wrapper around executeStreamableToolCall.\n *\n * Each tool call ID gets its own independent leading+trailing throttle via\n * {@link createKeyedThrottle}. The first call for a tool ID fires immediately\n * (leading edge). Subsequent calls during the cooldown window update the\n * stored args. After `delay` ms, if new args arrived, the tool re-executes\n * with the latest args (trailing edge). This repeats as long as new args\n * keep arriving — roughly one execution per `delay` ms during streaming.\n *\n * Call `flush()` to force-execute all pending trailing calls and reset to idle.\n * @param toolTracker - Tracker holding pending tool call state\n * @param toolRegistry - Record of tool name to tool definition\n * @param delay - Throttle interval in milliseconds\n * @returns Keyed throttle controller (schedule / flush)\n */\nexport function createThrottledStreamableExecutor(\n toolTracker: ToolCallTracker,\n toolRegistry: Record<string, TamboTool>,\n delay = DEFAULT_STREAMABLE_THROTTLE_MS,\n): KeyedThrottle<Record<string, unknown>> {\n return createKeyedThrottle<Record<string, unknown>>((toolCallId, args) => {\n void executeStreamableToolCall(toolCallId, args, toolTracker, toolRegistry);\n }, delay);\n}\n\n/**\n * Execute a single client-side tool and return the result.\n * @param tool - The tool definition from the registry\n * @param toolCallId - The ID of the tool call to respond to\n * @param args - The parsed arguments for the tool\n * @returns ToolResultContent with the execution result or error\n */\nexport async function executeClientTool(\n tool: TamboTool,\n toolCallId: string,\n args: Record<string, unknown>,\n): Promise<ToolResultContent> {\n try {\n const result = await tool.tool(args);\n\n // Transform result to content if transformer provided\n let content: (TextContent | ResourceContent)[];\n if (tool.transformToContent) {\n // transformToContent may return content parts in beta format\n // Convert to v1 format (TextContent | ResourceContent)\n const transformed = await tool.transformToContent(result);\n content = transformed.map((part) => {\n if (part.type === \"text\" && \"text\" in part && part.text) {\n return { type: \"text\" as const, text: part.text };\n }\n // For other types, stringify as text\n return {\n type: \"text\" as const,\n text: JSON.stringify(part),\n };\n });\n } else {\n // Default: stringify result as text\n content = [\n {\n type: \"text\" as const,\n text: typeof result === \"string\" ? result : JSON.stringify(result),\n },\n ];\n }\n\n return {\n type: \"tool_result\",\n toolUseId: toolCallId,\n content,\n };\n } catch (error) {\n return {\n type: \"tool_result\",\n toolUseId: toolCallId,\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text:\n error instanceof Error ? error.message : \"Tool execution failed\",\n },\n ],\n };\n }\n}\n\n/**\n * Execute all pending tool calls and return their results.\n * Tools are executed sequentially to avoid race conditions when\n * tools may have side effects that depend on each other.\n * @param toolCalls - Map of tool call IDs to their call details\n * @param registry - Registry of tool names to their definitions (Map or Record)\n * @returns Array of ToolResultContent for all executed tools\n */\nexport async function executeAllPendingTools(\n toolCalls: Map<string, PendingToolCall>,\n registry: Map<string, TamboTool> | Record<string, TamboTool>,\n): Promise<ToolResultContent[]> {\n const results: ToolResultContent[] = [];\n\n // Normalize registry to allow lookup regardless of Map or Record\n const getTool = (name: string): TamboTool | undefined => {\n if (registry instanceof Map) {\n return registry.get(name);\n }\n return registry[name];\n };\n\n for (const [toolCallId, { name, input }] of toolCalls) {\n const tool = getTool(name);\n if (!tool) {\n results.push({\n type: \"tool_result\",\n toolUseId: toolCallId,\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Tool \"${name}\" not found in registry`,\n },\n ],\n });\n continue;\n }\n\n const result = await executeClientTool(tool, toolCallId, input);\n results.push(result);\n }\n\n return results;\n}\n"]}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@ag-ui/core");
|
|
3
4
|
const zod_1 = require("zod");
|
|
4
5
|
const tool_executor_1 = require("./tool-executor");
|
|
6
|
+
const tool_call_tracker_1 = require("./tool-call-tracker");
|
|
5
7
|
describe("tool-executor", () => {
|
|
6
8
|
describe("executeClientTool", () => {
|
|
7
9
|
it("executes a tool and returns text result", async () => {
|
|
@@ -223,5 +225,214 @@ describe("tool-executor", () => {
|
|
|
223
225
|
});
|
|
224
226
|
});
|
|
225
227
|
});
|
|
228
|
+
describe("executeStreamableToolCall", () => {
|
|
229
|
+
function createTrackerWithToolCall(toolCallId, toolName) {
|
|
230
|
+
const tracker = new tool_call_tracker_1.ToolCallTracker();
|
|
231
|
+
tracker.handleEvent({
|
|
232
|
+
type: core_1.EventType.TOOL_CALL_START,
|
|
233
|
+
toolCallId,
|
|
234
|
+
toolCallName: toolName,
|
|
235
|
+
parentMessageId: "msg_1",
|
|
236
|
+
});
|
|
237
|
+
tracker.handleEvent({
|
|
238
|
+
type: core_1.EventType.TOOL_CALL_ARGS,
|
|
239
|
+
toolCallId,
|
|
240
|
+
delta: '{"text":"hello"}',
|
|
241
|
+
});
|
|
242
|
+
return tracker;
|
|
243
|
+
}
|
|
244
|
+
it("calls tool when tamboStreamableHint is true", async () => {
|
|
245
|
+
const toolFn = jest.fn().mockResolvedValue(undefined);
|
|
246
|
+
const registry = {
|
|
247
|
+
write_story: {
|
|
248
|
+
name: "write_story",
|
|
249
|
+
description: "Writes a story",
|
|
250
|
+
tool: toolFn,
|
|
251
|
+
inputSchema: zod_1.z.object({ text: zod_1.z.string() }),
|
|
252
|
+
outputSchema: zod_1.z.void(),
|
|
253
|
+
annotations: { tamboStreamableHint: true },
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
const tracker = createTrackerWithToolCall("call_1", "write_story");
|
|
257
|
+
await (0, tool_executor_1.executeStreamableToolCall)("call_1", { text: "hello" }, tracker, registry);
|
|
258
|
+
expect(toolFn).toHaveBeenCalledWith({ text: "hello" });
|
|
259
|
+
});
|
|
260
|
+
it("does NOT call tool when tamboStreamableHint is false", async () => {
|
|
261
|
+
const toolFn = jest.fn().mockResolvedValue(undefined);
|
|
262
|
+
const registry = {
|
|
263
|
+
write_story: {
|
|
264
|
+
name: "write_story",
|
|
265
|
+
description: "Writes a story",
|
|
266
|
+
tool: toolFn,
|
|
267
|
+
inputSchema: zod_1.z.object({ text: zod_1.z.string() }),
|
|
268
|
+
outputSchema: zod_1.z.void(),
|
|
269
|
+
annotations: { tamboStreamableHint: false },
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
const tracker = createTrackerWithToolCall("call_1", "write_story");
|
|
273
|
+
await (0, tool_executor_1.executeStreamableToolCall)("call_1", { text: "hello" }, tracker, registry);
|
|
274
|
+
expect(toolFn).not.toHaveBeenCalled();
|
|
275
|
+
});
|
|
276
|
+
it("does NOT call tool when tamboStreamableHint is undefined", async () => {
|
|
277
|
+
const toolFn = jest.fn().mockResolvedValue(undefined);
|
|
278
|
+
const registry = {
|
|
279
|
+
write_story: {
|
|
280
|
+
name: "write_story",
|
|
281
|
+
description: "Writes a story",
|
|
282
|
+
tool: toolFn,
|
|
283
|
+
inputSchema: zod_1.z.object({ text: zod_1.z.string() }),
|
|
284
|
+
outputSchema: zod_1.z.void(),
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
const tracker = createTrackerWithToolCall("call_1", "write_story");
|
|
288
|
+
await (0, tool_executor_1.executeStreamableToolCall)("call_1", { text: "hello" }, tracker, registry);
|
|
289
|
+
expect(toolFn).not.toHaveBeenCalled();
|
|
290
|
+
});
|
|
291
|
+
it("does NOT call tool when tool is not in registry", async () => {
|
|
292
|
+
const registry = {};
|
|
293
|
+
const tracker = createTrackerWithToolCall("call_1", "missing_tool");
|
|
294
|
+
// Should not throw
|
|
295
|
+
await (0, tool_executor_1.executeStreamableToolCall)("call_1", { text: "hello" }, tracker, registry);
|
|
296
|
+
});
|
|
297
|
+
it("logs and swallows tool execution errors during streaming", async () => {
|
|
298
|
+
const warnSpy = jest.spyOn(console, "warn").mockImplementation(() => { });
|
|
299
|
+
const registry = {
|
|
300
|
+
write_story: {
|
|
301
|
+
name: "write_story",
|
|
302
|
+
description: "Writes a story",
|
|
303
|
+
tool: jest.fn().mockRejectedValue(new Error("tool error")),
|
|
304
|
+
inputSchema: zod_1.z.object({ text: zod_1.z.string() }),
|
|
305
|
+
outputSchema: zod_1.z.void(),
|
|
306
|
+
annotations: { tamboStreamableHint: true },
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
const tracker = createTrackerWithToolCall("call_1", "write_story");
|
|
310
|
+
// Should not throw
|
|
311
|
+
await (0, tool_executor_1.executeStreamableToolCall)("call_1", { text: "hello" }, tracker, registry);
|
|
312
|
+
expect(warnSpy).toHaveBeenCalledTimes(1);
|
|
313
|
+
const warningMessage = String(warnSpy.mock.calls[0]?.[0]);
|
|
314
|
+
expect(warningMessage).toContain("write_story");
|
|
315
|
+
expect(warningMessage).toContain("call_1");
|
|
316
|
+
warnSpy.mockRestore();
|
|
317
|
+
});
|
|
318
|
+
it("returns early when tool call ID is not being tracked", async () => {
|
|
319
|
+
const toolFn = jest.fn();
|
|
320
|
+
const registry = {
|
|
321
|
+
write_story: {
|
|
322
|
+
name: "write_story",
|
|
323
|
+
description: "Writes a story",
|
|
324
|
+
tool: toolFn,
|
|
325
|
+
inputSchema: zod_1.z.object({ text: zod_1.z.string() }),
|
|
326
|
+
outputSchema: zod_1.z.void(),
|
|
327
|
+
annotations: { tamboStreamableHint: true },
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
const tracker = new tool_call_tracker_1.ToolCallTracker();
|
|
331
|
+
await (0, tool_executor_1.executeStreamableToolCall)("nonexistent", { text: "hello" }, tracker, registry);
|
|
332
|
+
expect(toolFn).not.toHaveBeenCalled();
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
describe("createThrottledStreamableExecutor", () => {
|
|
336
|
+
beforeEach(() => {
|
|
337
|
+
jest.useFakeTimers();
|
|
338
|
+
});
|
|
339
|
+
afterEach(() => {
|
|
340
|
+
jest.useRealTimers();
|
|
341
|
+
});
|
|
342
|
+
function createTrackerWithToolCall(toolCallId, toolName) {
|
|
343
|
+
const tracker = new tool_call_tracker_1.ToolCallTracker();
|
|
344
|
+
tracker.handleEvent({
|
|
345
|
+
type: core_1.EventType.TOOL_CALL_START,
|
|
346
|
+
toolCallId,
|
|
347
|
+
toolCallName: toolName,
|
|
348
|
+
parentMessageId: "msg_1",
|
|
349
|
+
});
|
|
350
|
+
tracker.handleEvent({
|
|
351
|
+
type: core_1.EventType.TOOL_CALL_ARGS,
|
|
352
|
+
toolCallId,
|
|
353
|
+
delta: '{"text":"hello"}',
|
|
354
|
+
});
|
|
355
|
+
return tracker;
|
|
356
|
+
}
|
|
357
|
+
it("fires immediately on the leading edge", () => {
|
|
358
|
+
const toolFn = jest.fn().mockResolvedValue(undefined);
|
|
359
|
+
const registry = {
|
|
360
|
+
write_story: {
|
|
361
|
+
name: "write_story",
|
|
362
|
+
description: "Writes a story",
|
|
363
|
+
tool: toolFn,
|
|
364
|
+
inputSchema: zod_1.z.object({ text: zod_1.z.string() }),
|
|
365
|
+
outputSchema: zod_1.z.void(),
|
|
366
|
+
annotations: { tamboStreamableHint: true },
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
const tracker = createTrackerWithToolCall("call_1", "write_story");
|
|
370
|
+
const executor = (0, tool_executor_1.createThrottledStreamableExecutor)(tracker, registry, 100);
|
|
371
|
+
executor.schedule("call_1", { text: "hello" });
|
|
372
|
+
// Leading edge: fires immediately
|
|
373
|
+
expect(toolFn).toHaveBeenCalledTimes(1);
|
|
374
|
+
expect(toolFn).toHaveBeenCalledWith({ text: "hello" });
|
|
375
|
+
});
|
|
376
|
+
it("collapses rapid calls, fires leading then trailing with latest args", () => {
|
|
377
|
+
const toolFn = jest.fn().mockResolvedValue(undefined);
|
|
378
|
+
const registry = {
|
|
379
|
+
write_story: {
|
|
380
|
+
name: "write_story",
|
|
381
|
+
description: "Writes a story",
|
|
382
|
+
tool: toolFn,
|
|
383
|
+
inputSchema: zod_1.z.object({ text: zod_1.z.string() }),
|
|
384
|
+
outputSchema: zod_1.z.void(),
|
|
385
|
+
annotations: { tamboStreamableHint: true },
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
const tracker = createTrackerWithToolCall("call_1", "write_story");
|
|
389
|
+
const executor = (0, tool_executor_1.createThrottledStreamableExecutor)(tracker, registry, 100);
|
|
390
|
+
executor.schedule("call_1", { text: "h" });
|
|
391
|
+
// Leading edge fires immediately with first value
|
|
392
|
+
expect(toolFn).toHaveBeenCalledTimes(1);
|
|
393
|
+
expect(toolFn).toHaveBeenCalledWith({ text: "h" });
|
|
394
|
+
jest.advanceTimersByTime(50);
|
|
395
|
+
executor.schedule("call_1", { text: "he" });
|
|
396
|
+
jest.advanceTimersByTime(50);
|
|
397
|
+
executor.schedule("call_1", { text: "hel" });
|
|
398
|
+
jest.advanceTimersByTime(100);
|
|
399
|
+
// Trailing edge fires with latest value after cooldown
|
|
400
|
+
expect(toolFn).toHaveBeenCalledTimes(3);
|
|
401
|
+
expect(toolFn).toHaveBeenLastCalledWith({ text: "hel" });
|
|
402
|
+
});
|
|
403
|
+
it("flush() executes pending trailing calls immediately", () => {
|
|
404
|
+
const toolFn = jest.fn().mockResolvedValue(undefined);
|
|
405
|
+
const registry = {
|
|
406
|
+
write_story: {
|
|
407
|
+
name: "write_story",
|
|
408
|
+
description: "Writes a story",
|
|
409
|
+
tool: toolFn,
|
|
410
|
+
inputSchema: zod_1.z.object({ text: zod_1.z.string() }),
|
|
411
|
+
outputSchema: zod_1.z.void(),
|
|
412
|
+
annotations: { tamboStreamableHint: true },
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
const tracker = createTrackerWithToolCall("call_1", "write_story");
|
|
416
|
+
const executor = (0, tool_executor_1.createThrottledStreamableExecutor)(tracker, registry, 100);
|
|
417
|
+
executor.schedule("call_1", { text: "hello" });
|
|
418
|
+
// Leading edge fires immediately
|
|
419
|
+
expect(toolFn).toHaveBeenCalledTimes(1);
|
|
420
|
+
executor.schedule("call_1", { text: "hello world" });
|
|
421
|
+
executor.flush();
|
|
422
|
+
// Trailing fires with latest value
|
|
423
|
+
expect(toolFn).toHaveBeenCalledTimes(2);
|
|
424
|
+
expect(toolFn).toHaveBeenLastCalledWith({ text: "hello world" });
|
|
425
|
+
// Timer should be cancelled — advancing should not fire again
|
|
426
|
+
jest.advanceTimersByTime(200);
|
|
427
|
+
expect(toolFn).toHaveBeenCalledTimes(2);
|
|
428
|
+
});
|
|
429
|
+
it("flush() is a no-op when nothing is pending", () => {
|
|
430
|
+
const registry = {};
|
|
431
|
+
const tracker = new tool_call_tracker_1.ToolCallTracker();
|
|
432
|
+
const executor = (0, tool_executor_1.createThrottledStreamableExecutor)(tracker, registry, 100);
|
|
433
|
+
// Should not throw
|
|
434
|
+
executor.flush();
|
|
435
|
+
});
|
|
436
|
+
});
|
|
226
437
|
});
|
|
227
438
|
//# sourceMappingURL=tool-executor.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-executor.test.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport type { TamboTool } from \"../../model/component-metadata\";\nimport {\n executeClientTool,\n executeAllPendingTools,\n type PendingToolCall,\n} from \"./tool-executor\";\n\ndescribe(\"tool-executor\", () => {\n describe(\"executeClientTool\", () => {\n it(\"executes a tool and returns text result\", async () => {\n const tool: TamboTool = {\n name: \"get_weather\",\n description: \"Gets weather\",\n tool: async ({ city }: { city: string }) =>\n `Weather in ${city} is sunny`,\n inputSchema: z.object({ city: z.string() }),\n outputSchema: z.string(),\n };\n\n const result = await executeClientTool(tool, \"call-1\", {\n city: \"Seattle\",\n });\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"Weather in Seattle is sunny\" }],\n });\n });\n\n it(\"stringifies non-string results\", async () => {\n const tool: TamboTool = {\n name: \"get_data\",\n description: \"Gets data\",\n tool: async () => ({ value: 42 }),\n inputSchema: z.object({}),\n outputSchema: z.object({ value: z.number() }),\n };\n\n const result = await executeClientTool(tool, \"call-2\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-2\",\n content: [{ type: \"text\", text: '{\"value\":42}' }],\n });\n });\n\n it(\"uses transformToContent when provided\", async () => {\n const tool: TamboTool = {\n name: \"custom_tool\",\n description: \"Custom tool\",\n tool: async () => \"custom result\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n transformToContent: (result) => [\n { type: \"text\", text: `Transformed: ${result}` },\n ],\n };\n\n const result = await executeClientTool(tool, \"call-3\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-3\",\n content: [{ type: \"text\", text: \"Transformed: custom result\" }],\n });\n });\n\n it(\"handles transformToContent with non-text types by stringifying\", async () => {\n const tool: TamboTool = {\n name: \"image_tool\",\n description: \"Image tool\",\n tool: async () => \"image data\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n transformToContent: () => [\n {\n type: \"image_url\",\n image_url: { url: \"https://example.com/image.png\" },\n },\n ],\n };\n\n const result = await executeClientTool(tool, \"call-4\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-4\",\n content: [\n {\n type: \"text\",\n text: '{\"type\":\"image_url\",\"image_url\":{\"url\":\"https://example.com/image.png\"}}',\n },\n ],\n });\n });\n\n it(\"handles tool execution errors gracefully\", async () => {\n const tool: TamboTool = {\n name: \"failing_tool\",\n description: \"A tool that fails\",\n tool: async () => {\n throw new Error(\"Tool failed!\");\n },\n inputSchema: z.object({}),\n outputSchema: z.void(),\n };\n\n const result = await executeClientTool(tool, \"call-5\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-5\",\n isError: true,\n content: [{ type: \"text\", text: \"Tool failed!\" }],\n });\n });\n\n it(\"handles non-Error throws gracefully\", async () => {\n const tool: TamboTool = {\n name: \"throwing_tool\",\n description: \"A tool that throws a string\",\n tool: async () => {\n throw \"string error\";\n },\n inputSchema: z.object({}),\n outputSchema: z.void(),\n };\n\n const result = await executeClientTool(tool, \"call-6\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-6\",\n isError: true,\n content: [{ type: \"text\", text: \"Tool execution failed\" }],\n });\n });\n });\n\n describe(\"executeAllPendingTools\", () => {\n it(\"executes multiple tools with Map registry\", async () => {\n const registry = new Map<string, TamboTool>([\n [\n \"add\",\n {\n name: \"add\",\n description: \"Adds numbers\",\n tool: async ({ a, b }: { a: number; b: number }) => a + b,\n inputSchema: z.object({ a: z.number(), b: z.number() }),\n outputSchema: z.number(),\n },\n ],\n [\n \"multiply\",\n {\n name: \"multiply\",\n description: \"Multiplies numbers\",\n tool: async ({ a, b }: { a: number; b: number }) => a * b,\n inputSchema: z.object({ a: z.number(), b: z.number() }),\n outputSchema: z.number(),\n },\n ],\n ]);\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"add\", input: { a: 2, b: 3 } }],\n [\"call-2\", { name: \"multiply\", input: { a: 4, b: 5 } }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(2);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"5\" }],\n });\n expect(results[1]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-2\",\n content: [{ type: \"text\", text: \"20\" }],\n });\n });\n\n it(\"executes tools with Record registry\", async () => {\n const registry: Record<string, TamboTool> = {\n greet: {\n name: \"greet\",\n description: \"Greets user\",\n tool: async ({ name }: { name: string }) => `Hello, ${name}!`,\n inputSchema: z.object({ name: z.string() }),\n outputSchema: z.string(),\n },\n };\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"greet\", input: { name: \"World\" } }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(1);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"Hello, World!\" }],\n });\n });\n\n it(\"returns error result for unknown tools\", async () => {\n const registry = new Map<string, TamboTool>();\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"unknown_tool\", input: {} }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(1);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n isError: true,\n content: [\n { type: \"text\", text: 'Tool \"unknown_tool\" not found in registry' },\n ],\n });\n });\n\n it(\"handles mixed known and unknown tools\", async () => {\n const registry = new Map<string, TamboTool>([\n [\n \"known\",\n {\n name: \"known\",\n description: \"Known tool\",\n tool: async () => \"success\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n },\n ],\n ]);\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"known\", input: {} }],\n [\"call-2\", { name: \"unknown\", input: {} }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(2);\n expect(results[0].isError).toBeUndefined();\n expect(results[0].content[0]).toEqual({ type: \"text\", text: \"success\" });\n expect(results[1].isError).toBe(true);\n expect(results[1].content[0]).toEqual({\n type: \"text\",\n text: 'Tool \"unknown\" not found in registry',\n });\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"tool-executor.test.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-executor.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventType } from \"@ag-ui/core\";\nimport { z } from \"zod\";\nimport type { TamboTool } from \"../../model/component-metadata\";\nimport {\n executeClientTool,\n executeAllPendingTools,\n executeStreamableToolCall,\n createThrottledStreamableExecutor,\n type PendingToolCall,\n} from \"./tool-executor\";\nimport { ToolCallTracker } from \"./tool-call-tracker\";\n\ndescribe(\"tool-executor\", () => {\n describe(\"executeClientTool\", () => {\n it(\"executes a tool and returns text result\", async () => {\n const tool: TamboTool = {\n name: \"get_weather\",\n description: \"Gets weather\",\n tool: async ({ city }: { city: string }) =>\n `Weather in ${city} is sunny`,\n inputSchema: z.object({ city: z.string() }),\n outputSchema: z.string(),\n };\n\n const result = await executeClientTool(tool, \"call-1\", {\n city: \"Seattle\",\n });\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"Weather in Seattle is sunny\" }],\n });\n });\n\n it(\"stringifies non-string results\", async () => {\n const tool: TamboTool = {\n name: \"get_data\",\n description: \"Gets data\",\n tool: async () => ({ value: 42 }),\n inputSchema: z.object({}),\n outputSchema: z.object({ value: z.number() }),\n };\n\n const result = await executeClientTool(tool, \"call-2\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-2\",\n content: [{ type: \"text\", text: '{\"value\":42}' }],\n });\n });\n\n it(\"uses transformToContent when provided\", async () => {\n const tool: TamboTool = {\n name: \"custom_tool\",\n description: \"Custom tool\",\n tool: async () => \"custom result\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n transformToContent: (result) => [\n { type: \"text\", text: `Transformed: ${result}` },\n ],\n };\n\n const result = await executeClientTool(tool, \"call-3\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-3\",\n content: [{ type: \"text\", text: \"Transformed: custom result\" }],\n });\n });\n\n it(\"handles transformToContent with non-text types by stringifying\", async () => {\n const tool: TamboTool = {\n name: \"image_tool\",\n description: \"Image tool\",\n tool: async () => \"image data\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n transformToContent: () => [\n {\n type: \"image_url\",\n image_url: { url: \"https://example.com/image.png\" },\n },\n ],\n };\n\n const result = await executeClientTool(tool, \"call-4\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-4\",\n content: [\n {\n type: \"text\",\n text: '{\"type\":\"image_url\",\"image_url\":{\"url\":\"https://example.com/image.png\"}}',\n },\n ],\n });\n });\n\n it(\"handles tool execution errors gracefully\", async () => {\n const tool: TamboTool = {\n name: \"failing_tool\",\n description: \"A tool that fails\",\n tool: async () => {\n throw new Error(\"Tool failed!\");\n },\n inputSchema: z.object({}),\n outputSchema: z.void(),\n };\n\n const result = await executeClientTool(tool, \"call-5\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-5\",\n isError: true,\n content: [{ type: \"text\", text: \"Tool failed!\" }],\n });\n });\n\n it(\"handles non-Error throws gracefully\", async () => {\n const tool: TamboTool = {\n name: \"throwing_tool\",\n description: \"A tool that throws a string\",\n tool: async () => {\n throw \"string error\";\n },\n inputSchema: z.object({}),\n outputSchema: z.void(),\n };\n\n const result = await executeClientTool(tool, \"call-6\", {});\n\n expect(result).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-6\",\n isError: true,\n content: [{ type: \"text\", text: \"Tool execution failed\" }],\n });\n });\n });\n\n describe(\"executeAllPendingTools\", () => {\n it(\"executes multiple tools with Map registry\", async () => {\n const registry = new Map<string, TamboTool>([\n [\n \"add\",\n {\n name: \"add\",\n description: \"Adds numbers\",\n tool: async ({ a, b }: { a: number; b: number }) => a + b,\n inputSchema: z.object({ a: z.number(), b: z.number() }),\n outputSchema: z.number(),\n },\n ],\n [\n \"multiply\",\n {\n name: \"multiply\",\n description: \"Multiplies numbers\",\n tool: async ({ a, b }: { a: number; b: number }) => a * b,\n inputSchema: z.object({ a: z.number(), b: z.number() }),\n outputSchema: z.number(),\n },\n ],\n ]);\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"add\", input: { a: 2, b: 3 } }],\n [\"call-2\", { name: \"multiply\", input: { a: 4, b: 5 } }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(2);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"5\" }],\n });\n expect(results[1]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-2\",\n content: [{ type: \"text\", text: \"20\" }],\n });\n });\n\n it(\"executes tools with Record registry\", async () => {\n const registry: Record<string, TamboTool> = {\n greet: {\n name: \"greet\",\n description: \"Greets user\",\n tool: async ({ name }: { name: string }) => `Hello, ${name}!`,\n inputSchema: z.object({ name: z.string() }),\n outputSchema: z.string(),\n },\n };\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"greet\", input: { name: \"World\" } }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(1);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n content: [{ type: \"text\", text: \"Hello, World!\" }],\n });\n });\n\n it(\"returns error result for unknown tools\", async () => {\n const registry = new Map<string, TamboTool>();\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"unknown_tool\", input: {} }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(1);\n expect(results[0]).toEqual({\n type: \"tool_result\",\n toolUseId: \"call-1\",\n isError: true,\n content: [\n { type: \"text\", text: 'Tool \"unknown_tool\" not found in registry' },\n ],\n });\n });\n\n it(\"handles mixed known and unknown tools\", async () => {\n const registry = new Map<string, TamboTool>([\n [\n \"known\",\n {\n name: \"known\",\n description: \"Known tool\",\n tool: async () => \"success\",\n inputSchema: z.object({}),\n outputSchema: z.string(),\n },\n ],\n ]);\n\n const toolCalls = new Map<string, PendingToolCall>([\n [\"call-1\", { name: \"known\", input: {} }],\n [\"call-2\", { name: \"unknown\", input: {} }],\n ]);\n\n const results = await executeAllPendingTools(toolCalls, registry);\n\n expect(results).toHaveLength(2);\n expect(results[0].isError).toBeUndefined();\n expect(results[0].content[0]).toEqual({ type: \"text\", text: \"success\" });\n expect(results[1].isError).toBe(true);\n expect(results[1].content[0]).toEqual({\n type: \"text\",\n text: 'Tool \"unknown\" not found in registry',\n });\n });\n });\n\n describe(\"executeStreamableToolCall\", () => {\n function createTrackerWithToolCall(\n toolCallId: string,\n toolName: string,\n ): ToolCallTracker {\n const tracker = new ToolCallTracker();\n tracker.handleEvent({\n type: EventType.TOOL_CALL_START,\n toolCallId,\n toolCallName: toolName,\n parentMessageId: \"msg_1\",\n });\n tracker.handleEvent({\n type: EventType.TOOL_CALL_ARGS,\n toolCallId,\n delta: '{\"text\":\"hello\"}',\n });\n return tracker;\n }\n\n it(\"calls tool when tamboStreamableHint is true\", async () => {\n const toolFn = jest.fn().mockResolvedValue(undefined);\n const registry: Record<string, TamboTool> = {\n write_story: {\n name: \"write_story\",\n description: \"Writes a story\",\n tool: toolFn,\n inputSchema: z.object({ text: z.string() }),\n outputSchema: z.void(),\n annotations: { tamboStreamableHint: true },\n },\n };\n\n const tracker = createTrackerWithToolCall(\"call_1\", \"write_story\");\n await executeStreamableToolCall(\n \"call_1\",\n { text: \"hello\" },\n tracker,\n registry,\n );\n\n expect(toolFn).toHaveBeenCalledWith({ text: \"hello\" });\n });\n\n it(\"does NOT call tool when tamboStreamableHint is false\", async () => {\n const toolFn = jest.fn().mockResolvedValue(undefined);\n const registry: Record<string, TamboTool> = {\n write_story: {\n name: \"write_story\",\n description: \"Writes a story\",\n tool: toolFn,\n inputSchema: z.object({ text: z.string() }),\n outputSchema: z.void(),\n annotations: { tamboStreamableHint: false },\n },\n };\n\n const tracker = createTrackerWithToolCall(\"call_1\", \"write_story\");\n await executeStreamableToolCall(\n \"call_1\",\n { text: \"hello\" },\n tracker,\n registry,\n );\n\n expect(toolFn).not.toHaveBeenCalled();\n });\n\n it(\"does NOT call tool when tamboStreamableHint is undefined\", async () => {\n const toolFn = jest.fn().mockResolvedValue(undefined);\n const registry: Record<string, TamboTool> = {\n write_story: {\n name: \"write_story\",\n description: \"Writes a story\",\n tool: toolFn,\n inputSchema: z.object({ text: z.string() }),\n outputSchema: z.void(),\n },\n };\n\n const tracker = createTrackerWithToolCall(\"call_1\", \"write_story\");\n await executeStreamableToolCall(\n \"call_1\",\n { text: \"hello\" },\n tracker,\n registry,\n );\n\n expect(toolFn).not.toHaveBeenCalled();\n });\n\n it(\"does NOT call tool when tool is not in registry\", async () => {\n const registry: Record<string, TamboTool> = {};\n const tracker = createTrackerWithToolCall(\"call_1\", \"missing_tool\");\n\n // Should not throw\n await executeStreamableToolCall(\n \"call_1\",\n { text: \"hello\" },\n tracker,\n registry,\n );\n });\n\n it(\"logs and swallows tool execution errors during streaming\", async () => {\n const warnSpy = jest.spyOn(console, \"warn\").mockImplementation(() => {});\n const registry: Record<string, TamboTool> = {\n write_story: {\n name: \"write_story\",\n description: \"Writes a story\",\n tool: jest.fn().mockRejectedValue(new Error(\"tool error\")),\n inputSchema: z.object({ text: z.string() }),\n outputSchema: z.void(),\n annotations: { tamboStreamableHint: true },\n },\n };\n\n const tracker = createTrackerWithToolCall(\"call_1\", \"write_story\");\n\n // Should not throw\n await executeStreamableToolCall(\n \"call_1\",\n { text: \"hello\" },\n tracker,\n registry,\n );\n\n expect(warnSpy).toHaveBeenCalledTimes(1);\n const warningMessage = String(warnSpy.mock.calls[0]?.[0]);\n expect(warningMessage).toContain(\"write_story\");\n expect(warningMessage).toContain(\"call_1\");\n warnSpy.mockRestore();\n });\n\n it(\"returns early when tool call ID is not being tracked\", async () => {\n const toolFn = jest.fn();\n const registry: Record<string, TamboTool> = {\n write_story: {\n name: \"write_story\",\n description: \"Writes a story\",\n tool: toolFn,\n inputSchema: z.object({ text: z.string() }),\n outputSchema: z.void(),\n annotations: { tamboStreamableHint: true },\n },\n };\n\n const tracker = new ToolCallTracker();\n await executeStreamableToolCall(\n \"nonexistent\",\n { text: \"hello\" },\n tracker,\n registry,\n );\n\n expect(toolFn).not.toHaveBeenCalled();\n });\n });\n\n describe(\"createThrottledStreamableExecutor\", () => {\n beforeEach(() => {\n jest.useFakeTimers();\n });\n\n afterEach(() => {\n jest.useRealTimers();\n });\n\n function createTrackerWithToolCall(\n toolCallId: string,\n toolName: string,\n ): ToolCallTracker {\n const tracker = new ToolCallTracker();\n tracker.handleEvent({\n type: EventType.TOOL_CALL_START,\n toolCallId,\n toolCallName: toolName,\n parentMessageId: \"msg_1\",\n });\n tracker.handleEvent({\n type: EventType.TOOL_CALL_ARGS,\n toolCallId,\n delta: '{\"text\":\"hello\"}',\n });\n return tracker;\n }\n\n it(\"fires immediately on the leading edge\", () => {\n const toolFn = jest.fn().mockResolvedValue(undefined);\n const registry: Record<string, TamboTool> = {\n write_story: {\n name: \"write_story\",\n description: \"Writes a story\",\n tool: toolFn,\n inputSchema: z.object({ text: z.string() }),\n outputSchema: z.void(),\n annotations: { tamboStreamableHint: true },\n },\n };\n\n const tracker = createTrackerWithToolCall(\"call_1\", \"write_story\");\n const executor = createThrottledStreamableExecutor(\n tracker,\n registry,\n 100,\n );\n\n executor.schedule(\"call_1\", { text: \"hello\" });\n // Leading edge: fires immediately\n expect(toolFn).toHaveBeenCalledTimes(1);\n expect(toolFn).toHaveBeenCalledWith({ text: \"hello\" });\n });\n\n it(\"collapses rapid calls, fires leading then trailing with latest args\", () => {\n const toolFn = jest.fn().mockResolvedValue(undefined);\n const registry: Record<string, TamboTool> = {\n write_story: {\n name: \"write_story\",\n description: \"Writes a story\",\n tool: toolFn,\n inputSchema: z.object({ text: z.string() }),\n outputSchema: z.void(),\n annotations: { tamboStreamableHint: true },\n },\n };\n\n const tracker = createTrackerWithToolCall(\"call_1\", \"write_story\");\n const executor = createThrottledStreamableExecutor(\n tracker,\n registry,\n 100,\n );\n\n executor.schedule(\"call_1\", { text: \"h\" });\n // Leading edge fires immediately with first value\n expect(toolFn).toHaveBeenCalledTimes(1);\n expect(toolFn).toHaveBeenCalledWith({ text: \"h\" });\n\n jest.advanceTimersByTime(50);\n executor.schedule(\"call_1\", { text: \"he\" });\n jest.advanceTimersByTime(50);\n executor.schedule(\"call_1\", { text: \"hel\" });\n jest.advanceTimersByTime(100);\n\n // Trailing edge fires with latest value after cooldown\n expect(toolFn).toHaveBeenCalledTimes(3);\n expect(toolFn).toHaveBeenLastCalledWith({ text: \"hel\" });\n });\n\n it(\"flush() executes pending trailing calls immediately\", () => {\n const toolFn = jest.fn().mockResolvedValue(undefined);\n const registry: Record<string, TamboTool> = {\n write_story: {\n name: \"write_story\",\n description: \"Writes a story\",\n tool: toolFn,\n inputSchema: z.object({ text: z.string() }),\n outputSchema: z.void(),\n annotations: { tamboStreamableHint: true },\n },\n };\n\n const tracker = createTrackerWithToolCall(\"call_1\", \"write_story\");\n const executor = createThrottledStreamableExecutor(\n tracker,\n registry,\n 100,\n );\n\n executor.schedule(\"call_1\", { text: \"hello\" });\n // Leading edge fires immediately\n expect(toolFn).toHaveBeenCalledTimes(1);\n\n executor.schedule(\"call_1\", { text: \"hello world\" });\n executor.flush();\n // Trailing fires with latest value\n expect(toolFn).toHaveBeenCalledTimes(2);\n expect(toolFn).toHaveBeenLastCalledWith({ text: \"hello world\" });\n\n // Timer should be cancelled — advancing should not fire again\n jest.advanceTimersByTime(200);\n expect(toolFn).toHaveBeenCalledTimes(2);\n });\n\n it(\"flush() is a no-op when nothing is pending\", () => {\n const registry: Record<string, TamboTool> = {};\n const tracker = new ToolCallTracker();\n const executor = createThrottledStreamableExecutor(\n tracker,\n registry,\n 100,\n );\n\n // Should not throw\n executor.flush();\n });\n });\n});\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import type { ToolAnnotations } from "../model/component-metadata.js";
|
|
2
3
|
import { SupportedSchema } from "../schema/index.js";
|
|
3
4
|
export interface InteractableConfig<Props = Record<string, unknown>, State = Record<string, unknown>> {
|
|
4
5
|
/**
|
|
@@ -20,6 +21,13 @@ export interface InteractableConfig<Props = Record<string, unknown>, State = Rec
|
|
|
20
21
|
* validated against this schema.
|
|
21
22
|
*/
|
|
22
23
|
stateSchema?: SupportedSchema<State>;
|
|
24
|
+
/**
|
|
25
|
+
* Optional annotations for the interactable component's auto-registered tools
|
|
26
|
+
* (props update and state update). By default, `tamboStreamableHint` is `true`
|
|
27
|
+
* so props/state updates stream in real-time. Set `{ tamboStreamableHint: false }`
|
|
28
|
+
* to disable streaming for this component's tools.
|
|
29
|
+
*/
|
|
30
|
+
annotations?: ToolAnnotations;
|
|
23
31
|
}
|
|
24
32
|
/**
|
|
25
33
|
* Props injected by withTamboInteractable HOC. These can be passed to the wrapped
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"with-tambo-interactable.d.ts","sourceRoot":"","sources":["../../src/hoc/with-tambo-interactable.tsx"],"names":[],"mappings":"AACA,OAAO,KAAmD,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"with-tambo-interactable.d.ts","sourceRoot":"","sources":["../../src/hoc/with-tambo-interactable.tsx"],"names":[],"mappings":"AACA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAExE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAG5C,MAAM,WAAW,kBAAkB,CACjC,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE/B;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC;IACrC;;;OAGG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC;IACrC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,qBAAqB,CAAC,cAAc,SAAS,MAAM,EACjE,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,EACrD,MAAM,EAAE,kBAAkB,yDA8H3B"}
|