@tambo-ai/react 0.29.0 → 0.30.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 (82) hide show
  1. package/README.md +170 -46
  2. package/dist/hooks/use-component-state.d.ts.map +1 -1
  3. package/dist/hooks/use-component-state.js +1 -0
  4. package/dist/hooks/use-component-state.js.map +1 -1
  5. package/dist/hooks/use-current-message.d.ts.map +1 -1
  6. package/dist/hooks/use-current-message.js +1 -0
  7. package/dist/hooks/use-current-message.js.map +1 -1
  8. package/dist/hooks/use-streaming-props.d.ts.map +1 -1
  9. package/dist/hooks/use-streaming-props.js +1 -0
  10. package/dist/hooks/use-streaming-props.js.map +1 -1
  11. package/dist/hooks/use-suggestions.d.ts.map +1 -1
  12. package/dist/hooks/use-suggestions.js +1 -0
  13. package/dist/hooks/use-suggestions.js.map +1 -1
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/providers/__tests__/tambo-stubs.test.d.ts +2 -0
  19. package/dist/providers/__tests__/tambo-stubs.test.d.ts.map +1 -0
  20. package/dist/providers/__tests__/tambo-stubs.test.js +93 -0
  21. package/dist/providers/__tests__/tambo-stubs.test.js.map +1 -0
  22. package/dist/providers/index.d.ts +1 -0
  23. package/dist/providers/index.d.ts.map +1 -1
  24. package/dist/providers/index.js +3 -1
  25. package/dist/providers/index.js.map +1 -1
  26. package/dist/providers/tambo-client-provider.d.ts +1 -0
  27. package/dist/providers/tambo-client-provider.d.ts.map +1 -1
  28. package/dist/providers/tambo-client-provider.js +6 -5
  29. package/dist/providers/tambo-client-provider.js.map +1 -1
  30. package/dist/providers/tambo-provider.d.ts +8 -0
  31. package/dist/providers/tambo-provider.d.ts.map +1 -1
  32. package/dist/providers/tambo-provider.js +4 -3
  33. package/dist/providers/tambo-provider.js.map +1 -1
  34. package/dist/providers/tambo-registry-provider.d.ts +1 -0
  35. package/dist/providers/tambo-registry-provider.d.ts.map +1 -1
  36. package/dist/providers/tambo-registry-provider.js +4 -4
  37. package/dist/providers/tambo-registry-provider.js.map +1 -1
  38. package/dist/providers/tambo-stubs.d.ts +85 -0
  39. package/dist/providers/tambo-stubs.d.ts.map +1 -0
  40. package/dist/providers/tambo-stubs.js +248 -0
  41. package/dist/providers/tambo-stubs.js.map +1 -0
  42. package/esm/hooks/use-component-state.d.ts.map +1 -1
  43. package/esm/hooks/use-component-state.js +1 -0
  44. package/esm/hooks/use-component-state.js.map +1 -1
  45. package/esm/hooks/use-current-message.d.ts.map +1 -1
  46. package/esm/hooks/use-current-message.js +1 -0
  47. package/esm/hooks/use-current-message.js.map +1 -1
  48. package/esm/hooks/use-streaming-props.d.ts.map +1 -1
  49. package/esm/hooks/use-streaming-props.js +1 -0
  50. package/esm/hooks/use-streaming-props.js.map +1 -1
  51. package/esm/hooks/use-suggestions.d.ts.map +1 -1
  52. package/esm/hooks/use-suggestions.js +1 -0
  53. package/esm/hooks/use-suggestions.js.map +1 -1
  54. package/esm/index.d.ts +1 -1
  55. package/esm/index.d.ts.map +1 -1
  56. package/esm/index.js +1 -1
  57. package/esm/index.js.map +1 -1
  58. package/esm/providers/__tests__/tambo-stubs.test.d.ts +2 -0
  59. package/esm/providers/__tests__/tambo-stubs.test.d.ts.map +1 -0
  60. package/esm/providers/__tests__/tambo-stubs.test.js +58 -0
  61. package/esm/providers/__tests__/tambo-stubs.test.js.map +1 -0
  62. package/esm/providers/index.d.ts +1 -0
  63. package/esm/providers/index.d.ts.map +1 -1
  64. package/esm/providers/index.js +1 -0
  65. package/esm/providers/index.js.map +1 -1
  66. package/esm/providers/tambo-client-provider.d.ts +1 -0
  67. package/esm/providers/tambo-client-provider.d.ts.map +1 -1
  68. package/esm/providers/tambo-client-provider.js +2 -1
  69. package/esm/providers/tambo-client-provider.js.map +1 -1
  70. package/esm/providers/tambo-provider.d.ts +8 -0
  71. package/esm/providers/tambo-provider.d.ts.map +1 -1
  72. package/esm/providers/tambo-provider.js +1 -1
  73. package/esm/providers/tambo-provider.js.map +1 -1
  74. package/esm/providers/tambo-registry-provider.d.ts +1 -0
  75. package/esm/providers/tambo-registry-provider.d.ts.map +1 -1
  76. package/esm/providers/tambo-registry-provider.js +1 -1
  77. package/esm/providers/tambo-registry-provider.js.map +1 -1
  78. package/esm/providers/tambo-stubs.d.ts +85 -0
  79. package/esm/providers/tambo-stubs.d.ts.map +1 -0
  80. package/esm/providers/tambo-stubs.js +211 -0
  81. package/esm/providers/tambo-stubs.js.map +1 -0
  82. package/package.json +12 -12
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ "use client";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.TamboStubProvider = void 0;
38
+ const react_query_1 = require("@tanstack/react-query");
39
+ const react_1 = __importStar(require("react"));
40
+ const generate_component_response_1 = require("../model/generate-component-response");
41
+ const tambo_client_provider_1 = require("./tambo-client-provider");
42
+ const tambo_component_provider_1 = require("./tambo-component-provider");
43
+ const tambo_provider_1 = require("./tambo-provider");
44
+ const tambo_registry_provider_1 = require("./tambo-registry-provider");
45
+ const tambo_thread_provider_1 = require("./tambo-thread-provider");
46
+ /**
47
+ * Stub client provider that accepts a client and queryClient as props
48
+ * @returns The TamboStubClientProvider component
49
+ */
50
+ const TamboStubClientProvider = ({ children, client, queryClient, threads, projectId, contextKey }) => {
51
+ // Prepopulate the query cache with threads data if provided
52
+ (0, react_1.useEffect)(() => {
53
+ if (threads) {
54
+ // Set the project ID in the cache
55
+ queryClient.setQueryData(["projectId"], projectId);
56
+ // Set the threads data in the cache using the same query key pattern as useTamboThreadList
57
+ queryClient.setQueryData(["threads", projectId, contextKey], threads);
58
+ }
59
+ }, [threads, projectId, contextKey, queryClient]);
60
+ return (react_1.default.createElement(tambo_client_provider_1.TamboClientContext.Provider, { value: { client, queryClient } }, children));
61
+ };
62
+ /**
63
+ * Stub registry provider that accepts componentList, toolRegistry, and componentToolAssociations as props
64
+ * @returns The TamboStubRegistryProvider component
65
+ */
66
+ const TamboStubRegistryProvider = ({ children, componentList, toolRegistry, componentToolAssociations, registerComponent, registerTool, registerTools, addToolAssociation, }) => {
67
+ return (react_1.default.createElement(tambo_registry_provider_1.TamboRegistryContext.Provider, { value: {
68
+ componentList,
69
+ toolRegistry,
70
+ componentToolAssociations,
71
+ registerComponent,
72
+ registerTool,
73
+ registerTools,
74
+ addToolAssociation,
75
+ } }, children));
76
+ };
77
+ /**
78
+ * Stub thread provider that accepts all thread context props
79
+ * @returns The TamboStubThreadProvider component
80
+ */
81
+ const TamboStubThreadProvider = ({ children, ...threadContextProps }) => {
82
+ return (react_1.default.createElement(tambo_thread_provider_1.TamboThreadContext.Provider, { value: threadContextProps }, children));
83
+ };
84
+ /**
85
+ * Default no-op functions that throw errors - used when callbacks are not provided
86
+ * @returns The default callbacks
87
+ */
88
+ const createDefaultCallbacks = () => ({
89
+ switchCurrentThread: () => {
90
+ throw new Error("switchCurrentThread not implemented in stub");
91
+ },
92
+ startNewThread: () => {
93
+ throw new Error("startNewThread not implemented in stub");
94
+ },
95
+ updateThreadName: () => {
96
+ throw new Error("updateThreadName not implemented in stub");
97
+ },
98
+ generateThreadName: () => {
99
+ throw new Error("generateThreadName not implemented in stub");
100
+ },
101
+ addThreadMessage: () => {
102
+ throw new Error("addThreadMessage not implemented in stub");
103
+ },
104
+ updateThreadMessage: () => {
105
+ throw new Error("updateThreadMessage not implemented in stub");
106
+ },
107
+ setInputValue: () => {
108
+ throw new Error("setInputValue not implemented in stub");
109
+ },
110
+ sendThreadMessage: () => {
111
+ throw new Error("sendThreadMessage not implemented in stub");
112
+ },
113
+ registerComponent: () => {
114
+ throw new Error("registerComponent not implemented in stub");
115
+ },
116
+ registerTool: () => {
117
+ throw new Error("registerTool not implemented in stub");
118
+ },
119
+ registerTools: () => {
120
+ throw new Error("registerTools not implemented in stub");
121
+ },
122
+ addToolAssociation: () => {
123
+ throw new Error("addToolAssociation not implemented in stub");
124
+ },
125
+ });
126
+ /**
127
+ * The TamboStubProvider provides a way to use the Tambo API with static/stub data.
128
+ * This is useful for testing, samples, and static UI development.
129
+ *
130
+ * Unlike TamboProvider, all data must be provided as props rather than being inferred.
131
+ * @example
132
+ * ```tsx
133
+ * import { TamboStubProvider } from '@tambo-ai/react-sdk';
134
+ *
135
+ * const exampleThread = {
136
+ * id: "example-thread",
137
+ * messages: [
138
+ * {
139
+ * id: "msg-1",
140
+ * role: "user",
141
+ * content: [{ type: "text", text: "Hello!" }],
142
+ * createdAt: new Date().toISOString(),
143
+ * threadId: "example-thread",
144
+ * componentState: {},
145
+ * },
146
+ * {
147
+ * id: "msg-2",
148
+ * role: "assistant",
149
+ * content: [{ type: "text", text: "Hi there!" }],
150
+ * createdAt: new Date().toISOString(),
151
+ * threadId: "example-thread",
152
+ * componentState: {},
153
+ * }
154
+ * ],
155
+ * createdAt: new Date().toISOString(),
156
+ * projectId: "example-project",
157
+ * updatedAt: new Date().toISOString(),
158
+ * metadata: {},
159
+ * };
160
+ *
161
+ * const exampleThreadList = [exampleThread];
162
+ *
163
+ * function MyComponent() {
164
+ * return (
165
+ * <TamboStubProvider
166
+ * thread={exampleThread}
167
+ * components={[]}
168
+ * tools={[]}
169
+ * threads={exampleThreadList}
170
+ * projectId="example-project"
171
+ * >
172
+ * <MessageThreadFull />
173
+ * </TamboStubProvider>
174
+ * );
175
+ * }
176
+ * ```
177
+ * @param props - The props for the TamboStubProvider
178
+ * @param props.children - The children to wrap
179
+ * @param props.thread - The thread data to display
180
+ * @param props.components - Optional components registry
181
+ * @param props.tools - Optional tools registry
182
+ * @param props.threads - Optional threads data to populate thread list (overrides useTamboThreadList)
183
+ * @param props.projectId - Optional project ID for query cache (defaults to thread.projectId)
184
+ * @param props.contextKey - Optional context key for thread list queries
185
+ * @returns The TamboStubProvider component
186
+ */
187
+ const TamboStubProvider = ({ children, thread, components = [], tools = [], threads, projectId, contextKey, ...overrides }) => {
188
+ const defaults = createDefaultCallbacks();
189
+ // Create stub client and queryClient
190
+ const stubClient = {};
191
+ const stubQueryClient = new react_query_1.QueryClient();
192
+ // Use provided projectId or fall back to thread's projectId
193
+ const resolvedProjectId = projectId ?? thread.projectId;
194
+ // Build component registry from components prop
195
+ const componentList = components.reduce((acc, component) => {
196
+ acc[component.name] = {
197
+ component: component.component,
198
+ loadingComponent: component.loadingComponent,
199
+ name: component.name,
200
+ description: component.description,
201
+ props: component.propsDefinition ?? {},
202
+ contextTools: [],
203
+ };
204
+ return acc;
205
+ }, {});
206
+ // Build tool registry from tools prop
207
+ const toolRegistry = tools.reduce((acc, tool) => {
208
+ acc[tool.name] = tool;
209
+ return acc;
210
+ }, {});
211
+ // Build tool associations from components
212
+ const componentToolAssociations = components.reduce((acc, component) => {
213
+ if (component.associatedTools) {
214
+ acc[component.name] = component.associatedTools.map((tool) => tool.name);
215
+ }
216
+ return acc;
217
+ }, {});
218
+ // Merge defaults with provided overrides
219
+ const threadContextProps = {
220
+ thread,
221
+ switchCurrentThread: overrides.switchCurrentThread ?? defaults.switchCurrentThread,
222
+ startNewThread: overrides.startNewThread ?? defaults.startNewThread,
223
+ updateThreadName: overrides.updateThreadName ?? defaults.updateThreadName,
224
+ generateThreadName: overrides.generateThreadName ?? defaults.generateThreadName,
225
+ addThreadMessage: overrides.addThreadMessage ?? defaults.addThreadMessage,
226
+ updateThreadMessage: overrides.updateThreadMessage ?? defaults.updateThreadMessage,
227
+ inputValue: overrides.inputValue ?? "",
228
+ streaming: overrides.streaming ?? true,
229
+ setInputValue: overrides.setInputValue ?? defaults.setInputValue,
230
+ sendThreadMessage: overrides.sendThreadMessage ?? defaults.sendThreadMessage,
231
+ generationStage: overrides.generationStage ?? generate_component_response_1.GenerationStage.IDLE,
232
+ generationStatusMessage: overrides.generationStatusMessage ?? "",
233
+ isIdle: overrides.isIdle ?? true,
234
+ };
235
+ const componentContextProps = {
236
+ registerComponent: overrides.registerComponent ?? defaults.registerComponent,
237
+ registerTool: overrides.registerTool ?? defaults.registerTool,
238
+ registerTools: overrides.registerTools ?? defaults.registerTools,
239
+ addToolAssociation: overrides.addToolAssociation ?? defaults.addToolAssociation,
240
+ };
241
+ return (react_1.default.createElement(TamboStubClientProvider, { client: stubClient, queryClient: stubQueryClient, threads: threads, projectId: resolvedProjectId, contextKey: contextKey },
242
+ react_1.default.createElement(TamboStubRegistryProvider, { componentList: componentList, toolRegistry: toolRegistry, componentToolAssociations: componentToolAssociations, registerComponent: componentContextProps.registerComponent, registerTool: componentContextProps.registerTool, registerTools: componentContextProps.registerTools, addToolAssociation: componentContextProps.addToolAssociation },
243
+ react_1.default.createElement(TamboStubThreadProvider, { ...threadContextProps },
244
+ react_1.default.createElement(tambo_component_provider_1.TamboComponentProvider, null,
245
+ react_1.default.createElement(tambo_provider_1.TamboCompositeProvider, null, children))))));
246
+ };
247
+ exports.TamboStubProvider = TamboStubProvider;
248
+ //# sourceMappingURL=tambo-stubs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tambo-stubs.js","sourceRoot":"","sources":["../../src/providers/tambo-stubs.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { QueryClient } from \"@tanstack/react-query\";\nimport React, { PropsWithChildren, useEffect } from \"react\";\nimport { TamboComponent, TamboTool } from \"../model/component-metadata\";\nimport { GenerationStage } from \"../model/generate-component-response\";\nimport { TamboThread } from \"../model/tambo-thread\";\nimport { TamboClientContext } from \"./tambo-client-provider\";\nimport {\n TamboComponentContextProps,\n TamboComponentProvider,\n} from \"./tambo-component-provider\";\nimport {\n TamboCompositeProvider,\n type TamboContextProps,\n} from \"./tambo-provider\";\nimport { TamboRegistryContext } from \"./tambo-registry-provider\";\nimport {\n TamboThreadContext,\n TamboThreadContextProps,\n} from \"./tambo-thread-provider\";\n\n/**\n * TamboStubProvider props - includes all the data that would normally be inferred\n */\nexport interface TamboStubProviderProps extends Partial<TamboContextProps> {\n /** Required: The thread data to display */\n thread: TamboThread;\n /** Optional: Components registry - defaults to empty */\n components?: TamboComponent[];\n /** Optional: Tools registry - defaults to empty */\n tools?: TamboTool[];\n /** Optional: Threads data to populate thread list - overrides useTamboThreadList() */\n threads?: Partial<TamboAI.Beta.Threads.ThreadsOffsetAndLimit>;\n /** Optional: Project ID to use for query cache - defaults to thread.projectId */\n projectId?: string;\n /** Optional: Context key for thread list queries */\n contextKey?: string;\n}\n\n/**\n * Stub client provider that accepts a client and queryClient as props\n * @returns The TamboStubClientProvider component\n */\nconst TamboStubClientProvider: React.FC<\n PropsWithChildren<{\n client: TamboAI;\n queryClient: QueryClient;\n threads?: Partial<TamboAI.Beta.Threads.ThreadsOffsetAndLimit>;\n projectId?: string;\n contextKey?: string;\n }>\n> = ({ children, client, queryClient, threads, projectId, contextKey }) => {\n // Prepopulate the query cache with threads data if provided\n useEffect(() => {\n if (threads) {\n // Set the project ID in the cache\n queryClient.setQueryData([\"projectId\"], projectId);\n\n // Set the threads data in the cache using the same query key pattern as useTamboThreadList\n queryClient.setQueryData([\"threads\", projectId, contextKey], threads);\n }\n }, [threads, projectId, contextKey, queryClient]);\n\n return (\n <TamboClientContext.Provider value={{ client, queryClient }}>\n {children}\n </TamboClientContext.Provider>\n );\n};\n\n/**\n * Stub registry provider that accepts componentList, toolRegistry, and componentToolAssociations as props\n * @returns The TamboStubRegistryProvider component\n */\nconst TamboStubRegistryProvider: React.FC<\n PropsWithChildren<{\n componentList: Record<string, any>;\n toolRegistry: Record<string, TamboTool>;\n componentToolAssociations: Record<string, string[]>;\n registerComponent: (options: TamboComponent) => void;\n registerTool: (tool: TamboTool) => void;\n registerTools: (tools: TamboTool[]) => void;\n addToolAssociation: (componentName: string, tool: TamboTool) => void;\n }>\n> = ({\n children,\n componentList,\n toolRegistry,\n componentToolAssociations,\n registerComponent,\n registerTool,\n registerTools,\n addToolAssociation,\n}) => {\n return (\n <TamboRegistryContext.Provider\n value={{\n componentList,\n toolRegistry,\n componentToolAssociations,\n registerComponent,\n registerTool,\n registerTools,\n addToolAssociation,\n }}\n >\n {children}\n </TamboRegistryContext.Provider>\n );\n};\n\n/**\n * Stub thread provider that accepts all thread context props\n * @returns The TamboStubThreadProvider component\n */\nconst TamboStubThreadProvider: React.FC<\n PropsWithChildren<TamboThreadContextProps>\n> = ({ children, ...threadContextProps }) => {\n return (\n <TamboThreadContext.Provider value={threadContextProps}>\n {children}\n </TamboThreadContext.Provider>\n );\n};\n\n/**\n * Default no-op functions that throw errors - used when callbacks are not provided\n * @returns The default callbacks\n */\nconst createDefaultCallbacks = () => ({\n switchCurrentThread: () => {\n throw new Error(\"switchCurrentThread not implemented in stub\");\n },\n startNewThread: () => {\n throw new Error(\"startNewThread not implemented in stub\");\n },\n updateThreadName: () => {\n throw new Error(\"updateThreadName not implemented in stub\");\n },\n generateThreadName: () => {\n throw new Error(\"generateThreadName not implemented in stub\");\n },\n addThreadMessage: () => {\n throw new Error(\"addThreadMessage not implemented in stub\");\n },\n updateThreadMessage: () => {\n throw new Error(\"updateThreadMessage not implemented in stub\");\n },\n setInputValue: () => {\n throw new Error(\"setInputValue not implemented in stub\");\n },\n sendThreadMessage: () => {\n throw new Error(\"sendThreadMessage not implemented in stub\");\n },\n registerComponent: () => {\n throw new Error(\"registerComponent not implemented in stub\");\n },\n registerTool: () => {\n throw new Error(\"registerTool not implemented in stub\");\n },\n registerTools: () => {\n throw new Error(\"registerTools not implemented in stub\");\n },\n addToolAssociation: () => {\n throw new Error(\"addToolAssociation not implemented in stub\");\n },\n});\n\n/**\n * The TamboStubProvider provides a way to use the Tambo API with static/stub data.\n * This is useful for testing, samples, and static UI development.\n *\n * Unlike TamboProvider, all data must be provided as props rather than being inferred.\n * @example\n * ```tsx\n * import { TamboStubProvider } from '@tambo-ai/react-sdk';\n *\n * const exampleThread = {\n * id: \"example-thread\",\n * messages: [\n * {\n * id: \"msg-1\",\n * role: \"user\",\n * content: [{ type: \"text\", text: \"Hello!\" }],\n * createdAt: new Date().toISOString(),\n * threadId: \"example-thread\",\n * componentState: {},\n * },\n * {\n * id: \"msg-2\",\n * role: \"assistant\",\n * content: [{ type: \"text\", text: \"Hi there!\" }],\n * createdAt: new Date().toISOString(),\n * threadId: \"example-thread\",\n * componentState: {},\n * }\n * ],\n * createdAt: new Date().toISOString(),\n * projectId: \"example-project\",\n * updatedAt: new Date().toISOString(),\n * metadata: {},\n * };\n *\n * const exampleThreadList = [exampleThread];\n *\n * function MyComponent() {\n * return (\n * <TamboStubProvider\n * thread={exampleThread}\n * components={[]}\n * tools={[]}\n * threads={exampleThreadList}\n * projectId=\"example-project\"\n * >\n * <MessageThreadFull />\n * </TamboStubProvider>\n * );\n * }\n * ```\n * @param props - The props for the TamboStubProvider\n * @param props.children - The children to wrap\n * @param props.thread - The thread data to display\n * @param props.components - Optional components registry\n * @param props.tools - Optional tools registry\n * @param props.threads - Optional threads data to populate thread list (overrides useTamboThreadList)\n * @param props.projectId - Optional project ID for query cache (defaults to thread.projectId)\n * @param props.contextKey - Optional context key for thread list queries\n * @returns The TamboStubProvider component\n */\nexport const TamboStubProvider: React.FC<\n PropsWithChildren<TamboStubProviderProps>\n> = ({\n children,\n thread,\n components = [],\n tools = [],\n threads,\n projectId,\n contextKey,\n ...overrides\n}) => {\n const defaults = createDefaultCallbacks();\n\n // Create stub client and queryClient\n const stubClient = {} as TamboAI;\n const stubQueryClient = new QueryClient();\n\n // Use provided projectId or fall back to thread's projectId\n const resolvedProjectId = projectId ?? thread.projectId;\n\n // Build component registry from components prop\n const componentList = components.reduce(\n (acc, component) => {\n acc[component.name] = {\n component: component.component,\n loadingComponent: component.loadingComponent,\n name: component.name,\n description: component.description,\n props: component.propsDefinition ?? {},\n contextTools: [],\n };\n return acc;\n },\n {} as Record<string, any>,\n );\n\n // Build tool registry from tools prop\n const toolRegistry = tools.reduce(\n (acc, tool) => {\n acc[tool.name] = tool;\n return acc;\n },\n {} as Record<string, TamboTool>,\n );\n\n // Build tool associations from components\n const componentToolAssociations = components.reduce(\n (acc, component) => {\n if (component.associatedTools) {\n acc[component.name] = component.associatedTools.map(\n (tool) => tool.name,\n );\n }\n return acc;\n },\n {} as Record<string, string[]>,\n );\n\n // Merge defaults with provided overrides\n const threadContextProps: TamboThreadContextProps = {\n thread,\n switchCurrentThread:\n overrides.switchCurrentThread ?? defaults.switchCurrentThread,\n startNewThread: overrides.startNewThread ?? defaults.startNewThread,\n updateThreadName: overrides.updateThreadName ?? defaults.updateThreadName,\n generateThreadName:\n overrides.generateThreadName ?? defaults.generateThreadName,\n addThreadMessage: overrides.addThreadMessage ?? defaults.addThreadMessage,\n updateThreadMessage:\n overrides.updateThreadMessage ?? defaults.updateThreadMessage,\n inputValue: overrides.inputValue ?? \"\",\n streaming: overrides.streaming ?? true,\n setInputValue: overrides.setInputValue ?? defaults.setInputValue,\n sendThreadMessage:\n overrides.sendThreadMessage ?? defaults.sendThreadMessage,\n generationStage: overrides.generationStage ?? GenerationStage.IDLE,\n generationStatusMessage: overrides.generationStatusMessage ?? \"\",\n isIdle: overrides.isIdle ?? true,\n };\n\n const componentContextProps: TamboComponentContextProps = {\n registerComponent:\n overrides.registerComponent ?? defaults.registerComponent,\n registerTool: overrides.registerTool ?? defaults.registerTool,\n registerTools: overrides.registerTools ?? defaults.registerTools,\n addToolAssociation:\n overrides.addToolAssociation ?? defaults.addToolAssociation,\n };\n\n return (\n <TamboStubClientProvider\n client={stubClient}\n queryClient={stubQueryClient}\n threads={threads}\n projectId={resolvedProjectId}\n contextKey={contextKey}\n >\n <TamboStubRegistryProvider\n componentList={componentList}\n toolRegistry={toolRegistry}\n componentToolAssociations={componentToolAssociations}\n registerComponent={componentContextProps.registerComponent}\n registerTool={componentContextProps.registerTool}\n registerTools={componentContextProps.registerTools}\n addToolAssociation={componentContextProps.addToolAssociation}\n >\n <TamboStubThreadProvider {...threadContextProps}>\n <TamboComponentProvider>\n <TamboCompositeProvider>{children}</TamboCompositeProvider>\n </TamboComponentProvider>\n </TamboStubThreadProvider>\n </TamboStubRegistryProvider>\n </TamboStubClientProvider>\n );\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-component-state.d.ts","sourceRoot":"","sources":["../../src/hooks/use-component-state.tsx"],"names":[],"mappings":"AAQA,UAAU,kBAAkB;IAC1B,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,KAAK,iBAAiB,CAAC,CAAC,IAAI;IAC1B,YAAY,EAAE,CAAC;IACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI;IAC/B,IAAI,EAAE,kBAAkB;CACzB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,SAAS,EAClD,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,CAAC,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,iBAAiB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AACpC,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,CAAC,EACf,YAAY,CAAC,EAAE,MAAM,GACpB,iBAAiB,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"use-component-state.d.ts","sourceRoot":"","sources":["../../src/hooks/use-component-state.tsx"],"names":[],"mappings":"AASA,UAAU,kBAAkB;IAC1B,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,KAAK,iBAAiB,CAAC,CAAC,IAAI;IAC1B,YAAY,EAAE,CAAC;IACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI;IAC/B,IAAI,EAAE,kBAAkB;CACzB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,SAAS,EAClD,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,CAAC,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,iBAAiB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AACpC,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,CAAC,EACf,YAAY,CAAC,EAAE,MAAM,GACpB,iBAAiB,CAAC,CAAC,CAAC,CAAC"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useCallback, useEffect, useState } from "react";
2
3
  import { useDebouncedCallback } from "use-debounce";
