@tambo-ai/react 0.74.0 → 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.d.ts.map +1 -1
- package/dist/mcp/mcp-hooks.js +70 -16
- package/dist/mcp/mcp-hooks.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.d.ts.map +1 -1
- package/esm/mcp/mcp-hooks.js +70 -16
- package/esm/mcp/mcp-hooks.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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tambo-v1-send-message.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-send-message.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * Send Message Hook for v1 API\n *\n * React Query mutation hook for sending messages and handling streaming responses.\n */\n\nimport React, { useContext } from \"react\";\nimport { EventType, type RunErrorEvent } from \"@ag-ui/core\";\nimport { asTamboCustomEvent, type RunAwaitingInputEvent } from \"../types/event\";\nimport type TamboAI from \"@tambo-ai/typescript-sdk\";\nimport type { Stream } from \"@tambo-ai/typescript-sdk/core/streaming\";\nimport {\n useTamboClient,\n useTamboQueryClient,\n} from \"../../providers/tambo-client-provider\";\nimport { useTamboMutation } from \"../../hooks/react-query-hooks\";\nimport {\n TamboRegistryContext,\n type TamboRegistryContext as TamboRegistry,\n} from \"../../providers/tambo-registry-provider\";\nimport {\n useStreamDispatch,\n useStreamState,\n} from \"../providers/tambo-v1-stream-context\";\nimport { useTamboV1Config } from \"../providers/tambo-v1-provider\";\nimport { useTamboContextHelpers } from \"../../providers/tambo-context-helpers-provider\";\nimport type { InputMessage } from \"../types/message\";\nimport {\n isPlaceholderThreadId,\n type StreamAction,\n} from \"../utils/event-accumulator\";\nimport {\n toAvailableComponents,\n toAvailableTools,\n} from \"../utils/registry-conversion\";\nimport { handleEventStream } from \"../utils/stream-handler\";\nimport { executeAllPendingTools } from \"../utils/tool-executor\";\nimport type { ToolResultContent } from \"@tambo-ai/typescript-sdk/resources/threads/threads\";\nimport { ToolCallTracker } from \"../utils/tool-call-tracker\";\n\n/**\n * Dispatches synthetic AG-UI events to show a user message in the thread.\n * @param dispatch - Stream state dispatcher\n * @param targetThreadId - Thread to add the message to\n * @param messageId - Stable ID for the user message\n * @param messageText - Text content of the message\n */\nfunction dispatchUserMessage(\n dispatch: React.Dispatch<StreamAction>,\n targetThreadId: string,\n messageId: string,\n messageText: string,\n): void {\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId,\n role: \"user\" as const,\n },\n });\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId,\n delta: messageText,\n },\n });\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId,\n },\n });\n}\n\n/**\n * Dispatches synthetic events for tool results as optimistic local state.\n * The server doesn't echo these back for client-side tools.\n * @param dispatch - Stream state dispatcher\n * @param targetThreadId - Thread to add results to\n * @param toolResults - Tool execution results to dispatch\n */\nfunction dispatchToolResults(\n dispatch: React.Dispatch<StreamAction>,\n targetThreadId: string,\n toolResults: ToolResultContent[],\n): void {\n if (toolResults.length === 0) return;\n\n const toolResultMessageId = `msg_tool_result_${Date.now()}`;\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: toolResultMessageId,\n role: \"user\" as const,\n },\n });\n\n for (const result of toolResults) {\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TOOL_CALL_RESULT,\n toolCallId: result.toolUseId,\n messageId: toolResultMessageId,\n content:\n result.content\n .filter((c) => c.type === \"text\")\n .map((c) => (c as { type: \"text\"; text: string }).text)\n .join(\"\") || JSON.stringify(result.content),\n },\n });\n }\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: toolResultMessageId,\n },\n });\n}\n\n/**\n * Checks whether a thread name should be auto-generated based on config\n * and the current thread state.\n * @param threadId - The thread ID (undefined or placeholder means no)\n * @param threadAlreadyHasTitle - Whether the thread already has a title\n * @param preMutationMessageCount - Message count before the current mutation\n * @param autoGenerateNameThreshold - Minimum message count to trigger generation\n * @returns Whether to generate a thread name\n */\nfunction shouldGenerateThreadName(\n threadId: string | undefined,\n threadAlreadyHasTitle: boolean,\n preMutationMessageCount: number,\n autoGenerateNameThreshold: number,\n): threadId is string {\n return (\n !threadAlreadyHasTitle &&\n !!threadId &&\n !isPlaceholderThreadId(threadId) &&\n // +2 accounts for the user message and assistant response just added\n preMutationMessageCount + 2 >= autoGenerateNameThreshold\n );\n}\n\n/**\n * Generates a thread name via the beta API, dispatches the title update,\n * and invalidates the thread list cache. Errors are logged, never thrown.\n * @param client - The Tambo API client\n * @param dispatch - Stream state dispatcher\n * @param queryClient - React Query client for cache invalidation\n * @param threadId - The thread to generate a name for\n */\nasync function generateThreadName(\n client: TamboAI,\n dispatch: React.Dispatch<StreamAction>,\n queryClient: ReturnType<typeof useTamboQueryClient>,\n threadId: string,\n): Promise<void> {\n try {\n const threadWithName = await client.beta.threads.generateName(threadId);\n if (threadWithName.name) {\n dispatch({\n type: \"UPDATE_THREAD_TITLE\",\n threadId,\n title: threadWithName.name,\n });\n await queryClient.invalidateQueries({\n queryKey: [\"v1-threads\", \"list\"],\n });\n }\n } catch (error) {\n console.error(\n \"[useTamboV1SendMessage] Failed to auto-generate thread name:\",\n error,\n );\n }\n}\n\n/**\n * Options for sending a message\n */\nexport interface SendMessageOptions {\n /**\n * The message to send\n */\n message: InputMessage;\n\n /**\n * User message text for optimistic display.\n * If provided, synthetic AG-UI events will be dispatched to show\n * the user message in the thread immediately after getting the threadId.\n */\n userMessageText?: string;\n\n /**\n * Enable debug logging for the stream\n */\n debug?: boolean;\n}\n\n/**\n * Parameters for creating a run stream\n */\nexport interface CreateRunStreamParams {\n client: TamboAI;\n threadId: string | undefined;\n message: InputMessage;\n registry: TamboRegistry;\n userKey: string | undefined;\n /**\n * Previous run ID for continuing a thread with existing messages.\n * Required when threadId is provided and the thread has previous runs.\n */\n previousRunId: string | undefined;\n /**\n * Additional context gathered from context helpers (including interactables).\n * Merged into the message's additionalContext before sending.\n */\n additionalContext?: Record<string, unknown>;\n}\n\n/**\n * Stream types from the SDK\n */\ntype RunStream = Stream<TamboAI.Threads.Runs.RunRunResponse>;\ntype CreateStream = Stream<TamboAI.Threads.Runs.RunCreateResponse>;\n\n/**\n * Result from creating a run stream\n */\nexport interface CreateRunStreamResult {\n stream: RunStream | CreateStream;\n initialThreadId: string | undefined;\n}\n\n/**\n * Parameters for executing tools and continuing the run\n */\ninterface ExecuteToolsParams {\n event: RunAwaitingInputEvent;\n toolTracker: ToolCallTracker;\n registry: TamboRegistry;\n client: TamboAI;\n threadId: string;\n runId: string;\n userKey: string | undefined;\n additionalContext?: Record<string, unknown>;\n}\n\n/**\n * Result from executing tools and continuing the run\n */\ninterface ExecuteToolsResult {\n stream: RunStream;\n toolResults: ToolResultContent[];\n}\n\n/**\n * Executes pending tools and returns a continuation stream.\n *\n * This function does NOT process the continuation stream - it just executes\n * the tools and returns the new stream for the caller to process. This enables\n * the flat loop pattern that correctly handles multi-round tool execution.\n * @param params - The parameters for tool execution\n * @returns The continuation stream and tool results for optimistic local state updates\n */\nasync function executeToolsAndContinue(\n params: ExecuteToolsParams,\n): Promise<ExecuteToolsResult> {\n const {\n event,\n toolTracker,\n registry,\n client,\n threadId,\n runId,\n userKey,\n additionalContext,\n } = params;\n\n const pendingToolCallIds = event.value.pendingToolCalls.map(\n (tc) => tc.toolCallId,\n );\n const toolCallsToExecute = toolTracker.getToolCallsById(pendingToolCallIds);\n\n // Execute tools\n const toolResults = await executeAllPendingTools(\n toolCallsToExecute,\n registry.toolRegistry,\n );\n\n // Clear executed tool calls before continuing\n toolTracker.clearToolCalls(pendingToolCallIds);\n\n // Return the continuation stream and tool results\n const stream = await client.threads.runs.run(threadId, {\n message: {\n role: \"user\",\n content: toolResults,\n additionalContext,\n },\n previousRunId: runId,\n availableComponents: toAvailableComponents(registry.componentList),\n tools: toAvailableTools(registry.toolRegistry),\n userKey,\n });\n\n return { stream, toolResults };\n}\n\n/**\n * Creates a run stream by calling the appropriate API method.\n *\n * If threadId is provided, runs on existing thread via client.threads.runs.run().\n * If no threadId, creates new thread via client.threads.runs.create().\n * @param params - The parameters for creating the run stream\n * @returns The stream and initial thread ID (undefined if creating new thread)\n */\nexport async function createRunStream(\n params: CreateRunStreamParams,\n): Promise<CreateRunStreamResult> {\n const {\n client,\n threadId,\n message,\n registry,\n userKey,\n previousRunId,\n additionalContext,\n } = params;\n\n // Merge helper context with any caller-provided additionalContext on the message\n const mergedContext =\n additionalContext || message.additionalContext\n ? {\n ...((message.additionalContext as Record<string, unknown>) ?? {}),\n ...additionalContext,\n }\n : undefined;\n const messageWithContext: InputMessage = mergedContext\n ? { ...message, additionalContext: mergedContext }\n : message;\n\n // Convert registry components/tools to v1 API format\n const availableComponents = toAvailableComponents(registry.componentList);\n const availableTools = toAvailableTools(registry.toolRegistry);\n\n if (threadId) {\n // Run on existing thread\n const stream = await client.threads.runs.run(threadId, {\n message: messageWithContext,\n availableComponents,\n tools: availableTools,\n userKey,\n previousRunId,\n });\n return { stream, initialThreadId: threadId };\n } else {\n // Create new thread\n const stream = await client.threads.runs.create({\n message: messageWithContext,\n availableComponents,\n tools: availableTools,\n thread: userKey ? { userKey } : undefined,\n });\n // threadId will be extracted from first event (RUN_STARTED)\n return { stream, initialThreadId: undefined };\n }\n}\n\n/**\n * Hook to send a message and handle streaming responses.\n *\n * This hook handles two scenarios:\n * - If threadId provided: runs on existing thread via client.threads.runs.run()\n * - If no threadId: creates new thread via client.threads.runs.create()\n *\n * The hook:\n * - Sends a user message to the API\n * - Streams AG-UI events in real-time\n * - Dispatches events to the stream reducer\n * - Extracts threadId from events when creating new thread\n * - Handles tool execution (Phase 6)\n * - Invalidates thread queries on completion\n * @param threadId - Optional thread ID to send message to. If not provided, creates new thread\n * @returns React Query mutation object with threadId in mutation result\n * @example\n * ```tsx\n * function ChatInput({ threadId }: { threadId?: string }) {\n * const sendMessage = useTamboV1SendMessage(threadId);\n *\n * const handleSubmit = async (text: string) => {\n * const result = await sendMessage.mutateAsync({\n * message: {\n * role: \"user\",\n * content: [{ type: \"text\", text }],\n * },\n * });\n *\n * // If threadId wasn't provided, a new thread was created\n * if (!threadId) {\n * console.log(\"Created thread:\", result.threadId);\n * }\n * };\n *\n * return (\n * <div>\n * <input onSubmit={handleSubmit} />\n * {sendMessage.isPending && <Spinner />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useTamboV1SendMessage(threadId?: string) {\n const client = useTamboClient();\n const dispatch = useStreamDispatch();\n const streamState = useStreamState();\n const {\n userKey,\n autoGenerateThreadName = true,\n autoGenerateNameThreshold = 3,\n } = useTamboV1Config();\n const registry = useContext(TamboRegistryContext);\n const queryClient = useTamboQueryClient();\n const { getAdditionalContext } = useTamboContextHelpers();\n\n if (!registry) {\n throw new Error(\n \"useTamboV1SendMessage must be used within TamboRegistryProvider\",\n );\n }\n\n // Placeholder ID isn't a valid API thread ID - treat as new thread creation\n const isNewThread = isPlaceholderThreadId(threadId);\n const apiThreadId = isNewThread ? undefined : threadId;\n\n // Get previousRunId from the thread's streaming state (if thread exists and has messages)\n const threadState = apiThreadId\n ? streamState.threadMap[apiThreadId]\n : undefined;\n const previousRunId = threadState?.streaming.runId;\n\n return useTamboMutation({\n mutationFn: async (options: SendMessageOptions) => {\n const { message, userMessageText, debug = false } = options;\n\n // Capture pre-mutation state for auto thread name generation\n const existingThread = streamState.threadMap[apiThreadId ?? \"\"];\n const preMutationMessageCount =\n existingThread?.thread.messages.length ?? 0;\n const threadAlreadyHasTitle = !!existingThread?.thread.title;\n\n const toolTracker = new ToolCallTracker();\n\n // Generate a stable message ID for the user message\n const userMessageId = userMessageText\n ? `user_msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`\n : undefined;\n\n // Add user message immediately for instant feedback\n // Use threadId (which could be temp_xxx for new threads) for display\n if (threadId && userMessageText && userMessageId) {\n dispatchUserMessage(dispatch, threadId, userMessageId, userMessageText);\n }\n\n // Gather additional context from all registered context helpers.\n // TODO: This snapshot is captured once and reused for the entire multi-round\n // tool loop. If interactables change during streaming (e.g. user interactions),\n // continuations will send stale context. Re-gather before each continuation\n // if freshness matters.\n const helperContexts = await getAdditionalContext();\n const additionalContext: Record<string, unknown> = {};\n for (const helperContext of helperContexts) {\n additionalContext[helperContext.name] = helperContext.context;\n }\n\n // Create the run stream\n const { stream, initialThreadId } = await createRunStream({\n client,\n threadId: apiThreadId,\n message,\n registry,\n userKey,\n previousRunId,\n additionalContext,\n });\n\n let actualThreadId = initialThreadId;\n let runId: string | undefined;\n let currentStream: CreateRunStreamResult[\"stream\"] = stream;\n\n try {\n // Outer loop handles stream replacement for multi-round tool execution.\n // When we hit awaiting_input, we execute tools, get a new stream, and continue.\n // This flat loop pattern correctly handles tool→AI→tool→AI chains.\n while (true) {\n let pendingAwaitingInput: RunAwaitingInputEvent | undefined;\n\n // Process current stream until completion or awaiting_input\n for await (const event of handleEventStream(currentStream, {\n debug,\n })) {\n // Extract threadId and runId from RUN_STARTED event\n if (event.type === EventType.RUN_STARTED) {\n runId = event.runId;\n actualThreadId ??= event.threadId;\n\n // For threads with no ID at all: add user message now that we have the real threadId\n // Note: temp thread migration (temp_xxx -> real ID) is handled automatically\n // by the reducer when it sees RUN_STARTED with a different threadId\n if (!threadId && userMessageText && userMessageId) {\n dispatchUserMessage(\n dispatch,\n actualThreadId,\n userMessageId,\n userMessageText,\n );\n }\n } else if (!actualThreadId) {\n throw new Error(\n `Expected first event to be RUN_STARTED with threadId, got: ${event.type}`,\n );\n }\n\n toolTracker.handleEvent(event);\n dispatch({ type: \"EVENT\", event, threadId: actualThreadId });\n\n // Check for awaiting_input - if found, break to execute tools\n if (event.type === EventType.CUSTOM) {\n const customEvent = asTamboCustomEvent(event);\n if (customEvent?.name === \"tambo.run.awaiting_input\") {\n pendingAwaitingInput = customEvent;\n break; // Exit stream loop to handle tool execution\n }\n }\n }\n\n // If stream finished without awaiting_input, we're done\n if (!pendingAwaitingInput) {\n break;\n }\n\n // Execute tools and get continuation stream\n // These checks should never fail since awaiting_input comes after RUN_STARTED\n if (!runId || !actualThreadId) {\n throw new Error(\n \"Cannot continue run after awaiting_input: missing runId or threadId\",\n );\n }\n\n const { stream: continuationStream, toolResults } =\n await executeToolsAndContinue({\n event: pendingAwaitingInput,\n toolTracker,\n registry,\n client,\n threadId: actualThreadId,\n runId,\n userKey,\n additionalContext,\n });\n\n dispatchToolResults(dispatch, actualThreadId, toolResults);\n\n currentStream = continuationStream;\n }\n\n return {\n threadId: actualThreadId,\n preMutationMessageCount,\n threadAlreadyHasTitle,\n };\n } catch (error) {\n // Dispatch a synthetic RUN_ERROR event to clean up thread state\n // This ensures the thread doesn't stay stuck in \"streaming\" status\n if (actualThreadId) {\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown streaming error\";\n const errorEvent: RunErrorEvent = {\n type: EventType.RUN_ERROR,\n message: errorMessage,\n };\n dispatch({\n type: \"EVENT\",\n event: errorEvent,\n threadId: actualThreadId,\n });\n }\n throw error;\n }\n },\n onSuccess: async (result) => {\n await queryClient.invalidateQueries({\n queryKey: [\"v1-threads\", result.threadId],\n });\n\n if (\n autoGenerateThreadName &&\n shouldGenerateThreadName(\n result.threadId,\n result.threadAlreadyHasTitle,\n result.preMutationMessageCount,\n autoGenerateNameThreshold,\n )\n ) {\n await generateThreadName(\n client,\n dispatch,\n queryClient,\n result.threadId,\n );\n }\n },\n onError: (error) => {\n console.error(\"[useTamboV1SendMessage] Mutation failed:\", error);\n },\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-tambo-v1-send-message.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-send-message.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * Send Message Hook for v1 API\n *\n * React Query mutation hook for sending messages and handling streaming responses.\n */\n\nimport React, { useContext } from \"react\";\nimport { EventType, type RunErrorEvent } from \"@ag-ui/core\";\nimport { asTamboCustomEvent, type RunAwaitingInputEvent } from \"../types/event\";\nimport type TamboAI from \"@tambo-ai/typescript-sdk\";\nimport type { Stream } from \"@tambo-ai/typescript-sdk/core/streaming\";\nimport {\n useTamboClient,\n useTamboQueryClient,\n} from \"../../providers/tambo-client-provider\";\nimport { useTamboMutation } from \"../../hooks/react-query-hooks\";\nimport {\n TamboRegistryContext,\n type TamboRegistryContext as TamboRegistry,\n} from \"../../providers/tambo-registry-provider\";\nimport {\n useStreamDispatch,\n useStreamState,\n} from \"../providers/tambo-v1-stream-context\";\nimport { useTamboV1Config } from \"../providers/tambo-v1-provider\";\nimport { useTamboV1AuthState } from \"./use-tambo-v1-auth-state\";\nimport { useTamboContextHelpers } from \"../../providers/tambo-context-helpers-provider\";\nimport type { InitialInputMessage, InputMessage } from \"../types/message\";\nimport type { ToolChoice } from \"../types/tool-choice\";\nimport {\n isPlaceholderThreadId,\n type StreamAction,\n} from \"../utils/event-accumulator\";\nimport {\n toAvailableComponents,\n toAvailableTools,\n} from \"../utils/registry-conversion\";\nimport { handleEventStream } from \"../utils/stream-handler\";\nimport {\n executeAllPendingTools,\n createThrottledStreamableExecutor,\n} from \"../utils/tool-executor\";\nimport type { ToolResultContent } from \"@tambo-ai/typescript-sdk/resources/threads/threads\";\nimport { ToolCallTracker } from \"../utils/tool-call-tracker\";\nimport { parse as parsePartialJson } from \"partial-json\";\n\n/**\n * Dispatches synthetic AG-UI events to show a user message in the thread.\n * @param dispatch - Stream state dispatcher\n * @param targetThreadId - Thread to add the message to\n * @param messageId - Stable ID for the user message\n * @param messageText - Text content of the message\n */\nfunction dispatchUserMessage(\n dispatch: React.Dispatch<StreamAction>,\n targetThreadId: string,\n messageId: string,\n messageText: string,\n): void {\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId,\n role: \"user\" as const,\n },\n });\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId,\n delta: messageText,\n },\n });\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId,\n },\n });\n}\n\n/**\n * Dispatches synthetic events for tool results as optimistic local state.\n * The server doesn't echo these back for client-side tools.\n * @param dispatch - Stream state dispatcher\n * @param targetThreadId - Thread to add results to\n * @param toolResults - Tool execution results to dispatch\n */\nfunction dispatchToolResults(\n dispatch: React.Dispatch<StreamAction>,\n targetThreadId: string,\n toolResults: ToolResultContent[],\n): void {\n if (toolResults.length === 0) return;\n\n const toolResultMessageId = `msg_tool_result_${Date.now()}`;\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: toolResultMessageId,\n role: \"user\" as const,\n },\n });\n\n for (const result of toolResults) {\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TOOL_CALL_RESULT,\n toolCallId: result.toolUseId,\n messageId: toolResultMessageId,\n content:\n result.content\n .filter((c) => c.type === \"text\")\n .map((c) => (c as { type: \"text\"; text: string }).text)\n .join(\"\") || JSON.stringify(result.content),\n },\n });\n }\n\n dispatch({\n type: \"EVENT\",\n threadId: targetThreadId,\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: toolResultMessageId,\n },\n });\n}\n\n/**\n * Checks whether a thread name should be auto-generated based on config\n * and the current thread state.\n * @param threadId - The thread ID (undefined or placeholder means no)\n * @param threadAlreadyHasTitle - Whether the thread already has a title\n * @param preMutationMessageCount - Message count before the current mutation\n * @param autoGenerateNameThreshold - Minimum message count to trigger generation\n * @returns Whether to generate a thread name\n */\nfunction shouldGenerateThreadName(\n threadId: string | undefined,\n threadAlreadyHasTitle: boolean,\n preMutationMessageCount: number,\n autoGenerateNameThreshold: number,\n): threadId is string {\n return (\n !threadAlreadyHasTitle &&\n !!threadId &&\n !isPlaceholderThreadId(threadId) &&\n // +2 accounts for the user message and assistant response just added\n preMutationMessageCount + 2 >= autoGenerateNameThreshold\n );\n}\n\n/**\n * Attempts to parse partial JSON from accumulated tool call args.\n *\n * Returns a parsed object if the accumulated args are parseable as\n * a JSON object, or undefined if parsing fails or the result is not\n * a plain object (e.g. array or primitive).\n * @param toolTracker - Tracker holding pending tool call state\n * @param toolCallId - The tool call ID to parse args for\n * @returns Parsed args object, or undefined if not parseable yet\n */\nfunction parseToolCallArgs(\n toolTracker: ToolCallTracker,\n toolCallId: string,\n): Record<string, unknown> | undefined {\n const accToolCall = toolTracker.getAccumulatingToolCall(toolCallId);\n if (!accToolCall) return undefined;\n\n try {\n const parsed: unknown = parsePartialJson(accToolCall.accumulatedArgs);\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n !Array.isArray(parsed)\n ) {\n return parsed as Record<string, unknown>;\n }\n } catch {\n /* not parseable yet */\n }\n return undefined;\n}\n\n/**\n * Generates a thread name via the beta API, dispatches the title update,\n * and invalidates the thread list cache. Errors are logged, never thrown.\n * @param client - The Tambo API client\n * @param dispatch - Stream state dispatcher\n * @param queryClient - React Query client for cache invalidation\n * @param threadId - The thread to generate a name for\n */\nasync function generateThreadName(\n client: TamboAI,\n dispatch: React.Dispatch<StreamAction>,\n queryClient: ReturnType<typeof useTamboQueryClient>,\n threadId: string,\n): Promise<void> {\n try {\n const threadWithName = await client.beta.threads.generateName(threadId);\n if (threadWithName.name) {\n dispatch({\n type: \"UPDATE_THREAD_TITLE\",\n threadId,\n title: threadWithName.name,\n });\n await queryClient.invalidateQueries({\n queryKey: [\"v1-threads\", \"list\"],\n });\n }\n } catch (error) {\n console.error(\n \"[useTamboV1SendMessage] Failed to auto-generate thread name:\",\n error,\n );\n }\n}\n\n/**\n * Options for sending a message\n */\nexport interface SendMessageOptions {\n /**\n * The message to send\n */\n message: InputMessage;\n\n /**\n * User message text for optimistic display.\n * If provided, synthetic AG-UI events will be dispatched to show\n * the user message in the thread immediately after getting the threadId.\n */\n userMessageText?: string;\n\n /**\n * Enable debug logging for the stream\n */\n debug?: boolean;\n\n /**\n * How the model should use tools. Defaults to \"auto\".\n * - \"auto\": Model decides whether to use tools\n * - \"required\": Model must use at least one tool\n * - \"none\": Model cannot use tools\n * - { name: \"toolName\" }: Model must use the specified tool\n */\n toolChoice?: ToolChoice;\n}\n\n/**\n * Parameters for creating a run stream\n */\nexport interface CreateRunStreamParams {\n client: TamboAI;\n threadId: string | undefined;\n message: InputMessage;\n registry: TamboRegistry;\n userKey: string | undefined;\n /**\n * Previous run ID for continuing a thread with existing messages.\n * Required when threadId is provided and the thread has previous runs.\n */\n previousRunId: string | undefined;\n /**\n * Additional context gathered from context helpers (including interactables).\n * Merged into the message's additionalContext before sending.\n */\n additionalContext?: Record<string, unknown>;\n /**\n * How the model should use tools.\n */\n toolChoice?: ToolChoice;\n /**\n * Initial messages to seed the thread with when creating a new thread.\n * Only used when threadId is undefined (new thread creation).\n */\n initialMessages?: InitialInputMessage[];\n}\n\n/**\n * Stream types from the SDK\n */\ntype RunStream = Stream<TamboAI.Threads.Runs.RunRunResponse>;\ntype CreateStream = Stream<TamboAI.Threads.Runs.RunCreateResponse>;\n\n/**\n * Result from creating a run stream\n */\nexport interface CreateRunStreamResult {\n stream: RunStream | CreateStream;\n initialThreadId: string | undefined;\n}\n\n/**\n * Parameters for executing tools and continuing the run\n */\ninterface ExecuteToolsParams {\n event: RunAwaitingInputEvent;\n toolTracker: ToolCallTracker;\n registry: TamboRegistry;\n client: TamboAI;\n threadId: string;\n runId: string;\n userKey: string | undefined;\n additionalContext?: Record<string, unknown>;\n toolChoice?: ToolChoice;\n}\n\n/**\n * Result from executing tools and continuing the run\n */\ninterface ExecuteToolsResult {\n stream: RunStream;\n toolResults: ToolResultContent[];\n}\n\n/**\n * Executes pending tools and returns a continuation stream.\n *\n * This function does NOT process the continuation stream - it just executes\n * the tools and returns the new stream for the caller to process. This enables\n * the flat loop pattern that correctly handles multi-round tool execution.\n * @param params - The parameters for tool execution\n * @returns The continuation stream and tool results for optimistic local state updates\n */\nasync function executeToolsAndContinue(\n params: ExecuteToolsParams,\n): Promise<ExecuteToolsResult> {\n const {\n event,\n toolTracker,\n registry,\n client,\n threadId,\n runId,\n userKey,\n additionalContext,\n toolChoice,\n } = params;\n\n const pendingToolCallIds = event.value.pendingToolCalls.map(\n (tc) => tc.toolCallId,\n );\n const toolCallsToExecute = toolTracker.getToolCallsById(pendingToolCallIds);\n\n // Execute tools\n const toolResults = await executeAllPendingTools(\n toolCallsToExecute,\n registry.toolRegistry,\n );\n\n // Clear executed tool calls before continuing\n toolTracker.clearToolCalls(pendingToolCallIds);\n\n // Return the continuation stream and tool results\n const stream = await client.threads.runs.run(threadId, {\n message: {\n role: \"user\",\n content: toolResults,\n additionalContext,\n },\n previousRunId: runId,\n availableComponents: toAvailableComponents(registry.componentList),\n tools: toAvailableTools(registry.toolRegistry),\n userKey,\n toolChoice,\n });\n\n return { stream, toolResults };\n}\n\n/**\n * Creates a run stream by calling the appropriate API method.\n *\n * If threadId is provided, runs on existing thread via client.threads.runs.run().\n * If no threadId, creates new thread via client.threads.runs.create().\n * @param params - The parameters for creating the run stream\n * @returns The stream and initial thread ID (undefined if creating new thread)\n */\nexport async function createRunStream(\n params: CreateRunStreamParams,\n): Promise<CreateRunStreamResult> {\n const {\n client,\n threadId,\n message,\n registry,\n userKey,\n previousRunId,\n additionalContext,\n toolChoice,\n initialMessages,\n } = params;\n\n // Merge helper context with any caller-provided additionalContext on the message\n const mergedContext =\n additionalContext || message.additionalContext\n ? {\n ...((message.additionalContext as Record<string, unknown>) ?? {}),\n ...additionalContext,\n }\n : undefined;\n const messageWithContext: InputMessage = mergedContext\n ? { ...message, additionalContext: mergedContext }\n : message;\n\n // Convert registry components/tools to v1 API format\n const availableComponents = toAvailableComponents(registry.componentList);\n const availableTools = toAvailableTools(registry.toolRegistry);\n\n if (threadId) {\n // Run on existing thread\n const stream = await client.threads.runs.run(threadId, {\n message: messageWithContext,\n availableComponents,\n tools: availableTools,\n userKey,\n previousRunId,\n toolChoice,\n });\n return { stream, initialThreadId: threadId };\n } else {\n // Create new thread - include initialMessages if provided\n // Cast to InputMessage[] at the SDK boundary: the V1 API accepts system/assistant roles\n // but the TS SDK type constrains role to 'user'. Remove cast when typescript-sdk is regenerated.\n const threadConfig: { userKey?: string; initialMessages?: InputMessage[] } =\n {};\n if (userKey) {\n threadConfig.userKey = userKey;\n }\n if (initialMessages?.length) {\n threadConfig.initialMessages = initialMessages as InputMessage[];\n }\n\n const stream = await client.threads.runs.create({\n message: messageWithContext,\n availableComponents,\n tools: availableTools,\n thread: Object.keys(threadConfig).length > 0 ? threadConfig : undefined,\n toolChoice,\n });\n // threadId will be extracted from first event (RUN_STARTED)\n return { stream, initialThreadId: undefined };\n }\n}\n\n/**\n * Hook to send a message and handle streaming responses.\n *\n * This hook handles two scenarios:\n * - If threadId provided: runs on existing thread via client.threads.runs.run()\n * - If no threadId: creates new thread via client.threads.runs.create()\n *\n * The hook:\n * - Sends a user message to the API\n * - Streams AG-UI events in real-time\n * - Dispatches events to the stream reducer\n * - Extracts threadId from events when creating new thread\n * - Handles tool execution (Phase 6)\n * - Invalidates thread queries on completion\n * @param threadId - Optional thread ID to send message to. If not provided, creates new thread\n * @returns React Query mutation object with threadId in mutation result\n * @example\n * ```tsx\n * function ChatInput({ threadId }: { threadId?: string }) {\n * const sendMessage = useTamboV1SendMessage(threadId);\n *\n * const handleSubmit = async (text: string) => {\n * const result = await sendMessage.mutateAsync({\n * message: {\n * role: \"user\",\n * content: [{ type: \"text\", text }],\n * },\n * });\n *\n * // If threadId wasn't provided, a new thread was created\n * if (!threadId) {\n * console.log(\"Created thread:\", result.threadId);\n * }\n * };\n *\n * return (\n * <div>\n * <input onSubmit={handleSubmit} />\n * {sendMessage.isPending && <Spinner />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useTamboV1SendMessage(threadId?: string) {\n const client = useTamboClient();\n const dispatch = useStreamDispatch();\n const streamState = useStreamState();\n const {\n userKey,\n autoGenerateThreadName = true,\n autoGenerateNameThreshold = 3,\n initialMessages,\n } = useTamboV1Config();\n const registry = useContext(TamboRegistryContext);\n const queryClient = useTamboQueryClient();\n const { getAdditionalContext } = useTamboContextHelpers();\n const authState = useTamboV1AuthState();\n\n if (!registry) {\n throw new Error(\n \"useTamboV1SendMessage must be used within TamboRegistryProvider\",\n );\n }\n\n // Placeholder ID isn't a valid API thread ID - treat as new thread creation\n const isNewThread = isPlaceholderThreadId(threadId);\n const apiThreadId = isNewThread ? undefined : threadId;\n\n // Get previousRunId from the thread's streaming state (active run) or\n // lastCompletedRunId (persisted after run finishes / loaded from API).\n // The latter is essential after page reload when streaming state is gone.\n const threadState = apiThreadId\n ? streamState.threadMap[apiThreadId]\n : undefined;\n const previousRunId =\n threadState?.streaming.runId ?? threadState?.lastCompletedRunId;\n\n return useTamboMutation({\n mutationFn: async (options: SendMessageOptions) => {\n if (authState.status !== \"identified\") {\n const messages: Record<string, string> = {\n unauthenticated:\n \"Cannot send message: no userKey or userToken provided. \" +\n \"Configure authentication in TamboV1Provider.\",\n exchanging:\n \"Cannot send message: token exchange is still in progress. \" +\n \"Wait for authentication to complete.\",\n error:\n \"Cannot send message: token exchange failed. \" +\n \"Check your userToken configuration.\",\n invalid:\n \"Cannot send message: both userKey and userToken were provided. \" +\n \"You must provide one or the other, not both.\",\n };\n throw new Error(messages[authState.status]);\n }\n\n const { message, userMessageText, debug = false, toolChoice } = options;\n\n // Capture pre-mutation state for auto thread name generation\n const existingThread = streamState.threadMap[apiThreadId ?? \"\"];\n const preMutationMessageCount =\n existingThread?.thread.messages.length ?? 0;\n const threadAlreadyHasTitle = !!existingThread?.thread.title;\n\n const toolTracker = new ToolCallTracker();\n const throttledStreamable = createThrottledStreamableExecutor(\n toolTracker,\n registry.toolRegistry,\n );\n\n // Generate a stable message ID for the user message\n const userMessageId = userMessageText\n ? `user_msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`\n : undefined;\n\n // Add user message immediately for instant feedback\n // Use threadId (which could be temp_xxx for new threads) for display\n if (threadId && userMessageText && userMessageId) {\n dispatchUserMessage(dispatch, threadId, userMessageId, userMessageText);\n }\n\n // Gather additional context from all registered context helpers.\n // TODO: This snapshot is captured once and reused for the entire multi-round\n // tool loop. If interactables change during streaming (e.g. user interactions),\n // continuations will send stale context. Re-gather before each continuation\n // if freshness matters.\n const helperContexts = await getAdditionalContext();\n const additionalContext: Record<string, unknown> = {};\n for (const helperContext of helperContexts) {\n additionalContext[helperContext.name] = helperContext.context;\n }\n\n // Create the run stream\n // Include initialMessages only on first send (new thread creation)\n const { stream, initialThreadId } = await createRunStream({\n client,\n threadId: apiThreadId,\n message,\n registry,\n userKey,\n previousRunId,\n additionalContext,\n toolChoice,\n initialMessages: isNewThread ? initialMessages : undefined,\n });\n\n let actualThreadId = initialThreadId;\n let runId: string | undefined;\n let currentStream: CreateRunStreamResult[\"stream\"] = stream;\n\n try {\n // Outer loop handles stream replacement for multi-round tool execution.\n // When we hit awaiting_input, we execute tools, get a new stream, and continue.\n // This flat loop pattern correctly handles tool→AI→tool→AI chains.\n while (true) {\n let pendingAwaitingInput: RunAwaitingInputEvent | undefined;\n\n // Process current stream until completion or awaiting_input\n for await (const event of handleEventStream(currentStream, {\n debug,\n })) {\n // Extract threadId and runId from RUN_STARTED event\n if (event.type === EventType.RUN_STARTED) {\n runId = event.runId;\n actualThreadId ??= event.threadId;\n\n // For threads with no ID at all: add user message now that we have the real threadId\n // Note: temp thread migration (temp_xxx -> real ID) is handled automatically\n // by the reducer when it sees RUN_STARTED with a different threadId\n if (!threadId && userMessageText && userMessageId) {\n dispatchUserMessage(\n dispatch,\n actualThreadId,\n userMessageId,\n userMessageText,\n );\n }\n } else if (!actualThreadId) {\n throw new Error(\n `Expected first event to be RUN_STARTED with threadId, got: ${event.type}`,\n );\n }\n\n toolTracker.handleEvent(event);\n\n // Parse partial JSON once for TOOL_CALL_ARGS — reused by both dispatch and streamable execution\n const parsedToolArgs =\n event.type === EventType.TOOL_CALL_ARGS\n ? parseToolCallArgs(toolTracker, event.toolCallId)\n : undefined;\n\n dispatch({\n type: \"EVENT\",\n event,\n threadId: actualThreadId,\n parsedToolArgs,\n });\n\n // Schedule debounced streamable tool execution with the same pre-parsed args\n if (parsedToolArgs && event.type === EventType.TOOL_CALL_ARGS) {\n throttledStreamable.schedule(event.toolCallId, parsedToolArgs);\n }\n\n // Check for awaiting_input - if found, break to execute tools\n if (event.type === EventType.CUSTOM) {\n const customEvent = asTamboCustomEvent(event);\n if (customEvent?.name === \"tambo.run.awaiting_input\") {\n pendingAwaitingInput = customEvent;\n break; // Exit stream loop to handle tool execution\n }\n }\n }\n\n // Flush any pending debounced streamable calls before continuing\n throttledStreamable.flush();\n\n // If stream finished without awaiting_input, we're done\n if (!pendingAwaitingInput) {\n break;\n }\n\n // Execute tools and get continuation stream\n // These checks should never fail since awaiting_input comes after RUN_STARTED\n if (!runId || !actualThreadId) {\n throw new Error(\n \"Cannot continue run after awaiting_input: missing runId or threadId\",\n );\n }\n\n const { stream: continuationStream, toolResults } =\n await executeToolsAndContinue({\n event: pendingAwaitingInput,\n toolTracker,\n registry,\n client,\n threadId: actualThreadId,\n runId,\n userKey,\n additionalContext,\n toolChoice,\n });\n\n dispatchToolResults(dispatch, actualThreadId, toolResults);\n\n currentStream = continuationStream;\n }\n\n return {\n threadId: actualThreadId,\n preMutationMessageCount,\n threadAlreadyHasTitle,\n };\n } catch (error) {\n // Dispatch a synthetic RUN_ERROR event to clean up thread state\n // This ensures the thread doesn't stay stuck in \"streaming\" status\n if (actualThreadId) {\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown streaming error\";\n const errorEvent: RunErrorEvent = {\n type: EventType.RUN_ERROR,\n message: errorMessage,\n };\n dispatch({\n type: \"EVENT\",\n event: errorEvent,\n threadId: actualThreadId,\n });\n }\n throw error;\n }\n },\n onSuccess: async (result) => {\n await queryClient.invalidateQueries({\n queryKey: [\"v1-threads\", result.threadId],\n });\n\n if (\n autoGenerateThreadName &&\n shouldGenerateThreadName(\n result.threadId,\n result.threadAlreadyHasTitle,\n result.preMutationMessageCount,\n autoGenerateNameThreshold,\n )\n ) {\n await generateThreadName(\n client,\n dispatch,\n queryClient,\n result.threadId,\n );\n }\n },\n onError: (error) => {\n console.error(\"[useTamboV1SendMessage] Mutation failed:\", error);\n },\n });\n}\n"]}
|
|
@@ -15,6 +15,12 @@ jest.mock("../../providers/tambo-client-provider", () => ({
|
|
|
15
15
|
jest.mock("../providers/tambo-v1-provider", () => ({
|
|
16
16
|
useTamboV1Config: jest.fn(),
|
|
17
17
|
}));
|
|
18
|
+
jest.mock("./use-tambo-v1-auth-state", () => ({
|
|
19
|
+
useTamboV1AuthState: () => ({
|
|
20
|
+
status: "identified",
|
|
21
|
+
source: "userKey",
|
|
22
|
+
}),
|
|
23
|
+
}));
|
|
18
24
|
jest.mock("../../providers/tambo-context-helpers-provider", () => ({
|
|
19
25
|
useTamboContextHelpers: () => ({
|
|
20
26
|
getAdditionalContext: jest.fn().mockResolvedValue([]),
|
|
@@ -860,6 +866,67 @@ describe("useTamboV1SendMessage mutation", () => {
|
|
|
860
866
|
content: [{ type: "text", text: "result from tool 2" }],
|
|
861
867
|
});
|
|
862
868
|
});
|
|
869
|
+
it("uses lastCompletedRunId as previousRunId when streaming.runId is absent", async () => {
|
|
870
|
+
const mockStream = createAsyncIterator([
|
|
871
|
+
{
|
|
872
|
+
type: EventType.RUN_STARTED,
|
|
873
|
+
runId: "run_2",
|
|
874
|
+
threadId: "thread_123",
|
|
875
|
+
},
|
|
876
|
+
{ type: EventType.RUN_FINISHED },
|
|
877
|
+
]);
|
|
878
|
+
mockThreadsRunsApi.run.mockResolvedValue(mockStream);
|
|
879
|
+
const mockRegistry = {
|
|
880
|
+
componentList: new Map(),
|
|
881
|
+
toolRegistry: new Map(),
|
|
882
|
+
};
|
|
883
|
+
// Provide stream state with lastCompletedRunId but no active streaming.runId
|
|
884
|
+
const stateWithLastRun = {
|
|
885
|
+
currentThreadId: "thread_123",
|
|
886
|
+
threadMap: {
|
|
887
|
+
thread_123: {
|
|
888
|
+
thread: {
|
|
889
|
+
id: "thread_123",
|
|
890
|
+
messages: [
|
|
891
|
+
{
|
|
892
|
+
id: "msg_1",
|
|
893
|
+
role: "user",
|
|
894
|
+
content: [{ type: "text", text: "Hello" }],
|
|
895
|
+
createdAt: "2024-01-01T00:00:00.000Z",
|
|
896
|
+
},
|
|
897
|
+
],
|
|
898
|
+
status: "idle",
|
|
899
|
+
createdAt: "2024-01-01T00:00:00.000Z",
|
|
900
|
+
updatedAt: "2024-01-01T00:00:00.000Z",
|
|
901
|
+
lastRunCancelled: false,
|
|
902
|
+
},
|
|
903
|
+
streaming: { status: "idle" },
|
|
904
|
+
accumulatingToolArgs: new Map(),
|
|
905
|
+
lastCompletedRunId: "run_1",
|
|
906
|
+
},
|
|
907
|
+
},
|
|
908
|
+
};
|
|
909
|
+
function TestWrapper({ children }) {
|
|
910
|
+
return (React.createElement(QueryClientProvider, { client: queryClient },
|
|
911
|
+
React.createElement(TamboRegistryContext.Provider, { value: mockRegistry },
|
|
912
|
+
React.createElement(TamboV1StreamProvider, { state: stateWithLastRun, dispatch: jest.fn() }, children))));
|
|
913
|
+
}
|
|
914
|
+
const { result } = renderHook(() => useTamboV1SendMessage("thread_123"), {
|
|
915
|
+
wrapper: TestWrapper,
|
|
916
|
+
});
|
|
917
|
+
await act(async () => {
|
|
918
|
+
await result.current.mutateAsync({
|
|
919
|
+
message: {
|
|
920
|
+
role: "user",
|
|
921
|
+
content: [{ type: "text", text: "Follow-up" }],
|
|
922
|
+
},
|
|
923
|
+
});
|
|
924
|
+
});
|
|
925
|
+
// Should have used lastCompletedRunId as previousRunId
|
|
926
|
+
expect(mockThreadsRunsApi.run).toHaveBeenCalledWith("thread_123", expect.objectContaining({
|
|
927
|
+
previousRunId: "run_1",
|
|
928
|
+
}));
|
|
929
|
+
});
|
|
863
930
|
it("logs error on mutation failure", async () => {
|
|
864
931
|
const consoleSpy = jest
|
|
865
932
|
.spyOn(console, "error")
|
|
@@ -1086,4 +1153,210 @@ describe("useTamboV1SendMessage auto thread name generation", () => {
|
|
|
1086
1153
|
expect(mockGenerateName).not.toHaveBeenCalled();
|
|
1087
1154
|
});
|
|
1088
1155
|
});
|
|
1156
|
+
describe("useTamboV1SendMessage tamboStreamableHint", () => {
|
|
1157
|
+
const mockThreadsRunsApi = {
|
|
1158
|
+
run: jest.fn(),
|
|
1159
|
+
create: jest.fn(),
|
|
1160
|
+
};
|
|
1161
|
+
const mockTamboAI = {
|
|
1162
|
+
apiKey: "",
|
|
1163
|
+
threads: {
|
|
1164
|
+
runs: mockThreadsRunsApi,
|
|
1165
|
+
},
|
|
1166
|
+
};
|
|
1167
|
+
let queryClient;
|
|
1168
|
+
function createAsyncIterator(events) {
|
|
1169
|
+
return {
|
|
1170
|
+
[Symbol.asyncIterator]: async function* () {
|
|
1171
|
+
for (const event of events) {
|
|
1172
|
+
yield event;
|
|
1173
|
+
}
|
|
1174
|
+
},
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
beforeEach(() => {
|
|
1178
|
+
queryClient = new QueryClient({
|
|
1179
|
+
defaultOptions: {
|
|
1180
|
+
queries: { retry: false },
|
|
1181
|
+
mutations: { retry: false },
|
|
1182
|
+
},
|
|
1183
|
+
});
|
|
1184
|
+
jest.mocked(useTamboClient).mockReturnValue(mockTamboAI);
|
|
1185
|
+
jest.mocked(useTamboQueryClient).mockReturnValue(queryClient);
|
|
1186
|
+
jest.mocked(useTamboV1Config).mockReturnValue({ userKey: undefined });
|
|
1187
|
+
mockThreadsRunsApi.run.mockReset();
|
|
1188
|
+
mockThreadsRunsApi.create.mockReset();
|
|
1189
|
+
});
|
|
1190
|
+
it("calls streamable tool on TOOL_CALL_ARGS events during streaming", async () => {
|
|
1191
|
+
const streamableToolFn = jest.fn().mockResolvedValue(undefined);
|
|
1192
|
+
const streamableTool = {
|
|
1193
|
+
name: "write_story",
|
|
1194
|
+
description: "Writes a story",
|
|
1195
|
+
tool: streamableToolFn,
|
|
1196
|
+
inputSchema: z.object({ text: z.string() }),
|
|
1197
|
+
outputSchema: z.void(),
|
|
1198
|
+
annotations: { tamboStreamableHint: true },
|
|
1199
|
+
};
|
|
1200
|
+
// Use Record (not Map) for toolRegistry — matches real runtime type
|
|
1201
|
+
const mockRegistry = {
|
|
1202
|
+
componentList: new Map(),
|
|
1203
|
+
toolRegistry: { write_story: streamableTool },
|
|
1204
|
+
};
|
|
1205
|
+
const initialStream = createAsyncIterator([
|
|
1206
|
+
{
|
|
1207
|
+
type: EventType.RUN_STARTED,
|
|
1208
|
+
runId: "run_1",
|
|
1209
|
+
threadId: "thread_123",
|
|
1210
|
+
},
|
|
1211
|
+
{
|
|
1212
|
+
type: EventType.TEXT_MESSAGE_START,
|
|
1213
|
+
messageId: "msg_1",
|
|
1214
|
+
role: "assistant",
|
|
1215
|
+
},
|
|
1216
|
+
{
|
|
1217
|
+
type: EventType.TOOL_CALL_START,
|
|
1218
|
+
toolCallId: "call_1",
|
|
1219
|
+
toolCallName: "write_story",
|
|
1220
|
+
parentMessageId: "msg_1",
|
|
1221
|
+
},
|
|
1222
|
+
{
|
|
1223
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
1224
|
+
toolCallId: "call_1",
|
|
1225
|
+
delta: '{"text":"Once upon',
|
|
1226
|
+
},
|
|
1227
|
+
{
|
|
1228
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
1229
|
+
toolCallId: "call_1",
|
|
1230
|
+
delta: ' a time"}',
|
|
1231
|
+
},
|
|
1232
|
+
{
|
|
1233
|
+
type: EventType.TOOL_CALL_END,
|
|
1234
|
+
toolCallId: "call_1",
|
|
1235
|
+
},
|
|
1236
|
+
{
|
|
1237
|
+
type: EventType.CUSTOM,
|
|
1238
|
+
name: "tambo.run.awaiting_input",
|
|
1239
|
+
value: {
|
|
1240
|
+
pendingToolCalls: [
|
|
1241
|
+
{ toolCallId: "call_1", toolName: "write_story", arguments: "{}" },
|
|
1242
|
+
],
|
|
1243
|
+
},
|
|
1244
|
+
},
|
|
1245
|
+
]);
|
|
1246
|
+
const continueStream = createAsyncIterator([
|
|
1247
|
+
{
|
|
1248
|
+
type: EventType.RUN_STARTED,
|
|
1249
|
+
runId: "run_2",
|
|
1250
|
+
threadId: "thread_123",
|
|
1251
|
+
},
|
|
1252
|
+
{ type: EventType.RUN_FINISHED },
|
|
1253
|
+
]);
|
|
1254
|
+
mockThreadsRunsApi.run
|
|
1255
|
+
.mockResolvedValueOnce(initialStream)
|
|
1256
|
+
.mockResolvedValueOnce(continueStream);
|
|
1257
|
+
function TestWrapper({ children }) {
|
|
1258
|
+
return (React.createElement(QueryClientProvider, { client: queryClient },
|
|
1259
|
+
React.createElement(TamboRegistryContext.Provider, { value: mockRegistry },
|
|
1260
|
+
React.createElement(TamboV1StreamProvider, null, children))));
|
|
1261
|
+
}
|
|
1262
|
+
const { result } = renderHook(() => useTamboV1SendMessage("thread_123"), {
|
|
1263
|
+
wrapper: TestWrapper,
|
|
1264
|
+
});
|
|
1265
|
+
await act(async () => {
|
|
1266
|
+
await result.current.mutateAsync({
|
|
1267
|
+
message: {
|
|
1268
|
+
role: "user",
|
|
1269
|
+
content: [{ type: "text", text: "Write me a story" }],
|
|
1270
|
+
},
|
|
1271
|
+
});
|
|
1272
|
+
});
|
|
1273
|
+
// Streamable tool should have been called during TOOL_CALL_ARGS events
|
|
1274
|
+
// (at least once per parseable chunk)
|
|
1275
|
+
expect(streamableToolFn.mock.calls.length).toBeGreaterThanOrEqual(1);
|
|
1276
|
+
// Each streaming call should have had partial args
|
|
1277
|
+
const firstStreamingCall = streamableToolFn.mock.calls[0][0];
|
|
1278
|
+
expect(firstStreamingCall).toHaveProperty("text");
|
|
1279
|
+
});
|
|
1280
|
+
it("does NOT call non-streamable tool during TOOL_CALL_ARGS events", async () => {
|
|
1281
|
+
const normalToolFn = jest.fn().mockResolvedValue("result");
|
|
1282
|
+
const normalTool = {
|
|
1283
|
+
name: "normal_tool",
|
|
1284
|
+
description: "Normal tool (not streamable)",
|
|
1285
|
+
tool: normalToolFn,
|
|
1286
|
+
inputSchema: z.object({ query: z.string() }),
|
|
1287
|
+
outputSchema: z.string(),
|
|
1288
|
+
// No tamboStreamableHint
|
|
1289
|
+
};
|
|
1290
|
+
const mockRegistry = {
|
|
1291
|
+
componentList: new Map(),
|
|
1292
|
+
toolRegistry: { normal_tool: normalTool },
|
|
1293
|
+
};
|
|
1294
|
+
const initialStream = createAsyncIterator([
|
|
1295
|
+
{
|
|
1296
|
+
type: EventType.RUN_STARTED,
|
|
1297
|
+
runId: "run_1",
|
|
1298
|
+
threadId: "thread_123",
|
|
1299
|
+
},
|
|
1300
|
+
{
|
|
1301
|
+
type: EventType.TEXT_MESSAGE_START,
|
|
1302
|
+
messageId: "msg_1",
|
|
1303
|
+
role: "assistant",
|
|
1304
|
+
},
|
|
1305
|
+
{
|
|
1306
|
+
type: EventType.TOOL_CALL_START,
|
|
1307
|
+
toolCallId: "call_1",
|
|
1308
|
+
toolCallName: "normal_tool",
|
|
1309
|
+
parentMessageId: "msg_1",
|
|
1310
|
+
},
|
|
1311
|
+
{
|
|
1312
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
1313
|
+
toolCallId: "call_1",
|
|
1314
|
+
delta: '{"query":"test"}',
|
|
1315
|
+
},
|
|
1316
|
+
{
|
|
1317
|
+
type: EventType.TOOL_CALL_END,
|
|
1318
|
+
toolCallId: "call_1",
|
|
1319
|
+
},
|
|
1320
|
+
{
|
|
1321
|
+
type: EventType.CUSTOM,
|
|
1322
|
+
name: "tambo.run.awaiting_input",
|
|
1323
|
+
value: {
|
|
1324
|
+
pendingToolCalls: [
|
|
1325
|
+
{ toolCallId: "call_1", toolName: "normal_tool", arguments: "{}" },
|
|
1326
|
+
],
|
|
1327
|
+
},
|
|
1328
|
+
},
|
|
1329
|
+
]);
|
|
1330
|
+
const continueStream = createAsyncIterator([
|
|
1331
|
+
{
|
|
1332
|
+
type: EventType.RUN_STARTED,
|
|
1333
|
+
runId: "run_2",
|
|
1334
|
+
threadId: "thread_123",
|
|
1335
|
+
},
|
|
1336
|
+
{ type: EventType.RUN_FINISHED },
|
|
1337
|
+
]);
|
|
1338
|
+
mockThreadsRunsApi.run
|
|
1339
|
+
.mockResolvedValueOnce(initialStream)
|
|
1340
|
+
.mockResolvedValueOnce(continueStream);
|
|
1341
|
+
function TestWrapper({ children }) {
|
|
1342
|
+
return (React.createElement(QueryClientProvider, { client: queryClient },
|
|
1343
|
+
React.createElement(TamboRegistryContext.Provider, { value: mockRegistry },
|
|
1344
|
+
React.createElement(TamboV1StreamProvider, null, children))));
|
|
1345
|
+
}
|
|
1346
|
+
const { result } = renderHook(() => useTamboV1SendMessage("thread_123"), {
|
|
1347
|
+
wrapper: TestWrapper,
|
|
1348
|
+
});
|
|
1349
|
+
await act(async () => {
|
|
1350
|
+
await result.current.mutateAsync({
|
|
1351
|
+
message: {
|
|
1352
|
+
role: "user",
|
|
1353
|
+
content: [{ type: "text", text: "Test" }],
|
|
1354
|
+
},
|
|
1355
|
+
});
|
|
1356
|
+
});
|
|
1357
|
+
// Tool should only be called once at awaiting_input, not during streaming
|
|
1358
|
+
expect(normalToolFn).toHaveBeenCalledTimes(1);
|
|
1359
|
+
expect(normalToolFn).toHaveBeenCalledWith({ query: "test" });
|
|
1360
|
+
});
|
|
1361
|
+
});
|
|
1089
1362
|
//# sourceMappingURL=use-tambo-v1-send-message.test.js.map
|