@tambo-ai/react 0.72.0 → 0.73.1

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 (151) hide show
  1. package/dist/mcp/mcp-hooks.d.ts +4 -0
  2. package/dist/mcp/mcp-hooks.d.ts.map +1 -1
  3. package/dist/mcp/mcp-hooks.js +4 -0
  4. package/dist/mcp/mcp-hooks.js.map +1 -1
  5. package/dist/providers/tambo-provider.d.ts +3 -0
  6. package/dist/providers/tambo-provider.d.ts.map +1 -1
  7. package/dist/providers/tambo-provider.js +3 -0
  8. package/dist/providers/tambo-provider.js.map +1 -1
  9. package/dist/util/resource-content-resolver.d.ts.map +1 -1
  10. package/dist/util/resource-content-resolver.js +2 -0
  11. package/dist/util/resource-content-resolver.js.map +1 -1
  12. package/dist/v1/hooks/use-tambo-v1-messages.test.js +22 -9
  13. package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
  14. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +1 -0
  15. package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
  16. package/dist/v1/hooks/use-tambo-v1-send-message.js +9 -2
  17. package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
  18. package/dist/v1/hooks/use-tambo-v1-send-message.test.js +22 -9
  19. package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
  20. package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts +91 -0
  21. package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -0
  22. package/dist/v1/hooks/use-tambo-v1-suggestions.js +152 -0
  23. package/dist/v1/hooks/use-tambo-v1-suggestions.js.map +1 -0
  24. package/dist/v1/hooks/use-tambo-v1-suggestions.test.d.ts +2 -0
  25. package/dist/v1/hooks/use-tambo-v1-suggestions.test.d.ts.map +1 -0
  26. package/dist/v1/hooks/use-tambo-v1-suggestions.test.js +511 -0
  27. package/dist/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -0
  28. package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts +6 -57
  29. package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -1
  30. package/dist/v1/hooks/use-tambo-v1-thread-input.js +7 -67
  31. package/dist/v1/hooks/use-tambo-v1-thread-input.js.map +1 -1
  32. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +201 -72
  33. package/dist/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
  34. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts +6 -4
  35. package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
  36. package/dist/v1/hooks/use-tambo-v1-thread-list.js +2 -2
  37. package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
  38. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +2 -2
  39. package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
  40. package/dist/v1/hooks/use-tambo-v1.test.js +16 -7
  41. package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
  42. package/dist/v1/index.d.ts +22 -13
  43. package/dist/v1/index.d.ts.map +1 -1
  44. package/dist/v1/index.js +31 -39
  45. package/dist/v1/index.js.map +1 -1
  46. package/dist/v1/providers/tambo-v1-provider.d.ts +27 -9
  47. package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
  48. package/dist/v1/providers/tambo-v1-provider.js +22 -11
  49. package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
  50. package/dist/v1/providers/tambo-v1-provider.test.js +27 -10
  51. package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
  52. package/dist/v1/providers/tambo-v1-stream-context.d.ts +19 -10
  53. package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
  54. package/dist/v1/providers/tambo-v1-stream-context.js +43 -53
  55. package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
  56. package/dist/v1/providers/tambo-v1-stream-context.test.js +94 -19
  57. package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
  58. package/dist/v1/providers/tambo-v1-stub-provider.d.ts +74 -0
  59. package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -0
  60. package/dist/v1/providers/tambo-v1-stub-provider.js +212 -0
  61. package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -0
  62. package/dist/v1/providers/tambo-v1-stub-provider.test.d.ts +2 -0
  63. package/dist/v1/providers/tambo-v1-stub-provider.test.d.ts.map +1 -0
  64. package/dist/v1/providers/tambo-v1-stub-provider.test.js +162 -0
  65. package/dist/v1/providers/tambo-v1-stub-provider.test.js.map +1 -0
  66. package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +105 -0
  67. package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -0
  68. package/dist/v1/providers/tambo-v1-thread-input-provider.js +191 -0
  69. package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -0
  70. package/dist/v1/utils/component-renderer.d.ts +15 -67
  71. package/dist/v1/utils/component-renderer.d.ts.map +1 -1
  72. package/dist/v1/utils/component-renderer.js +3 -149
  73. package/dist/v1/utils/component-renderer.js.map +1 -1
  74. package/dist/v1/utils/component-renderer.test.js +15 -350
  75. package/dist/v1/utils/component-renderer.test.js.map +1 -1
  76. package/esm/mcp/mcp-hooks.d.ts +4 -0
  77. package/esm/mcp/mcp-hooks.d.ts.map +1 -1
  78. package/esm/mcp/mcp-hooks.js +4 -0
  79. package/esm/mcp/mcp-hooks.js.map +1 -1
  80. package/esm/providers/tambo-provider.d.ts +3 -0
  81. package/esm/providers/tambo-provider.d.ts.map +1 -1
  82. package/esm/providers/tambo-provider.js +3 -0
  83. package/esm/providers/tambo-provider.js.map +1 -1
  84. package/esm/util/resource-content-resolver.d.ts.map +1 -1
  85. package/esm/util/resource-content-resolver.js +2 -0
  86. package/esm/util/resource-content-resolver.js.map +1 -1
  87. package/esm/v1/hooks/use-tambo-v1-messages.test.js +22 -9
  88. package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
  89. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +1 -0
  90. package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
  91. package/esm/v1/hooks/use-tambo-v1-send-message.js +9 -2
  92. package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
  93. package/esm/v1/hooks/use-tambo-v1-send-message.test.js +22 -9
  94. package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
  95. package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts +91 -0
  96. package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -0
  97. package/esm/v1/hooks/use-tambo-v1-suggestions.js +149 -0
  98. package/esm/v1/hooks/use-tambo-v1-suggestions.js.map +1 -0
  99. package/esm/v1/hooks/use-tambo-v1-suggestions.test.d.ts +2 -0
  100. package/esm/v1/hooks/use-tambo-v1-suggestions.test.d.ts.map +1 -0
  101. package/esm/v1/hooks/use-tambo-v1-suggestions.test.js +506 -0
  102. package/esm/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -0
  103. package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts +6 -57
  104. package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -1
  105. package/esm/v1/hooks/use-tambo-v1-thread-input.js +5 -66
  106. package/esm/v1/hooks/use-tambo-v1-thread-input.js.map +1 -1
  107. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +199 -73
  108. package/esm/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
  109. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts +6 -4
  110. package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
  111. package/esm/v1/hooks/use-tambo-v1-thread-list.js +2 -2
  112. package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
  113. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +2 -2
  114. package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
  115. package/esm/v1/hooks/use-tambo-v1.test.js +16 -7
  116. package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
  117. package/esm/v1/index.d.ts +22 -13
  118. package/esm/v1/index.d.ts.map +1 -1
  119. package/esm/v1/index.js +23 -18
  120. package/esm/v1/index.js.map +1 -1
  121. package/esm/v1/providers/tambo-v1-provider.d.ts +27 -9
  122. package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
  123. package/esm/v1/providers/tambo-v1-provider.js +20 -10
  124. package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
  125. package/esm/v1/providers/tambo-v1-provider.test.js +28 -11
  126. package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
  127. package/esm/v1/providers/tambo-v1-stream-context.d.ts +19 -10
  128. package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
  129. package/esm/v1/providers/tambo-v1-stream-context.js +44 -54
  130. package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
  131. package/esm/v1/providers/tambo-v1-stream-context.test.js +95 -20
  132. package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
  133. package/esm/v1/providers/tambo-v1-stub-provider.d.ts +74 -0
  134. package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -0
  135. package/esm/v1/providers/tambo-v1-stub-provider.js +176 -0
  136. package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -0
  137. package/esm/v1/providers/tambo-v1-stub-provider.test.d.ts +2 -0
  138. package/esm/v1/providers/tambo-v1-stub-provider.test.d.ts.map +1 -0
  139. package/esm/v1/providers/tambo-v1-stub-provider.test.js +157 -0
  140. package/esm/v1/providers/tambo-v1-stub-provider.test.js.map +1 -0
  141. package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +105 -0
  142. package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -0
  143. package/esm/v1/providers/tambo-v1-thread-input-provider.js +153 -0
  144. package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -0
  145. package/esm/v1/utils/component-renderer.d.ts +15 -67
  146. package/esm/v1/utils/component-renderer.d.ts.map +1 -1
  147. package/esm/v1/utils/component-renderer.js +4 -146
  148. package/esm/v1/utils/component-renderer.js.map +1 -1
  149. package/esm/v1/utils/component-renderer.test.js +16 -351
  150. package/esm/v1/utils/component-renderer.test.js.map +1 -1
  151. package/package.json +2 -2
@@ -17,16 +17,23 @@ import { TamboClientProvider, } from "../../providers/tambo-client-provider";
17
17
  import { TamboRegistryProvider, } from "../../providers/tambo-registry-provider";
18
18
  import { TamboContextHelpersProvider } from "../../providers/tambo-context-helpers-provider";
19
19
  import { TamboV1StreamProvider } from "./tambo-v1-stream-context";
20
+ import { TamboV1ThreadInputProvider } from "./tambo-v1-thread-input-provider";
20
21
  /**
21
- * Context for providing contextKey to child components.
22
+ * Context for v1 SDK configuration.
23
+ * @internal
22
24
  */
23
- const ContextKeyContext = createContext(undefined);
25
+ export const TamboV1ConfigContext = createContext(null);
24
26
  /**
25
- * Hook to access the contextKey from TamboV1Provider.
26
- * @returns The contextKey if provided, undefined otherwise
27
+ * Hook to access v1 SDK configuration.
28
+ * @returns Configuration values including userKey
29
+ * @throws {Error} If used outside TamboV1Provider
27
30
  */
