@tambo-ai/react 0.56.0 → 0.58.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/README.md +36 -0
- package/dist/hooks/react-query-hooks.d.ts +4 -4
- package/dist/hooks/react-query-hooks.js +4 -4
- package/dist/hooks/react-query-hooks.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.js +9 -0
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/model/component-metadata.d.ts +7 -0
- package/dist/model/component-metadata.d.ts.map +1 -1
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/providers/__tests__/tambo-thread-provider-initial-messages.test.d.ts +2 -0
- package/dist/providers/__tests__/tambo-thread-provider-initial-messages.test.d.ts.map +1 -0
- package/dist/providers/__tests__/tambo-thread-provider-initial-messages.test.js +179 -0
- package/dist/providers/__tests__/tambo-thread-provider-initial-messages.test.js.map +1 -0
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts +1 -0
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js +3 -2
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts +13 -0
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js +67 -23
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/testing/tools.d.ts +1 -0
- package/dist/testing/tools.d.ts.map +1 -1
- package/dist/util/__tests__/content-parts.test.d.ts +2 -0
- package/dist/util/__tests__/content-parts.test.d.ts.map +1 -0
- package/dist/util/__tests__/content-parts.test.js +47 -0
- package/dist/util/__tests__/content-parts.test.js.map +1 -0
- package/dist/util/content-parts.d.ts +19 -0
- package/dist/util/content-parts.d.ts.map +1 -0
- package/dist/util/content-parts.js +40 -0
- package/dist/util/content-parts.js.map +1 -0
- package/dist/util/tool-caller.d.ts +4 -3
- package/dist/util/tool-caller.d.ts.map +1 -1
- package/dist/util/tool-caller.js +9 -5
- package/dist/util/tool-caller.js.map +1 -1
- package/esm/hooks/react-query-hooks.d.ts +4 -4
- package/esm/hooks/react-query-hooks.js +4 -4
- package/esm/hooks/react-query-hooks.js.map +1 -1
- package/esm/index.d.ts +3 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.js +9 -0
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/model/component-metadata.d.ts +7 -0
- package/esm/model/component-metadata.d.ts.map +1 -1
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/providers/__tests__/tambo-thread-provider-initial-messages.test.d.ts +2 -0
- package/esm/providers/__tests__/tambo-thread-provider-initial-messages.test.d.ts.map +1 -0
- package/esm/providers/__tests__/tambo-thread-provider-initial-messages.test.js +174 -0
- package/esm/providers/__tests__/tambo-thread-provider-initial-messages.test.js.map +1 -0
- package/esm/providers/index.d.ts +1 -1
- package/esm/providers/index.d.ts.map +1 -1
- package/esm/providers/index.js.map +1 -1
- package/esm/providers/tambo-provider.d.ts +1 -0
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js +3 -2
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts +13 -0
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js +67 -23
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/testing/tools.d.ts +1 -0
- package/esm/testing/tools.d.ts.map +1 -1
- package/esm/util/__tests__/content-parts.test.d.ts +2 -0
- package/esm/util/__tests__/content-parts.test.d.ts.map +1 -0
- package/esm/util/__tests__/content-parts.test.js +45 -0
- package/esm/util/__tests__/content-parts.test.js.map +1 -0
- package/esm/util/content-parts.d.ts +19 -0
- package/esm/util/content-parts.d.ts.map +1 -0
- package/esm/util/content-parts.js +35 -0
- package/esm/util/content-parts.js.map +1 -0
- package/esm/util/tool-caller.d.ts +4 -3
- package/esm/util/tool-caller.d.ts.map +1 -1
- package/esm/util/tool-caller.js +9 -5
- package/esm/util/tool-caller.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { advanceStream } from "@tambo-ai/typescript-sdk";
|
|
2
|
+
import { act, renderHook } from "@testing-library/react";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { GenerationStage, } from "../../model/generate-component-response";
|
|
5
|
+
import { useTamboClient, useTamboQueryClient } from "../tambo-client-provider";
|
|
6
|
+
import { TamboContextHelpersProvider } from "../tambo-context-helpers-provider";
|
|
7
|
+
import { TamboRegistryProvider } from "../tambo-registry-provider";
|
|
8
|
+
import { TamboThreadProvider, useTamboThread } from "../tambo-thread-provider";
|
|
9
|
+
// Mock crypto.randomUUID
|
|
10
|
+
Object.defineProperty(global, "crypto", {
|
|
11
|
+
value: {
|
|
12
|
+
randomUUID: jest.fn().mockReturnValue("test-uuid"),
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
// Mock the required providers
|
|
16
|
+
jest.mock("../tambo-client-provider", () => ({
|
|
17
|
+
useTamboClient: jest.fn(),
|
|
18
|
+
useTamboQueryClient: jest.fn(),
|
|
19
|
+
}));
|
|
20
|
+
jest.mock("@tambo-ai/typescript-sdk", () => ({
|
|
21
|
+
advanceStream: jest.fn(),
|
|
22
|
+
}));
|
|
23
|
+
// Test utilities
|
|
24
|
+
const createMockMessage = (overrides = {}) => ({
|
|
25
|
+
id: "test-message-1",
|
|
26
|
+
content: [{ type: "text", text: "Hello" }],
|
|
27
|
+
role: "user",
|
|
28
|
+
threadId: "test-thread-1",
|
|
29
|
+
createdAt: new Date().toISOString(),
|
|
30
|
+
componentState: {},
|
|
31
|
+
...overrides,
|
|
32
|
+
});
|
|
33
|
+
// Test wrapper
|
|
34
|
+
const createWrapper = (initialMessages = []) => {
|
|
35
|
+
const TestWrapper = ({ children }) => (React.createElement(TamboRegistryProvider, { components: [], tools: [] },
|
|
36
|
+
React.createElement(TamboContextHelpersProvider, null,
|
|
37
|
+
React.createElement(TamboThreadProvider, { initialMessages: initialMessages }, children))));
|
|
38
|
+
TestWrapper.displayName = "TestWrapper";
|
|
39
|
+
return TestWrapper;
|
|
40
|
+
};
|
|
41
|
+
describe("TamboThreadProvider with initial messages", () => {
|
|
42
|
+
const mockClient = {
|
|
43
|
+
beta: {
|
|
44
|
+
threads: {
|
|
45
|
+
advance: jest.fn(),
|
|
46
|
+
advanceByID: jest.fn(),
|
|
47
|
+
cancel: jest.fn(),
|
|
48
|
+
messages: {
|
|
49
|
+
create: jest.fn(),
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
jest.clearAllMocks();
|
|
56
|
+
useTamboClient.mockReturnValue(mockClient);
|
|
57
|
+
// Provide a minimal mock for the query client used by the provider
|
|
58
|
+
const mockQueryClient = {
|
|
59
|
+
setQueryData: jest.fn(),
|
|
60
|
+
invalidateQueries: jest.fn(),
|
|
61
|
+
};
|
|
62
|
+
useTamboQueryClient.mockReturnValue(mockQueryClient);
|
|
63
|
+
advanceStream.mockImplementation(async function* () {
|
|
64
|
+
yield {
|
|
65
|
+
responseMessageDto: {
|
|
66
|
+
id: "response-1",
|
|
67
|
+
role: "assistant",
|
|
68
|
+
content: [{ type: "text", text: "Hello back!" }],
|
|
69
|
+
threadId: "new-thread-id",
|
|
70
|
+
componentState: {},
|
|
71
|
+
createdAt: new Date().toISOString(),
|
|
72
|
+
},
|
|
73
|
+
generationStage: GenerationStage.COMPLETE,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
it("should initialize with empty messages when no initial messages provided", () => {
|
|
78
|
+
const { result } = renderHook(() => useTamboThread(), {
|
|
79
|
+
wrapper: createWrapper(),
|
|
80
|
+
});
|
|
81
|
+
expect(result.current.thread.messages).toEqual([]);
|
|
82
|
+
});
|
|
83
|
+
it("should initialize with provided initial messages", () => {
|
|
84
|
+
const initialMessages = [
|
|
85
|
+
createMockMessage({
|
|
86
|
+
id: "initial-1",
|
|
87
|
+
role: "system",
|
|
88
|
+
content: [{ type: "text", text: "You are a helpful assistant." }],
|
|
89
|
+
}),
|
|
90
|
+
createMockMessage({
|
|
91
|
+
id: "initial-2",
|
|
92
|
+
role: "user",
|
|
93
|
+
content: [{ type: "text", text: "Hello!" }],
|
|
94
|
+
}),
|
|
95
|
+
];
|
|
96
|
+
const { result } = renderHook(() => useTamboThread(), {
|
|
97
|
+
wrapper: createWrapper(initialMessages),
|
|
98
|
+
});
|
|
99
|
+
expect(result.current.thread.messages).toHaveLength(2);
|
|
100
|
+
expect(result.current.thread.messages[0].content[0].text).toBe("You are a helpful assistant.");
|
|
101
|
+
expect(result.current.thread.messages[1].content[0].text).toBe("Hello!");
|
|
102
|
+
});
|
|
103
|
+
it("should include initial messages when sending a message to a new thread", async () => {
|
|
104
|
+
const initialMessages = [
|
|
105
|
+
createMockMessage({
|
|
106
|
+
id: "initial-1",
|
|
107
|
+
role: "system",
|
|
108
|
+
content: [{ type: "text", text: "You are a helpful assistant." }],
|
|
109
|
+
}),
|
|
110
|
+
];
|
|
111
|
+
const { result } = renderHook(() => useTamboThread(), {
|
|
112
|
+
wrapper: createWrapper(initialMessages),
|
|
113
|
+
});
|
|
114
|
+
await act(async () => {
|
|
115
|
+
await result.current.sendThreadMessage("Test message");
|
|
116
|
+
});
|
|
117
|
+
// Check that advanceStream was called with initial messages
|
|
118
|
+
expect(advanceStream).toHaveBeenCalledWith(mockClient, expect.objectContaining({
|
|
119
|
+
initialMessages: [
|
|
120
|
+
{
|
|
121
|
+
content: [{ type: "text", text: "You are a helpful assistant." }],
|
|
122
|
+
role: "system",
|
|
123
|
+
additionalContext: undefined,
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
}), undefined);
|
|
127
|
+
});
|
|
128
|
+
it("should not include initial messages when sending to an existing thread", async () => {
|
|
129
|
+
const initialMessages = [
|
|
130
|
+
createMockMessage({
|
|
131
|
+
id: "initial-1",
|
|
132
|
+
role: "system",
|
|
133
|
+
content: [{ type: "text", text: "You are a helpful assistant." }],
|
|
134
|
+
}),
|
|
135
|
+
];
|
|
136
|
+
const { result } = renderHook(() => useTamboThread(), {
|
|
137
|
+
wrapper: createWrapper(initialMessages),
|
|
138
|
+
});
|
|
139
|
+
// Switch to an existing thread first
|
|
140
|
+
await act(async () => {
|
|
141
|
+
result.current.switchCurrentThread("existing-thread-id", false);
|
|
142
|
+
});
|
|
143
|
+
await act(async () => {
|
|
144
|
+
await result.current.sendThreadMessage("Test message");
|
|
145
|
+
});
|
|
146
|
+
// Check that advanceStream was called without initial messages
|
|
147
|
+
expect(advanceStream).toHaveBeenCalledWith(mockClient, expect.not.objectContaining({
|
|
148
|
+
initialMessages: expect.anything(),
|
|
149
|
+
}), "existing-thread-id");
|
|
150
|
+
});
|
|
151
|
+
it("should reset to initial messages when starting a new thread", () => {
|
|
152
|
+
const initialMessages = [
|
|
153
|
+
createMockMessage({
|
|
154
|
+
id: "initial-1",
|
|
155
|
+
role: "system",
|
|
156
|
+
content: [{ type: "text", text: "You are a helpful assistant." }],
|
|
157
|
+
}),
|
|
158
|
+
];
|
|
159
|
+
const { result } = renderHook(() => useTamboThread(), {
|
|
160
|
+
wrapper: createWrapper(initialMessages),
|
|
161
|
+
});
|
|
162
|
+
// Switch to an existing thread
|
|
163
|
+
act(() => {
|
|
164
|
+
result.current.switchCurrentThread("existing-thread-id", false);
|
|
165
|
+
});
|
|
166
|
+
// Start a new thread
|
|
167
|
+
act(() => {
|
|
168
|
+
result.current.startNewThread();
|
|
169
|
+
});
|
|
170
|
+
expect(result.current.thread.messages).toHaveLength(1);
|
|
171
|
+
expect(result.current.thread.messages[0].content[0].text).toBe("You are a helpful assistant.");
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
//# sourceMappingURL=tambo-thread-provider-initial-messages.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tambo-thread-provider-initial-messages.test.js","sourceRoot":"","sources":["../../../src/providers/__tests__/tambo-thread-provider-initial-messages.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import TamboAI, { advanceStream } from \"@tambo-ai/typescript-sdk\";\nimport { act, renderHook } from \"@testing-library/react\";\nimport React from \"react\";\nimport { DeepPartial } from \"ts-essentials\";\nimport {\n GenerationStage,\n TamboThreadMessage,\n} from \"../../model/generate-component-response\";\nimport { useTamboClient, useTamboQueryClient } from \"../tambo-client-provider\";\nimport { TamboContextHelpersProvider } from \"../tambo-context-helpers-provider\";\nimport { TamboRegistryProvider } from \"../tambo-registry-provider\";\nimport { TamboThreadProvider, useTamboThread } from \"../tambo-thread-provider\";\n\ntype PartialTamboAI = DeepPartial<TamboAI>;\n\n// Mock crypto.randomUUID\nObject.defineProperty(global, \"crypto\", {\n value: {\n randomUUID: jest.fn().mockReturnValue(\"test-uuid\"),\n },\n});\n\n// Mock the required providers\njest.mock(\"../tambo-client-provider\", () => ({\n useTamboClient: jest.fn(),\n useTamboQueryClient: jest.fn(),\n}));\njest.mock(\"@tambo-ai/typescript-sdk\", () => ({\n advanceStream: jest.fn(),\n}));\n\n// Test utilities\nconst createMockMessage = (\n overrides: Partial<TamboThreadMessage> = {},\n): TamboThreadMessage => ({\n id: \"test-message-1\",\n content: [{ type: \"text\", text: \"Hello\" }],\n role: \"user\",\n threadId: \"test-thread-1\",\n createdAt: new Date().toISOString(),\n componentState: {},\n ...overrides,\n});\n\n// Test wrapper\nconst createWrapper = (initialMessages: TamboThreadMessage[] = []) => {\n const TestWrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider components={[]} tools={[]}>\n <TamboContextHelpersProvider>\n <TamboThreadProvider initialMessages={initialMessages}>\n {children}\n </TamboThreadProvider>\n </TamboContextHelpersProvider>\n </TamboRegistryProvider>\n );\n TestWrapper.displayName = \"TestWrapper\";\n return TestWrapper;\n};\n\ndescribe(\"TamboThreadProvider with initial messages\", () => {\n const mockClient: PartialTamboAI = {\n beta: {\n threads: {\n advance: jest.fn(),\n advanceByID: jest.fn(),\n cancel: jest.fn(),\n messages: {\n create: jest.fn(),\n },\n },\n },\n };\n\n beforeEach(() => {\n jest.clearAllMocks();\n (useTamboClient as jest.Mock).mockReturnValue(mockClient);\n // Provide a minimal mock for the query client used by the provider\n const mockQueryClient = {\n setQueryData: jest.fn(),\n invalidateQueries: jest.fn(),\n };\n (useTamboQueryClient as jest.Mock).mockReturnValue(mockQueryClient);\n (advanceStream as jest.Mock).mockImplementation(async function* () {\n yield {\n responseMessageDto: {\n id: \"response-1\",\n role: \"assistant\",\n content: [{ type: \"text\", text: \"Hello back!\" }],\n threadId: \"new-thread-id\",\n componentState: {},\n createdAt: new Date().toISOString(),\n },\n generationStage: GenerationStage.COMPLETE,\n };\n });\n });\n\n it(\"should initialize with empty messages when no initial messages provided\", () => {\n const { result } = renderHook(() => useTamboThread(), {\n wrapper: createWrapper(),\n });\n\n expect(result.current.thread.messages).toEqual([]);\n });\n\n it(\"should initialize with provided initial messages\", () => {\n const initialMessages: TamboThreadMessage[] = [\n createMockMessage({\n id: \"initial-1\",\n role: \"system\",\n content: [{ type: \"text\", text: \"You are a helpful assistant.\" }],\n }),\n createMockMessage({\n id: \"initial-2\",\n role: \"user\",\n content: [{ type: \"text\", text: \"Hello!\" }],\n }),\n ];\n\n const { result } = renderHook(() => useTamboThread(), {\n wrapper: createWrapper(initialMessages),\n });\n\n expect(result.current.thread.messages).toHaveLength(2);\n expect(result.current.thread.messages[0].content[0].text).toBe(\n \"You are a helpful assistant.\",\n );\n expect(result.current.thread.messages[1].content[0].text).toBe(\"Hello!\");\n });\n\n it(\"should include initial messages when sending a message to a new thread\", async () => {\n const initialMessages: TamboThreadMessage[] = [\n createMockMessage({\n id: \"initial-1\",\n role: \"system\",\n content: [{ type: \"text\", text: \"You are a helpful assistant.\" }],\n }),\n ];\n\n const { result } = renderHook(() => useTamboThread(), {\n wrapper: createWrapper(initialMessages),\n });\n\n await act(async () => {\n await result.current.sendThreadMessage(\"Test message\");\n });\n\n // Check that advanceStream was called with initial messages\n expect(advanceStream).toHaveBeenCalledWith(\n mockClient,\n expect.objectContaining({\n initialMessages: [\n {\n content: [{ type: \"text\", text: \"You are a helpful assistant.\" }],\n role: \"system\",\n additionalContext: undefined,\n },\n ],\n }),\n undefined,\n );\n });\n\n it(\"should not include initial messages when sending to an existing thread\", async () => {\n const initialMessages: TamboThreadMessage[] = [\n createMockMessage({\n id: \"initial-1\",\n role: \"system\",\n content: [{ type: \"text\", text: \"You are a helpful assistant.\" }],\n }),\n ];\n\n const { result } = renderHook(() => useTamboThread(), {\n wrapper: createWrapper(initialMessages),\n });\n\n // Switch to an existing thread first\n await act(async () => {\n result.current.switchCurrentThread(\"existing-thread-id\", false);\n });\n\n await act(async () => {\n await result.current.sendThreadMessage(\"Test message\");\n });\n\n // Check that advanceStream was called without initial messages\n expect(advanceStream).toHaveBeenCalledWith(\n mockClient,\n expect.not.objectContaining({\n initialMessages: expect.anything(),\n }),\n \"existing-thread-id\",\n );\n });\n\n it(\"should reset to initial messages when starting a new thread\", () => {\n const initialMessages: TamboThreadMessage[] = [\n createMockMessage({\n id: \"initial-1\",\n role: \"system\",\n content: [{ type: \"text\", text: \"You are a helpful assistant.\" }],\n }),\n ];\n\n const { result } = renderHook(() => useTamboThread(), {\n wrapper: createWrapper(initialMessages),\n });\n\n // Switch to an existing thread\n act(() => {\n result.current.switchCurrentThread(\"existing-thread-id\", false);\n });\n\n // Start a new thread\n act(() => {\n result.current.startNewThread();\n });\n\n expect(result.current.thread.messages).toHaveLength(1);\n expect(result.current.thread.messages[0].content[0].text).toBe(\n \"You are a helpful assistant.\",\n );\n });\n});\n"]}
|
package/esm/providers/index.d.ts
CHANGED
|
@@ -8,5 +8,5 @@ export { TamboContext, TamboProvider, useTambo } from "./tambo-provider";
|
|
|
8
8
|
export { TamboRegistryProvider, useTamboRegistry, type TamboRegistryContext, } from "./tambo-registry-provider";
|
|
9
9
|
export { TamboStubProvider, type TamboStubProviderProps } from "./tambo-stubs";
|
|
10
10
|
export { TamboThreadInputProvider, useTamboThreadInput, type TamboThreadInputContextProps, } from "./tambo-thread-input-provider";
|
|
11
|
-
export { TamboThreadContext, TamboThreadProvider, useTamboGenerationStage, useTamboThread, } from "./tambo-thread-provider";
|
|
11
|
+
export { TamboThreadContext, TamboThreadProvider, useTamboGenerationStage, useTamboThread, type TamboThreadProviderProps, } from "./tambo-thread-provider";
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EACtB,KAAK,+BAA+B,EACpC,KAAK,gCAAgC,GACtC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,uBAAuB,EACvB,cAAc,GACf,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,yBAAyB,EACzB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,oBAAoB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,4BAA4B,GAClC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EACtB,KAAK,+BAA+B,EACpC,KAAK,gCAAgC,GACtC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,uBAAuB,EACvB,cAAc,GACf,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,yBAAyB,EACzB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,oBAAoB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,4BAA4B,GAClC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,EACd,KAAK,wBAAwB,GAC9B,MAAM,yBAAyB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,GAGvB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,uBAAuB,EACvB,cAAc,GACf,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAA+B,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,GAEpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,GAGvB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,uBAAuB,EACvB,cAAc,GACf,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAA+B,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,GAEpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,GAEf,MAAM,yBAAyB,CAAC","sourcesContent":["export type { TamboComponent, TamboTool } from \"../model/component-metadata\";\nexport {\n TamboClientProvider,\n useIsTamboTokenUpdating,\n useTamboClient,\n} from \"./tambo-client-provider\";\nexport {\n TamboComponentProvider,\n useTamboComponent,\n} from \"./tambo-component-provider\";\nexport {\n TamboContextHelpersProvider,\n useTamboContextHelpers,\n type TamboContextHelpersContextProps,\n type TamboContextHelpersProviderProps,\n} from \"./tambo-context-helpers-provider\";\nexport {\n Pending,\n Streaming,\n Success,\n TamboPropStreamProvider,\n useTamboStream,\n} from \"./tambo-prop-stream-provider\";\nexport type {\n StreamStateComponentProps,\n StreamStatus,\n TamboPropStreamContextValue,\n} from \"./tambo-prop-stream-provider\";\nexport { TamboContext, TamboProvider, useTambo } from \"./tambo-provider\";\nexport {\n TamboRegistryProvider,\n useTamboRegistry,\n type TamboRegistryContext,\n} from \"./tambo-registry-provider\";\nexport { TamboStubProvider, type TamboStubProviderProps } from \"./tambo-stubs\";\nexport {\n TamboThreadInputProvider,\n useTamboThreadInput,\n type TamboThreadInputContextProps,\n} from \"./tambo-thread-input-provider\";\nexport {\n TamboThreadContext,\n TamboThreadProvider,\n useTamboGenerationStage,\n useTamboThread,\n type TamboThreadProviderProps,\n} from \"./tambo-thread-provider\";\n"]}
|
|
@@ -21,6 +21,7 @@ import { TamboGenerationStageContextProps, TamboThreadContextProps, TamboThreadP
|
|
|
21
21
|
* @param props.userToken - The user's OAuth token (access or ID) used to identify the user and exchange for a Tambo session token (preferred over contextKey)
|
|
22
22
|
* @param props.contextKey - Optional context key to be used in the thread input provider
|
|
23
23
|
* @param props.onCallUnregisteredTool - Callback function called when an unregistered tool is called
|
|
24
|
+
* @param props.initialMessages - Initial messages to be included in new threads
|
|
24
25
|
* @returns The TamboProvider component
|
|
25
26
|
*/
|
|
26
27
|
export declare const TamboProvider: React.FC<PropsWithChildren<TamboClientProviderProps & TamboRegistryProviderProps & TamboThreadProviderProps & TamboContextHelpersProviderProps & TamboThreadInputProviderProps>>;
|
|
@@ -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,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EACL,uBAAuB,EAEvB,wBAAwB,EAIzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,0BAA0B,EAG3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,+BAA+B,EAE/B,gCAAgC,EAEjC,MAAM,kCAAkC,CAAC;AAK1C,OAAO,EAEL,0BAA0B,EAC3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAEL,6BAA6B,EAC9B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,gCAAgC,EAChC,uBAAuB,EAEvB,wBAAwB,EAEzB,MAAM,yBAAyB,CAAC;AAEjC
|
|
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,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EACL,uBAAuB,EAEvB,wBAAwB,EAIzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,0BAA0B,EAG3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,+BAA+B,EAE/B,gCAAgC,EAEjC,MAAM,kCAAkC,CAAC;AAK1C,OAAO,EAEL,0BAA0B,EAC3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAEL,6BAA6B,EAC9B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,gCAAgC,EAChC,uBAAuB,EAEvB,wBAAwB,EAEzB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAClC,iBAAiB,CACf,wBAAwB,GACtB,0BAA0B,GAC1B,wBAAwB,GACxB,gCAAgC,GAChC,6BAA6B,CAChC,CAiDF,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,uBAAuB,GACrD,uBAAuB,GACvB,gCAAgC,GAChC,0BAA0B,GAC1B,wBAAwB,GACxB,+BAA+B,CAAC;AAElC,eAAO,MAAM,YAAY,kCAExB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA0B9D,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,yBAEpB,CAAC"}
|
|
@@ -22,9 +22,10 @@ import { TamboThreadProvider, useTamboThread, } from "./tambo-thread-provider";
|
|
|
22
22
|
* @param props.userToken - The user's OAuth token (access or ID) used to identify the user and exchange for a Tambo session token (preferred over contextKey)
|
|
23
23
|
* @param props.contextKey - Optional context key to be used in the thread input provider
|
|
24
24
|
* @param props.onCallUnregisteredTool - Callback function called when an unregistered tool is called
|
|
25
|
+
* @param props.initialMessages - Initial messages to be included in new threads
|
|
25
26
|
* @returns The TamboProvider component
|
|
26
27
|
*/
|
|
27
|
-
export const TamboProvider = ({ children, tamboUrl, apiKey, userToken, components, environment, tools, streaming, contextHelpers, contextKey, onCallUnregisteredTool, }) => {
|
|
28
|
+
export const TamboProvider = ({ children, tamboUrl, apiKey, userToken, components, environment, tools, streaming, contextHelpers, contextKey, initialMessages, onCallUnregisteredTool, }) => {
|
|
28
29
|
// Should only be used in browser
|
|
29
30
|
if (typeof window === "undefined") {
|
|
30
31
|
console.error("TamboProvider must be used within a browser");
|
|
@@ -32,7 +33,7 @@ export const TamboProvider = ({ children, tamboUrl, apiKey, userToken, component
|
|
|
32
33
|
return (React.createElement(TamboClientProvider, { tamboUrl: tamboUrl, apiKey: apiKey, environment: environment, userToken: userToken },
|
|
33
34
|
React.createElement(TamboRegistryProvider, { components: components, tools: tools, onCallUnregisteredTool: onCallUnregisteredTool },
|
|
34
35
|
React.createElement(TamboContextHelpersProvider, { contextHelpers: contextHelpers },
|
|
35
|
-
React.createElement(TamboThreadProvider, { streaming: streaming },
|
|
36
|
+
React.createElement(TamboThreadProvider, { streaming: streaming, initialMessages: initialMessages },
|
|
36
37
|
React.createElement(TamboThreadInputProvider, { contextKey: contextKey },
|
|
37
38
|
React.createElement(TamboComponentProvider, null,
|
|
38
39
|
React.createElement(TamboInteractableProvider, 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;AAE5E,OAAO,EAEL,mBAAmB,EAEnB,uBAAuB,EACvB,cAAc,EACd,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,2BAA2B,EAE3B,sBAAsB,GACvB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,wBAAwB,GAEzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGL,mBAAmB,EAEnB,cAAc,GACf,MAAM,yBAAyB,CAAC;AAEjC
|
|
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;AAE5E,OAAO,EAEL,mBAAmB,EAEnB,uBAAuB,EACvB,cAAc,EACd,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,2BAA2B,EAE3B,sBAAsB,GACvB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,wBAAwB,GAEzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGL,mBAAmB,EAEnB,cAAc,GACf,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,aAAa,GAQtB,CAAC,EACH,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,SAAS,EACT,UAAU,EACV,WAAW,EACX,KAAK,EACL,SAAS,EACT,cAAc,EACd,UAAU,EACV,eAAe,EACf,sBAAsB,GACvB,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,IACpB,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,KAAK,EACZ,sBAAsB,EAAE,sBAAsB;YAE9C,oBAAC,2BAA2B,IAAC,cAAc,EAAE,cAAc;gBACzD,oBAAC,mBAAmB,IAClB,SAAS,EAAE,SAAS,EACpB,eAAe,EAAE,eAAe;oBAEhC,oBAAC,wBAAwB,IAAC,UAAU,EAAE,UAAU;wBAC9C,oBAAC,sBAAsB;4BACrB,oBAAC,yBAAyB;gCACxB,oBAAC,sBAAsB,QAAE,QAAQ,CAA0B,CACjC,CACL,CACA,CACP,CACM,CACR,CACJ,CACvB,CAAC;AACJ,CAAC,CAAC;AASF,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,eAAe,GAAG,uBAAuB,EAAE,CAAC;IAClD,MAAM,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IAC9C,MAAM,sBAAsB,GAAG,oBAAoB,EAAE,CAAC;IACtD,MAAM,cAAc,GAAG,sBAAsB,EAAE,CAAC;IAEhD,OAAO,CACL,oBAAC,YAAY,CAAC,QAAQ,IACpB,KAAK,EAAE;YACL,MAAM;YACN,WAAW;YACX,eAAe;YACf,GAAG,iBAAiB;YACpB,GAAG,OAAO;YACV,GAAG,sBAAsB;YACzB,GAAG,cAAc;SAClB,IAEA,QAAQ,CACa,CACzB,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;GAOG;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 { TamboInteractableContext } from \"../model/tambo-interactable\";\nimport {\n TamboClientContextProps,\n TamboClientProvider,\n TamboClientProviderProps,\n useIsTamboTokenUpdating,\n useTamboClient,\n useTamboQueryClient,\n} from \"./tambo-client-provider\";\nimport {\n TamboComponentContextProps,\n TamboComponentProvider,\n useTamboComponent,\n} from \"./tambo-component-provider\";\nimport {\n TamboContextHelpersContextProps,\n TamboContextHelpersProvider,\n TamboContextHelpersProviderProps,\n useTamboContextHelpers,\n} from \"./tambo-context-helpers-provider\";\nimport {\n TamboInteractableProvider,\n useTamboInteractable,\n} from \"./tambo-interactable-provider\";\nimport {\n TamboRegistryProvider,\n TamboRegistryProviderProps,\n} from \"./tambo-registry-provider\";\nimport {\n TamboThreadInputProvider,\n TamboThreadInputProviderProps,\n} from \"./tambo-thread-input-provider\";\nimport {\n TamboGenerationStageContextProps,\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, the current thread context, and interactable components.\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 * @param props.contextHelpers - Configuration for which context helpers are enabled/disabled\n * @param props.userToken - The user's OAuth token (access or ID) used to identify the user and exchange for a Tambo session token (preferred over contextKey)\n * @param props.contextKey - Optional context key to be used in the thread input provider\n * @param props.onCallUnregisteredTool - Callback function called when an unregistered tool is called\n * @param props.initialMessages - Initial messages to be included in new threads\n * @returns The TamboProvider component\n */\nexport const TamboProvider: React.FC<\n PropsWithChildren<\n TamboClientProviderProps &\n TamboRegistryProviderProps &\n TamboThreadProviderProps &\n TamboContextHelpersProviderProps &\n TamboThreadInputProviderProps\n >\n> = ({\n children,\n tamboUrl,\n apiKey,\n userToken,\n components,\n environment,\n tools,\n streaming,\n contextHelpers,\n contextKey,\n initialMessages,\n onCallUnregisteredTool,\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\n components={components}\n tools={tools}\n onCallUnregisteredTool={onCallUnregisteredTool}\n >\n <TamboContextHelpersProvider contextHelpers={contextHelpers}>\n <TamboThreadProvider\n streaming={streaming}\n initialMessages={initialMessages}\n >\n <TamboThreadInputProvider contextKey={contextKey}>\n <TamboComponentProvider>\n <TamboInteractableProvider>\n <TamboCompositeProvider>{children}</TamboCompositeProvider>\n </TamboInteractableProvider>\n </TamboComponentProvider>\n </TamboThreadInputProvider>\n </TamboThreadProvider>\n </TamboContextHelpersProvider>\n </TamboRegistryProvider>\n </TamboClientProvider>\n );\n};\n\nexport type TamboContextProps = TamboClientContextProps &\n TamboThreadContextProps &\n TamboGenerationStageContextProps &\n TamboComponentContextProps &\n TamboInteractableContext &\n TamboContextHelpersContextProps;\n\nexport const TamboContext = createContext<TamboContextProps>(\n {} as TamboContextProps,\n);\n\n/**\n * TamboCompositeProvider is a provider that combines the TamboClient,\n * TamboThread, TamboComponent, and TamboInteractable 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 isUpdatingToken = useIsTamboTokenUpdating();\n const componentRegistry = useTamboComponent();\n const interactableComponents = useTamboInteractable();\n const contextHelpers = useTamboContextHelpers();\n\n return (\n <TamboContext.Provider\n value={{\n client,\n queryClient,\n isUpdatingToken,\n ...componentRegistry,\n ...threads,\n ...interactableComponents,\n ...contextHelpers,\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, the current thread context,\n * and interactable component management.\n * @returns The Tambo API\n */\nexport const useTambo = () => {\n return useContext(TamboContext);\n};\n"]}
|
|
@@ -65,9 +65,21 @@ export interface CombinedTamboThreadContextProps extends TamboThreadContextProps
|
|
|
65
65
|
*/
|
|
66
66
|
export declare const PLACEHOLDER_THREAD: TamboThread;
|
|
67
67
|
export declare const TamboThreadContext: React.Context<TamboThreadContextProps>;
|
|
68
|
+
export type InitialTamboThreadMessage = Pick<TamboThreadMessage, "role" | "content"> & {
|
|
69
|
+
/** Optional ID - will be auto-generated if not provided */
|
|
70
|
+
id?: string;
|
|
71
|
+
/** Optional creation timestamp - will be auto-generated if not provided */
|
|
72
|
+
createdAt?: string;
|
|
73
|
+
/** Optional additional context to include with the message */
|
|
74
|
+
additionalContext?: Record<string, any>;
|
|
75
|
+
/** Optional component state - will default to empty object if not provided */
|
|
76
|
+
componentState?: Record<string, any>;
|
|
77
|
+
};
|
|
68
78
|
export interface TamboThreadProviderProps {
|
|
69
79
|
/** Whether to stream the response */
|
|
70
80
|
streaming?: boolean;
|
|
81
|
+
/** Initial messages to be included in new threads */
|
|
82
|
+
initialMessages?: InitialTamboThreadMessage[];
|
|
71
83
|
}
|
|
72
84
|
/**
|
|
73
85
|
* The TamboThreadProvider is a React provider that provides a thread context
|
|
@@ -75,6 +87,7 @@ export interface TamboThreadProviderProps {
|
|
|
75
87
|
* @param props - The props for the TamboThreadProvider
|
|
76
88
|
* @param props.children - The children to wrap
|
|
77
89
|
* @param props.streaming - Whether to stream the response by default. Defaults to true.
|
|
90
|
+
* @param props.initialMessages - Initial messages to be included in new threads
|
|
78
91
|
* @returns The TamboThreadProvider component
|
|
79
92
|
*/
|
|
80
93
|
export declare const TamboThreadProvider: React.FC<PropsWithChildren<TamboThreadProviderProps>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-thread-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-thread-provider.tsx"],"names":[],"mappings":"AACA,OAAO,OAA0B,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,yDAAyD,CAAC;AACjF,OAAO,KAAK,EAAE,EAEZ,iBAAiB,EAOlB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"tambo-thread-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-thread-provider.tsx"],"names":[],"mappings":"AACA,OAAO,OAA0B,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,yDAAyD,CAAC;AACjF,OAAO,KAAK,EAAE,EAEZ,iBAAiB,EAOlB,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,eAAe,EAEf,kBAAkB,EACnB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAcpD,MAAM,WAAW,gCAAgC;IAC/C,eAAe,EAAE,eAAe,CAAC;IACjC,uBAAuB,EAAE,MAAM,CAAC;IAChC,MAAM,EAAE,OAAO,CAAC;CACjB;AAMD,UAAU,iCAAiC;IACzC,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,EAAE,KAAK,CAAC,EAAE,CACjD,iBAAiB,CAAC,iCAAiC,CAAC,CAiBrD,CAAC;AAGF,KAAK,qCAAqC,GAAG,OAAO,CAAC,kBAAkB,CAAC,GAAG;IACzE,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,yBAAyB;IACzB,MAAM,EAAE,WAAW,CAAC;IACpB,mCAAmC;IACnC,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjE,yBAAyB;IACzB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,6BAA6B;IAC7B,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,gFAAgF;IAChF,kBAAkB,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,0CAA0C;IAC1C,gBAAgB,EAAE,CAChB,OAAO,EAAE,kBAAkB,EAC3B,YAAY,EAAE,OAAO,KAClB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IACnD,6CAA6C;IAC7C,mBAAmB,EAAE,CACnB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,qCAAqC,EAC9C,YAAY,EAAE,OAAO,KAClB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,sBAAsB;IACtB,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,sCAAsC;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,2CAA2C;IAC3C,iBAAiB,EAAE,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,OAAO,CAAC;QACzB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACxC,OAAO,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,yBAAyB,EAAE,CAAC;KAC5D,KACE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAClC;AAGD,MAAM,WAAW,+BACf,SAAQ,uBAAuB,EAC7B,gCAAgC;CAAG;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAOhC,CAAC;AAEF,eAAO,MAAM,kBAAkB,wCAmD7B,CAAC;AAEH,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC1C,kBAAkB,EAClB,MAAM,GAAG,SAAS,CACnB,GAAG;IACF,2DAA2D;IAC3D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACxC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,qCAAqC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qDAAqD;IACrD,eAAe,CAAC,EAAE,yBAAyB,EAAE,CAAC;CAC/C;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CACxC,iBAAiB,CAAC,wBAAwB,CAAC,CAi2B5C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,QAAO,gCAU1C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAAO,+BAgBjC,CAAC"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { advanceStream } from "@tambo-ai/typescript-sdk";
|
|
3
3
|
import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
|
|
4
4
|
import { GenerationStage, isIdleStage, } from "../model/generate-component-response";
|
|
5
|
+
import { toText } from "../util/content-parts";
|
|
5
6
|
import { renderComponentIntoMessage } from "../util/generate-component";
|
|
6
7
|
import { getAvailableComponents, getUnassociatedTools, mapTamboToolToContextTool, } from "../util/registry";
|
|
7
8
|
import { handleToolCall } from "../util/tool-caller";
|
|
@@ -102,11 +103,27 @@ export const TamboThreadContext = createContext({
|
|
|
102
103
|
* @param props - The props for the TamboThreadProvider
|
|
103
104
|
* @param props.children - The children to wrap
|
|
104
105
|
* @param props.streaming - Whether to stream the response by default. Defaults to true.
|
|
106
|
+
* @param props.initialMessages - Initial messages to be included in new threads
|
|
105
107
|
* @returns The TamboThreadProvider component
|
|
106
108
|
*/
|
|
107
|
-
export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
109
|
+
export const TamboThreadProvider = ({ children, streaming = true, initialMessages = [] }) => {
|
|
110
|
+
// Create placeholder thread with initial messages
|
|
111
|
+
const placeholderThread = useMemo(() => ({
|
|
112
|
+
id: "placeholder",
|
|
113
|
+
messages: initialMessages.map((msg) => ({
|
|
114
|
+
...msg,
|
|
115
|
+
id: msg.id ?? crypto.randomUUID(),
|
|
116
|
+
threadId: "placeholder",
|
|
117
|
+
createdAt: msg.createdAt ?? new Date().toISOString(),
|
|
118
|
+
componentState: msg.componentState ?? {},
|
|
119
|
+
})),
|
|
120
|
+
createdAt: "",
|
|
121
|
+
projectId: "",
|
|
122
|
+
updatedAt: "",
|
|
123
|
+
metadata: {},
|
|
124
|
+
}), [initialMessages]);
|
|
108
125
|
const [threadMap, setThreadMap] = useState({
|
|
109
|
-
[
|
|
126
|
+
[placeholderThread.id]: placeholderThread,
|
|
110
127
|
});
|
|
111
128
|
const client = useTamboClient();
|
|
112
129
|
const queryClient = useTamboQueryClient();
|
|
@@ -114,7 +131,7 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
114
131
|
const { getAdditionalContext } = useTamboContextHelpers();
|
|
115
132
|
const [ignoreResponse, setIgnoreResponse] = useState(false);
|
|
116
133
|
const ignoreResponseRef = useRef(ignoreResponse);
|
|
117
|
-
const [currentThreadId, setCurrentThreadId] = useState(
|
|
134
|
+
const [currentThreadId, setCurrentThreadId] = useState(placeholderThread.id);
|
|
118
135
|
const currentThread = threadMap[currentThreadId];
|
|
119
136
|
// Generation stage props for GenerationStageProvider
|
|
120
137
|
const currentGenerationStage = currentThread?.generationStage ?? GenerationStage.IDLE;
|
|
@@ -184,11 +201,11 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
184
201
|
}, [client.beta.threads, componentList, currentMessageCache]);
|
|
185
202
|
useEffect(() => {
|
|
186
203
|
if (currentThreadId &&
|
|
187
|
-
currentThreadId !==
|
|
204
|
+
currentThreadId !== placeholderThread.id &&
|
|
188
205
|
!threadMap[currentThreadId]) {
|
|
189
206
|
fetchThread(currentThreadId);
|
|
190
207
|
}
|
|
191
|
-
}, [currentThreadId, fetchThread, threadMap]);
|
|
208
|
+
}, [currentThreadId, fetchThread, threadMap, placeholderThread.id]);
|
|
192
209
|
const addThreadMessage = useCallback(async (message, sendToServer = true, createdAt = new Date().toISOString()) => {
|
|
193
210
|
if (!currentThread) {
|
|
194
211
|
console.warn("Cannot add messages if we do not have a current thread");
|
|
@@ -269,14 +286,14 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
269
286
|
}
|
|
270
287
|
}, [client.beta.threads.messages]);
|
|
271
288
|
const startNewThread = useCallback(() => {
|
|
272
|
-
setCurrentThreadId(
|
|
289
|
+
setCurrentThreadId(placeholderThread.id);
|
|
273
290
|
setThreadMap((prevMap) => {
|
|
274
291
|
return {
|
|
275
292
|
...prevMap,
|
|
276
|
-
[
|
|
293
|
+
[placeholderThread.id]: placeholderThread,
|
|
277
294
|
};
|
|
278
295
|
});
|
|
279
|
-
}, []);
|
|
296
|
+
}, [placeholderThread]);
|
|
280
297
|
const updateThreadName = useCallback(async (name, threadId) => {
|
|
281
298
|
threadId ??= currentThreadId;
|
|
282
299
|
setThreadMap((prevMap) => {
|
|
@@ -285,17 +302,22 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
285
302
|
}
|
|
286
303
|
return { ...prevMap, [threadId]: { ...prevMap[threadId], name } };
|
|
287
304
|
});
|
|
288
|
-
if (threadId !==
|
|
305
|
+
if (threadId !== placeholderThread.id) {
|
|
289
306
|
const currentProject = await client.beta.projects.getCurrent();
|
|
290
307
|
await client.beta.threads.update(threadId, {
|
|
291
308
|
name,
|
|
292
309
|
projectId: currentProject.id,
|
|
293
310
|
});
|
|
294
311
|
}
|
|
295
|
-
}, [
|
|
312
|
+
}, [
|
|
313
|
+
currentThreadId,
|
|
314
|
+
client.beta.projects,
|
|
315
|
+
client.beta.threads,
|
|
316
|
+
placeholderThread.id,
|
|
317
|
+
]);
|
|
296
318
|
const generateThreadName = useCallback(async (threadId) => {
|
|
297
319
|
threadId ??= currentThreadId;
|
|
298
|
-
if (threadId ===
|
|
320
|
+
if (threadId === placeholderThread.id) {
|
|
299
321
|
console.warn("Cannot generate name for empty thread");
|
|
300
322
|
return threadMap[threadId];
|
|
301
323
|
}
|
|
@@ -313,9 +335,9 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
313
335
|
};
|
|
314
336
|
});
|
|
315
337
|
return threadWithGeneratedName;
|
|
316
|
-
}, [client.beta.threads, currentThreadId, threadMap]);
|
|
338
|
+
}, [client.beta.threads, currentThreadId, threadMap, placeholderThread.id]);
|
|
317
339
|
const switchCurrentThread = useCallback(async (threadId, fetch = true) => {
|
|
318
|
-
if (threadId ===
|
|
340
|
+
if (threadId === placeholderThread.id) {
|
|
319
341
|
console.warn("Switching to placeholder thread, may be a bug.");
|
|
320
342
|
return;
|
|
321
343
|
}
|
|
@@ -328,7 +350,7 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
328
350
|
const updatedThreadMap = {
|
|
329
351
|
...prevMap,
|
|
330
352
|
[threadId]: {
|
|
331
|
-
...prevMap[
|
|
353
|
+
...prevMap[placeholderThread.id],
|
|
332
354
|
id: threadId,
|
|
333
355
|
},
|
|
334
356
|
};
|
|
@@ -337,7 +359,7 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
337
359
|
if (fetch) {
|
|
338
360
|
await fetchThread(threadId);
|
|
339
361
|
}
|
|
340
|
-
}, [fetchThread]);
|
|
362
|
+
}, [fetchThread, placeholderThread]);
|
|
341
363
|
const updateThreadStatus = useCallback((threadId, stage, statusMessage) => {
|
|
342
364
|
setThreadMap((prevMap) => {
|
|
343
365
|
const updatedThreadMap = {
|
|
@@ -525,7 +547,7 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
525
547
|
]);
|
|
526
548
|
const sendThreadMessage = useCallback(async (message, options = {}) => {
|
|
527
549
|
setIgnoreResponse(false);
|
|
528
|
-
const { threadId = currentThreadId ??
|
|
550
|
+
const { threadId = currentThreadId ?? placeholderThread.id, streamResponse = streaming, forceToolChoice, contextKey, additionalContext, content, } = options;
|
|
529
551
|
updateThreadStatus(threadId, GenerationStage.FETCHING_CONTEXT);
|
|
530
552
|
// Get additional context from enabled helpers
|
|
531
553
|
const helperContexts = await getAdditionalContext();
|
|
@@ -566,11 +588,19 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
566
588
|
clientTools: unassociatedTools.map((tool) => mapTamboToolToContextTool(tool)),
|
|
567
589
|
forceToolChoice: forceToolChoice,
|
|
568
590
|
toolCallCounts,
|
|
591
|
+
...(threadId === placeholderThread.id &&
|
|
592
|
+
initialMessages.length > 0 && {
|
|
593
|
+
initialMessages: initialMessages.map((msg) => ({
|
|
594
|
+
content: msg.content,
|
|
595
|
+
role: msg.role,
|
|
596
|
+
additionalContext: msg.additionalContext,
|
|
597
|
+
})),
|
|
598
|
+
}),
|
|
569
599
|
};
|
|
570
600
|
if (streamResponse) {
|
|
571
601
|
let advanceStreamResponse;
|
|
572
602
|
try {
|
|
573
|
-
advanceStreamResponse = await advanceStream(client, params, threadId ===
|
|
603
|
+
advanceStreamResponse = await advanceStream(client, params, threadId === placeholderThread.id ? undefined : threadId);
|
|
574
604
|
}
|
|
575
605
|
catch (error) {
|
|
576
606
|
updateThreadStatus(threadId, GenerationStage.ERROR);
|
|
@@ -586,7 +616,7 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
586
616
|
}
|
|
587
617
|
let advanceResponse;
|
|
588
618
|
try {
|
|
589
|
-
advanceResponse = await (threadId ===
|
|
619
|
+
advanceResponse = await (threadId === placeholderThread.id
|
|
590
620
|
? client.beta.threads.advance(params)
|
|
591
621
|
: client.beta.threads.advanceByID(threadId, params));
|
|
592
622
|
}
|
|
@@ -604,14 +634,12 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
604
634
|
}
|
|
605
635
|
updateThreadStatus(threadId, GenerationStage.FETCHING_CONTEXT);
|
|
606
636
|
const toolCallResponse = await handleToolCall(advanceResponse.responseMessageDto, toolRegistry, onCallUnregisteredTool);
|
|
607
|
-
const
|
|
608
|
-
? toolCallResponse.result
|
|
609
|
-
: JSON.stringify(toolCallResponse.result);
|
|
637
|
+
const contentParts = convertToolResponse(toolCallResponse);
|
|
610
638
|
const toolCallResponseParams = {
|
|
611
639
|
...params,
|
|
612
640
|
messageToAppend: {
|
|
613
641
|
...params.messageToAppend,
|
|
614
|
-
content:
|
|
642
|
+
content: contentParts,
|
|
615
643
|
role: "tool",
|
|
616
644
|
actionType: "tool_response",
|
|
617
645
|
component: advanceResponse.responseMessageDto.component,
|
|
@@ -630,7 +658,7 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
630
658
|
updateThreadStatus(threadId, GenerationStage.HYDRATING_COMPONENT);
|
|
631
659
|
addThreadMessage({
|
|
632
660
|
threadId: threadId,
|
|
633
|
-
content:
|
|
661
|
+
content: contentParts,
|
|
634
662
|
role: "tool",
|
|
635
663
|
id: crypto.randomUUID(),
|
|
636
664
|
createdAt: new Date().toISOString(),
|
|
@@ -672,6 +700,8 @@ export const TamboThreadProvider = ({ children, streaming = true }) => {
|
|
|
672
700
|
handleAdvanceStream,
|
|
673
701
|
streaming,
|
|
674
702
|
getAdditionalContext,
|
|
703
|
+
placeholderThread.id,
|
|
704
|
+
initialMessages,
|
|
675
705
|
onCallUnregisteredTool,
|
|
676
706
|
refetchThreadsList,
|
|
677
707
|
]);
|
|
@@ -720,4 +750,18 @@ export const useTamboThread = () => {
|
|
|
720
750
|
...generationStageContext,
|
|
721
751
|
};
|
|
722
752
|
};
|
|
753
|
+
function convertToolResponse(toolCallResponse) {
|
|
754
|
+
// If the tool call errored, surface that as text so the model reliably sees the error
|
|
755
|
+
if (toolCallResponse.error) {
|
|
756
|
+
return [{ type: "text", text: toText(toolCallResponse.result) }];
|
|
757
|
+
}
|
|
758
|
+
// Use custom transform when available
|
|
759
|
+
if (toolCallResponse.tamboTool?.transformToContent) {
|
|
760
|
+
return toolCallResponse.tamboTool.transformToContent(
|
|
761
|
+
// result shape is user-defined; let the transform decide how to handle it
|
|
762
|
+
toolCallResponse.result);
|
|
763
|
+
}
|
|
764
|
+
// Default fallback to stringified text
|
|
765
|
+
return [{ type: "text", text: toText(toolCallResponse.result) }];
|
|
766
|
+
}
|
|
723
767
|
//# sourceMappingURL=tambo-thread-provider.js.map
|