@tambo-ai/react 0.16.2 → 0.18.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 (54) hide show
  1. package/README.md +39 -47
  2. package/dist/hooks/index.d.ts +8 -0
  3. package/dist/hooks/index.d.ts.map +1 -0
  4. package/dist/hooks/index.js +32 -0
  5. package/dist/hooks/index.js.map +1 -0
  6. package/dist/hooks/use-component-state.d.ts +40 -5
  7. package/dist/hooks/use-component-state.d.ts.map +1 -1
  8. package/dist/hooks/use-component-state.js +138 -47
  9. package/dist/hooks/use-component-state.js.map +1 -1
  10. package/dist/hooks/use-streaming-props.d.ts +25 -0
  11. package/dist/hooks/use-streaming-props.d.ts.map +1 -0
  12. package/dist/hooks/use-streaming-props.js +49 -0
  13. package/dist/hooks/use-streaming-props.js.map +1 -0
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/model/component-metadata.d.ts +7 -1
  19. package/dist/model/component-metadata.d.ts.map +1 -1
  20. package/dist/model/component-metadata.js.map +1 -1
  21. package/dist/providers/tambo-registry-provider.d.ts.map +1 -1
  22. package/dist/providers/tambo-registry-provider.js +24 -2
  23. package/dist/providers/tambo-registry-provider.js.map +1 -1
  24. package/dist/util/registry.d.ts +1 -0
  25. package/dist/util/registry.d.ts.map +1 -1
  26. package/dist/util/registry.js +14 -1
  27. package/dist/util/registry.js.map +1 -1
  28. package/esm/hooks/index.d.ts +8 -0
  29. package/esm/hooks/index.d.ts.map +1 -0
  30. package/esm/hooks/index.js +9 -0
  31. package/esm/hooks/index.js.map +1 -0
  32. package/esm/hooks/use-component-state.d.ts +40 -5
  33. package/esm/hooks/use-component-state.d.ts.map +1 -1
  34. package/esm/hooks/use-component-state.js +139 -48
  35. package/esm/hooks/use-component-state.js.map +1 -1
  36. package/esm/hooks/use-streaming-props.d.ts +25 -0
  37. package/esm/hooks/use-streaming-props.d.ts.map +1 -0
  38. package/esm/hooks/use-streaming-props.js +46 -0
  39. package/esm/hooks/use-streaming-props.js.map +1 -0
  40. package/esm/index.d.ts +1 -0
  41. package/esm/index.d.ts.map +1 -1
  42. package/esm/index.js +1 -0
  43. package/esm/index.js.map +1 -1
  44. package/esm/model/component-metadata.d.ts +7 -1
  45. package/esm/model/component-metadata.d.ts.map +1 -1
  46. package/esm/model/component-metadata.js.map +1 -1
  47. package/esm/providers/tambo-registry-provider.d.ts.map +1 -1
  48. package/esm/providers/tambo-registry-provider.js +21 -2
  49. package/esm/providers/tambo-registry-provider.js.map +1 -1
  50. package/esm/util/registry.d.ts +1 -0
  51. package/esm/util/registry.d.ts.map +1 -1
  52. package/esm/util/registry.js +12 -0
  53. package/esm/util/registry.js.map +1 -1
  54. package/package.json +2 -1
package/README.md CHANGED
@@ -74,6 +74,45 @@ npm install @tambo-ai/react
74
74
 
75
75
  Define which components your AI assistant can use to respond to users:
76
76
 
77
+ ```tsx
78
+ import { z } from "zod";
79
+
80
+ // Recommended: Using Zod for type-safe props definition
81
+ registerComponent({
82
+ component: DataChart,
83
+ name: "DataChart",
84
+ description: "Displays data as a chart",
85
+ propsSchema: z.object({
86
+ data: z.object({
87
+ labels: z.array(z.string()),
88
+ values: z.array(z.number()),
89
+ }),
90
+ type: z.enum(["bar", "line", "pie"]),
91
+ }),
92
+ });
93
+ ```
94
+
95
+ You can also use `z.describe()` for extra prompting to the ai:
96
+
97
+ ```tsx
98
+ import { z } from "zod";
99
+
100
+ schema = z.object({
101
+ data: z.object({
102
+ labels: z.array(z.string()).describe("Use single words or short phrases."),
103
+ values: z.array(z.number()).describe("Use whole numbers."),
104
+ }),
105
+ type: z
106
+ .enum(["bar", "line", "pie"])
107
+ .describe(
108
+ "Use a chart type that is appropriate for the data. Only use pie charts when less than 5 values.",
109
+ ),
110
+ });
111
+ ```
112
+
113
+ Alternative: Using JSON object (like JSON Schema)
114
+ Note: Use either propsSchema OR propsDefinition, not both
115
+
77
116
  ```tsx
78
117
  registerComponent({
79
118
  component: DataChart,
@@ -110,50 +149,3 @@ registerComponent({
110
149
  associatedTools: [dataTool],
111
150
  });
112
151
  ```
