@tambo-ai/react 0.32.1 → 0.34.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.
Files changed (59) hide show
  1. package/dist/hooks/__tests__/use-tambo-stream-status.test.d.ts +2 -0
  2. package/dist/hooks/__tests__/use-tambo-stream-status.test.d.ts.map +1 -0
  3. package/dist/hooks/__tests__/use-tambo-stream-status.test.js +335 -0
  4. package/dist/hooks/__tests__/use-tambo-stream-status.test.js.map +1 -0
  5. package/dist/hooks/index.d.ts +1 -0
  6. package/dist/hooks/index.d.ts.map +1 -1
  7. package/dist/hooks/index.js +3 -1
  8. package/dist/hooks/index.js.map +1 -1
  9. package/dist/hooks/use-tambo-stream-status.d.ts +89 -0
  10. package/dist/hooks/use-tambo-stream-status.d.ts.map +1 -0
  11. package/dist/hooks/use-tambo-stream-status.js +212 -0
  12. package/dist/hooks/use-tambo-stream-status.js.map +1 -0
  13. package/dist/index.d.ts +1 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +3 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/model/generate-component-response.d.ts +2 -1
  18. package/dist/model/generate-component-response.d.ts.map +1 -1
  19. package/dist/model/generate-component-response.js +2 -0
  20. package/dist/model/generate-component-response.js.map +1 -1
  21. package/dist/providers/__tests__/tambo-thread-provider.test.js +8 -0
  22. package/dist/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
  23. package/dist/providers/tambo-stubs.d.ts.map +1 -1
  24. package/dist/providers/tambo-stubs.js +4 -0
  25. package/dist/providers/tambo-stubs.js.map +1 -1
  26. package/dist/providers/tambo-thread-provider.d.ts +2 -0
  27. package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
  28. package/dist/providers/tambo-thread-provider.js +78 -2
  29. package/dist/providers/tambo-thread-provider.js.map +1 -1
  30. package/esm/hooks/__tests__/use-tambo-stream-status.test.d.ts +2 -0
  31. package/esm/hooks/__tests__/use-tambo-stream-status.test.d.ts.map +1 -0
  32. package/esm/hooks/__tests__/use-tambo-stream-status.test.js +333 -0
  33. package/esm/hooks/__tests__/use-tambo-stream-status.test.js.map +1 -0
  34. package/esm/hooks/index.d.ts +1 -0
  35. package/esm/hooks/index.d.ts.map +1 -1
  36. package/esm/hooks/index.js +1 -0
  37. package/esm/hooks/index.js.map +1 -1
  38. package/esm/hooks/use-tambo-stream-status.d.ts +89 -0
  39. package/esm/hooks/use-tambo-stream-status.d.ts.map +1 -0
  40. package/esm/hooks/use-tambo-stream-status.js +209 -0
  41. package/esm/hooks/use-tambo-stream-status.js.map +1 -0
  42. package/esm/index.d.ts +1 -0
  43. package/esm/index.d.ts.map +1 -1
  44. package/esm/index.js +1 -0
  45. package/esm/index.js.map +1 -1
  46. package/esm/model/generate-component-response.d.ts +2 -1
  47. package/esm/model/generate-component-response.d.ts.map +1 -1
  48. package/esm/model/generate-component-response.js +2 -0
  49. package/esm/model/generate-component-response.js.map +1 -1
  50. package/esm/providers/__tests__/tambo-thread-provider.test.js +8 -0
  51. package/esm/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
  52. package/esm/providers/tambo-stubs.d.ts.map +1 -1
  53. package/esm/providers/tambo-stubs.js +4 -0
  54. package/esm/providers/tambo-stubs.js.map +1 -1
  55. package/esm/providers/tambo-thread-provider.d.ts +2 -0
  56. package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
  57. package/esm/providers/tambo-thread-provider.js +79 -3
  58. package/esm/providers/tambo-thread-provider.js.map +1 -1
  59. package/package.json +11 -11
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=use-tambo-stream-status.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-stream-status.test.d.ts","sourceRoot":"","sources":["../../../src/hooks/__tests__/use-tambo-stream-status.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,335 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const react_1 = require("@testing-library/react");
4
+ const generate_component_response_1 = require("../../model/generate-component-response");
5
+ const tambo_thread_provider_1 = require("../../providers/tambo-thread-provider");
6
+ const use_current_message_1 = require("../use-current-message");
7
+ const use_tambo_stream_status_1 = require("../use-tambo-stream-status");
8
+ // Mock the required providers
9
+ jest.mock("../../providers/tambo-thread-provider", () => ({
10
+ useTamboThread: jest.fn(),
11
+ }));
12
+ jest.mock("../use-current-message", () => ({
13
+ useTamboCurrentMessage: jest.fn(),
14
+ }));
15
+ // Mock window for SSR tests
16
+ const originalWindow = global.window;
17
+ // Helper function to create mock ComponentDecisionV2
18
+ const createMockComponent = (props = {}) => ({
19
+ componentName: "TestComponent",
20
+ componentState: {},
21
+ message: "Component generated",
22
+ props,
23
+ reasoning: "Test reasoning",
24
+ });
25
+ // Helper function to create mock TamboThreadMessage
26
+ const createMockMessage = (overrides = {}) => ({
27
+ id: "test-message",
28
+ componentState: {},
29
+ content: [{ type: "text", text: "test content" }],
30
+ createdAt: new Date().toISOString(),
31
+ role: "assistant",
32
+ threadId: "test-thread",
33
+ ...overrides,
34
+ });
35
+ describe("useTamboStreamStatus", () => {
36
+ beforeEach(() => {
37
+ // Restore window for client-side tests
38
+ global.window = originalWindow;
39
+ // Default mock implementations
40
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
41
+ generationStage: generate_component_response_1.GenerationStage.IDLE,
42
+ });
43
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue({
44
+ id: "test-message",
45
+ component: {
46
+ props: {},
47
+ },
48
+ });
49
+ });
50
+ afterEach(() => {
51
+ jest.clearAllMocks();
52
+ });
53
+ describe("Initial State", () => {
54
+ it("should start with all flags as pending when idle and no props", () => {
55
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
56
+ generationStage: generate_component_response_1.GenerationStage.IDLE,
57
+ });
58
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
59
+ component: createMockComponent({ title: "", body: "" }),
60
+ }));
61
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
62
+ expect(result.current.streamStatus).toEqual({
63
+ isPending: true,
64
+ isStreaming: false,
65
+ isSuccess: false,
66
+ isError: false,
67
+ streamError: undefined,
68
+ });
69
+ expect(result.current.propStatus.title).toEqual({
70
+ isPending: true,
71
+ isStreaming: false,
72
+ isSuccess: false,
73
+ error: undefined,
74
+ });
75
+ expect(result.current.propStatus.body).toEqual({
76
+ isPending: true,
77
+ isStreaming: false,
78
+ isSuccess: false,
79
+ error: undefined,
80
+ });
81
+ });
82
+ });
83
+ describe("Generation vs Props Streaming", () => {
84
+ it("should show generation streaming but props still pending when STREAMING_RESPONSE with no prop content", () => {
85
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
86
+ generationStage: generate_component_response_1.GenerationStage.STREAMING_RESPONSE,
87
+ });
88
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
89
+ component: createMockComponent({ title: "", body: "" }),
90
+ }));
91
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
92
+ // Global streaming should be false because no props are actually streaming yet
93
+ expect(result.current.streamStatus.isStreaming).toBe(false);
94
+ expect(result.current.streamStatus.isPending).toBe(false);
95
+ // Individual props should be pending because they haven't started streaming yet
96
+ expect(result.current.propStatus.title.isPending).toBe(true);
97
+ expect(result.current.propStatus.title.isStreaming).toBe(false);
98
+ expect(result.current.propStatus.body.isPending).toBe(true);
99
+ expect(result.current.propStatus.body.isStreaming).toBe(false);
100
+ });
101
+ it("should show prop streaming when props receive content during STREAMING_RESPONSE", () => {
102
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
103
+ generationStage: generate_component_response_1.GenerationStage.STREAMING_RESPONSE,
104
+ });
105
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
106
+ component: createMockComponent({ title: "Hello", body: "" }),
107
+ }));
108
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
109
+ // Title prop should be streaming since it has content
110
+ expect(result.current.propStatus.title.isStreaming).toBe(true);
111
+ expect(result.current.propStatus.title.isPending).toBe(false);
112
+ // Body prop should still be pending since it has no content
113
+ expect(result.current.propStatus.body.isStreaming).toBe(false);
114
+ expect(result.current.propStatus.body.isPending).toBe(true);
115
+ // Global should be streaming because at least one prop is streaming
116
+ expect(result.current.streamStatus.isStreaming).toBe(true);
117
+ });
118
+ });
119
+ describe("Boolean Lifecycle", () => {
120
+ it("should transition through Init -> Streaming -> Success lifecycle", () => {
121
+ // Start with IDLE (Init phase)
122
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
123
+ generationStage: generate_component_response_1.GenerationStage.IDLE,
124
+ });
125
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
126
+ component: createMockComponent({ title: "", body: "" }),
127
+ }));
128
+ const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
129
+ // Phase 1: Init - isPending = true
130
+ expect(result.current.streamStatus.isPending).toBe(true);
131
+ expect(result.current.streamStatus.isStreaming).toBe(false);
132
+ expect(result.current.streamStatus.isSuccess).toBe(false);
133
+ // Phase 2: Streaming - move to STREAMING_RESPONSE with content
134
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
135
+ generationStage: generate_component_response_1.GenerationStage.STREAMING_RESPONSE,
136
+ });
137
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
138
+ component: createMockComponent({
139
+ title: "Hello World",
140
+ body: "Some content",
141
+ }),
142
+ }));
143
+ rerender();
144
+ expect(result.current.streamStatus.isPending).toBe(false);
145
+ expect(result.current.streamStatus.isStreaming).toBe(true);
146
+ expect(result.current.streamStatus.isSuccess).toBe(false);
147
+ // Phase 3: Complete - move to COMPLETE
148
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
149
+ generationStage: generate_component_response_1.GenerationStage.COMPLETE,
150
+ });
151
+ rerender();
152
+ expect(result.current.streamStatus.isPending).toBe(false);
153
+ expect(result.current.streamStatus.isStreaming).toBe(false);
154
+ expect(result.current.streamStatus.isSuccess).toBe(true);
155
+ });
156
+ it("should handle error state correctly", () => {
157
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
158
+ generationStage: generate_component_response_1.GenerationStage.ERROR,
159
+ });
160
+ const errorMessage = "Generation failed";
161
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
162
+ component: createMockComponent({ title: "", body: "" }),
163
+ error: errorMessage,
164
+ }));
165
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
166
+ expect(result.current.streamStatus.isPending).toBe(true);
167
+ expect(result.current.streamStatus.isStreaming).toBe(false);
168
+ expect(result.current.streamStatus.isSuccess).toBe(false);
169
+ expect(result.current.streamStatus.isError).toBe(true);
170
+ expect(result.current.streamStatus.streamError?.message).toBe(errorMessage);
171
+ });
172
+ });
173
+ describe("Derivation Rules", () => {
174
+ it("should derive isPending correctly (no generation activity AND all props pending)", () => {
175
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
176
+ generationStage: generate_component_response_1.GenerationStage.IDLE,
177
+ });
178
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
179
+ component: createMockComponent({ title: "", body: "", footer: "" }),
180
+ }));
181
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
182
+ // All props are pending and no generation activity
183
+ expect(result.current.streamStatus.isPending).toBe(true);
184
+ expect(result.current.propStatus.title.isPending).toBe(true);
185
+ expect(result.current.propStatus.body.isPending).toBe(true);
186
+ expect(result.current.propStatus.footer.isPending).toBe(true);
187
+ });
188
+ it("should derive isStreaming correctly (generation streaming OR any prop streaming)", () => {
189
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
190
+ generationStage: generate_component_response_1.GenerationStage.COMPLETE,
191
+ });
192
+ // One prop still streaming
193
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
194
+ component: createMockComponent({
195
+ title: "Complete Title",
196
+ body: "Still streaming...",
197
+ }),
198
+ }));
199
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
200
+ // Should be streaming because at least one prop is streaming
201
+ expect(result.current.streamStatus.isStreaming).toBe(false); // Note: this will be false in our implementation because props are considered complete when generation is COMPLETE
202
+ });
203
+ it("should derive isSuccess correctly (generation complete AND all props successful)", () => {
204
+ // Step 1: Start with streaming, props empty
205
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
206
+ generationStage: generate_component_response_1.GenerationStage.STREAMING_RESPONSE,
207
+ });
208
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
209
+ component: createMockComponent({
210
+ title: "",
211
+ body: "",
212
+ }),
213
+ }));
214
+ const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
215
+ // Step 2: Simulate streaming in title
216
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
217
+ component: createMockComponent({
218
+ title: "Complete Title",
219
+ body: "",
220
+ }),
221
+ }));
222
+ rerender();
223
+ // Step 3: Simulate streaming in body
224
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
225
+ component: createMockComponent({
226
+ title: "Complete Title",
227
+ body: "Complete Body",
228
+ }),
229
+ }));
230
+ rerender();
231
+ // Step 4: Generation complete
232
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
233
+ generationStage: generate_component_response_1.GenerationStage.COMPLETE,
234
+ });
235
+ rerender();
236
+ // Now both props should be successful
237
+ expect(result.current.propStatus.title.isSuccess).toBe(true);
238
+ expect(result.current.propStatus.body.isSuccess).toBe(true);
239
+ expect(result.current.streamStatus.isSuccess).toBe(true);
240
+ });
241
+ it("should derive isError correctly (generation error OR any prop error)", () => {
242
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
243
+ generationStage: generate_component_response_1.GenerationStage.COMPLETE,
244
+ });
245
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
246
+ component: createMockComponent({
247
+ title: "Good Title",
248
+ body: "Good Body",
249
+ }),
250
+ error: "Something went wrong",
251
+ }));
252
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
253
+ expect(result.current.streamStatus.isError).toBe(true);
254
+ expect(result.current.streamStatus.streamError?.message).toBe("Something went wrong");
255
+ });
256
+ });
257
+ describe("Type Safety", () => {
258
+ it("should provide strongly typed prop status based on generic", () => {
259
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
260
+ component: createMockComponent({
261
+ title: "Test",
262
+ description: "Test desc",
263
+ count: 42,
264
+ }),
265
+ }));
266
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
267
+ // TypeScript should infer these keys correctly
268
+ expect(result.current.propStatus.title).toBeDefined();
269
+ expect(result.current.propStatus.description).toBeDefined();
270
+ expect(result.current.propStatus.count).toBeDefined();
271
+ // This would cause a TypeScript error if uncommented:
272
+ // expect(result.current.propStatus.nonExistentProp).toBeDefined();
273
+ });
274
+ it("should work without generic type parameter", () => {
275
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
276
+ component: createMockComponent({ dynamicProp: "value" }),
277
+ }));
278
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
279
+ expect(result.current.streamStatus).toBeDefined();
280
+ expect(result.current.propStatus).toBeDefined();
281
+ });
282
+ });
283
+ describe("Edge Cases", () => {
284
+ it("should handle missing message gracefully", () => {
285
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(undefined);
286
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
287
+ expect(result.current.streamStatus.isPending).toBe(true);
288
+ expect(result.current.propStatus).toEqual({});
289
+ });
290
+ it("should handle missing component props gracefully", () => {
291
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue({
292
+ id: "test-message",
293
+ // Missing component property
294
+ });
295
+ const { result } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
296
+ expect(result.current.streamStatus.isPending).toBe(true);
297
+ expect(result.current.propStatus).toEqual({});
298
+ });
299
+ it("should reset prop tracking when generation restarts", () => {
300
+ // Step 1: Complete a message
301
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
302
+ generationStage: generate_component_response_1.GenerationStage.STREAMING_RESPONSE,
303
+ });
304
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
305
+ component: createMockComponent({ title: "" }),
306
+ }));
307
+ const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_stream_status_1.useTamboStreamStatus)());
308
+ // Simulate streaming in title
309
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
310
+ component: createMockComponent({ title: "First Title" }),
311
+ }));
312
+ rerender();
313
+ // Complete generation
314
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
315
+ generationStage: generate_component_response_1.GenerationStage.COMPLETE,
316
+ });
317
+ rerender();
318
+ // Should be successful initially
319
+ expect(result.current.propStatus.title.isSuccess).toBe(true);
320
+ // Step 2: Start new generation with a new message ID to trigger reset
321
+ jest.mocked(tambo_thread_provider_1.useTamboThread).mockReturnValue({
322
+ generationStage: generate_component_response_1.GenerationStage.CHOOSING_COMPONENT,
323
+ });
324
+ jest.mocked(use_current_message_1.useTamboCurrentMessage).mockReturnValue(createMockMessage({
325
+ id: "new-message-id", // Different message ID to trigger reset
326
+ component: createMockComponent({ title: "" }),
327
+ }));
328
+ rerender();
329
+ // Should reset to pending
330
+ expect(result.current.propStatus.title.isPending).toBe(true);
331
+ expect(result.current.propStatus.title.isSuccess).toBe(false);
332
+ });
333
+ });
334
+ });
335
+ //# sourceMappingURL=use-tambo-stream-status.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-stream-status.test.js","sourceRoot":"","sources":["../../../src/hooks/__tests__/use-tambo-stream-status.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport {\n GenerationStage,\n TamboThreadMessage,\n} from \"../../model/generate-component-response\";\nimport {\n TamboThreadContextProps,\n useTamboThread,\n} from \"../../providers/tambo-thread-provider\";\nimport { useTamboCurrentMessage } from \"../use-current-message\";\nimport { useTamboStreamStatus } from \"../use-tambo-stream-status\";\n\n// Mock the required providers\njest.mock(\"../../providers/tambo-thread-provider\", () => ({\n useTamboThread: jest.fn(),\n}));\n\njest.mock(\"../use-current-message\", () => ({\n useTamboCurrentMessage: jest.fn(),\n}));\n\n// Mock window for SSR tests\nconst originalWindow = global.window;\n\n// Helper function to create mock ComponentDecisionV2\nconst createMockComponent = (props: Record<string, unknown> = {}): any => ({\n componentName: \"TestComponent\",\n componentState: {},\n message: \"Component generated\",\n props,\n reasoning: \"Test reasoning\",\n});\n\n// Helper function to create mock TamboThreadMessage\nconst createMockMessage = (\n overrides: Partial<TamboThreadMessage> = {},\n): TamboThreadMessage => ({\n id: \"test-message\",\n componentState: {},\n content: [{ type: \"text\", text: \"test content\" }],\n createdAt: new Date().toISOString(),\n role: \"assistant\",\n threadId: \"test-thread\",\n ...overrides,\n});\n\ndescribe(\"useTamboStreamStatus\", () => {\n beforeEach(() => {\n // Restore window for client-side tests\n global.window = originalWindow;\n\n // Default mock implementations\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.IDLE,\n } as TamboThreadContextProps);\n\n jest.mocked(useTamboCurrentMessage).mockReturnValue({\n id: \"test-message\",\n component: {\n props: {},\n },\n } as TamboThreadMessage);\n });\n\n afterEach(() => {\n jest.clearAllMocks();\n });\n\n describe(\"Initial State\", () => {\n it(\"should start with all flags as pending when idle and no props\", () => {\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.IDLE,\n } as TamboThreadContextProps);\n\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({ title: \"\", body: \"\" }),\n }),\n );\n\n const { result } = renderHook(() =>\n useTamboStreamStatus<{ title: string; body: string }>(),\n );\n\n expect(result.current.streamStatus).toEqual({\n isPending: true,\n isStreaming: false,\n isSuccess: false,\n isError: false,\n streamError: undefined,\n });\n\n expect(result.current.propStatus.title).toEqual({\n isPending: true,\n isStreaming: false,\n isSuccess: false,\n error: undefined,\n });\n\n expect(result.current.propStatus.body).toEqual({\n isPending: true,\n isStreaming: false,\n isSuccess: false,\n error: undefined,\n });\n });\n });\n\n describe(\"Generation vs Props Streaming\", () => {\n it(\"should show generation streaming but props still pending when STREAMING_RESPONSE with no prop content\", () => {\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.STREAMING_RESPONSE,\n } as TamboThreadContextProps);\n\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({ title: \"\", body: \"\" }),\n }),\n );\n\n const { result } = renderHook(() =>\n useTamboStreamStatus<{ title: string; body: string }>(),\n );\n\n // Global streaming should be false because no props are actually streaming yet\n expect(result.current.streamStatus.isStreaming).toBe(false);\n expect(result.current.streamStatus.isPending).toBe(false);\n\n // Individual props should be pending because they haven't started streaming yet\n expect(result.current.propStatus.title.isPending).toBe(true);\n expect(result.current.propStatus.title.isStreaming).toBe(false);\n expect(result.current.propStatus.body.isPending).toBe(true);\n expect(result.current.propStatus.body.isStreaming).toBe(false);\n });\n\n it(\"should show prop streaming when props receive content during STREAMING_RESPONSE\", () => {\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.STREAMING_RESPONSE,\n } as TamboThreadContextProps);\n\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({ title: \"Hello\", body: \"\" }),\n }),\n );\n\n const { result } = renderHook(() =>\n useTamboStreamStatus<{ title: string; body: string }>(),\n );\n\n // Title prop should be streaming since it has content\n expect(result.current.propStatus.title.isStreaming).toBe(true);\n expect(result.current.propStatus.title.isPending).toBe(false);\n\n // Body prop should still be pending since it has no content\n expect(result.current.propStatus.body.isStreaming).toBe(false);\n expect(result.current.propStatus.body.isPending).toBe(true);\n\n // Global should be streaming because at least one prop is streaming\n expect(result.current.streamStatus.isStreaming).toBe(true);\n });\n });\n\n describe(\"Boolean Lifecycle\", () => {\n it(\"should transition through Init -> Streaming -> Success lifecycle\", () => {\n // Start with IDLE (Init phase)\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.IDLE,\n } as TamboThreadContextProps);\n\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({ title: \"\", body: \"\" }),\n }),\n );\n\n const { result, rerender } = renderHook(() =>\n useTamboStreamStatus<{ title: string; body: string }>(),\n );\n\n // Phase 1: Init - isPending = true\n expect(result.current.streamStatus.isPending).toBe(true);\n expect(result.current.streamStatus.isStreaming).toBe(false);\n expect(result.current.streamStatus.isSuccess).toBe(false);\n\n // Phase 2: Streaming - move to STREAMING_RESPONSE with content\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.STREAMING_RESPONSE,\n } as TamboThreadContextProps);\n\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({\n title: \"Hello World\",\n body: \"Some content\",\n }),\n }),\n );\n\n rerender();\n\n expect(result.current.streamStatus.isPending).toBe(false);\n expect(result.current.streamStatus.isStreaming).toBe(true);\n expect(result.current.streamStatus.isSuccess).toBe(false);\n\n // Phase 3: Complete - move to COMPLETE\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.COMPLETE,\n } as TamboThreadContextProps);\n\n rerender();\n\n expect(result.current.streamStatus.isPending).toBe(false);\n expect(result.current.streamStatus.isStreaming).toBe(false);\n expect(result.current.streamStatus.isSuccess).toBe(true);\n });\n\n it(\"should handle error state correctly\", () => {\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.ERROR,\n } as TamboThreadContextProps);\n\n const errorMessage = \"Generation failed\";\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({ title: \"\", body: \"\" }),\n error: errorMessage,\n }),\n );\n\n const { result } = renderHook(() =>\n useTamboStreamStatus<{ title: string; body: string }>(),\n );\n\n expect(result.current.streamStatus.isPending).toBe(true);\n expect(result.current.streamStatus.isStreaming).toBe(false);\n expect(result.current.streamStatus.isSuccess).toBe(false);\n expect(result.current.streamStatus.isError).toBe(true);\n expect(result.current.streamStatus.streamError?.message).toBe(\n errorMessage,\n );\n });\n });\n\n describe(\"Derivation Rules\", () => {\n it(\"should derive isPending correctly (no generation activity AND all props pending)\", () => {\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.IDLE,\n } as TamboThreadContextProps);\n\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({ title: \"\", body: \"\", footer: \"\" }),\n }),\n );\n\n const { result } = renderHook(() =>\n useTamboStreamStatus<{\n title: string;\n body: string;\n footer: string;\n }>(),\n );\n\n // All props are pending and no generation activity\n expect(result.current.streamStatus.isPending).toBe(true);\n expect(result.current.propStatus.title.isPending).toBe(true);\n expect(result.current.propStatus.body.isPending).toBe(true);\n expect(result.current.propStatus.footer.isPending).toBe(true);\n });\n\n it(\"should derive isStreaming correctly (generation streaming OR any prop streaming)\", () => {\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.COMPLETE,\n } as TamboThreadContextProps);\n\n // One prop still streaming\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({\n title: \"Complete Title\",\n body: \"Still streaming...\",\n }),\n }),\n );\n\n const { result } = renderHook(() =>\n useTamboStreamStatus<{ title: string; body: string }>(),\n );\n\n // Should be streaming because at least one prop is streaming\n expect(result.current.streamStatus.isStreaming).toBe(false); // Note: this will be false in our implementation because props are considered complete when generation is COMPLETE\n });\n\n it(\"should derive isSuccess correctly (generation complete AND all props successful)\", () => {\n // Step 1: Start with streaming, props empty\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.STREAMING_RESPONSE,\n } as TamboThreadContextProps);\n\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({\n title: \"\",\n body: \"\",\n }),\n }),\n );\n\n const { result, rerender } = renderHook(() =>\n useTamboStreamStatus<{ title: string; body: string }>(),\n );\n\n // Step 2: Simulate streaming in title\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({\n title: \"Complete Title\",\n body: \"\",\n }),\n }),\n );\n rerender();\n\n // Step 3: Simulate streaming in body\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({\n title: \"Complete Title\",\n body: \"Complete Body\",\n }),\n }),\n );\n rerender();\n\n // Step 4: Generation complete\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.COMPLETE,\n } as TamboThreadContextProps);\n rerender();\n\n // Now both props should be successful\n expect(result.current.propStatus.title.isSuccess).toBe(true);\n expect(result.current.propStatus.body.isSuccess).toBe(true);\n expect(result.current.streamStatus.isSuccess).toBe(true);\n });\n\n it(\"should derive isError correctly (generation error OR any prop error)\", () => {\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.COMPLETE,\n } as TamboThreadContextProps);\n\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({\n title: \"Good Title\",\n body: \"Good Body\",\n }),\n error: \"Something went wrong\",\n }),\n );\n\n const { result } = renderHook(() =>\n useTamboStreamStatus<{ title: string; body: string }>(),\n );\n\n expect(result.current.streamStatus.isError).toBe(true);\n expect(result.current.streamStatus.streamError?.message).toBe(\n \"Something went wrong\",\n );\n });\n });\n\n describe(\"Type Safety\", () => {\n it(\"should provide strongly typed prop status based on generic\", () => {\n interface TestProps {\n title: string;\n description: string;\n count: number;\n }\n\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({\n title: \"Test\",\n description: \"Test desc\",\n count: 42,\n }),\n }),\n );\n\n const { result } = renderHook(() => useTamboStreamStatus<TestProps>());\n\n // TypeScript should infer these keys correctly\n expect(result.current.propStatus.title).toBeDefined();\n expect(result.current.propStatus.description).toBeDefined();\n expect(result.current.propStatus.count).toBeDefined();\n\n // This would cause a TypeScript error if uncommented:\n // expect(result.current.propStatus.nonExistentProp).toBeDefined();\n });\n\n it(\"should work without generic type parameter\", () => {\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({ dynamicProp: \"value\" }),\n }),\n );\n\n const { result } = renderHook(() => useTamboStreamStatus());\n\n expect(result.current.streamStatus).toBeDefined();\n expect(result.current.propStatus).toBeDefined();\n });\n });\n\n describe(\"Edge Cases\", () => {\n it(\"should handle missing message gracefully\", () => {\n jest.mocked(useTamboCurrentMessage).mockReturnValue(undefined);\n\n const { result } = renderHook(() => useTamboStreamStatus());\n\n expect(result.current.streamStatus.isPending).toBe(true);\n expect(result.current.propStatus).toEqual({});\n });\n\n it(\"should handle missing component props gracefully\", () => {\n jest.mocked(useTamboCurrentMessage).mockReturnValue({\n id: \"test-message\",\n // Missing component property\n } as TamboThreadMessage);\n\n const { result } = renderHook(() => useTamboStreamStatus());\n\n expect(result.current.streamStatus.isPending).toBe(true);\n expect(result.current.propStatus).toEqual({});\n });\n\n it(\"should reset prop tracking when generation restarts\", () => {\n // Step 1: Complete a message\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.STREAMING_RESPONSE,\n } as TamboThreadContextProps);\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({ title: \"\" }),\n }),\n );\n const { result, rerender } = renderHook(() =>\n useTamboStreamStatus<{ title: string }>(),\n );\n // Simulate streaming in title\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n component: createMockComponent({ title: \"First Title\" }),\n }),\n );\n rerender();\n // Complete generation\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.COMPLETE,\n } as TamboThreadContextProps);\n rerender();\n // Should be successful initially\n expect(result.current.propStatus.title.isSuccess).toBe(true);\n\n // Step 2: Start new generation with a new message ID to trigger reset\n jest.mocked(useTamboThread).mockReturnValue({\n generationStage: GenerationStage.CHOOSING_COMPONENT,\n } as TamboThreadContextProps);\n jest.mocked(useTamboCurrentMessage).mockReturnValue(\n createMockMessage({\n id: \"new-message-id\", // Different message ID to trigger reset\n component: createMockComponent({ title: \"\" }),\n }),\n );\n rerender();\n // Should reset to pending\n expect(result.current.propStatus.title.isPending).toBe(true);\n expect(result.current.propStatus.title.isSuccess).toBe(false);\n });\n });\n});\n"]}
@@ -2,6 +2,7 @@ export * from "./react-query-hooks";
2
2
  export { useTamboComponentState } from "./use-component-state";