28
- export function useContextKey() {
29
- return useContext(ContextKeyContext);
31
+ export function useTamboV1Config() {
32
+ const config = useContext(TamboV1ConfigContext);
33
+ if (!config) {
34
+ throw new Error("useTamboV1Config must be used within TamboV1Provider");
35
+ }
36
+ return config;
30
37
  }
31
38
  /**
32
39
  * Main provider for the Tambo v1 SDK.
@@ -51,7 +58,7 @@ export function useContextKey() {
51
58
  * @param props.listResources - Dynamic resource search function (must be paired with getResource)
52
59
  * @param props.getResource - Dynamic resource fetch function (must be paired with listResources)
53
60
  * @param props.contextHelpers - Configuration for context helper functions
54
- * @param props.contextKey - Optional context key for thread scoping/isolation
61
+ * @param props.userKey - User key for thread ownership (required if not using userToken)
55
62
  * @param props.queryClient - Optional custom React Query client
56
63
  * @param props.children - Child components
57
64
  * @returns Provider component tree
@@ -72,7 +79,7 @@ export function useContextKey() {
72
79
  * }
73
80
  * ```
74
81
  */
75
- export function TamboV1Provider({ apiKey, tamboUrl, environment, userToken, components, tools, mcpServers, onCallUnregisteredTool, resources, listResources, getResource, contextHelpers, contextKey, queryClient, children, }) {
82
+ export function TamboV1Provider({ apiKey, tamboUrl, environment, userToken, components, tools, mcpServers, onCallUnregisteredTool, resources, listResources, getResource, contextHelpers, userKey, queryClient, children, }) {
76
83
  // Create a stable default QueryClient if none provided.
77
84
  // Using useState to avoid SSR issues with module-level singletons.
78
85
  const [defaultQueryClient] = useState(() => new QueryClient({
@@ -84,11 +91,14 @@ export function TamboV1Provider({ apiKey, tamboUrl, environment, userToken, comp
84
91
  },
85
92
  }));
86
93
  const client = queryClient ?? defaultQueryClient;
94
+ // Config is static - created once and never changes
95
+ const config = { userKey };
87
96
  return (React.createElement(QueryClientProvider, { client: client },
88
97
  React.createElement(TamboClientProvider, { apiKey: apiKey, tamboUrl: tamboUrl, environment: environment, userToken: userToken },
89
98
  React.createElement(TamboRegistryProvider, { components: components, tools: tools, mcpServers: mcpServers, onCallUnregisteredTool: onCallUnregisteredTool, resources: resources, listResources: listResources, getResource: getResource },
90
99
  React.createElement(TamboContextHelpersProvider, { contextHelpers: contextHelpers },
91
- React.createElement(ContextKeyContext.Provider, { value: contextKey },
92
- React.createElement(TamboV1StreamProvider, null, children)))))));
100
+ React.createElement(TamboV1ConfigContext.Provider, { value: config },
101
+ React.createElement(TamboV1StreamProvider, null,
102
+ React.createElement(TamboV1ThreadInputProvider, null, children))))))));
93
103
  }