113
-
114
- ### 3. Thread Management
115
-
116
- Let your AI agent maintain conversation context automatically:
117
-
118
- ```tsx
119
- // Send a message in a specific thread
120
- sendThreadMessage("Show me sales data", {
121
- contextKey: userId,
122
- streamResponse: true,
123
- });
124
-
125
- // Switch between threads
126
- switchCurrentThread(threadId);
127
- ```
128
-
129
- ## API Reference
130
-
131
- ### Main Hooks
132
-
133
- - `useTambo`: All-in-one hook for most functionality
134
- - `useTamboRegistry`: Component registration
135
- - `useTamboThread`: Thread management
136
- - `useTamboSuggestions`: AI-powered message suggestions
137
-
138
- ## Docs
139
-
140
- For complete documentation, check out the [docs](https://tambo.co/docs).
141
-
142
- ## License
143
-
144
- MIT License - see the [LICENSE](https://github.com/tambo-ai/tambo/blob/main/LICENSE) file for details.
145
-
146
- ## Join the Community
147
-
148
- We're building tools for the future of user interfaces. Your contributions matter.
149
-
150
- **[Star this repo](https://github.com/tambo-ai/tambo)** to support our work.
151
-
152
- **[Join our Discord](https://discord.gg/dJNvPEHth6)** to connect with other developers.
153
-
154
- ---
155
-
156
- <p align="center">
157
- <i>Built by developers, for developers.</i><br>
158
- <i>Because we believe the future of UI is generative and hyper-personalized.</i>
159
- </p>
@@ -0,0 +1,8 @@
1
+ export * from "./react-query-hooks";
2
+ export { useTamboComponentState } from "./use-component-state";
3
+ export { useTamboCurrentMessage, useTamboMessageContext, } from "./use-current-message";
4
+ export { useTamboStreamingProps } from "./use-streaming-props";
5
+ export * from "./use-suggestions";
6
+ export { useTamboThreads } from "./use-tambo-threads";
7
+ export { useTamboThreadInput } from "./use-thread-input";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.useTamboThreadInput = exports.useTamboThreads = exports.useTamboStreamingProps = exports.useTamboMessageContext = exports.useTamboCurrentMessage = exports.useTamboComponentState = void 0;
18
+ // Export all hooks from this directory
19
+ __exportStar(require("./react-query-hooks"), exports);
20
+ var use_component_state_1 = require("./use-component-state");
21
+ Object.defineProperty(exports, "useTamboComponentState", { enumerable: true, get: function () { return use_component_state_1.useTamboComponentState; } });
22
+ var use_current_message_1 = require("./use-current-message");
23
+ Object.defineProperty(exports, "useTamboCurrentMessage", { enumerable: true, get: function () { return use_current_message_1.useTamboCurrentMessage; } });
24
+ Object.defineProperty(exports, "useTamboMessageContext", { enumerable: true, get: function () { return use_current_message_1.useTamboMessageContext; } });
25
+ var use_streaming_props_1 = require("./use-streaming-props");
26
+ Object.defineProperty(exports, "useTamboStreamingProps", { enumerable: true, get: function () { return use_streaming_props_1.useTamboStreamingProps; } });
27
+ __exportStar(require("./use-suggestions"), exports);
28
+ var use_tambo_threads_1 = require("./use-tambo-threads");
29
+ Object.defineProperty(exports, "useTamboThreads", { enumerable: true, get: function () { return use_tambo_threads_1.useTamboThreads; } });
30
+ var use_thread_input_1 = require("./use-thread-input");
31
+ Object.defineProperty(exports, "useTamboThreadInput", { enumerable: true, get: function () { return use_thread_input_1.useTamboThreadInput; } });
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,sDAAoC;AACpC,6DAA+D;AAAtD,6HAAA,sBAAsB,OAAA;AAC/B,6DAG+B;AAF7B,6HAAA,sBAAsB,OAAA;AACtB,6HAAA,sBAAsB,OAAA;AAExB,6DAA+D;AAAtD,6HAAA,sBAAsB,OAAA;AAC/B,oDAAkC;AAClC,yDAAsD;AAA7C,oHAAA,eAAe,OAAA;AACxB,uDAAyD;AAAhD,uHAAA,mBAAmB,OAAA","sourcesContent":["// Export all hooks from this directory\nexport * from \"./react-query-hooks\";\nexport { useTamboComponentState } from \"./use-component-state\";\nexport {\n useTamboCurrentMessage,\n useTamboMessageContext,\n} from \"./use-current-message\";\nexport { useTamboStreamingProps } from \"./use-streaming-props\";\nexport * from \"./use-suggestions\";\nexport { useTamboThreads } from \"./use-tambo-threads\";\nexport { useTamboThreadInput } from \"./use-thread-input\";\n"]}
@@ -1,9 +1,44 @@
1
- type StateUpdateResult<T> = [currentState: T, setState: (newState: T) => void];
1
+ interface ComponentStateMeta {
2
+ isPending: boolean;
3
+ }
4
+ type StateUpdateResult<T> = [
5
+ currentState: T,
6
+ setState: (newState: T) => void,
7
+ meta: ComponentStateMeta
8
+ ];
2
9
  /**
3
- * Behaves similarly to useState, but the value is stored in the thread
4
- * message, and the state is keyed by the keyName
10
+ * A React hook that provides state management and passes user updates to Tambo.
11
+ * Benefits: Passes user changes to AI, and when threads are returned, state is preserved.
12
+ *
13
+ * @param keyName - The unique key to identify this state within the message's componentState object
14
+ * @param initialValue - Optional initial value for the state, used if no value exists in the message
15
+ * @param debounceTime - Optional debounce time in milliseconds (default: 300ms) to limit API calls
16
+ *
17
+ * @returns A tuple containing:
18
+ * - The current state value
19
+ * - A setter function to update the state (updates UI immediately, debounces server sync)
20
+ * - A metadata object with properties like isPending to track sync status
21
+ *
22
+ * @example
23
+ * // Basic usage
24
+ * const [count, setCount, { isPending }] = useTamboComponentState("counter", 0);
25
+ *
26
+ * // Usage with object state
27
+ * const [formState, setFormState] = useTamboComponentState("myForm", {
28
+ * name: "",
29
+ * email: "",
30
+ * message: ""
31
+ * });
32
+ *
33
+ * // Handling form input
34
+ * const handleChange = (e) => {
35
+ * setFormState({
36
+ * ...formState,
37
+ * [e.target.name]: e.target.value
38
+ * });
39
+ * };
5
40
  */
6
- export declare function useTamboComponentState<S = undefined>(keyName: string): StateUpdateResult<S | undefined>;
7
- export declare function useTamboComponentState<S>(keyName: string, initialValue?: S): StateUpdateResult<S>;
41
+ export declare function useTamboComponentState<S = undefined>(keyName: string, initialValue?: S, debounceTime?: number): StateUpdateResult<S | undefined>;
42
+ export declare function useTamboComponentState<S>(keyName: string, initialValue: S, debounceTime?: number): StateUpdateResult<S>;
8
43
  export {};
9
44
  //# sourceMappingURL=use-component-state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-component-state.d.ts","sourceRoot":"","sources":["../../src/hooks/use-component-state.tsx"],"names":[],"mappings":"AAOA,KAAK,iBAAiB,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC;AAE/E;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,SAAS,EAClD,OAAO,EAAE,MAAM,GACd,iBAAiB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AACpC,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,CAAC,GACf,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,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"}
@@ -2,42 +2,136 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useTamboComponentState = useTamboComponentState;
4
4
  const react_1 = require("react");
5
+ const use_debounce_1 = require("use-debounce");
5
6
  const providers_1 = require("../providers");
6
7
  const use_current_message_1 = require("./use-current-message");
7
- function useTamboComponentState(keyName, initialValue) {
8
+ function useTamboComponentState(keyName, initialValue, debounceTime = 300) {
8
9
  const { threadId, messageId } = (0, use_current_message_1.useTamboMessageContext)();
9
10
  const { updateThreadMessage } = (0, providers_1.useTamboThread)();
10
11
  const client = (0, providers_1.useTamboClient)();
11
12
  const message = (0, use_current_message_1.useTamboCurrentMessage)();
13
+ // Initial value management
12
14
  const [cachedInitialValue] = (0, react_1.useState)(() => initialValue);
13
- const value = (0, react_1.useMemo)(() => {
14
- if (!message?.componentState)
15
- return cachedInitialValue;
16
- return keyName in message.componentState
17
- ? message.componentState[keyName]
18
- : cachedInitialValue;
19
- }, [cachedInitialValue, keyName, message?.componentState]);
15
+ // UI state management
16
+ const [localState, setLocalState] = (0, react_1.useState)(cachedInitialValue);
17
+ // Synchronization state
18
+ const [isPending, setIsPending] = (0, react_1.useState)(false);
19
+ // Track the last user-initiated value instead of a simple boolean flag
20
+ const [lastUserValue, setLastUserValue] = (0, react_1.useState)(null);
21
+ const [haveInitialized, setHaveInitialized] = (0, react_1.useState)(false);
22
+ // Determine if we need to initialize state
23
+ const shouldInitialize = !haveInitialized &&
24
+ message &&
25
+ cachedInitialValue !== undefined &&
26
+ (!message.componentState || !(keyName in message.componentState));
27
+ // Helper function to check if two values are deeply equal
28
+ const isEqual = (a, b) => {
29
+ if (a === b)
30
+ return true;
31
+ // Handle primitive types
32
+ if (typeof a !== "object" ||
33
+ typeof b !== "object" ||
34
+ a === null ||
35
+ b === null)
36
+ return false;
37
+ // For objects and arrays, do a shallow comparison for simplicity
38
+ // This could be enhanced with a proper deep equality check if needed
39
+ if (Array.isArray(a) && Array.isArray(b)) {
40
+ if (a.length !== b.length)
41
+ return false;
42
+ return a.every((val, idx) => val === b[idx]);
43
+ }
44
+ const keysA = Object.keys(a);
45
+ const keysB = Object.keys(b);
46
+ if (keysA.length !== keysB.length)
47
+ return false;
48
+ return keysA.every((key) => a[key] === b[key]);
49
+ };
50
+ // Sync local state with message state on initial load and when message changes
51
+ (0, react_1.useEffect)(() => {
52
+ if (message?.componentState && keyName in message.componentState) {
53
+ const messageState = message.componentState[keyName];
54
+ // If this is a user-initiated state that matches what we're getting from server,
55
+ // we can clear the lastUserValue flag since it's been synchronized
56
+ if (lastUserValue !== null && isEqual(messageState, lastUserValue)) {
57
+ setLastUserValue(null);
58
+ }
59
+ // Update local state with server state unless user has specifically changed this value
60
+ // This allows streaming updates to continue while protecting user edits
61
+ if (lastUserValue === null || !isEqual(localState, lastUserValue)) {
62
+ setLocalState(messageState);
63
+ }
64
+ }
65
+ // Otherwise fall back to initial value if we have one
66
+ else if (cachedInitialValue !== undefined && !localState) {
67
+ setLocalState(cachedInitialValue);
68
+ }
69
+ }, [
70
+ keyName,
71
+ message?.componentState,
72
+ cachedInitialValue,
73
+ lastUserValue,
74
+ localState,
75
+ ]);
76
+ // Create debounced save function for efficient server synchronization
77
+ const debouncedSave = (0, use_debounce_1.useDebouncedCallback)(async (newValue) => {
78
+ if (!message) {
79
+ console.warn(`Cannot update missing message ${messageId} for state key "${keyName}"`);
80
+ setLastUserValue(null);
81
+ return;
82
+ }
83
+ setIsPending(true);
84
+ try {
85
+ const messageUpdate = {
86
+ ...message,
87
+ componentState: {
88
+ ...message.componentState,
89
+ [keyName]: newValue,
90
+ },
91
+ };
92
+ const componentStateUpdate = {
93
+ state: { [keyName]: newValue },
94
+ };
95
+ await Promise.all([
96
+ updateThreadMessage(messageId, messageUpdate, false),
97
+ client.beta.threads.messages.updateComponentState(threadId, messageId, componentStateUpdate),
98
+ ]);
99
+ // Only clear the lastUserValue when we've successfully synced this exact value
100
+ if (isEqual(newValue, lastUserValue)) {
101
+ setLastUserValue(null);
102
+ }
103
+ }
104
+ catch (err) {
105
+ console.error(`Failed to save component state for key "${keyName}":`, err);
106
+ }
107
+ finally {
108
+ setIsPending(false);
109
+ }
110
+ }, debounceTime);
111
+ // Initialize state on first render if needed
20
112
  const initializeState = (0, react_1.useCallback)(async () => {
21
113
  if (!message) {
22
- console.warn(`Cannot initialize state for missing message ${messageId}`);
114
+ console.warn(`Cannot initialize state for missing message ${messageId} with key "${keyName}"`);
23
115
  return;
24
116
  }
25
117
  try {
118
+ const messageUpdate = {
119
+ ...message,
120
+ componentState: {
121
+ ...message.componentState,
122
+ [keyName]: cachedInitialValue,
123
+ },
124
+ };
125
+ const componentStateUpdate = {
126
+ state: { [keyName]: cachedInitialValue },
127
+ };
26
128
  await Promise.all([
27
- updateThreadMessage(messageId, {
28
- ...message,
29
- componentState: {
30
- ...message.componentState,
31
- [keyName]: cachedInitialValue,
32
- },
33
- }, false),
34
- client.beta.threads.messages.updateComponentState(threadId, messageId, {
35
- state: { [keyName]: cachedInitialValue },
36
- }),
129
+ updateThreadMessage(messageId, messageUpdate, false),
130
+ client.beta.threads.messages.updateComponentState(threadId, messageId, componentStateUpdate),
37
131
  ]);
38
132
  }
39
133
  catch (err) {
40
- console.warn("Failed to initialize component state:", err);
134
+ console.warn(`Failed to initialize component state for key "${keyName}":`, err);
41
135
  }
42
136
  }, [
43
137
  cachedInitialValue,
@@ -48,39 +142,36 @@ function useTamboComponentState(keyName, initialValue) {
48
142
  threadId,
49
143
  updateThreadMessage,
50
144
  ]);
51
- const [haveInitialized, setHaveInitialized] = (0, react_1.useState)(false);
52
- const shouldInitialize = !haveInitialized &&
53
- message &&
54
- cachedInitialValue !== undefined &&
55
- (!message.componentState || !(keyName in message.componentState));
56
- // send initial state
145
+ // Send initial state when component mounts
57
146
  (0, react_1.useEffect)(() => {
58
147
  if (shouldInitialize) {
59
148
  initializeState();
60
149
  setHaveInitialized(true);
61
150
  }
62
151
  }, [initializeState, shouldInitialize]);
63
- const setValue = (0, react_1.useCallback)(async (newValue) => {
64
- if (!message) {
65
- console.warn(`Cannot update missing message ${messageId}`);
66
- return;
152
+ // setValue function for updating state
153
+ // Updates local state immediately and schedules debounced server sync
154
+ const setValue = (0, react_1.useCallback)((newValue) => {
155
+ // Track this as a user-initiated update
156
+ setLastUserValue(newValue);
157
+ setLocalState(newValue);
158
+ // Only trigger server updates if we have a message
159
+ if (message) {
160
+ debouncedSave(newValue);
67
161
  }
68
- await updateThreadMessage(messageId, {
69
- ...message,
70
- componentState: {
71
- ...message.componentState,
72
- [keyName]: newValue,
73
- },
74
- }, false);
75
- await client.beta.threads.messages.updateComponentState(threadId, messageId, { state: { [keyName]: newValue } });
76
- }, [
77
- client.beta.threads.messages,
78
- keyName,
79
- message,
80
- messageId,
81
- threadId,
82
- updateThreadMessage,
83
- ]);
84
- return [value, setValue];
162
+ else {
163
+ console.warn(`Cannot update server for missing message ${messageId} with key "${keyName}"`);
164
+ setLastUserValue(null);
165
+ }
166
+ }, [debouncedSave, message, messageId, keyName]);
167
+ // Ensure pending changes are flushed on unmount
168
+ (0, react_1.useEffect)(() => {
169
+ return () => {
170
+ debouncedSave.flush();
171
+ setLastUserValue(null);
172
+ };
173
+ }, [debouncedSave]);
174
+ // Return the local state for immediate UI rendering
175
+ return [localState, setValue, { isPending }];
85
176
  }
86
177
  //# sourceMappingURL=use-component-state.js.map
@@ -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, useMemo, useState } from \"react\";\nimport { useTamboClient, useTamboThread } from \"../providers\";\nimport {\n useTamboCurrentMessage,\n useTamboMessageContext,\n} from \"./use-current-message\";\n\ntype StateUpdateResult<T> = [currentState: T, setState: (newState: T) => void];\n\n/**\n * Behaves similarly to useState, but the value is stored in the thread\n * message, and the state is keyed by the keyName\n */\nexport function useTamboComponentState<S = undefined>(\n keyName: string,\n): StateUpdateResult<S | undefined>;\nexport function useTamboComponentState<S>(\n keyName: string,\n initialValue?: S,\n): StateUpdateResult<S>;\nexport function useTamboComponentState<S>(\n keyName: string,\n initialValue?: S,\n): StateUpdateResult<S> {\n const { threadId, messageId } = useTamboMessageContext();\n const { updateThreadMessage } = useTamboThread();\n const client = useTamboClient();\n\n const message = useTamboCurrentMessage();\n const [cachedInitialValue] = useState(() => initialValue);\n\n const value = useMemo(() => {\n if (!message?.componentState) return cachedInitialValue;\n return keyName in message.componentState\n ? (message.componentState[keyName] as S)\n : cachedInitialValue;\n }, [cachedInitialValue, keyName, message?.componentState]);\n\n const initializeState = useCallback(async () => {\n if (!message) {\n console.warn(`Cannot initialize state for missing message ${messageId}`);\n return;\n }\n try {\n await Promise.all([\n updateThreadMessage(\n messageId,\n {\n ...message,\n componentState: {\n ...message.componentState,\n [keyName]: cachedInitialValue,\n },\n },\n false,\n ),\n client.beta.threads.messages.updateComponentState(threadId, messageId, {\n state: { [keyName]: cachedInitialValue },\n }),\n ]);\n } catch (err) {\n console.warn(\"Failed to initialize component state:\", err);\n }\n }, [\n cachedInitialValue,\n client.beta.threads.messages,\n keyName,\n message,\n messageId,\n threadId,\n updateThreadMessage,\n ]);\n const [haveInitialized, setHaveInitialized] = useState(false);\n const shouldInitialize =\n !haveInitialized &&\n message &&\n cachedInitialValue !== undefined &&\n (!message.componentState || !(keyName in message.componentState));\n\n // send initial state\n useEffect(() => {\n if (shouldInitialize) {\n initializeState();\n setHaveInitialized(true);\n }\n }, [initializeState, shouldInitialize]);\n\n const setValue = useCallback(\n async (newValue: S) => {\n if (!message) {\n console.warn(`Cannot update missing message ${messageId}`);\n return;\n }\n await updateThreadMessage(\n messageId,\n {\n ...message,\n componentState: {\n ...message.componentState,\n [keyName]: newValue,\n },\n },\n false,\n );\n await client.beta.threads.messages.updateComponentState(\n threadId,\n messageId,\n { state: { [keyName]: newValue } },\n );\n },\n [\n client.beta.threads.messages,\n keyName,\n message,\n messageId,\n threadId,\n updateThreadMessage,\n ],\n );\n return [value as S, setValue];\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":["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\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 *\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 *\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 *\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 */\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>;\nexport function useTamboComponentState<S>(\n keyName: string,\n initialValue?: S,\n debounceTime = 300,\n): StateUpdateResult<S> {\n const { threadId, messageId } = useTamboMessageContext();\n const { updateThreadMessage } = useTamboThread();\n const client = useTamboClient();\n const message = useTamboCurrentMessage();\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 // Helper function to check if two values are deeply equal\n const isEqual = (a: any, b: any): boolean => {\n if (a === b) return true;\n\n // Handle primitive types\n if (\n typeof a !== \"object\" ||\n typeof b !== \"object\" ||\n a === null ||\n b === null\n )\n return false;\n\n // For objects and arrays, do a shallow comparison for simplicity\n // This could be enhanced with a proper deep equality check if needed\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n return a.every((val, idx) => val === b[idx]);\n }\n\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n return keysA.every((key) => a[key] === b[key]);\n };\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 // If this is a user-initiated state that matches what we're getting from server,\n // we can clear the lastUserValue flag since it's been synchronized\n if (lastUserValue !== null && isEqual(messageState, lastUserValue)) {\n setLastUserValue(null);\n }\n\n // Update local state with server state unless user has specifically changed this value\n // This allows streaming updates to continue while protecting user edits\n if (lastUserValue === null || !isEqual(localState, lastUserValue)) {\n setLocalState(messageState);\n }\n }\n // Otherwise fall back to initial value if we have one\n else if (cachedInitialValue !== undefined && !localState) {\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 debouncedSave = useDebouncedCallback(async (newValue: S) => {\n if (!message) {\n console.warn(\n `Cannot update missing message ${messageId} for state key \"${keyName}\"`,\n );\n setLastUserValue(null);\n return;\n }\n\n setIsPending(true);\n try {\n const messageUpdate = {\n ...message,\n componentState: {\n ...message.componentState,\n [keyName]: newValue,\n },\n };\n\n const componentStateUpdate = {\n state: { [keyName]: newValue },\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\n // Only clear the lastUserValue when we've successfully synced this exact value\n if (isEqual(newValue, lastUserValue)) {\n setLastUserValue(null);\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 debouncedSave(newValue);\n } else {\n console.warn(\n `Cannot update server for missing message ${messageId} with key \"${keyName}\"`,\n );\n setLastUserValue(null);\n }\n },\n [debouncedSave, message, messageId, keyName],\n );\n\n // Ensure pending changes are flushed on unmount\n useEffect(() => {\n return () => {\n debouncedSave.flush();\n setLastUserValue(null);\n };\n }, [debouncedSave]);\n\n // Return the local state for immediate UI rendering\n return [localState as S, setValue, { isPending }];\n}\n"]}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * A helper hook that automatically updates Tambo component state when specified props change.
3
+ *
4
+ * This hook streamlines the common pattern of updating component state when receiving new
5
+ * streamed values from Tambo, eliminating the need to write repetitive useEffect code.
6
+ *
7
+ * @param currentState - The current state object from useTamboComponentState
8
+ * @param setState - The setState function from useTamboComponentState
9
+ * @param streamingProps - An object mapping state keys to prop values that should update the state
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * // Instead of writing a complex useEffect:
14
+ * const [emailState, setEmailState] = useTamboComponentState("email", initialState);
15
+ *
16
+ * // Simply use:
17
+ * useTamboStreamingProps(emailState, setEmailState, {
18
+ * subject: aiGeneratedSubject,
19
+ * body: aiGeneratedBody,
20
+ * usersEmail: usersEmail
21
+ * });
22
+ * ```
23
+ */
24
+ export declare function useTamboStreamingProps<T extends Record<string, any>>(currentState: T | undefined, setState: (state: T) => void, streamingProps: Partial<T>): void;
25
+ //# sourceMappingURL=use-streaming-props.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-streaming-props.d.ts","sourceRoot":"","sources":["../../src/hooks/use-streaming-props.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;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,QAuB3B"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useTamboStreamingProps = useTamboStreamingProps;
4
+ const react_1 = require("react");
5
+ /**
6
+ * A helper hook that automatically updates Tambo component state when specified props change.
7
+ *
8
+ * This hook streamlines the common pattern of updating component state when receiving new
9
+ * streamed values from Tambo, eliminating the need to write repetitive useEffect code.
10
+ *
11
+ * @param currentState - The current state object from useTamboComponentState
12
+ * @param setState - The setState function from useTamboComponentState
13
+ * @param streamingProps - An object mapping state keys to prop values that should update the state
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * // Instead of writing a complex useEffect:
18
+ * const [emailState, setEmailState] = useTamboComponentState("email", initialState);
19
+ *
20
+ * // Simply use:
21
+ * useTamboStreamingProps(emailState, setEmailState, {
22
+ * subject: aiGeneratedSubject,
23
+ * body: aiGeneratedBody,
24
+ * usersEmail: usersEmail
25
+ * });
26
+ * ```
27
+ */
28
+ function useTamboStreamingProps(currentState, setState, streamingProps) {
29
+ (0, react_1.useEffect)(() => {
30
+ if (currentState) {
31
+ let shouldUpdate = false;
32
+ const updates = {};
33
+ Object.entries(streamingProps).forEach(([key, value]) => {
34
+ if (value !== undefined && value !== currentState[key]) {
35
+ shouldUpdate = true;
36
+ updates[key] = value;
37
+ }
38
+ });
39
+ if (shouldUpdate) {
40
+ setState({
41
+ ...currentState,
42
+ ...updates,
43
+ });
44
+ }
45
+ }
46
+ // eslint-disable-next-line react-hooks/exhaustive-deps
47
+ }, [currentState, setState, ...Object.values(streamingProps)]);
48
+ }
49
+ //# sourceMappingURL=use-streaming-props.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-streaming-props.js","sourceRoot":"","sources":["../../src/hooks/use-streaming-props.tsx"],"names":[],"mappings":";;AAyBA,wDA0BC;AAnDD,iCAAkC;AAElC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,SAAgB,sBAAsB,CACpC,YAA2B,EAC3B,QAA4B,EAC5B,cAA0B;IAE1B,IAAA,iBAAS,EAAC,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,uDAAuD;IACzD,CAAC,EAAE,CAAC,YAAY,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACjE,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 *\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 *\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 // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentState, setState, ...Object.values(streamingProps)]);\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /** 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. */
2
2
  export { useTamboComponentState } from "./hooks/use-component-state";
3
3
  export { TamboMessageProvider, useTamboCurrentMessage, useTamboMessageContext, } from "./hooks/use-current-message";
4
+ export { useTamboStreamingProps } from "./hooks/use-streaming-props";
4
5
  export * from "./hooks/use-suggestions";
5
6
  export { useTamboThreadInput } from "./hooks/use-thread-input";
6
7
  export * from "./providers";
@@ -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,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D,cAAc,aAAa,CAAC;AAG5B,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,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,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,cAAc,aAAa,CAAC;AAG5B,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,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,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/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.GenerationStage = exports.useTamboThreads = exports.useTamboThreadInput = exports.useTamboMessageContext = exports.useTamboCurrentMessage = exports.TamboMessageProvider = exports.useTamboComponentState = void 0;
17
+ exports.GenerationStage = exports.useTamboThreads = exports.useTamboThreadInput = exports.useTamboStreamingProps = exports.useTamboMessageContext = exports.useTamboCurrentMessage = exports.TamboMessageProvider = exports.useTamboComponentState = void 0;
18
18
  /** 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. */
19
19
  var use_component_state_1 = require("./hooks/use-component-state");
20
20
  Object.defineProperty(exports, "useTamboComponentState", { enumerable: true, get: function () { return use_component_state_1.useTamboComponentState; } });
@@ -22,6 +22,8 @@ var use_current_message_1 = require("./hooks/use-current-message");
22
22
  Object.defineProperty(exports, "TamboMessageProvider", { enumerable: true, get: function () { return use_current_message_1.TamboMessageProvider; } });
23
23
  Object.defineProperty(exports, "useTamboCurrentMessage", { enumerable: true, get: function () { return use_current_message_1.useTamboCurrentMessage; } });
24
24
  Object.defineProperty(exports, "useTamboMessageContext", { enumerable: true, get: function () { return use_current_message_1.useTamboMessageContext; } });
25
+ var use_streaming_props_1 = require("./hooks/use-streaming-props");
26
+ Object.defineProperty(exports, "useTamboStreamingProps", { enumerable: true, get: function () { return use_streaming_props_1.useTamboStreamingProps; } });
25
27
  __exportStar(require("./hooks/use-suggestions"), exports);
26
28
  var use_thread_input_1 = require("./hooks/use-thread-input");
27
29
  Object.defineProperty(exports, "useTamboThreadInput", { enumerable: true, get: function () { return use_thread_input_1.useTamboThreadInput; } });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,wKAAwK;AACxK,mEAAqE;AAA5D,6HAAA,sBAAsB,OAAA;AAC/B,mEAIqC;AAHnC,2HAAA,oBAAoB,OAAA;AACpB,6HAAA,sBAAsB,OAAA;AACtB,6HAAA,sBAAsB,OAAA;AAExB,0DAAwC;AACxC,6DAA+D;AAAtD,uHAAA,mBAAmB,OAAA;AAE5B,gCAAgC;AAChC,8CAA4B;AAc5B,+DAA4D;AAAnD,oHAAA,eAAe,OAAA;AAQxB,mFAG6C;AAF3C,8HAAA,eAAe,OAAA","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 * from \"./hooks/use-suggestions\";\nexport { useTamboThreadInput } from \"./hooks/use-thread-input\";\n\n// Re-export provider components\nexport * 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 { useTamboThreads } 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,mEAAqE;AAA5D,6HAAA,sBAAsB,OAAA;AAC/B,mEAIqC;AAHnC,2HAAA,oBAAoB,OAAA;AACpB,6HAAA,sBAAsB,OAAA;AACtB,6HAAA,sBAAsB,OAAA;AAExB,mEAAqE;AAA5D,6HAAA,sBAAsB,OAAA;AAC/B,0DAAwC;AACxC,6DAA+D;AAAtD,uHAAA,mBAAmB,OAAA;AAE5B,gCAAgC;AAChC,8CAA4B;AAc5B,+DAA4D;AAAnD,oHAAA,eAAe,OAAA;AAQxB,mFAG6C;AAF3C,8HAAA,eAAe,OAAA","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 * 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 { useTamboThreads } 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"]}
@@ -57,7 +57,13 @@ export interface TamboComponent {
57
57
  * ```
58
58
  */
59
59
  component: ComponentType<any>;
60
- /** The props definition of the component */
60
+ /** A zod schema for the component props. (Recommended)
61
+ * Either this or propsDefinition must be provided, but not both.
62
+ */
63
+ propsSchema?: z.ZodTypeAny;
64
+ /** The props definition of the component as a JSON object.
65
+ * Either this or propsSchema must be provided, but not both.
66
+ */
61
67
  propsDefinition?: any;
62
68
  /** The loading component to render while the component is loading */
63
69
  loadingComponent?: ComponentType<any>;
@@ -1 +1 @@
1
- {"version":3,"file":"component-metadata.d.ts","sourceRoot":"","sources":["../../src/model/component-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,0BAA0B,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,KAAK,eAAe,MAAM,oBAAoB,CAAC;AACtD,+FAA+F;AAC/F,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,cAAc,GAAG;IACnD,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;CAC7C,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,4BACf,SAAQ,OAAO,CAAC,4BAA4B;IAC5C,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,mBAAmB,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACtD,UAAU,EAAE,4BAA4B,CAAC;CAC1C;AAED,MAAM,WAAW,mBAAoB,SAAQ,OAAO,CAAC,kBAAkB;IACrE,SAAS,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAC9B,gBAAgB,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;CACvC;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAEpE,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE1D,MAAM,WAAW,SAAS,CACxB,IAAI,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,EACxD,OAAO,SAAS,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU;IAE3C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnD,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAC7D;;GAEG;AAEH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAC9B,4CAA4C;IAC5C,eAAe,CAAC,EAAE,GAAG,CAAC;IACtB,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,uDAAuD;IACvD,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;CAC/B"}
1
+ {"version":3,"file":"component-metadata.d.ts","sourceRoot":"","sources":["../../src/model/component-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,0BAA0B,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,KAAK,eAAe,MAAM,oBAAoB,CAAC;AACtD,+FAA+F;AAC/F,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,cAAc,GAAG;IACnD,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;CAC7C,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,4BACf,SAAQ,OAAO,CAAC,4BAA4B;IAC5C,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,mBAAmB,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACtD,UAAU,EAAE,4BAA4B,CAAC;CAC1C;AAED,MAAM,WAAW,mBAAoB,SAAQ,OAAO,CAAC,kBAAkB;IACrE,SAAS,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAC9B,gBAAgB,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;CACvC;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAEpE,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE1D,MAAM,WAAW,SAAS,CACxB,IAAI,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,EACxD,OAAO,SAAS,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU;IAE3C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnD,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAC7D;;GAEG;AAEH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAE9B;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC;IAC3B;;OAEG;IACH,eAAe,CAAC,EAAE,GAAG,CAAC;IACtB,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IACtC,uDAAuD;IACvD,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;CAC/B"}