3
3
  export { useTamboCurrentMessage, useTamboMessageContext, } from "./use-current-message";
4
4
  export { useTamboStreamingProps } from "./use-streaming-props";
5
+ export { useTamboStreamStatus, type StreamStatus, type PropStatus, } from "./use-tambo-stream-status";
5
6
  export * from "./use-suggestions";
6
7
  export { useTamboThreadList } from "./use-tambo-threads";
7
8
  export { useTamboThreadInput } from "./use-thread-input";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EACL,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EACL,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EACL,oBAAoB,EACpB,KAAK,YAAY,EACjB,KAAK,UAAU,GAChB,MAAM,2BAA2B,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.useTamboThreadInput = exports.useTamboThreadList = exports.useTamboStreamingProps = exports.useTamboMessageContext = exports.useTamboCurrentMessage = exports.useTamboComponentState = void 0;
17
+ exports.useTamboThreadInput = exports.useTamboThreadList = exports.useTamboStreamStatus = exports.useTamboStreamingProps = exports.useTamboMessageContext = exports.useTamboCurrentMessage = exports.useTamboComponentState = void 0;
18
18
  // Export all hooks from this directory
19
19
  __exportStar(require("./react-query-hooks"), exports);
20
20
  var use_component_state_1 = require("./use-component-state");
