@tambo-ai/react 0.36.0 → 0.37.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.
- package/dist/providers/tambo-client-provider.d.ts +8 -0
- package/dist/providers/tambo-client-provider.d.ts.map +1 -1
- package/dist/providers/tambo-client-provider.js +51 -1
- package/dist/providers/tambo-client-provider.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js +2 -2
- package/dist/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-client-provider.d.ts +8 -0
- package/esm/providers/tambo-client-provider.d.ts.map +1 -1
- package/esm/providers/tambo-client-provider.js +52 -2
- package/esm/providers/tambo-client-provider.js.map +1 -1
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js +2 -2
- package/esm/providers/tambo-provider.js.map +1 -1
- package/package.json +2 -2
|
@@ -15,6 +15,13 @@ export interface TamboClientProviderProps {
|
|
|
15
15
|
* The environment to use for the Tambo API
|
|
16
16
|
*/
|
|
17
17
|
environment?: "production" | "staging";
|
|
18
|
+
/**
|
|
19
|
+
* The user token to use to identify the user in the Tambo API. This token is
|
|
20
|
+
* a 3rd party token like a Google or GitHub access token, exchanged with the
|
|
21
|
+
* Tambo API to get a session token. This is used to securely identify the
|
|
22
|
+
* user when calling the Tambo API.
|
|
23
|
+
*/
|
|
24
|
+
userToken?: string;
|
|
18
25
|
}
|
|
19
26
|
export interface TamboClientContextProps {
|
|
20
27
|
/** The TamboAI client */
|
|
@@ -31,6 +38,7 @@ export declare const TamboClientContext: React.Context<TamboClientContextProps |
|
|
|
31
38
|
* @param props.tamboUrl - The URL of the Tambo API
|
|
32
39
|
* @param props.apiKey - The API key for the Tambo API
|
|
33
40
|
* @param props.environment - The environment to use for the Tambo API
|
|
41
|
+
* @param props.userToken - The oauth access token to use to identify the user in the Tambo API
|
|
34
42
|
* @returns The TamboClientProvider component
|
|
35
43
|
*/
|
|
36
44
|
export declare const TamboClientProvider: React.FC<PropsWithChildren<TamboClientProviderProps>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-client-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.tsx"],"names":[],"mappings":"AACA,OAAO,OAA0B,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"tambo-client-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.tsx"],"names":[],"mappings":"AACA,OAAO,OAA0B,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,EAEZ,iBAAiB,EAGlB,MAAM,OAAO,CAAC;AAGf,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAEvC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,yBAAyB;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,sCAAsC;IACtC,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,eAAO,MAAM,kBAAkB,oDAEnB,CAAC;AAEb;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CACxC,iBAAiB,CAAC,wBAAwB,CAAC,CAyB5C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,cAAc,eAM1B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,mBAQ/B,CAAC"}
|
|
@@ -51,9 +51,10 @@ exports.TamboClientContext = (0, react_1.createContext)(undefined);
|
|
|
51
51
|
* @param props.tamboUrl - The URL of the Tambo API
|
|
52
52
|
* @param props.apiKey - The API key for the Tambo API
|
|
53
53
|
* @param props.environment - The environment to use for the Tambo API
|
|
54
|
+
* @param props.userToken - The oauth access token to use to identify the user in the Tambo API
|
|
54
55
|
* @returns The TamboClientProvider component
|
|
55
56
|
*/
|
|
56
|
-
const TamboClientProvider = ({ children, tamboUrl, apiKey, environment }) => {
|
|
57
|
+
const TamboClientProvider = ({ children, tamboUrl, apiKey, environment, userToken }) => {
|
|
57
58
|
const tamboConfig = {
|
|
58
59
|
apiKey,
|
|
59
60
|
defaultHeaders: {
|
|
@@ -68,6 +69,8 @@ const TamboClientProvider = ({ children, tamboUrl, apiKey, environment }) => {
|
|
|
68
69
|
}
|
|
69
70
|
const [client] = (0, react_1.useState)(() => new typescript_sdk_1.default(tamboConfig));
|
|
70
71
|
const [queryClient] = (0, react_1.useState)(() => new react_query_1.QueryClient());
|
|
72
|
+
// Keep the session token updated
|
|
73
|
+
useTamboSessionToken(client, userToken);
|
|
71
74
|
return (react_1.default.createElement(exports.TamboClientContext.Provider, { value: { client, queryClient } }, children));
|
|
72
75
|
};
|
|
73
76
|
exports.TamboClientProvider = TamboClientProvider;
|
|
@@ -98,4 +101,51 @@ const useTamboQueryClient = () => {
|
|
|
98
101
|
return context.queryClient;
|
|
99
102
|
};
|
|
100
103
|
exports.useTamboQueryClient = useTamboQueryClient;
|
|
104
|
+
function useTamboSessionToken(client, userToken) {
|
|
105
|
+
const [tamboSessionToken, setTamboSessionToken] = (0, react_1.useState)(null);
|
|
106
|
+
// we need to set this to true when the token is expired, this is effectively
|
|
107
|
+
// like a dirty bit, which will trigger a new useEffect()
|
|
108
|
+
const [isExpired, setIsExpired] = (0, react_1.useState)(true);
|
|
109
|
+
(0, react_1.useEffect)(() => {
|
|
110
|
+
let expireTimer = null;
|
|
111
|
+
async function updateToken(subjectToken, abortController) {
|
|
112
|
+
if (abortController.signal.aborted || !userToken) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const tokenRequest = {
|
|
116
|
+
grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
|
|
117
|
+
subject_token: subjectToken,
|
|
118
|
+
subject_token_type: "urn:ietf:params:oauth:token-type:access_token",
|
|
119
|
+
};
|
|
120
|
+
const tokenRequestFormEncoded = new URLSearchParams(tokenRequest).toString();
|
|
121
|
+
const tokenAsArrayBuffer = new TextEncoder().encode(tokenRequestFormEncoded);
|
|
122
|
+
const tamboToken = await client.beta.auth.getToken(tokenAsArrayBuffer);
|
|
123
|
+
if (abortController.signal.aborted) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
setTamboSessionToken(tamboToken.access_token);
|
|
127
|
+
client.bearer = tamboToken.access_token;
|
|
128
|
+
// we need to set a timer to refresh the token when it expires
|
|
129
|
+
const refreshTime = Math.max(tamboToken.expires_in - 60, 0);
|
|
130
|
+
// careful with the assignment here: since this is an async function, this
|
|
131
|
+
// code is executed outside the of the scope of the useEffect() hook, so
|
|
132
|
+
// we need to use a let variable to store the timer
|
|
133
|
+
expireTimer = setTimeout(() => {
|
|
134
|
+
setIsExpired(true);
|
|
135
|
+
}, refreshTime * 1000);
|
|
136
|
+
}
|
|
137
|
+
const abortController = new AbortController();
|
|
138
|
+
if (userToken && isExpired) {
|
|
139
|
+
updateToken(userToken, abortController);
|
|
140
|
+
}
|
|
141
|
+
return () => {
|
|
142
|
+
// This fires when the component unmounts or the userToken changes
|
|
143
|
+
abortController.abort();
|
|
144
|
+
if (expireTimer) {
|
|
145
|
+
clearTimeout(expireTimer);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}, [client, isExpired, userToken]);
|
|
149
|
+
return tamboSessionToken;
|
|
150
|
+
}
|
|
101
151
|
//# sourceMappingURL=tambo-client-provider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-client-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACb,8EAAkE;AAClE,uDAAoD;AACpD,+
|
|
1
|
+
{"version":3,"file":"tambo-client-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport TamboAI, { ClientOptions } from \"@tambo-ai/typescript-sdk\";\nimport { QueryClient } from \"@tanstack/react-query\";\nimport React, {\n createContext,\n PropsWithChildren,\n useEffect,\n useState,\n} from \"react\";\nimport packageJson from \"../../package.json\";\n\nexport interface TamboClientProviderProps {\n /**\n * The URL of the Tambo API (only used for local development and debugging)\n */\n tamboUrl?: string;\n /**\n * The API key for the Tambo API. This typically comes from a variable like\n * `process.env.NEXT_PUBLIC_TAMBO_API_KEY`\n */\n apiKey: string;\n /**\n * The environment to use for the Tambo API\n */\n environment?: \"production\" | \"staging\";\n\n /**\n * The user token to use to identify the user in the Tambo API. This token is\n * a 3rd party token like a Google or GitHub access token, exchanged with the\n * Tambo API to get a session token. This is used to securely identify the\n * user when calling the Tambo API.\n */\n userToken?: string;\n}\n\nexport interface TamboClientContextProps {\n /** The TamboAI client */\n client: TamboAI;\n /** The tambo-specific query client */\n queryClient: QueryClient;\n}\n\nexport const TamboClientContext = createContext<\n TamboClientContextProps | undefined\n>(undefined);\n\n/**\n * The TamboClientProvider is a React provider that provides a TamboAI client\n * and a query client to the descendants of the provider.\n * @param props - The props for the TamboClientProvider\n * @param props.children - The children to wrap\n * @param props.tamboUrl - The URL of the Tambo API\n * @param props.apiKey - The API key for the Tambo API\n * @param props.environment - The environment to use for the Tambo API\n * @param props.userToken - The oauth access token to use to identify the user in the Tambo API\n * @returns The TamboClientProvider component\n */\nexport const TamboClientProvider: React.FC<\n PropsWithChildren<TamboClientProviderProps>\n> = ({ children, tamboUrl, apiKey, environment, userToken }) => {\n const tamboConfig: ClientOptions = {\n apiKey,\n defaultHeaders: {\n \"X-Tambo-React-Version\": packageJson.version,\n },\n };\n if (tamboUrl) {\n tamboConfig.baseURL = tamboUrl;\n }\n if (environment) {\n tamboConfig.environment = environment;\n }\n const [client] = useState(() => new TamboAI(tamboConfig));\n const [queryClient] = useState(() => new QueryClient());\n\n // Keep the session token updated\n useTamboSessionToken(client, userToken);\n\n return (\n <TamboClientContext.Provider value={{ client, queryClient }}>\n {children}\n </TamboClientContext.Provider>\n );\n};\n\n/**\n * The useTamboClient hook provides access to the TamboAI client\n * to the descendants of the TamboClientProvider.\n * @returns The TamboAI client\n */\nexport const useTamboClient = () => {\n const context = React.useContext(TamboClientContext);\n if (context === undefined) {\n throw new Error(\"useTamboClient must be used within a TamboClientProvider\");\n }\n return context.client;\n};\n\n/**\n * The useTamboQueryClient hook provides access to the tambo-specific query client\n * to the descendants of the TamboClientProvider.\n * @returns The tambo-specific query client\n * @private\n */\nexport const useTamboQueryClient = () => {\n const context = React.useContext(TamboClientContext);\n if (context === undefined) {\n throw new Error(\n \"useTamboQueryClient must be used within a TamboClientProvider\",\n );\n }\n return context.queryClient;\n};\n\nfunction useTamboSessionToken(client: TamboAI, userToken: string | undefined) {\n const [tamboSessionToken, setTamboSessionToken] = useState<string | null>(\n null,\n );\n // we need to set this to true when the token is expired, this is effectively\n // like a dirty bit, which will trigger a new useEffect()\n const [isExpired, setIsExpired] = useState(true);\n useEffect(() => {\n let expireTimer: NodeJS.Timeout | null = null;\n\n async function updateToken(\n subjectToken: string,\n abortController: AbortController,\n ) {\n if (abortController.signal.aborted || !userToken) {\n return;\n }\n const tokenRequest = {\n grant_type: \"urn:ietf:params:oauth:grant-type:token-exchange\",\n subject_token: subjectToken,\n subject_token_type: \"urn:ietf:params:oauth:token-type:access_token\",\n };\n const tokenRequestFormEncoded = new URLSearchParams(\n tokenRequest,\n ).toString();\n const tokenAsArrayBuffer = new TextEncoder().encode(\n tokenRequestFormEncoded,\n );\n const tamboToken = await client.beta.auth.getToken(\n tokenAsArrayBuffer as any,\n );\n\n if (abortController.signal.aborted) {\n return;\n }\n setTamboSessionToken(tamboToken.access_token);\n client.bearer = tamboToken.access_token;\n\n // we need to set a timer to refresh the token when it expires\n const refreshTime = Math.max(tamboToken.expires_in - 60, 0);\n\n // careful with the assignment here: since this is an async function, this\n // code is executed outside the of the scope of the useEffect() hook, so\n // we need to use a let variable to store the timer\n expireTimer = setTimeout(() => {\n setIsExpired(true);\n }, refreshTime * 1000);\n }\n\n const abortController = new AbortController();\n if (userToken && isExpired) {\n updateToken(userToken, abortController);\n }\n\n return () => {\n // This fires when the component unmounts or the userToken changes\n abortController.abort();\n if (expireTimer) {\n clearTimeout(expireTimer);\n }\n };\n }, [client, isExpired, userToken]);\n\n return tamboSessionToken;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAA6B,MAAM,OAAO,CAAC;AAC5E,OAAO,EACL,uBAAuB,EAEvB,wBAAwB,EAGzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,0BAA0B,EAG3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,0BAA0B,EAC3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EAEvB,wBAAwB,EAEzB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAClC,iBAAiB,CACf,wBAAwB,GACtB,0BAA0B,GAC1B,wBAAwB,CAC3B,
|
|
1
|
+
{"version":3,"file":"tambo-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAA6B,MAAM,OAAO,CAAC;AAC5E,OAAO,EACL,uBAAuB,EAEvB,wBAAwB,EAGzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,0BAA0B,EAG3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,0BAA0B,EAC3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EAEvB,wBAAwB,EAEzB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAClC,iBAAiB,CACf,wBAAwB,GACtB,0BAA0B,GAC1B,wBAAwB,CAC3B,CAgCF,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG,uBAAuB,GACrD,uBAAuB,GACvB,0BAA0B,CAAC;AAE7B,eAAO,MAAM,YAAY,kCAExB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAoB9D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,yBAEpB,CAAC"}
|
|
@@ -53,12 +53,12 @@ const tambo_thread_provider_1 = require("./tambo-thread-provider");
|
|
|
53
53
|
* @param props.streaming - Whether to stream the response by default. Defaults to true.
|
|
54
54
|
* @returns The TamboProvider component
|
|
55
55
|
*/
|
|
56
|
-
const TamboProvider = ({ children, tamboUrl, apiKey, components, environment, tools, streaming, }) => {
|
|
56
|
+
const TamboProvider = ({ children, tamboUrl, apiKey, userToken, components, environment, tools, streaming, }) => {
|
|
57
57
|
// Should only be used in browser
|
|
58
58
|
if (typeof window === "undefined") {
|
|
59
59
|
console.error("TamboProvider must be used within a browser");
|
|
60
60
|
}
|
|
61
|
-
return (react_1.default.createElement(tambo_client_provider_1.TamboClientProvider, { tamboUrl: tamboUrl, apiKey: apiKey, environment: environment },
|
|
61
|
+
return (react_1.default.createElement(tambo_client_provider_1.TamboClientProvider, { tamboUrl: tamboUrl, apiKey: apiKey, environment: environment, userToken: userToken },
|
|
62
62
|
react_1.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, { components: components, tools: tools },
|
|
63
63
|
react_1.default.createElement(tambo_thread_provider_1.TamboThreadProvider, { streaming: streaming },
|
|
64
64
|
react_1.default.createElement(tambo_component_provider_1.TamboComponentProvider, null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-provider.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACb,+CAA4E;AAC5E,mEAMiC;AACjC,yEAIoC;AACpC,uEAGmC;AACnC,mEAKiC;AAEjC;;;;;;;;;;;;GAYG;AACI,MAAM,aAAa,GAMtB,CAAC,EACH,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,UAAU,EACV,WAAW,EACX,KAAK,EACL,SAAS,GACV,EAAE,EAAE;IACH,iCAAiC;IACjC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,CACL,8BAAC,2CAAmB,IAClB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW;
|
|
1
|
+
{"version":3,"file":"tambo-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-provider.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACb,+CAA4E;AAC5E,mEAMiC;AACjC,yEAIoC;AACpC,uEAGmC;AACnC,mEAKiC;AAEjC;;;;;;;;;;;;GAYG;AACI,MAAM,aAAa,GAMtB,CAAC,EACH,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,SAAS,EACT,UAAU,EACV,WAAW,EACX,KAAK,EACL,SAAS,GACV,EAAE,EAAE;IACH,iCAAiC;IACjC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,CACL,8BAAC,2CAAmB,IAClB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS;QAEpB,8BAAC,+CAAqB,IAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK;YACzD,8BAAC,2CAAmB,IAAC,SAAS,EAAE,SAAS;gBACvC,8BAAC,iDAAsB;oBACrB,8BAAC,8BAAsB,QAAE,QAAQ,CAA0B,CACpC,CACL,CACA,CACJ,CACvB,CAAC;AACJ,CAAC,CAAC;AArCW,QAAA,aAAa,iBAqCxB;AAKW,QAAA,YAAY,GAAG,IAAA,qBAAa,EACvC,EAAuB,CACxB,CAAC;AAEF;;;;;;GAMG;AACI,MAAM,sBAAsB,GAAgC,CAAC,EAClE,QAAQ,GACT,EAAE,EAAE;IACH,MAAM,OAAO,GAAG,IAAA,sCAAc,GAAE,CAAC;IACjC,MAAM,MAAM,GAAG,IAAA,sCAAc,GAAE,CAAC;IAChC,MAAM,WAAW,GAAG,IAAA,2CAAmB,GAAE,CAAC;IAC1C,MAAM,iBAAiB,GAAG,IAAA,4CAAiB,GAAE,CAAC;IAE9C,OAAO,CACL,8BAAC,oBAAY,CAAC,QAAQ,IACpB,KAAK,EAAE;YACL,MAAM;YACN,WAAW;YACX,GAAG,iBAAiB;YACpB,GAAG,OAAO;SACX,IAEA,QAAQ,CACa,CACzB,CAAC;AACJ,CAAC,CAAC;AApBW,QAAA,sBAAsB,0BAoBjC;AAEF;;;;;;GAMG;AACI,MAAM,QAAQ,GAAG,GAAG,EAAE;IAC3B,OAAO,IAAA,kBAAU,EAAC,oBAAY,CAAC,CAAC;AAClC,CAAC,CAAC;AAFW,QAAA,QAAQ,YAEnB","sourcesContent":["\"use client\";\nimport React, { PropsWithChildren, createContext, useContext } from \"react\";\nimport {\n TamboClientContextProps,\n TamboClientProvider,\n TamboClientProviderProps,\n useTamboClient,\n useTamboQueryClient,\n} from \"./tambo-client-provider\";\nimport {\n TamboComponentContextProps,\n TamboComponentProvider,\n useTamboComponent,\n} from \"./tambo-component-provider\";\nimport {\n TamboRegistryProvider,\n TamboRegistryProviderProps,\n} from \"./tambo-registry-provider\";\nimport {\n TamboThreadContextProps,\n TamboThreadProvider,\n TamboThreadProviderProps,\n useTamboThread,\n} from \"./tambo-thread-provider\";\n\n/**\n * The TamboProvider gives full access to the whole Tambo API. This includes the\n * TamboAI client, the component registry, and the current thread context.\n * @param props - The props for the TamboProvider\n * @param props.children - The children to wrap\n * @param props.tamboUrl - The URL of the Tambo API\n * @param props.apiKey - The API key for the Tambo API\n * @param props.components - The components to register\n * @param props.environment - The environment to use for the Tambo API\n * @param props.tools - The tools to register\n * @param props.streaming - Whether to stream the response by default. Defaults to true.\n * @returns The TamboProvider component\n */\nexport const TamboProvider: React.FC<\n PropsWithChildren<\n TamboClientProviderProps &\n TamboRegistryProviderProps &\n TamboThreadProviderProps\n >\n> = ({\n children,\n tamboUrl,\n apiKey,\n userToken,\n components,\n environment,\n tools,\n streaming,\n}) => {\n // Should only be used in browser\n if (typeof window === \"undefined\") {\n console.error(\"TamboProvider must be used within a browser\");\n }\n\n return (\n <TamboClientProvider\n tamboUrl={tamboUrl}\n apiKey={apiKey}\n environment={environment}\n userToken={userToken}\n >\n <TamboRegistryProvider components={components} tools={tools}>\n <TamboThreadProvider streaming={streaming}>\n <TamboComponentProvider>\n <TamboCompositeProvider>{children}</TamboCompositeProvider>\n </TamboComponentProvider>\n </TamboThreadProvider>\n </TamboRegistryProvider>\n </TamboClientProvider>\n );\n};\nexport type TamboContextProps = TamboClientContextProps &\n TamboThreadContextProps &\n TamboComponentContextProps;\n\nexport const TamboContext = createContext<TamboContextProps>(\n {} as TamboContextProps,\n);\n\n/**\n * TamboCompositeProvider is a provider that combines the TamboClient,\n * TamboThread, and TamboComponent providers\n * @param props - The props for the TamboCompositeProvider\n * @param props.children - The children to wrap\n * @returns The wrapped component\n */\nexport const TamboCompositeProvider: React.FC<PropsWithChildren> = ({\n children,\n}) => {\n const threads = useTamboThread();\n const client = useTamboClient();\n const queryClient = useTamboQueryClient();\n const componentRegistry = useTamboComponent();\n\n return (\n <TamboContext.Provider\n value={{\n client,\n queryClient,\n ...componentRegistry,\n ...threads,\n }}\n >\n {children}\n </TamboContext.Provider>\n );\n};\n\n/**\n * The useTambo hook provides access to the Tambo API. This is the primary entrypoint\n * for the Tambo React SDK.\n *\n * This includes the TamboAI client, the component registry, and the current thread context.\n * @returns The Tambo API\n */\nexport const useTambo = () => {\n return useContext(TamboContext);\n};\n"]}
|
|
@@ -15,6 +15,13 @@ export interface TamboClientProviderProps {
|
|
|
15
15
|
* The environment to use for the Tambo API
|
|
16
16
|
*/
|
|
17
17
|
environment?: "production" | "staging";
|
|
18
|
+
/**
|
|
19
|
+
* The user token to use to identify the user in the Tambo API. This token is
|
|
20
|
+
* a 3rd party token like a Google or GitHub access token, exchanged with the
|
|
21
|
+
* Tambo API to get a session token. This is used to securely identify the
|
|
22
|
+
* user when calling the Tambo API.
|
|
23
|
+
*/
|
|
24
|
+
userToken?: string;
|
|
18
25
|
}
|
|
19
26
|
export interface TamboClientContextProps {
|
|
20
27
|
/** The TamboAI client */
|
|
@@ -31,6 +38,7 @@ export declare const TamboClientContext: React.Context<TamboClientContextProps |
|
|
|
31
38
|
* @param props.tamboUrl - The URL of the Tambo API
|
|
32
39
|
* @param props.apiKey - The API key for the Tambo API
|
|
33
40
|
* @param props.environment - The environment to use for the Tambo API
|
|
41
|
+
* @param props.userToken - The oauth access token to use to identify the user in the Tambo API
|
|
34
42
|
* @returns The TamboClientProvider component
|
|
35
43
|
*/
|
|
36
44
|
export declare const TamboClientProvider: React.FC<PropsWithChildren<TamboClientProviderProps>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-client-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.tsx"],"names":[],"mappings":"AACA,OAAO,OAA0B,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"tambo-client-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.tsx"],"names":[],"mappings":"AACA,OAAO,OAA0B,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,EAEZ,iBAAiB,EAGlB,MAAM,OAAO,CAAC;AAGf,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAEvC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,yBAAyB;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,sCAAsC;IACtC,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,eAAO,MAAM,kBAAkB,oDAEnB,CAAC;AAEb;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CACxC,iBAAiB,CAAC,wBAAwB,CAAC,CAyB5C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,cAAc,eAM1B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,mBAQ/B,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import TamboAI from "@tambo-ai/typescript-sdk";
|
|
3
3
|
import { QueryClient } from "@tanstack/react-query";
|
|
4
|
-
import React, { createContext, useState } from "react";
|
|
4
|
+
import React, { createContext, useEffect, useState, } from "react";
|
|
5
5
|
import packageJson from "../../package.json";
|
|
6
6
|
export const TamboClientContext = createContext(undefined);
|
|
7
7
|
/**
|
|
@@ -12,9 +12,10 @@ export const TamboClientContext = createContext(undefined);
|
|
|
12
12
|
* @param props.tamboUrl - The URL of the Tambo API
|
|
13
13
|
* @param props.apiKey - The API key for the Tambo API
|
|
14
14
|
* @param props.environment - The environment to use for the Tambo API
|
|
15
|
+
* @param props.userToken - The oauth access token to use to identify the user in the Tambo API
|
|
15
16
|
* @returns The TamboClientProvider component
|
|
16
17
|
*/
|
|
17
|
-
export const TamboClientProvider = ({ children, tamboUrl, apiKey, environment }) => {
|
|
18
|
+
export const TamboClientProvider = ({ children, tamboUrl, apiKey, environment, userToken }) => {
|
|
18
19
|
const tamboConfig = {
|
|
19
20
|
apiKey,
|
|
20
21
|
defaultHeaders: {
|
|
@@ -29,6 +30,8 @@ export const TamboClientProvider = ({ children, tamboUrl, apiKey, environment })
|
|
|
29
30
|
}
|
|
30
31
|
const [client] = useState(() => new TamboAI(tamboConfig));
|
|
31
32
|
const [queryClient] = useState(() => new QueryClient());
|
|
33
|
+
// Keep the session token updated
|
|
34
|
+
useTamboSessionToken(client, userToken);
|
|
32
35
|
return (React.createElement(TamboClientContext.Provider, { value: { client, queryClient } }, children));
|
|
33
36
|
};
|
|
34
37
|
/**
|
|
@@ -56,4 +59,51 @@ export const useTamboQueryClient = () => {
|
|
|
56
59
|
}
|
|
57
60
|
return context.queryClient;
|
|
58
61
|
};
|
|
62
|
+
function useTamboSessionToken(client, userToken) {
|
|
63
|
+
const [tamboSessionToken, setTamboSessionToken] = useState(null);
|
|
64
|
+
// we need to set this to true when the token is expired, this is effectively
|
|
65
|
+
// like a dirty bit, which will trigger a new useEffect()
|
|
66
|
+
const [isExpired, setIsExpired] = useState(true);
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
let expireTimer = null;
|
|
69
|
+
async function updateToken(subjectToken, abortController) {
|
|
70
|
+
if (abortController.signal.aborted || !userToken) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const tokenRequest = {
|
|
74
|
+
grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
|
|
75
|
+
subject_token: subjectToken,
|
|
76
|
+
subject_token_type: "urn:ietf:params:oauth:token-type:access_token",
|
|
77
|
+
};
|
|
78
|
+
const tokenRequestFormEncoded = new URLSearchParams(tokenRequest).toString();
|
|
79
|
+
const tokenAsArrayBuffer = new TextEncoder().encode(tokenRequestFormEncoded);
|
|
80
|
+
const tamboToken = await client.beta.auth.getToken(tokenAsArrayBuffer);
|
|
81
|
+
if (abortController.signal.aborted) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
setTamboSessionToken(tamboToken.access_token);
|
|
85
|
+
client.bearer = tamboToken.access_token;
|
|
86
|
+
// we need to set a timer to refresh the token when it expires
|
|
87
|
+
const refreshTime = Math.max(tamboToken.expires_in - 60, 0);
|
|
88
|
+
// careful with the assignment here: since this is an async function, this
|
|
89
|
+
// code is executed outside the of the scope of the useEffect() hook, so
|
|
90
|
+
// we need to use a let variable to store the timer
|
|
91
|
+
expireTimer = setTimeout(() => {
|
|
92
|
+
setIsExpired(true);
|
|
93
|
+
}, refreshTime * 1000);
|
|
94
|
+
}
|
|
95
|
+
const abortController = new AbortController();
|
|
96
|
+
if (userToken && isExpired) {
|
|
97
|
+
updateToken(userToken, abortController);
|
|
98
|
+
}
|
|
99
|
+
return () => {
|
|
100
|
+
// This fires when the component unmounts or the userToken changes
|
|
101
|
+
abortController.abort();
|
|
102
|
+
if (expireTimer) {
|
|
103
|
+
clearTimeout(expireTimer);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}, [client, isExpired, userToken]);
|
|
107
|
+
return tamboSessionToken;
|
|
108
|
+
}
|
|
59
109
|
//# sourceMappingURL=tambo-client-provider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-client-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,OAA0B,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"tambo-client-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\nimport TamboAI, { ClientOptions } from \"@tambo-ai/typescript-sdk\";\nimport { QueryClient } from \"@tanstack/react-query\";\nimport React, {\n createContext,\n PropsWithChildren,\n useEffect,\n useState,\n} from \"react\";\nimport packageJson from \"../../package.json\";\n\nexport interface TamboClientProviderProps {\n /**\n * The URL of the Tambo API (only used for local development and debugging)\n */\n tamboUrl?: string;\n /**\n * The API key for the Tambo API. This typically comes from a variable like\n * `process.env.NEXT_PUBLIC_TAMBO_API_KEY`\n */\n apiKey: string;\n /**\n * The environment to use for the Tambo API\n */\n environment?: \"production\" | \"staging\";\n\n /**\n * The user token to use to identify the user in the Tambo API. This token is\n * a 3rd party token like a Google or GitHub access token, exchanged with the\n * Tambo API to get a session token. This is used to securely identify the\n * user when calling the Tambo API.\n */\n userToken?: string;\n}\n\nexport interface TamboClientContextProps {\n /** The TamboAI client */\n client: TamboAI;\n /** The tambo-specific query client */\n queryClient: QueryClient;\n}\n\nexport const TamboClientContext = createContext<\n TamboClientContextProps | undefined\n>(undefined);\n\n/**\n * The TamboClientProvider is a React provider that provides a TamboAI client\n * and a query client to the descendants of the provider.\n * @param props - The props for the TamboClientProvider\n * @param props.children - The children to wrap\n * @param props.tamboUrl - The URL of the Tambo API\n * @param props.apiKey - The API key for the Tambo API\n * @param props.environment - The environment to use for the Tambo API\n * @param props.userToken - The oauth access token to use to identify the user in the Tambo API\n * @returns The TamboClientProvider component\n */\nexport const TamboClientProvider: React.FC<\n PropsWithChildren<TamboClientProviderProps>\n> = ({ children, tamboUrl, apiKey, environment, userToken }) => {\n const tamboConfig: ClientOptions = {\n apiKey,\n defaultHeaders: {\n \"X-Tambo-React-Version\": packageJson.version,\n },\n };\n if (tamboUrl) {\n tamboConfig.baseURL = tamboUrl;\n }\n if (environment) {\n tamboConfig.environment = environment;\n }\n const [client] = useState(() => new TamboAI(tamboConfig));\n const [queryClient] = useState(() => new QueryClient());\n\n // Keep the session token updated\n useTamboSessionToken(client, userToken);\n\n return (\n <TamboClientContext.Provider value={{ client, queryClient }}>\n {children}\n </TamboClientContext.Provider>\n );\n};\n\n/**\n * The useTamboClient hook provides access to the TamboAI client\n * to the descendants of the TamboClientProvider.\n * @returns The TamboAI client\n */\nexport const useTamboClient = () => {\n const context = React.useContext(TamboClientContext);\n if (context === undefined) {\n throw new Error(\"useTamboClient must be used within a TamboClientProvider\");\n }\n return context.client;\n};\n\n/**\n * The useTamboQueryClient hook provides access to the tambo-specific query client\n * to the descendants of the TamboClientProvider.\n * @returns The tambo-specific query client\n * @private\n */\nexport const useTamboQueryClient = () => {\n const context = React.useContext(TamboClientContext);\n if (context === undefined) {\n throw new Error(\n \"useTamboQueryClient must be used within a TamboClientProvider\",\n );\n }\n return context.queryClient;\n};\n\nfunction useTamboSessionToken(client: TamboAI, userToken: string | undefined) {\n const [tamboSessionToken, setTamboSessionToken] = useState<string | null>(\n null,\n );\n // we need to set this to true when the token is expired, this is effectively\n // like a dirty bit, which will trigger a new useEffect()\n const [isExpired, setIsExpired] = useState(true);\n useEffect(() => {\n let expireTimer: NodeJS.Timeout | null = null;\n\n async function updateToken(\n subjectToken: string,\n abortController: AbortController,\n ) {\n if (abortController.signal.aborted || !userToken) {\n return;\n }\n const tokenRequest = {\n grant_type: \"urn:ietf:params:oauth:grant-type:token-exchange\",\n subject_token: subjectToken,\n subject_token_type: \"urn:ietf:params:oauth:token-type:access_token\",\n };\n const tokenRequestFormEncoded = new URLSearchParams(\n tokenRequest,\n ).toString();\n const tokenAsArrayBuffer = new TextEncoder().encode(\n tokenRequestFormEncoded,\n );\n const tamboToken = await client.beta.auth.getToken(\n tokenAsArrayBuffer as any,\n );\n\n if (abortController.signal.aborted) {\n return;\n }\n setTamboSessionToken(tamboToken.access_token);\n client.bearer = tamboToken.access_token;\n\n // we need to set a timer to refresh the token when it expires\n const refreshTime = Math.max(tamboToken.expires_in - 60, 0);\n\n // careful with the assignment here: since this is an async function, this\n // code is executed outside the of the scope of the useEffect() hook, so\n // we need to use a let variable to store the timer\n expireTimer = setTimeout(() => {\n setIsExpired(true);\n }, refreshTime * 1000);\n }\n\n const abortController = new AbortController();\n if (userToken && isExpired) {\n updateToken(userToken, abortController);\n }\n\n return () => {\n // This fires when the component unmounts or the userToken changes\n abortController.abort();\n if (expireTimer) {\n clearTimeout(expireTimer);\n }\n };\n }, [client, isExpired, userToken]);\n\n return tamboSessionToken;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAA6B,MAAM,OAAO,CAAC;AAC5E,OAAO,EACL,uBAAuB,EAEvB,wBAAwB,EAGzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,0BAA0B,EAG3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,0BAA0B,EAC3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EAEvB,wBAAwB,EAEzB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAClC,iBAAiB,CACf,wBAAwB,GACtB,0BAA0B,GAC1B,wBAAwB,CAC3B,
|
|
1
|
+
{"version":3,"file":"tambo-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAA6B,MAAM,OAAO,CAAC;AAC5E,OAAO,EACL,uBAAuB,EAEvB,wBAAwB,EAGzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,0BAA0B,EAG3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,0BAA0B,EAC3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EAEvB,wBAAwB,EAEzB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAClC,iBAAiB,CACf,wBAAwB,GACtB,0BAA0B,GAC1B,wBAAwB,CAC3B,CAgCF,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG,uBAAuB,GACrD,uBAAuB,GACvB,0BAA0B,CAAC;AAE7B,eAAO,MAAM,YAAY,kCAExB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAoB9D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,yBAEpB,CAAC"}
|
|
@@ -17,12 +17,12 @@ import { TamboThreadProvider, useTamboThread, } from "./tambo-thread-provider";
|
|
|
17
17
|
* @param props.streaming - Whether to stream the response by default. Defaults to true.
|
|
18
18
|
* @returns The TamboProvider component
|
|
19
19
|
*/
|
|
20
|
-
export const TamboProvider = ({ children, tamboUrl, apiKey, components, environment, tools, streaming, }) => {
|
|
20
|
+
export const TamboProvider = ({ children, tamboUrl, apiKey, userToken, components, environment, tools, streaming, }) => {
|
|
21
21
|
// Should only be used in browser
|
|
22
22
|
if (typeof window === "undefined") {
|
|
23
23
|
console.error("TamboProvider must be used within a browser");
|
|
24
24
|
}
|
|
25
|
-
return (React.createElement(TamboClientProvider, { tamboUrl: tamboUrl, apiKey: apiKey, environment: environment },
|
|
25
|
+
return (React.createElement(TamboClientProvider, { tamboUrl: tamboUrl, apiKey: apiKey, environment: environment, userToken: userToken },
|
|
26
26
|
React.createElement(TamboRegistryProvider, { components: components, tools: tools },
|
|
27
27
|
React.createElement(TamboThreadProvider, { streaming: streaming },
|
|
28
28
|
React.createElement(TamboComponentProvider, null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-provider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,KAAK,EAAE,EAAqB,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC5E,OAAO,EAEL,mBAAmB,EAEnB,cAAc,EACd,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAEL,mBAAmB,EAEnB,cAAc,GACf,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,aAAa,GAMtB,CAAC,EACH,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,UAAU,EACV,WAAW,EACX,KAAK,EACL,SAAS,GACV,EAAE,EAAE;IACH,iCAAiC;IACjC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,CACL,oBAAC,mBAAmB,IAClB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW;
|
|
1
|
+
{"version":3,"file":"tambo-provider.js","sourceRoot":"","sources":["../../src/providers/tambo-provider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,KAAK,EAAE,EAAqB,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC5E,OAAO,EAEL,mBAAmB,EAEnB,cAAc,EACd,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAEL,mBAAmB,EAEnB,cAAc,GACf,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,aAAa,GAMtB,CAAC,EACH,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,SAAS,EACT,UAAU,EACV,WAAW,EACX,KAAK,EACL,SAAS,GACV,EAAE,EAAE;IACH,iCAAiC;IACjC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,CACL,oBAAC,mBAAmB,IAClB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS;QAEpB,oBAAC,qBAAqB,IAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK;YACzD,oBAAC,mBAAmB,IAAC,SAAS,EAAE,SAAS;gBACvC,oBAAC,sBAAsB;oBACrB,oBAAC,sBAAsB,QAAE,QAAQ,CAA0B,CACpC,CACL,CACA,CACJ,CACvB,CAAC;AACJ,CAAC,CAAC;AAKF,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CACvC,EAAuB,CACxB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAgC,CAAC,EAClE,QAAQ,GACT,EAAE,EAAE;IACH,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAC;IAC1C,MAAM,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IAE9C,OAAO,CACL,oBAAC,YAAY,CAAC,QAAQ,IACpB,KAAK,EAAE;YACL,MAAM;YACN,WAAW;YACX,GAAG,iBAAiB;YACpB,GAAG,OAAO;SACX,IAEA,QAAQ,CACa,CACzB,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,EAAE;IAC3B,OAAO,UAAU,CAAC,YAAY,CAAC,CAAC;AAClC,CAAC,CAAC","sourcesContent":["\"use client\";\nimport React, { PropsWithChildren, createContext, useContext } from \"react\";\nimport {\n TamboClientContextProps,\n TamboClientProvider,\n TamboClientProviderProps,\n useTamboClient,\n useTamboQueryClient,\n} from \"./tambo-client-provider\";\nimport {\n TamboComponentContextProps,\n TamboComponentProvider,\n useTamboComponent,\n} from \"./tambo-component-provider\";\nimport {\n TamboRegistryProvider,\n TamboRegistryProviderProps,\n} from \"./tambo-registry-provider\";\nimport {\n TamboThreadContextProps,\n TamboThreadProvider,\n TamboThreadProviderProps,\n useTamboThread,\n} from \"./tambo-thread-provider\";\n\n/**\n * The TamboProvider gives full access to the whole Tambo API. This includes the\n * TamboAI client, the component registry, and the current thread context.\n * @param props - The props for the TamboProvider\n * @param props.children - The children to wrap\n * @param props.tamboUrl - The URL of the Tambo API\n * @param props.apiKey - The API key for the Tambo API\n * @param props.components - The components to register\n * @param props.environment - The environment to use for the Tambo API\n * @param props.tools - The tools to register\n * @param props.streaming - Whether to stream the response by default. Defaults to true.\n * @returns The TamboProvider component\n */\nexport const TamboProvider: React.FC<\n PropsWithChildren<\n TamboClientProviderProps &\n TamboRegistryProviderProps &\n TamboThreadProviderProps\n >\n> = ({\n children,\n tamboUrl,\n apiKey,\n userToken,\n components,\n environment,\n tools,\n streaming,\n}) => {\n // Should only be used in browser\n if (typeof window === \"undefined\") {\n console.error(\"TamboProvider must be used within a browser\");\n }\n\n return (\n <TamboClientProvider\n tamboUrl={tamboUrl}\n apiKey={apiKey}\n environment={environment}\n userToken={userToken}\n >\n <TamboRegistryProvider components={components} tools={tools}>\n <TamboThreadProvider streaming={streaming}>\n <TamboComponentProvider>\n <TamboCompositeProvider>{children}</TamboCompositeProvider>\n </TamboComponentProvider>\n </TamboThreadProvider>\n </TamboRegistryProvider>\n </TamboClientProvider>\n );\n};\nexport type TamboContextProps = TamboClientContextProps &\n TamboThreadContextProps &\n TamboComponentContextProps;\n\nexport const TamboContext = createContext<TamboContextProps>(\n {} as TamboContextProps,\n);\n\n/**\n * TamboCompositeProvider is a provider that combines the TamboClient,\n * TamboThread, and TamboComponent providers\n * @param props - The props for the TamboCompositeProvider\n * @param props.children - The children to wrap\n * @returns The wrapped component\n */\nexport const TamboCompositeProvider: React.FC<PropsWithChildren> = ({\n children,\n}) => {\n const threads = useTamboThread();\n const client = useTamboClient();\n const queryClient = useTamboQueryClient();\n const componentRegistry = useTamboComponent();\n\n return (\n <TamboContext.Provider\n value={{\n client,\n queryClient,\n ...componentRegistry,\n ...threads,\n }}\n >\n {children}\n </TamboContext.Provider>\n );\n};\n\n/**\n * The useTambo hook provides access to the Tambo API. This is the primary entrypoint\n * for the Tambo React SDK.\n *\n * This includes the TamboAI client, the component registry, and the current thread context.\n * @returns The Tambo API\n */\nexport const useTambo = () => {\n return useContext(TamboContext);\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tambo-ai/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"description": "React client package for Tambo AI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
70
|
"@modelcontextprotocol/sdk": "^1.13.2",
|
|
71
|
-
"@tambo-ai/typescript-sdk": "^0.
|
|
71
|
+
"@tambo-ai/typescript-sdk": "^0.61.0",
|
|
72
72
|
"@tanstack/react-query": "^5.81.5",
|
|
73
73
|
"partial-json": "^0.1.7",
|
|
74
74
|
"react-fast-compare": "^3.2.2",
|