@tambo-ai/react 0.20.2 → 0.20.4
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/hooks/__tests__/use-suggestions.test.js +66 -23
- package/dist/hooks/__tests__/use-suggestions.test.js.map +1 -1
- package/dist/hooks/__tests__/use-tambo-threads.test.d.ts +2 -0
- package/dist/hooks/__tests__/use-tambo-threads.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/use-tambo-threads.test.js +212 -0
- package/dist/hooks/__tests__/use-tambo-threads.test.js.map +1 -0
- package/dist/hooks/react-query-hooks.d.ts +0 -8
- package/dist/hooks/react-query-hooks.d.ts.map +1 -1
- package/dist/hooks/react-query-hooks.js +0 -11
- package/dist/hooks/react-query-hooks.js.map +1 -1
- package/dist/hooks/use-suggestions.js +2 -2
- package/dist/hooks/use-suggestions.js.map +1 -1
- package/dist/hooks/use-tambo-threads.d.ts +13 -11
- package/dist/hooks/use-tambo-threads.d.ts.map +1 -1
- package/dist/hooks/use-tambo-threads.js +3 -1
- package/dist/hooks/use-tambo-threads.js.map +1 -1
- package/dist/providers/__tests__/tambo-thread-provider.test.d.ts +2 -0
- package/dist/providers/__tests__/tambo-thread-provider.test.d.ts.map +1 -0
- package/dist/providers/__tests__/tambo-thread-provider.test.js +279 -0
- package/dist/providers/__tests__/tambo-thread-provider.test.js.map +1 -0
- package/dist/providers/tambo-provider.d.ts +1 -2
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-registry-provider.js +1 -4
- package/dist/providers/tambo-registry-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js +29 -25
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/setupTests.d.ts +3 -0
- package/dist/setupTests.d.ts.map +1 -0
- package/dist/setupTests.js +8 -0
- package/dist/setupTests.js.map +1 -0
- package/dist/testing/tools.d.ts +24 -0
- package/dist/testing/tools.d.ts.map +1 -0
- package/dist/testing/tools.js +31 -0
- package/dist/testing/tools.js.map +1 -0
- package/dist/testing/types.d.ts +4 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing/types.js +3 -0
- package/dist/testing/types.js.map +1 -0
- package/esm/hooks/__tests__/use-suggestions.test.js +69 -26
- package/esm/hooks/__tests__/use-suggestions.test.js.map +1 -1
- package/esm/hooks/__tests__/use-tambo-threads.test.d.ts +2 -0
- package/esm/hooks/__tests__/use-tambo-threads.test.d.ts.map +1 -0
- package/esm/hooks/__tests__/use-tambo-threads.test.js +210 -0
- package/esm/hooks/__tests__/use-tambo-threads.test.js.map +1 -0
- package/esm/hooks/react-query-hooks.d.ts +0 -8
- package/esm/hooks/react-query-hooks.d.ts.map +1 -1
- package/esm/hooks/react-query-hooks.js +0 -10
- package/esm/hooks/react-query-hooks.js.map +1 -1
- package/esm/hooks/use-suggestions.js +3 -3
- package/esm/hooks/use-suggestions.js.map +1 -1
- package/esm/hooks/use-tambo-threads.d.ts +13 -11
- package/esm/hooks/use-tambo-threads.d.ts.map +1 -1
- package/esm/hooks/use-tambo-threads.js +3 -1
- package/esm/hooks/use-tambo-threads.js.map +1 -1
- package/esm/providers/__tests__/tambo-thread-provider.test.d.ts +2 -0
- package/esm/providers/__tests__/tambo-thread-provider.test.d.ts.map +1 -0
- package/esm/providers/__tests__/tambo-thread-provider.test.js +274 -0
- package/esm/providers/__tests__/tambo-thread-provider.test.js.map +1 -0
- package/esm/providers/tambo-provider.d.ts +1 -2
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-registry-provider.js +1 -4
- package/esm/providers/tambo-registry-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js +29 -25
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/setupTests.d.ts +3 -0
- package/esm/setupTests.d.ts.map +1 -0
- package/esm/setupTests.js +6 -0
- package/esm/setupTests.js.map +1 -0
- package/esm/testing/tools.d.ts +24 -0
- package/esm/testing/tools.d.ts.map +1 -0
- package/esm/testing/tools.js +25 -0
- package/esm/testing/tools.js.map +1 -0
- package/esm/testing/types.d.ts +4 -0
- package/esm/testing/types.d.ts.map +1 -0
- package/esm/testing/types.js +2 -0
- package/esm/testing/types.js.map +1 -0
- package/package.json +8 -6
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
2
|
+
import { renderHook, waitFor } from "@testing-library/react";
|
|
3
|
+
import { useTamboClient, useTamboQueryClient, } from "../../providers/tambo-client-provider";
|
|
4
|
+
import { useTamboThreadList } from "../use-tambo-threads";
|
|
5
|
+
jest.mock("../../providers/tambo-client-provider", () => ({
|
|
6
|
+
useTamboClient: jest.fn(),
|
|
7
|
+
useTamboQueryClient: jest.fn(),
|
|
8
|
+
}));
|
|
9
|
+
describe("useTamboThreadList", () => {
|
|
10
|
+
const mockThreads = [
|
|
11
|
+
{ id: "thread-1", title: "Thread 1" },
|
|
12
|
+
{ id: "thread-2", title: "Thread 2" },
|
|
13
|
+
];
|
|
14
|
+
const mockProjects = {
|
|
15
|
+
getCurrent: jest.fn(),
|
|
16
|
+
retrieve: jest.fn(),
|
|
17
|
+
delete: jest.fn(),
|
|
18
|
+
};
|
|
19
|
+
const mockThreadsApi = {
|
|
20
|
+
list: jest.fn(),
|
|
21
|
+
messages: {
|
|
22
|
+
list: jest.fn(),
|
|
23
|
+
create: jest.fn(),
|
|
24
|
+
delete: jest.fn(),
|
|
25
|
+
updateComponentState: jest.fn(),
|
|
26
|
+
},
|
|
27
|
+
suggestions: {
|
|
28
|
+
list: jest.fn(),
|
|
29
|
+
generate: jest.fn(),
|
|
30
|
+
},
|
|
31
|
+
create: jest.fn(),
|
|
32
|
+
retrieve: jest.fn(),
|
|
33
|
+
update: jest.fn(),
|
|
34
|
+
delete: jest.fn(),
|
|
35
|
+
advance: jest.fn(),
|
|
36
|
+
advanceById: jest.fn(),
|
|
37
|
+
};
|
|
38
|
+
const mockBeta = {
|
|
39
|
+
projects: mockProjects,
|
|
40
|
+
threads: mockThreadsApi,
|
|
41
|
+
registry: {
|
|
42
|
+
retrieve: jest.fn(),
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const mockTamboAI = {
|
|
46
|
+
apiKey: "",
|
|
47
|
+
components: {},
|
|
48
|
+
beta: mockBeta,
|
|
49
|
+
};
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
jest.mocked(useTamboQueryClient).mockReturnValue(new QueryClient());
|
|
52
|
+
});
|
|
53
|
+
it("should fetch threads for current project when no projectId is provided", async () => {
|
|
54
|
+
const mockClient = jest.mocked(useTamboClient);
|
|
55
|
+
mockClient.mockReturnValue({
|
|
56
|
+
...mockTamboAI,
|
|
57
|
+
beta: {
|
|
58
|
+
...mockBeta,
|
|
59
|
+
projects: {
|
|
60
|
+
...mockProjects,
|
|
61
|
+
getCurrent: jest.fn().mockResolvedValue({ id: "current-project" }),
|
|
62
|
+
},
|
|
63
|
+
threads: {
|
|
64
|
+
...mockThreadsApi,
|
|
65
|
+
list: jest.fn().mockResolvedValue(mockThreads),
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
const { result } = renderHook(() => useTamboThreadList());
|
|
70
|
+
await waitFor(() => {
|
|
71
|
+
expect(result.current.data).toEqual(mockThreads);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
it("should fetch threads for specified projectId", async () => {
|
|
75
|
+
const mockList = jest.fn().mockResolvedValue(mockThreads);
|
|
76
|
+
const mockClient = jest.mocked(useTamboClient);
|
|
77
|
+
mockClient.mockReturnValue({
|
|
78
|
+
...mockTamboAI,
|
|
79
|
+
beta: {
|
|
80
|
+
...mockBeta,
|
|
81
|
+
threads: {
|
|
82
|
+
...mockThreadsApi,
|
|
83
|
+
list: mockList,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
const { result } = renderHook(() => useTamboThreadList({ projectId: "custom-project" }));
|
|
88
|
+
await waitFor(() => {
|
|
89
|
+
expect(result.current.data).toEqual(mockThreads);
|
|
90
|
+
});
|
|
91
|
+
expect(mockList).toHaveBeenCalledWith("custom-project", {});
|
|
92
|
+
});
|
|
93
|
+
it("should fetch threads with contextKey when provided", async () => {
|
|
94
|
+
const mockList = jest.fn().mockResolvedValue(mockThreads);
|
|
95
|
+
const mockClient = jest.mocked(useTamboClient);
|
|
96
|
+
mockClient.mockReturnValue({
|
|
97
|
+
...mockTamboAI,
|
|
98
|
+
beta: {
|
|
99
|
+
...mockBeta,
|
|
100
|
+
projects: {
|
|
101
|
+
...mockProjects,
|
|
102
|
+
getCurrent: jest.fn().mockResolvedValue({ id: "current-project" }),
|
|
103
|
+
},
|
|
104
|
+
threads: {
|
|
105
|
+
...mockThreadsApi,
|
|
106
|
+
list: mockList,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
const { result } = renderHook(() => useTamboThreadList({ contextKey: "test-context" }));
|
|
111
|
+
await waitFor(() => {
|
|
112
|
+
expect(result.current.data).toEqual(mockThreads);
|
|
113
|
+
});
|
|
114
|
+
expect(mockList).toHaveBeenCalledWith("current-project", {
|
|
115
|
+
contextKey: "test-context",
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
it("should handle loading state", async () => {
|
|
119
|
+
let resolvePromise;
|
|
120
|
+
const promise = new Promise((resolve) => {
|
|
121
|
+
resolvePromise = resolve;
|
|
122
|
+
});
|
|
123
|
+
const mockClient = jest.mocked(useTamboClient);
|
|
124
|
+
mockClient.mockReturnValue({
|
|
125
|
+
...mockTamboAI,
|
|
126
|
+
beta: {
|
|
127
|
+
...mockBeta,
|
|
128
|
+
projects: {
|
|
129
|
+
...mockProjects,
|
|
130
|
+
getCurrent: jest.fn().mockResolvedValue({ id: "current-project" }),
|
|
131
|
+
},
|
|
132
|
+
threads: {
|
|
133
|
+
...mockThreadsApi,
|
|
134
|
+
list: jest.fn().mockReturnValue(promise),
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
const { result } = renderHook(() => useTamboThreadList({}, { retry: false }));
|
|
139
|
+
expect(result.current).toMatchInlineSnapshot(`
|
|
140
|
+
{
|
|
141
|
+
"data": null,
|
|
142
|
+
"dataUpdatedAt": 0,
|
|
143
|
+
"error": null,
|
|
144
|
+
"errorUpdateCount": 0,
|
|
145
|
+
"errorUpdatedAt": 0,
|
|
146
|
+
"failureCount": 0,
|
|
147
|
+
"failureReason": null,
|
|
148
|
+
"fetchStatus": "fetching",
|
|
149
|
+
"isError": false,
|
|
150
|
+
"isFetched": false,
|
|
151
|
+
"isFetchedAfterMount": false,
|
|
152
|
+
"isFetching": true,
|
|
153
|
+
"isInitialLoading": true,
|
|
154
|
+
"isLoading": true,
|
|
155
|
+
"isLoadingError": false,
|
|
156
|
+
"isPaused": false,
|
|
157
|
+
"isPending": true,
|
|
158
|
+
"isPlaceholderData": false,
|
|
159
|
+
"isRefetchError": false,
|
|
160
|
+
"isRefetching": false,
|
|
161
|
+
"isStale": true,
|
|
162
|
+
"isSuccess": false,
|
|
163
|
+
"promise": Promise {
|
|
164
|
+
"reason": [Error: experimental_prefetchInRender feature flag is not enabled],
|
|
165
|
+
"status": "rejected",
|
|
166
|
+
},
|
|
167
|
+
"refetch": [Function],
|
|
168
|
+
"status": "pending",
|
|
169
|
+
}
|
|
170
|
+
`);
|
|
171
|
+
expect(result.current.isLoading).toBe(true);
|
|
172
|
+
expect(result.current.data).toBeNull();
|
|
173
|
+
resolvePromise(mockThreads);
|
|
174
|
+
await waitFor(() => {
|
|
175
|
+
expect(result.current.isLoading).toBe(false);
|
|
176
|
+
});
|
|
177
|
+
await waitFor(() => {
|
|
178
|
+
expect(result.current.isLoading).toBe(false);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
it("should handle error state", async () => {
|
|
182
|
+
const mockError = new Error("Failed to fetch threads");
|
|
183
|
+
const mockClient = jest.mocked(useTamboClient);
|
|
184
|
+
mockClient.mockReturnValue({
|
|
185
|
+
...mockTamboAI,
|
|
186
|
+
beta: {
|
|
187
|
+
...mockBeta,
|
|
188
|
+
projects: {
|
|
189
|
+
...mockProjects,
|
|
190
|
+
getCurrent: jest.fn().mockResolvedValue({ id: "current-project" }),
|
|
191
|
+
},
|
|
192
|
+
threads: {
|
|
193
|
+
...mockThreadsApi,
|
|
194
|
+
list: jest.fn().mockImplementation(async () => {
|
|
195
|
+
// console.log("Mocking error", mockCount++);
|
|
196
|
+
throw mockError;
|
|
197
|
+
}),
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
const { result } = renderHook(() => useTamboThreadList({}, { retry: false }));
|
|
202
|
+
await waitFor(() => {
|
|
203
|
+
const { isLoading, error, isError } = result.current;
|
|
204
|
+
expect(isLoading).toBe(false);
|
|
205
|
+
expect(isError).toBe(true);
|
|
206
|
+
expect(error).toBe(mockError);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
//# sourceMappingURL=use-tambo-threads.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-tambo-threads.test.js","sourceRoot":"","sources":["../../../src/hooks/__tests__/use-tambo-threads.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { QueryClient } from \"@tanstack/react-query\";\nimport { renderHook, waitFor } from \"@testing-library/react\";\nimport { DeepPartial } from \"ts-essentials\";\nimport {\n useTamboClient,\n useTamboQueryClient,\n} from \"../../providers/tambo-client-provider\";\nimport { PartialTamboAI } from \"../../testing/types\";\nimport { useTamboThreadList } from \"../use-tambo-threads\";\n\njest.mock(\"../../providers/tambo-client-provider\", () => ({\n useTamboClient: jest.fn(),\n useTamboQueryClient: jest.fn(),\n}));\n\ndescribe(\"useTamboThreadList\", () => {\n const mockThreads = [\n { id: \"thread-1\", title: \"Thread 1\" },\n { id: \"thread-2\", title: \"Thread 2\" },\n ];\n\n const mockProjects = {\n getCurrent: jest.fn(),\n retrieve: jest.fn(),\n delete: jest.fn(),\n } satisfies Partial<TamboAI[\"beta\"][\"projects\"]>;\n\n const mockThreadsApi = {\n list: jest.fn(),\n messages: {\n list: jest.fn(),\n create: jest.fn(),\n delete: jest.fn(),\n updateComponentState: jest.fn(),\n },\n suggestions: {\n list: jest.fn(),\n generate: jest.fn(),\n },\n create: jest.fn(),\n retrieve: jest.fn(),\n update: jest.fn(),\n delete: jest.fn(),\n advance: jest.fn(),\n advanceById: jest.fn(),\n } satisfies DeepPartial<TamboAI[\"beta\"][\"threads\"]>;\n\n const mockBeta = {\n projects: mockProjects,\n threads: mockThreadsApi,\n registry: {\n retrieve: jest.fn(),\n },\n } satisfies PartialTamboAI[\"beta\"];\n\n const mockTamboAI = {\n apiKey: \"\",\n components: {},\n beta: mockBeta,\n } satisfies PartialTamboAI as unknown as TamboAI;\n\n beforeEach(() => {\n jest.mocked(useTamboQueryClient).mockReturnValue(new QueryClient());\n });\n\n it(\"should fetch threads for current project when no projectId is provided\", async () => {\n const mockClient = jest.mocked(useTamboClient);\n mockClient.mockReturnValue({\n ...mockTamboAI,\n beta: {\n ...mockBeta,\n projects: {\n ...mockProjects,\n getCurrent: jest.fn().mockResolvedValue({ id: \"current-project\" }),\n },\n threads: {\n ...mockThreadsApi,\n list: jest.fn().mockResolvedValue(mockThreads),\n },\n },\n } satisfies PartialTamboAI as any);\n\n const { result } = renderHook(() => useTamboThreadList());\n\n await waitFor(() => {\n expect(result.current.data).toEqual(mockThreads);\n });\n });\n\n it(\"should fetch threads for specified projectId\", async () => {\n const mockList = jest.fn().mockResolvedValue(mockThreads);\n const mockClient = jest.mocked(useTamboClient);\n mockClient.mockReturnValue({\n ...mockTamboAI,\n beta: {\n ...mockBeta,\n threads: {\n ...mockThreadsApi,\n list: mockList,\n },\n },\n } satisfies PartialTamboAI as any);\n\n const { result } = renderHook(() =>\n useTamboThreadList({ projectId: \"custom-project\" }),\n );\n\n await waitFor(() => {\n expect(result.current.data).toEqual(mockThreads);\n });\n\n expect(mockList).toHaveBeenCalledWith(\"custom-project\", {});\n });\n\n it(\"should fetch threads with contextKey when provided\", async () => {\n const mockList = jest.fn().mockResolvedValue(mockThreads);\n const mockClient = jest.mocked(useTamboClient);\n mockClient.mockReturnValue({\n ...mockTamboAI,\n beta: {\n ...mockBeta,\n projects: {\n ...mockProjects,\n getCurrent: jest.fn().mockResolvedValue({ id: \"current-project\" }),\n },\n threads: {\n ...mockThreadsApi,\n list: mockList,\n },\n },\n } satisfies PartialTamboAI as any);\n\n const { result } = renderHook(() =>\n useTamboThreadList({ contextKey: \"test-context\" }),\n );\n\n await waitFor(() => {\n expect(result.current.data).toEqual(mockThreads);\n });\n\n expect(mockList).toHaveBeenCalledWith(\"current-project\", {\n contextKey: \"test-context\",\n });\n });\n\n it(\"should handle loading state\", async () => {\n let resolvePromise: (value: any) => void;\n const promise = new Promise((resolve) => {\n resolvePromise = resolve;\n });\n\n const mockClient = jest.mocked(useTamboClient);\n mockClient.mockReturnValue({\n ...mockTamboAI,\n beta: {\n ...mockBeta,\n projects: {\n ...mockProjects,\n getCurrent: jest.fn().mockResolvedValue({ id: \"current-project\" }),\n },\n threads: {\n ...mockThreadsApi,\n list: jest.fn().mockReturnValue(promise),\n },\n },\n } satisfies PartialTamboAI as any);\n\n const { result } = renderHook(() =>\n useTamboThreadList({}, { retry: false }),\n );\n\n expect(result.current).toMatchInlineSnapshot(`\n {\n \"data\": null,\n \"dataUpdatedAt\": 0,\n \"error\": null,\n \"errorUpdateCount\": 0,\n \"errorUpdatedAt\": 0,\n \"failureCount\": 0,\n \"failureReason\": null,\n \"fetchStatus\": \"fetching\",\n \"isError\": false,\n \"isFetched\": false,\n \"isFetchedAfterMount\": false,\n \"isFetching\": true,\n \"isInitialLoading\": true,\n \"isLoading\": true,\n \"isLoadingError\": false,\n \"isPaused\": false,\n \"isPending\": true,\n \"isPlaceholderData\": false,\n \"isRefetchError\": false,\n \"isRefetching\": false,\n \"isStale\": true,\n \"isSuccess\": false,\n \"promise\": Promise {\n \"reason\": [Error: experimental_prefetchInRender feature flag is not enabled],\n \"status\": \"rejected\",\n },\n \"refetch\": [Function],\n \"status\": \"pending\",\n }\n `);\n expect(result.current.isLoading).toBe(true);\n expect(result.current.data).toBeNull();\n\n resolvePromise!(mockThreads);\n await waitFor(() => {\n expect(result.current.isLoading).toBe(false);\n });\n await waitFor(() => {\n expect(result.current.isLoading).toBe(false);\n });\n });\n\n it(\"should handle error state\", async () => {\n const mockError = new Error(\"Failed to fetch threads\");\n const mockClient = jest.mocked(useTamboClient);\n mockClient.mockReturnValue({\n ...mockTamboAI,\n beta: {\n ...mockBeta,\n projects: {\n ...mockProjects,\n getCurrent: jest.fn().mockResolvedValue({ id: \"current-project\" }),\n },\n threads: {\n ...mockThreadsApi,\n list: jest.fn().mockImplementation(async () => {\n // console.log(\"Mocking error\", mockCount++);\n throw mockError;\n }),\n },\n },\n } satisfies PartialTamboAI as any);\n\n const { result } = renderHook(() =>\n useTamboThreadList({}, { retry: false }),\n );\n\n await waitFor(() => {\n const { isLoading, error, isError } = result.current;\n expect(isLoading).toBe(false);\n expect(isError).toBe(true);\n expect(error).toBe(mockError);\n });\n });\n});\n"]}
|
|
@@ -19,14 +19,6 @@ export declare function useTamboMutation<TData = unknown, TError = Error, TVaria
|
|
|
19
19
|
* Type alias for the result of a mutation.
|
|
20
20
|
*/
|
|
21
21
|
export type UseTamboMutationResult<TData = unknown, TError = Error, TVariables = void, TContext = unknown> = UseMutationResult<TData, TError, TVariables, TContext>;
|
|
22
|
-
/**
|
|
23
|
-
* Hook for creating a mutation with the tambo query client.
|
|
24
|
-
*
|
|
25
|
-
* Use this instead of useMutation from @tanstack/react-query
|
|
26
|
-
* @param options - The options for the mutation, same as useMutation from @tanstack/react-query
|
|
27
|
-
* @returns The mutation result
|
|
28
|
-
*/
|
|
29
|
-
export declare function useTamboMutationResult<TData = unknown, TError = Error, TVariables = void, TContext = unknown>(options: UseMutationOptions<TData, TError, TVariables, TContext>): UseMutationResult<TData, TError, TVariables, TContext>;
|
|
30
22
|
/**
|
|
31
23
|
* Type alias for the result of a query.
|
|
32
24
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-query-hooks.d.ts","sourceRoot":"","sources":["../../src/hooks/react-query-hooks.ts"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,EAER,kBAAkB,EAClB,iBAAiB,EAEjB,eAAe,EACf,cAAc,EACf,MAAM,uBAAuB,CAAC;AAG/B;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,YAAY,GAAG,OAAO,EACtB,MAAM,GAAG,KAAK,EACd,KAAK,GAAG,YAAY,EACpB,SAAS,SAAS,QAAQ,GAAG,QAAQ,EACrC,OAAO,EAAE,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,iCAGjE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,GAAG,OAAO,EACf,MAAM,GAAG,KAAK,EACd,UAAU,GAAG,IAAI,EACjB,QAAQ,GAAG,OAAO,EAClB,OAAO,EAAE,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,0DAGjE;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,CAChC,KAAK,GAAG,OAAO,EACf,MAAM,GAAG,KAAK,EACd,UAAU,GAAG,IAAI,EACjB,QAAQ,GAAG,OAAO,IAChB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;AAE3D
|
|
1
|
+
{"version":3,"file":"react-query-hooks.d.ts","sourceRoot":"","sources":["../../src/hooks/react-query-hooks.ts"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,EAER,kBAAkB,EAClB,iBAAiB,EAEjB,eAAe,EACf,cAAc,EACf,MAAM,uBAAuB,CAAC;AAG/B;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,YAAY,GAAG,OAAO,EACtB,MAAM,GAAG,KAAK,EACd,KAAK,GAAG,YAAY,EACpB,SAAS,SAAS,QAAQ,GAAG,QAAQ,EACrC,OAAO,EAAE,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,iCAGjE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,GAAG,OAAO,EACf,MAAM,GAAG,KAAK,EACd,UAAU,GAAG,IAAI,EACjB,QAAQ,GAAG,OAAO,EAClB,OAAO,EAAE,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,0DAGjE;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,CAChC,KAAK,GAAG,OAAO,EACf,MAAM,GAAG,KAAK,EACd,UAAU,GAAG,IAAI,EACjB,QAAQ,GAAG,OAAO,IAChB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;AAE3D;;GAEG;AACH,MAAM,MAAM,mBAAmB,CAC7B,KAAK,GAAG,OAAO,EACf,MAAM,GAAG,KAAK,IACZ,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC"}
|
|
@@ -23,14 +23,4 @@ export function useTamboMutation(options) {
|
|
|
23
23
|
const queryClient = useTamboQueryClient();
|
|
24
24
|
return useMutation(options, queryClient);
|
|
25
25
|
}
|
|
26
|
-
/**
|
|
27
|
-
* Hook for creating a mutation with the tambo query client.
|
|
28
|
-
*
|
|
29
|
-
* Use this instead of useMutation from @tanstack/react-query
|
|
30
|
-
* @param options - The options for the mutation, same as useMutation from @tanstack/react-query
|
|
31
|
-
* @returns The mutation result
|
|
32
|
-
*/
|
|
33
|
-
export function useTamboMutationResult(options) {
|
|
34
|
-
return useTamboMutation(options);
|
|
35
|
-
}
|
|
36
26
|
//# sourceMappingURL=react-query-hooks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-query-hooks.js","sourceRoot":"","sources":["../../src/hooks/react-query-hooks.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,OAAO,EAEL,WAAW,EAGX,QAAQ,GAGT,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAEzE;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAK3B,OAAgE;IAChE,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAC;IAC1C,OAAO,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAK9B,OAAgE;IAChE,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAC;IAC1C,OAAO,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAC3C,CAAC
|
|
1
|
+
{"version":3,"file":"react-query-hooks.js","sourceRoot":"","sources":["../../src/hooks/react-query-hooks.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,OAAO,EAEL,WAAW,EAGX,QAAQ,GAGT,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAEzE;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAK3B,OAAgE;IAChE,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAC;IAC1C,OAAO,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAK9B,OAAgE;IAChE,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAC;IAC1C,OAAO,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAC3C,CAAC","sourcesContent":["// tamboHooks.ts\nimport {\n QueryKey,\n useMutation,\n UseMutationOptions,\n UseMutationResult,\n useQuery,\n UseQueryOptions,\n UseQueryResult,\n} from \"@tanstack/react-query\";\nimport { useTamboQueryClient } from \"../providers/tambo-client-provider\";\n\n/**\n * Wrapper around useQuery that uses the internal tambo query client.\n *\n * Use this instead of useQuery from @tanstack/react-query\n * @param options - The options for the query, same as useQuery from @tanstack/react-query\n * @returns The query result\n */\nexport function useTamboQuery<\n TQueryFnData = unknown,\n TError = Error,\n TData = TQueryFnData,\n TQueryKey extends QueryKey = QueryKey,\n>(options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>) {\n const queryClient = useTamboQueryClient();\n return useQuery(options, queryClient);\n}\n\n/**\n * Wrapper around useMutation that uses the internal tambo query client.\n *\n * Use this instead of useMutation from @tanstack/react-query\n * @param options - The options for the mutation, same as useMutation from @tanstack/react-query\n * @returns The mutation result\n */\nexport function useTamboMutation<\n TData = unknown,\n TError = Error,\n TVariables = void,\n TContext = unknown,\n>(options: UseMutationOptions<TData, TError, TVariables, TContext>) {\n const queryClient = useTamboQueryClient();\n return useMutation(options, queryClient);\n}\n\n/**\n * Type alias for the result of a mutation.\n */\nexport type UseTamboMutationResult<\n TData = unknown,\n TError = Error,\n TVariables = void,\n TContext = unknown,\n> = UseMutationResult<TData, TError, TVariables, TContext>;\n\n/**\n * Type alias for the result of a query.\n */\nexport type UseTamboQueryResult<\n TData = unknown,\n TError = Error,\n> = UseQueryResult<TData, TError>;\n"]}
|
|
@@ -6,7 +6,7 @@ import { useTamboRegistry } from "../providers/tambo-registry-provider";
|
|
|
6
6
|
import { useTamboThread } from "../providers/tambo-thread-provider";
|
|
7
7
|
import { combineMutationResults, } from "../util/query-utils";
|
|
8
8
|
import { getAvailableComponents } from "../util/registry";
|
|
9
|
-
import {
|
|
9
|
+
import { useTamboMutation, useTamboQuery, } from "./react-query-hooks";
|
|
10
10
|
import { INPUT_ERROR_MESSAGES, useTamboThreadInput } from "./use-thread-input";
|
|
11
11
|
/**
|
|
12
12
|
* Hook for managing Tambo AI suggestions in a thread
|
|
@@ -53,7 +53,7 @@ export function useTamboSuggestions(options = {}) {
|
|
|
53
53
|
retry: false,
|
|
54
54
|
});
|
|
55
55
|
// Accept suggestion mutation
|
|
56
|
-
const acceptMutationState =
|
|
56
|
+
const acceptMutationState = useTamboMutation({
|
|
57
57
|
mutationFn: async ({ suggestion, shouldSubmit = false }) => {
|
|
58
58
|
const validation = validateInput(suggestion.detailedSuggestion);
|
|
59
59
|
if (!validation.isValid) {
|
|
@@ -74,7 +74,7 @@ export function useTamboSuggestions(options = {}) {
|
|
|
74
74
|
},
|
|
75
75
|
});
|
|
76
76
|
// Generate suggestions mutation
|
|
77
|
-
const generateMutationState =
|
|
77
|
+
const generateMutationState = useTamboMutation({
|
|
78
78
|
mutationFn: async (abortController) => {
|
|
79
79
|
if (!latestMessageId || !isLatestFromTambo) {
|
|
80
80
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-suggestions.js","sourceRoot":"","sources":["../../src/hooks/use-suggestions.ts"],"names":[],"mappings":"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","sourcesContent":["import TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { useEffect, useState } from \"react\";\nimport { validateInput } from \"../model/validate-input\";\nimport { useTamboClient } from \"../providers/tambo-client-provider\";\nimport { useTambo } from \"../providers/tambo-provider\";\nimport { useTamboRegistry } from \"../providers/tambo-registry-provider\";\nimport { useTamboThread } from \"../providers/tambo-thread-provider\";\nimport {\n CombinedMutationResult,\n combineMutationResults,\n} from \"../util/query-utils\";\nimport { getAvailableComponents } from \"../util/registry\";\nimport {\n UseTamboMutationResult,\n UseTamboQueryResult,\n useTamboMutationResult,\n useTamboQuery,\n} from \"./react-query-hooks\";\nimport { INPUT_ERROR_MESSAGES, useTamboThreadInput } from \"./use-thread-input\";\n\n/**\n * Configuration options for the useTamboSuggestions hook\n */\nexport interface useTamboSuggestionsOptions {\n /** Maximum number of suggestions to generate (1-10, default 3) */\n maxSuggestions?: number;\n}\n\n/**\n * Return value interface for useTamboSuggestions hook\n */\nexport interface useTamboSuggestionsResultInternal {\n /** List of available suggestions (also available in generateResult.data) */\n suggestions: TamboAI.Beta.Threads.Suggestion[];\n /** ID of the currently selected suggestion */\n selectedSuggestionId: string | null;\n /**\n * Accept and apply a suggestion (also available in acceptResult.mutateAsync)\n * @param suggestion - The suggestion to accept\n * @param shouldSubmit - Whether to automatically submit after accepting (default: false)\n */\n accept: (acceptOptions: {\n suggestion: TamboAI.Beta.Threads.Suggestion;\n shouldSubmit?: boolean;\n }) => Promise<void>;\n\n /** Result and network state for accepting a suggestion */\n acceptResult: UseTamboMutationResult<\n void,\n Error,\n { suggestion: TamboAI.Beta.Threads.Suggestion; shouldSubmit?: boolean }\n >;\n\n /** Result and network state for generating suggestions */\n generateResult: UseTamboMutationResult<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error,\n AbortController\n >;\n\n /** The full suggestions query object from React Query */\n suggestionsResult: UseTamboQueryResult<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error\n >;\n}\n\ntype useTamboSuggestionsResult = CombinedMutationResult<any, Error> &\n useTamboSuggestionsResultInternal;\n\n/**\n * Hook for managing Tambo AI suggestions in a thread\n * @param options - Configuration options for suggestion generation\n * @returns Object containing suggestions state and control functions\n */\nexport function useTamboSuggestions(\n options: useTamboSuggestionsOptions = {},\n): useTamboSuggestionsResult {\n const { maxSuggestions = 3 } = options;\n const { thread } = useTamboThread();\n const { sendThreadMessage } = useTambo();\n const tamboClient = useTamboClient();\n const { componentList, toolRegistry, componentToolAssociations } =\n useTamboRegistry();\n\n const [selectedSuggestionId, setSelectedSuggestionId] = useState<\n string | null\n >(null);\n const { setValue: setInputValue } = useTamboThreadInput();\n\n const latestMessage = thread.messages[thread.messages.length - 1];\n const isLatestFromTambo = latestMessage?.role === \"assistant\";\n const latestMessageId = latestMessage?.id;\n\n // Reset selected suggestion when the message changes\n useEffect(() => {\n setSelectedSuggestionId(null);\n }, [latestMessageId]);\n\n // Use React Query to fetch suggestions when a new hydra message is received\n const suggestionsResult = useTamboQuery({\n // Only include latestMessageId in the queryKey if the message is from hydra\n queryKey: [\"suggestions\", isLatestFromTambo ? latestMessageId : null],\n queryFn: async () => {\n if (!latestMessageId || !isLatestFromTambo) {\n return [];\n }\n\n // Get registered components from the registry\n const components = getAvailableComponents(\n componentList,\n toolRegistry,\n componentToolAssociations,\n );\n\n return await tamboClient.beta.threads.suggestions.generate(\n thread.id,\n latestMessageId,\n {\n maxSuggestions,\n // The API expects an array of arrays for availableComponents\n availableComponents: [components],\n },\n );\n },\n // Only run the query if we have a valid message from hydra\n enabled: Boolean(latestMessageId && isLatestFromTambo),\n // Don't refetch on window focus or reconnect\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n // Don't retry on failure\n retry: false,\n });\n\n // Accept suggestion mutation\n const acceptMutationState = useTamboMutationResult<\n void,\n Error,\n { suggestion: TamboAI.Beta.Threads.Suggestion; shouldSubmit?: boolean }\n >({\n mutationFn: async ({ suggestion, shouldSubmit = false }) => {\n const validation = validateInput(suggestion.detailedSuggestion);\n if (!validation.isValid) {\n if (validation.error) {\n throw validation.error;\n }\n throw new Error(INPUT_ERROR_MESSAGES.VALIDATION);\n }\n\n if (shouldSubmit) {\n await sendThreadMessage(validation.sanitizedInput, {\n threadId: thread.id,\n });\n } else {\n setInputValue(validation.sanitizedInput);\n }\n setSelectedSuggestionId(suggestion.id);\n },\n });\n\n // Generate suggestions mutation\n const generateMutationState = useTamboMutationResult<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error,\n AbortController\n >({\n mutationFn: async (abortController: AbortController) => {\n if (!latestMessageId || !isLatestFromTambo) {\n return undefined;\n }\n\n // Get registered components from the registry\n const components = getAvailableComponents(\n componentList,\n toolRegistry,\n componentToolAssociations,\n );\n\n return await tamboClient.beta.threads.suggestions.generate(\n thread.id,\n latestMessageId,\n {\n maxSuggestions,\n // The API expects an array of arrays for availableComponents\n availableComponents: [components],\n },\n { signal: abortController.signal },\n );\n },\n // Don't retry on failure\n retry: false,\n });\n\n // Use the query data if available, otherwise use the mutation data\n // Only return suggestions if the latest message is from hydra\n const suggestions = isLatestFromTambo\n ? (suggestionsResult.data ?? generateMutationState.data ?? [])\n : [];\n\n return {\n suggestions,\n accept: acceptMutationState.mutateAsync,\n selectedSuggestionId,\n acceptResult: acceptMutationState,\n generateResult: generateMutationState,\n suggestionsResult,\n ...combineMutationResults(acceptMutationState, generateMutationState),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-suggestions.js","sourceRoot":"","sources":["../../src/hooks/use-suggestions.ts"],"names":[],"mappings":"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","sourcesContent":["import TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { useEffect, useState } from \"react\";\nimport { validateInput } from \"../model/validate-input\";\nimport { useTamboClient } from \"../providers/tambo-client-provider\";\nimport { useTambo } from \"../providers/tambo-provider\";\nimport { useTamboRegistry } from \"../providers/tambo-registry-provider\";\nimport { useTamboThread } from \"../providers/tambo-thread-provider\";\nimport {\n CombinedMutationResult,\n combineMutationResults,\n} from \"../util/query-utils\";\nimport { getAvailableComponents } from \"../util/registry\";\nimport {\n UseTamboMutationResult,\n UseTamboQueryResult,\n useTamboMutation,\n useTamboQuery,\n} from \"./react-query-hooks\";\nimport { INPUT_ERROR_MESSAGES, useTamboThreadInput } from \"./use-thread-input\";\n\n/**\n * Configuration options for the useTamboSuggestions hook\n */\nexport interface useTamboSuggestionsOptions {\n /** Maximum number of suggestions to generate (1-10, default 3) */\n maxSuggestions?: number;\n}\n\n/**\n * Return value interface for useTamboSuggestions hook\n */\nexport interface useTamboSuggestionsResultInternal {\n /** List of available suggestions (also available in generateResult.data) */\n suggestions: TamboAI.Beta.Threads.Suggestion[];\n /** ID of the currently selected suggestion */\n selectedSuggestionId: string | null;\n /**\n * Accept and apply a suggestion (also available in acceptResult.mutateAsync)\n * @param suggestion - The suggestion to accept\n * @param shouldSubmit - Whether to automatically submit after accepting (default: false)\n */\n accept: (acceptOptions: {\n suggestion: TamboAI.Beta.Threads.Suggestion;\n shouldSubmit?: boolean;\n }) => Promise<void>;\n\n /** Result and network state for accepting a suggestion */\n acceptResult: UseTamboMutationResult<\n void,\n Error,\n { suggestion: TamboAI.Beta.Threads.Suggestion; shouldSubmit?: boolean }\n >;\n\n /** Result and network state for generating suggestions */\n generateResult: UseTamboMutationResult<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error,\n AbortController\n >;\n\n /** The full suggestions query object from React Query */\n suggestionsResult: UseTamboQueryResult<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error\n >;\n}\n\ntype useTamboSuggestionsResult = CombinedMutationResult<any, Error> &\n useTamboSuggestionsResultInternal;\n\n/**\n * Hook for managing Tambo AI suggestions in a thread\n * @param options - Configuration options for suggestion generation\n * @returns Object containing suggestions state and control functions\n */\nexport function useTamboSuggestions(\n options: useTamboSuggestionsOptions = {},\n): useTamboSuggestionsResult {\n const { maxSuggestions = 3 } = options;\n const { thread } = useTamboThread();\n const { sendThreadMessage } = useTambo();\n const tamboClient = useTamboClient();\n const { componentList, toolRegistry, componentToolAssociations } =\n useTamboRegistry();\n\n const [selectedSuggestionId, setSelectedSuggestionId] = useState<\n string | null\n >(null);\n const { setValue: setInputValue } = useTamboThreadInput();\n\n const latestMessage = thread.messages[thread.messages.length - 1];\n const isLatestFromTambo = latestMessage?.role === \"assistant\";\n const latestMessageId = latestMessage?.id;\n\n // Reset selected suggestion when the message changes\n useEffect(() => {\n setSelectedSuggestionId(null);\n }, [latestMessageId]);\n\n // Use React Query to fetch suggestions when a new hydra message is received\n const suggestionsResult = useTamboQuery({\n // Only include latestMessageId in the queryKey if the message is from hydra\n queryKey: [\"suggestions\", isLatestFromTambo ? latestMessageId : null],\n queryFn: async () => {\n if (!latestMessageId || !isLatestFromTambo) {\n return [];\n }\n\n // Get registered components from the registry\n const components = getAvailableComponents(\n componentList,\n toolRegistry,\n componentToolAssociations,\n );\n\n return await tamboClient.beta.threads.suggestions.generate(\n thread.id,\n latestMessageId,\n {\n maxSuggestions,\n // The API expects an array of arrays for availableComponents\n availableComponents: [components],\n },\n );\n },\n // Only run the query if we have a valid message from hydra\n enabled: Boolean(latestMessageId && isLatestFromTambo),\n // Don't refetch on window focus or reconnect\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n // Don't retry on failure\n retry: false,\n });\n\n // Accept suggestion mutation\n const acceptMutationState = useTamboMutation<\n void,\n Error,\n { suggestion: TamboAI.Beta.Threads.Suggestion; shouldSubmit?: boolean }\n >({\n mutationFn: async ({ suggestion, shouldSubmit = false }) => {\n const validation = validateInput(suggestion.detailedSuggestion);\n if (!validation.isValid) {\n if (validation.error) {\n throw validation.error;\n }\n throw new Error(INPUT_ERROR_MESSAGES.VALIDATION);\n }\n\n if (shouldSubmit) {\n await sendThreadMessage(validation.sanitizedInput, {\n threadId: thread.id,\n });\n } else {\n setInputValue(validation.sanitizedInput);\n }\n setSelectedSuggestionId(suggestion.id);\n },\n });\n\n // Generate suggestions mutation\n const generateMutationState = useTamboMutation<\n TamboAI.Beta.Threads.Suggestions.SuggestionGenerateResponse | undefined,\n Error,\n AbortController\n >({\n mutationFn: async (abortController: AbortController) => {\n if (!latestMessageId || !isLatestFromTambo) {\n return undefined;\n }\n\n // Get registered components from the registry\n const components = getAvailableComponents(\n componentList,\n toolRegistry,\n componentToolAssociations,\n );\n\n return await tamboClient.beta.threads.suggestions.generate(\n thread.id,\n latestMessageId,\n {\n maxSuggestions,\n // The API expects an array of arrays for availableComponents\n availableComponents: [components],\n },\n { signal: abortController.signal },\n );\n },\n // Don't retry on failure\n retry: false,\n });\n\n // Use the query data if available, otherwise use the mutation data\n // Only return suggestions if the latest message is from hydra\n const suggestions = isLatestFromTambo\n ? (suggestionsResult.data ?? generateMutationState.data ?? [])\n : [];\n\n return {\n suggestions,\n accept: acceptMutationState.mutateAsync,\n selectedSuggestionId,\n acceptResult: acceptMutationState,\n generateResult: generateMutationState,\n suggestionsResult,\n ...combineMutationResults(acceptMutationState, generateMutationState),\n };\n}\n"]}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type TamboAI from "@tambo-ai/typescript-sdk";
|
|
2
|
+
import { UseQueryOptions } from "@tanstack/react-query";
|
|
1
3
|
interface UseTamboThreadListConfig {
|
|
2
4
|
/**
|
|
3
5
|
* The projectId to get the threads for. If not provided, the current project
|
|
@@ -33,7 +35,7 @@ interface UseTamboThreadListConfig {
|
|
|
33
35
|
* @param config.contextKey - The context key to get the threads for
|
|
34
36
|
* @returns The threads for the specified project and optional context key
|
|
35
37
|
*/
|
|
36
|
-
export declare function useTamboThreadList({ projectId, contextKey
|
|
38
|
+
export declare function useTamboThreadList({ projectId, contextKey }?: UseTamboThreadListConfig, options?: Partial<UseQueryOptions<TamboAI.Beta.Threads.ThreadsOffsetAndLimit | null>>): import("@tanstack/react-query").QueryObserverRefetchErrorResult<TamboAI.Beta.Threads.ThreadsOffsetAndLimit | null, Error> | import("@tanstack/react-query").QueryObserverSuccessResult<TamboAI.Beta.Threads.ThreadsOffsetAndLimit | null, Error> | import("@tanstack/react-query").QueryObserverLoadingErrorResult<TamboAI.Beta.Threads.ThreadsOffsetAndLimit | null, Error> | import("@tanstack/react-query").QueryObserverPendingResult<TamboAI.Beta.Threads.ThreadsOffsetAndLimit | null, Error> | import("@tanstack/react-query").QueryObserverPlaceholderResult<TamboAI.Beta.Threads.ThreadsOffsetAndLimit | null, Error> | {
|
|
37
39
|
error: Error;
|
|
38
40
|
isError: true;
|
|
39
41
|
isPending: false;
|
|
@@ -55,8 +57,8 @@ export declare function useTamboThreadList({ projectId, contextKey, }?: UseTambo
|
|
|
55
57
|
isPaused: boolean;
|
|
56
58
|
isRefetching: boolean;
|
|
57
59
|
isStale: boolean;
|
|
58
|
-
refetch: (options?: import("@tanstack/query
|
|
59
|
-
fetchStatus: import("@tanstack/query
|
|
60
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<string, Error>>;
|
|
61
|
+
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
60
62
|
promise: Promise<string>;
|
|
61
63
|
data: null;
|
|
62
64
|
} | {
|
|
@@ -81,8 +83,8 @@ export declare function useTamboThreadList({ projectId, contextKey, }?: UseTambo
|
|
|
81
83
|
isPaused: boolean;
|
|
82
84
|
isRefetching: boolean;
|
|
83
85
|
isStale: boolean;
|
|
84
|
-
refetch: (options?: import("@tanstack/query
|
|
85
|
-
fetchStatus: import("@tanstack/query
|
|
86
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<string, Error>>;
|
|
87
|
+
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
86
88
|
promise: Promise<string>;
|
|
87
89
|
data: null;
|
|
88
90
|
} | {
|
|
@@ -107,8 +109,8 @@ export declare function useTamboThreadList({ projectId, contextKey, }?: UseTambo
|
|
|
107
109
|
isPaused: boolean;
|
|
108
110
|
isRefetching: boolean;
|
|
109
111
|
isStale: boolean;
|
|
110
|
-
refetch: (options?: import("@tanstack/query
|
|
111
|
-
fetchStatus: import("@tanstack/query
|
|
112
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<string, Error>>;
|
|
113
|
+
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
112
114
|
promise: Promise<string>;
|
|
113
115
|
data: null;
|
|
114
116
|
} | {
|
|
@@ -133,8 +135,8 @@ export declare function useTamboThreadList({ projectId, contextKey, }?: UseTambo
|
|
|
133
135
|
isPaused: boolean;
|
|
134
136
|
isRefetching: boolean;
|
|
135
137
|
isStale: boolean;
|
|
136
|
-
refetch: (options?: import("@tanstack/query
|
|
137
|
-
fetchStatus: import("@tanstack/query
|
|
138
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<string, Error>>;
|
|
139
|
+
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
138
140
|
promise: Promise<string>;
|
|
139
141
|
data: null;
|
|
140
142
|
} | {
|
|
@@ -159,8 +161,8 @@ export declare function useTamboThreadList({ projectId, contextKey, }?: UseTambo
|
|
|
159
161
|
isPaused: boolean;
|
|
160
162
|
isRefetching: boolean;
|
|
161
163
|
isStale: boolean;
|
|
162
|
-
refetch: (options?: import("@tanstack/query
|
|
163
|
-
fetchStatus: import("@tanstack/query
|
|
164
|
+
refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<string, Error>>;
|
|
165
|
+
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
164
166
|
promise: Promise<string>;
|
|
165
167
|
data: null;
|
|
166
168
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tambo-threads.d.ts","sourceRoot":"","sources":["../../src/hooks/use-tambo-threads.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-tambo-threads.d.ts","sourceRoot":"","sources":["../../src/hooks/use-tambo-threads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIxD,UAAU,wBAAwB;IAChC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,wBAAwB;IAChC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,SAAS,EAAE,UAAU,EAAE,GAAE,wBAA6B,EACxD,OAAO,GAAE,OAAO,CACd,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAC9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BP"}
|
|
@@ -11,9 +11,10 @@ import { useTamboQuery } from "./react-query-hooks";
|
|
|
11
11
|
* @param config.contextKey - The context key to get the threads for
|
|
12
12
|
* @returns The threads for the specified project and optional context key
|
|
13
13
|
*/
|
|
14
|
-
export function useTamboThreadList({ projectId, contextKey
|
|
14
|
+
export function useTamboThreadList({ projectId, contextKey } = {}, options = {}) {
|
|
15
15
|
const client = useTamboClient();
|
|
16
16
|
const { data: queriedProjectId, ...projectIdState } = useTamboQuery({
|
|
17
|
+
...options,
|
|
17
18
|
queryKey: ["projectId"],
|
|
18
19
|
queryFn: async () => {
|
|
19
20
|
return (await client.beta.projects.getCurrent()).id;
|
|
@@ -21,6 +22,7 @@ export function useTamboThreadList({ projectId, contextKey, } = {}) {
|
|
|
21
22
|
});
|
|
22
23
|
const currentProjectId = projectId ?? queriedProjectId;
|
|
23
24
|
const threadState = useTamboQuery({
|
|
25
|
+
...options,
|
|
24
26
|
enabled: !!currentProjectId,
|
|
25
27
|
queryKey: ["threads", currentProjectId, contextKey],
|
|
26
28
|
queryFn: async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tambo-threads.js","sourceRoot":"","sources":["../../src/hooks/use-tambo-threads.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-tambo-threads.js","sourceRoot":"","sources":["../../src/hooks/use-tambo-threads.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA4BpD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAChC,EAAE,SAAS,EAAE,UAAU,KAA+B,EAAE,EACxD,UAEI,EAAE;IAEN,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,cAAc,EAAE,GAAG,aAAa,CAAC;QAClE,GAAI,OAA8C;QAClD,QAAQ,EAAE,CAAC,WAAW,CAAC;QACvB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,OAAO,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC;QACtD,CAAC;KACF,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAG,SAAS,IAAI,gBAAgB,CAAC;IAEvD,MAAM,WAAW,GAAG,aAAa,CAAC;QAChC,GAAG,OAAO;QACV,OAAO,EAAE,CAAC,CAAC,gBAAgB;QAC3B,QAAQ,EAAE,CAAC,SAAS,EAAE,gBAAgB,EAAE,UAAU,CAAC;QACnD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE;gBAClE,UAAU;aACX,CAAC,CAAC;YACH,OAAO,UAAU,CAAC;QACpB,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,gBAAgB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,cAAc,EAAE,CAAC;AAC5E,CAAC","sourcesContent":["import type TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { UseQueryOptions } from \"@tanstack/react-query\";\nimport { useTamboClient } from \"../providers/tambo-client-provider\";\nimport { useTamboQuery } from \"./react-query-hooks\";\n\ninterface UseTamboThreadListConfig {\n /**\n * The projectId to get the threads for. If not provided, the current project\n * will be used.\n */\n projectId?: string;\n /**\n * The context key to get the threads for. If not provided, all threads for\n * the project will be returned.\n */\n contextKey?: string;\n}\n\ninterface UseTamboThreadListConfig {\n /**\n * The projectId to get the threads for. If not provided, the current project\n * will be used.\n */\n projectId?: string;\n /**\n * The context key to get the threads for. If not provided, all threads for\n * the project will be returned.\n */\n contextKey?: string;\n}\n\n/**\n * Get all the threads for the specified project.\n *\n * If contextKey is empty, then all threads for the project will be returned.\n * If contextKey is not empty, then only the threads for the specified context\n * key will be returned.\n * @param config - The config for the useTamboThreadList hook\n * @param config.projectId - The projectId to get the threads for\n * @param config.contextKey - The context key to get the threads for\n * @returns The threads for the specified project and optional context key\n */\nexport function useTamboThreadList(\n { projectId, contextKey }: UseTamboThreadListConfig = {},\n options: Partial<\n UseQueryOptions<TamboAI.Beta.Threads.ThreadsOffsetAndLimit | null>\n > = {},\n) {\n const client = useTamboClient();\n const { data: queriedProjectId, ...projectIdState } = useTamboQuery({\n ...(options as unknown as UseQueryOptions<string>),\n queryKey: [\"projectId\"],\n queryFn: async () => {\n return (await client.beta.projects.getCurrent()).id;\n },\n });\n const currentProjectId = projectId ?? queriedProjectId;\n\n const threadState = useTamboQuery({\n ...options,\n enabled: !!currentProjectId,\n queryKey: [\"threads\", currentProjectId, contextKey],\n queryFn: async () => {\n if (!currentProjectId) {\n return null;\n }\n const threadIter = await client.beta.threads.list(currentProjectId, {\n contextKey,\n });\n return threadIter;\n },\n });\n\n return currentProjectId ? threadState : { data: null, ...projectIdState };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tambo-thread-provider.test.d.ts","sourceRoot":"","sources":["../../../src/providers/__tests__/tambo-thread-provider.test.tsx"],"names":[],"mappings":""}
|