@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,333 @@
1
+ import { renderHook } from "@testing-library/react";
2
+ import { GenerationStage, } from "../../model/generate-component-response";
3
+ import { useTamboThread, } from "../../providers/tambo-thread-provider";
4
+ import { useTamboCurrentMessage } from "../use-current-message";
5
+ import { useTamboStreamStatus } from "../use-tambo-stream-status";
6
+ // Mock the required providers
7
+ jest.mock("../../providers/tambo-thread-provider", () => ({
8
+ useTamboThread: jest.fn(),
9
+ }));
10
+ jest.mock("../use-current-message", () => ({
11
+ useTamboCurrentMessage: jest.fn(),
12
+ }));
13
+ // Mock window for SSR tests
14
+ const originalWindow = global.window;
15
+ // Helper function to create mock ComponentDecisionV2
16
+ const createMockComponent = (props = {}) => ({
17
+ componentName: "TestComponent",
18
+ componentState: {},
19
+ message: "Component generated",
20
+ props,
21
+ reasoning: "Test reasoning",
22
+ });
23
+ // Helper function to create mock TamboThreadMessage
24
+ const createMockMessage = (overrides = {}) => ({
25
+ id: "test-message",
26
+ componentState: {},
27
+ content: [{ type: "text", text: "test content" }],
28
+ createdAt: new Date().toISOString(),
29
+ role: "assistant",
30
+ threadId: "test-thread",
31
+ ...overrides,
32
+ });
33
+ describe("useTamboStreamStatus", () => {
34
+ beforeEach(() => {
35
+ // Restore window for client-side tests
36
+ global.window = originalWindow;
37
+ // Default mock implementations
38
+ jest.mocked(useTamboThread).mockReturnValue({
39
+ generationStage: GenerationStage.IDLE,
40
+ });
41
+ jest.mocked(useTamboCurrentMessage).mockReturnValue({
42
+ id: "test-message",
43
+ component: {
44
+ props: {},
45
+ },
46
+ });
47
+ });
48
+ afterEach(() => {
49
+ jest.clearAllMocks();
50
+ });
51
+ describe("Initial State", () => {
52
+ it("should start with all flags as pending when idle and no props", () => {
53
+ jest.mocked(useTamboThread).mockReturnValue({
54
+ generationStage: GenerationStage.IDLE,
55
+ });
56
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
57
+ component: createMockComponent({ title: "", body: "" }),
58
+ }));
59
+ const { result } = renderHook(() => useTamboStreamStatus());
60
+ expect(result.current.streamStatus).toEqual({
61
+ isPending: true,
62
+ isStreaming: false,
63
+ isSuccess: false,
64
+ isError: false,
65
+ streamError: undefined,
66
+ });
67
+ expect(result.current.propStatus.title).toEqual({
68
+ isPending: true,
69
+ isStreaming: false,
70
+ isSuccess: false,
71
+ error: undefined,
72
+ });
73
+ expect(result.current.propStatus.body).toEqual({
74
+ isPending: true,
75
+ isStreaming: false,
76
+ isSuccess: false,
77
+ error: undefined,
78
+ });
79
+ });
80
+ });
81
+ describe("Generation vs Props Streaming", () => {
82
+ it("should show generation streaming but props still pending when STREAMING_RESPONSE with no prop content", () => {
83
+ jest.mocked(useTamboThread).mockReturnValue({
84
+ generationStage: GenerationStage.STREAMING_RESPONSE,
85
+ });
86
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
87
+ component: createMockComponent({ title: "", body: "" }),
88
+ }));
89
+ const { result } = renderHook(() => useTamboStreamStatus());
90
+ // Global streaming should be false because no props are actually streaming yet
91
+ expect(result.current.streamStatus.isStreaming).toBe(false);
92
+ expect(result.current.streamStatus.isPending).toBe(false);
93
+ // Individual props should be pending because they haven't started streaming yet
94
+ expect(result.current.propStatus.title.isPending).toBe(true);
95
+ expect(result.current.propStatus.title.isStreaming).toBe(false);
96
+ expect(result.current.propStatus.body.isPending).toBe(true);
97
+ expect(result.current.propStatus.body.isStreaming).toBe(false);
98
+ });
99
+ it("should show prop streaming when props receive content during STREAMING_RESPONSE", () => {
100
+ jest.mocked(useTamboThread).mockReturnValue({
101
+ generationStage: GenerationStage.STREAMING_RESPONSE,
102
+ });
103
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
104
+ component: createMockComponent({ title: "Hello", body: "" }),
105
+ }));
106
+ const { result } = renderHook(() => useTamboStreamStatus());
107
+ // Title prop should be streaming since it has content
108
+ expect(result.current.propStatus.title.isStreaming).toBe(true);
109
+ expect(result.current.propStatus.title.isPending).toBe(false);
110
+ // Body prop should still be pending since it has no content
111
+ expect(result.current.propStatus.body.isStreaming).toBe(false);
112
+ expect(result.current.propStatus.body.isPending).toBe(true);
113
+ // Global should be streaming because at least one prop is streaming
114
+ expect(result.current.streamStatus.isStreaming).toBe(true);
115
+ });
116
+ });
117
+ describe("Boolean Lifecycle", () => {
118
+ it("should transition through Init -> Streaming -> Success lifecycle", () => {
119
+ // Start with IDLE (Init phase)
120
+ jest.mocked(useTamboThread).mockReturnValue({
121
+ generationStage: GenerationStage.IDLE,
122
+ });
123
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
124
+ component: createMockComponent({ title: "", body: "" }),
125
+ }));
126
+ const { result, rerender } = renderHook(() => useTamboStreamStatus());
127
+ // Phase 1: Init - isPending = true
128
+ expect(result.current.streamStatus.isPending).toBe(true);
129
+ expect(result.current.streamStatus.isStreaming).toBe(false);
130
+ expect(result.current.streamStatus.isSuccess).toBe(false);
131
+ // Phase 2: Streaming - move to STREAMING_RESPONSE with content
132
+ jest.mocked(useTamboThread).mockReturnValue({
133
+ generationStage: GenerationStage.STREAMING_RESPONSE,
134
+ });
135
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
136
+ component: createMockComponent({
137
+ title: "Hello World",
138
+ body: "Some content",
139
+ }),
140
+ }));
141
+ rerender();
142
+ expect(result.current.streamStatus.isPending).toBe(false);
143
+ expect(result.current.streamStatus.isStreaming).toBe(true);
144
+ expect(result.current.streamStatus.isSuccess).toBe(false);
145
+ // Phase 3: Complete - move to COMPLETE
146
+ jest.mocked(useTamboThread).mockReturnValue({
147
+ generationStage: GenerationStage.COMPLETE,
148
+ });
149
+ rerender();
150
+ expect(result.current.streamStatus.isPending).toBe(false);
151
+ expect(result.current.streamStatus.isStreaming).toBe(false);
152
+ expect(result.current.streamStatus.isSuccess).toBe(true);
153
+ });
154
+ it("should handle error state correctly", () => {
155
+ jest.mocked(useTamboThread).mockReturnValue({
156
+ generationStage: GenerationStage.ERROR,
157
+ });
158
+ const errorMessage = "Generation failed";
159
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
160
+ component: createMockComponent({ title: "", body: "" }),
161
+ error: errorMessage,
162
+ }));
163
+ const { result } = renderHook(() => useTamboStreamStatus());
164
+ expect(result.current.streamStatus.isPending).toBe(true);
165
+ expect(result.current.streamStatus.isStreaming).toBe(false);
166
+ expect(result.current.streamStatus.isSuccess).toBe(false);
167
+ expect(result.current.streamStatus.isError).toBe(true);
168
+ expect(result.current.streamStatus.streamError?.message).toBe(errorMessage);
169
+ });
170
+ });
171
+ describe("Derivation Rules", () => {
172
+ it("should derive isPending correctly (no generation activity AND all props pending)", () => {
173
+ jest.mocked(useTamboThread).mockReturnValue({
174
+ generationStage: GenerationStage.IDLE,
175
+ });
176
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
177
+ component: createMockComponent({ title: "", body: "", footer: "" }),
178
+ }));
179
+ const { result } = renderHook(() => useTamboStreamStatus());
180
+ // All props are pending and no generation activity
181
+ expect(result.current.streamStatus.isPending).toBe(true);
182
+ expect(result.current.propStatus.title.isPending).toBe(true);
183
+ expect(result.current.propStatus.body.isPending).toBe(true);
184
+ expect(result.current.propStatus.footer.isPending).toBe(true);
185
+ });
186
+ it("should derive isStreaming correctly (generation streaming OR any prop streaming)", () => {
187
+ jest.mocked(useTamboThread).mockReturnValue({
188
+ generationStage: GenerationStage.COMPLETE,
189
+ });
190
+ // One prop still streaming
191
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
192
+ component: createMockComponent({
193
+ title: "Complete Title",
194
+ body: "Still streaming...",
195
+ }),
196
+ }));
197
+ const { result } = renderHook(() => useTamboStreamStatus());
198
+ // Should be streaming because at least one prop is streaming
199
+ expect(result.current.streamStatus.isStreaming).toBe(false); // Note: this will be false in our implementation because props are considered complete when generation is COMPLETE
200
+ });
201
+ it("should derive isSuccess correctly (generation complete AND all props successful)", () => {
202
+ // Step 1: Start with streaming, props empty
203
+ jest.mocked(useTamboThread).mockReturnValue({
204
+ generationStage: GenerationStage.STREAMING_RESPONSE,
205
+ });
206
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
207
+ component: createMockComponent({
208
+ title: "",
209
+ body: "",
210
+ }),
211
+ }));
212
+ const { result, rerender } = renderHook(() => useTamboStreamStatus());
213
+ // Step 2: Simulate streaming in title
214
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
215
+ component: createMockComponent({
216
+ title: "Complete Title",
217
+ body: "",
218
+ }),
219
+ }));
220
+ rerender();
221
+ // Step 3: Simulate streaming in body
222
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
223
+ component: createMockComponent({
224
+ title: "Complete Title",
225
+ body: "Complete Body",
226
+ }),
227
+ }));
228
+ rerender();
229
+ // Step 4: Generation complete
230
+ jest.mocked(useTamboThread).mockReturnValue({
231
+ generationStage: GenerationStage.COMPLETE,
232
+ });
233
+ rerender();
234
+ // Now both props should be successful
235
+ expect(result.current.propStatus.title.isSuccess).toBe(true);
236
+ expect(result.current.propStatus.body.isSuccess).toBe(true);
237
+ expect(result.current.streamStatus.isSuccess).toBe(true);
238
+ });
239
+ it("should derive isError correctly (generation error OR any prop error)", () => {
240
+ jest.mocked(useTamboThread).mockReturnValue({
241
+ generationStage: GenerationStage.COMPLETE,
242
+ });
243
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
244
+ component: createMockComponent({
245
+ title: "Good Title",
246
+ body: "Good Body",
247
+ }),
248
+ error: "Something went wrong",
249
+ }));
250
+ const { result } = renderHook(() => useTamboStreamStatus());
251
+ expect(result.current.streamStatus.isError).toBe(true);
252
+ expect(result.current.streamStatus.streamError?.message).toBe("Something went wrong");
253
+ });
254
+ });
255
+ describe("Type Safety", () => {
256
+ it("should provide strongly typed prop status based on generic", () => {
257
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
258
+ component: createMockComponent({
259
+ title: "Test",
260
+ description: "Test desc",
261
+ count: 42,
262
+ }),
263
+ }));
264
+ const { result } = renderHook(() => useTamboStreamStatus());
265
+ // TypeScript should infer these keys correctly
266
+ expect(result.current.propStatus.title).toBeDefined();
267
+ expect(result.current.propStatus.description).toBeDefined();
268
+ expect(result.current.propStatus.count).toBeDefined();
269
+ // This would cause a TypeScript error if uncommented:
270
+ // expect(result.current.propStatus.nonExistentProp).toBeDefined();
271
+ });
272
+ it("should work without generic type parameter", () => {
273
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
274
+ component: createMockComponent({ dynamicProp: "value" }),
275
+ }));
276
+ const { result } = renderHook(() => useTamboStreamStatus());
277
+ expect(result.current.streamStatus).toBeDefined();
278
+ expect(result.current.propStatus).toBeDefined();
279
+ });
280
+ });
281
+ describe("Edge Cases", () => {
282
+ it("should handle missing message gracefully", () => {
283
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(undefined);
284
+ const { result } = renderHook(() => useTamboStreamStatus());
285
+ expect(result.current.streamStatus.isPending).toBe(true);
286
+ expect(result.current.propStatus).toEqual({});
287
+ });
288
+ it("should handle missing component props gracefully", () => {
289
+ jest.mocked(useTamboCurrentMessage).mockReturnValue({
290
+ id: "test-message",
291
+ // Missing component property
292
+ });
293
+ const { result } = renderHook(() => useTamboStreamStatus());
294
+ expect(result.current.streamStatus.isPending).toBe(true);
295
+ expect(result.current.propStatus).toEqual({});
296
+ });
297
+ it("should reset prop tracking when generation restarts", () => {
298
+ // Step 1: Complete a message
299
+ jest.mocked(useTamboThread).mockReturnValue({
300
+ generationStage: GenerationStage.STREAMING_RESPONSE,
301
+ });
302
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
303
+ component: createMockComponent({ title: "" }),
304
+ }));
305
+ const { result, rerender } = renderHook(() => useTamboStreamStatus());
306
+ // Simulate streaming in title
307
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
308
+ component: createMockComponent({ title: "First Title" }),
309
+ }));
310
+ rerender();
311
+ // Complete generation
312
+ jest.mocked(useTamboThread).mockReturnValue({
313
+ generationStage: GenerationStage.COMPLETE,
314
+ });
315
+ rerender();
316
+ // Should be successful initially
317
+ expect(result.current.propStatus.title.isSuccess).toBe(true);
318
+ // Step 2: Start new generation with a new message ID to trigger reset
319
+ jest.mocked(useTamboThread).mockReturnValue({
320
+ generationStage: GenerationStage.CHOOSING_COMPONENT,
321
+ });
322
+ jest.mocked(useTamboCurrentMessage).mockReturnValue(createMockMessage({
323
+ id: "new-message-id", // Different message ID to trigger reset
324
+ component: createMockComponent({ title: "" }),
325
+ }));
326
+ rerender();
327
+ // Should reset to pending
328
+ expect(result.current.propStatus.title.isPending).toBe(true);
329
+ expect(result.current.propStatus.title.isSuccess).toBe(false);
330
+ });
331
+ });
332
+ });
333
+ //# 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"}
@@ -3,6 +3,7 @@ export * from "./react-query-hooks";
3
3
  export { useTamboComponentState } from "./use-component-state";
4
4
  export { useTamboCurrentMessage, useTamboMessageContext, } from "./use-current-message";
5
5
  export { useTamboStreamingProps } from "./use-streaming-props";
6
+ export { useTamboStreamStatus, } from "./use-tambo-stream-status";
6
7
  export * from "./use-suggestions";
7
8
  export { useTamboThreadList } from "./use-tambo-threads";
8
9
  export { useTamboThreadInput } from "./use-thread-input";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,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","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,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,GAGrB,MAAM,2BAA2B,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC","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"}