@@ -24,6 +24,8 @@ Object.defineProperty(exports, "useTamboCurrentMessage", { enumerable: true, get
24
24
  Object.defineProperty(exports, "useTamboMessageContext", { enumerable: true, get: function () { return use_current_message_1.useTamboMessageContext; } });
25
25
  var use_streaming_props_1 = require("./use-streaming-props");
26
26
  Object.defineProperty(exports, "useTamboStreamingProps", { enumerable: true, get: function () { return use_streaming_props_1.useTamboStreamingProps; } });
27
+ var use_tambo_stream_status_1 = require("./use-tambo-stream-status");
28
+ Object.defineProperty(exports, "useTamboStreamStatus", { enumerable: true, get: function () { return use_tambo_stream_status_1.useTamboStreamStatus; } });
27
29
  __exportStar(require("./use-suggestions"), exports);
28
30
  var use_tambo_threads_1 = require("./use-tambo-threads");
29
31
  Object.defineProperty(exports, "useTamboThreadList", { enumerable: true, get: function () { return use_tambo_threads_1.useTamboThreadList; } });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,sDAAoC;AACpC,6DAA+D;AAAtD,6HAAA,sBAAsB,OAAA;AAC/B,6DAG+B;AAF7B,6HAAA,sBAAsB,OAAA;AACtB,6HAAA,sBAAsB,OAAA;AAExB,6DAA+D;AAAtD,6HAAA,sBAAsB,OAAA;AAC/B,oDAAkC;AAClC,yDAAyD;AAAhD,uHAAA,kBAAkB,OAAA;AAC3B,uDAAyD;AAAhD,uHAAA,mBAAmB,OAAA","sourcesContent":["// Export all hooks from this directory\nexport * from \"./react-query-hooks\";\nexport { useTamboComponentState } from \"./use-component-state\";\nexport {\n useTamboCurrentMessage,\n useTamboMessageContext,\n} from \"./use-current-message\";\nexport { useTamboStreamingProps } from \"./use-streaming-props\";\nexport * from \"./use-suggestions\";\nexport { useTamboThreadList } from \"./use-tambo-threads\";\nexport { useTamboThreadInput } from \"./use-thread-input\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,sDAAoC;AACpC,6DAA+D;AAAtD,6HAAA,sBAAsB,OAAA;AAC/B,6DAG+B;AAF7B,6HAAA,sBAAsB,OAAA;AACtB,6HAAA,sBAAsB,OAAA;AAExB,6DAA+D;AAAtD,6HAAA,sBAAsB,OAAA;AAC/B,qEAImC;AAHjC,+HAAA,oBAAoB,OAAA;AAItB,oDAAkC;AAClC,yDAAyD;AAAhD,uHAAA,kBAAkB,OAAA;AAC3B,uDAAyD;AAAhD,uHAAA,mBAAmB,OAAA","sourcesContent":["// Export all hooks from this directory\nexport * from \"./react-query-hooks\";\nexport { useTamboComponentState } from \"./use-component-state\";\nexport {\n useTamboCurrentMessage,\n useTamboMessageContext,\n} from \"./use-current-message\";\nexport { useTamboStreamingProps } from \"./use-streaming-props\";\nexport {\n useTamboStreamStatus,\n type StreamStatus,\n type PropStatus,\n} from \"./use-tambo-stream-status\";\nexport * from \"./use-suggestions\";\nexport { useTamboThreadList } from \"./use-tambo-threads\";\nexport { useTamboThreadInput } from \"./use-thread-input\";\n"]}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Global stream status flags for a specific component in a message.
3
+ * Represents the aggregate state across all props for this component only.
4
+ * Once a component completes, its status remains stable regardless of other generations.
5
+ */
6
+ export interface StreamStatus {
7
+ /**
8
+ * Indicates no tokens have been received for any prop and generation is not active.
9
+ * Useful for showing initial loading states before any data arrives.
10
+ */
11
+ isPending: boolean;
12
+ /**
13
+ * Indicates active streaming - either generation is streaming OR at least one prop is still streaming.
14
+ * Use this to show loading animations or skeleton states during data transmission.
15
+ */
16
+ isStreaming: boolean;
17
+ /**
18
+ * Indicates successful completion - generation is complete AND every prop finished without error.
19
+ * Safe to render the final component when this is true.
20
+ */
21
+ isSuccess: boolean;
22
+ /**
23
+ * Indicates a fatal error occurred in any prop or the stream itself.
24
+ * Check streamError for details about what went wrong.
25
+ */
26
+ isError: boolean;
27
+ /**
28
+ * The first fatal error encountered during streaming (if any).
29
+ * Will be undefined if no errors occurred.
30
+ */
31
+ streamError?: Error;
32
+ }
33
+ /**
34
+ * Streaming status flags for individual component props.
35
+ * Tracks the state of each prop as it streams from the LLM.
36
+ */
37
+ export interface PropStatus {
38
+ /**
39
+ * Indicates no tokens have been received for this specific prop yet.
40
+ * The prop value is still undefined, null, or empty string.
41
+ */
42
+ isPending: boolean;
43
+ /**
44
+ * Indicates at least one token has been received but streaming is not complete.
45
+ * The prop has partial content that may still be updating.
46
+ */
47
+ isStreaming: boolean;
48
+ /**
49
+ * Indicates this prop has finished streaming successfully.
50
+ * The prop value is complete and stable.
51
+ */
52
+ isSuccess: boolean;
53
+ /**
54
+ * The error that occurred during streaming (if any).
55
+ * Will be undefined if no error occurred for this prop.
56
+ */
57
+ error?: Error;
58
+ }
59
+ /**
60
+ * Hook that exposes per-prop and global streaming status for tambo-ai components.
61
+ * Provides streaming readiness flags so consumers can show loaders, skeletons,
62
+ * or errors while LLM-generated props stream in.
63
+ * This hook tracks status for the specific component in the current message only.
64
+ * Once a component's props complete streaming, they remain stable regardless of
65
+ * other components being generated in the thread.
66
+ * @template Props - The type of the component props being tracked (defaults to Record<string, any>)
67
+ * @returns An object containing both global streamStatus and per-prop propStatus
68
+ * @throws {Error} When used during SSR/SSG
69
+ * @example
70
+ * ```tsx
71
+ * // Wait for entire stream
72
+ * const { streamStatus } = useTamboStreamStatus();
73
+ * if (!streamStatus.isSuccess) return <Spinner />;
74
+ * return <Card {...props} />;
75
+ * ```
76
+ * @example
77
+ * ```tsx
78
+ * // Highlight in-flight props
79
+ * const { propStatus } = useTamboStreamStatus<Props>();
80
+ * <h2 className={propStatus.title.isStreaming ? "animate-pulse" : ""}>
81
+ * {title}
82
+ * </h2>
83
+ * ```
84
+ */
85
+ export declare function useTamboStreamStatus<Props extends Record<string, any> = Record<string, any>>(): {
86
+ streamStatus: StreamStatus;
87
+ propStatus: Record<keyof Props, PropStatus>;
88
+ };
89
+ //# sourceMappingURL=use-tambo-stream-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tambo-stream-status.d.ts","sourceRoot":"","sources":["../../src/hooks/use-tambo-stream-status.tsx"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AA8ND;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KACpD;IACH,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,KAAK,EAAE,UAAU,CAAC,CAAC;CAC7C,CAmCA"}