3
4
  import { useTamboClient, useTamboThread } from "../providers";
@@ -1 +1 @@
1
- {"version":3,"file":"use-component-state.js","sourceRoot":"","sources":["../../src/hooks/use-component-state.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { useTamboClient, useTamboThread } from \"../providers\";\nimport {\n useTamboCurrentMessage,\n useTamboMessageContext,\n} from \"./use-current-message\";\n// Define metadata interface for better extensibility\ninterface ComponentStateMeta {\n isPending: boolean;\n}\n\ntype StateUpdateResult<T> = [\n currentState: T,\n setState: (newState: T) => void,\n meta: ComponentStateMeta,\n];\n\n/**\n * A React hook that provides state management and passes user updates to Tambo.\n * Benefits: Passes user changes to AI, and when threads are returned, state is preserved.\n * @param keyName - The unique key to identify this state within the message's componentState object\n * @param initialValue - Optional initial value for the state, used if no value exists in the message\n * @param debounceTime - Optional debounce time in milliseconds (default: 300ms) to limit API calls\n * @returns A tuple containing:\n * - The current state value\n * - A setter function to update the state (updates UI immediately, debounces server sync)\n * - A metadata object with properties like isPending to track sync status\n * @example\n * // Basic usage\n * const [count, setCount, { isPending }] = useTamboComponentState(\"counter\", 0);\n *\n * // Usage with object state\n * const [formState, setFormState] = useTamboComponentState(\"myForm\", {\n * name: \"\",\n * email: \"\",\n * message: \"\"\n * });\n *\n * // Handling form input\n * const handleChange = (e) => {\n * setFormState({\n * ...formState,\n * [e.target.name]: e.target.value\n * });\n * };\n */\nexport function useTamboComponentState<S = undefined>(\n keyName: string,\n initialValue?: S,\n debounceTime?: number,\n): StateUpdateResult<S | undefined>;\nexport function useTamboComponentState<S>(\n keyName: string,\n initialValue: S,\n debounceTime?: number,\n): StateUpdateResult<S>;\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport function useTamboComponentState<S>(\n keyName: string,\n initialValue?: S,\n debounceTime = 500,\n): StateUpdateResult<S> {\n const { messageId } = useTamboMessageContext();\n const { updateThreadMessage, thread } = useTamboThread();\n const client = useTamboClient();\n const message = useTamboCurrentMessage();\n const threadId = thread.id;\n\n // Initial value management\n const [cachedInitialValue] = useState(() => initialValue);\n // UI state management\n const [localState, setLocalState] = useState<S | undefined>(\n cachedInitialValue,\n );\n // Synchronization state\n const [isPending, setIsPending] = useState(false);\n // Track the last user-initiated value instead of a simple boolean flag\n const [lastUserValue, setLastUserValue] = useState<S | null>(null);\n const [haveInitialized, setHaveInitialized] = useState(false);\n\n // Determine if we need to initialize state\n const shouldInitialize =\n !haveInitialized &&\n message &&\n cachedInitialValue !== undefined &&\n (!message.componentState || !(keyName in message.componentState));\n\n // Sync local state with message state on initial load and when message changes\n useEffect(() => {\n if (message?.componentState && keyName in message.componentState) {\n const messageState = message.componentState[keyName] as S;\n\n // Only update local state if we haven't had any user changes yet\n if (lastUserValue === null) {\n setLocalState(messageState);\n }\n }\n // Otherwise fall back to initial value if we have one and no user changes\n else if (\n cachedInitialValue !== undefined &&\n !localState &&\n lastUserValue === null\n ) {\n setLocalState(cachedInitialValue);\n }\n }, [\n keyName,\n message?.componentState,\n cachedInitialValue,\n lastUserValue,\n localState,\n ]);\n\n // Create debounced save function for efficient server synchronization\n const debouncedServerWrite = useDebouncedCallback(async (newValue: S) => {\n setIsPending(true);\n try {\n const componentStateUpdate = {\n state: { [keyName]: newValue },\n };\n\n await client.beta.threads.messages.updateComponentState(\n threadId,\n messageId,\n componentStateUpdate,\n );\n } catch (err) {\n console.error(\n `Failed to save component state for key \"${keyName}\":`,\n err,\n );\n } finally {\n setIsPending(false);\n }\n }, debounceTime);\n\n // Initialize state on first render if needed\n const initializeState = useCallback(async () => {\n if (!message) {\n console.warn(\n `Cannot initialize state for missing message ${messageId} with key \"${keyName}\"`,\n );\n return;\n }\n\n try {\n const messageUpdate = {\n ...message,\n componentState: {\n ...message.componentState,\n [keyName]: cachedInitialValue,\n },\n };\n\n const componentStateUpdate = {\n state: { [keyName]: cachedInitialValue },\n };\n\n await Promise.all([\n updateThreadMessage(messageId, messageUpdate, false),\n client.beta.threads.messages.updateComponentState(\n threadId,\n messageId,\n componentStateUpdate,\n ),\n ]);\n } catch (err) {\n console.warn(\n `Failed to initialize component state for key \"${keyName}\":`,\n err,\n );\n }\n }, [\n cachedInitialValue,\n client.beta.threads.messages,\n keyName,\n message,\n messageId,\n threadId,\n updateThreadMessage,\n ]);\n\n // Send initial state when component mounts\n useEffect(() => {\n if (shouldInitialize) {\n initializeState();\n setHaveInitialized(true);\n }\n }, [initializeState, shouldInitialize]);\n\n // setValue function for updating state\n // Updates local state immediately and schedules debounced server sync\n const setValue = useCallback(\n (newValue: S) => {\n // Track this as a user-initiated update\n setLastUserValue(newValue);\n setLocalState(newValue);\n\n // Only trigger server updates if we have a message\n if (message) {\n debouncedServerWrite(newValue);\n const messageUpdate = {\n ...message,\n componentState: {\n ...message.componentState,\n [keyName]: newValue,\n },\n };\n\n updateThreadMessage(messageId, messageUpdate, false);\n } else {\n console.warn(\n `Cannot update server for missing message ${messageId} with key \"${keyName}\"`,\n );\n }\n },\n [message, debouncedServerWrite, keyName, updateThreadMessage, messageId],\n );\n\n // Ensure pending changes are flushed on unmount\n useEffect(() => {\n return () => {\n debouncedServerWrite.flush();\n };\n }, [debouncedServerWrite]);\n\n // Return the local state for immediate UI rendering\n return [localState as S, setValue, { isPending }];\n}\n"]}
1
+ {"version":3,"file":"use-component-state.js","sourceRoot":"","sources":["../../src/hooks/use-component-state.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { useTamboClient, useTamboThread } from \"../providers\";\nimport {\n useTamboCurrentMessage,\n useTamboMessageContext,\n} from \"./use-current-message\";\n// Define metadata interface for better extensibility\ninterface ComponentStateMeta {\n isPending: boolean;\n}\n\ntype StateUpdateResult<T> = [\n currentState: T,\n setState: (newState: T) => void,\n meta: ComponentStateMeta,\n];\n\n/**\n * A React hook that provides state management and passes user updates to Tambo.\n * Benefits: Passes user changes to AI, and when threads are returned, state is preserved.\n * @param keyName - The unique key to identify this state within the message's componentState object\n * @param initialValue - Optional initial value for the state, used if no value exists in the message\n * @param debounceTime - Optional debounce time in milliseconds (default: 300ms) to limit API calls\n * @returns A tuple containing:\n * - The current state value\n * - A setter function to update the state (updates UI immediately, debounces server sync)\n * - A metadata object with properties like isPending to track sync status\n * @example\n * // Basic usage\n * const [count, setCount, { isPending }] = useTamboComponentState(\"counter\", 0);\n *\n * // Usage with object state\n * const [formState, setFormState] = useTamboComponentState(\"myForm\", {\n * name: \"\",\n * email: \"\",\n * message: \"\"\n * });\n *\n * // Handling form input\n * const handleChange = (e) => {\n * setFormState({\n * ...formState,\n * [e.target.name]: e.target.value\n * });\n * };\n */\nexport function useTamboComponentState<S = undefined>(\n keyName: string,\n initialValue?: S,\n debounceTime?: number,\n): StateUpdateResult<S | undefined>;\nexport function useTamboComponentState<S>(\n keyName: string,\n initialValue: S,\n debounceTime?: number,\n): StateUpdateResult<S>;\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport function useTamboComponentState<S>(\n keyName: string,\n initialValue?: S,\n debounceTime = 500,\n): StateUpdateResult<S> {\n const { messageId } = useTamboMessageContext();\n const { updateThreadMessage, thread } = useTamboThread();\n const client = useTamboClient();\n const message = useTamboCurrentMessage();\n const threadId = thread.id;\n\n // Initial value management\n const [cachedInitialValue] = useState(() => initialValue);\n // UI state management\n const [localState, setLocalState] = useState<S | undefined>(\n cachedInitialValue,\n );\n // Synchronization state\n const [isPending, setIsPending] = useState(false);\n // Track the last user-initiated value instead of a simple boolean flag\n const [lastUserValue, setLastUserValue] = useState<S | null>(null);\n const [haveInitialized, setHaveInitialized] = useState(false);\n\n // Determine if we need to initialize state\n const shouldInitialize =\n !haveInitialized &&\n message &&\n cachedInitialValue !== undefined &&\n (!message.componentState || !(keyName in message.componentState));\n\n // Sync local state with message state on initial load and when message changes\n useEffect(() => {\n if (message?.componentState && keyName in message.componentState) {\n const messageState = message.componentState[keyName] as S;\n\n // Only update local state if we haven't had any user changes yet\n if (lastUserValue === null) {\n setLocalState(messageState);\n }\n }\n // Otherwise fall back to initial value if we have one and no user changes\n else if (\n cachedInitialValue !== undefined &&\n !localState &&\n lastUserValue === null\n ) {\n setLocalState(cachedInitialValue);\n }\n }, [\n keyName,\n message?.componentState,\n cachedInitialValue,\n lastUserValue,\n localState,\n ]);\n\n // Create debounced save function for efficient server synchronization\n const debouncedServerWrite = useDebouncedCallback(async (newValue: S) => {\n setIsPending(true);\n try {\n const componentStateUpdate = {\n state: { [keyName]: newValue },\n };\n\n await client.beta.threads.messages.updateComponentState(\n threadId,\n messageId,\n componentStateUpdate,\n );\n } catch (err) {\n console.error(\n `Failed to save component state for key \"${keyName}\":`,\n err,\n );\n } finally {\n setIsPending(false);\n }\n }, debounceTime);\n\n // Initialize state on first render if needed\n const initializeState = useCallback(async () => {\n if (!message) {\n console.warn(\n `Cannot initialize state for missing message ${messageId} with key \"${keyName}\"`,\n );\n return;\n }\n\n try {\n const messageUpdate = {\n ...message,\n componentState: {\n ...message.componentState,\n [keyName]: cachedInitialValue,\n },\n };\n\n const componentStateUpdate = {\n state: { [keyName]: cachedInitialValue },\n };\n\n await Promise.all([\n updateThreadMessage(messageId, messageUpdate, false),\n client.beta.threads.messages.updateComponentState(\n threadId,\n messageId,\n componentStateUpdate,\n ),\n ]);\n } catch (err) {\n console.warn(\n `Failed to initialize component state for key \"${keyName}\":`,\n err,\n );\n }\n }, [\n cachedInitialValue,\n client.beta.threads.messages,\n keyName,\n message,\n messageId,\n threadId,\n updateThreadMessage,\n ]);\n\n // Send initial state when component mounts\n useEffect(() => {\n if (shouldInitialize) {\n initializeState();\n setHaveInitialized(true);\n }\n }, [initializeState, shouldInitialize]);\n\n // setValue function for updating state\n // Updates local state immediately and schedules debounced server sync\n const setValue = useCallback(\n (newValue: S) => {\n // Track this as a user-initiated update\n setLastUserValue(newValue);\n setLocalState(newValue);\n\n // Only trigger server updates if we have a message\n if (message) {\n debouncedServerWrite(newValue);\n const messageUpdate = {\n ...message,\n componentState: {\n ...message.componentState,\n [keyName]: newValue,\n },\n };\n\n updateThreadMessage(messageId, messageUpdate, false);\n } else {\n console.warn(\n `Cannot update server for missing message ${messageId} with key \"${keyName}\"`,\n );\n }\n },\n [message, debouncedServerWrite, keyName, updateThreadMessage, messageId],\n );\n\n // Ensure pending changes are flushed on unmount\n useEffect(() => {\n return () => {\n debouncedServerWrite.flush();\n };\n }, [debouncedServerWrite]);\n\n // Return the local state for immediate UI rendering\n return [localState as S, setValue, { isPending }];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-current-message.d.ts","sourceRoot":"","sources":["../../src/hooks/use-current-message.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAiB,iBAAiB,EAAc,MAAM,OAAO,CAAC;AAG5E,UAAU,wBAAwB;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CACzC,iBAAiB,CAAC,wBAAwB,CAAC,CAU5C,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,KAAK,CAAC,SAAS,EACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,qBAOlB;AACD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,gCAQlC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,mDASlC,CAAC"}
1
+ {"version":3,"file":"use-current-message.d.ts","sourceRoot":"","sources":["../../src/hooks/use-current-message.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAiB,iBAAiB,EAAc,MAAM,OAAO,CAAC;AAG5E,UAAU,wBAAwB;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CACzC,iBAAiB,CAAC,wBAAwB,CAAC,CAU5C,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,KAAK,CAAC,SAAS,EACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,qBAOlB;AACD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,gCAQlC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,mDASlC,CAAC"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import React, { createContext, useContext } from "react";
2
3
  import { useTamboThread } from "../providers";
3
4
  const TamboMessageContext = createContext({
@@ -1 +1 @@
1
- {"version":3,"file":"use-current-message.js","sourceRoot":"","sources":["../../src/hooks/use-current-message.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,aAAa,EAAqB,UAAU,EAAE,MAAM,OAAO,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAY9C,MAAM,mBAAmB,GAAG,aAAa,CAA2B;IAClE,SAAS,EAAE,EAAE;CACd,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAE7B,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE;IAC9B,gFAAgF;IAChF,2EAA2E;IAC3E,6EAA6E;IAC7E,OAAO,CACL,oBAAC,mBAAmB,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,SAAS,IAC/D,QAAQ,CACoB,CAChC,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAC1C,QAAyB,EACzB,QAAgB,EAChB,SAAiB;IAEjB,OAAO,CACL,oBAAC,oBAAoB,IAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,IAC3D,QAAQ,CACY,CACxB,CAAC;AACJ,CAAC;AACD;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE;IACzC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,sBAAsB,EAAE,CAAC;IACzD,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IACpC,IAAI,MAAM,CAAC,EAAE,IAAI,QAAQ,IAAI,MAAM,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,sBAAsB,MAAM,CAAC,EAAE,QAAQ,QAAQ,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;IAChE,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC","sourcesContent":["import React, { createContext, PropsWithChildren, useContext } from \"react\";\nimport { useTamboThread } from \"../providers\";\n\ninterface TamboMessageContextProps {\n /**\n * The threadId of the thread\n * @deprecated Use the thread object from the TamboThreadProvider instead\n */\n threadId?: string;\n /** The messageId of the message */\n messageId: string;\n}\n\nconst TamboMessageContext = createContext<TamboMessageContextProps>({\n messageId: \"\",\n});\n\n/**\n * Wraps all components, so that they can find what thread and message they are in\n * @param props - props for the TamboMessageProvider\n * @param props.children - The children to wrap\n * @param props.messageId - The messageId of the message\n * @returns The wrapped component\n */\nexport const TamboMessageProvider: React.FC<\n PropsWithChildren<TamboMessageContextProps>\n> = ({ children, messageId }) => {\n // Use a unique key={...} to force a re-render when the messageId changes - this\n // make sure that if the rendered component is swapped into a tree (like if\n // you always show the last rendered component) then the state/etc is correct\n return (\n <TamboMessageContext.Provider value={{ messageId }} key={messageId}>\n {children}\n </TamboMessageContext.Provider>\n );\n};\n\n/**\n * Wraps a component with a ComponentMessageProvider - this allows the provider\n * to be used outside of a TSX file\n * @param children - The children to wrap\n * @param threadId - The threadId of the thread\n * @param messageId - The messageId of the message\n * @returns The wrapped component\n */\nexport function wrapWithTamboMessageProvider(\n children: React.ReactNode,\n threadId: string,\n messageId: string,\n) {\n return (\n <TamboMessageProvider threadId={threadId} messageId={messageId}>\n {children}\n </TamboMessageProvider>\n );\n}\n/**\n * Hook used inside a component wrapped with ComponentMessageProvider, to get\n * the threadId and messageId\n * @returns The threadId and messageId\n */\nexport const useTamboMessageContext = () => {\n const context = useContext(TamboMessageContext);\n if (!context) {\n throw new Error(\n \"useTamboMessageContext must be used within a TamboMessageProvider\",\n );\n }\n return context;\n};\n\n/**\n * Hook used inside a component wrapped with ComponentMessageProvider, to get\n * the current message. The current thread will be fetched from the server, if\n * it is not already in the cache.\n * @returns The current message that is used to render the component\n */\nexport const useTamboCurrentMessage = () => {\n const { messageId, threadId } = useTamboMessageContext();\n const { thread } = useTamboThread();\n if (thread.id && threadId && thread.id !== threadId) {\n console.warn(`Thread ID mismatch ${thread.id} !== ${threadId}`);\n }\n\n const message = thread.messages.find((m) => m.id === messageId);\n return message;\n};\n"]}
1
+ {"version":3,"file":"use-current-message.js","sourceRoot":"","sources":["../../src/hooks/use-current-message.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,KAAK,EAAE,EAAE,aAAa,EAAqB,UAAU,EAAE,MAAM,OAAO,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAY9C,MAAM,mBAAmB,GAAG,aAAa,CAA2B;IAClE,SAAS,EAAE,EAAE;CACd,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAE7B,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE;IAC9B,gFAAgF;IAChF,2EAA2E;IAC3E,6EAA6E;IAC7E,OAAO,CACL,oBAAC,mBAAmB,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,SAAS,IAC/D,QAAQ,CACoB,CAChC,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAC1C,QAAyB,EACzB,QAAgB,EAChB,SAAiB;IAEjB,OAAO,CACL,oBAAC,oBAAoB,IAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,IAC3D,QAAQ,CACY,CACxB,CAAC;AACJ,CAAC;AACD;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE;IACzC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,sBAAsB,EAAE,CAAC;IACzD,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IACpC,IAAI,MAAM,CAAC,EAAE,IAAI,QAAQ,IAAI,MAAM,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,sBAAsB,MAAM,CAAC,EAAE,QAAQ,QAAQ,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;IAChE,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC","sourcesContent":["\"use client\";\nimport React, { createContext, PropsWithChildren, useContext } from \"react\";\nimport { useTamboThread } from \"../providers\";\n\ninterface TamboMessageContextProps {\n /**\n * The threadId of the thread\n * @deprecated Use the thread object from the TamboThreadProvider instead\n */\n threadId?: string;\n /** The messageId of the message */\n messageId: string;\n}\n\nconst TamboMessageContext = createContext<TamboMessageContextProps>({\n messageId: \"\",\n});\n\n/**\n * Wraps all components, so that they can find what thread and message they are in\n * @param props - props for the TamboMessageProvider\n * @param props.children - The children to wrap\n * @param props.messageId - The messageId of the message\n * @returns The wrapped component\n */\nexport const TamboMessageProvider: React.FC<\n PropsWithChildren<TamboMessageContextProps>\n> = ({ children, messageId }) => {\n // Use a unique key={...} to force a re-render when the messageId changes - this\n // make sure that if the rendered component is swapped into a tree (like if\n // you always show the last rendered component) then the state/etc is correct\n return (\n <TamboMessageContext.Provider value={{ messageId }} key={messageId}>\n {children}\n </TamboMessageContext.Provider>\n );\n};\n\n/**\n * Wraps a component with a ComponentMessageProvider - this allows the provider\n * to be used outside of a TSX file\n * @param children - The children to wrap\n * @param threadId - The threadId of the thread\n * @param messageId - The messageId of the message\n * @returns The wrapped component\n */\nexport function wrapWithTamboMessageProvider(\n children: React.ReactNode,\n threadId: string,\n messageId: string,\n) {\n return (\n <TamboMessageProvider threadId={threadId} messageId={messageId}>\n {children}\n </TamboMessageProvider>\n );\n}\n/**\n * Hook used inside a component wrapped with ComponentMessageProvider, to get\n * the threadId and messageId\n * @returns The threadId and messageId\n */\nexport const useTamboMessageContext = () => {\n const context = useContext(TamboMessageContext);\n if (!context) {\n throw new Error(\n \"useTamboMessageContext must be used within a TamboMessageProvider\",\n );\n }\n return context;\n};\n\n/**\n * Hook used inside a component wrapped with ComponentMessageProvider, to get\n * the current message. The current thread will be fetched from the server, if\n * it is not already in the cache.\n * @returns The current message that is used to render the component\n */\nexport const useTamboCurrentMessage = () => {\n const { messageId, threadId } = useTamboMessageContext();\n const { thread } = useTamboThread();\n if (thread.id && threadId && thread.id !== threadId) {\n console.warn(`Thread ID mismatch ${thread.id} !== ${threadId}`);\n }\n\n const message = thread.messages.find((m) => m.id === messageId);\n return message;\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-streaming-props.d.ts","sourceRoot":"","sources":["../../src/hooks/use-streaming-props.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAClE,YAAY,EAAE,CAAC,GAAG,SAAS,EAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAC5B,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,QAwB3B"}
1
+ {"version":3,"file":"use-streaming-props.d.ts","sourceRoot":"","sources":["../../src/hooks/use-streaming-props.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAClE,YAAY,EAAE,CAAC,GAAG,SAAS,EAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAC5B,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,QAwB3B"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useEffect } from "react";
2
3
  /**
3
4
  * A helper hook that automatically updates Tambo component state when specified props change.
@@ -1 +1 @@
1
- {"version":3,"file":"use-streaming-props.js","sourceRoot":"","sources":["../../src/hooks/use-streaming-props.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,sBAAsB,CACpC,YAA2B,EAC3B,QAA4B,EAC5B,cAA0B;IAE1B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,YAAY,GAAG,KAAK,CAAC;YACzB,MAAM,OAAO,GAAe,EAAE,CAAC;YAE/B,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;gBACtD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvD,YAAY,GAAG,IAAI,CAAC;oBACpB,OAAO,CAAC,GAAc,CAAC,GAAG,KAAmB,CAAC;gBAChD,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,IAAI,YAAY,EAAE,CAAC;gBACjB,QAAQ,CAAC;oBACP,GAAG,YAAY;oBACf,GAAG,OAAO;iBACX,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,sCAAsC;QACtC,uDAAuD;IACzD,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC","sourcesContent":["import { useEffect } from \"react\";\n\n/**\n * A helper hook that automatically updates Tambo component state when specified props change.\n *\n * This hook streamlines the common pattern of updating component state when receiving new\n * streamed values from Tambo, eliminating the need to write repetitive useEffect code.\n * @param currentState - The current state object from useTamboComponentState\n * @param setState - The setState function from useTamboComponentState\n * @param streamingProps - An object mapping state keys to prop values that should update the state\n * @example\n * ```tsx\n * // Instead of writing a complex useEffect:\n * const [emailState, setEmailState] = useTamboComponentState(\"email\", initialState);\n *\n * // Simply use:\n * useTamboStreamingProps(emailState, setEmailState, {\n * subject: aiGeneratedSubject,\n * body: aiGeneratedBody,\n * usersEmail: usersEmail\n * });\n * ```\n */\nexport function useTamboStreamingProps<T extends Record<string, any>>(\n currentState: T | undefined,\n setState: (state: T) => void,\n streamingProps: Partial<T>,\n) {\n useEffect(() => {\n if (currentState) {\n let shouldUpdate = false;\n const updates: Partial<T> = {};\n\n Object.entries(streamingProps).forEach(([key, value]) => {\n if (value !== undefined && value !== currentState[key]) {\n shouldUpdate = true;\n updates[key as keyof T] = value as T[keyof T];\n }\n });\n\n if (shouldUpdate) {\n setState({\n ...currentState,\n ...updates,\n });\n }\n }\n // Only run when streamingProps change\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [...Object.values(streamingProps)]);\n}\n"]}
1
+ {"version":3,"file":"use-streaming-props.js","sourceRoot":"","sources":["../../src/hooks/use-streaming-props.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,sBAAsB,CACpC,YAA2B,EAC3B,QAA4B,EAC5B,cAA0B;IAE1B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,YAAY,GAAG,KAAK,CAAC;YACzB,MAAM,OAAO,GAAe,EAAE,CAAC;YAE/B,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;gBACtD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvD,YAAY,GAAG,IAAI,CAAC;oBACpB,OAAO,CAAC,GAAc,CAAC,GAAG,KAAmB,CAAC;gBAChD,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,IAAI,YAAY,EAAE,CAAC;gBACjB,QAAQ,CAAC;oBACP,GAAG,YAAY;oBACf,GAAG,OAAO;iBACX,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,sCAAsC;QACtC,uDAAuD;IACzD,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC","sourcesContent":["\"use client\";\nimport { useEffect } from \"react\";\n\n/**\n * A helper hook that automatically updates Tambo component state when specified props change.\n *\n * This hook streamlines the common pattern of updating component state when receiving new\n * streamed values from Tambo, eliminating the need to write repetitive useEffect code.\n * @param currentState - The current state object from useTamboComponentState\n * @param setState - The setState function from useTamboComponentState\n * @param streamingProps - An object mapping state keys to prop values that should update the state\n * @example\n * ```tsx\n * // Instead of writing a complex useEffect:\n * const [emailState, setEmailState] = useTamboComponentState(\"email\", initialState);\n *\n * // Simply use:\n * useTamboStreamingProps(emailState, setEmailState, {\n * subject: aiGeneratedSubject,\n * body: aiGeneratedBody,\n * usersEmail: usersEmail\n * });\n * ```\n */\nexport function useTamboStreamingProps<T extends Record<string, any>>(\n currentState: T | undefined,\n setState: (state: T) => void,\n streamingProps: Partial<T>,\n) {\n useEffect(() => {\n if (currentState) {\n let shouldUpdate = false;\n const updates: Partial<T> = {};\n\n Object.entries(streamingProps).forEach(([key, value]) => {\n if (value !== undefined && value !== currentState[key]) {\n shouldUpdate = true;\n updates[key as keyof T] = value as T[keyof T];\n }\n });\n\n if (shouldUpdate) {\n setState({\n ...currentState,\n ...updates,\n });\n }\n }\n // Only run when streamingProps change\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [...Object.values(streamingProps)]);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-suggestions.d.ts","sourceRoot":"","sources":["../../src/hooks/use-suggestions.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,0BAA0B,CAAC;AAQ/C,OAAO,EACL,sBAAsB,EAEvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EAGpB,MAAM,qBAAqB,CAAC;AAG7B;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,iCAAiC;IAChD,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;IAC/C,8CAA8C;IAC9C,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC;;;;OAIG;IACH,MAAM,EAAE,CAAC,aAAa,EAAE;QACtB,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpB,0DAA0D;IAC1D,YAAY,EAAE,sBAAsB,CAClC,IAAI,EACJ,KAAK,EACL;QAAE,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,CACxE,CAAC;IAEF,0DAA0D;IAC1D,cAAc,EAAE,sBAAsB,CACpC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,0BAA0B,GAAG,SAAS,EACvE,KAAK,EACL,eAAe,CAChB,CAAC;IAEF,yDAAyD;IACzD,iBAAiB,EAAE,mBAAmB,CACpC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,0BAA0B,GAAG,SAAS,EACvE,KAAK,CACN,CAAC;CACH;AAED,KAAK,yBAAyB,GAAG,sBAAsB,CAAC,GAAG,EAAE,KAAK,CAAC,GACjE,iCAAiC,CAAC;AAEpC;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,0BAA+B,GACvC,yBAAyB,CAsI3B"}
1
+ {"version":3,"file":"use-suggestions.d.ts","sourceRoot":"","sources":["../../src/hooks/use-suggestions.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,0BAA0B,CAAC;AAQ/C,OAAO,EACL,sBAAsB,EAEvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EAGpB,MAAM,qBAAqB,CAAC;AAG7B;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,iCAAiC;IAChD,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;IAC/C,8CAA8C;IAC9C,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC;;;;OAIG;IACH,MAAM,EAAE,CAAC,aAAa,EAAE;QACtB,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpB,0DAA0D;IAC1D,YAAY,EAAE,sBAAsB,CAClC,IAAI,EACJ,KAAK,EACL;QAAE,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,CACxE,CAAC;IAEF,0DAA0D;IAC1D,cAAc,EAAE,sBAAsB,CACpC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,0BAA0B,GAAG,SAAS,EACvE,KAAK,EACL,eAAe,CAChB,CAAC;IAEF,yDAAyD;IACzD,iBAAiB,EAAE,mBAAmB,CACpC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,0BAA0B,GAAG,SAAS,EACvE,KAAK,CACN,CAAC;CACH;AAED,KAAK,yBAAyB,GAAG,sBAAsB,CAAC,GAAG,EAAE,KAAK,CAAC,GACjE,iCAAiC,CAAC;AAEpC;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,0BAA+B,GACvC,yBAAyB,CAsI3B"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useEffect, useState } from "react";
2
3
  import { isIdleStage } from "../model/generate-component-response";
3
4
  import { validateInput } from "../model/validate-input";
@@ -1 +1 @@
1
- {"version":3,"file":"use-suggestions.js","sourceRoot":"","sources":["../../src/hooks/use-suggestions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAEL,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAGL,gBAAgB,EAChB,aAAa,GACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAoD/E;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAAsC,EAAE;IAExC,MAAM,EAAE,cAAc,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IACvC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,cAAc,EAAE,CAAC;IACrD,MAAM,EAAE,iBAAiB,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,yBAAyB,EAAE,GAC9D,gBAAgB,EAAE,CAAC;IAErB,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GAAG,QAAQ,CAE9D,IAAI,CAAC,CAAC;IACR,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,mBAAmB,EAAE,CAAC;IAE1D,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClE,MAAM,iBAAiB,GAAG,aAAa,EAAE,IAAI,KAAK,WAAW,CAAC;IAC9D,MAAM,eAAe,GAAG,aAAa,EAAE,EAAE,CAAC;IAE1C,qDAAqD;IACrD,SAAS,CAAC,GAAG,EAAE;QACb,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtB,MAAM,yBAAyB,GAC7B,eAAe,IAAI,iBAAiB,IAAI,WAAW,CAAC,eAAe,CAAC,CAAC;IACvE,4EAA4E;IAC5E,MAAM,iBAAiB,GAAG,aAAa,CAAC;QACtC,2EAA2E;QAC3E,4DAA4D;QAC5D,QAAQ,EAAE;YACR,aAAa;YACb,yBAAyB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI;SACnD;QACD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,CAAC,yBAAyB,EAAE,CAAC;gBAC/B,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,8CAA8C;YAC9C,MAAM,UAAU,GAAG,sBAAsB,CACvC,aAAa,EACb,YAAY,EACZ,yBAAyB,CAC1B,CAAC;YAEF,OAAO,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CACxD,MAAM,CAAC,EAAE,EACT,eAAe,EACf;gBACE,cAAc;gBACd,mBAAmB,EAAE,UAAU;aAChC,CACF,CAAC;QACJ,CAAC;QACD,2DAA2D;QAC3D,OAAO,EAAE,OAAO,CAAC,eAAe,IAAI,iBAAiB,CAAC;QACtD,6CAA6C;QAC7C,oBAAoB,EAAE,KAAK;QAC3B,kBAAkB,EAAE,KAAK;QACzB,yBAAyB;QACzB,KAAK,EAAE,KAAK;KACb,CAAC,CAAC;IAEH,6BAA6B;IAC7B,MAAM,mBAAmB,GAAG,gBAAgB,CAI1C;QACA,UAAU,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,YAAY,GAAG,KAAK,EAAE,EAAE,EAAE;YACzD,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;YAChE,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;gBACxB,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;oBACrB,MAAM,UAAU,CAAC,KAAK,CAAC;gBACzB,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;YACnD,CAAC;YAED,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,iBAAiB,CAAC,UAAU,CAAC,cAAc,EAAE;oBACjD,QAAQ,EAAE,MAAM,CAAC,EAAE;iBACpB,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,aAAa,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;YAC3C,CAAC;YACD,uBAAuB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACzC,CAAC;KACF,CAAC,CAAC;IAEH,gCAAgC;IAChC,MAAM,qBAAqB,GAAG,gBAAgB,CAI5C;QACA,UAAU,EAAE,KAAK,EAAE,eAAgC,EAAE,EAAE;YACrD,IAAI,CAAC,yBAAyB,EAAE,CAAC;gBAC/B,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,8CAA8C;YAC9C,MAAM,UAAU,GAAG,sBAAsB,CACvC,aAAa,EACb,YAAY,EACZ,yBAAyB,CAC1B,CAAC;YACF,OAAO,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CACxD,MAAM,CAAC,EAAE,EACT,eAAe,EACf;gBACE,cAAc;gBACd,mBAAmB,EAAE,UAAU;aAChC,EACD,EAAE,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,CACnC,CAAC;QACJ,CAAC;QACD,yBAAyB;QACzB,KAAK,EAAE,KAAK;KACb,CAAC,CAAC;IAEH,mEAAmE;IACnE,8DAA8D;IAC9D,MAAM,WAAW,GAAG,iBAAiB;QACnC,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,IAAI,qBAAqB,CAAC,IAAI,IAAI,EAAE,CAAC;QAC9D,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;QACL,WAAW;QACX,MAAM,EAAE,mBAAmB,CAAC,WAAW;QACvC,oBAAoB;QACpB,YAAY,EAAE,mBAAmB;QACjC,cAAc,EAAE,qBAAqB;QACrC,iBAAiB;QACjB,GAAG,sBAAsB,CAAC,mBAAmB,EAAE,qBAAqB,CAAC;KACtE,CAAC;AACJ,CAAC","sourcesContent":["import TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { useEffect, useState } from \"react\";\nimport { isIdleStage } from \"../model/generate-component-response\";\nimport { validateInput } from \"../model/validate-input\";\nimport { useTamboClient } from \"../providers/tambo-client-provider\";\nimport { useTambo } from \"../providers/tambo-provider\";\nimport { useTamboRegistry } from \"../providers/tambo-registry-provider\";\nimport { useTamboThread } from \"../providers/tambo-thread-provider\";\nimport {\n CombinedMutationResult,\n combineMutationResults,\n} from \"../util/query-utils\";\nimport { getAvailableComponents } from \"../util/registry\";\nimport {\n UseTamboMutationResult,\n UseTamboQueryResult,\n useTamboMutation,\n useTamboQuery,\n} from \"./react-query-hooks\";\nimport { INPUT_ERROR_MESSAGES, useTamboThreadInput } from \"./use-thread-input\";\n\n/**\n * Configuration options for the useTamboSuggestions hook\n */\nexport interface useTamboSuggestionsOptions {\n /** Maximum number of suggestions to generate (1-10, default 3) */\n maxSuggestions?: number;\n}\n\n/**\n * Return value interface for useTamboSuggestions hook\n */\nexport interface useTamboSuggestionsResultInternal {\n /** List of available suggestions (also available in generateResult.data) */\n suggestions: TamboAI.Beta.Threads.Suggestion[];\n /** ID of the currently selected suggestion */\n selectedSuggestionId: string | null;\n /**\n * Accept and apply a suggestion (also available in acceptResult.mutateAsync)\n * @param suggestion - The suggestion to accept\n * @param shouldSubmit - Whether to automatically submit after accepting (default: false)\n */\n accept: (acceptOptions: {\n suggestion: TamboAI.Beta.Threads.Suggestion;\n shouldSubmit?: boolean;\n }) => Promise<void>;\n\n /** Result and network state for accepting a suggestion */\n acceptResult: UseTamboMutationResult<\n void,\n Error,\n { suggestion: TamboAI.Beta.Threads.Suggestion; shouldSubmit?: boolean }\n >;\n\n /** Result and network state for generating suggestions */\n generateResult: UseTamboMutationResult<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error,\n AbortController\n >;\n\n /** The full suggestions query object from React Query */\n suggestionsResult: UseTamboQueryResult<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error\n >;\n}\n\ntype useTamboSuggestionsResult = CombinedMutationResult<any, Error> &\n useTamboSuggestionsResultInternal;\n\n/**\n * Hook for managing Tambo AI suggestions in a thread\n * @param options - Configuration options for suggestion generation\n * @returns Object containing suggestions state and control functions\n */\nexport function useTamboSuggestions(\n options: useTamboSuggestionsOptions = {},\n): useTamboSuggestionsResult {\n const { maxSuggestions = 3 } = options;\n const { thread, generationStage } = useTamboThread();\n const { sendThreadMessage } = useTambo();\n const tamboClient = useTamboClient();\n const { componentList, toolRegistry, componentToolAssociations } =\n useTamboRegistry();\n\n const [selectedSuggestionId, setSelectedSuggestionId] = useState<\n string | null\n >(null);\n const { setValue: setInputValue } = useTamboThreadInput();\n\n const latestMessage = thread.messages[thread.messages.length - 1];\n const isLatestFromTambo = latestMessage?.role === \"assistant\";\n const latestMessageId = latestMessage?.id;\n\n // Reset selected suggestion when the message changes\n useEffect(() => {\n setSelectedSuggestionId(null);\n }, [latestMessageId]);\n\n const shouldGenerateSuggestions =\n latestMessageId && isLatestFromTambo && isIdleStage(generationStage);\n // Use React Query to fetch suggestions when a new hydra message is received\n const suggestionsResult = useTamboQuery({\n // Make sure the query key changes when the message changes, so that we are\n // always generating suggestions when there is a new message\n queryKey: [\n \"suggestions\",\n shouldGenerateSuggestions ? latestMessageId : null,\n ],\n queryFn: async () => {\n if (!shouldGenerateSuggestions) {\n return [];\n }\n\n // Get registered components from the registry\n const components = getAvailableComponents(\n componentList,\n toolRegistry,\n componentToolAssociations,\n );\n\n return await tamboClient.beta.threads.suggestions.generate(\n thread.id,\n latestMessageId,\n {\n maxSuggestions,\n availableComponents: components,\n },\n );\n },\n // Only run the query if we have a valid message from hydra\n enabled: Boolean(latestMessageId && isLatestFromTambo),\n // Don't refetch on window focus or reconnect\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n // Don't retry on failure\n retry: false,\n });\n\n // Accept suggestion mutation\n const acceptMutationState = useTamboMutation<\n void,\n Error,\n { suggestion: TamboAI.Beta.Threads.Suggestion; shouldSubmit?: boolean }\n >({\n mutationFn: async ({ suggestion, shouldSubmit = false }) => {\n const validation = validateInput(suggestion.detailedSuggestion);\n if (!validation.isValid) {\n if (validation.error) {\n throw validation.error;\n }\n throw new Error(INPUT_ERROR_MESSAGES.VALIDATION);\n }\n\n if (shouldSubmit) {\n await sendThreadMessage(validation.sanitizedInput, {\n threadId: thread.id,\n });\n } else {\n setInputValue(validation.sanitizedInput);\n }\n setSelectedSuggestionId(suggestion.id);\n },\n });\n\n // Generate suggestions mutation\n const generateMutationState = useTamboMutation<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error,\n AbortController\n >({\n mutationFn: async (abortController: AbortController) => {\n if (!shouldGenerateSuggestions) {\n return undefined;\n }\n\n // Get registered components from the registry\n const components = getAvailableComponents(\n componentList,\n toolRegistry,\n componentToolAssociations,\n );\n return await tamboClient.beta.threads.suggestions.generate(\n thread.id,\n latestMessageId,\n {\n maxSuggestions,\n availableComponents: components,\n },\n { signal: abortController.signal },\n );\n },\n // Don't retry on failure\n retry: false,\n });\n\n // Use the query data if available, otherwise use the mutation data\n // Only return suggestions if the latest message is from hydra\n const suggestions = isLatestFromTambo\n ? (suggestionsResult.data ?? generateMutationState.data ?? [])\n : [];\n\n return {\n suggestions,\n accept: acceptMutationState.mutateAsync,\n selectedSuggestionId,\n acceptResult: acceptMutationState,\n generateResult: generateMutationState,\n suggestionsResult,\n ...combineMutationResults(acceptMutationState, generateMutationState),\n };\n}\n"]}
1
+ {"version":3,"file":"use-suggestions.js","sourceRoot":"","sources":["../../src/hooks/use-suggestions.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { useEffect, useState } from \"react\";\nimport { isIdleStage } from \"../model/generate-component-response\";\nimport { validateInput } from \"../model/validate-input\";\nimport { useTamboClient } from \"../providers/tambo-client-provider\";\nimport { useTambo } from \"../providers/tambo-provider\";\nimport { useTamboRegistry } from \"../providers/tambo-registry-provider\";\nimport { useTamboThread } from \"../providers/tambo-thread-provider\";\nimport {\n CombinedMutationResult,\n combineMutationResults,\n} from \"../util/query-utils\";\nimport { getAvailableComponents } from \"../util/registry\";\nimport {\n UseTamboMutationResult,\n UseTamboQueryResult,\n useTamboMutation,\n useTamboQuery,\n} from \"./react-query-hooks\";\nimport { INPUT_ERROR_MESSAGES, useTamboThreadInput } from \"./use-thread-input\";\n\n/**\n * Configuration options for the useTamboSuggestions hook\n */\nexport interface useTamboSuggestionsOptions {\n /** Maximum number of suggestions to generate (1-10, default 3) */\n maxSuggestions?: number;\n}\n\n/**\n * Return value interface for useTamboSuggestions hook\n */\nexport interface useTamboSuggestionsResultInternal {\n /** List of available suggestions (also available in generateResult.data) */\n suggestions: TamboAI.Beta.Threads.Suggestion[];\n /** ID of the currently selected suggestion */\n selectedSuggestionId: string | null;\n /**\n * Accept and apply a suggestion (also available in acceptResult.mutateAsync)\n * @param suggestion - The suggestion to accept\n * @param shouldSubmit - Whether to automatically submit after accepting (default: false)\n */\n accept: (acceptOptions: {\n suggestion: TamboAI.Beta.Threads.Suggestion;\n shouldSubmit?: boolean;\n }) => Promise<void>;\n\n /** Result and network state for accepting a suggestion */\n acceptResult: UseTamboMutationResult<\n void,\n Error,\n { suggestion: TamboAI.Beta.Threads.Suggestion; shouldSubmit?: boolean }\n >;\n\n /** Result and network state for generating suggestions */\n generateResult: UseTamboMutationResult<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error,\n AbortController\n >;\n\n /** The full suggestions query object from React Query */\n suggestionsResult: UseTamboQueryResult<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error\n >;\n}\n\ntype useTamboSuggestionsResult = CombinedMutationResult<any, Error> &\n useTamboSuggestionsResultInternal;\n\n/**\n * Hook for managing Tambo AI suggestions in a thread\n * @param options - Configuration options for suggestion generation\n * @returns Object containing suggestions state and control functions\n */\nexport function useTamboSuggestions(\n options: useTamboSuggestionsOptions = {},\n): useTamboSuggestionsResult {\n const { maxSuggestions = 3 } = options;\n const { thread, generationStage } = useTamboThread();\n const { sendThreadMessage } = useTambo();\n const tamboClient = useTamboClient();\n const { componentList, toolRegistry, componentToolAssociations } =\n useTamboRegistry();\n\n const [selectedSuggestionId, setSelectedSuggestionId] = useState<\n string | null\n >(null);\n const { setValue: setInputValue } = useTamboThreadInput();\n\n const latestMessage = thread.messages[thread.messages.length - 1];\n const isLatestFromTambo = latestMessage?.role === \"assistant\";\n const latestMessageId = latestMessage?.id;\n\n // Reset selected suggestion when the message changes\n useEffect(() => {\n setSelectedSuggestionId(null);\n }, [latestMessageId]);\n\n const shouldGenerateSuggestions =\n latestMessageId && isLatestFromTambo && isIdleStage(generationStage);\n // Use React Query to fetch suggestions when a new hydra message is received\n const suggestionsResult = useTamboQuery({\n // Make sure the query key changes when the message changes, so that we are\n // always generating suggestions when there is a new message\n queryKey: [\n \"suggestions\",\n shouldGenerateSuggestions ? latestMessageId : null,\n ],\n queryFn: async () => {\n if (!shouldGenerateSuggestions) {\n return [];\n }\n\n // Get registered components from the registry\n const components = getAvailableComponents(\n componentList,\n toolRegistry,\n componentToolAssociations,\n );\n\n return await tamboClient.beta.threads.suggestions.generate(\n thread.id,\n latestMessageId,\n {\n maxSuggestions,\n availableComponents: components,\n },\n );\n },\n // Only run the query if we have a valid message from hydra\n enabled: Boolean(latestMessageId && isLatestFromTambo),\n // Don't refetch on window focus or reconnect\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n // Don't retry on failure\n retry: false,\n });\n\n // Accept suggestion mutation\n const acceptMutationState = useTamboMutation<\n void,\n Error,\n { suggestion: TamboAI.Beta.Threads.Suggestion; shouldSubmit?: boolean }\n >({\n mutationFn: async ({ suggestion, shouldSubmit = false }) => {\n const validation = validateInput(suggestion.detailedSuggestion);\n if (!validation.isValid) {\n if (validation.error) {\n throw validation.error;\n }\n throw new Error(INPUT_ERROR_MESSAGES.VALIDATION);\n }\n\n if (shouldSubmit) {\n await sendThreadMessage(validation.sanitizedInput, {\n threadId: thread.id,\n });\n } else {\n setInputValue(validation.sanitizedInput);\n }\n setSelectedSuggestionId(suggestion.id);\n },\n });\n\n // Generate suggestions mutation\n const generateMutationState = useTamboMutation<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error,\n AbortController\n >({\n mutationFn: async (abortController: AbortController) => {\n if (!shouldGenerateSuggestions) {\n return undefined;\n }\n\n // Get registered components from the registry\n const components = getAvailableComponents(\n componentList,\n toolRegistry,\n componentToolAssociations,\n );\n return await tamboClient.beta.threads.suggestions.generate(\n thread.id,\n latestMessageId,\n {\n maxSuggestions,\n availableComponents: components,\n },\n { signal: abortController.signal },\n );\n },\n // Don't retry on failure\n retry: false,\n });\n\n // Use the query data if available, otherwise use the mutation data\n // Only return suggestions if the latest message is from hydra\n const suggestions = isLatestFromTambo\n ? (suggestionsResult.data ?? generateMutationState.data ?? [])\n : [];\n\n return {\n suggestions,\n accept: acceptMutationState.mutateAsync,\n selectedSuggestionId,\n acceptResult: acceptMutationState,\n generateResult: generateMutationState,\n suggestionsResult,\n ...combineMutationResults(acceptMutationState, generateMutationState),\n };\n}\n"]}
package/esm/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { TamboMessageProvider, useTamboCurrentMessage, useTamboMessageContext, }
4
4
  export { useTamboStreamingProps } from "./hooks/use-streaming-props";
5
5
  export * from "./hooks/use-suggestions";
6
6
  export { useTamboThreadInput } from "./hooks/use-thread-input";
7
- export { TamboClientProvider, TamboComponentProvider, TamboProvider, TamboThreadProvider, useTambo, useTamboClient, useTamboThread, type TamboComponent, type TamboRegistryContext, } from "./providers";
7
+ export { TamboClientProvider, TamboComponentProvider, TamboProvider, TamboStubProvider, TamboThreadProvider, useTambo, useTamboClient, useTamboThread, type TamboComponent, type TamboRegistryContext, type TamboStubProviderProps, } from "./providers";
8
8
  export type { APIError, RateLimitError, TamboAIError, } from "@tambo-ai/typescript-sdk";
9
9
  export type { Suggestion, SuggestionGenerateParams, SuggestionGenerateResponse, SuggestionListResponse, } from "@tambo-ai/typescript-sdk/resources/beta/threads/suggestions";
10
10
  export { useTamboThreadList } from "./hooks/use-tambo-threads";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wKAAwK;AACxK,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,QAAQ,EACR,cAAc,EACd,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAC;AAGrB,YAAY,EACV,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,UAAU,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EACL,KAAK,4BAA4B,EACjC,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,SAAS,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,GACxB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wKAAwK;AACxK,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,QAAQ,EACR,cAAc,EACd,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AAGrB,YAAY,EACV,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,UAAU,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EACL,KAAK,4BAA4B,EACjC,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,SAAS,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,GACxB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
package/esm/index.js CHANGED
@@ -5,7 +5,7 @@ export { useTamboStreamingProps } from "./hooks/use-streaming-props";
5
5
  export * from "./hooks/use-suggestions";
6
6
  export { useTamboThreadInput } from "./hooks/use-thread-input";
7
7
  // Re-export provider components
8
- export { TamboClientProvider, TamboComponentProvider, TamboProvider, TamboThreadProvider, useTambo, useTamboClient, useTamboThread, } from "./providers";
8
+ export { TamboClientProvider, TamboComponentProvider, TamboProvider, TamboStubProvider, TamboThreadProvider, useTambo, useTamboClient, useTamboThread, } from "./providers";
9
9
  export { useTamboThreadList } from "./hooks/use-tambo-threads";
10
10
  export { GenerationStage, } from "./model/generate-component-response";
11
11
  //# sourceMappingURL=index.js.map
package/esm/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wKAAwK;AACxK,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,gCAAgC;AAChC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,QAAQ,EACR,cAAc,EACd,cAAc,GAGf,MAAM,aAAa,CAAC;AAcrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAQ/D,OAAO,EACL,eAAe,GAEhB,MAAM,qCAAqC,CAAC","sourcesContent":["/** Exports for the library. Only publically available exports are re-exported here. Anything not exported here is not supported and may change or break at any time. */\nexport { useTamboComponentState } from \"./hooks/use-component-state\";\nexport {\n TamboMessageProvider,\n useTamboCurrentMessage,\n useTamboMessageContext,\n} from \"./hooks/use-current-message\";\nexport { useTamboStreamingProps } from \"./hooks/use-streaming-props\";\nexport * from \"./hooks/use-suggestions\";\nexport { useTamboThreadInput } from \"./hooks/use-thread-input\";\n\n// Re-export provider components\nexport {\n TamboClientProvider,\n TamboComponentProvider,\n TamboProvider,\n TamboThreadProvider,\n useTambo,\n useTamboClient,\n useTamboThread,\n type TamboComponent,\n type TamboRegistryContext,\n} from \"./providers\";\n\n// Re-export types from Tambo Node SDK\nexport type {\n APIError,\n RateLimitError,\n TamboAIError,\n} from \"@tambo-ai/typescript-sdk\";\nexport type {\n Suggestion,\n SuggestionGenerateParams,\n SuggestionGenerateResponse,\n SuggestionListResponse,\n} from \"@tambo-ai/typescript-sdk/resources/beta/threads/suggestions\";\nexport { useTamboThreadList } from \"./hooks/use-tambo-threads\";\nexport {\n type ComponentContextToolMetadata,\n type ComponentRegistry,\n type ParameterSpec,\n type RegisteredComponent,\n type TamboTool,\n} from \"./model/component-metadata\";\nexport {\n GenerationStage,\n type TamboThreadMessage,\n} from \"./model/generate-component-response\";\nexport { type TamboThread } from \"./model/tambo-thread\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wKAAwK;AACxK,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,gCAAgC;AAChC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,QAAQ,EACR,cAAc,EACd,cAAc,GAIf,MAAM,aAAa,CAAC;AAcrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAQ/D,OAAO,EACL,eAAe,GAEhB,MAAM,qCAAqC,CAAC","sourcesContent":["/** Exports for the library. Only publically available exports are re-exported here. Anything not exported here is not supported and may change or break at any time. */\nexport { useTamboComponentState } from \"./hooks/use-component-state\";\nexport {\n TamboMessageProvider,\n useTamboCurrentMessage,\n useTamboMessageContext,\n} from \"./hooks/use-current-message\";\nexport { useTamboStreamingProps } from \"./hooks/use-streaming-props\";\nexport * from \"./hooks/use-suggestions\";\nexport { useTamboThreadInput } from \"./hooks/use-thread-input\";\n\n// Re-export provider components\nexport {\n TamboClientProvider,\n TamboComponentProvider,\n TamboProvider,\n TamboStubProvider,\n TamboThreadProvider,\n useTambo,\n useTamboClient,\n useTamboThread,\n type TamboComponent,\n type TamboRegistryContext,\n type TamboStubProviderProps,\n} from \"./providers\";\n\n// Re-export types from Tambo Node SDK\nexport type {\n APIError,\n RateLimitError,\n TamboAIError,\n} from \"@tambo-ai/typescript-sdk\";\nexport type {\n Suggestion,\n SuggestionGenerateParams,\n SuggestionGenerateResponse,\n SuggestionListResponse,\n} from \"@tambo-ai/typescript-sdk/resources/beta/threads/suggestions\";\nexport { useTamboThreadList } from \"./hooks/use-tambo-threads\";\nexport {\n type ComponentContextToolMetadata,\n type ComponentRegistry,\n type ParameterSpec,\n type RegisteredComponent,\n type TamboTool,\n} from \"./model/component-metadata\";\nexport {\n GenerationStage,\n type TamboThreadMessage,\n} from \"./model/generate-component-response\";\nexport { type TamboThread } from \"./model/tambo-thread\";\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tambo-stubs.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tambo-stubs.test.d.ts","sourceRoot":"","sources":["../../../src/providers/__tests__/tambo-stubs.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ import { renderHook } from "@testing-library/react";
2
+ import React, { act } from "react";
3
+ import { useTamboThreadList } from "../../hooks/use-tambo-threads";
4
+ import { TamboStubProvider } from "../tambo-stubs";
5
+ describe("TamboStubProvider threads functionality", () => {
6
+ const mockThread = {
7
+ id: "test-thread",
8
+ messages: [],
9
+ createdAt: "2024-01-01T00:00:00Z",
10
+ projectId: "test-project",
11
+ updatedAt: "2024-01-01T00:00:00Z",
12
+ metadata: {},
13
+ };
14
+ const mockThreadsData = {
15
+ items: [mockThread],
16
+ total: 1,
17
+ count: 1,
18
+ getPaginatedItems: () => [mockThread],
19
+ nextPageParams: () => ({ offset: 1, limit: 10 }),
20
+ nextPageInfo: () => null,
21
+ };
22
+ it("should populate query cache with threads data", async () => {
23
+ const wrapper = ({ children }) => (React.createElement(TamboStubProvider, { thread: mockThread, threads: mockThreadsData, projectId: "test-project", components: [], tools: [] }, children));
24
+ const { result } = renderHook(() => useTamboThreadList(), { wrapper });
25
+ // Wait for the effect to run
26
+ await act(async () => {
27
+ await new Promise((resolve) => setTimeout(resolve, 0));
28
+ });
29
+ // The hook should return the pre-populated threads data
30
+ expect(result.current.data).toEqual(mockThreadsData);
31
+ expect(result.current.isLoading).toBe(false);
32
+ });
33
+ it("should populate query cache with threads data using contextKey", async () => {
34
+ const wrapper = ({ children }) => (React.createElement(TamboStubProvider, { thread: mockThread, threads: mockThreadsData, projectId: "test-project", contextKey: "test-context", components: [], tools: [] }, children));
35
+ const { result } = renderHook(() => useTamboThreadList({ contextKey: "test-context" }), { wrapper });
36
+ // Wait for the effect to run
37
+ await act(async () => {
38
+ await new Promise((resolve) => setTimeout(resolve, 0));
39
+ });
40
+ // The hook should return the pre-populated threads data for the specific context
41
+ expect(result.current.data).toEqual(mockThreadsData);
42
+ expect(result.current.isLoading).toBe(false);
43
+ });
44
+ it("should default projectId to thread.projectId when not provided", async () => {
45
+ const wrapper = ({ children }) => (React.createElement(TamboStubProvider, { thread: mockThread, threads: mockThreadsData,
46
+ // No explicit projectId provided - should use thread.projectId
47
+ components: [], tools: [] }, children));
48
+ const { result } = renderHook(() => useTamboThreadList(), { wrapper });
49
+ // Wait for the effect to run
50
+ await act(async () => {
51
+ await new Promise((resolve) => setTimeout(resolve, 0));
52
+ });
53
+ // The hook should return the pre-populated threads data using thread.projectId
54
+ expect(result.current.data).toEqual(mockThreadsData);
55
+ expect(result.current.isLoading).toBe(false);
56
+ });
57
+ });
58
+ //# sourceMappingURL=tambo-stubs.test.js.map