94
104
  //# sourceMappingURL=tambo-v1-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tambo-v1-provider.js","sourceRoot":"","sources":["../../../src/v1/providers/tambo-v1-provider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,EACZ,aAAa,EACb,UAAU,EAEV,QAAQ,GACT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EACL,mBAAmB,GAEpB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,qBAAqB,GAEtB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAO7F,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE;;GAEG;AACH,MAAM,iBAAiB,GAAG,aAAa,CAAqB,SAAS,CAAC,CAAC;AAEvE;;;GAGG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,UAAU,CAAC,iBAAiB,CAAC,CAAC;AACvC,CAAC;AA+ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,MAAM,EACN,QAAQ,EACR,WAAW,EACX,SAAS,EACT,UAAU,EACV,KAAK,EACL,UAAU,EACV,sBAAsB,EACtB,SAAS,EACT,aAAa,EACb,WAAW,EACX,cAAc,EACd,UAAU,EACV,WAAW,EACX,QAAQ,GACgC;IACxC,wDAAwD;IACxD,mEAAmE;IACnE,MAAM,CAAC,kBAAkB,CAAC,GAAG,QAAQ,CACnC,GAAG,EAAE,CACH,IAAI,WAAW,CAAC;QACd,cAAc,EAAE;YACd,OAAO,EAAE;gBACP,SAAS,EAAE,IAAI;gBACf,KAAK,EAAE,CAAC;aACT;SACF;KACF,CAAC,CACL,CAAC;IAEF,MAAM,MAAM,GAAG,WAAW,IAAI,kBAAkB,CAAC;IAEjD,OAAO,CACL,oBAAC,mBAAmB,IAAC,MAAM,EAAE,MAAM;QACjC,oBAAC,mBAAmB,IAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS;YAEpB,oBAAC,qBAAqB,IACpB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,UAAU,EACtB,sBAAsB,EAAE,sBAAsB,EAC9C,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,WAAW;gBAExB,oBAAC,2BAA2B,IAAC,cAAc,EAAE,cAAc;oBACzD,oBAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,UAAU;wBAC3C,oBAAC,qBAAqB,QAAE,QAAQ,CAAyB,CAC9B,CACD,CACR,CACJ,CACF,CACvB,CAAC;AACJ,CAAC","sourcesContent":["\"use client\";\n\n/**\n * TamboV1Provider - Main Provider for v1 API\n *\n * Composes the necessary providers for the v1 SDK:\n * - TamboClientProvider: API client and authentication\n * - TamboRegistryProvider: Component and tool registration\n * - TamboContextHelpersProvider: Context helper functions\n * - TamboV1StreamProvider: Streaming state management\n *\n * This provider should wrap your entire application or the portion\n * that needs access to Tambo v1 functionality.\n */\n\nimport React, {\n createContext,\n useContext,\n type PropsWithChildren,\n useState,\n} from \"react\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport {\n TamboClientProvider,\n type TamboClientProviderProps,\n} from \"../../providers/tambo-client-provider\";\nimport {\n TamboRegistryProvider,\n type TamboRegistryProviderProps,\n} from \"../../providers/tambo-registry-provider\";\nimport { TamboContextHelpersProvider } from \"../../providers/tambo-context-helpers-provider\";\nimport type { ContextHelpers } from \"../../context-helpers\";\nimport type { McpServerInfo } from \"../../model/mcp-server-info\";\nimport type {\n ListResourceItem,\n ResourceSource,\n} from \"../../model/resource-info\";\nimport { TamboV1StreamProvider } from \"./tambo-v1-stream-context\";\n\n/**\n * Context for providing contextKey to child components.\n */\nconst ContextKeyContext = createContext<string | undefined>(undefined);\n\n/**\n * Hook to access the contextKey from TamboV1Provider.\n * @returns The contextKey if provided, undefined otherwise\n */\nexport function useContextKey(): string | undefined {\n return useContext(ContextKeyContext);\n}\n\n/**\n * Props for TamboV1Provider\n */\nexport interface TamboV1ProviderProps extends Pick<\n TamboClientProviderProps,\n \"apiKey\" | \"tamboUrl\" | \"environment\" | \"userToken\"\n> {\n /**\n * Components to register with the registry.\n * These will be available for the AI to use in responses.\n */\n components?: TamboRegistryProviderProps[\"components\"];\n\n /**\n * Tools to register with the registry.\n * These will be executed client-side when requested by the AI.\n */\n tools?: TamboRegistryProviderProps[\"tools\"];\n\n /**\n * MCP servers to register with the registry.\n * These provide additional tools and resources from MCP-compatible servers.\n */\n mcpServers?: (McpServerInfo | string)[];\n\n /**\n * Callback function called when an unregistered tool is called.\n * If not provided, an error will be thrown for unknown tools.\n */\n onCallUnregisteredTool?: TamboRegistryProviderProps[\"onCallUnregisteredTool\"];\n\n /**\n * Static resources to register with the registry.\n * These will be available for the AI to access.\n */\n resources?: ListResourceItem[];\n\n /**\n * Dynamic resource search function.\n * Must be paired with getResource.\n * Called when searching for resources dynamically.\n */\n listResources?: ResourceSource[\"listResources\"];\n\n /**\n * Dynamic resource fetch function.\n * Must be paired with listResources.\n * Called when fetching a specific resource by URI.\n */\n getResource?: ResourceSource[\"getResource\"];\n\n /**\n * Configuration for context helpers.\n * A dictionary of functions that provide additional context to the AI.\n * Each key becomes the context name, and the function returns the value.\n */\n contextHelpers?: ContextHelpers;\n\n /**\n * Optional context key for thread scoping/isolation.\n * Threads created with the same contextKey are grouped together.\n * Useful for multi-tenant applications or separating conversation contexts.\n */\n contextKey?: string;\n\n /**\n * Optional custom QueryClient instance.\n * If not provided, a default client will be created.\n */\n queryClient?: QueryClient;\n\n /**\n * Children components\n */\n children: React.ReactNode;\n}\n\n/**\n * Main provider for the Tambo v1 SDK.\n *\n * Composes TamboClientProvider, TamboRegistryProvider, and TamboV1StreamProvider\n * to provide a complete context for building AI-powered applications.\n *\n * Threads are managed dynamically through useTamboV1() hook functions:\n * - startNewThread() - Begin a new conversation\n * - switchThread(threadId) - Switch to an existing thread\n * - initThread(threadId) - Initialize a thread for receiving events\n * @param props - Provider configuration\n * @param props.apiKey - Tambo API key for authentication\n * @param props.tamboUrl - Optional custom Tambo API URL\n * @param props.environment - Optional environment configuration\n * @param props.userToken - Optional OAuth token for user authentication\n * @param props.components - Components to register with the AI\n * @param props.tools - Tools to register for client-side execution\n * @param props.mcpServers - MCP servers to register for additional tools/resources\n * @param props.onCallUnregisteredTool - Callback for handling unknown tool calls\n * @param props.resources - Static resources to register with the AI\n * @param props.listResources - Dynamic resource search function (must be paired with getResource)\n * @param props.getResource - Dynamic resource fetch function (must be paired with listResources)\n * @param props.contextHelpers - Configuration for context helper functions\n * @param props.contextKey - Optional context key for thread scoping/isolation\n * @param props.queryClient - Optional custom React Query client\n * @param props.children - Child components\n * @returns Provider component tree\n * @example\n * ```tsx\n * import { TamboV1Provider } from '@tambo-ai/react/v1';\n *\n * function App() {\n * return (\n * <TamboV1Provider\n * apiKey={process.env.NEXT_PUBLIC_TAMBO_API_KEY!}\n * components={[WeatherCard, StockChart]}\n * tools={[searchTool, calculatorTool]}\n * >\n * <ChatInterface />\n * </TamboV1Provider>\n * );\n * }\n * ```\n */\nexport function TamboV1Provider({\n apiKey,\n tamboUrl,\n environment,\n userToken,\n components,\n tools,\n mcpServers,\n onCallUnregisteredTool,\n resources,\n listResources,\n getResource,\n contextHelpers,\n contextKey,\n queryClient,\n children,\n}: PropsWithChildren<TamboV1ProviderProps>) {\n // Create a stable default QueryClient if none provided.\n // Using useState to avoid SSR issues with module-level singletons.\n const [defaultQueryClient] = useState(\n () =>\n new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 1000,\n retry: 1,\n },\n },\n }),\n );\n\n const client = queryClient ?? defaultQueryClient;\n\n return (\n <QueryClientProvider client={client}>\n <TamboClientProvider\n apiKey={apiKey}\n tamboUrl={tamboUrl}\n environment={environment}\n userToken={userToken}\n >\n <TamboRegistryProvider\n components={components}\n tools={tools}\n mcpServers={mcpServers}\n onCallUnregisteredTool={onCallUnregisteredTool}\n resources={resources}\n listResources={listResources}\n getResource={getResource}\n >\n <TamboContextHelpersProvider contextHelpers={contextHelpers}>\n <ContextKeyContext.Provider value={contextKey}>\n <TamboV1StreamProvider>{children}</TamboV1StreamProvider>\n </ContextKeyContext.Provider>\n </TamboContextHelpersProvider>\n </TamboRegistryProvider>\n </TamboClientProvider>\n </QueryClientProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"tambo-v1-provider.js","sourceRoot":"","sources":["../../../src/v1/providers/tambo-v1-provider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,EACZ,aAAa,EACb,UAAU,EAEV,QAAQ,GACT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EACL,mBAAmB,GAEpB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,qBAAqB,GAEtB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAO7F,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAW9E;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,aAAa,CAAuB,IAAI,CAAC,CAAC;AAE9E;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAmFD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,MAAM,EACN,QAAQ,EACR,WAAW,EACX,SAAS,EACT,UAAU,EACV,KAAK,EACL,UAAU,EACV,sBAAsB,EACtB,SAAS,EACT,aAAa,EACb,WAAW,EACX,cAAc,EACd,OAAO,EACP,WAAW,EACX,QAAQ,GACgC;IACxC,wDAAwD;IACxD,mEAAmE;IACnE,MAAM,CAAC,kBAAkB,CAAC,GAAG,QAAQ,CACnC,GAAG,EAAE,CACH,IAAI,WAAW,CAAC;QACd,cAAc,EAAE;YACd,OAAO,EAAE;gBACP,SAAS,EAAE,IAAI;gBACf,KAAK,EAAE,CAAC;aACT;SACF;KACF,CAAC,CACL,CAAC;IAEF,MAAM,MAAM,GAAG,WAAW,IAAI,kBAAkB,CAAC;IAEjD,oDAAoD;IACpD,MAAM,MAAM,GAAkB,EAAE,OAAO,EAAE,CAAC;IAE1C,OAAO,CACL,oBAAC,mBAAmB,IAAC,MAAM,EAAE,MAAM;QACjC,oBAAC,mBAAmB,IAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS;YAEpB,oBAAC,qBAAqB,IACpB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,UAAU,EACtB,sBAAsB,EAAE,sBAAsB,EAC9C,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,WAAW;gBAExB,oBAAC,2BAA2B,IAAC,cAAc,EAAE,cAAc;oBACzD,oBAAC,oBAAoB,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM;wBAC1C,oBAAC,qBAAqB;4BACpB,oBAAC,0BAA0B,QACxB,QAAQ,CACkB,CACP,CACM,CACJ,CACR,CACJ,CACF,CACvB,CAAC;AACJ,CAAC","sourcesContent":["\"use client\";\n\n/**\n * TamboV1Provider - Main Provider for v1 API\n *\n * Composes the necessary providers for the v1 SDK:\n * - TamboClientProvider: API client and authentication\n * - TamboRegistryProvider: Component and tool registration\n * - TamboContextHelpersProvider: Context helper functions\n * - TamboV1StreamProvider: Streaming state management\n *\n * This provider should wrap your entire application or the portion\n * that needs access to Tambo v1 functionality.\n */\n\nimport React, {\n createContext,\n useContext,\n type PropsWithChildren,\n useState,\n} from \"react\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport {\n TamboClientProvider,\n type TamboClientProviderProps,\n} from \"../../providers/tambo-client-provider\";\nimport {\n TamboRegistryProvider,\n type TamboRegistryProviderProps,\n} from \"../../providers/tambo-registry-provider\";\nimport { TamboContextHelpersProvider } from \"../../providers/tambo-context-helpers-provider\";\nimport type { ContextHelpers } from \"../../context-helpers\";\nimport type { McpServerInfo } from \"../../model/mcp-server-info\";\nimport type {\n ListResourceItem,\n ResourceSource,\n} from \"../../model/resource-info\";\nimport { TamboV1StreamProvider } from \"./tambo-v1-stream-context\";\nimport { TamboV1ThreadInputProvider } from \"./tambo-v1-thread-input-provider\";\n\n/**\n * Configuration values for v1 SDK.\n * These are static values that don't change during the session.\n */\nexport interface TamboV1Config {\n /** User key for thread ownership and scoping */\n userKey?: string;\n}\n\n/**\n * Context for v1 SDK configuration.\n * @internal\n */\nexport const TamboV1ConfigContext = createContext<TamboV1Config | null>(null);\n\n/**\n * Hook to access v1 SDK configuration.\n * @returns Configuration values including userKey\n * @throws {Error} If used outside TamboV1Provider\n */\nexport function useTamboV1Config(): TamboV1Config {\n const config = useContext(TamboV1ConfigContext);\n if (!config) {\n throw new Error(\"useTamboV1Config must be used within TamboV1Provider\");\n }\n return config;\n}\n\n/**\n * Props for TamboV1Provider\n */\nexport interface TamboV1ProviderProps extends Pick<\n TamboClientProviderProps,\n \"apiKey\" | \"tamboUrl\" | \"environment\" | \"userToken\"\n> {\n /**\n * Components to register with the registry.\n * These will be available for the AI to use in responses.\n */\n components?: TamboRegistryProviderProps[\"components\"];\n\n /**\n * Tools to register with the registry.\n * These will be executed client-side when requested by the AI.\n */\n tools?: TamboRegistryProviderProps[\"tools\"];\n\n /**\n * MCP servers to register with the registry.\n * These provide additional tools and resources from MCP-compatible servers.\n */\n mcpServers?: (McpServerInfo | string)[];\n\n /**\n * Callback function called when an unregistered tool is called.\n * If not provided, an error will be thrown for unknown tools.\n */\n onCallUnregisteredTool?: TamboRegistryProviderProps[\"onCallUnregisteredTool\"];\n\n /**\n * Static resources to register with the registry.\n * These will be available for the AI to access.\n */\n resources?: ListResourceItem[];\n\n /**\n * Dynamic resource search function.\n * Must be paired with getResource.\n * Called when searching for resources dynamically.\n */\n listResources?: ResourceSource[\"listResources\"];\n\n /**\n * Dynamic resource fetch function.\n * Must be paired with listResources.\n * Called when fetching a specific resource by URI.\n */\n getResource?: ResourceSource[\"getResource\"];\n\n /**\n * Configuration for context helpers.\n * A dictionary of functions that provide additional context to the AI.\n * Each key becomes the context name, and the function returns the value.\n */\n contextHelpers?: ContextHelpers;\n\n /**\n * User key for thread ownership and scoping.\n *\n * **Required**: You must provide either `userKey` OR `userToken` (which contains a userKey).\n * All thread operations (create, list, fetch) only return threads owned by this userKey.\n *\n * - Use `userKey` for server-side or trusted environments where you control the user identity\n * - Use `userToken` (OAuth bearer token) for client-side apps where the token contains the userKey\n */\n userKey?: string;\n\n /**\n * Optional custom QueryClient instance.\n * If not provided, a default client will be created.\n */\n queryClient?: QueryClient;\n\n /**\n * Children components\n */\n children: React.ReactNode;\n}\n\n/**\n * Main provider for the Tambo v1 SDK.\n *\n * Composes TamboClientProvider, TamboRegistryProvider, and TamboV1StreamProvider\n * to provide a complete context for building AI-powered applications.\n *\n * Threads are managed dynamically through useTamboV1() hook functions:\n * - startNewThread() - Begin a new conversation\n * - switchThread(threadId) - Switch to an existing thread\n * - initThread(threadId) - Initialize a thread for receiving events\n * @param props - Provider configuration\n * @param props.apiKey - Tambo API key for authentication\n * @param props.tamboUrl - Optional custom Tambo API URL\n * @param props.environment - Optional environment configuration\n * @param props.userToken - Optional OAuth token for user authentication\n * @param props.components - Components to register with the AI\n * @param props.tools - Tools to register for client-side execution\n * @param props.mcpServers - MCP servers to register for additional tools/resources\n * @param props.onCallUnregisteredTool - Callback for handling unknown tool calls\n * @param props.resources - Static resources to register with the AI\n * @param props.listResources - Dynamic resource search function (must be paired with getResource)\n * @param props.getResource - Dynamic resource fetch function (must be paired with listResources)\n * @param props.contextHelpers - Configuration for context helper functions\n * @param props.userKey - User key for thread ownership (required if not using userToken)\n * @param props.queryClient - Optional custom React Query client\n * @param props.children - Child components\n * @returns Provider component tree\n * @example\n * ```tsx\n * import { TamboV1Provider } from '@tambo-ai/react/v1';\n *\n * function App() {\n * return (\n * <TamboV1Provider\n * apiKey={process.env.NEXT_PUBLIC_TAMBO_API_KEY!}\n * components={[WeatherCard, StockChart]}\n * tools={[searchTool, calculatorTool]}\n * >\n * <ChatInterface />\n * </TamboV1Provider>\n * );\n * }\n * ```\n */\nexport function TamboV1Provider({\n apiKey,\n tamboUrl,\n environment,\n userToken,\n components,\n tools,\n mcpServers,\n onCallUnregisteredTool,\n resources,\n listResources,\n getResource,\n contextHelpers,\n userKey,\n queryClient,\n children,\n}: PropsWithChildren<TamboV1ProviderProps>) {\n // Create a stable default QueryClient if none provided.\n // Using useState to avoid SSR issues with module-level singletons.\n const [defaultQueryClient] = useState(\n () =>\n new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 1000,\n retry: 1,\n },\n },\n }),\n );\n\n const client = queryClient ?? defaultQueryClient;\n\n // Config is static - created once and never changes\n const config: TamboV1Config = { userKey };\n\n return (\n <QueryClientProvider client={client}>\n <TamboClientProvider\n apiKey={apiKey}\n tamboUrl={tamboUrl}\n environment={environment}\n userToken={userToken}\n >\n <TamboRegistryProvider\n components={components}\n tools={tools}\n mcpServers={mcpServers}\n onCallUnregisteredTool={onCallUnregisteredTool}\n resources={resources}\n listResources={listResources}\n getResource={getResource}\n >\n <TamboContextHelpersProvider contextHelpers={contextHelpers}>\n <TamboV1ConfigContext.Provider value={config}>\n <TamboV1StreamProvider>\n <TamboV1ThreadInputProvider>\n {children}\n </TamboV1ThreadInputProvider>\n </TamboV1StreamProvider>\n </TamboV1ConfigContext.Provider>\n </TamboContextHelpersProvider>\n </TamboRegistryProvider>\n </TamboClientProvider>\n </QueryClientProvider>\n );\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import TamboAI from "@tambo-ai/typescript-sdk";
