@tambo-ai/react 0.69.1 → 0.71.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 +7 -7
- package/dist/hooks/use-tambo-threads.test.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +4 -5
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +4 -5
- package/dist/mcp/index.js.map +1 -1
- package/dist/model/component-metadata.d.ts +88 -241
- package/dist/model/component-metadata.d.ts.map +1 -1
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/model/mcp-server-info.d.ts +3 -3
- package/dist/model/mcp-server-info.js.map +1 -1
- package/dist/providers/hooks/use-tambo-session-token.test.js.map +1 -1
- package/dist/providers/tambo-component-provider.d.ts +2 -2
- package/dist/providers/tambo-component-provider.d.ts.map +1 -1
- package/dist/providers/tambo-component-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts +1 -1
- package/dist/providers/tambo-registry-provider.d.ts +4 -4
- package/dist/providers/tambo-registry-provider.d.ts.map +1 -1
- package/dist/providers/tambo-registry-provider.js +11 -8
- package/dist/providers/tambo-registry-provider.js.map +1 -1
- package/dist/providers/tambo-registry-provider.test.js +31 -0
- package/dist/providers/tambo-registry-provider.test.js.map +1 -1
- package/dist/providers/tambo-registry-schema-compat.test.js +42 -52
- package/dist/providers/tambo-registry-schema-compat.test.js.map +1 -1
- package/dist/providers/tambo-stubs.d.ts +2 -2
- package/dist/providers/tambo-stubs.d.ts.map +1 -1
- package/dist/providers/tambo-stubs.js.map +1 -1
- package/dist/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js +107 -141
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.test.js +274 -445
- package/dist/providers/tambo-thread-provider.test.js.map +1 -1
- package/dist/schema/index.d.ts +1 -2
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -5
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/schema.d.ts +7 -24
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +34 -105
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/schema.test.js +26 -124
- package/dist/schema/schema.test.js.map +1 -1
- package/dist/testing/tools.d.ts +2 -12
- package/dist/testing/tools.d.ts.map +1 -1
- package/dist/testing/tools.js +1 -20
- package/dist/testing/tools.js.map +1 -1
- package/dist/testing/types.d.ts +2 -2
- package/dist/testing/types.d.ts.map +1 -1
- package/dist/testing/types.js.map +1 -1
- package/dist/util/registry-validators.d.ts +2 -2
- package/dist/util/registry-validators.d.ts.map +1 -1
- package/dist/util/registry-validators.js +37 -17
- package/dist/util/registry-validators.js.map +1 -1
- package/dist/util/registry-validators.test.js +64 -25
- package/dist/util/registry-validators.test.js.map +1 -1
- package/dist/util/registry.d.ts +4 -10
- package/dist/util/registry.d.ts.map +1 -1
- package/dist/util/registry.js +6 -22
- package/dist/util/registry.js.map +1 -1
- package/dist/util/registry.test.js +1 -47
- package/dist/util/registry.test.js.map +1 -1
- package/dist/util/tool-caller.d.ts +2 -2
- package/dist/util/tool-caller.d.ts.map +1 -1
- package/dist/util/tool-caller.js +5 -12
- package/dist/util/tool-caller.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.d.ts +58 -0
- package/dist/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-messages.js +54 -0
- package/dist/v1/hooks/use-tambo-v1-messages.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-messages.test.d.ts +2 -0
- package/dist/v1/hooks/use-tambo-v1-messages.test.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-messages.test.js +137 -0
- package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +96 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.js +227 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.test.d.ts +2 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.test.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js +827 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts +61 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.js +56 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.d.ts +2 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +98 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-thread.d.ts +37 -0
- package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-thread.js +49 -0
- package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-thread.test.d.ts +2 -0
- package/dist/v1/hooks/use-tambo-v1-thread.test.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-thread.test.js +83 -0
- package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1.d.ts +107 -0
- package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1.js +87 -0
- package/dist/v1/hooks/use-tambo-v1.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1.test.d.ts +2 -0
- package/dist/v1/hooks/use-tambo-v1.test.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1.test.js +150 -0
- package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -0
- package/dist/v1/index.d.ts +73 -0
- package/dist/v1/index.d.ts.map +1 -0
- package/dist/v1/index.js +106 -0
- package/dist/v1/index.js.map +1 -0
- package/dist/v1/providers/tambo-v1-provider.d.ts +91 -0
- package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -0
- package/dist/v1/providers/tambo-v1-provider.js +110 -0
- package/dist/v1/providers/tambo-v1-provider.js.map +1 -0
- package/dist/v1/providers/tambo-v1-provider.test.d.ts +2 -0
- package/dist/v1/providers/tambo-v1-provider.test.d.ts.map +1 -0
- package/dist/v1/providers/tambo-v1-provider.test.js +123 -0
- package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -0
- package/dist/v1/providers/tambo-v1-stream-context.d.ts +136 -0
- package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -0
- package/dist/v1/providers/tambo-v1-stream-context.js +230 -0
- package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -0
- package/dist/v1/providers/tambo-v1-stream-context.test.d.ts +2 -0
- package/dist/v1/providers/tambo-v1-stream-context.test.d.ts.map +1 -0
- package/dist/v1/providers/tambo-v1-stream-context.test.js +85 -0
- package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -0
- package/dist/v1/types/component.d.ts +50 -0
- package/dist/v1/types/component.d.ts.map +1 -0
- package/dist/v1/types/component.js +14 -0
- package/dist/v1/types/component.js.map +1 -0
- package/dist/v1/types/event.d.ts +72 -0
- package/dist/v1/types/event.d.ts.map +1 -0
- package/dist/v1/types/event.js +54 -0
- package/dist/v1/types/event.js.map +1 -0
- package/dist/v1/types/event.test.d.ts +2 -0
- package/dist/v1/types/event.test.d.ts.map +1 -0
- package/dist/v1/types/event.test.js +70 -0
- package/dist/v1/types/event.test.js.map +1 -0
- package/dist/v1/types/message.d.ts +35 -0
- package/dist/v1/types/message.d.ts.map +1 -0
- package/dist/v1/types/message.js +10 -0
- package/dist/v1/types/message.js.map +1 -0
- package/dist/v1/types/thread.d.ts +52 -0
- package/dist/v1/types/thread.d.ts.map +1 -0
- package/dist/v1/types/thread.js +9 -0
- package/dist/v1/types/thread.js.map +1 -0
- package/dist/v1/utils/event-accumulator.d.ts +100 -0
- package/dist/v1/utils/event-accumulator.d.ts.map +1 -0
- package/dist/v1/utils/event-accumulator.js +715 -0
- package/dist/v1/utils/event-accumulator.js.map +1 -0
- package/dist/v1/utils/event-accumulator.test.d.ts +2 -0
- package/dist/v1/utils/event-accumulator.test.d.ts.map +1 -0
- package/dist/v1/utils/event-accumulator.test.js +1010 -0
- package/dist/v1/utils/event-accumulator.test.js.map +1 -0
- package/dist/v1/utils/json-patch.d.ts +18 -0
- package/dist/v1/utils/json-patch.d.ts.map +1 -0
- package/dist/v1/utils/json-patch.js +35 -0
- package/dist/v1/utils/json-patch.js.map +1 -0
- package/dist/v1/utils/json-patch.test.d.ts +2 -0
- package/dist/v1/utils/json-patch.test.d.ts.map +1 -0
- package/dist/v1/utils/json-patch.test.js +28 -0
- package/dist/v1/utils/json-patch.test.js.map +1 -0
- package/dist/v1/utils/registry-conversion.d.ts +53 -0
- package/dist/v1/utils/registry-conversion.d.ts.map +1 -0
- package/dist/v1/utils/registry-conversion.js +114 -0
- package/dist/v1/utils/registry-conversion.js.map +1 -0
- package/dist/v1/utils/registry-conversion.test.d.ts +2 -0
- package/dist/v1/utils/registry-conversion.test.d.ts.map +1 -0
- package/dist/v1/utils/registry-conversion.test.js +179 -0
- package/dist/v1/utils/registry-conversion.test.js.map +1 -0
- package/dist/v1/utils/stream-handler.d.ts +45 -0
- package/dist/v1/utils/stream-handler.d.ts.map +1 -0
- package/dist/v1/utils/stream-handler.js +47 -0
- package/dist/v1/utils/stream-handler.js.map +1 -0
- package/dist/v1/utils/stream-handler.test.d.ts +2 -0
- package/dist/v1/utils/stream-handler.test.d.ts.map +1 -0
- package/dist/v1/utils/stream-handler.test.js +74 -0
- package/dist/v1/utils/stream-handler.test.js.map +1 -0
- package/dist/v1/utils/tool-call-tracker.d.ts +41 -0
- package/dist/v1/utils/tool-call-tracker.d.ts.map +1 -0
- package/dist/v1/utils/tool-call-tracker.js +90 -0
- package/dist/v1/utils/tool-call-tracker.js.map +1 -0
- package/dist/v1/utils/tool-executor.d.ts +33 -0
- package/dist/v1/utils/tool-executor.d.ts.map +1 -0
- package/dist/v1/utils/tool-executor.js +103 -0
- package/dist/v1/utils/tool-executor.js.map +1 -0
- package/dist/v1/utils/tool-executor.test.d.ts +2 -0
- package/dist/v1/utils/tool-executor.test.d.ts.map +1 -0
- package/dist/v1/utils/tool-executor.test.js +222 -0
- package/dist/v1/utils/tool-executor.test.js.map +1 -0
- package/esm/hooks/use-tambo-threads.test.js.map +1 -1
- package/esm/index.d.ts +1 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js.map +1 -1
- package/esm/mcp/index.d.ts +4 -5
- package/esm/mcp/index.d.ts.map +1 -1
- package/esm/mcp/index.js +4 -5
- package/esm/mcp/index.js.map +1 -1
- package/esm/model/component-metadata.d.ts +88 -241
- package/esm/model/component-metadata.d.ts.map +1 -1
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/model/mcp-server-info.d.ts +3 -3
- package/esm/model/mcp-server-info.js.map +1 -1
- package/esm/providers/hooks/use-tambo-session-token.test.js.map +1 -1
- package/esm/providers/tambo-component-provider.d.ts +2 -2
- package/esm/providers/tambo-component-provider.d.ts.map +1 -1
- package/esm/providers/tambo-component-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts +1 -1
- package/esm/providers/tambo-registry-provider.d.ts +4 -4
- package/esm/providers/tambo-registry-provider.d.ts.map +1 -1
- package/esm/providers/tambo-registry-provider.js +11 -8
- package/esm/providers/tambo-registry-provider.js.map +1 -1
- package/esm/providers/tambo-registry-provider.test.js +31 -0
- package/esm/providers/tambo-registry-provider.test.js.map +1 -1
- package/esm/providers/tambo-registry-schema-compat.test.js +42 -52
- package/esm/providers/tambo-registry-schema-compat.test.js.map +1 -1
- package/esm/providers/tambo-stubs.d.ts +2 -2
- package/esm/providers/tambo-stubs.d.ts.map +1 -1
- package/esm/providers/tambo-stubs.js.map +1 -1
- package/esm/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js +107 -141
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.test.js +241 -445
- package/esm/providers/tambo-thread-provider.test.js.map +1 -1
- package/esm/schema/index.d.ts +1 -2
- package/esm/schema/index.d.ts.map +1 -1
- package/esm/schema/index.js +1 -2
- package/esm/schema/index.js.map +1 -1
- package/esm/schema/schema.d.ts +7 -24
- package/esm/schema/schema.d.ts.map +1 -1
- package/esm/schema/schema.js +34 -103
- package/esm/schema/schema.js.map +1 -1
- package/esm/schema/schema.test.js +27 -125
- package/esm/schema/schema.test.js.map +1 -1
- package/esm/testing/tools.d.ts +2 -12
- package/esm/testing/tools.d.ts.map +1 -1
- package/esm/testing/tools.js +2 -20
- package/esm/testing/tools.js.map +1 -1
- package/esm/testing/types.d.ts +2 -2
- package/esm/testing/types.d.ts.map +1 -1
- package/esm/testing/types.js.map +1 -1
- package/esm/util/registry-validators.d.ts +2 -2
- package/esm/util/registry-validators.d.ts.map +1 -1
- package/esm/util/registry-validators.js +38 -18
- package/esm/util/registry-validators.js.map +1 -1
- package/esm/util/registry-validators.test.js +64 -25
- package/esm/util/registry-validators.test.js.map +1 -1
- package/esm/util/registry.d.ts +4 -10
- package/esm/util/registry.d.ts.map +1 -1
- package/esm/util/registry.js +7 -22
- package/esm/util/registry.js.map +1 -1
- package/esm/util/registry.test.js +3 -49
- package/esm/util/registry.test.js.map +1 -1
- package/esm/util/tool-caller.d.ts +2 -2
- package/esm/util/tool-caller.d.ts.map +1 -1
- package/esm/util/tool-caller.js +5 -12
- package/esm/util/tool-caller.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.d.ts +58 -0
- package/esm/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-messages.js +51 -0
- package/esm/v1/hooks/use-tambo-v1-messages.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-messages.test.d.ts +2 -0
- package/esm/v1/hooks/use-tambo-v1-messages.test.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-messages.test.js +132 -0
- package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +96 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.js +223 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.test.d.ts +2 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.test.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js +822 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts +61 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.js +53 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.d.ts +2 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +93 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-thread.d.ts +37 -0
- package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-thread.js +46 -0
- package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-thread.test.d.ts +2 -0
- package/esm/v1/hooks/use-tambo-v1-thread.test.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-thread.test.js +78 -0
- package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1.d.ts +107 -0
- package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1.js +84 -0
- package/esm/v1/hooks/use-tambo-v1.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1.test.d.ts +2 -0
- package/esm/v1/hooks/use-tambo-v1.test.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1.test.js +145 -0
- package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -0
- package/esm/v1/index.d.ts +73 -0
- package/esm/v1/index.d.ts.map +1 -0
- package/esm/v1/index.js +83 -0
- package/esm/v1/index.js.map +1 -0
- package/esm/v1/providers/tambo-v1-provider.d.ts +91 -0
- package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -0
- package/esm/v1/providers/tambo-v1-provider.js +74 -0
- package/esm/v1/providers/tambo-v1-provider.js.map +1 -0
- package/esm/v1/providers/tambo-v1-provider.test.d.ts +2 -0
- package/esm/v1/providers/tambo-v1-provider.test.d.ts.map +1 -0
- package/esm/v1/providers/tambo-v1-provider.test.js +118 -0
- package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -0
- package/esm/v1/providers/tambo-v1-stream-context.d.ts +136 -0
- package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -0
- package/esm/v1/providers/tambo-v1-stream-context.js +191 -0
- package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -0
- package/esm/v1/providers/tambo-v1-stream-context.test.d.ts +2 -0
- package/esm/v1/providers/tambo-v1-stream-context.test.d.ts.map +1 -0
- package/esm/v1/providers/tambo-v1-stream-context.test.js +80 -0
- package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -0
- package/esm/v1/types/component.d.ts +50 -0
- package/esm/v1/types/component.d.ts.map +1 -0
- package/esm/v1/types/component.js +13 -0
- package/esm/v1/types/component.js.map +1 -0
- package/esm/v1/types/event.d.ts +72 -0
- package/esm/v1/types/event.d.ts.map +1 -0
- package/esm/v1/types/event.js +50 -0
- package/esm/v1/types/event.js.map +1 -0
- package/esm/v1/types/event.test.d.ts +2 -0
- package/esm/v1/types/event.test.d.ts.map +1 -0
- package/esm/v1/types/event.test.js +68 -0
- package/esm/v1/types/event.test.js.map +1 -0
- package/esm/v1/types/message.d.ts +35 -0
- package/esm/v1/types/message.d.ts.map +1 -0
- package/esm/v1/types/message.js +9 -0
- package/esm/v1/types/message.js.map +1 -0
- package/esm/v1/types/thread.d.ts +52 -0
- package/esm/v1/types/thread.d.ts.map +1 -0
- package/esm/v1/types/thread.js +8 -0
- package/esm/v1/types/thread.js.map +1 -0
- package/esm/v1/utils/event-accumulator.d.ts +100 -0
- package/esm/v1/utils/event-accumulator.d.ts.map +1 -0
- package/esm/v1/utils/event-accumulator.js +708 -0
- package/esm/v1/utils/event-accumulator.js.map +1 -0
- package/esm/v1/utils/event-accumulator.test.d.ts +2 -0
- package/esm/v1/utils/event-accumulator.test.d.ts.map +1 -0
- package/esm/v1/utils/event-accumulator.test.js +1008 -0
- package/esm/v1/utils/event-accumulator.test.js.map +1 -0
- package/esm/v1/utils/json-patch.d.ts +18 -0
- package/esm/v1/utils/json-patch.d.ts.map +1 -0
- package/esm/v1/utils/json-patch.js +32 -0
- package/esm/v1/utils/json-patch.js.map +1 -0
- package/esm/v1/utils/json-patch.test.d.ts +2 -0
- package/esm/v1/utils/json-patch.test.d.ts.map +1 -0
- package/esm/v1/utils/json-patch.test.js +26 -0
- package/esm/v1/utils/json-patch.test.js.map +1 -0
- package/esm/v1/utils/registry-conversion.d.ts +53 -0
- package/esm/v1/utils/registry-conversion.d.ts.map +1 -0
- package/esm/v1/utils/registry-conversion.js +108 -0
- package/esm/v1/utils/registry-conversion.js.map +1 -0
- package/esm/v1/utils/registry-conversion.test.d.ts +2 -0
- package/esm/v1/utils/registry-conversion.test.d.ts.map +1 -0
- package/esm/v1/utils/registry-conversion.test.js +177 -0
- package/esm/v1/utils/registry-conversion.test.js.map +1 -0
- package/esm/v1/utils/stream-handler.d.ts +45 -0
- package/esm/v1/utils/stream-handler.d.ts.map +1 -0
- package/esm/v1/utils/stream-handler.js +44 -0
- package/esm/v1/utils/stream-handler.js.map +1 -0
- package/esm/v1/utils/stream-handler.test.d.ts +2 -0
- package/esm/v1/utils/stream-handler.test.d.ts.map +1 -0
- package/esm/v1/utils/stream-handler.test.js +72 -0
- package/esm/v1/utils/stream-handler.test.js.map +1 -0
- package/esm/v1/utils/tool-call-tracker.d.ts +41 -0
- package/esm/v1/utils/tool-call-tracker.d.ts.map +1 -0
- package/esm/v1/utils/tool-call-tracker.js +86 -0
- package/esm/v1/utils/tool-call-tracker.js.map +1 -0
- package/esm/v1/utils/tool-executor.d.ts +33 -0
- package/esm/v1/utils/tool-executor.d.ts.map +1 -0
- package/esm/v1/utils/tool-executor.js +99 -0
- package/esm/v1/utils/tool-executor.js.map +1 -0
- package/esm/v1/utils/tool-executor.test.d.ts +2 -0
- package/esm/v1/utils/tool-executor.test.d.ts.map +1 -0
- package/esm/v1/utils/tool-executor.test.js +220 -0
- package/esm/v1/utils/tool-executor.test.js.map +1 -0
- package/package.json +20 -9
- package/dist/schema/zod.d.ts +0 -57
- package/dist/schema/zod.d.ts.map +0 -1
- package/dist/schema/zod.js +0 -191
- package/dist/schema/zod.js.map +0 -1
- package/dist/schema/zod.test.d.ts +0 -2
- package/dist/schema/zod.test.d.ts.map +0 -1
- package/dist/schema/zod.test.js +0 -663
- package/dist/schema/zod.test.js.map +0 -1
- package/esm/schema/zod.d.ts +0 -57
- package/esm/schema/zod.d.ts.map +0 -1
- package/esm/schema/zod.js +0 -180
- package/esm/schema/zod.js.map +0 -1
- package/esm/schema/zod.test.d.ts +0 -2
- package/esm/schema/zod.test.d.ts.map +0 -1
- package/esm/schema/zod.test.js +0 -628
- package/esm/schema/zod.test.js.map +0 -1
|
@@ -1,9 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const typescript_sdk_1 = require("@tambo-ai/typescript-sdk");
|
|
39
|
+
const typescript_sdk_1 = __importStar(require("@tambo-ai/typescript-sdk"));
|
|
7
40
|
const react_1 = require("@testing-library/react");
|
|
8
41
|
const react_2 = __importDefault(require("react"));
|
|
9
42
|
const v4_1 = require("zod/v4");
|
|
@@ -28,9 +61,14 @@ jest.mock("./tambo-client-provider", () => {
|
|
|
28
61
|
TamboClientContext: react_2.default.createContext(undefined),
|
|
29
62
|
};
|
|
30
63
|
});
|
|
31
|
-
jest.mock("@tambo-ai/typescript-sdk", () =>
|
|
32
|
-
|
|
33
|
-
|
|
64
|
+
jest.mock("@tambo-ai/typescript-sdk", () => {
|
|
65
|
+
const actual = jest.requireActual("@tambo-ai/typescript-sdk");
|
|
66
|
+
return {
|
|
67
|
+
__esModule: true,
|
|
68
|
+
...actual,
|
|
69
|
+
advanceStream: jest.fn(),
|
|
70
|
+
};
|
|
71
|
+
});
|
|
34
72
|
// Mock the getCustomContext
|
|
35
73
|
jest.mock("../util/registry", () => ({
|
|
36
74
|
...jest.requireActual("../util/registry"),
|
|
@@ -73,26 +111,9 @@ const createMockAdvanceResponse = (overrides = {}) => ({
|
|
|
73
111
|
});
|
|
74
112
|
describe("TamboThreadProvider", () => {
|
|
75
113
|
const mockThread = createMockThread();
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
},
|
|
80
|
-
retrieve: jest.fn(),
|
|
81
|
-
advance: jest.fn(),
|
|
82
|
-
advanceByID: jest.fn(),
|
|
83
|
-
generateName: jest.fn(),
|
|
84
|
-
};
|
|
85
|
-
const mockProjectsApi = {
|
|
86
|
-
getCurrent: jest.fn(),
|
|
87
|
-
};
|
|
88
|
-
const mockBeta = {
|
|
89
|
-
threads: mockThreadsApi,
|
|
90
|
-
projects: mockProjectsApi,
|
|
91
|
-
};
|
|
92
|
-
const mockTamboAI = {
|
|
93
|
-
apiKey: "",
|
|
94
|
-
beta: mockBeta,
|
|
95
|
-
};
|
|
114
|
+
let mockTamboAI;
|
|
115
|
+
let mockThreadsApi;
|
|
116
|
+
let mockProjectsApi;
|
|
96
117
|
let mockQueryClient;
|
|
97
118
|
const mockRegistry = [
|
|
98
119
|
{
|
|
@@ -144,8 +165,19 @@ describe("TamboThreadProvider", () => {
|
|
|
144
165
|
};
|
|
145
166
|
// Default wrapper for most tests
|
|
146
167
|
const Wrapper = createWrapper();
|
|
168
|
+
afterEach(() => {
|
|
169
|
+
jest.restoreAllMocks();
|
|
170
|
+
});
|
|
147
171
|
beforeEach(() => {
|
|
148
172
|
jest.clearAllMocks();
|
|
173
|
+
mockTamboAI = new typescript_sdk_1.default({
|
|
174
|
+
apiKey: "",
|
|
175
|
+
fetch: () => {
|
|
176
|
+
throw new Error("Unexpected network call in test");
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
mockThreadsApi = mockTamboAI.beta.threads;
|
|
180
|
+
mockProjectsApi = mockTamboAI.beta.projects;
|
|
149
181
|
// Setup mock query client
|
|
150
182
|
mockQueryClient = {
|
|
151
183
|
invalidateQueries: jest.fn().mockResolvedValue(undefined),
|
|
@@ -154,21 +186,22 @@ describe("TamboThreadProvider", () => {
|
|
|
154
186
|
jest
|
|
155
187
|
.mocked(tambo_client_provider_1.useTamboQueryClient)
|
|
156
188
|
.mockReturnValue(mockQueryClient);
|
|
157
|
-
jest.
|
|
189
|
+
jest.spyOn(mockThreadsApi, "retrieve").mockResolvedValue(mockThread);
|
|
158
190
|
jest
|
|
159
|
-
.
|
|
191
|
+
.spyOn(mockThreadsApi.messages, "create")
|
|
160
192
|
.mockResolvedValue(createMockMessage());
|
|
161
193
|
jest
|
|
162
|
-
.
|
|
194
|
+
.spyOn(mockThreadsApi, "advance")
|
|
163
195
|
.mockResolvedValue(createMockAdvanceResponse());
|
|
164
196
|
jest
|
|
165
|
-
.
|
|
197
|
+
.spyOn(mockThreadsApi, "advanceByID")
|
|
166
198
|
.mockResolvedValue(createMockAdvanceResponse());
|
|
167
|
-
jest.
|
|
199
|
+
jest.spyOn(mockThreadsApi, "generateName").mockResolvedValue({
|
|
168
200
|
...mockThread,
|
|
169
201
|
name: "Generated Thread Name",
|
|
170
202
|
});
|
|
171
|
-
jest.
|
|
203
|
+
jest.spyOn(mockThreadsApi, "update").mockResolvedValue({});
|
|
204
|
+
jest.spyOn(mockProjectsApi, "getCurrent").mockResolvedValue({
|
|
172
205
|
id: "test-project-id",
|
|
173
206
|
name: "Test Project",
|
|
174
207
|
isTokenRequired: false,
|
|
@@ -236,7 +269,7 @@ describe("TamboThreadProvider", () => {
|
|
|
236
269
|
});
|
|
237
270
|
});
|
|
238
271
|
it("should send a message and update thread state", async () => {
|
|
239
|
-
const
|
|
272
|
+
const mockStreamResponse = {
|
|
240
273
|
responseMessageDto: {
|
|
241
274
|
id: "response-1",
|
|
242
275
|
content: [{ type: "text", text: "Response" }],
|
|
@@ -249,14 +282,17 @@ describe("TamboThreadProvider", () => {
|
|
|
249
282
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
250
283
|
mcpAccessToken: "test-mcp-access-token",
|
|
251
284
|
};
|
|
252
|
-
|
|
253
|
-
.
|
|
254
|
-
|
|
285
|
+
const mockAsyncIterator = {
|
|
286
|
+
[Symbol.asyncIterator]: async function* () {
|
|
287
|
+
yield mockStreamResponse;
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
jest.mocked(typescript_sdk_1.advanceStream).mockResolvedValue(mockAsyncIterator);
|
|
255
291
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), { wrapper: Wrapper });
|
|
256
292
|
await (0, react_1.act)(async () => {
|
|
257
293
|
await result.current.sendThreadMessage("Hello", {
|
|
258
294
|
threadId: "test-thread-1",
|
|
259
|
-
streamResponse:
|
|
295
|
+
streamResponse: true,
|
|
260
296
|
additionalContext: {
|
|
261
297
|
custom: {
|
|
262
298
|
message: "additional instructions",
|
|
@@ -264,7 +300,7 @@ describe("TamboThreadProvider", () => {
|
|
|
264
300
|
},
|
|
265
301
|
});
|
|
266
302
|
});
|
|
267
|
-
expect(
|
|
303
|
+
expect(typescript_sdk_1.advanceStream).toHaveBeenCalledWith(expect.anything(), {
|
|
268
304
|
messageToAppend: {
|
|
269
305
|
content: [{ type: "text", text: "Hello" }],
|
|
270
306
|
role: "user",
|
|
@@ -278,7 +314,7 @@ describe("TamboThreadProvider", () => {
|
|
|
278
314
|
contextKey: undefined,
|
|
279
315
|
clientTools: [],
|
|
280
316
|
toolCallCounts: {},
|
|
281
|
-
});
|
|
317
|
+
}, "test-thread-1");
|
|
282
318
|
expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.COMPLETE);
|
|
283
319
|
});
|
|
284
320
|
it("should handle streaming responses", async () => {
|
|
@@ -313,7 +349,7 @@ describe("TamboThreadProvider", () => {
|
|
|
313
349
|
expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.COMPLETE);
|
|
314
350
|
});
|
|
315
351
|
it("should handle tool calls during message processing.", async () => {
|
|
316
|
-
const
|
|
352
|
+
const mockToolCallChunk = {
|
|
317
353
|
responseMessageDto: {
|
|
318
354
|
id: "tool-call-1",
|
|
319
355
|
content: [{ type: "text", text: "Tool response" }],
|
|
@@ -329,10 +365,7 @@ describe("TamboThreadProvider", () => {
|
|
|
329
365
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
330
366
|
mcpAccessToken: "test-mcp-access-token",
|
|
331
367
|
};
|
|
332
|
-
|
|
333
|
-
.mocked(mockThreadsApi.advanceByID)
|
|
334
|
-
.mockResolvedValueOnce(mockToolCallResponse)
|
|
335
|
-
.mockResolvedValueOnce({
|
|
368
|
+
const mockFinalChunk = {
|
|
336
369
|
responseMessageDto: {
|
|
337
370
|
id: "advance-response2",
|
|
338
371
|
content: [{ type: "text", text: "response 2" }],
|
|
@@ -343,12 +376,26 @@ describe("TamboThreadProvider", () => {
|
|
|
343
376
|
},
|
|
344
377
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
345
378
|
mcpAccessToken: "test-mcp-access-token",
|
|
346
|
-
}
|
|
379
|
+
};
|
|
380
|
+
const mockAsyncIterator = {
|
|
381
|
+
[Symbol.asyncIterator]: async function* () {
|
|
382
|
+
yield mockToolCallChunk;
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
const mockAsyncIterator2 = {
|
|
386
|
+
[Symbol.asyncIterator]: async function* () {
|
|
387
|
+
yield mockFinalChunk;
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
jest
|
|
391
|
+
.mocked(typescript_sdk_1.advanceStream)
|
|
392
|
+
.mockResolvedValueOnce(mockAsyncIterator)
|
|
393
|
+
.mockResolvedValueOnce(mockAsyncIterator2);
|
|
347
394
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), { wrapper: Wrapper });
|
|
348
395
|
await (0, react_1.act)(async () => {
|
|
349
396
|
await result.current.sendThreadMessage("Use tool", {
|
|
350
397
|
threadId: "test-thread-1",
|
|
351
|
-
streamResponse:
|
|
398
|
+
streamResponse: true,
|
|
352
399
|
});
|
|
353
400
|
});
|
|
354
401
|
expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.COMPLETE);
|
|
@@ -361,7 +408,7 @@ describe("TamboThreadProvider", () => {
|
|
|
361
408
|
const mockOnCallUnregisteredTool = jest
|
|
362
409
|
.fn()
|
|
363
410
|
.mockResolvedValue("unregistered-tool-result");
|
|
364
|
-
const
|
|
411
|
+
const mockUnregisteredToolCallChunk = {
|
|
365
412
|
responseMessageDto: {
|
|
366
413
|
id: "unregistered-tool-call-1",
|
|
367
414
|
content: [{ type: "text", text: "Unregistered tool response" }],
|
|
@@ -379,10 +426,7 @@ describe("TamboThreadProvider", () => {
|
|
|
379
426
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
380
427
|
mcpAccessToken: "test-mcp-access-token",
|
|
381
428
|
};
|
|
382
|
-
|
|
383
|
-
.mocked(mockThreadsApi.advanceByID)
|
|
384
|
-
.mockResolvedValueOnce(mockUnregisteredToolCallResponse)
|
|
385
|
-
.mockResolvedValueOnce({
|
|
429
|
+
const mockFinalChunk = {
|
|
386
430
|
responseMessageDto: {
|
|
387
431
|
id: "advance-response2",
|
|
388
432
|
content: [{ type: "text", text: "response 2" }],
|
|
@@ -393,7 +437,21 @@ describe("TamboThreadProvider", () => {
|
|
|
393
437
|
},
|
|
394
438
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
395
439
|
mcpAccessToken: "test-mcp-access-token",
|
|
396
|
-
}
|
|
440
|
+
};
|
|
441
|
+
const mockAsyncIterator = {
|
|
442
|
+
[Symbol.asyncIterator]: async function* () {
|
|
443
|
+
yield mockUnregisteredToolCallChunk;
|
|
444
|
+
},
|
|
445
|
+
};
|
|
446
|
+
const mockAsyncIterator2 = {
|
|
447
|
+
[Symbol.asyncIterator]: async function* () {
|
|
448
|
+
yield mockFinalChunk;
|
|
449
|
+
},
|
|
450
|
+
};
|
|
451
|
+
jest
|
|
452
|
+
.mocked(typescript_sdk_1.advanceStream)
|
|
453
|
+
.mockResolvedValueOnce(mockAsyncIterator)
|
|
454
|
+
.mockResolvedValueOnce(mockAsyncIterator2);
|
|
397
455
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
398
456
|
wrapper: createWrapper({
|
|
399
457
|
onCallUnregisteredTool: mockOnCallUnregisteredTool,
|
|
@@ -402,14 +460,14 @@ describe("TamboThreadProvider", () => {
|
|
|
402
460
|
await (0, react_1.act)(async () => {
|
|
403
461
|
await result.current.sendThreadMessage("Use unregistered tool", {
|
|
404
462
|
threadId: "test-thread-1",
|
|
405
|
-
streamResponse:
|
|
463
|
+
streamResponse: true,
|
|
406
464
|
});
|
|
407
465
|
});
|
|
408
466
|
expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.COMPLETE);
|
|
409
467
|
expect(mockOnCallUnregisteredTool).toHaveBeenCalledWith("unregistered-tool", [{ parameterName: "input", parameterValue: "test-input" }]);
|
|
410
468
|
});
|
|
411
469
|
it("should handle unregistered tool calls without onCallUnregisteredTool", async () => {
|
|
412
|
-
const
|
|
470
|
+
const mockUnregisteredToolCallChunk = {
|
|
413
471
|
responseMessageDto: {
|
|
414
472
|
id: "unregistered-tool-call-1",
|
|
415
473
|
content: [{ type: "text", text: "Unregistered tool response" }],
|
|
@@ -427,10 +485,7 @@ describe("TamboThreadProvider", () => {
|
|
|
427
485
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
428
486
|
mcpAccessToken: "test-mcp-access-token",
|
|
429
487
|
};
|
|
430
|
-
|
|
431
|
-
.mocked(mockThreadsApi.advanceByID)
|
|
432
|
-
.mockResolvedValueOnce(mockUnregisteredToolCallResponse)
|
|
433
|
-
.mockResolvedValueOnce({
|
|
488
|
+
const mockFinalChunk = {
|
|
434
489
|
responseMessageDto: {
|
|
435
490
|
id: "advance-response2",
|
|
436
491
|
content: [{ type: "text", text: "response 2" }],
|
|
@@ -441,12 +496,26 @@ describe("TamboThreadProvider", () => {
|
|
|
441
496
|
},
|
|
442
497
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
443
498
|
mcpAccessToken: "test-mcp-access-token",
|
|
444
|
-
}
|
|
499
|
+
};
|
|
500
|
+
const mockAsyncIterator = {
|
|
501
|
+
[Symbol.asyncIterator]: async function* () {
|
|
502
|
+
yield mockUnregisteredToolCallChunk;
|
|
503
|
+
},
|
|
504
|
+
};
|
|
505
|
+
const mockAsyncIterator2 = {
|
|
506
|
+
[Symbol.asyncIterator]: async function* () {
|
|
507
|
+
yield mockFinalChunk;
|
|
508
|
+
},
|
|
509
|
+
};
|
|
510
|
+
jest
|
|
511
|
+
.mocked(typescript_sdk_1.advanceStream)
|
|
512
|
+
.mockResolvedValueOnce(mockAsyncIterator)
|
|
513
|
+
.mockResolvedValueOnce(mockAsyncIterator2);
|
|
445
514
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), { wrapper: Wrapper });
|
|
446
515
|
await (0, react_1.act)(async () => {
|
|
447
516
|
await result.current.sendThreadMessage("Use unregistered tool", {
|
|
448
517
|
threadId: "test-thread-1",
|
|
449
|
-
streamResponse:
|
|
518
|
+
streamResponse: true,
|
|
450
519
|
});
|
|
451
520
|
});
|
|
452
521
|
expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.COMPLETE);
|
|
@@ -507,77 +576,16 @@ describe("TamboThreadProvider", () => {
|
|
|
507
576
|
expect(mockThreadsApi.advance).not.toHaveBeenCalled();
|
|
508
577
|
expect(mockThreadsApi.advanceByID).not.toHaveBeenCalled();
|
|
509
578
|
});
|
|
510
|
-
it("should
|
|
511
|
-
// Use wrapper with streaming=true to show that explicit streamResponse=false overrides provider setting
|
|
579
|
+
it("should throw error when streamResponse=false (non-streaming not supported)", async () => {
|
|
512
580
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
513
581
|
wrapper: createWrapper({ streaming: true }),
|
|
514
582
|
});
|
|
515
583
|
await (0, react_1.act)(async () => {
|
|
516
|
-
await result.current.sendThreadMessage("Hello non-streaming", {
|
|
584
|
+
await expect(result.current.sendThreadMessage("Hello non-streaming", {
|
|
517
585
|
threadId: "test-thread-1",
|
|
518
586
|
streamResponse: false,
|
|
519
|
-
|
|
520
|
-
custom: {
|
|
521
|
-
message: "additional instructions",
|
|
522
|
-
},
|
|
523
|
-
},
|
|
524
|
-
});
|
|
525
|
-
});
|
|
526
|
-
expect(mockThreadsApi.advanceByID).toHaveBeenCalledWith("test-thread-1", {
|
|
527
|
-
messageToAppend: {
|
|
528
|
-
content: [{ type: "text", text: "Hello non-streaming" }],
|
|
529
|
-
role: "user",
|
|
530
|
-
additionalContext: {
|
|
531
|
-
custom: {
|
|
532
|
-
message: "additional instructions",
|
|
533
|
-
},
|
|
534
|
-
},
|
|
535
|
-
},
|
|
536
|
-
availableComponents: (0, tools_1.serializeRegistry)(mockRegistry),
|
|
537
|
-
contextKey: undefined,
|
|
538
|
-
clientTools: [],
|
|
539
|
-
forceToolChoice: undefined,
|
|
540
|
-
toolCallCounts: {},
|
|
541
|
-
});
|
|
542
|
-
// Should not call advance or advanceStream
|
|
543
|
-
expect(mockThreadsApi.advance).not.toHaveBeenCalled();
|
|
544
|
-
expect(typescript_sdk_1.advanceStream).not.toHaveBeenCalled();
|
|
545
|
-
});
|
|
546
|
-
it("should call advanceById when streamResponse is undefined and provider streaming=false", async () => {
|
|
547
|
-
// Use wrapper with streaming=false to test that undefined streamResponse respects provider setting
|
|
548
|
-
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
549
|
-
wrapper: createWrapper({ streaming: false }),
|
|
550
|
-
});
|
|
551
|
-
await (0, react_1.act)(async () => {
|
|
552
|
-
await result.current.sendThreadMessage("Hello default", {
|
|
553
|
-
threadId: "test-thread-1",
|
|
554
|
-
// streamResponse is undefined, should use provider's streaming=false
|
|
555
|
-
additionalContext: {
|
|
556
|
-
custom: {
|
|
557
|
-
message: "additional instructions",
|
|
558
|
-
},
|
|
559
|
-
},
|
|
560
|
-
});
|
|
561
|
-
});
|
|
562
|
-
expect(mockThreadsApi.advanceByID).toHaveBeenCalledWith("test-thread-1", {
|
|
563
|
-
messageToAppend: {
|
|
564
|
-
content: [{ type: "text", text: "Hello default" }],
|
|
565
|
-
role: "user",
|
|
566
|
-
additionalContext: {
|
|
567
|
-
custom: {
|
|
568
|
-
message: "additional instructions",
|
|
569
|
-
},
|
|
570
|
-
},
|
|
571
|
-
},
|
|
572
|
-
availableComponents: (0, tools_1.serializeRegistry)(mockRegistry),
|
|
573
|
-
contextKey: undefined,
|
|
574
|
-
clientTools: [],
|
|
575
|
-
forceToolChoice: undefined,
|
|
576
|
-
toolCallCounts: {},
|
|
587
|
+
})).rejects.toThrow();
|
|
577
588
|
});
|
|
578
|
-
// Should not call advance or advanceStream
|
|
579
|
-
expect(mockThreadsApi.advance).not.toHaveBeenCalled();
|
|
580
|
-
expect(typescript_sdk_1.advanceStream).not.toHaveBeenCalled();
|
|
581
589
|
});
|
|
582
590
|
it("should call advanceStream when streamResponse is undefined and provider streaming=true (default)", async () => {
|
|
583
591
|
const mockStreamResponse = {
|
|
@@ -633,44 +641,6 @@ describe("TamboThreadProvider", () => {
|
|
|
633
641
|
expect(mockThreadsApi.advance).not.toHaveBeenCalled();
|
|
634
642
|
expect(mockThreadsApi.advanceByID).not.toHaveBeenCalled();
|
|
635
643
|
});
|
|
636
|
-
it("should call advance when streamResponse=false for placeholder thread", async () => {
|
|
637
|
-
// Use wrapper with streaming=true to show that explicit streamResponse=false overrides provider setting
|
|
638
|
-
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
639
|
-
wrapper: createWrapper({ streaming: true }),
|
|
640
|
-
});
|
|
641
|
-
// Start with placeholder thread (which is the default state)
|
|
642
|
-
expect(result.current.thread.id).toBe("placeholder");
|
|
643
|
-
await (0, react_1.act)(async () => {
|
|
644
|
-
await result.current.sendThreadMessage("Hello new thread", {
|
|
645
|
-
threadId: "placeholder",
|
|
646
|
-
streamResponse: false,
|
|
647
|
-
additionalContext: {
|
|
648
|
-
custom: {
|
|
649
|
-
message: "additional instructions",
|
|
650
|
-
},
|
|
651
|
-
},
|
|
652
|
-
});
|
|
653
|
-
});
|
|
654
|
-
expect(mockThreadsApi.advance).toHaveBeenCalledWith({
|
|
655
|
-
messageToAppend: {
|
|
656
|
-
content: [{ type: "text", text: "Hello new thread" }],
|
|
657
|
-
role: "user",
|
|
658
|
-
additionalContext: {
|
|
659
|
-
custom: {
|
|
660
|
-
message: "additional instructions",
|
|
661
|
-
},
|
|
662
|
-
},
|
|
663
|
-
},
|
|
664
|
-
availableComponents: (0, tools_1.serializeRegistry)(mockRegistry),
|
|
665
|
-
contextKey: undefined,
|
|
666
|
-
clientTools: [],
|
|
667
|
-
forceToolChoice: undefined,
|
|
668
|
-
toolCallCounts: {},
|
|
669
|
-
});
|
|
670
|
-
// Should not call advanceById or advanceStream
|
|
671
|
-
expect(mockThreadsApi.advanceByID).not.toHaveBeenCalled();
|
|
672
|
-
expect(typescript_sdk_1.advanceStream).not.toHaveBeenCalled();
|
|
673
|
-
});
|
|
674
644
|
it("should call advanceStream when streamResponse=true for placeholder thread", async () => {
|
|
675
645
|
const mockStreamResponse = {
|
|
676
646
|
responseMessageDto: {
|
|
@@ -817,10 +787,10 @@ describe("TamboThreadProvider", () => {
|
|
|
817
787
|
});
|
|
818
788
|
});
|
|
819
789
|
describe("error handling", () => {
|
|
820
|
-
it("should set generation stage to ERROR when
|
|
821
|
-
const testError = new Error("API call failed");
|
|
822
|
-
// Mock
|
|
823
|
-
jest.mocked(
|
|
790
|
+
it("should set generation stage to ERROR when streaming sendThreadMessage fails", async () => {
|
|
791
|
+
const testError = new Error("Streaming API call failed");
|
|
792
|
+
// Mock advanceStream to throw an error
|
|
793
|
+
jest.mocked(typescript_sdk_1.advanceStream).mockRejectedValue(testError);
|
|
824
794
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
825
795
|
wrapper: Wrapper,
|
|
826
796
|
});
|
|
@@ -829,48 +799,91 @@ describe("TamboThreadProvider", () => {
|
|
|
829
799
|
await result.current.switchCurrentThread("test-thread-1");
|
|
830
800
|
await expect(result.current.sendThreadMessage("Hello", {
|
|
831
801
|
threadId: "test-thread-1",
|
|
832
|
-
streamResponse:
|
|
833
|
-
})).rejects.toThrow("API call failed");
|
|
802
|
+
streamResponse: true,
|
|
803
|
+
})).rejects.toThrow("Streaming API call failed");
|
|
834
804
|
});
|
|
835
805
|
// Verify generation stage is set to ERROR
|
|
836
806
|
expect(result.current.generationStage).toBe(generate_component_response_1.GenerationStage.ERROR);
|
|
837
807
|
});
|
|
838
|
-
it("should
|
|
839
|
-
const testError = new Error("
|
|
840
|
-
// Mock advanceStream to throw an error
|
|
808
|
+
it("should rollback optimistic user message when sendThreadMessage fails", async () => {
|
|
809
|
+
const testError = new Error("API call failed");
|
|
841
810
|
jest.mocked(typescript_sdk_1.advanceStream).mockRejectedValue(testError);
|
|
842
811
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
843
812
|
wrapper: Wrapper,
|
|
844
813
|
});
|
|
845
|
-
// Expect the error to be thrown
|
|
846
814
|
await (0, react_1.act)(async () => {
|
|
847
815
|
await result.current.switchCurrentThread("test-thread-1");
|
|
816
|
+
});
|
|
817
|
+
const initialMessageCount = result.current.thread.messages.length;
|
|
818
|
+
await (0, react_1.act)(async () => {
|
|
848
819
|
await expect(result.current.sendThreadMessage("Hello", {
|
|
849
820
|
threadId: "test-thread-1",
|
|
850
821
|
streamResponse: true,
|
|
851
|
-
})).rejects.toThrow("
|
|
822
|
+
})).rejects.toThrow("API call failed");
|
|
852
823
|
});
|
|
853
|
-
// Verify
|
|
854
|
-
expect(result.current.
|
|
824
|
+
// Verify user message was rolled back
|
|
825
|
+
expect(result.current.thread.messages.length).toBe(initialMessageCount);
|
|
855
826
|
});
|
|
856
|
-
it("should
|
|
857
|
-
const testError = new Error("
|
|
858
|
-
|
|
859
|
-
jest.mocked(mockThreadsApi.advance).mockRejectedValue(testError);
|
|
827
|
+
it("should rollback optimistic message when addThreadMessage fails", async () => {
|
|
828
|
+
const testError = new Error("Create message failed");
|
|
829
|
+
jest.mocked(mockThreadsApi.messages.create).mockRejectedValue(testError);
|
|
860
830
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
861
831
|
wrapper: Wrapper,
|
|
862
832
|
});
|
|
863
|
-
// Start with placeholder thread (which is the default state)
|
|
864
|
-
expect(result.current.thread.id).toBe("placeholder");
|
|
865
|
-
// Expect the error to be thrown
|
|
866
833
|
await (0, react_1.act)(async () => {
|
|
867
|
-
await
|
|
868
|
-
threadId: "placeholder",
|
|
869
|
-
streamResponse: false,
|
|
870
|
-
})).rejects.toThrow("Advance API call failed");
|
|
834
|
+
await result.current.switchCurrentThread("test-thread-1");
|
|
871
835
|
});
|
|
872
|
-
|
|
873
|
-
|
|
836
|
+
const initialMessageCount = result.current.thread.messages.length;
|
|
837
|
+
const newMessage = createMockMessage({ threadId: "test-thread-1" });
|
|
838
|
+
await (0, react_1.act)(async () => {
|
|
839
|
+
await expect(result.current.addThreadMessage(newMessage, true)).rejects.toThrow("Create message failed");
|
|
840
|
+
});
|
|
841
|
+
// Verify message was rolled back
|
|
842
|
+
expect(result.current.thread.messages.length).toBe(initialMessageCount);
|
|
843
|
+
});
|
|
844
|
+
it("should rollback optimistic update when updateThreadMessage fails", async () => {
|
|
845
|
+
const testError = new Error("Update message failed");
|
|
846
|
+
jest.mocked(mockThreadsApi.messages.create).mockRejectedValue(testError);
|
|
847
|
+
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
848
|
+
wrapper: Wrapper,
|
|
849
|
+
});
|
|
850
|
+
await (0, react_1.act)(async () => {
|
|
851
|
+
await result.current.switchCurrentThread("test-thread-1");
|
|
852
|
+
});
|
|
853
|
+
const existingMessage = createMockMessage({
|
|
854
|
+
id: "existing-msg",
|
|
855
|
+
threadId: "test-thread-1",
|
|
856
|
+
content: [{ type: "text", text: "Old content" }],
|
|
857
|
+
});
|
|
858
|
+
await (0, react_1.act)(async () => {
|
|
859
|
+
await result.current.addThreadMessage(existingMessage, false);
|
|
860
|
+
});
|
|
861
|
+
const initialMessageCount = result.current.thread.messages.length;
|
|
862
|
+
await (0, react_1.act)(async () => {
|
|
863
|
+
await expect(result.current.updateThreadMessage("existing-msg", {
|
|
864
|
+
threadId: "test-thread-1",
|
|
865
|
+
content: [{ type: "text", text: "New content" }],
|
|
866
|
+
role: "assistant",
|
|
867
|
+
}, true)).rejects.toThrow("Update message failed");
|
|
868
|
+
});
|
|
869
|
+
// Verify message was rolled back
|
|
870
|
+
expect(result.current.thread.messages.length).toBe(initialMessageCount - 1);
|
|
871
|
+
});
|
|
872
|
+
it("should rollback optimistic name update when updateThreadName fails", async () => {
|
|
873
|
+
const testError = new Error("Update name failed");
|
|
874
|
+
jest.mocked(mockThreadsApi.update).mockRejectedValue(testError);
|
|
875
|
+
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
876
|
+
wrapper: Wrapper,
|
|
877
|
+
});
|
|
878
|
+
await (0, react_1.act)(async () => {
|
|
879
|
+
await result.current.switchCurrentThread("test-thread-1");
|
|
880
|
+
});
|
|
881
|
+
const initialName = result.current.thread.name;
|
|
882
|
+
await (0, react_1.act)(async () => {
|
|
883
|
+
await expect(result.current.updateThreadName("New Name", "test-thread-1")).rejects.toThrow("Update name failed");
|
|
884
|
+
});
|
|
885
|
+
// Verify name was rolled back
|
|
886
|
+
expect(result.current.thread.name).toBe(initialName);
|
|
874
887
|
});
|
|
875
888
|
});
|
|
876
889
|
describe("refetch threads list behavior", () => {
|
|
@@ -878,8 +891,8 @@ describe("TamboThreadProvider", () => {
|
|
|
878
891
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
879
892
|
wrapper: Wrapper,
|
|
880
893
|
});
|
|
881
|
-
// Mock the
|
|
882
|
-
const
|
|
894
|
+
// Mock the stream response to return a new thread ID
|
|
895
|
+
const mockStreamResponse = {
|
|
883
896
|
responseMessageDto: {
|
|
884
897
|
id: "response-1",
|
|
885
898
|
content: [{ type: "text", text: "Response" }],
|
|
@@ -892,16 +905,19 @@ describe("TamboThreadProvider", () => {
|
|
|
892
905
|
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
893
906
|
mcpAccessToken: "test-mcp-access-token",
|
|
894
907
|
};
|
|
895
|
-
|
|
896
|
-
.
|
|
897
|
-
|
|
908
|
+
const mockAsyncIterator = {
|
|
909
|
+
[Symbol.asyncIterator]: async function* () {
|
|
910
|
+
yield mockStreamResponse;
|
|
911
|
+
},
|
|
912
|
+
};
|
|
913
|
+
jest.mocked(typescript_sdk_1.advanceStream).mockResolvedValue(mockAsyncIterator);
|
|
898
914
|
// Start with placeholder thread
|
|
899
915
|
expect(result.current.thread.id).toBe("placeholder");
|
|
900
916
|
// Send a message which will create a new thread with contextKey
|
|
901
917
|
await (0, react_1.act)(async () => {
|
|
902
918
|
await result.current.sendThreadMessage("Hello", {
|
|
903
919
|
threadId: "placeholder",
|
|
904
|
-
streamResponse:
|
|
920
|
+
streamResponse: true,
|
|
905
921
|
contextKey: "test-context-key",
|
|
906
922
|
});
|
|
907
923
|
});
|
|
@@ -939,93 +955,6 @@ describe("TamboThreadProvider", () => {
|
|
|
939
955
|
});
|
|
940
956
|
});
|
|
941
957
|
describe("transformToContent", () => {
|
|
942
|
-
it("should use custom transformToContent when provided (non-streaming)", async () => {
|
|
943
|
-
const mockTransformToContent = jest.fn().mockReturnValue([
|
|
944
|
-
{ type: "text", text: "Custom transformed content" },
|
|
945
|
-
{
|
|
946
|
-
type: "image_url",
|
|
947
|
-
image_url: { url: "https://example.com/image.png" },
|
|
948
|
-
},
|
|
949
|
-
]);
|
|
950
|
-
const customToolRegistry = [
|
|
951
|
-
{
|
|
952
|
-
name: "TestComponent",
|
|
953
|
-
component: () => react_2.default.createElement("div", null, "Test"),
|
|
954
|
-
description: "Test",
|
|
955
|
-
propsSchema: v4_1.z.object({ test: v4_1.z.string() }),
|
|
956
|
-
associatedTools: [
|
|
957
|
-
{
|
|
958
|
-
name: "custom-tool",
|
|
959
|
-
tool: jest.fn().mockResolvedValue({ data: "tool result" }),
|
|
960
|
-
description: "Tool with custom transform",
|
|
961
|
-
inputSchema: v4_1.z.object({ input: v4_1.z.string() }),
|
|
962
|
-
outputSchema: v4_1.z.object({ data: v4_1.z.string() }),
|
|
963
|
-
transformToContent: mockTransformToContent,
|
|
964
|
-
},
|
|
965
|
-
],
|
|
966
|
-
},
|
|
967
|
-
];
|
|
968
|
-
const mockToolCallResponse = {
|
|
969
|
-
responseMessageDto: {
|
|
970
|
-
id: "tool-call-1",
|
|
971
|
-
content: [{ type: "text", text: "Tool response" }],
|
|
972
|
-
role: "tool",
|
|
973
|
-
threadId: "test-thread-1",
|
|
974
|
-
toolCallRequest: {
|
|
975
|
-
toolName: "custom-tool",
|
|
976
|
-
parameters: [{ parameterName: "input", parameterValue: "test" }],
|
|
977
|
-
},
|
|
978
|
-
componentState: {},
|
|
979
|
-
createdAt: new Date().toISOString(),
|
|
980
|
-
},
|
|
981
|
-
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
982
|
-
mcpAccessToken: "test-mcp-access-token",
|
|
983
|
-
};
|
|
984
|
-
jest
|
|
985
|
-
.mocked(mockThreadsApi.advanceByID)
|
|
986
|
-
.mockResolvedValueOnce(mockToolCallResponse)
|
|
987
|
-
.mockResolvedValueOnce({
|
|
988
|
-
responseMessageDto: {
|
|
989
|
-
id: "final-response",
|
|
990
|
-
content: [{ type: "text", text: "Final response" }],
|
|
991
|
-
role: "assistant",
|
|
992
|
-
threadId: "test-thread-1",
|
|
993
|
-
componentState: {},
|
|
994
|
-
createdAt: new Date().toISOString(),
|
|
995
|
-
},
|
|
996
|
-
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
997
|
-
mcpAccessToken: "test-mcp-access-token",
|
|
998
|
-
});
|
|
999
|
-
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
1000
|
-
wrapper: createWrapper({ components: customToolRegistry }),
|
|
1001
|
-
});
|
|
1002
|
-
await (0, react_1.act)(async () => {
|
|
1003
|
-
await result.current.sendThreadMessage("Use custom tool", {
|
|
1004
|
-
threadId: "test-thread-1",
|
|
1005
|
-
streamResponse: false,
|
|
1006
|
-
});
|
|
1007
|
-
});
|
|
1008
|
-
// Verify the tool was called with single object arg (new inputSchema interface)
|
|
1009
|
-
expect(customToolRegistry[0]?.associatedTools?.[0]?.tool).toHaveBeenCalledWith({ input: "test" });
|
|
1010
|
-
// Verify transformToContent was called with the tool result
|
|
1011
|
-
expect(mockTransformToContent).toHaveBeenCalledWith({
|
|
1012
|
-
data: "tool result",
|
|
1013
|
-
});
|
|
1014
|
-
// Verify the second advance call included the transformed content
|
|
1015
|
-
expect(mockThreadsApi.advanceByID).toHaveBeenCalledTimes(2);
|
|
1016
|
-
expect(mockThreadsApi.advanceByID).toHaveBeenLastCalledWith("test-thread-1", expect.objectContaining({
|
|
1017
|
-
messageToAppend: expect.objectContaining({
|
|
1018
|
-
content: [
|
|
1019
|
-
{ type: "text", text: "Custom transformed content" },
|
|
1020
|
-
{
|
|
1021
|
-
type: "image_url",
|
|
1022
|
-
image_url: { url: "https://example.com/image.png" },
|
|
1023
|
-
},
|
|
1024
|
-
],
|
|
1025
|
-
role: "tool",
|
|
1026
|
-
}),
|
|
1027
|
-
}));
|
|
1028
|
-
});
|
|
1029
958
|
it("should use custom async transformToContent when provided (streaming)", async () => {
|
|
1030
959
|
const mockTransformToContent = jest
|
|
1031
960
|
.fn()
|
|
@@ -1122,169 +1051,6 @@ describe("TamboThreadProvider", () => {
|
|
|
1122
1051
|
}),
|
|
1123
1052
|
}), "test-thread-1");
|
|
1124
1053
|
});
|
|
1125
|
-
it("should fallback to stringified text when transformToContent is not provided", async () => {
|
|
1126
|
-
const toolWithoutTransform = [
|
|
1127
|
-
{
|
|
1128
|
-
name: "TestComponent",
|
|
1129
|
-
component: () => react_2.default.createElement("div", null, "Test"),
|
|
1130
|
-
description: "Test",
|
|
1131
|
-
propsSchema: v4_1.z.object({ test: v4_1.z.string() }),
|
|
1132
|
-
associatedTools: [
|
|
1133
|
-
{
|
|
1134
|
-
name: "no-transform-tool",
|
|
1135
|
-
tool: jest
|
|
1136
|
-
.fn()
|
|
1137
|
-
.mockResolvedValue({ complex: "data", nested: { value: 42 } }),
|
|
1138
|
-
description: "Tool without custom transform",
|
|
1139
|
-
inputSchema: v4_1.z.object({ input: v4_1.z.string() }),
|
|
1140
|
-
outputSchema: v4_1.z.object({
|
|
1141
|
-
complex: v4_1.z.string(),
|
|
1142
|
-
nested: v4_1.z.object({ value: v4_1.z.number() }),
|
|
1143
|
-
}),
|
|
1144
|
-
// No transformToContent provided
|
|
1145
|
-
},
|
|
1146
|
-
],
|
|
1147
|
-
},
|
|
1148
|
-
];
|
|
1149
|
-
const mockToolCallResponse = {
|
|
1150
|
-
responseMessageDto: {
|
|
1151
|
-
id: "tool-call-1",
|
|
1152
|
-
content: [{ type: "text", text: "Tool call" }],
|
|
1153
|
-
role: "tool",
|
|
1154
|
-
threadId: "test-thread-1",
|
|
1155
|
-
toolCallRequest: {
|
|
1156
|
-
toolName: "no-transform-tool",
|
|
1157
|
-
parameters: [{ parameterName: "input", parameterValue: "test" }],
|
|
1158
|
-
},
|
|
1159
|
-
componentState: {},
|
|
1160
|
-
createdAt: new Date().toISOString(),
|
|
1161
|
-
},
|
|
1162
|
-
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
1163
|
-
mcpAccessToken: "test-mcp-access-token",
|
|
1164
|
-
};
|
|
1165
|
-
jest
|
|
1166
|
-
.mocked(mockThreadsApi.advanceByID)
|
|
1167
|
-
.mockResolvedValueOnce(mockToolCallResponse)
|
|
1168
|
-
.mockResolvedValueOnce({
|
|
1169
|
-
responseMessageDto: {
|
|
1170
|
-
id: "final-response",
|
|
1171
|
-
content: [{ type: "text", text: "Final response" }],
|
|
1172
|
-
role: "assistant",
|
|
1173
|
-
threadId: "test-thread-1",
|
|
1174
|
-
componentState: {},
|
|
1175
|
-
createdAt: new Date().toISOString(),
|
|
1176
|
-
},
|
|
1177
|
-
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
1178
|
-
mcpAccessToken: "test-mcp-access-token",
|
|
1179
|
-
});
|
|
1180
|
-
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
1181
|
-
wrapper: createWrapper({ components: toolWithoutTransform }),
|
|
1182
|
-
});
|
|
1183
|
-
await (0, react_1.act)(async () => {
|
|
1184
|
-
await result.current.sendThreadMessage("Use tool without transform", {
|
|
1185
|
-
threadId: "test-thread-1",
|
|
1186
|
-
streamResponse: false,
|
|
1187
|
-
});
|
|
1188
|
-
});
|
|
1189
|
-
// Verify the tool was called with single object arg (new inputSchema interface)
|
|
1190
|
-
expect(toolWithoutTransform[0]?.associatedTools?.[0]?.tool).toHaveBeenCalledWith({ input: "test" });
|
|
1191
|
-
// Verify the second advance call used stringified content
|
|
1192
|
-
expect(mockThreadsApi.advanceByID).toHaveBeenLastCalledWith("test-thread-1", expect.objectContaining({
|
|
1193
|
-
messageToAppend: expect.objectContaining({
|
|
1194
|
-
content: [
|
|
1195
|
-
{
|
|
1196
|
-
type: "text",
|
|
1197
|
-
text: '{"complex":"data","nested":{"value":42}}',
|
|
1198
|
-
},
|
|
1199
|
-
],
|
|
1200
|
-
role: "tool",
|
|
1201
|
-
}),
|
|
1202
|
-
}));
|
|
1203
|
-
});
|
|
1204
|
-
it("should always return text for error responses even with transformToContent", async () => {
|
|
1205
|
-
const mockTransformToContent = jest.fn().mockReturnValue([
|
|
1206
|
-
{
|
|
1207
|
-
type: "image_url",
|
|
1208
|
-
image_url: { url: "https://example.com/error.png" },
|
|
1209
|
-
},
|
|
1210
|
-
]);
|
|
1211
|
-
const toolWithTransform = [
|
|
1212
|
-
{
|
|
1213
|
-
name: "TestComponent",
|
|
1214
|
-
component: () => react_2.default.createElement("div", null, "Test"),
|
|
1215
|
-
description: "Test",
|
|
1216
|
-
propsSchema: v4_1.z.object({ test: v4_1.z.string() }),
|
|
1217
|
-
associatedTools: [
|
|
1218
|
-
{
|
|
1219
|
-
name: "error-tool",
|
|
1220
|
-
tool: jest
|
|
1221
|
-
.fn()
|
|
1222
|
-
.mockRejectedValue(new Error("Tool execution failed")),
|
|
1223
|
-
description: "Tool that errors",
|
|
1224
|
-
inputSchema: v4_1.z.object({ input: v4_1.z.string() }),
|
|
1225
|
-
outputSchema: v4_1.z.string(),
|
|
1226
|
-
transformToContent: mockTransformToContent,
|
|
1227
|
-
},
|
|
1228
|
-
],
|
|
1229
|
-
},
|
|
1230
|
-
];
|
|
1231
|
-
const mockToolCallResponse = {
|
|
1232
|
-
responseMessageDto: {
|
|
1233
|
-
id: "tool-call-1",
|
|
1234
|
-
content: [{ type: "text", text: "Tool call" }],
|
|
1235
|
-
role: "tool",
|
|
1236
|
-
threadId: "test-thread-1",
|
|
1237
|
-
toolCallRequest: {
|
|
1238
|
-
toolName: "error-tool",
|
|
1239
|
-
parameters: [{ parameterName: "input", parameterValue: "test" }],
|
|
1240
|
-
},
|
|
1241
|
-
componentState: {},
|
|
1242
|
-
createdAt: new Date().toISOString(),
|
|
1243
|
-
},
|
|
1244
|
-
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
1245
|
-
mcpAccessToken: "test-mcp-access-token",
|
|
1246
|
-
};
|
|
1247
|
-
jest
|
|
1248
|
-
.mocked(mockThreadsApi.advanceByID)
|
|
1249
|
-
.mockResolvedValueOnce(mockToolCallResponse)
|
|
1250
|
-
.mockResolvedValueOnce({
|
|
1251
|
-
responseMessageDto: {
|
|
1252
|
-
id: "final-response",
|
|
1253
|
-
content: [{ type: "text", text: "Final response" }],
|
|
1254
|
-
role: "assistant",
|
|
1255
|
-
threadId: "test-thread-1",
|
|
1256
|
-
componentState: {},
|
|
1257
|
-
createdAt: new Date().toISOString(),
|
|
1258
|
-
},
|
|
1259
|
-
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
1260
|
-
mcpAccessToken: "test-mcp-access-token",
|
|
1261
|
-
});
|
|
1262
|
-
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
1263
|
-
wrapper: createWrapper({ components: toolWithTransform }),
|
|
1264
|
-
});
|
|
1265
|
-
await (0, react_1.act)(async () => {
|
|
1266
|
-
await result.current.sendThreadMessage("Use error tool", {
|
|
1267
|
-
threadId: "test-thread-1",
|
|
1268
|
-
streamResponse: false,
|
|
1269
|
-
});
|
|
1270
|
-
});
|
|
1271
|
-
// Verify the tool was called with single object arg (new inputSchema interface)
|
|
1272
|
-
expect(toolWithTransform[0]?.associatedTools?.[0]?.tool).toHaveBeenCalledWith({ input: "test" });
|
|
1273
|
-
// Verify transformToContent was NOT called for error responses
|
|
1274
|
-
expect(mockTransformToContent).not.toHaveBeenCalled();
|
|
1275
|
-
// Verify the second advance call used text content with the error message
|
|
1276
|
-
expect(mockThreadsApi.advanceByID).toHaveBeenLastCalledWith("test-thread-1", expect.objectContaining({
|
|
1277
|
-
messageToAppend: expect.objectContaining({
|
|
1278
|
-
content: [
|
|
1279
|
-
expect.objectContaining({
|
|
1280
|
-
type: "text",
|
|
1281
|
-
// Error message should be in text format
|
|
1282
|
-
}),
|
|
1283
|
-
],
|
|
1284
|
-
role: "tool",
|
|
1285
|
-
}),
|
|
1286
|
-
}));
|
|
1287
|
-
});
|
|
1288
1054
|
});
|
|
1289
1055
|
describe("tamboStreamableHint streaming behavior", () => {
|
|
1290
1056
|
it("should call streamable tool during streaming when tamboStreamableHint is true", async () => {
|
|
@@ -1617,6 +1383,25 @@ describe("TamboThreadProvider", () => {
|
|
|
1617
1383
|
});
|
|
1618
1384
|
describe("auto-generate thread name", () => {
|
|
1619
1385
|
it("should auto-generate thread name after reaching threshold", async () => {
|
|
1386
|
+
const mockStreamResponse = {
|
|
1387
|
+
responseMessageDto: {
|
|
1388
|
+
id: "response-1",
|
|
1389
|
+
content: [{ type: "text", text: "Response" }],
|
|
1390
|
+
role: "assistant",
|
|
1391
|
+
threadId: "test-thread-1",
|
|
1392
|
+
component: undefined,
|
|
1393
|
+
componentState: {},
|
|
1394
|
+
createdAt: new Date().toISOString(),
|
|
1395
|
+
},
|
|
1396
|
+
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
1397
|
+
mcpAccessToken: "test-mcp-access-token",
|
|
1398
|
+
};
|
|
1399
|
+
const mockAsyncIterator = {
|
|
1400
|
+
[Symbol.asyncIterator]: async function* () {
|
|
1401
|
+
yield mockStreamResponse;
|
|
1402
|
+
},
|
|
1403
|
+
};
|
|
1404
|
+
jest.mocked(typescript_sdk_1.advanceStream).mockResolvedValue(mockAsyncIterator);
|
|
1620
1405
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
1621
1406
|
wrapper: createWrapper({ autoGenerateNameThreshold: 2 }),
|
|
1622
1407
|
});
|
|
@@ -1648,13 +1433,34 @@ describe("TamboThreadProvider", () => {
|
|
|
1648
1433
|
}), false);
|
|
1649
1434
|
});
|
|
1650
1435
|
await (0, react_1.act)(async () => {
|
|
1651
|
-
await result.current.sendThreadMessage("Test message"
|
|
1436
|
+
await result.current.sendThreadMessage("Test message", {
|
|
1437
|
+
streamResponse: true,
|
|
1438
|
+
});
|
|
1652
1439
|
});
|
|
1653
1440
|
expect(mockThreadsApi.generateName).toHaveBeenCalledWith("test-thread-1");
|
|
1654
1441
|
expect(result.current.thread.name).toBe("Generated Thread Name");
|
|
1655
1442
|
expect(mockQueryClient.setQueryData).toHaveBeenCalledWith(["threads", "test-project-id", undefined], expect.any(Function));
|
|
1656
1443
|
});
|
|
1657
1444
|
it("should NOT auto-generate when autoGenerateThreadName is false", async () => {
|
|
1445
|
+
const mockStreamResponse = {
|
|
1446
|
+
responseMessageDto: {
|
|
1447
|
+
id: "response-1",
|
|
1448
|
+
content: [{ type: "text", text: "Response" }],
|
|
1449
|
+
role: "assistant",
|
|
1450
|
+
threadId: "test-thread-1",
|
|
1451
|
+
component: undefined,
|
|
1452
|
+
componentState: {},
|
|
1453
|
+
createdAt: new Date().toISOString(),
|
|
1454
|
+
},
|
|
1455
|
+
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
1456
|
+
mcpAccessToken: "test-mcp-access-token",
|
|
1457
|
+
};
|
|
1458
|
+
const mockAsyncIterator = {
|
|
1459
|
+
[Symbol.asyncIterator]: async function* () {
|
|
1460
|
+
yield mockStreamResponse;
|
|
1461
|
+
},
|
|
1462
|
+
};
|
|
1463
|
+
jest.mocked(typescript_sdk_1.advanceStream).mockResolvedValue(mockAsyncIterator);
|
|
1658
1464
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
1659
1465
|
wrapper: createWrapper({
|
|
1660
1466
|
autoGenerateThreadName: false,
|
|
@@ -1686,12 +1492,33 @@ describe("TamboThreadProvider", () => {
|
|
|
1686
1492
|
}), false);
|
|
1687
1493
|
});
|
|
1688
1494
|
await (0, react_1.act)(async () => {
|
|
1689
|
-
await result.current.sendThreadMessage("Test message"
|
|
1495
|
+
await result.current.sendThreadMessage("Test message", {
|
|
1496
|
+
streamResponse: true,
|
|
1497
|
+
});
|
|
1690
1498
|
});
|
|
1691
1499
|
// Should NOT generate name because feature is disabled
|
|
1692
1500
|
expect(mockThreadsApi.generateName).not.toHaveBeenCalled();
|
|
1693
1501
|
});
|
|
1694
1502
|
it("should NOT auto-generate when thread already has a name", async () => {
|
|
1503
|
+
const mockStreamResponse = {
|
|
1504
|
+
responseMessageDto: {
|
|
1505
|
+
id: "response-1",
|
|
1506
|
+
content: [{ type: "text", text: "Response" }],
|
|
1507
|
+
role: "assistant",
|
|
1508
|
+
threadId: "test-thread-1",
|
|
1509
|
+
component: undefined,
|
|
1510
|
+
componentState: {},
|
|
1511
|
+
createdAt: new Date().toISOString(),
|
|
1512
|
+
},
|
|
1513
|
+
generationStage: generate_component_response_1.GenerationStage.COMPLETE,
|
|
1514
|
+
mcpAccessToken: "test-mcp-access-token",
|
|
1515
|
+
};
|
|
1516
|
+
const mockAsyncIterator = {
|
|
1517
|
+
[Symbol.asyncIterator]: async function* () {
|
|
1518
|
+
yield mockStreamResponse;
|
|
1519
|
+
},
|
|
1520
|
+
};
|
|
1521
|
+
jest.mocked(typescript_sdk_1.advanceStream).mockResolvedValue(mockAsyncIterator);
|
|
1695
1522
|
const { result } = (0, react_1.renderHook)(() => (0, tambo_thread_provider_1.useTamboThread)(), {
|
|
1696
1523
|
wrapper: createWrapper({ autoGenerateNameThreshold: 2 }),
|
|
1697
1524
|
});
|
|
@@ -1725,7 +1552,9 @@ describe("TamboThreadProvider", () => {
|
|
|
1725
1552
|
expect(result.current.thread.messages).toHaveLength(2);
|
|
1726
1553
|
// Send another message to reach threshold (3 messages total)
|
|
1727
1554
|
await (0, react_1.act)(async () => {
|
|
1728
|
-
await result.current.sendThreadMessage("Test message"
|
|
1555
|
+
await result.current.sendThreadMessage("Test message", {
|
|
1556
|
+
streamResponse: true,
|
|
1557
|
+
});
|
|
1729
1558
|
});
|
|
1730
1559
|
// Should NOT generate name because thread already has one
|
|
1731
1560
|
expect(mockThreadsApi.generateName).not.toHaveBeenCalled();
|