@tambo-ai/react 0.73.0 → 0.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -12
- package/dist/hooks/use-component-state.d.ts +1 -1
- package/dist/hooks/use-component-state.js.map +1 -1
- package/dist/hooks/use-streaming-props.d.ts +1 -1
- package/dist/hooks/use-streaming-props.js +1 -1
- package/dist/hooks/use-streaming-props.js.map +1 -1
- package/dist/hooks/use-tambo-stream-status.d.ts +1 -1
- package/dist/hooks/use-tambo-stream-status.js +1 -1
- package/dist/hooks/use-tambo-stream-status.js.map +1 -1
- package/dist/mcp/mcp-hooks.d.ts +4 -0
- package/dist/mcp/mcp-hooks.d.ts.map +1 -1
- package/dist/mcp/mcp-hooks.js +4 -0
- package/dist/mcp/mcp-hooks.js.map +1 -1
- package/dist/providers/tambo-interactable-provider-partial-updates.test.js +3 -3
- package/dist/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +2 -2
- package/dist/providers/tambo-interactable-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.test.js +3 -3
- package/dist/providers/tambo-interactable-provider.test.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts +3 -0
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js +3 -0
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-input-provider.js +1 -0
- package/dist/providers/tambo-thread-input-provider.js.map +1 -1
- package/dist/util/resource-content-resolver.d.ts.map +1 -1
- package/dist/util/resource-content-resolver.js +2 -0
- package/dist/util/resource-content-resolver.js.map +1 -1
- package/dist/v1/__tests__/v1-interactables.test.d.ts +2 -0
- package/dist/v1/__tests__/v1-interactables.test.d.ts.map +1 -0
- package/dist/v1/__tests__/v1-interactables.test.js +135 -0
- package/dist/v1/__tests__/v1-interactables.test.js.map +1 -0
- package/dist/v1/components/v1-component-renderer.d.ts +48 -0
- package/dist/v1/components/v1-component-renderer.d.ts.map +1 -0
- package/dist/v1/components/v1-component-renderer.js +137 -0
- package/dist/v1/components/v1-component-renderer.js.map +1 -0
- package/dist/v1/components/v1-component-renderer.test.d.ts +2 -0
- package/dist/v1/components/v1-component-renderer.test.d.ts.map +1 -0
- package/dist/v1/components/v1-component-renderer.test.js +270 -0
- package/dist/v1/components/v1-component-renderer.test.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.js +2 -25
- package/dist/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.test.js +2 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.test.js +25 -1
- package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +18 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.js +204 -17
- package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js +261 -7
- 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 +90 -0
- package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-stream-status.js +179 -0
- package/dist/v1/hooks/use-tambo-v1-stream-status.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.d.ts +2 -0
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.js +371 -0
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts +78 -54
- package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-suggestions.js +153 -87
- package/dist/v1/hooks/use-tambo-v1-suggestions.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-suggestions.test.js +213 -134
- package/dist/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +148 -13
- 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 +8 -21
- package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.js +11 -10
- package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +37 -2
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.d.ts +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.js +2 -7
- package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.test.js +2 -0
- package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.d.ts +12 -28
- package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.js +164 -31
- package/dist/v1/hooks/use-tambo-v1.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.test.js +891 -18
- package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/dist/v1/index.d.ts +7 -1
- package/dist/v1/index.d.ts.map +1 -1
- package/dist/v1/index.js +18 -1
- package/dist/v1/index.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.d.ts +16 -6
- package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.js +14 -19
- package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.test.js +34 -20
- package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.d.ts +3 -3
- package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.js +60 -12
- package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.test.js +49 -20
- package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.js +2 -0
- package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.test.js +7 -6
- package/dist/v1/providers/tambo-v1-stub-provider.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +1 -6
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.js +14 -12
- package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
- package/dist/v1/types/event.d.ts +9 -1
- package/dist/v1/types/event.d.ts.map +1 -1
- package/dist/v1/types/event.js.map +1 -1
- package/dist/v1/types/event.test.js +5 -1
- package/dist/v1/types/event.test.js.map +1 -1
- package/dist/v1/types/message.d.ts +65 -7
- package/dist/v1/types/message.d.ts.map +1 -1
- package/dist/v1/types/message.js.map +1 -1
- package/dist/v1/types/thread.d.ts +4 -0
- package/dist/v1/types/thread.d.ts.map +1 -1
- package/dist/v1/types/thread.js.map +1 -1
- package/dist/v1/utils/event-accumulator.d.ts +40 -4
- package/dist/v1/utils/event-accumulator.d.ts.map +1 -1
- package/dist/v1/utils/event-accumulator.js +444 -35
- package/dist/v1/utils/event-accumulator.js.map +1 -1
- package/dist/v1/utils/event-accumulator.test.js +1041 -28
- package/dist/v1/utils/event-accumulator.test.js.map +1 -1
- package/dist/v1/utils/registry-conversion.d.ts +9 -9
- package/dist/v1/utils/registry-conversion.d.ts.map +1 -1
- package/dist/v1/utils/registry-conversion.js +10 -11
- package/dist/v1/utils/registry-conversion.js.map +1 -1
- package/dist/v1/utils/registry-conversion.test.js +39 -11
- package/dist/v1/utils/registry-conversion.test.js.map +1 -1
- package/dist/v1/utils/thread-utils.d.ts +16 -0
- package/dist/v1/utils/thread-utils.d.ts.map +1 -0
- package/dist/v1/utils/thread-utils.js +34 -0
- package/dist/v1/utils/thread-utils.js.map +1 -0
- package/dist/v1/utils/tool-executor.d.ts.map +1 -1
- package/dist/v1/utils/tool-executor.js +2 -0
- package/dist/v1/utils/tool-executor.js.map +1 -1
- package/dist/v1/utils/tool-executor.test.js +5 -0
- package/dist/v1/utils/tool-executor.test.js.map +1 -1
- package/esm/context-helpers/context-helpers-provider.test.js +2 -2
- package/esm/context-helpers/context-helpers.test.js +1 -1
- package/esm/context-helpers/current-interactables-context-helper.d.ts +1 -1
- package/esm/context-helpers/current-page-context-helper.d.ts +1 -1
- package/esm/context-helpers/current-time-context-helper.d.ts +1 -1
- package/esm/context-helpers/index.d.ts +4 -4
- package/esm/context-helpers/index.js +4 -4
- package/esm/hoc/with-tambo-interactable.d.ts +1 -1
- package/esm/hoc/with-tambo-interactable.js +2 -2
- package/esm/hoc/with-tambo-interactable.test.js +3 -3
- package/esm/hooks/index.d.ts +8 -8
- package/esm/hooks/index.js +8 -8
- package/esm/hooks/react-query-hooks.js +1 -1
- package/esm/hooks/use-component-state.d.ts +1 -1
- package/esm/hooks/use-component-state.js +3 -3
- package/esm/hooks/use-component-state.js.map +1 -1
- package/esm/hooks/use-component-state.test.js +5 -5
- package/esm/hooks/use-current-message.d.ts +1 -1
- package/esm/hooks/use-current-message.test.js +1 -1
- package/esm/hooks/use-message-images.test.js +1 -1
- package/esm/hooks/use-streaming-props.d.ts +1 -1
- package/esm/hooks/use-streaming-props.js +1 -1
- package/esm/hooks/use-streaming-props.js.map +1 -1
- package/esm/hooks/use-suggestions.d.ts +2 -2
- package/esm/hooks/use-suggestions.js +10 -10
- package/esm/hooks/use-suggestions.test.js +7 -7
- package/esm/hooks/use-tambo-stream-status.d.ts +1 -1
- package/esm/hooks/use-tambo-stream-status.js +4 -4
- package/esm/hooks/use-tambo-stream-status.js.map +1 -1
- package/esm/hooks/use-tambo-stream-status.test.js +4 -4
- package/esm/hooks/use-tambo-threads.js +3 -3
- package/esm/hooks/use-tambo-threads.test.js +3 -3
- package/esm/hooks/use-tambo-voice.js +2 -2
- package/esm/hooks/use-tambo-voice.test.js +3 -3
- package/esm/index.d.ts +22 -22
- package/esm/index.js +15 -15
- package/esm/mcp/elicitation.d.ts +1 -1
- package/esm/mcp/elicitation.test.js +1 -1
- package/esm/mcp/index.d.ts +7 -7
- package/esm/mcp/index.js +3 -3
- package/esm/mcp/mcp-client.d.ts +1 -1
- package/esm/mcp/mcp-client.js +1 -1
- package/esm/mcp/mcp-client.test.js +1 -1
- package/esm/mcp/mcp-hooks.d.ts +5 -1
- package/esm/mcp/mcp-hooks.d.ts.map +1 -1
- package/esm/mcp/mcp-hooks.js +8 -4
- package/esm/mcp/mcp-hooks.js.map +1 -1
- package/esm/mcp/mcp-hooks.test.js +6 -6
- package/esm/mcp/tambo-mcp-provider.d.ts +4 -4
- package/esm/mcp/tambo-mcp-provider.js +7 -7
- package/esm/mcp/tambo-mcp-provider.test.js +5 -5
- package/esm/mcp/use-mcp-servers.test.js +4 -4
- package/esm/model/generate-component-response.d.ts +1 -1
- package/esm/model/tambo-interactable.d.ts +1 -1
- package/esm/model/tambo-thread.d.ts +1 -1
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js +3 -3
- package/esm/providers/hooks/use-tambo-session-token.test.js +1 -1
- package/esm/providers/index.d.ts +12 -12
- package/esm/providers/index.js +10 -10
- package/esm/providers/tambo-client-provider.js +1 -1
- package/esm/providers/tambo-client-provider.test.js +2 -2
- package/esm/providers/tambo-component-provider.d.ts +1 -1
- package/esm/providers/tambo-component-provider.js +2 -2
- package/esm/providers/tambo-context-attachment-provider.js +1 -1
- package/esm/providers/tambo-context-attachment-provider.test.js +2 -2
- package/esm/providers/tambo-context-helpers-provider.d.ts +1 -1
- package/esm/providers/tambo-context-helpers-provider.js +1 -1
- package/esm/providers/tambo-context-helpers-provider.test.js +2 -2
- package/esm/providers/tambo-interactable-provider-partial-updates.test.js +4 -4
- package/esm/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts +5 -5
- package/esm/providers/tambo-interactable-provider.js +6 -6
- package/esm/providers/tambo-interactable-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.test.js +4 -4
- package/esm/providers/tambo-interactable-provider.test.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js +4 -4
- package/esm/providers/tambo-interactables-additional-context.test.js +4 -4
- package/esm/providers/tambo-mcp-token-provider.js +2 -2
- package/esm/providers/tambo-prop-stream-provider/index.d.ts +8 -8
- package/esm/providers/tambo-prop-stream-provider/index.js +9 -9
- package/esm/providers/tambo-prop-stream-provider/pending.d.ts +1 -1
- package/esm/providers/tambo-prop-stream-provider/pending.js +2 -2
- package/esm/providers/tambo-prop-stream-provider/provider.d.ts +1 -1
- package/esm/providers/tambo-prop-stream-provider/provider.js +2 -2
- package/esm/providers/tambo-prop-stream-provider/streaming.d.ts +1 -1
- package/esm/providers/tambo-prop-stream-provider/streaming.js +2 -2
- package/esm/providers/tambo-prop-stream-provider/success.d.ts +1 -1
- package/esm/providers/tambo-prop-stream-provider/success.js +2 -2
- package/esm/providers/tambo-prop-stream-provider/types.d.ts +1 -1
- package/esm/providers/tambo-prop-stream-provider.test.js +4 -4
- package/esm/providers/tambo-provider.d.ts +10 -7
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js +13 -10
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-registry-provider.d.ts +3 -3
- package/esm/providers/tambo-registry-provider.js +3 -3
- package/esm/providers/tambo-registry-provider.test.js +2 -2
- package/esm/providers/tambo-registry-schema-compat.test.js +2 -2
- package/esm/providers/tambo-stubs.d.ts +4 -4
- package/esm/providers/tambo-stubs.js +9 -9
- package/esm/providers/tambo-stubs.test.js +2 -2
- package/esm/providers/tambo-thread-input-provider.d.ts +2 -2
- package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-input-provider.js +11 -10
- package/esm/providers/tambo-thread-input-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider-initial-messages.test.js +6 -6
- package/esm/providers/tambo-thread-provider.d.ts +2 -2
- package/esm/providers/tambo-thread-provider.js +8 -8
- package/esm/providers/tambo-thread-provider.test.js +7 -7
- package/esm/schema/index.d.ts +4 -4
- package/esm/schema/index.js +4 -4
- package/esm/schema/json-schema.test.js +1 -1
- package/esm/schema/schema.d.ts +1 -1
- package/esm/schema/schema.js +2 -2
- package/esm/schema/schema.test.js +3 -3
- package/esm/schema/standard-schema.test.js +1 -1
- package/esm/schema/validate.js +2 -2
- package/esm/schema/validate.test.js +1 -1
- package/esm/testing/tools.d.ts +3 -3
- package/esm/testing/tools.js +2 -2
- package/esm/util/content-parts.test.js +1 -1
- package/esm/util/generate-component.d.ts +2 -2
- package/esm/util/generate-component.js +4 -4
- package/esm/util/generate-component.test.js +2 -2
- package/esm/util/is-promise.test.js +1 -1
- package/esm/util/mcp-server-utils.d.ts +1 -1
- package/esm/util/mcp-server-utils.js +1 -1
- package/esm/util/mcp-server-utils.test.js +2 -2
- package/esm/util/message-builder.d.ts +1 -1
- package/esm/util/message-builder.test.js +1 -1
- package/esm/util/query-utils.test.js +1 -1
- package/esm/util/registry-validators.d.ts +1 -1
- package/esm/util/registry-validators.js +2 -2
- package/esm/util/registry-validators.test.js +1 -1
- package/esm/util/registry.d.ts +1 -1
- package/esm/util/registry.js +1 -1
- package/esm/util/registry.test.js +2 -2
- package/esm/util/resource-content-resolver.d.ts +2 -2
- package/esm/util/resource-content-resolver.d.ts.map +1 -1
- package/esm/util/resource-content-resolver.js +3 -1
- package/esm/util/resource-content-resolver.js.map +1 -1
- package/esm/util/resource-content-resolver.test.js +3 -3
- package/esm/util/resource-validators.d.ts +1 -1
- package/esm/util/resource-validators.test.js +1 -1
- package/esm/util/tool-caller.d.ts +1 -1
- package/esm/util/tool-caller.js +1 -1
- package/esm/util/validate-component-name.test.js +1 -1
- package/esm/v1/__tests__/v1-interactables.test.d.ts +2 -0
- package/esm/v1/__tests__/v1-interactables.test.d.ts.map +1 -0
- package/esm/v1/__tests__/v1-interactables.test.js +130 -0
- package/esm/v1/__tests__/v1-interactables.test.js.map +1 -0
- package/esm/v1/components/v1-component-renderer.d.ts +48 -0
- package/esm/v1/components/v1-component-renderer.d.ts.map +1 -0
- package/esm/v1/components/v1-component-renderer.js +100 -0
- package/esm/v1/components/v1-component-renderer.js.map +1 -0
- package/esm/v1/components/v1-component-renderer.test.d.ts +2 -0
- package/esm/v1/components/v1-component-renderer.test.d.ts.map +1 -0
- package/esm/v1/components/v1-component-renderer.test.js +265 -0
- package/esm/v1/components/v1-component-renderer.test.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.js +4 -27
- package/esm/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.test.js +6 -5
- package/esm/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.d.ts +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.js +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.test.js +27 -3
- package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +20 -2
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.js +213 -26
- package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js +266 -12
- 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 +90 -0
- package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-stream-status.js +176 -0
- package/esm/v1/hooks/use-tambo-v1-stream-status.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.d.ts +2 -0
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.js +369 -0
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts +78 -54
- package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-suggestions.js +157 -91
- package/esm/v1/hooks/use-tambo-v1-suggestions.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-suggestions.test.js +218 -139
- package/esm/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.js +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +151 -16
- 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 +8 -21
- package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.js +12 -11
- package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +39 -4
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.d.ts +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.js +3 -8
- package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.test.js +4 -2
- package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.d.ts +15 -31
- package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.js +134 -34
- package/esm/v1/hooks/use-tambo-v1.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.test.js +862 -19
- package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/esm/v1/index.d.ts +28 -22
- package/esm/v1/index.d.ts.map +1 -1
- package/esm/v1/index.js +30 -18
- package/esm/v1/index.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.d.ts +21 -11
- package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.js +20 -25
- package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.test.js +40 -26
- package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.d.ts +4 -4
- package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.js +62 -14
- package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.test.js +50 -21
- package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.d.ts +3 -3
- package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.js +7 -5
- package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.test.js +12 -11
- package/esm/v1/providers/tambo-v1-stub-provider.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +3 -8
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.js +18 -16
- package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
- package/esm/v1/types/event.d.ts +9 -1
- package/esm/v1/types/event.d.ts.map +1 -1
- package/esm/v1/types/event.js.map +1 -1
- package/esm/v1/types/event.test.js +6 -2
- package/esm/v1/types/event.test.js.map +1 -1
- package/esm/v1/types/message.d.ts +65 -7
- package/esm/v1/types/message.d.ts.map +1 -1
- package/esm/v1/types/message.js.map +1 -1
- package/esm/v1/types/thread.d.ts +5 -1
- package/esm/v1/types/thread.d.ts.map +1 -1
- package/esm/v1/types/thread.js.map +1 -1
- package/esm/v1/utils/component-renderer.test.js +1 -1
- package/esm/v1/utils/event-accumulator.d.ts +41 -5
- package/esm/v1/utils/event-accumulator.d.ts.map +1 -1
- package/esm/v1/utils/event-accumulator.js +444 -36
- package/esm/v1/utils/event-accumulator.js.map +1 -1
- package/esm/v1/utils/event-accumulator.test.js +1042 -29
- package/esm/v1/utils/event-accumulator.test.js.map +1 -1
- package/esm/v1/utils/json-patch.test.js +1 -1
- package/esm/v1/utils/registry-conversion.d.ts +9 -9
- package/esm/v1/utils/registry-conversion.d.ts.map +1 -1
- package/esm/v1/utils/registry-conversion.js +11 -12
- package/esm/v1/utils/registry-conversion.js.map +1 -1
- package/esm/v1/utils/registry-conversion.test.js +40 -12
- package/esm/v1/utils/registry-conversion.test.js.map +1 -1
- package/esm/v1/utils/stream-handler.test.js +1 -1
- package/esm/v1/utils/thread-utils.d.ts +16 -0
- package/esm/v1/utils/thread-utils.d.ts.map +1 -0
- package/esm/v1/utils/thread-utils.js +31 -0
- package/esm/v1/utils/thread-utils.js.map +1 -0
- package/esm/v1/utils/tool-call-tracker.d.ts +1 -1
- package/esm/v1/utils/tool-executor.d.ts +1 -1
- package/esm/v1/utils/tool-executor.d.ts.map +1 -1
- package/esm/v1/utils/tool-executor.js +2 -0
- package/esm/v1/utils/tool-executor.js.map +1 -1
- package/esm/v1/utils/tool-executor.test.js +6 -1
- package/esm/v1/utils/tool-executor.test.js.map +1 -1
- package/package.json +11 -10
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* Used with useReducer to accumulate events into thread state.
|
|
6
6
|
*/
|
|
7
7
|
import { EventType } from "@ag-ui/core";
|
|
8
|
-
import { asTamboCustomEvent, } from "../types/event";
|
|
9
|
-
import {
|
|
8
|
+
import { asTamboCustomEvent, } from "../types/event.js";
|
|
9
|
+
import { parse as parsePartialJson } from "partial-json";
|
|
10
|
+
import { applyJsonPatch } from "./json-patch.js";
|
|
10
11
|
/**
|
|
11
12
|
* Error thrown when an unreachable case is reached in a switch statement.
|
|
12
13
|
* This indicates a programming error where not all cases were handled.
|
|
@@ -37,19 +38,36 @@ export function createInitialThreadState(threadId) {
|
|
|
37
38
|
status: "idle",
|
|
38
39
|
createdAt: now,
|
|
39
40
|
updatedAt: now,
|
|
41
|
+
lastRunCancelled: false,
|
|
40
42
|
},
|
|
41
43
|
streaming: initialStreamingState,
|
|
42
44
|
accumulatingToolArgs: new Map(),
|
|
43
45
|
};
|
|
44
46
|
}
|
|
45
47
|
/**
|
|
46
|
-
*
|
|
48
|
+
* Placeholder thread ID used for new threads before they get a real ID from the server.
|
|
49
|
+
* This allows optimistic UI updates (showing user messages immediately) before the
|
|
50
|
+
* server responds with the actual thread ID.
|
|
51
|
+
*/
|
|
52
|
+
export const PLACEHOLDER_THREAD_ID = "placeholder";
|
|
53
|
+
/**
|
|
54
|
+
* Check if a thread ID is a placeholder (not a real API thread ID).
|
|
55
|
+
* @param threadId - Thread ID to check
|
|
56
|
+
* @returns True if this is a placeholder thread ID
|
|
57
|
+
*/
|
|
58
|
+
export function isPlaceholderThreadId(threadId) {
|
|
59
|
+
return threadId === PLACEHOLDER_THREAD_ID;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create initial stream state with placeholder thread.
|
|
47
63
|
* @returns Initial stream state
|
|
48
64
|
*/
|
|
49
65
|
export function createInitialState() {
|
|
50
66
|
return {
|
|
51
|
-
threadMap: {
|
|
52
|
-
|
|
67
|
+
threadMap: {
|
|
68
|
+
[PLACEHOLDER_THREAD_ID]: createInitialThreadState(PLACEHOLDER_THREAD_ID),
|
|
69
|
+
},
|
|
70
|
+
currentThreadId: PLACEHOLDER_THREAD_ID,
|
|
53
71
|
};
|
|
54
72
|
}
|
|
55
73
|
/**
|
|
@@ -193,28 +211,85 @@ export function streamReducer(state, action) {
|
|
|
193
211
|
currentThreadId: threadId,
|
|
194
212
|
};
|
|
195
213
|
}
|
|
214
|
+
case "LOAD_THREAD_MESSAGES": {
|
|
215
|
+
return handleLoadThreadMessages(state, action);
|
|
216
|
+
}
|
|
217
|
+
case "UPDATE_THREAD_TITLE": {
|
|
218
|
+
const threadState = state.threadMap[action.threadId];
|
|
219
|
+
if (!threadState) {
|
|
220
|
+
return state;
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
...state,
|
|
224
|
+
threadMap: {
|
|
225
|
+
...state.threadMap,
|
|
226
|
+
[action.threadId]: {
|
|
227
|
+
...threadState,
|
|
228
|
+
thread: {
|
|
229
|
+
...threadState.thread,
|
|
230
|
+
title: action.title,
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
196
236
|
case "EVENT":
|
|
197
237
|
// Fall through to event handling below
|
|
198
238
|
break;
|
|
199
239
|
}
|
|
200
240
|
// Handle EVENT action
|
|
201
241
|
const { event, threadId } = action;
|
|
242
|
+
const effectiveThreadId = event.type === EventType.RUN_STARTED ? event.threadId : threadId;
|
|
202
243
|
// Get the current thread state, auto-initializing if needed
|
|
203
244
|
// Auto-initialization handles the case where events arrive before explicit thread init
|
|
204
245
|
// (e.g., when creating a new thread and RUN_STARTED is the first event)
|
|
205
|
-
let threadState = state.threadMap[
|
|
246
|
+
let threadState = state.threadMap[effectiveThreadId];
|
|
206
247
|
let updatedState = state;
|
|
207
248
|
if (!threadState) {
|
|
208
249
|
// Auto-initialize the thread to avoid dropping events
|
|
209
|
-
threadState = createInitialThreadState(
|
|
250
|
+
threadState = createInitialThreadState(effectiveThreadId);
|
|
210
251
|
updatedState = {
|
|
211
252
|
...state,
|
|
212
253
|
threadMap: {
|
|
213
254
|
...state.threadMap,
|
|
214
|
-
[
|
|
255
|
+
[effectiveThreadId]: threadState,
|
|
215
256
|
},
|
|
216
257
|
};
|
|
217
258
|
}
|
|
259
|
+
// Handle placeholder thread migration for RUN_STARTED events
|
|
260
|
+
// When a new thread is created, messages may have been added to the placeholder thread
|
|
261
|
+
// for immediate UI feedback. Now that we have the real threadId, migrate those messages.
|
|
262
|
+
if (event.type === EventType.RUN_STARTED &&
|
|
263
|
+
effectiveThreadId !== PLACEHOLDER_THREAD_ID) {
|
|
264
|
+
const placeholderState = updatedState.threadMap[PLACEHOLDER_THREAD_ID];
|
|
265
|
+
if (placeholderState?.thread.messages.length) {
|
|
266
|
+
// Prepend placeholder thread messages to the real thread
|
|
267
|
+
threadState = {
|
|
268
|
+
...threadState,
|
|
269
|
+
thread: {
|
|
270
|
+
...threadState.thread,
|
|
271
|
+
messages: [
|
|
272
|
+
...placeholderState.thread.messages,
|
|
273
|
+
...threadState.thread.messages,
|
|
274
|
+
],
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
// Reset placeholder thread to empty state
|
|
278
|
+
const resetPlaceholder = createInitialThreadState(PLACEHOLDER_THREAD_ID);
|
|
279
|
+
updatedState = {
|
|
280
|
+
...updatedState,
|
|
281
|
+
threadMap: {
|
|
282
|
+
...updatedState.threadMap,
|
|
283
|
+
[PLACEHOLDER_THREAD_ID]: resetPlaceholder,
|
|
284
|
+
[effectiveThreadId]: threadState,
|
|
285
|
+
},
|
|
286
|
+
// Only switch selection if the user is currently on the placeholder thread
|
|
287
|
+
currentThreadId: isPlaceholderThreadId(updatedState.currentThreadId)
|
|
288
|
+
? effectiveThreadId
|
|
289
|
+
: updatedState.currentThreadId,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
218
293
|
// Process the event for this specific thread
|
|
219
294
|
let updatedThreadState;
|
|
220
295
|
// Switch on event.type - AGUIEvent is a discriminated union so TypeScript
|
|
@@ -253,11 +328,17 @@ export function streamReducer(state, action) {
|
|
|
253
328
|
case EventType.CUSTOM:
|
|
254
329
|
updatedThreadState = handleCustomEvent(threadState, event);
|
|
255
330
|
break;
|
|
256
|
-
// Unsupported AG-UI event types - may be added in future phases
|
|
257
|
-
case EventType.TEXT_MESSAGE_CHUNK:
|
|
258
331
|
case EventType.THINKING_TEXT_MESSAGE_START:
|
|
332
|
+
updatedThreadState = handleThinkingTextMessageStart(threadState, event);
|
|
333
|
+
break;
|
|
259
334
|
case EventType.THINKING_TEXT_MESSAGE_CONTENT:
|
|
335
|
+
updatedThreadState = handleThinkingTextMessageContent(threadState, event);
|
|
336
|
+
break;
|
|
260
337
|
case EventType.THINKING_TEXT_MESSAGE_END:
|
|
338
|
+
updatedThreadState = handleThinkingTextMessageEnd(threadState, event);
|
|
339
|
+
break;
|
|
340
|
+
// Unsupported AG-UI event types - may be added in future phases
|
|
341
|
+
case EventType.TEXT_MESSAGE_CHUNK:
|
|
261
342
|
case EventType.TOOL_CALL_CHUNK:
|
|
262
343
|
case EventType.THINKING_START:
|
|
263
344
|
case EventType.THINKING_END:
|
|
@@ -285,7 +366,7 @@ export function streamReducer(state, action) {
|
|
|
285
366
|
...updatedState,
|
|
286
367
|
threadMap: {
|
|
287
368
|
...updatedState.threadMap,
|
|
288
|
-
[
|
|
369
|
+
[effectiveThreadId]: updatedThreadState,
|
|
289
370
|
},
|
|
290
371
|
};
|
|
291
372
|
}
|
|
@@ -302,6 +383,8 @@ function handleRunStarted(threadState, event) {
|
|
|
302
383
|
...threadState.thread,
|
|
303
384
|
status: "streaming",
|
|
304
385
|
updatedAt: new Date().toISOString(),
|
|
386
|
+
// Reset lastRunCancelled when a new run starts
|
|
387
|
+
lastRunCancelled: false,
|
|
305
388
|
},
|
|
306
389
|
streaming: {
|
|
307
390
|
status: "streaming",
|
|
@@ -332,39 +415,78 @@ function handleRunFinished(threadState, _event) {
|
|
|
332
415
|
}
|
|
333
416
|
/**
|
|
334
417
|
* Handle RUN_ERROR event.
|
|
418
|
+
* Sets lastRunCancelled if the error code is "CANCELLED".
|
|
335
419
|
* @param threadState - Current thread state
|
|
336
420
|
* @param event - Run error event
|
|
337
421
|
* @returns Updated thread state
|
|
338
422
|
*/
|
|
339
423
|
function handleRunError(threadState, event) {
|
|
424
|
+
const isCancelled = event.code === "CANCELLED";
|
|
340
425
|
return {
|
|
341
426
|
...threadState,
|
|
342
427
|
thread: {
|
|
343
428
|
...threadState.thread,
|
|
344
|
-
status
|
|
429
|
+
// Use "idle" status for cancelled runs (not a real error from user perspective)
|
|
430
|
+
status: isCancelled ? "idle" : "error",
|
|
345
431
|
updatedAt: new Date().toISOString(),
|
|
432
|
+
lastRunCancelled: isCancelled,
|
|
346
433
|
},
|
|
347
434
|
streaming: {
|
|
348
435
|
...threadState.streaming,
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
436
|
+
// Use "idle" status for cancelled runs so UI shows as not streaming
|
|
437
|
+
status: isCancelled ? "idle" : "error",
|
|
438
|
+
error: isCancelled
|
|
439
|
+
? undefined
|
|
440
|
+
: {
|
|
441
|
+
message: event.message,
|
|
442
|
+
code: event.code,
|
|
443
|
+
},
|
|
354
444
|
},
|
|
355
445
|
};
|
|
356
446
|
}
|
|
357
447
|
/**
|
|
358
448
|
* Handle TEXT_MESSAGE_START event.
|
|
359
|
-
* Creates a new message
|
|
449
|
+
* Creates a new message or reuses an ephemeral reasoning message.
|
|
360
450
|
* @param threadState - Current thread state
|
|
361
451
|
* @param event - Text message start event
|
|
362
452
|
* @returns Updated thread state
|
|
363
453
|
*/
|
|
364
454
|
function handleTextMessageStart(threadState, event) {
|
|
455
|
+
const isAssistant = event.role !== "user";
|
|
456
|
+
const messages = threadState.thread.messages;
|
|
457
|
+
// For assistant messages, check if there's an ephemeral message with reasoning
|
|
458
|
+
// that we should merge into instead of creating a new message.
|
|
459
|
+
if (isAssistant) {
|
|
460
|
+
const ephemeralIndex = messages.findIndex((m) => m.role === "assistant" &&
|
|
461
|
+
m.id.startsWith("ephemeral_") &&
|
|
462
|
+
m.reasoning &&
|
|
463
|
+
m.reasoning.length > 0);
|
|
464
|
+
if (ephemeralIndex !== -1) {
|
|
465
|
+
// Update the ephemeral message with the real ID
|
|
466
|
+
const ephemeralMessage = messages[ephemeralIndex];
|
|
467
|
+
const updatedMessages = [...messages];
|
|
468
|
+
updatedMessages[ephemeralIndex] = {
|
|
469
|
+
...ephemeralMessage,
|
|
470
|
+
id: event.messageId,
|
|
471
|
+
};
|
|
472
|
+
return {
|
|
473
|
+
...threadState,
|
|
474
|
+
thread: {
|
|
475
|
+
...threadState.thread,
|
|
476
|
+
messages: updatedMessages,
|
|
477
|
+
updatedAt: new Date().toISOString(),
|
|
478
|
+
},
|
|
479
|
+
streaming: {
|
|
480
|
+
...threadState.streaming,
|
|
481
|
+
messageId: event.messageId,
|
|
482
|
+
},
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
// No ephemeral message to reuse - create a new message
|
|
365
487
|
const newMessage = {
|
|
366
488
|
id: event.messageId,
|
|
367
|
-
role:
|
|
489
|
+
role: isAssistant ? "assistant" : "user",
|
|
368
490
|
content: [],
|
|
369
491
|
createdAt: new Date().toISOString(),
|
|
370
492
|
};
|
|
@@ -372,7 +494,7 @@ function handleTextMessageStart(threadState, event) {
|
|
|
372
494
|
...threadState,
|
|
373
495
|
thread: {
|
|
374
496
|
...threadState.thread,
|
|
375
|
-
messages: [...
|
|
497
|
+
messages: [...messages, newMessage],
|
|
376
498
|
updatedAt: new Date().toISOString(),
|
|
377
499
|
},
|
|
378
500
|
streaming: {
|
|
@@ -445,6 +567,7 @@ function handleTextMessageEnd(threadState, event) {
|
|
|
445
567
|
/**
|
|
446
568
|
* Handle TOOL_CALL_START event.
|
|
447
569
|
* Adds a tool use content block to the current message.
|
|
570
|
+
* If no message exists, creates a synthetic assistant message to hold the tool call.
|
|
448
571
|
* @param threadState - Current thread state
|
|
449
572
|
* @param event - Tool call start event
|
|
450
573
|
* @returns Updated thread state
|
|
@@ -456,18 +579,35 @@ function handleToolCallStart(threadState, event) {
|
|
|
456
579
|
const messageIndex = messageId
|
|
457
580
|
? messages.findIndex((m) => m.id === messageId)
|
|
458
581
|
: messages.length - 1;
|
|
459
|
-
if (messageIndex === -1) {
|
|
460
|
-
throw new Error(messageId
|
|
461
|
-
? `Message ${messageId} not found for TOOL_CALL_START event`
|
|
462
|
-
: `No messages exist for TOOL_CALL_START event`);
|
|
463
|
-
}
|
|
464
|
-
const message = messages[messageIndex];
|
|
465
582
|
const newContent = {
|
|
466
583
|
type: "tool_use",
|
|
467
584
|
id: event.toolCallId,
|
|
468
585
|
name: event.toolCallName,
|
|
469
586
|
input: {},
|
|
470
587
|
};
|
|
588
|
+
// If no message found, create a synthetic assistant message for the tool call
|
|
589
|
+
if (messageIndex === -1) {
|
|
590
|
+
const syntheticMessageId = messageId ?? `msg_tool_${event.toolCallId}`;
|
|
591
|
+
const syntheticMessage = {
|
|
592
|
+
id: syntheticMessageId,
|
|
593
|
+
role: "assistant",
|
|
594
|
+
content: [newContent],
|
|
595
|
+
createdAt: new Date().toISOString(),
|
|
596
|
+
};
|
|
597
|
+
return {
|
|
598
|
+
...threadState,
|
|
599
|
+
thread: {
|
|
600
|
+
...threadState.thread,
|
|
601
|
+
messages: [...messages, syntheticMessage],
|
|
602
|
+
updatedAt: new Date().toISOString(),
|
|
603
|
+
},
|
|
604
|
+
streaming: {
|
|
605
|
+
...threadState.streaming,
|
|
606
|
+
messageId: syntheticMessageId,
|
|
607
|
+
},
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
const message = messages[messageIndex];
|
|
471
611
|
const updatedMessage = {
|
|
472
612
|
...message,
|
|
473
613
|
content: [...message.content, newContent],
|
|
@@ -476,8 +616,9 @@ function handleToolCallStart(threadState, event) {
|
|
|
476
616
|
}
|
|
477
617
|
/**
|
|
478
618
|
* Handle TOOL_CALL_ARGS event.
|
|
479
|
-
* Accumulates JSON string deltas for tool call arguments
|
|
480
|
-
*
|
|
619
|
+
* Accumulates JSON string deltas for tool call arguments and optimistically
|
|
620
|
+
* parses the partial JSON to update the tool_use content block in real-time.
|
|
621
|
+
* The final authoritative parse still happens at TOOL_CALL_END.
|
|
481
622
|
* @param threadState - Current thread state
|
|
482
623
|
* @param event - Tool call args event
|
|
483
624
|
* @returns Updated thread state
|
|
@@ -487,10 +628,46 @@ function handleToolCallArgs(threadState, event) {
|
|
|
487
628
|
// Accumulate the JSON string delta
|
|
488
629
|
const accumulatedArgs = threadState.accumulatingToolArgs;
|
|
489
630
|
const existingArgs = accumulatedArgs.get(toolCallId) ?? "";
|
|
631
|
+
const newAccumulatedJson = existingArgs + event.delta;
|
|
490
632
|
const newAccumulatedArgs = new Map(accumulatedArgs);
|
|
491
|
-
newAccumulatedArgs.set(toolCallId,
|
|
633
|
+
newAccumulatedArgs.set(toolCallId, newAccumulatedJson);
|
|
634
|
+
// Optimistically parse partial JSON to update the tool_use content block
|
|
635
|
+
let parsedInput;
|
|
636
|
+
try {
|
|
637
|
+
const parsed = parsePartialJson(newAccumulatedJson);
|
|
638
|
+
if (typeof parsed === "object" &&
|
|
639
|
+
parsed !== null &&
|
|
640
|
+
!Array.isArray(parsed)) {
|
|
641
|
+
parsedInput = parsed;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
catch {
|
|
645
|
+
// Partial JSON not parseable yet — leave input unchanged
|
|
646
|
+
}
|
|
647
|
+
if (!parsedInput) {
|
|
648
|
+
return {
|
|
649
|
+
...threadState,
|
|
650
|
+
accumulatingToolArgs: newAccumulatedArgs,
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
// Update the tool_use content block with partially parsed input
|
|
654
|
+
const messages = threadState.thread.messages;
|
|
655
|
+
const { messageIndex, contentIndex } = findContentById(messages, "tool_use", toolCallId, "TOOL_CALL_ARGS event");
|
|
656
|
+
const message = messages[messageIndex];
|
|
657
|
+
const toolUseContent = message.content[contentIndex];
|
|
658
|
+
if (toolUseContent.type !== "tool_use") {
|
|
659
|
+
throw new Error(`Content at index ${contentIndex} is not a tool_use block for TOOL_CALL_ARGS event`);
|
|
660
|
+
}
|
|
661
|
+
const updatedContent = {
|
|
662
|
+
...toolUseContent,
|
|
663
|
+
input: parsedInput,
|
|
664
|
+
};
|
|
665
|
+
const updatedMessage = {
|
|
666
|
+
...message,
|
|
667
|
+
content: updateContentAtIndex(message.content, contentIndex, updatedContent),
|
|
668
|
+
};
|
|
492
669
|
return {
|
|
493
|
-
...threadState,
|
|
670
|
+
...updateThreadMessages(threadState, updateMessageAtIndex(messages, messageIndex, updatedMessage)),
|
|
494
671
|
accumulatingToolArgs: newAccumulatedArgs,
|
|
495
672
|
};
|
|
496
673
|
}
|
|
@@ -510,7 +687,7 @@ function handleToolCallEnd(threadState, event) {
|
|
|
510
687
|
// No args accumulated - tool call has empty input
|
|
511
688
|
return threadState;
|
|
512
689
|
}
|
|
513
|
-
// Parse the accumulated JSON
|
|
690
|
+
// Parse the accumulated JSON - tool inputs are always objects
|
|
514
691
|
let parsedInput;
|
|
515
692
|
try {
|
|
516
693
|
parsedInput = JSON.parse(accumulatedJson);
|
|
@@ -544,7 +721,7 @@ function handleToolCallEnd(threadState, event) {
|
|
|
544
721
|
}
|
|
545
722
|
/**
|
|
546
723
|
* Handle TOOL_CALL_RESULT event.
|
|
547
|
-
* Adds tool result to the message.
|
|
724
|
+
* Adds tool result to the specified message.
|
|
548
725
|
* @param threadState - Current thread state
|
|
549
726
|
* @param event - Tool call result event
|
|
550
727
|
* @returns Updated thread state
|
|
@@ -617,11 +794,23 @@ function handleCustomEvent(threadState, event) {
|
|
|
617
794
|
*/
|
|
618
795
|
function handleComponentStart(threadState, event) {
|
|
619
796
|
const messageId = event.value.messageId;
|
|
620
|
-
|
|
621
|
-
// Find the message
|
|
622
|
-
|
|
797
|
+
let messages = threadState.thread.messages;
|
|
798
|
+
// Find the message, or create it if it doesn't exist.
|
|
799
|
+
// The backend may emit component events before TEXT_MESSAGE_START when
|
|
800
|
+
// the LLM outputs a component tool call without preceding text.
|
|
801
|
+
let messageIndex = messages.findIndex((m) => m.id === messageId);
|
|
623
802
|
if (messageIndex === -1) {
|
|
624
|
-
|
|
803
|
+
// Create a new assistant message for this component
|
|
804
|
+
const newMessage = {
|
|
805
|
+
id: messageId,
|
|
806
|
+
role: "assistant",
|
|
807
|
+
content: [],
|
|
808
|
+
createdAt: new Date().toISOString(),
|
|
809
|
+
};
|
|
810
|
+
messages = [...messages, newMessage];
|
|
811
|
+
messageIndex = messages.length - 1;
|
|
812
|
+
// Update thread state with the new message before adding the component
|
|
813
|
+
threadState = updateThreadMessages(threadState, messages);
|
|
625
814
|
}
|
|
626
815
|
const message = messages[messageIndex];
|
|
627
816
|
// Add component content block with 'started' streaming state
|
|
@@ -725,4 +914,223 @@ function handleRunAwaitingInput(threadState, _event) {
|
|
|
725
914
|
},
|
|
726
915
|
};
|
|
727
916
|
}
|
|
917
|
+
// ============================================================================
|
|
918
|
+
// Reasoning Event Handlers (currently mapped from THINKING_TEXT_MESSAGE_* events)
|
|
919
|
+
// ============================================================================
|
|
920
|
+
/**
|
|
921
|
+
* Generate an ephemeral message ID for reasoning messages that arrive before TEXT_MESSAGE_START.
|
|
922
|
+
* Uses crypto.randomUUID() which is available in Node.js 19+ and modern browsers.
|
|
923
|
+
*/
|
|
924
|
+
function generateEphemeralMessageId() {
|
|
925
|
+
return `ephemeral_${crypto.randomUUID()}`;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Find or create an assistant message for reasoning events.
|
|
929
|
+
* Reasoning should only be attached to assistant messages.
|
|
930
|
+
* If no suitable assistant message exists, creates an ephemeral one.
|
|
931
|
+
* @param threadState - Current thread state
|
|
932
|
+
* @returns Object with messageIndex, messages array, and updated threadState
|
|
933
|
+
*/
|
|
934
|
+
function findOrCreateMessageForReasoning(threadState) {
|
|
935
|
+
const messageId = threadState.streaming.messageId;
|
|
936
|
+
let messages = threadState.thread.messages;
|
|
937
|
+
// If we have an active streaming messageId, try to find it
|
|
938
|
+
if (messageId) {
|
|
939
|
+
const messageIndex = messages.findIndex((m) => m.id === messageId);
|
|
940
|
+
if (messageIndex !== -1 && messages[messageIndex].role === "assistant") {
|
|
941
|
+
return { messageIndex, messages, threadState };
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
// Look for the last assistant message
|
|
945
|
+
const lastAssistantIndex = messages.findLastIndex((m) => m.role === "assistant");
|
|
946
|
+
// If there's an assistant message and it's the most recent message, use it
|
|
947
|
+
// (Don't attach reasoning to an old assistant message if user message came after)
|
|
948
|
+
if (lastAssistantIndex !== -1 && lastAssistantIndex === messages.length - 1) {
|
|
949
|
+
return { messageIndex: lastAssistantIndex, messages, threadState };
|
|
950
|
+
}
|
|
951
|
+
// No suitable assistant message - create an ephemeral one
|
|
952
|
+
const ephemeralId = generateEphemeralMessageId();
|
|
953
|
+
const newMessage = {
|
|
954
|
+
id: ephemeralId,
|
|
955
|
+
role: "assistant",
|
|
956
|
+
content: [],
|
|
957
|
+
createdAt: new Date().toISOString(),
|
|
958
|
+
};
|
|
959
|
+
messages = [...messages, newMessage];
|
|
960
|
+
const messageIndex = messages.length - 1;
|
|
961
|
+
// Update thread state with new message
|
|
962
|
+
threadState = {
|
|
963
|
+
...threadState,
|
|
964
|
+
thread: {
|
|
965
|
+
...threadState.thread,
|
|
966
|
+
messages,
|
|
967
|
+
updatedAt: new Date().toISOString(),
|
|
968
|
+
},
|
|
969
|
+
streaming: {
|
|
970
|
+
...threadState.streaming,
|
|
971
|
+
messageId: ephemeralId,
|
|
972
|
+
},
|
|
973
|
+
};
|
|
974
|
+
return { messageIndex, messages, threadState };
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* Handle THINKING_TEXT_MESSAGE_START event (will become REASONING_MESSAGE_START).
|
|
978
|
+
* Starts a new reasoning chunk by appending an empty string to the message's reasoning array.
|
|
979
|
+
* Records the start time for duration calculation.
|
|
980
|
+
* @param threadState - Current thread state
|
|
981
|
+
* @param event - Thinking text message start event
|
|
982
|
+
* @returns Updated thread state
|
|
983
|
+
*/
|
|
984
|
+
function handleThinkingTextMessageStart(threadState, event) {
|
|
985
|
+
const { messageIndex, messages, threadState: updatedThreadState, } = findOrCreateMessageForReasoning(threadState);
|
|
986
|
+
threadState = updatedThreadState;
|
|
987
|
+
const message = messages[messageIndex];
|
|
988
|
+
const existingReasoning = message.reasoning ?? [];
|
|
989
|
+
const updatedMessage = {
|
|
990
|
+
...message,
|
|
991
|
+
reasoning: [...existingReasoning, ""],
|
|
992
|
+
};
|
|
993
|
+
// Record reasoning start time if this is the first reasoning chunk
|
|
994
|
+
const reasoningStartTime = threadState.streaming.reasoningStartTime ?? event.timestamp ?? Date.now();
|
|
995
|
+
return {
|
|
996
|
+
...updateThreadMessages(threadState, updateMessageAtIndex(messages, messageIndex, updatedMessage)),
|
|
997
|
+
streaming: {
|
|
998
|
+
...threadState.streaming,
|
|
999
|
+
reasoningStartTime,
|
|
1000
|
+
},
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Handle THINKING_TEXT_MESSAGE_CONTENT event (will become REASONING_MESSAGE_CONTENT).
|
|
1005
|
+
* Appends delta text to the last reasoning chunk.
|
|
1006
|
+
* @param threadState - Current thread state
|
|
1007
|
+
* @param event - Thinking text message content event
|
|
1008
|
+
* @returns Updated thread state
|
|
1009
|
+
*/
|
|
1010
|
+
function handleThinkingTextMessageContent(threadState, event) {
|
|
1011
|
+
const { messageIndex, messages, threadState: updatedThreadState, } = findOrCreateMessageForReasoning(threadState);
|
|
1012
|
+
threadState = updatedThreadState;
|
|
1013
|
+
const message = messages[messageIndex];
|
|
1014
|
+
const existingReasoning = message.reasoning ?? [];
|
|
1015
|
+
if (existingReasoning.length === 0) {
|
|
1016
|
+
// No reasoning chunk started - start one implicitly
|
|
1017
|
+
const updatedMessage = {
|
|
1018
|
+
...message,
|
|
1019
|
+
reasoning: [event.delta],
|
|
1020
|
+
};
|
|
1021
|
+
return {
|
|
1022
|
+
...updateThreadMessages(threadState, updateMessageAtIndex(messages, messageIndex, updatedMessage)),
|
|
1023
|
+
streaming: {
|
|
1024
|
+
...threadState.streaming,
|
|
1025
|
+
reasoningStartTime: threadState.streaming.reasoningStartTime ??
|
|
1026
|
+
event.timestamp ??
|
|
1027
|
+
Date.now(),
|
|
1028
|
+
},
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
// Append to the last reasoning chunk
|
|
1032
|
+
const updatedReasoning = [
|
|
1033
|
+
...existingReasoning.slice(0, -1),
|
|
1034
|
+
existingReasoning[existingReasoning.length - 1] + event.delta,
|
|
1035
|
+
];
|
|
1036
|
+
const updatedMessage = {
|
|
1037
|
+
...message,
|
|
1038
|
+
reasoning: updatedReasoning,
|
|
1039
|
+
};
|
|
1040
|
+
return updateThreadMessages(threadState, updateMessageAtIndex(messages, messageIndex, updatedMessage));
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Handle THINKING_TEXT_MESSAGE_END event (will become REASONING_MESSAGE_END).
|
|
1044
|
+
* Calculates and stores the reasoning duration.
|
|
1045
|
+
* @param threadState - Current thread state
|
|
1046
|
+
* @param event - Thinking text message end event
|
|
1047
|
+
* @returns Updated thread state
|
|
1048
|
+
*/
|
|
1049
|
+
function handleThinkingTextMessageEnd(threadState, event) {
|
|
1050
|
+
const { messageIndex, messages, threadState: updatedThreadState, } = findOrCreateMessageForReasoning(threadState);
|
|
1051
|
+
threadState = updatedThreadState;
|
|
1052
|
+
const message = messages[messageIndex];
|
|
1053
|
+
// Calculate duration if we have a start time
|
|
1054
|
+
const reasoningStartTime = threadState.streaming.reasoningStartTime;
|
|
1055
|
+
const endTime = event.timestamp ?? Date.now();
|
|
1056
|
+
const reasoningDurationMS = reasoningStartTime
|
|
1057
|
+
? endTime - reasoningStartTime
|
|
1058
|
+
: undefined;
|
|
1059
|
+
const updatedMessage = {
|
|
1060
|
+
...message,
|
|
1061
|
+
reasoningDurationMS: reasoningDurationMS ?? message.reasoningDurationMS ?? undefined,
|
|
1062
|
+
};
|
|
1063
|
+
return updateThreadMessages(threadState, updateMessageAtIndex(messages, messageIndex, updatedMessage));
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Handle LOAD_THREAD_MESSAGES action.
|
|
1067
|
+
* Loads messages from API into stream state for an existing thread.
|
|
1068
|
+
* Deduplicates by message ID, keeping existing messages (they may have in-flight updates).
|
|
1069
|
+
* Sorts merged messages by createdAt to ensure chronological order.
|
|
1070
|
+
* @param state - Current stream state
|
|
1071
|
+
* @param action - Load thread messages action
|
|
1072
|
+
* @returns Updated stream state
|
|
1073
|
+
*/
|
|
1074
|
+
function handleLoadThreadMessages(state, action) {
|
|
1075
|
+
const { threadId, messages, skipIfStreaming } = action;
|
|
1076
|
+
// Get or create thread state
|
|
1077
|
+
let threadState = state.threadMap[threadId];
|
|
1078
|
+
if (!threadState) {
|
|
1079
|
+
threadState = createInitialThreadState(threadId);
|
|
1080
|
+
}
|
|
1081
|
+
// Skip if streaming and skipIfStreaming is true
|
|
1082
|
+
if (skipIfStreaming && threadState.streaming.status === "streaming") {
|
|
1083
|
+
return state;
|
|
1084
|
+
}
|
|
1085
|
+
const existingMessages = threadState.thread.messages;
|
|
1086
|
+
// Build a set of existing message IDs for fast lookup
|
|
1087
|
+
const existingIds = new Set(existingMessages.map((m) => m.id));
|
|
1088
|
+
// Filter out messages that already exist (keep existing, add new).
|
|
1089
|
+
// API-loaded messages are by definition fully complete, so stamp
|
|
1090
|
+
// streamingState: "done" on all component content blocks. This is
|
|
1091
|
+
// required by downstream hooks (usePropsStreamingStatus) which check
|
|
1092
|
+
// streamingState === "done" to report isSuccess: true.
|
|
1093
|
+
const newMessages = messages
|
|
1094
|
+
.filter((m) => !existingIds.has(m.id))
|
|
1095
|
+
.map((m) => ({
|
|
1096
|
+
...m,
|
|
1097
|
+
content: m.content.map((block) => {
|
|
1098
|
+
if (block.type !== "component")
|
|
1099
|
+
return block;
|
|
1100
|
+
if (block.streamingState !== undefined &&
|
|
1101
|
+
block.streamingState !== "done") {
|
|
1102
|
+
console.warn(`LOAD_THREAD_MESSAGES: component "${block.id}" has unexpected ` +
|
|
1103
|
+
`streamingState "${block.streamingState}". API-loaded messages ` +
|
|
1104
|
+
`should not have in-flight streaming state.`);
|
|
1105
|
+
}
|
|
1106
|
+
return { ...block, streamingState: "done" };
|
|
1107
|
+
}),
|
|
1108
|
+
}));
|
|
1109
|
+
// Merge and sort by createdAt
|
|
1110
|
+
const mergedMessages = [...existingMessages, ...newMessages].toSorted((a, b) => {
|
|
1111
|
+
// Messages without createdAt go to the end
|
|
1112
|
+
if (!a.createdAt && !b.createdAt)
|
|
1113
|
+
return 0;
|
|
1114
|
+
if (!a.createdAt)
|
|
1115
|
+
return 1;
|
|
1116
|
+
if (!b.createdAt)
|
|
1117
|
+
return -1;
|
|
1118
|
+
return a.createdAt.localeCompare(b.createdAt);
|
|
1119
|
+
});
|
|
1120
|
+
const updatedThreadState = {
|
|
1121
|
+
...threadState,
|
|
1122
|
+
thread: {
|
|
1123
|
+
...threadState.thread,
|
|
1124
|
+
messages: mergedMessages,
|
|
1125
|
+
updatedAt: new Date().toISOString(),
|
|
1126
|
+
},
|
|
1127
|
+
};
|
|
1128
|
+
return {
|
|
1129
|
+
...state,
|
|
1130
|
+
threadMap: {
|
|
1131
|
+
...state.threadMap,
|
|
1132
|
+
[threadId]: updatedThreadState,
|
|
1133
|
+
},
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
728
1136
|
//# sourceMappingURL=event-accumulator.js.map
|