1
2
  import { QueryClient, useQueryClient } from "@tanstack/react-query";
2
3
  import { renderHook, act } from "@testing-library/react";
3
4
  import React from "react";
@@ -6,17 +7,33 @@ import { useTamboClient } from "../../providers/tambo-client-provider";
6
7
  import { useTamboRegistry } from "../../providers/tambo-registry-provider";
7
8
  import { useTamboContextHelpers } from "../../providers/tambo-context-helpers-provider";
8
9
  import { useStreamState, useThreadManagement } from "./tambo-v1-stream-context";
9
- import { TamboV1Provider, useContextKey } from "./tambo-v1-provider";
10
+ import { TamboV1Provider, useTamboV1Config } from "./tambo-v1-provider";
10
11
  // Mock the client provider to capture the apiKey
11
12
  jest.mock("../../providers/tambo-client-provider", () => ({
12
13
  useTamboClient: jest.fn(),
14
+ useTamboQueryClient: jest.fn(() => new QueryClient()),
13
15
  TamboClientProvider: ({ children }) => children,
14
16
  }));
17
+ // Mock useTamboV1SendMessage to avoid complex dependencies
18
+ jest.mock("../hooks/use-tambo-v1-send-message", () => ({
19
+ useTamboV1SendMessage: jest.fn(() => ({
20
+ mutateAsync: jest.fn(),
21
+ mutate: jest.fn(),
22
+ isPending: false,
23
+ isError: false,
24
+ error: null,
25
+ isSuccess: false,
26
+ reset: jest.fn(),
27
+ })),
28
+ }));
15
29
  describe("TamboV1Provider", () => {
16
- const mockClient = {
17
- apiKey: "test-api-key",
18
- threads: {},
30
+ const mockFetch = async (..._args) => {
31
+ throw new Error("fetch not implemented");
19
32
  };
33
+ const mockClient = new TamboAI({
34
+ apiKey: "test-api-key",
35
+ fetch: mockFetch,
36
+ });
20
37
  beforeEach(() => {
21
38
  jest.mocked(useTamboClient).mockReturnValue(mockClient);
22
39
  });
@@ -139,15 +156,15 @@ describe("TamboV1Provider", () => {
139
156
  expect(result.current.resourceSource?.listResources).toBe(listResources);
140
157
  expect(result.current.resourceSource?.getResource).toBe(getResource);
141
158
  });
142
- it("provides contextKey via useContextKey hook", () => {
143
- const wrapper = ({ children }) => (React.createElement(TamboV1Provider, { apiKey: "test-api-key", contextKey: "my-context-key" }, children));
144
- const { result } = renderHook(() => useContextKey(), { wrapper });
145
- expect(result.current).toBe("my-context-key");
159
+ it("provides userKey via useTamboV1Config", () => {
160
+ const wrapper = ({ children }) => (React.createElement(TamboV1Provider, { apiKey: "test-api-key", userKey: "my-user-key" }, children));
161
+ const { result } = renderHook(() => useTamboV1Config(), { wrapper });
162
+ expect(result.current.userKey).toBe("my-user-key");
146
163
  });
147
- it("returns undefined from useContextKey when no contextKey provided", () => {
164
+ it("returns undefined userKey from useTamboV1Config when no userKey provided", () => {
148
165
  const wrapper = ({ children }) => (React.createElement(TamboV1Provider, { apiKey: "test-api-key" }, children));
149
- const { result } = renderHook(() => useContextKey(), { wrapper });
150
- expect(result.current).toBeUndefined();
166
+ const { result } = renderHook(() => useTamboV1Config(), { wrapper });
167
+ expect(result.current.userKey).toBeUndefined();
151
168
  });
152
169
  it("provides context helpers via useTamboContextHelpers hook", async () => {
153
170
  const contextHelpers = {
@@ -1 +1 @@
1
- {"version":3,"file":"tambo-v1-provider.test.js","sourceRoot":"","sources":["../../../src/v1/providers/tambo-v1-provider.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { QueryClient, useQueryClient } from \"@tanstack/react-query\";\nimport { renderHook, act } from \"@testing-library/react\";\nimport React from \"react\";\nimport { z } from \"zod\";\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { useTamboRegistry } from \"../../providers/tambo-registry-provider\";\nimport { useTamboContextHelpers } from \"../../providers/tambo-context-helpers-provider\";\nimport { useStreamState, useThreadManagement } from \"./tambo-v1-stream-context\";\nimport { TamboV1Provider, useContextKey } from \"./tambo-v1-provider\";\n\n// Mock the client provider to capture the apiKey\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(),\n TamboClientProvider: ({ children }: { children: React.ReactNode }) =>\n children,\n}));\n\ndescribe(\"TamboV1Provider\", () => {\n const mockClient = {\n apiKey: \"test-api-key\",\n threads: {},\n } as unknown as TamboAI;\n\n beforeEach(() => {\n jest.mocked(useTamboClient).mockReturnValue(mockClient);\n });\n\n it(\"provides access to registry context\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.componentList).toBeDefined();\n expect(result.current.toolRegistry).toBeDefined();\n expect(typeof result.current.registerComponent).toBe(\"function\");\n expect(typeof result.current.registerTool).toBe(\"function\");\n });\n\n it(\"provides access to stream context\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(() => useStreamState(), { wrapper });\n\n expect(result.current.threadMap).toBeDefined();\n expect(result.current.currentThreadId).toBeNull();\n });\n\n it(\"manages threads via useThreadManagement\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(\n () => ({\n state: useStreamState(),\n management: useThreadManagement(),\n }),\n { wrapper },\n );\n\n // Initially no thread\n expect(result.current.state.currentThreadId).toBeNull();\n\n // Initialize and switch to a thread\n act(() => {\n result.current.management.initThread(\"thread_123\");\n result.current.management.switchThread(\"thread_123\");\n });\n\n expect(result.current.state.currentThreadId).toBe(\"thread_123\");\n expect(result.current.state.threadMap.thread_123).toBeDefined();\n });\n\n it(\"provides access to query client\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(() => useQueryClient(), { wrapper });\n\n expect(result.current).toBeInstanceOf(QueryClient);\n });\n\n it(\"uses custom query client when provided\", () => {\n const customClient = new QueryClient();\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" queryClient={customClient}>\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useQueryClient(), { wrapper });\n\n expect(result.current).toBe(customClient);\n });\n\n it(\"registers components when provided\", () => {\n const TestComponent = () => <div>Test</div>;\n const propsSchema = z.object({\n title: z.string().describe(\"The title\"),\n });\n const components = [\n {\n name: \"TestComponent\",\n description: \"A test component\",\n component: TestComponent,\n propsSchema,\n },\n ];\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" components={components}>\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.componentList.TestComponent).toBeDefined();\n expect(result.current.componentList.TestComponent.name).toBe(\n \"TestComponent\",\n );\n });\n\n it(\"registers tools when provided\", () => {\n const inputSchema = z.object({\n query: z.string().describe(\"Search query\"),\n });\n const outputSchema = z.string().describe(\"Result string\");\n const tools = [\n {\n name: \"testTool\",\n description: \"A test tool\",\n tool: async () => \"result\",\n inputSchema,\n outputSchema,\n },\n ];\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" tools={tools}>\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.toolRegistry.testTool).toBeDefined();\n expect(result.current.toolRegistry.testTool.name).toBe(\"testTool\");\n });\n\n it(\"registers MCP servers when provided\", () => {\n const mcpServers = [\n { url: \"https://mcp.example.com\", name: \"Example MCP\" },\n ];\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" mcpServers={mcpServers}>\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.mcpServerInfos).toHaveLength(1);\n expect(result.current.mcpServerInfos[0].url).toBe(\n \"https://mcp.example.com\",\n );\n });\n\n it(\"provides onCallUnregisteredTool to registry\", () => {\n const onCallUnregisteredTool = jest\n .fn()\n .mockResolvedValue(\"fallback result\");\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider\n apiKey=\"test-api-key\"\n onCallUnregisteredTool={onCallUnregisteredTool}\n >\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.onCallUnregisteredTool).toBe(onCallUnregisteredTool);\n });\n\n it(\"registers static resources when provided\", () => {\n const resources = [\n {\n uri: \"resource://test/example\",\n name: \"Test Resource\",\n description: \"A test resource\",\n mimeType: \"text/plain\",\n },\n ];\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" resources={resources}>\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.resources).toHaveLength(1);\n expect(result.current.resources[0].uri).toBe(\"resource://test/example\");\n expect(result.current.resources[0].name).toBe(\"Test Resource\");\n });\n\n it(\"registers resource source when listResources and getResource provided\", () => {\n const listResources = jest.fn().mockResolvedValue({ resources: [] });\n const getResource = jest.fn().mockResolvedValue({ contents: [] });\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider\n apiKey=\"test-api-key\"\n listResources={listResources}\n getResource={getResource}\n >\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.resourceSource).toBeDefined();\n expect(result.current.resourceSource?.listResources).toBe(listResources);\n expect(result.current.resourceSource?.getResource).toBe(getResource);\n });\n\n it(\"provides contextKey via useContextKey hook\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" contextKey=\"my-context-key\">\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useContextKey(), { wrapper });\n\n expect(result.current).toBe(\"my-context-key\");\n });\n\n it(\"returns undefined from useContextKey when no contextKey provided\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(() => useContextKey(), { wrapper });\n\n expect(result.current).toBeUndefined();\n });\n\n it(\"provides context helpers via useTamboContextHelpers hook\", async () => {\n const contextHelpers = {\n getUserName: () => \"Test User\",\n getCurrentTime: () => new Date().toISOString(),\n };\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" contextHelpers={contextHelpers}>\n {children}\n </TamboV1Provider>\n );\n\n const { result, rerender } = renderHook(() => useTamboContextHelpers(), {\n wrapper,\n });\n\n // Helpers are registered via useEffect, so we need to trigger a rerender\n await act(async () => {\n rerender();\n });\n\n const helpers = result.current.getContextHelpers();\n expect(helpers.getUserName).toBe(contextHelpers.getUserName);\n expect(helpers.getCurrentTime).toBe(contextHelpers.getCurrentTime);\n });\n\n it(\"returns empty contextHelpers when none provided\", async () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboContextHelpers(), { wrapper });\n\n const helpers = result.current.getContextHelpers();\n expect(Object.keys(helpers)).toHaveLength(0);\n });\n});\n"]}
1
+ {"version":3,"file":"tambo-v1-provider.test.js","sourceRoot":"","sources":["../../../src/v1/providers/tambo-v1-provider.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { QueryClient, useQueryClient } from \"@tanstack/react-query\";\nimport { renderHook, act } from \"@testing-library/react\";\nimport React from \"react\";\nimport { z } from \"zod\";\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { useTamboRegistry } from \"../../providers/tambo-registry-provider\";\nimport { useTamboContextHelpers } from \"../../providers/tambo-context-helpers-provider\";\nimport { useStreamState, useThreadManagement } from \"./tambo-v1-stream-context\";\nimport { TamboV1Provider, useTamboV1Config } from \"./tambo-v1-provider\";\n\n// Mock the client provider to capture the apiKey\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(),\n useTamboQueryClient: jest.fn(() => new QueryClient()),\n TamboClientProvider: ({ children }: { children: React.ReactNode }) =>\n children,\n}));\n\n// Mock useTamboV1SendMessage to avoid complex dependencies\njest.mock(\"../hooks/use-tambo-v1-send-message\", () => ({\n useTamboV1SendMessage: jest.fn(() => ({\n mutateAsync: jest.fn(),\n mutate: jest.fn(),\n isPending: false,\n isError: false,\n error: null,\n isSuccess: false,\n reset: jest.fn(),\n })),\n}));\n\ndescribe(\"TamboV1Provider\", () => {\n const mockFetch: typeof fetch = async (..._args) => {\n throw new Error(\"fetch not implemented\");\n };\n\n const mockClient = new TamboAI({\n apiKey: \"test-api-key\",\n fetch: mockFetch,\n });\n\n beforeEach(() => {\n jest.mocked(useTamboClient).mockReturnValue(mockClient);\n });\n\n it(\"provides access to registry context\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.componentList).toBeDefined();\n expect(result.current.toolRegistry).toBeDefined();\n expect(typeof result.current.registerComponent).toBe(\"function\");\n expect(typeof result.current.registerTool).toBe(\"function\");\n });\n\n it(\"provides access to stream context\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(() => useStreamState(), { wrapper });\n\n expect(result.current.threadMap).toBeDefined();\n expect(result.current.currentThreadId).toBeNull();\n });\n\n it(\"manages threads via useThreadManagement\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(\n () => ({\n state: useStreamState(),\n management: useThreadManagement(),\n }),\n { wrapper },\n );\n\n // Initially no thread\n expect(result.current.state.currentThreadId).toBeNull();\n\n // Initialize and switch to a thread\n act(() => {\n result.current.management.initThread(\"thread_123\");\n result.current.management.switchThread(\"thread_123\");\n });\n\n expect(result.current.state.currentThreadId).toBe(\"thread_123\");\n expect(result.current.state.threadMap.thread_123).toBeDefined();\n });\n\n it(\"provides access to query client\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(() => useQueryClient(), { wrapper });\n\n expect(result.current).toBeInstanceOf(QueryClient);\n });\n\n it(\"uses custom query client when provided\", () => {\n const customClient = new QueryClient();\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" queryClient={customClient}>\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useQueryClient(), { wrapper });\n\n expect(result.current).toBe(customClient);\n });\n\n it(\"registers components when provided\", () => {\n const TestComponent = () => <div>Test</div>;\n const propsSchema = z.object({\n title: z.string().describe(\"The title\"),\n });\n const components = [\n {\n name: \"TestComponent\",\n description: \"A test component\",\n component: TestComponent,\n propsSchema,\n },\n ];\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" components={components}>\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.componentList.TestComponent).toBeDefined();\n expect(result.current.componentList.TestComponent.name).toBe(\n \"TestComponent\",\n );\n });\n\n it(\"registers tools when provided\", () => {\n const inputSchema = z.object({\n query: z.string().describe(\"Search query\"),\n });\n const outputSchema = z.string().describe(\"Result string\");\n const tools = [\n {\n name: \"testTool\",\n description: \"A test tool\",\n tool: async () => \"result\",\n inputSchema,\n outputSchema,\n },\n ];\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" tools={tools}>\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.toolRegistry.testTool).toBeDefined();\n expect(result.current.toolRegistry.testTool.name).toBe(\"testTool\");\n });\n\n it(\"registers MCP servers when provided\", () => {\n const mcpServers = [\n { url: \"https://mcp.example.com\", name: \"Example MCP\" },\n ];\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" mcpServers={mcpServers}>\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.mcpServerInfos).toHaveLength(1);\n expect(result.current.mcpServerInfos[0].url).toBe(\n \"https://mcp.example.com\",\n );\n });\n\n it(\"provides onCallUnregisteredTool to registry\", () => {\n const onCallUnregisteredTool = jest\n .fn()\n .mockResolvedValue(\"fallback result\");\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider\n apiKey=\"test-api-key\"\n onCallUnregisteredTool={onCallUnregisteredTool}\n >\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.onCallUnregisteredTool).toBe(onCallUnregisteredTool);\n });\n\n it(\"registers static resources when provided\", () => {\n const resources = [\n {\n uri: \"resource://test/example\",\n name: \"Test Resource\",\n description: \"A test resource\",\n mimeType: \"text/plain\",\n },\n ];\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" resources={resources}>\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.resources).toHaveLength(1);\n expect(result.current.resources[0].uri).toBe(\"resource://test/example\");\n expect(result.current.resources[0].name).toBe(\"Test Resource\");\n });\n\n it(\"registers resource source when listResources and getResource provided\", () => {\n const listResources = jest.fn().mockResolvedValue({ resources: [] });\n const getResource = jest.fn().mockResolvedValue({ contents: [] });\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider\n apiKey=\"test-api-key\"\n listResources={listResources}\n getResource={getResource}\n >\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.resourceSource).toBeDefined();\n expect(result.current.resourceSource?.listResources).toBe(listResources);\n expect(result.current.resourceSource?.getResource).toBe(getResource);\n });\n\n it(\"provides userKey via useTamboV1Config\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" userKey=\"my-user-key\">\n {children}\n </TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboV1Config(), { wrapper });\n\n expect(result.current.userKey).toBe(\"my-user-key\");\n });\n\n it(\"returns undefined userKey from useTamboV1Config when no userKey provided\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboV1Config(), { wrapper });\n\n expect(result.current.userKey).toBeUndefined();\n });\n\n it(\"provides context helpers via useTamboContextHelpers hook\", async () => {\n const contextHelpers = {\n getUserName: () => \"Test User\",\n getCurrentTime: () => new Date().toISOString(),\n };\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\" contextHelpers={contextHelpers}>\n {children}\n </TamboV1Provider>\n );\n\n const { result, rerender } = renderHook(() => useTamboContextHelpers(), {\n wrapper,\n });\n\n // Helpers are registered via useEffect, so we need to trigger a rerender\n await act(async () => {\n rerender();\n });\n\n const helpers = result.current.getContextHelpers();\n expect(helpers.getUserName).toBe(contextHelpers.getUserName);\n expect(helpers.getCurrentTime).toBe(contextHelpers.getCurrentTime);\n });\n\n it(\"returns empty contextHelpers when none provided\", async () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboV1Provider apiKey=\"test-api-key\">{children}</TamboV1Provider>\n );\n\n const { result } = renderHook(() => useTamboContextHelpers(), { wrapper });\n\n const helpers = result.current.getContextHelpers();\n expect(Object.keys(helpers)).toHaveLength(0);\n });\n});\n"]}
@@ -5,7 +5,7 @@
5
5
  * Provides state and dispatch to child components via separate contexts
6
6
  * following the split-context pattern for optimal re-render performance.
7
7
  */
8
- import React, { type ReactNode, type Dispatch } from "react";
8
+ import React from "react";
9
9
  import { type StreamState, type StreamAction } from "../utils/event-accumulator";
10
10
  import type { TamboV1Thread } from "../types/thread";
11
11
  /**
@@ -36,27 +36,36 @@ export interface ThreadManagement {
36
36
  * Props for TamboV1StreamProvider
37
37
  */
38
38
  export interface TamboV1StreamProviderProps {
39
- children: ReactNode;
39
+ children: React.ReactNode;
40
40
  /**
41
- * Initial thread state (optional).
42
- * If not provided, an empty thread will be created.
41
+ * Optional override for stream state (primarily for tests).
42
+ * If provided, you must also provide `dispatch`.
43
43
  */
44
- initialThread?: Partial<TamboV1Thread>;
44
+ state?: StreamState;
45
45
  /**
46
- * Thread ID for the stream context.
47
- * Used to initialize the thread if initialThread is not provided.
46
+ * Optional override for stream dispatch (primarily for tests).
47
+ * If provided, you must also provide `state`.
48
48
  */
49
- threadId?: string;
49
+ dispatch?: React.Dispatch<StreamAction>;
50
+ /**
51
+ * Optional override for thread management functions (primarily for tests).
52
+ */
53
+ threadManagement?: ThreadManagement;
50
54
  }
51
55
  /**
52
56
  * Provider component for stream state management.
53
57
  *
54
58
  * Uses useReducer with streamReducer to accumulate AG-UI events into
55
59
  * thread state. Provides state, dispatch, and thread management via separate contexts.
60
+ *
61
+ * Thread management is done programmatically via the hooks:
62
+ * - startNewThread() - Start a new conversation
63
+ * - switchThread(threadId) - Switch to an existing thread
64
+ * - initThread(threadId) - Initialize a thread for receiving events
56
65
  * @returns JSX element wrapping children with stream contexts
57
66
  * @example
58
67
  * ```tsx
59
- * <TamboV1StreamProvider threadId="thread_123">
68
+ * <TamboV1StreamProvider>
60
69
  * <ChatInterface />
61
70
  * </TamboV1StreamProvider>
62
71
  * ```
@@ -107,7 +116,7 @@ export declare function useStreamState(): StreamState;
107
116
  * }
108
117
  * ```
109
118
  */
110
- export declare function useStreamDispatch(): Dispatch<StreamAction>;
119
+ export declare function useStreamDispatch(): React.Dispatch<StreamAction>;
111
120
  /**
112
121
  * Hook to access thread management functions.
113
122
  *
@@ -1 +1 @@
1
- {"version":3,"file":"tambo-v1-stream-context.d.ts","sourceRoot":"","sources":["../../../src/v1/providers/tambo-v1-stream-context.tsx"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EACd,KAAK,QAAQ,EACd,MAAM,OAAO,CAAC;AACf,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,YAAY,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,UAAU,EAAE,CACV,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,KACnC,IAAI,CAAC;IAEV;;;;OAIG;IACH,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAEhD;;;;OAIG;IACH,cAAc,EAAE,MAAM,MAAM,CAAC;CAC9B;AAsBD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAEvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA0CD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,qBAkDtE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAQ5C;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,IAAI,QAAQ,CAAC,YAAY,CAAC,CAU1D;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,CAUtD"}
1
+ {"version":3,"file":"tambo-v1-stream-context.d.ts","sourceRoot":"","sources":["../../../src/v1/providers/tambo-v1-stream-context.tsx"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH,OAAO,KAMN,MAAM,OAAO,CAAC;AACf,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,YAAY,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,UAAU,EAAE,CACV,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,KACnC,IAAI,CAAC;IAEV;;;;OAIG;IACH,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAEhD;;;;OAIG;IACH,cAAc,EAAE,MAAM,MAAM,CAAC;CAC9B;AAqBD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAE1B;;;OAGG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;IAEpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAExC;;OAEG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,qBAiFtE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAQ5C;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAUhE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,CAUtD"}
@@ -6,10 +6,8 @@
6
6
  * Provides state and dispatch to child components via separate contexts
7
7
  * following the split-context pattern for optimal re-render performance.
8
8
  */
9
- // React is used implicitly for JSX transformation (jsx: "react" in tsconfig)
10
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
11
9
  import React, { createContext, useReducer, useContext, useMemo, useCallback, } from "react";
12
- import { streamReducer, createInitialThreadState, } from "../utils/event-accumulator";
10
+ import { streamReducer, } from "../utils/event-accumulator";
13
11
  /**
14
12
  * Context for accessing stream state (read-only).
15
13
  * Separated from dispatch context to prevent unnecessary re-renders.
@@ -25,78 +23,70 @@ const StreamDispatchContext = createContext(null);
25
23
  * Separated from state to prevent unnecessary re-renders.
26
24
  */
27
25
  const ThreadManagementContext = createContext(null);
28
- /**
29
- * Creates initial stream state from props.
30
- * @param props - Provider props
31
- * @returns Initial stream state
32
- */
33
- function createInitialState(props) {
34
- const { initialThread, threadId } = props;
35
- // Initialize with empty threadMap
36
- const threadMap = {};
37
- // If threadId is provided, initialize that thread
38
- if (threadId) {
39
- // Create initial thread state (immutably)
40
- const baseState = createInitialThreadState(threadId);
41
- // If initial thread data provided, merge it immutably
42
- const threadState = initialThread
43
- ? {
44
- ...baseState,
45
- thread: {
46
- ...baseState.thread,
47
- ...initialThread,
48
- id: threadId, // Always use the provided threadId
49
- },
50
- }
51
- : baseState;
52
- threadMap[threadId] = threadState;
53
- }
54
- return {
55
- threadMap,
56
- currentThreadId: threadId ?? null,
57
- };
58
- }
59
26
  /**
60
27
  * Provider component for stream state management.
61
28
  *
62
29
  * Uses useReducer with streamReducer to accumulate AG-UI events into
63
30
  * thread state. Provides state, dispatch, and thread management via separate contexts.
31
+ *
32
+ * Thread management is done programmatically via the hooks:
33
+ * - startNewThread() - Start a new conversation
34
+ * - switchThread(threadId) - Switch to an existing thread
35
+ * - initThread(threadId) - Initialize a thread for receiving events
64
36
  * @returns JSX element wrapping children with stream contexts
65
37
  * @example
66
38
  * ```tsx
67
- * <TamboV1StreamProvider threadId="thread_123">
39
+ * <TamboV1StreamProvider>
68
40
  * <ChatInterface />
69
41
  * </TamboV1StreamProvider>
70
42
  * ```
71
43
  */
72
44
  export function TamboV1StreamProvider(props) {
73
- const { children } = props;
74
- const initialState = useMemo(() => createInitialState(props),
75
- // Only recompute if threadId changes
76
- // eslint-disable-next-line react-hooks/exhaustive-deps
77
- [props.threadId]);
78
- const [state, dispatch] = useReducer(streamReducer, initialState);
45
+ const { children, state: providedState, dispatch: providedDispatch } = props;
46
+ if ((providedState && !providedDispatch) ||
47
+ (!providedState && providedDispatch)) {
48
+ throw new Error("TamboV1StreamProvider requires both state and dispatch when overriding");
49
+ }
50
+ if (props.threadManagement) {
51
+ const { initThread, switchThread, startNewThread } = props.threadManagement;
52
+ if (typeof initThread !== "function" ||
53
+ typeof switchThread !== "function" ||
54
+ typeof startNewThread !== "function") {
55
+ throw new Error("TamboV1StreamProvider: threadManagement override is missing required methods");
56
+ }
57
+ }
58
+ // Create stable initial state - only computed once on mount
59
+ const [state, dispatch] = useReducer(streamReducer, undefined,
60
+ // Lazy initializer function
61
+ () => ({
62
+ threadMap: {},
63
+ currentThreadId: null,
64
+ }));
65
+ const activeState = providedState ?? state;
66
+ const activeDispatch = providedDispatch ?? dispatch;
79
67
  // Thread management functions
80
68
  const initThread = useCallback((threadId, initialThread) => {
81
- dispatch({ type: "INIT_THREAD", threadId, initialThread });
82
- }, []);
69
+ activeDispatch({ type: "INIT_THREAD", threadId, initialThread });
70
+ }, [activeDispatch]);
83
71
  const switchThread = useCallback((threadId) => {
84
- dispatch({ type: "SET_CURRENT_THREAD", threadId });
85
- }, []);
72
+ activeDispatch({ type: "SET_CURRENT_THREAD", threadId });
73
+ }, [activeDispatch]);
86
74
  const startNewThread = useCallback(() => {
87
75
  const tempId = `temp_${crypto.randomUUID()}`;
88
76
  // Use atomic START_NEW_THREAD action to prevent race conditions
89
77
  // when multiple calls happen concurrently (e.g., double-click)
90
- dispatch({ type: "START_NEW_THREAD", threadId: tempId });
78
+ activeDispatch({ type: "START_NEW_THREAD", threadId: tempId });
91
79
  return tempId;
92
- }, []);
93
- const threadManagement = useMemo(() => ({
94
- initThread,
95
- switchThread,
96
- startNewThread,
97
- }), [initThread, switchThread, startNewThread]);
98
- return (React.createElement(StreamStateContext.Provider, { value: state },
99
- React.createElement(StreamDispatchContext.Provider, { value: dispatch },
80
+ }, [activeDispatch]);
81
+ const threadManagement = useMemo(() => {
82
+ return (props.threadManagement ?? {
83
+ initThread,
84
+ switchThread,
85
+ startNewThread,
86
+ });
87
+ }, [props.threadManagement, initThread, switchThread, startNewThread]);
88
+ return (React.createElement(StreamStateContext.Provider, { value: activeState },
89
+ React.createElement(StreamDispatchContext.Provider, { value: activeDispatch },
100
90
  React.createElement(ThreadManagementContext.Provider, { value: threadManagement }, children))));
101
91
  }
102
92
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"tambo-v1-stream-context.js","sourceRoot":"","sources":["../../../src/v1/providers/tambo-v1-stream-context.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * Stream Context Provider for v1 API\n *\n * Manages streaming state using React Context and useReducer.\n * Provides state and dispatch to child components via separate contexts\n * following the split-context pattern for optimal re-render performance.\n */\n\n// React is used implicitly for JSX transformation (jsx: \"react\" in tsconfig)\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport React, {\n createContext,\n useReducer,\n useContext,\n useMemo,\n useCallback,\n type ReactNode,\n type Dispatch,\n} from \"react\";\nimport {\n streamReducer,\n createInitialThreadState,\n type StreamState,\n type StreamAction,\n} from \"../utils/event-accumulator\";\nimport type { TamboV1Thread } from \"../types/thread\";\n\n/**\n * Thread management functions exposed by the stream context.\n */\nexport interface ThreadManagement {\n /**\n * Initialize a new thread in the stream context.\n * Use this before sending messages to a new thread.\n * @param threadId - The thread ID to initialize\n * @param initialThread - Optional initial thread data\n */\n initThread: (\n threadId: string,\n initialThread?: Partial<TamboV1Thread>,\n ) => void;\n\n /**\n * Switch the current active thread.\n * Does not fetch thread data - use useTamboV1Thread for that.\n * @param threadId - The thread ID to switch to, or null to clear\n */\n switchThread: (threadId: string | null) => void;\n\n /**\n * Start a new thread (generates a temporary ID).\n * The actual thread ID will be assigned when the first message is sent.\n * @returns The temporary thread ID\n */\n startNewThread: () => string;\n}\n\n/**\n * Context for accessing stream state (read-only).\n * Separated from dispatch context to prevent unnecessary re-renders.\n */\nconst StreamStateContext = createContext<StreamState | null>(null);\n\n/**\n * Context for dispatching events to the stream reducer.\n * Separated from state context to prevent unnecessary re-renders.\n */\nconst StreamDispatchContext = createContext<Dispatch<StreamAction> | null>(\n null,\n);\n\n/**\n * Context for thread management functions.\n * Separated from state to prevent unnecessary re-renders.\n */\nconst ThreadManagementContext = createContext<ThreadManagement | null>(null);\n\n/**\n * Props for TamboV1StreamProvider\n */\nexport interface TamboV1StreamProviderProps {\n children: ReactNode;\n\n /**\n * Initial thread state (optional).\n * If not provided, an empty thread will be created.\n */\n initialThread?: Partial<TamboV1Thread>;\n\n /**\n * Thread ID for the stream context.\n * Used to initialize the thread if initialThread is not provided.\n */\n threadId?: string;\n}\n\n/**\n * Creates initial stream state from props.\n * @param props - Provider props\n * @returns Initial stream state\n */\nfunction createInitialState(props: TamboV1StreamProviderProps): StreamState {\n const { initialThread, threadId } = props;\n\n // Initialize with empty threadMap\n const threadMap: Record<\n string,\n ReturnType<typeof createInitialThreadState>\n > = {};\n\n // If threadId is provided, initialize that thread\n if (threadId) {\n // Create initial thread state (immutably)\n const baseState = createInitialThreadState(threadId);\n\n // If initial thread data provided, merge it immutably\n const threadState = initialThread\n ? {\n ...baseState,\n thread: {\n ...baseState.thread,\n ...initialThread,\n id: threadId, // Always use the provided threadId\n },\n }\n : baseState;\n\n threadMap[threadId] = threadState;\n }\n\n return {\n threadMap,\n currentThreadId: threadId ?? null,\n };\n}\n\n/**\n * Provider component for stream state management.\n *\n * Uses useReducer with streamReducer to accumulate AG-UI events into\n * thread state. Provides state, dispatch, and thread management via separate contexts.\n * @returns JSX element wrapping children with stream contexts\n * @example\n * ```tsx\n * <TamboV1StreamProvider threadId=\"thread_123\">\n * <ChatInterface />\n * </TamboV1StreamProvider>\n * ```\n */\nexport function TamboV1StreamProvider(props: TamboV1StreamProviderProps) {\n const { children } = props;\n\n const initialState = useMemo(\n () => createInitialState(props),\n // Only recompute if threadId changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [props.threadId],\n );\n\n const [state, dispatch] = useReducer(streamReducer, initialState);\n\n // Thread management functions\n const initThread = useCallback(\n (threadId: string, initialThread?: Partial<TamboV1Thread>) => {\n dispatch({ type: \"INIT_THREAD\", threadId, initialThread });\n },\n [],\n );\n\n const switchThread = useCallback((threadId: string | null) => {\n dispatch({ type: \"SET_CURRENT_THREAD\", threadId });\n }, []);\n\n const startNewThread = useCallback(() => {\n const tempId = `temp_${crypto.randomUUID()}`;\n // Use atomic START_NEW_THREAD action to prevent race conditions\n // when multiple calls happen concurrently (e.g., double-click)\n dispatch({ type: \"START_NEW_THREAD\", threadId: tempId });\n return tempId;\n }, []);\n\n const threadManagement = useMemo<ThreadManagement>(\n () => ({\n initThread,\n switchThread,\n startNewThread,\n }),\n [initThread, switchThread, startNewThread],\n );\n\n return (\n <StreamStateContext.Provider value={state}>\n <StreamDispatchContext.Provider value={dispatch}>\n <ThreadManagementContext.Provider value={threadManagement}>\n {children}\n </ThreadManagementContext.Provider>\n </StreamDispatchContext.Provider>\n </StreamStateContext.Provider>\n );\n}\n\n/**\n * Hook to access stream state.\n *\n * Must be used within TamboV1StreamProvider.\n * @returns Current stream state\n * @throws {Error} if used outside TamboV1StreamProvider\n * @example\n * ```tsx\n * function ChatMessages() {\n * const { thread, streaming } = useStreamState();\n *\n * return (\n * <div>\n * {thread.messages.map(msg => <Message key={msg.id} message={msg} />)}\n * {streaming.status === 'streaming' && <LoadingIndicator />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useStreamState(): StreamState {\n const context = useContext(StreamStateContext);\n\n if (!context) {\n throw new Error(\"useStreamState must be used within TamboV1StreamProvider\");\n }\n\n return context;\n}\n\n/**\n * Hook to access stream dispatch function.\n *\n * Must be used within TamboV1StreamProvider.\n * @returns Dispatch function for sending events to reducer\n * @throws {Error} if used outside TamboV1StreamProvider\n * @example\n * ```tsx\n * function StreamHandler() {\n * const dispatch = useStreamDispatch();\n *\n * useEffect(() => {\n * async function handleStream() {\n * for await (const event of streamEvents) {\n * dispatch({ type: 'EVENT', event });\n * }\n * }\n * handleStream();\n * }, [dispatch]);\n *\n * return null;\n * }\n * ```\n */\nexport function useStreamDispatch(): Dispatch<StreamAction> {\n const context = useContext(StreamDispatchContext);\n\n if (!context) {\n throw new Error(\n \"useStreamDispatch must be used within TamboV1StreamProvider\",\n );\n }\n\n return context;\n}\n\n/**\n * Hook to access thread management functions.\n *\n * Must be used within TamboV1StreamProvider.\n * @returns Thread management functions\n * @throws {Error} if used outside TamboV1StreamProvider\n * @example\n * ```tsx\n * function ThreadSwitcher() {\n * const { switchThread, startNewThread } = useThreadManagement();\n *\n * return (\n * <div>\n * <button onClick={() => switchThread('thread_123')}>\n * Load Thread\n * </button>\n * <button onClick={startNewThread}>\n * New Chat\n * </button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useThreadManagement(): ThreadManagement {\n const context = useContext(ThreadManagementContext);\n\n if (!context) {\n throw new Error(\n \"useThreadManagement must be used within TamboV1StreamProvider\",\n );\n }\n\n return context;\n}\n"]}
1
+ {"version":3,"file":"tambo-v1-stream-context.js","sourceRoot":"","sources":["../../../src/v1/providers/tambo-v1-stream-context.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * Stream Context Provider for v1 API\n *\n * Manages streaming state using React Context and useReducer.\n * Provides state and dispatch to child components via separate contexts\n * following the split-context pattern for optimal re-render performance.\n */\n\nimport React, {\n createContext,\n useReducer,\n useContext,\n useMemo,\n useCallback,\n} from \"react\";\nimport {\n streamReducer,\n type StreamState,\n type StreamAction,\n} from \"../utils/event-accumulator\";\nimport type { TamboV1Thread } from \"../types/thread\";\n\n/**\n * Thread management functions exposed by the stream context.\n */\nexport interface ThreadManagement {\n /**\n * Initialize a new thread in the stream context.\n * Use this before sending messages to a new thread.\n * @param threadId - The thread ID to initialize\n * @param initialThread - Optional initial thread data\n */\n initThread: (\n threadId: string,\n initialThread?: Partial<TamboV1Thread>,\n ) => void;\n\n /**\n * Switch the current active thread.\n * Does not fetch thread data - use useTamboV1Thread for that.\n * @param threadId - The thread ID to switch to, or null to clear\n */\n switchThread: (threadId: string | null) => void;\n\n /**\n * Start a new thread (generates a temporary ID).\n * The actual thread ID will be assigned when the first message is sent.\n * @returns The temporary thread ID\n */\n startNewThread: () => string;\n}\n\n/**\n * Context for accessing stream state (read-only).\n * Separated from dispatch context to prevent unnecessary re-renders.\n */\nconst StreamStateContext = createContext<StreamState | null>(null);\n\n/**\n * Context for dispatching events to the stream reducer.\n * Separated from state context to prevent unnecessary re-renders.\n */\nconst StreamDispatchContext =\n createContext<React.Dispatch<StreamAction> | null>(null);\n\n/**\n * Context for thread management functions.\n * Separated from state to prevent unnecessary re-renders.\n */\nconst ThreadManagementContext = createContext<ThreadManagement | null>(null);\n\n/**\n * Props for TamboV1StreamProvider\n */\nexport interface TamboV1StreamProviderProps {\n children: React.ReactNode;\n\n /**\n * Optional override for stream state (primarily for tests).\n * If provided, you must also provide `dispatch`.\n */\n state?: StreamState;\n\n /**\n * Optional override for stream dispatch (primarily for tests).\n * If provided, you must also provide `state`.\n */\n dispatch?: React.Dispatch<StreamAction>;\n\n /**\n * Optional override for thread management functions (primarily for tests).\n */\n threadManagement?: ThreadManagement;\n}\n\n/**\n * Provider component for stream state management.\n *\n * Uses useReducer with streamReducer to accumulate AG-UI events into\n * thread state. Provides state, dispatch, and thread management via separate contexts.\n *\n * Thread management is done programmatically via the hooks:\n * - startNewThread() - Start a new conversation\n * - switchThread(threadId) - Switch to an existing thread\n * - initThread(threadId) - Initialize a thread for receiving events\n * @returns JSX element wrapping children with stream contexts\n * @example\n * ```tsx\n * <TamboV1StreamProvider>\n * <ChatInterface />\n * </TamboV1StreamProvider>\n * ```\n */\nexport function TamboV1StreamProvider(props: TamboV1StreamProviderProps) {\n const { children, state: providedState, dispatch: providedDispatch } = props;\n\n if (\n (providedState && !providedDispatch) ||\n (!providedState && providedDispatch)\n ) {\n throw new Error(\n \"TamboV1StreamProvider requires both state and dispatch when overriding\",\n );\n }\n\n if (props.threadManagement) {\n const { initThread, switchThread, startNewThread } = props.threadManagement;\n if (\n typeof initThread !== \"function\" ||\n typeof switchThread !== \"function\" ||\n typeof startNewThread !== \"function\"\n ) {\n throw new Error(\n \"TamboV1StreamProvider: threadManagement override is missing required methods\",\n );\n }\n }\n\n // Create stable initial state - only computed once on mount\n const [state, dispatch] = useReducer(\n streamReducer,\n undefined,\n // Lazy initializer function\n () => ({\n threadMap: {},\n currentThreadId: null,\n }),\n );\n\n const activeState = providedState ?? state;\n const activeDispatch = providedDispatch ?? dispatch;\n\n // Thread management functions\n const initThread = useCallback(\n (threadId: string, initialThread?: Partial<TamboV1Thread>) => {\n activeDispatch({ type: \"INIT_THREAD\", threadId, initialThread });\n },\n [activeDispatch],\n );\n\n const switchThread = useCallback(\n (threadId: string | null) => {\n activeDispatch({ type: \"SET_CURRENT_THREAD\", threadId });\n },\n [activeDispatch],\n );\n\n const startNewThread = useCallback(() => {\n const tempId = `temp_${crypto.randomUUID()}`;\n // Use atomic START_NEW_THREAD action to prevent race conditions\n // when multiple calls happen concurrently (e.g., double-click)\n activeDispatch({ type: \"START_NEW_THREAD\", threadId: tempId });\n return tempId;\n }, [activeDispatch]);\n\n const threadManagement = useMemo<ThreadManagement>(() => {\n return (\n props.threadManagement ?? {\n initThread,\n switchThread,\n startNewThread,\n }\n );\n }, [props.threadManagement, initThread, switchThread, startNewThread]);\n\n return (\n <StreamStateContext.Provider value={activeState}>\n <StreamDispatchContext.Provider value={activeDispatch}>\n <ThreadManagementContext.Provider value={threadManagement}>\n {children}\n </ThreadManagementContext.Provider>\n </StreamDispatchContext.Provider>\n </StreamStateContext.Provider>\n );\n}\n\n/**\n * Hook to access stream state.\n *\n * Must be used within TamboV1StreamProvider.\n * @returns Current stream state\n * @throws {Error} if used outside TamboV1StreamProvider\n * @example\n * ```tsx\n * function ChatMessages() {\n * const { thread, streaming } = useStreamState();\n *\n * return (\n * <div>\n * {thread.messages.map(msg => <Message key={msg.id} message={msg} />)}\n * {streaming.status === 'streaming' && <LoadingIndicator />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useStreamState(): StreamState {\n const context = useContext(StreamStateContext);\n\n if (!context) {\n throw new Error(\"useStreamState must be used within TamboV1StreamProvider\");\n }\n\n return context;\n}\n\n/**\n * Hook to access stream dispatch function.\n *\n * Must be used within TamboV1StreamProvider.\n * @returns Dispatch function for sending events to reducer\n * @throws {Error} if used outside TamboV1StreamProvider\n * @example\n * ```tsx\n * function StreamHandler() {\n * const dispatch = useStreamDispatch();\n *\n * useEffect(() => {\n * async function handleStream() {\n * for await (const event of streamEvents) {\n * dispatch({ type: 'EVENT', event });\n * }\n * }\n * handleStream();\n * }, [dispatch]);\n *\n * return null;\n * }\n * ```\n */\nexport function useStreamDispatch(): React.Dispatch<StreamAction> {\n const context = useContext(StreamDispatchContext);\n\n if (!context) {\n throw new Error(\n \"useStreamDispatch must be used within TamboV1StreamProvider\",\n );\n }\n\n return context;\n}\n\n/**\n * Hook to access thread management functions.\n *\n * Must be used within TamboV1StreamProvider.\n * @returns Thread management functions\n * @throws {Error} if used outside TamboV1StreamProvider\n * @example\n * ```tsx\n * function ThreadSwitcher() {\n * const { switchThread, startNewThread } = useThreadManagement();\n *\n * return (\n * <div>\n * <button onClick={() => switchThread('thread_123')}>\n * Load Thread\n * </button>\n * <button onClick={startNewThread}>\n * New Chat\n * </button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useThreadManagement(): ThreadManagement {\n const context = useContext(ThreadManagementContext);\n\n if (!context) {\n throw new Error(\n \"useThreadManagement must be used within TamboV1StreamProvider\",\n );\n }\n\n return context;\n}\n"]}