@tambo-ai/react 0.75.0 → 1.0.0-rc.4
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/dist/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/dist/hoc/with-tambo-interactable.js +13 -13
- package/dist/hoc/with-tambo-interactable.js.map +1 -1
- package/dist/hoc/with-tambo-interactable.test.js +3 -3
- package/dist/hoc/with-tambo-interactable.test.js.map +1 -1
- package/dist/index.d.ts +7 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -59
- package/dist/index.js.map +1 -1
- package/dist/mcp/mcp-hooks.js +5 -5
- package/dist/mcp/mcp-hooks.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/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 -2
- package/dist/providers/tambo-client-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts +1 -1
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js +2 -10
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/dist/providers/tambo-interactables-additional-context.test.js +3 -19
- package/dist/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/dist/providers/tambo-mcp-token-provider.d.ts +8 -17
- package/dist/providers/tambo-mcp-token-provider.d.ts.map +1 -1
- package/dist/providers/tambo-mcp-token-provider.js +20 -97
- package/dist/providers/tambo-mcp-token-provider.js.map +1 -1
- package/dist/testing/tools.d.ts +3 -3
- package/dist/testing/tools.d.ts.map +1 -1
- package/dist/testing/tools.js.map +1 -1
- package/dist/util/registry-validators.js +1 -1
- package/dist/util/registry-validators.js.map +1 -1
- package/dist/v1/__tests__/v1-interactables.test.js +1 -1
- package/dist/v1/__tests__/v1-interactables.test.js.map +1 -1
- package/dist/v1/components/v1-component-renderer.d.ts +9 -9
- package/dist/v1/components/v1-component-renderer.d.ts.map +1 -1
- package/dist/v1/components/v1-component-renderer.js +13 -13
- package/dist/v1/components/v1-component-renderer.js.map +1 -1
- package/dist/v1/components/v1-component-renderer.test.js +15 -15
- package/dist/v1/components/v1-component-renderer.test.js.map +1 -1
- package/{esm/hooks/use-current-message.d.ts → dist/v1/hooks/use-tambo-current-message.d.ts} +30 -9
- package/dist/v1/hooks/use-tambo-current-message.d.ts.map +1 -0
- package/dist/{hooks/use-current-message.js → v1/hooks/use-tambo-current-message.js} +13 -8
- package/dist/v1/hooks/use-tambo-current-message.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.d.ts +5 -5
- package/dist/v1/hooks/use-tambo-v1-auth-state.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-auth-state.js +8 -8
- package/dist/v1/hooks/use-tambo-v1-auth-state.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.js +12 -12
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.d.ts +7 -6
- package/dist/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.js +50 -24
- package/dist/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.test.js +60 -35
- package/dist/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.d.ts +9 -9
- package/dist/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.js +4 -4
- package/dist/v1/hooks/use-tambo-v1-messages.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.test.js +7 -7
- package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +3 -3
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.js +20 -22
- package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js +51 -51
- 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 +5 -5
- package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.js +12 -14
- package/dist/v1/hooks/use-tambo-v1-stream-status.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.js +19 -19
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts +7 -7
- package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-suggestions.js +9 -9
- package/dist/v1/hooks/use-tambo-v1-suggestions.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-suggestions.test.js +44 -44
- package/dist/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts +3 -3
- package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.js +4 -4
- package/dist/v1/hooks/use-tambo-v1-thread-input.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +29 -29
- 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 +4 -4
- package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.js +5 -5
- package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +13 -17
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.d.ts +3 -3
- package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.js +4 -4
- package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.test.js +5 -5
- package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.d.ts +16 -7
- package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.js +41 -10
- package/dist/v1/hooks/use-tambo-v1.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.test.js +176 -48
- package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/dist/v1/index.d.ts +31 -27
- package/dist/v1/index.d.ts.map +1 -1
- package/dist/v1/index.js +45 -35
- package/dist/v1/index.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.d.ts +20 -20
- package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.js +32 -32
- package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.test.js +22 -22
- package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.d.ts +15 -15
- package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.js +17 -17
- package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.test.js +9 -9
- package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.d.ts +9 -9
- package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.js +7 -7
- package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.test.js +25 -25
- package/dist/v1/providers/tambo-v1-stub-provider.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +9 -9
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.js +16 -16
- package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
- package/dist/v1/types/auth.d.ts +2 -2
- package/dist/v1/types/auth.d.ts.map +1 -1
- package/dist/v1/types/auth.js.map +1 -1
- package/dist/v1/types/component.d.ts +3 -3
- package/dist/v1/types/component.d.ts.map +1 -1
- package/dist/v1/types/component.js +2 -2
- package/dist/v1/types/component.js.map +1 -1
- package/dist/v1/types/event.d.ts +1 -1
- package/dist/v1/types/event.js +1 -1
- package/dist/v1/types/event.js.map +1 -1
- package/dist/v1/types/message.d.ts +17 -24
- package/dist/v1/types/message.d.ts.map +1 -1
- package/dist/v1/types/message.js +1 -1
- package/dist/v1/types/message.js.map +1 -1
- package/dist/v1/types/thread.d.ts +10 -8
- package/dist/v1/types/thread.d.ts.map +1 -1
- package/dist/v1/types/thread.js +1 -1
- package/dist/v1/types/thread.js.map +1 -1
- package/dist/v1/types/tool-choice.d.ts +1 -1
- package/dist/v1/types/tool-choice.js.map +1 -1
- package/dist/v1/utils/component-renderer.d.ts +11 -5
- package/dist/v1/utils/component-renderer.d.ts.map +1 -1
- package/dist/v1/utils/component-renderer.js +16 -7
- package/dist/v1/utils/component-renderer.js.map +1 -1
- package/dist/v1/utils/component-renderer.test.js +7 -7
- package/dist/v1/utils/component-renderer.test.js.map +1 -1
- package/dist/v1/utils/event-accumulator.d.ts +13 -13
- package/dist/v1/utils/event-accumulator.d.ts.map +1 -1
- package/dist/v1/utils/event-accumulator.js +26 -15
- package/dist/v1/utils/event-accumulator.js.map +1 -1
- package/dist/v1/utils/event-accumulator.test.js +54 -19
- package/dist/v1/utils/event-accumulator.test.js.map +1 -1
- package/dist/v1/utils/registry-conversion.d.ts +18 -18
- package/dist/v1/utils/registry-conversion.js +23 -23
- package/dist/v1/utils/registry-conversion.js.map +1 -1
- package/dist/v1/utils/stream-handler.d.ts +1 -1
- package/dist/v1/utils/stream-handler.js +1 -1
- package/dist/v1/utils/stream-handler.js.map +1 -1
- package/dist/v1/utils/thread-utils.d.ts +2 -2
- package/dist/v1/utils/thread-utils.d.ts.map +1 -1
- package/dist/v1/utils/thread-utils.js.map +1 -1
- package/dist/v1/utils/tool-call-tracker.d.ts +1 -1
- package/dist/v1/utils/tool-call-tracker.js +1 -1
- package/dist/v1/utils/tool-call-tracker.js.map +1 -1
- package/dist/v1/utils/tool-executor.d.ts +1 -1
- package/dist/v1/utils/tool-executor.js +2 -2
- package/dist/v1/utils/tool-executor.js.map +1 -1
- package/esm/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/esm/hoc/with-tambo-interactable.js +13 -13
- package/esm/hoc/with-tambo-interactable.js.map +1 -1
- package/esm/hoc/with-tambo-interactable.test.js +1 -1
- package/esm/hoc/with-tambo-interactable.test.js.map +1 -1
- package/esm/index.d.ts +7 -25
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +7 -21
- package/esm/index.js.map +1 -1
- package/esm/mcp/mcp-hooks.js +1 -1
- package/esm/mcp/mcp-hooks.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/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 -2
- package/esm/providers/tambo-client-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts +1 -1
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js +2 -10
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context.test.js +3 -19
- package/esm/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/esm/providers/tambo-mcp-token-provider.d.ts +8 -17
- package/esm/providers/tambo-mcp-token-provider.d.ts.map +1 -1
- package/esm/providers/tambo-mcp-token-provider.js +20 -97
- package/esm/providers/tambo-mcp-token-provider.js.map +1 -1
- package/esm/testing/tools.d.ts +3 -3
- package/esm/testing/tools.d.ts.map +1 -1
- package/esm/testing/tools.js.map +1 -1
- package/esm/util/registry-validators.js +1 -1
- package/esm/util/registry-validators.js.map +1 -1
- package/esm/v1/__tests__/v1-interactables.test.js +1 -1
- package/esm/v1/__tests__/v1-interactables.test.js.map +1 -1
- package/esm/v1/components/v1-component-renderer.d.ts +9 -9
- package/esm/v1/components/v1-component-renderer.d.ts.map +1 -1
- package/esm/v1/components/v1-component-renderer.js +12 -12
- package/esm/v1/components/v1-component-renderer.js.map +1 -1
- package/esm/v1/components/v1-component-renderer.test.js +16 -16
- package/esm/v1/components/v1-component-renderer.test.js.map +1 -1
- package/{dist/hooks/use-current-message.d.ts → esm/v1/hooks/use-tambo-current-message.d.ts} +30 -9
- package/esm/v1/hooks/use-tambo-current-message.d.ts.map +1 -0
- package/esm/{hooks/use-current-message.js → v1/hooks/use-tambo-current-message.js} +13 -8
- package/esm/v1/hooks/use-tambo-current-message.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.d.ts +5 -5
- package/esm/v1/hooks/use-tambo-v1-auth-state.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-auth-state.js +8 -8
- package/esm/v1/hooks/use-tambo-v1-auth-state.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.js +14 -14
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.d.ts +7 -6
- package/esm/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.js +50 -24
- package/esm/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.test.js +62 -37
- package/esm/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.d.ts +9 -9
- package/esm/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.js +3 -3
- package/esm/v1/hooks/use-tambo-v1-messages.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.test.js +9 -9
- package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +3 -3
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.js +21 -23
- package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js +54 -54
- 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 +5 -5
- package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.js +12 -14
- package/esm/v1/hooks/use-tambo-v1-stream-status.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.js +21 -21
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts +7 -7
- package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-suggestions.js +11 -11
- package/esm/v1/hooks/use-tambo-v1-suggestions.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-suggestions.test.js +48 -48
- package/esm/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts +3 -3
- package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.js +3 -3
- package/esm/v1/hooks/use-tambo-v1-thread-input.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +32 -32
- 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 +4 -4
- package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.js +6 -6
- package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +15 -19
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.d.ts +3 -3
- package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.js +4 -4
- package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.test.js +6 -6
- package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.d.ts +16 -7
- package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.js +43 -12
- package/esm/v1/hooks/use-tambo-v1.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.test.js +178 -50
- package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/esm/v1/index.d.ts +31 -27
- package/esm/v1/index.d.ts.map +1 -1
- package/esm/v1/index.js +38 -33
- package/esm/v1/index.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.d.ts +20 -20
- package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.js +32 -32
- package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.test.js +23 -23
- package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.d.ts +15 -15
- package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.js +17 -17
- package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.test.js +10 -10
- package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.d.ts +9 -9
- package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.js +9 -9
- package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.test.js +28 -28
- package/esm/v1/providers/tambo-v1-stub-provider.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +9 -9
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.js +15 -15
- package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
- package/esm/v1/types/auth.d.ts +2 -2
- package/esm/v1/types/auth.d.ts.map +1 -1
- package/esm/v1/types/auth.js.map +1 -1
- package/esm/v1/types/component.d.ts +3 -3
- package/esm/v1/types/component.d.ts.map +1 -1
- package/esm/v1/types/component.js +2 -2
- package/esm/v1/types/component.js.map +1 -1
- package/esm/v1/types/event.d.ts +1 -1
- package/esm/v1/types/event.js +1 -1
- package/esm/v1/types/event.js.map +1 -1
- package/esm/v1/types/message.d.ts +17 -24
- package/esm/v1/types/message.d.ts.map +1 -1
- package/esm/v1/types/message.js +1 -1
- package/esm/v1/types/message.js.map +1 -1
- package/esm/v1/types/thread.d.ts +10 -8
- package/esm/v1/types/thread.d.ts.map +1 -1
- package/esm/v1/types/thread.js +1 -1
- package/esm/v1/types/thread.js.map +1 -1
- package/esm/v1/types/tool-choice.d.ts +1 -1
- package/esm/v1/types/tool-choice.js.map +1 -1
- package/esm/v1/utils/component-renderer.d.ts +11 -5
- package/esm/v1/utils/component-renderer.d.ts.map +1 -1
- package/esm/v1/utils/component-renderer.js +13 -5
- package/esm/v1/utils/component-renderer.js.map +1 -1
- package/esm/v1/utils/component-renderer.test.js +8 -8
- package/esm/v1/utils/component-renderer.test.js.map +1 -1
- package/esm/v1/utils/event-accumulator.d.ts +13 -13
- package/esm/v1/utils/event-accumulator.d.ts.map +1 -1
- package/esm/v1/utils/event-accumulator.js +26 -15
- package/esm/v1/utils/event-accumulator.js.map +1 -1
- package/esm/v1/utils/event-accumulator.test.js +54 -19
- package/esm/v1/utils/event-accumulator.test.js.map +1 -1
- package/esm/v1/utils/registry-conversion.d.ts +18 -18
- package/esm/v1/utils/registry-conversion.js +23 -23
- package/esm/v1/utils/registry-conversion.js.map +1 -1
- package/esm/v1/utils/stream-handler.d.ts +1 -1
- package/esm/v1/utils/stream-handler.js +1 -1
- package/esm/v1/utils/stream-handler.js.map +1 -1
- package/esm/v1/utils/thread-utils.d.ts +2 -2
- package/esm/v1/utils/thread-utils.d.ts.map +1 -1
- package/esm/v1/utils/thread-utils.js.map +1 -1
- package/esm/v1/utils/tool-call-tracker.d.ts +1 -1
- package/esm/v1/utils/tool-call-tracker.js +1 -1
- package/esm/v1/utils/tool-call-tracker.js.map +1 -1
- package/esm/v1/utils/tool-executor.d.ts +1 -1
- package/esm/v1/utils/tool-executor.js +2 -2
- package/esm/v1/utils/tool-executor.js.map +1 -1
- package/package.json +4 -9
- package/dist/hooks/index.d.ts +0 -9
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js +0 -34
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/use-component-state.d.ts +0 -30
- package/dist/hooks/use-component-state.d.ts.map +0 -1
- package/dist/hooks/use-component-state.js +0 -139
- package/dist/hooks/use-component-state.js.map +0 -1
- package/dist/hooks/use-component-state.test.d.ts +0 -2
- package/dist/hooks/use-component-state.test.d.ts.map +0 -1
- package/dist/hooks/use-component-state.test.js +0 -406
- package/dist/hooks/use-component-state.test.js.map +0 -1
- package/dist/hooks/use-current-message.d.ts.map +0 -1
- package/dist/hooks/use-current-message.js.map +0 -1
- package/dist/hooks/use-current-message.test.d.ts +0 -2
- package/dist/hooks/use-current-message.test.d.ts.map +0 -1
- package/dist/hooks/use-current-message.test.js +0 -269
- package/dist/hooks/use-current-message.test.js.map +0 -1
- package/dist/hooks/use-streaming-props.d.ts +0 -11
- package/dist/hooks/use-streaming-props.d.ts.map +0 -1
- package/dist/hooks/use-streaming-props.js +0 -37
- package/dist/hooks/use-streaming-props.js.map +0 -1
- package/dist/hooks/use-suggestions.d.ts +0 -46
- package/dist/hooks/use-suggestions.d.ts.map +0 -1
- package/dist/hooks/use-suggestions.js +0 -118
- package/dist/hooks/use-suggestions.js.map +0 -1
- package/dist/hooks/use-suggestions.test.d.ts +0 -2
- package/dist/hooks/use-suggestions.test.d.ts.map +0 -1
- package/dist/hooks/use-suggestions.test.js +0 -247
- package/dist/hooks/use-suggestions.test.js.map +0 -1
- package/dist/hooks/use-tambo-stream-status.d.ts +0 -90
- package/dist/hooks/use-tambo-stream-status.d.ts.map +0 -1
- package/dist/hooks/use-tambo-stream-status.js +0 -213
- package/dist/hooks/use-tambo-stream-status.js.map +0 -1
- package/dist/hooks/use-tambo-stream-status.test.d.ts +0 -2
- package/dist/hooks/use-tambo-stream-status.test.d.ts.map +0 -1
- package/dist/hooks/use-tambo-stream-status.test.js +0 -378
- package/dist/hooks/use-tambo-stream-status.test.js.map +0 -1
- package/dist/hooks/use-tambo-threads.d.ts +0 -158
- package/dist/hooks/use-tambo-threads.d.ts.map +0 -1
- package/dist/hooks/use-tambo-threads.js +0 -45
- package/dist/hooks/use-tambo-threads.js.map +0 -1
- package/dist/hooks/use-tambo-threads.test.d.ts +0 -2
- package/dist/hooks/use-tambo-threads.test.d.ts.map +0 -1
- package/dist/hooks/use-tambo-threads.test.js +0 -214
- package/dist/hooks/use-tambo-threads.test.js.map +0 -1
- package/dist/model/generate-component-response.d.ts +0 -37
- package/dist/model/generate-component-response.d.ts.map +0 -1
- package/dist/model/generate-component-response.js +0 -29
- package/dist/model/generate-component-response.js.map +0 -1
- package/dist/model/tambo-thread.d.ts +0 -15
- package/dist/model/tambo-thread.d.ts.map +0 -1
- package/dist/model/tambo-thread.js +0 -3
- package/dist/model/tambo-thread.js.map +0 -1
- package/dist/providers/__tests__/thread-input-resource-resolution.test.d.ts +0 -2
- package/dist/providers/__tests__/thread-input-resource-resolution.test.d.ts.map +0 -1
- package/dist/providers/__tests__/thread-input-resource-resolution.test.js +0 -592
- package/dist/providers/__tests__/thread-input-resource-resolution.test.js.map +0 -1
- package/dist/providers/index.d.ts +0 -13
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/providers/index.js +0 -41
- package/dist/providers/index.js.map +0 -1
- package/dist/providers/tambo-component-provider.d.ts +0 -23
- package/dist/providers/tambo-component-provider.d.ts.map +0 -1
- package/dist/providers/tambo-component-provider.js +0 -88
- package/dist/providers/tambo-component-provider.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/index.d.ts +0 -19
- package/dist/providers/tambo-prop-stream-provider/index.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/index.js +0 -43
- package/dist/providers/tambo-prop-stream-provider/index.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/pending.d.ts +0 -12
- package/dist/providers/tambo-prop-stream-provider/pending.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/pending.js +0 -31
- package/dist/providers/tambo-prop-stream-provider/pending.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/provider.d.ts +0 -17
- package/dist/providers/tambo-prop-stream-provider/provider.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/provider.js +0 -107
- package/dist/providers/tambo-prop-stream-provider/provider.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/streaming.d.ts +0 -12
- package/dist/providers/tambo-prop-stream-provider/streaming.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/streaming.js +0 -28
- package/dist/providers/tambo-prop-stream-provider/streaming.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/success.d.ts +0 -12
- package/dist/providers/tambo-prop-stream-provider/success.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/success.js +0 -28
- package/dist/providers/tambo-prop-stream-provider/success.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/types.d.ts +0 -25
- package/dist/providers/tambo-prop-stream-provider/types.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/types.js +0 -6
- package/dist/providers/tambo-prop-stream-provider/types.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider.test.d.ts +0 -2
- package/dist/providers/tambo-prop-stream-provider.test.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider.test.js +0 -275
- package/dist/providers/tambo-prop-stream-provider.test.js.map +0 -1
- package/dist/providers/tambo-provider.d.ts +0 -53
- package/dist/providers/tambo-provider.d.ts.map +0 -1
- package/dist/providers/tambo-provider.js +0 -133
- package/dist/providers/tambo-provider.js.map +0 -1
- package/dist/providers/tambo-stubs.d.ts +0 -89
- package/dist/providers/tambo-stubs.d.ts.map +0 -1
- package/dist/providers/tambo-stubs.js +0 -279
- package/dist/providers/tambo-stubs.js.map +0 -1
- package/dist/providers/tambo-stubs.test.d.ts +0 -2
- package/dist/providers/tambo-stubs.test.d.ts.map +0 -1
- package/dist/providers/tambo-stubs.test.js +0 -97
- package/dist/providers/tambo-stubs.test.js.map +0 -1
- package/dist/providers/tambo-thread-input-provider.d.ts +0 -65
- package/dist/providers/tambo-thread-input-provider.d.ts.map +0 -1
- package/dist/providers/tambo-thread-input-provider.js +0 -179
- package/dist/providers/tambo-thread-input-provider.js.map +0 -1
- package/dist/providers/tambo-thread-provider-initial-messages.test.d.ts +0 -2
- package/dist/providers/tambo-thread-provider-initial-messages.test.d.ts.map +0 -1
- package/dist/providers/tambo-thread-provider-initial-messages.test.js +0 -278
- package/dist/providers/tambo-thread-provider-initial-messages.test.js.map +0 -1
- package/dist/providers/tambo-thread-provider.d.ts +0 -126
- package/dist/providers/tambo-thread-provider.d.ts.map +0 -1
- package/dist/providers/tambo-thread-provider.js +0 -931
- package/dist/providers/tambo-thread-provider.js.map +0 -1
- package/dist/providers/tambo-thread-provider.test.d.ts +0 -2
- package/dist/providers/tambo-thread-provider.test.d.ts.map +0 -1
- package/dist/providers/tambo-thread-provider.test.js +0 -1591
- package/dist/providers/tambo-thread-provider.test.js.map +0 -1
- package/dist/util/generate-component.d.ts +0 -12
- package/dist/util/generate-component.d.ts.map +0 -1
- package/dist/util/generate-component.js +0 -58
- package/dist/util/generate-component.js.map +0 -1
- package/dist/util/generate-component.test.d.ts +0 -2
- package/dist/util/generate-component.test.d.ts.map +0 -1
- package/dist/util/generate-component.test.js +0 -340
- package/dist/util/generate-component.test.js.map +0 -1
- package/esm/hooks/index.d.ts +0 -9
- package/esm/hooks/index.d.ts.map +0 -1
- package/esm/hooks/index.js +0 -10
- package/esm/hooks/index.js.map +0 -1
- package/esm/hooks/use-component-state.d.ts +0 -30
- package/esm/hooks/use-component-state.d.ts.map +0 -1
- package/esm/hooks/use-component-state.js +0 -136
- package/esm/hooks/use-component-state.js.map +0 -1
- package/esm/hooks/use-component-state.test.d.ts +0 -2
- package/esm/hooks/use-component-state.test.d.ts.map +0 -1
- package/esm/hooks/use-component-state.test.js +0 -401
- package/esm/hooks/use-component-state.test.js.map +0 -1
- package/esm/hooks/use-current-message.d.ts.map +0 -1
- package/esm/hooks/use-current-message.js.map +0 -1
- package/esm/hooks/use-current-message.test.d.ts +0 -2
- package/esm/hooks/use-current-message.test.d.ts.map +0 -1
- package/esm/hooks/use-current-message.test.js +0 -264
- package/esm/hooks/use-current-message.test.js.map +0 -1
- package/esm/hooks/use-streaming-props.d.ts +0 -11
- package/esm/hooks/use-streaming-props.d.ts.map +0 -1
- package/esm/hooks/use-streaming-props.js +0 -34
- package/esm/hooks/use-streaming-props.js.map +0 -1
- package/esm/hooks/use-suggestions.d.ts +0 -46
- package/esm/hooks/use-suggestions.d.ts.map +0 -1
- package/esm/hooks/use-suggestions.js +0 -115
- package/esm/hooks/use-suggestions.js.map +0 -1
- package/esm/hooks/use-suggestions.test.d.ts +0 -2
- package/esm/hooks/use-suggestions.test.d.ts.map +0 -1
- package/esm/hooks/use-suggestions.test.js +0 -245
- package/esm/hooks/use-suggestions.test.js.map +0 -1
- package/esm/hooks/use-tambo-stream-status.d.ts +0 -90
- package/esm/hooks/use-tambo-stream-status.d.ts.map +0 -1
- package/esm/hooks/use-tambo-stream-status.js +0 -210
- package/esm/hooks/use-tambo-stream-status.js.map +0 -1
- package/esm/hooks/use-tambo-stream-status.test.d.ts +0 -2
- package/esm/hooks/use-tambo-stream-status.test.d.ts.map +0 -1
- package/esm/hooks/use-tambo-stream-status.test.js +0 -376
- package/esm/hooks/use-tambo-stream-status.test.js.map +0 -1
- package/esm/hooks/use-tambo-threads.d.ts +0 -158
- package/esm/hooks/use-tambo-threads.d.ts.map +0 -1
- package/esm/hooks/use-tambo-threads.js +0 -42
- package/esm/hooks/use-tambo-threads.js.map +0 -1
- package/esm/hooks/use-tambo-threads.test.d.ts +0 -2
- package/esm/hooks/use-tambo-threads.test.d.ts.map +0 -1
- package/esm/hooks/use-tambo-threads.test.js +0 -212
- package/esm/hooks/use-tambo-threads.test.js.map +0 -1
- package/esm/model/generate-component-response.d.ts +0 -37
- package/esm/model/generate-component-response.d.ts.map +0 -1
- package/esm/model/generate-component-response.js +0 -25
- package/esm/model/generate-component-response.js.map +0 -1
- package/esm/model/tambo-thread.d.ts +0 -15
- package/esm/model/tambo-thread.d.ts.map +0 -1
- package/esm/model/tambo-thread.js +0 -2
- package/esm/model/tambo-thread.js.map +0 -1
- package/esm/providers/__tests__/thread-input-resource-resolution.test.d.ts +0 -2
- package/esm/providers/__tests__/thread-input-resource-resolution.test.d.ts.map +0 -1
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js +0 -587
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js.map +0 -1
- package/esm/providers/index.d.ts +0 -13
- package/esm/providers/index.d.ts.map +0 -1
- package/esm/providers/index.js +0 -11
- package/esm/providers/index.js.map +0 -1
- package/esm/providers/tambo-component-provider.d.ts +0 -23
- package/esm/providers/tambo-component-provider.d.ts.map +0 -1
- package/esm/providers/tambo-component-provider.js +0 -50
- package/esm/providers/tambo-component-provider.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/index.d.ts +0 -19
- package/esm/providers/tambo-prop-stream-provider/index.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/index.js +0 -22
- package/esm/providers/tambo-prop-stream-provider/index.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/pending.d.ts +0 -12
- package/esm/providers/tambo-prop-stream-provider/pending.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/pending.js +0 -24
- package/esm/providers/tambo-prop-stream-provider/pending.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/provider.d.ts +0 -17
- package/esm/providers/tambo-prop-stream-provider/provider.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/provider.js +0 -70
- package/esm/providers/tambo-prop-stream-provider/provider.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/streaming.d.ts +0 -12
- package/esm/providers/tambo-prop-stream-provider/streaming.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/streaming.js +0 -21
- package/esm/providers/tambo-prop-stream-provider/streaming.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/success.d.ts +0 -12
- package/esm/providers/tambo-prop-stream-provider/success.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/success.js +0 -21
- package/esm/providers/tambo-prop-stream-provider/success.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/types.d.ts +0 -25
- package/esm/providers/tambo-prop-stream-provider/types.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/types.js +0 -3
- package/esm/providers/tambo-prop-stream-provider/types.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider.test.d.ts +0 -2
- package/esm/providers/tambo-prop-stream-provider.test.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider.test.js +0 -270
- package/esm/providers/tambo-prop-stream-provider.test.js.map +0 -1
- package/esm/providers/tambo-provider.d.ts +0 -53
- package/esm/providers/tambo-provider.d.ts.map +0 -1
- package/esm/providers/tambo-provider.js +0 -94
- package/esm/providers/tambo-provider.js.map +0 -1
- package/esm/providers/tambo-stubs.d.ts +0 -89
- package/esm/providers/tambo-stubs.d.ts.map +0 -1
- package/esm/providers/tambo-stubs.js +0 -242
- package/esm/providers/tambo-stubs.js.map +0 -1
- package/esm/providers/tambo-stubs.test.d.ts +0 -2
- package/esm/providers/tambo-stubs.test.d.ts.map +0 -1
- package/esm/providers/tambo-stubs.test.js +0 -62
- package/esm/providers/tambo-stubs.test.js.map +0 -1
- package/esm/providers/tambo-thread-input-provider.d.ts +0 -65
- package/esm/providers/tambo-thread-input-provider.d.ts.map +0 -1
- package/esm/providers/tambo-thread-input-provider.js +0 -141
- package/esm/providers/tambo-thread-input-provider.js.map +0 -1
- package/esm/providers/tambo-thread-provider-initial-messages.test.d.ts +0 -2
- package/esm/providers/tambo-thread-provider-initial-messages.test.d.ts.map +0 -1
- package/esm/providers/tambo-thread-provider-initial-messages.test.js +0 -273
- package/esm/providers/tambo-thread-provider-initial-messages.test.js.map +0 -1
- package/esm/providers/tambo-thread-provider.d.ts +0 -126
- package/esm/providers/tambo-thread-provider.d.ts.map +0 -1
- package/esm/providers/tambo-thread-provider.js +0 -891
- package/esm/providers/tambo-thread-provider.js.map +0 -1
- package/esm/providers/tambo-thread-provider.test.d.ts +0 -2
- package/esm/providers/tambo-thread-provider.test.d.ts.map +0 -1
- package/esm/providers/tambo-thread-provider.test.js +0 -1553
- package/esm/providers/tambo-thread-provider.test.js.map +0 -1
- package/esm/util/generate-component.d.ts +0 -12
- package/esm/util/generate-component.d.ts.map +0 -1
- package/esm/util/generate-component.js +0 -52
- package/esm/util/generate-component.js.map +0 -1
- package/esm/util/generate-component.test.d.ts +0 -2
- package/esm/util/generate-component.test.d.ts.map +0 -1
- package/esm/util/generate-component.test.js +0 -302
- package/esm/util/generate-component.test.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* useTamboMessages - Messages Hook
|
|
4
4
|
*
|
|
5
5
|
* Provides access to messages in a thread with streaming state awareness.
|
|
6
6
|
* Messages are accumulated from AG-UI events during streaming.
|
|
@@ -17,7 +17,7 @@ import { useStreamState } from "../providers/tambo-v1-stream-context.js";
|
|
|
17
17
|
* @example
|
|
18
18
|
* ```tsx
|
|
19
19
|
* function MessageList({ threadId }: { threadId: string }) {
|
|
20
|
-
* const { messages, hasMessages, lastMessage } =
|
|
20
|
+
* const { messages, hasMessages, lastMessage } = useTamboMessages(threadId);
|
|
21
21
|
*
|
|
22
22
|
* if (!hasMessages) {
|
|
23
23
|
* return <EmptyState />;
|
|
@@ -33,7 +33,7 @@ import { useStreamState } from "../providers/tambo-v1-stream-context.js";
|
|
|
33
33
|
* }
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
|
-
export function
|
|
36
|
+
export function useTamboMessages(threadId) {
|
|
37
37
|
const streamState = useStreamState();
|
|
38
38
|
const threadState = streamState.threadMap[threadId];
|
|
39
39
|
return useMemo(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tambo-v1-messages.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-messages.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAsCtE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"use-tambo-v1-messages.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-messages.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAsCtE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,QAAgB;IAEhB,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEpD,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,MAAM,QAAQ,GAAG,WAAW,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;QAEpD,OAAO;YACL,QAAQ;YACR,WAAW,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YAC1C,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;YACvD,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC;YACjE,WAAW,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC;YAChC,YAAY,EAAE,QAAQ,CAAC,MAAM;SAC9B,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;AACrC,CAAC","sourcesContent":["\"use client\";\n\n/**\n * useTamboMessages - Messages Hook\n *\n * Provides access to messages in a thread with streaming state awareness.\n * Messages are accumulated from AG-UI events during streaming.\n */\n\nimport { useMemo } from \"react\";\nimport { useStreamState } from \"../providers/tambo-v1-stream-context\";\nimport type { TamboThreadMessage } from \"../types/message\";\n\n/**\n * Return type for useTamboMessages hook\n */\nexport interface UseTamboThreadMessagesReturn {\n /**\n * All messages in the thread\n */\n messages: TamboThreadMessage[];\n\n /**\n * The most recent message (last in the list)\n */\n lastMessage: TamboThreadMessage | undefined;\n\n /**\n * User messages only\n */\n userMessages: TamboThreadMessage[];\n\n /**\n * Assistant messages only\n */\n assistantMessages: TamboThreadMessage[];\n\n /**\n * Whether there are any messages\n */\n hasMessages: boolean;\n\n /**\n * Total message count\n */\n messageCount: number;\n}\n\n/**\n * Hook to access messages in a thread.\n *\n * Provides filtered views of messages (user-only, assistant-only)\n * and metadata about the message list.\n * @param threadId - Thread ID to get messages for\n * @returns Message list and utilities\n * @example\n * ```tsx\n * function MessageList({ threadId }: { threadId: string }) {\n * const { messages, hasMessages, lastMessage } = useTamboMessages(threadId);\n *\n * if (!hasMessages) {\n * return <EmptyState />;\n * }\n *\n * return (\n * <div>\n * {messages.map(msg => (\n * <Message key={msg.id} message={msg} />\n * ))}\n * </div>\n * );\n * }\n * ```\n */\nexport function useTamboMessages(\n threadId: string,\n): UseTamboThreadMessagesReturn {\n const streamState = useStreamState();\n const threadState = streamState.threadMap[threadId];\n\n return useMemo(() => {\n const messages = threadState?.thread.messages ?? [];\n\n return {\n messages,\n lastMessage: messages[messages.length - 1],\n userMessages: messages.filter((m) => m.role === \"user\"),\n assistantMessages: messages.filter((m) => m.role === \"assistant\"),\n hasMessages: messages.length > 0,\n messageCount: messages.length,\n };\n }, [threadState?.thread.messages]);\n}\n"]}
|
|
@@ -2,8 +2,8 @@ import { EventType, } from "@ag-ui/core";
|
|
|
2
2
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
3
3
|
import { renderHook, act } from "@testing-library/react";
|
|
4
4
|
import React from "react";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { TamboStreamProvider, useStreamDispatch, } from "../providers/tambo-v1-stream-context.js";
|
|
6
|
+
import { useTamboMessages } from "./use-tambo-v1-messages.js";
|
|
7
7
|
// Mock useTamboClient and useTamboQueryClient to avoid TamboClientProvider dependency
|
|
8
8
|
jest.mock("../../providers/tambo-client-provider", () => ({
|
|
9
9
|
useTamboClient: jest.fn(() => ({
|
|
@@ -20,11 +20,11 @@ jest.mock("../providers/tambo-v1-provider", () => {
|
|
|
20
20
|
const actual = jest.requireActual("../providers/tambo-v1-provider");
|
|
21
21
|
return {
|
|
22
22
|
...actual,
|
|
23
|
-
|
|
23
|
+
useTamboConfig: () => ({ userKey: undefined }),
|
|
24
24
|
};
|
|
25
25
|
});
|
|
26
26
|
import { useTamboQueryClient } from "../../providers/tambo-client-provider.js";
|
|
27
|
-
describe("
|
|
27
|
+
describe("useTamboMessages", () => {
|
|
28
28
|
let queryClient;
|
|
29
29
|
beforeEach(() => {
|
|
30
30
|
queryClient = new QueryClient({
|
|
@@ -37,11 +37,11 @@ describe("useTamboV1Messages", () => {
|
|
|
37
37
|
});
|
|
38
38
|
function TestWrapper({ children }) {
|
|
39
39
|
return (React.createElement(QueryClientProvider, { client: queryClient },
|
|
40
|
-
React.createElement(
|
|
40
|
+
React.createElement(TamboStreamProvider, null, children)));
|
|
41
41
|
}
|
|
42
42
|
it("returns empty messages when thread has no messages", () => {
|
|
43
43
|
const { result } = renderHook(() => ({
|
|
44
|
-
messages:
|
|
44
|
+
messages: useTamboMessages("thread_123"),
|
|
45
45
|
dispatch: useStreamDispatch(),
|
|
46
46
|
}), { wrapper: TestWrapper });
|
|
47
47
|
// Initialize thread first
|
|
@@ -57,7 +57,7 @@ describe("useTamboV1Messages", () => {
|
|
|
57
57
|
});
|
|
58
58
|
it("returns messages after events are dispatched", () => {
|
|
59
59
|
const { result } = renderHook(() => ({
|
|
60
|
-
messages:
|
|
60
|
+
messages: useTamboMessages("thread_123"),
|
|
61
61
|
dispatch: useStreamDispatch(),
|
|
62
62
|
}), { wrapper: TestWrapper });
|
|
63
63
|
// Initialize thread first
|
|
@@ -107,7 +107,7 @@ describe("useTamboV1Messages", () => {
|
|
|
107
107
|
});
|
|
108
108
|
it("filters user and assistant messages correctly", () => {
|
|
109
109
|
const { result } = renderHook(() => ({
|
|
110
|
-
messages:
|
|
110
|
+
messages: useTamboMessages("thread_123"),
|
|
111
111
|
dispatch: useStreamDispatch(),
|
|
112
112
|
}), { wrapper: TestWrapper });
|
|
113
113
|
// Initialize thread first
|
|
@@ -166,7 +166,7 @@ describe("useTamboV1Messages", () => {
|
|
|
166
166
|
expect(result.current.messages.lastMessage?.id).toBe("msg_assistant");
|
|
167
167
|
});
|
|
168
168
|
it("returns empty messages when threadId does not exist in threadMap", () => {
|
|
169
|
-
const { result } = renderHook(() =>
|
|
169
|
+
const { result } = renderHook(() => useTamboMessages("nonexistent_thread"), {
|
|
170
170
|
wrapper: TestWrapper,
|
|
171
171
|
});
|
|
172
172
|
expect(result.current.messages).toEqual([]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tambo-v1-messages.test.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-messages.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n EventType,\n type TextMessageStartEvent,\n type TextMessageContentEvent,\n type TextMessageEndEvent,\n} from \"@ag-ui/core\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { renderHook, act } from \"@testing-library/react\";\nimport React from \"react\";\nimport {\n TamboV1StreamProvider,\n useStreamDispatch,\n} from \"../providers/tambo-v1-stream-context\";\nimport { useTamboV1Messages } from \"./use-tambo-v1-messages\";\n\n// Mock useTamboClient and useTamboQueryClient to avoid TamboClientProvider dependency\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(() => ({\n threads: {\n messages: {\n list: jest.fn().mockResolvedValue({ messages: [], hasMore: false }),\n },\n retrieve: jest.fn().mockResolvedValue({}),\n },\n })),\n useTamboQueryClient: jest.fn(),\n}));\n\njest.mock(\"../providers/tambo-v1-provider\", () => {\n const actual = jest.requireActual(\"../providers/tambo-v1-provider\");\n return {\n ...actual,\n useTamboV1Config: () => ({ userKey: undefined }),\n };\n});\n\nimport { useTamboQueryClient } from \"../../providers/tambo-client-provider\";\n\ndescribe(\"useTamboV1Messages\", () => {\n let queryClient: QueryClient;\n\n beforeEach(() => {\n queryClient = new QueryClient({\n defaultOptions: {\n queries: { retry: false },\n },\n });\n // Configure mock to return the test's queryClient\n jest.mocked(useTamboQueryClient).mockReturnValue(queryClient);\n });\n\n function TestWrapper({ children }: { children: React.ReactNode }) {\n return (\n <QueryClientProvider client={queryClient}>\n <TamboV1StreamProvider>{children}</TamboV1StreamProvider>\n </QueryClientProvider>\n );\n }\n\n it(\"returns empty messages when thread has no messages\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboV1Messages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n expect(result.current.messages.messages).toEqual([]);\n expect(result.current.messages.hasMessages).toBe(false);\n expect(result.current.messages.messageCount).toBe(0);\n expect(result.current.messages.lastMessage).toBeUndefined();\n expect(result.current.messages.userMessages).toEqual([]);\n expect(result.current.messages.assistantMessages).toEqual([]);\n });\n\n it(\"returns messages after events are dispatched\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboV1Messages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n // Simulate a text message being received\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_1\",\n role: \"assistant\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId: \"msg_1\",\n delta: \"Hello\",\n } as TextMessageContentEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_1\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n expect(result.current.messages.messages.length).toBe(1);\n expect(result.current.messages.hasMessages).toBe(true);\n expect(result.current.messages.messageCount).toBe(1);\n expect(result.current.messages.lastMessage?.id).toBe(\"msg_1\");\n expect(result.current.messages.lastMessage?.role).toBe(\"assistant\");\n expect(result.current.messages.assistantMessages.length).toBe(1);\n expect(result.current.messages.userMessages.length).toBe(0);\n });\n\n it(\"filters user and assistant messages correctly\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboV1Messages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n // Add user message\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_user\",\n role: \"user\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_user\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n // Add assistant message\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_assistant\",\n role: \"assistant\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_assistant\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n expect(result.current.messages.messageCount).toBe(2);\n expect(result.current.messages.userMessages.length).toBe(1);\n expect(result.current.messages.userMessages[0].id).toBe(\"msg_user\");\n expect(result.current.messages.assistantMessages.length).toBe(1);\n expect(result.current.messages.assistantMessages[0].id).toBe(\n \"msg_assistant\",\n );\n expect(result.current.messages.lastMessage?.id).toBe(\"msg_assistant\");\n });\n\n it(\"returns empty messages when threadId does not exist in threadMap\", () => {\n const { result } = renderHook(\n () => useTamboV1Messages(\"nonexistent_thread\"),\n {\n wrapper: TestWrapper,\n },\n );\n\n expect(result.current.messages).toEqual([]);\n expect(result.current.hasMessages).toBe(false);\n expect(result.current.messageCount).toBe(0);\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"use-tambo-v1-messages.test.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-messages.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n EventType,\n type TextMessageStartEvent,\n type TextMessageContentEvent,\n type TextMessageEndEvent,\n} from \"@ag-ui/core\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { renderHook, act } from \"@testing-library/react\";\nimport React from \"react\";\nimport {\n TamboStreamProvider,\n useStreamDispatch,\n} from \"../providers/tambo-v1-stream-context\";\nimport { useTamboMessages } from \"./use-tambo-v1-messages\";\n\n// Mock useTamboClient and useTamboQueryClient to avoid TamboClientProvider dependency\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(() => ({\n threads: {\n messages: {\n list: jest.fn().mockResolvedValue({ messages: [], hasMore: false }),\n },\n retrieve: jest.fn().mockResolvedValue({}),\n },\n })),\n useTamboQueryClient: jest.fn(),\n}));\n\njest.mock(\"../providers/tambo-v1-provider\", () => {\n const actual = jest.requireActual(\"../providers/tambo-v1-provider\");\n return {\n ...actual,\n useTamboConfig: () => ({ userKey: undefined }),\n };\n});\n\nimport { useTamboQueryClient } from \"../../providers/tambo-client-provider\";\n\ndescribe(\"useTamboMessages\", () => {\n let queryClient: QueryClient;\n\n beforeEach(() => {\n queryClient = new QueryClient({\n defaultOptions: {\n queries: { retry: false },\n },\n });\n // Configure mock to return the test's queryClient\n jest.mocked(useTamboQueryClient).mockReturnValue(queryClient);\n });\n\n function TestWrapper({ children }: { children: React.ReactNode }) {\n return (\n <QueryClientProvider client={queryClient}>\n <TamboStreamProvider>{children}</TamboStreamProvider>\n </QueryClientProvider>\n );\n }\n\n it(\"returns empty messages when thread has no messages\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboMessages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n expect(result.current.messages.messages).toEqual([]);\n expect(result.current.messages.hasMessages).toBe(false);\n expect(result.current.messages.messageCount).toBe(0);\n expect(result.current.messages.lastMessage).toBeUndefined();\n expect(result.current.messages.userMessages).toEqual([]);\n expect(result.current.messages.assistantMessages).toEqual([]);\n });\n\n it(\"returns messages after events are dispatched\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboMessages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n // Simulate a text message being received\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_1\",\n role: \"assistant\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId: \"msg_1\",\n delta: \"Hello\",\n } as TextMessageContentEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_1\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n expect(result.current.messages.messages.length).toBe(1);\n expect(result.current.messages.hasMessages).toBe(true);\n expect(result.current.messages.messageCount).toBe(1);\n expect(result.current.messages.lastMessage?.id).toBe(\"msg_1\");\n expect(result.current.messages.lastMessage?.role).toBe(\"assistant\");\n expect(result.current.messages.assistantMessages.length).toBe(1);\n expect(result.current.messages.userMessages.length).toBe(0);\n });\n\n it(\"filters user and assistant messages correctly\", () => {\n const { result } = renderHook(\n () => ({\n messages: useTamboMessages(\"thread_123\"),\n dispatch: useStreamDispatch(),\n }),\n { wrapper: TestWrapper },\n );\n\n // Initialize thread first\n act(() => {\n result.current.dispatch({ type: \"INIT_THREAD\", threadId: \"thread_123\" });\n });\n\n // Add user message\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_user\",\n role: \"user\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_user\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n // Add assistant message\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_START,\n messageId: \"msg_assistant\",\n role: \"assistant\",\n } as TextMessageStartEvent,\n threadId: \"thread_123\",\n });\n });\n\n act(() => {\n result.current.dispatch({\n type: \"EVENT\",\n event: {\n type: EventType.TEXT_MESSAGE_END,\n messageId: \"msg_assistant\",\n } as TextMessageEndEvent,\n threadId: \"thread_123\",\n });\n });\n\n expect(result.current.messages.messageCount).toBe(2);\n expect(result.current.messages.userMessages.length).toBe(1);\n expect(result.current.messages.userMessages[0].id).toBe(\"msg_user\");\n expect(result.current.messages.assistantMessages.length).toBe(1);\n expect(result.current.messages.assistantMessages[0].id).toBe(\n \"msg_assistant\",\n );\n expect(result.current.messages.lastMessage?.id).toBe(\"msg_assistant\");\n });\n\n it(\"returns empty messages when threadId does not exist in threadMap\", () => {\n const { result } = renderHook(\n () => useTamboMessages(\"nonexistent_thread\"),\n {\n wrapper: TestWrapper,\n },\n );\n\n expect(result.current.messages).toEqual([]);\n expect(result.current.hasMessages).toBe(false);\n expect(result.current.messageCount).toBe(0);\n });\n});\n"]}
|
|
@@ -99,7 +99,7 @@ export declare function createRunStream(params: CreateRunStreamParams): Promise<
|
|
|
99
99
|
* @example
|
|
100
100
|
* ```tsx
|
|
101
101
|
* function ChatInput({ threadId }: { threadId?: string }) {
|
|
102
|
-
* const sendMessage =
|
|
102
|
+
* const sendMessage = useTamboSendMessage(threadId);
|
|
103
103
|
*
|
|
104
104
|
* const handleSubmit = async (text: string) => {
|
|
105
105
|
* const result = await sendMessage.mutateAsync({
|
|
@@ -124,10 +124,10 @@ export declare function createRunStream(params: CreateRunStreamParams): Promise<
|
|
|
124
124
|
* }
|
|
125
125
|
* ```
|
|
126
126
|
*/
|
|
127
|
-
export declare function
|
|
127
|
+
export declare function useTamboSendMessage(threadId?: string): import("@tanstack/react-query").UseMutationResult<{
|
|
128
128
|
threadId: string | undefined;
|
|
129
129
|
preMutationMessageCount: number;
|
|
130
|
-
|
|
130
|
+
threadAlreadyHasName: boolean;
|
|
131
131
|
}, Error, SendMessageOptions, unknown>;
|
|
132
132
|
export {};
|
|
133
133
|
//# sourceMappingURL=use-tambo-v1-send-message.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tambo-v1-send-message.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-send-message.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AAMtE,OAAO,EAEL,KAAK,oBAAoB,IAAI,aAAa,EAC3C,MAAM,yCAAyC,CAAC;AAQjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"use-tambo-v1-send-message.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-send-message.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yCAAyC,CAAC;AAMtE,OAAO,EAEL,KAAK,oBAAoB,IAAI,aAAa,EAC3C,MAAM,yCAAyC,CAAC;AAQjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AA6MvD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B;;;OAGG;IACH,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C;;OAEG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACzC;AAED;;GAEG;AACH,KAAK,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;AAC7D,KAAK,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,SAAS,GAAG,YAAY,CAAC;IACjC,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAgFD;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC,CA4DhC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,CAAC,EAAE,MAAM;;;;uCA+PpD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
/**
|
|
3
|
-
* Send Message Hook
|
|
3
|
+
* Send Message Hook
|
|
4
4
|
*
|
|
5
5
|
* React Query mutation hook for sending messages and handling streaming responses.
|
|
6
6
|
*/
|
|
@@ -11,8 +11,8 @@ import { useTamboClient, useTamboQueryClient, } from "../../providers/tambo-clie
|
|
|
11
11
|
import { useTamboMutation } from "../../hooks/react-query-hooks.js";
|
|
12
12
|
import { TamboRegistryContext, } from "../../providers/tambo-registry-provider.js";
|
|
13
13
|
import { useStreamDispatch, useStreamState, } from "../providers/tambo-v1-stream-context.js";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { useTamboConfig } from "../providers/tambo-v1-provider.js";
|
|
15
|
+
import { useTamboAuthState } from "./use-tambo-v1-auth-state.js";
|
|
16
16
|
import { useTamboContextHelpers } from "../../providers/tambo-context-helpers-provider.js";
|
|
17
17
|
import { isPlaceholderThreadId, } from "../utils/event-accumulator.js";
|
|
18
18
|
import { toAvailableComponents, toAvailableTools, } from "../utils/registry-conversion.js";
|
|
@@ -103,13 +103,13 @@ function dispatchToolResults(dispatch, targetThreadId, toolResults) {
|
|
|
103
103
|
* Checks whether a thread name should be auto-generated based on config
|
|
104
104
|
* and the current thread state.
|
|
105
105
|
* @param threadId - The thread ID (undefined or placeholder means no)
|
|
106
|
-
* @param
|
|
106
|
+
* @param threadAlreadyHasName - Whether the thread already has a name
|
|
107
107
|
* @param preMutationMessageCount - Message count before the current mutation
|
|
108
108
|
* @param autoGenerateNameThreshold - Minimum message count to trigger generation
|
|
109
109
|
* @returns Whether to generate a thread name
|
|
110
110
|
*/
|
|
111
|
-
function shouldGenerateThreadName(threadId,
|
|
112
|
-
return (!
|
|
111
|
+
function shouldGenerateThreadName(threadId, threadAlreadyHasName, preMutationMessageCount, autoGenerateNameThreshold) {
|
|
112
|
+
return (!threadAlreadyHasName &&
|
|
113
113
|
!!threadId &&
|
|
114
114
|
!isPlaceholderThreadId(threadId) &&
|
|
115
115
|
// +2 accounts for the user message and assistant response just added
|
|
@@ -143,7 +143,7 @@ function parseToolCallArgs(toolTracker, toolCallId) {
|
|
|
143
143
|
return undefined;
|
|
144
144
|
}
|
|
145
145
|
/**
|
|
146
|
-
* Generates a thread name via the beta API, dispatches the
|
|
146
|
+
* Generates a thread name via the beta API, dispatches the name update,
|
|
147
147
|
* and invalidates the thread list cache. Errors are logged, never thrown.
|
|
148
148
|
* @param client - The Tambo API client
|
|
149
149
|
* @param dispatch - Stream state dispatcher
|
|
@@ -155,9 +155,9 @@ async function generateThreadName(client, dispatch, queryClient, threadId) {
|
|
|
155
155
|
const threadWithName = await client.beta.threads.generateName(threadId);
|
|
156
156
|
if (threadWithName.name) {
|
|
157
157
|
dispatch({
|
|
158
|
-
type: "
|
|
158
|
+
type: "UPDATE_THREAD_NAME",
|
|
159
159
|
threadId,
|
|
160
|
-
|
|
160
|
+
name: threadWithName.name,
|
|
161
161
|
});
|
|
162
162
|
await queryClient.invalidateQueries({
|
|
163
163
|
queryKey: ["v1-threads", "list"],
|
|
@@ -165,7 +165,7 @@ async function generateThreadName(client, dispatch, queryClient, threadId) {
|
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
167
|
catch (error) {
|
|
168
|
-
console.error("[
|
|
168
|
+
console.error("[useTamboSendMessage] Failed to auto-generate thread name:", error);
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
/**
|
|
@@ -220,7 +220,7 @@ export async function createRunStream(params) {
|
|
|
220
220
|
const messageWithContext = mergedContext
|
|
221
221
|
? { ...message, additionalContext: mergedContext }
|
|
222
222
|
: message;
|
|
223
|
-
// Convert registry components/tools to
|
|
223
|
+
// Convert registry components/tools to API format
|
|
224
224
|
const availableComponents = toAvailableComponents(registry.componentList);
|
|
225
225
|
const availableTools = toAvailableTools(registry.toolRegistry);
|
|
226
226
|
if (threadId) {
|
|
@@ -237,8 +237,6 @@ export async function createRunStream(params) {
|
|
|
237
237
|
}
|
|
238
238
|
else {
|
|
239
239
|
// Create new thread - include initialMessages if provided
|
|
240
|
-
// Cast to InputMessage[] at the SDK boundary: the V1 API accepts system/assistant roles
|
|
241
|
-
// but the TS SDK type constrains role to 'user'. Remove cast when typescript-sdk is regenerated.
|
|
242
240
|
const threadConfig = {};
|
|
243
241
|
if (userKey) {
|
|
244
242
|
threadConfig.userKey = userKey;
|
|
@@ -276,7 +274,7 @@ export async function createRunStream(params) {
|
|
|
276
274
|
* @example
|
|
277
275
|
* ```tsx
|
|
278
276
|
* function ChatInput({ threadId }: { threadId?: string }) {
|
|
279
|
-
* const sendMessage =
|
|
277
|
+
* const sendMessage = useTamboSendMessage(threadId);
|
|
280
278
|
*
|
|
281
279
|
* const handleSubmit = async (text: string) => {
|
|
282
280
|
* const result = await sendMessage.mutateAsync({
|
|
@@ -301,17 +299,17 @@ export async function createRunStream(params) {
|
|
|
301
299
|
* }
|
|
302
300
|
* ```
|
|
303
301
|
*/
|
|
304
|
-
export function
|
|
302
|
+
export function useTamboSendMessage(threadId) {
|
|
305
303
|
const client = useTamboClient();
|
|
306
304
|
const dispatch = useStreamDispatch();
|
|
307
305
|
const streamState = useStreamState();
|
|
308
|
-
const { userKey, autoGenerateThreadName = true, autoGenerateNameThreshold = 3, initialMessages, } =
|
|
306
|
+
const { userKey, autoGenerateThreadName = true, autoGenerateNameThreshold = 3, initialMessages, } = useTamboConfig();
|
|
309
307
|
const registry = useContext(TamboRegistryContext);
|
|
310
308
|
const queryClient = useTamboQueryClient();
|
|
311
309
|
const { getAdditionalContext } = useTamboContextHelpers();
|
|
312
|
-
const authState =
|
|
310
|
+
const authState = useTamboAuthState();
|
|
313
311
|
if (!registry) {
|
|
314
|
-
throw new Error("
|
|
312
|
+
throw new Error("useTamboSendMessage must be used within TamboRegistryProvider");
|
|
315
313
|
}
|
|
316
314
|
// Placeholder ID isn't a valid API thread ID - treat as new thread creation
|
|
317
315
|
const isNewThread = isPlaceholderThreadId(threadId);
|
|
@@ -328,7 +326,7 @@ export function useTamboV1SendMessage(threadId) {
|
|
|
328
326
|
if (authState.status !== "identified") {
|
|
329
327
|
const messages = {
|
|
330
328
|
unauthenticated: "Cannot send message: no userKey or userToken provided. " +
|
|
331
|
-
"Configure authentication in
|
|
329
|
+
"Configure authentication in TamboProvider.",
|
|
332
330
|
exchanging: "Cannot send message: token exchange is still in progress. " +
|
|
333
331
|
"Wait for authentication to complete.",
|
|
334
332
|
error: "Cannot send message: token exchange failed. " +
|
|
@@ -342,7 +340,7 @@ export function useTamboV1SendMessage(threadId) {
|
|
|
342
340
|
// Capture pre-mutation state for auto thread name generation
|
|
343
341
|
const existingThread = streamState.threadMap[apiThreadId ?? ""];
|
|
344
342
|
const preMutationMessageCount = existingThread?.thread.messages.length ?? 0;
|
|
345
|
-
const
|
|
343
|
+
const threadAlreadyHasName = !!existingThread?.thread.name;
|
|
346
344
|
const toolTracker = new ToolCallTracker();
|
|
347
345
|
const throttledStreamable = createThrottledStreamableExecutor(toolTracker, registry.toolRegistry);
|
|
348
346
|
// Generate a stable message ID for the user message
|
|
@@ -456,7 +454,7 @@ export function useTamboV1SendMessage(threadId) {
|
|
|
456
454
|
return {
|
|
457
455
|
threadId: actualThreadId,
|
|
458
456
|
preMutationMessageCount,
|
|
459
|
-
|
|
457
|
+
threadAlreadyHasName,
|
|
460
458
|
};
|
|
461
459
|
}
|
|
462
460
|
catch (error) {
|
|
@@ -482,12 +480,12 @@ export function useTamboV1SendMessage(threadId) {
|
|
|
482
480
|
queryKey: ["v1-threads", result.threadId],
|
|
483
481
|
});
|
|
484
482
|
if (autoGenerateThreadName &&
|
|
485
|
-
shouldGenerateThreadName(result.threadId, result.
|
|
483
|
+
shouldGenerateThreadName(result.threadId, result.threadAlreadyHasName, result.preMutationMessageCount, autoGenerateNameThreshold)) {
|
|
486
484
|
await generateThreadName(client, dispatch, queryClient, result.threadId);
|
|
487
485
|
}
|
|
488
486
|
},
|
|
489
487
|
onError: (error) => {
|
|
490
|
-
console.error("[
|
|
488
|
+
console.error("[useTamboSendMessage] Mutation failed:", error);
|
|
491
489
|
},
|
|
492
490
|
});
|
|
493
491
|
}
|
|
@@ -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 { 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"]}
|
|
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\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 { useTamboConfig } from \"../providers/tambo-v1-provider\";\nimport { useTamboAuthState } 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 type { RunCreateParams } from \"@tambo-ai/typescript-sdk/resources/threads/runs\";\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 threadAlreadyHasName - Whether the thread already has a name\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 threadAlreadyHasName: boolean,\n preMutationMessageCount: number,\n autoGenerateNameThreshold: number,\n): threadId is string {\n return (\n !threadAlreadyHasName &&\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 name 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_NAME\",\n threadId,\n name: threadWithName.name,\n });\n await queryClient.invalidateQueries({\n queryKey: [\"v1-threads\", \"list\"],\n });\n }\n } catch (error) {\n console.error(\n \"[useTamboSendMessage] 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 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 const threadConfig: RunCreateParams.Thread = {};\n if (userKey) {\n threadConfig.userKey = userKey;\n }\n if (initialMessages?.length) {\n threadConfig.initialMessages = initialMessages;\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 = useTamboSendMessage(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 useTamboSendMessage(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 } = useTamboConfig();\n const registry = useContext(TamboRegistryContext);\n const queryClient = useTamboQueryClient();\n const { getAdditionalContext } = useTamboContextHelpers();\n const authState = useTamboAuthState();\n\n if (!registry) {\n throw new Error(\n \"useTamboSendMessage 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 TamboProvider.\",\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 threadAlreadyHasName = !!existingThread?.thread.name;\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 threadAlreadyHasName,\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.threadAlreadyHasName,\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(\"[useTamboSendMessage] Mutation failed:\", error);\n },\n });\n}\n"]}
|