@tambo-ai/react 0.54.1 → 0.56.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 +49 -14
- package/dist/hooks/__tests__/use-tambo-threads.test.js +1 -9
- package/dist/hooks/__tests__/use-tambo-threads.test.js.map +1 -1
- package/dist/mcp/__tests__/mcp-client.test.js +73 -27
- package/dist/mcp/__tests__/mcp-client.test.js.map +1 -1
- package/dist/mcp/mcp-client.d.ts +93 -210
- package/dist/mcp/mcp-client.d.ts.map +1 -1
- package/dist/mcp/mcp-client.js +103 -18
- package/dist/mcp/mcp-client.js.map +1 -1
- package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.js +2 -1
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/providers/__tests__/tambo-thread-provider.test.js +2 -6
- package/dist/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/dist/providers/hooks/use-tambo-session-token.d.ts +2 -2
- package/dist/providers/hooks/use-tambo-session-token.js +2 -2
- package/dist/providers/hooks/use-tambo-session-token.js.map +1 -1
- package/dist/providers/tambo-context-helpers-provider.d.ts +7 -2
- package/dist/providers/tambo-context-helpers-provider.d.ts.map +1 -1
- package/dist/providers/tambo-context-helpers-provider.js +12 -7
- package/dist/providers/tambo-context-helpers-provider.js.map +1 -1
- package/dist/providers/tambo-prop-stream-provider/index.d.ts +1 -1
- package/dist/providers/tambo-prop-stream-provider/index.js +1 -1
- package/dist/providers/tambo-prop-stream-provider/index.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts +1 -1
- package/dist/providers/tambo-provider.js +1 -1
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js +2 -4
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/esm/hooks/__tests__/use-tambo-threads.test.js +1 -9
- package/esm/hooks/__tests__/use-tambo-threads.test.js.map +1 -1
- package/esm/mcp/__tests__/mcp-client.test.js +73 -27
- package/esm/mcp/__tests__/mcp-client.test.js.map +1 -1
- package/esm/mcp/mcp-client.d.ts +93 -210
- package/esm/mcp/mcp-client.d.ts.map +1 -1
- package/esm/mcp/mcp-client.js +103 -18
- package/esm/mcp/mcp-client.js.map +1 -1
- package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.js +2 -1
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/providers/__tests__/tambo-thread-provider.test.js +2 -6
- package/esm/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
- package/esm/providers/hooks/use-tambo-session-token.d.ts +2 -2
- package/esm/providers/hooks/use-tambo-session-token.js +2 -2
- package/esm/providers/hooks/use-tambo-session-token.js.map +1 -1
- package/esm/providers/tambo-context-helpers-provider.d.ts +7 -2
- package/esm/providers/tambo-context-helpers-provider.d.ts.map +1 -1
- package/esm/providers/tambo-context-helpers-provider.js +12 -7
- package/esm/providers/tambo-context-helpers-provider.js.map +1 -1
- package/esm/providers/tambo-prop-stream-provider/index.d.ts +1 -1
- package/esm/providers/tambo-prop-stream-provider/index.js +1 -1
- package/esm/providers/tambo-prop-stream-provider/index.js.map +1 -1
- package/esm/providers/tambo-provider.d.ts +1 -1
- package/esm/providers/tambo-provider.js +1 -1
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js +2 -4
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/package.json +16 -19
package/README.md
CHANGED
|
@@ -100,14 +100,38 @@ import { TamboProvider } from "@tambo-ai/react";
|
|
|
100
100
|
|
|
101
101
|
This is also handled automatically for you if you are using the `MessageThreadFull` component.
|
|
102
102
|
|
|
103
|
-
For custom components, you can use the `
|
|
103
|
+
For custom components rendered by Tambo, you can use the `useTamboCurrentMessage` hook inside the component to access the current message.
|
|
104
|
+
|
|
105
|
+
_Example (Tambo‑rendered custom component):_
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { useTamboCurrentMessage } from "@tambo-ai/react";
|
|
109
|
+
|
|
110
|
+
export function TamboRenderedMessage() {
|
|
111
|
+
const message = useTamboCurrentMessage();
|
|
112
|
+
return (
|
|
113
|
+
<div>
|
|
114
|
+
<div>Role: {message.role}</div>
|
|
115
|
+
<div>
|
|
116
|
+
{message.content.map((part, i) =>
|
|
117
|
+
part.type === "text" ? (
|
|
118
|
+
<div key={i}>{part.text}</div>
|
|
119
|
+
) : (
|
|
120
|
+
<div key={i}>Non-text content: {part.type}</div>
|
|
121
|
+
),
|
|
122
|
+
)}
|
|
123
|
+
</div>
|
|
124
|
+
{/* If Tambo provided rendered output, include it */}
|
|
125
|
+
<div>{message.renderedComponent}</div>
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
If you're rendering your own message list (outside of a Tambo‑rendered component), you can instead pass each `message` as a prop, as shown below:
|
|
104
132
|
|
|
105
133
|
```tsx
|
|
106
|
-
import {
|
|
107
|
-
useTambo,
|
|
108
|
-
useMessageContext,
|
|
109
|
-
type TamboThreadMessage,
|
|
110
|
-
} from "@tambo-ai/react";
|
|
134
|
+
import { useTambo, type TamboThreadMessage } from "@tambo-ai/react";
|
|
111
135
|
|
|
112
136
|
function ChatHistory() {
|
|
113
137
|
const { thread } = useTambo();
|
|
@@ -127,11 +151,11 @@ function CustomMessage({ message }: { message: TamboThreadMessage }) {
|
|
|
127
151
|
{/* Render the message content */}
|
|
128
152
|
<div>Role: {message.role}</div>
|
|
129
153
|
<div>
|
|
130
|
-
{message.content.map((part) =>
|
|
154
|
+
{message.content.map((part, i) =>
|
|
131
155
|
part.type === "text" ? (
|
|
132
|
-
<div key={
|
|
156
|
+
<div key={i}>{part.text}</div>
|
|
133
157
|
) : (
|
|
134
|
-
<div key={
|
|
158
|
+
<div key={i}>Non-text content: {part.type}</div>
|
|
135
159
|
),
|
|
136
160
|
)}
|
|
137
161
|
</div>
|
|
@@ -205,9 +229,17 @@ function ChatInterface() {
|
|
|
205
229
|
<div>
|
|
206
230
|
{/* Display messages */}
|
|
207
231
|
<div>
|
|
208
|
-
{thread.messages.map((message
|
|
209
|
-
<div key={
|
|
210
|
-
<div>
|
|
232
|
+
{thread.messages.map((message) => (
|
|
233
|
+
<div key={message.id} className={`message ${message.role}`}>
|
|
234
|
+
<div>
|
|
235
|
+
{message.content.map((part, i) =>
|
|
236
|
+
part.type === "text" ? (
|
|
237
|
+
<div key={i}>{part.text}</div>
|
|
238
|
+
) : (
|
|
239
|
+
<div key={i}>Non-text content: {part.type}</div>
|
|
240
|
+
),
|
|
241
|
+
)}
|
|
242
|
+
</div>
|
|
211
243
|
{message.renderedComponent}
|
|
212
244
|
</div>
|
|
213
245
|
))}
|
|
@@ -360,11 +392,12 @@ const tools: TamboTool[] = [
|
|
|
360
392
|
```tsx
|
|
361
393
|
import { TamboProvider } from "@tambo-ai/react";
|
|
362
394
|
import { TamboMcpProvider } from "@tambo-ai/react/mcp";
|
|
395
|
+
import { MCPTransport } from "@tambo-ai/react/mcp";
|
|
363
396
|
|
|
364
397
|
const mcpServers = [
|
|
365
398
|
{
|
|
366
399
|
url: "https://mcp-server-1.com",
|
|
367
|
-
transport:
|
|
400
|
+
transport: MCPTransport.HTTP,
|
|
368
401
|
name: "mcp-server-1",
|
|
369
402
|
},
|
|
370
403
|
];
|
|
@@ -374,7 +407,9 @@ const mcpServers = [
|
|
|
374
407
|
apiKey={process.env.NEXT_PUBLIC_TAMBO_API_KEY!}
|
|
375
408
|
components={components}
|
|
376
409
|
>
|
|
377
|
-
<TamboMcpProvider mcpServers={mcpServers}>
|
|
410
|
+
<TamboMcpProvider mcpServers={mcpServers}>
|
|
411
|
+
<YourApp />
|
|
412
|
+
</TamboMcpProvider>
|
|
378
413
|
</TamboProvider>;
|
|
379
414
|
```
|
|
380
415
|
|
|
@@ -162,23 +162,15 @@ describe("useTamboThreadList", () => {
|
|
|
162
162
|
"isRefetching": false,
|
|
163
163
|
"isStale": true,
|
|
164
164
|
"isSuccess": false,
|
|
165
|
-
"promise": Promise {
|
|
166
|
-
"reason": [Error: experimental_prefetchInRender feature flag is not enabled],
|
|
167
|
-
"status": "rejected",
|
|
168
|
-
},
|
|
165
|
+
"promise": Promise {},
|
|
169
166
|
"refetch": [Function],
|
|
170
167
|
"status": "pending",
|
|
171
168
|
}
|
|
172
169
|
`);
|
|
173
|
-
expect(result.current.isLoading).toBe(true);
|
|
174
|
-
expect(result.current.data).toBeNull();
|
|
175
170
|
resolvePromise(mockThreads);
|
|
176
171
|
await (0, react_1.waitFor)(() => {
|
|
177
172
|
expect(result.current.isLoading).toBe(false);
|
|
178
173
|
});
|
|
179
|
-
await (0, react_1.waitFor)(() => {
|
|
180
|
-
expect(result.current.isLoading).toBe(false);
|
|
181
|
-
});
|
|
182
174
|
});
|
|
183
175
|
it("should handle error state", async () => {
|
|
184
176
|
const mockError = new Error("Failed to fetch threads");
|
|
@@ -1 +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 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 \"isEnabled\": true,\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"]}
|
|
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 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 \"isEnabled\": true,\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 \"refetch\": [Function],\n \"status\": \"pending\",\n }\n `);\n\n resolvePromise!(mockThreads);\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"]}
|
|
@@ -8,6 +8,8 @@ jest.mock("@modelcontextprotocol/sdk/client/index.js", () => ({
|
|
|
8
8
|
close: jest.fn(),
|
|
9
9
|
listTools: jest.fn(),
|
|
10
10
|
callTool: jest.fn(),
|
|
11
|
+
setRequestHandler: jest.fn(),
|
|
12
|
+
removeRequestHandler: jest.fn(),
|
|
11
13
|
onclose: null,
|
|
12
14
|
})),
|
|
13
15
|
}));
|
|
@@ -41,6 +43,8 @@ describe("MCPClient", () => {
|
|
|
41
43
|
close: jest.fn().mockResolvedValue(undefined),
|
|
42
44
|
listTools: jest.fn(),
|
|
43
45
|
callTool: jest.fn(),
|
|
46
|
+
setRequestHandler: jest.fn(),
|
|
47
|
+
removeRequestHandler: jest.fn(),
|
|
44
48
|
onclose: null,
|
|
45
49
|
};
|
|
46
50
|
mockTransportInstance = {
|
|
@@ -55,18 +59,18 @@ describe("MCPClient", () => {
|
|
|
55
59
|
it("should create and connect an MCPClient with HTTP transport by default", async () => {
|
|
56
60
|
const endpoint = "https://api.example.com/mcp";
|
|
57
61
|
const headers = { Authorization: "Bearer token" };
|
|
58
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, headers);
|
|
62
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, headers, undefined, undefined);
|
|
59
63
|
expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(new URL(endpoint), { sessionId: undefined, requestInit: { headers } });
|
|
60
64
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
61
65
|
name: "tambo-mcp-client",
|
|
62
66
|
version: "1.0.0",
|
|
63
|
-
});
|
|
67
|
+
}, { capabilities: {} });
|
|
64
68
|
expect(mockClientInstance.connect).toHaveBeenCalledWith(mockTransportInstance);
|
|
65
69
|
expect(client).toBeInstanceOf(mcp_client_1.MCPClient);
|
|
66
70
|
});
|
|
67
71
|
it("should create and connect an MCPClient with SSE transport", async () => {
|
|
68
72
|
const endpoint = "https://api.example.com/mcp";
|
|
69
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.SSE);
|
|
73
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.SSE, undefined, undefined, undefined);
|
|
70
74
|
expect(MockedSSEClientTransport).toHaveBeenCalledWith(new URL(endpoint), {
|
|
71
75
|
requestInit: { headers: {} },
|
|
72
76
|
});
|
|
@@ -75,14 +79,14 @@ describe("MCPClient", () => {
|
|
|
75
79
|
});
|
|
76
80
|
it("should create client with default headers when none provided", async () => {
|
|
77
81
|
const endpoint = "https://api.example.com/mcp";
|
|
78
|
-
await mcp_client_1.MCPClient.create(endpoint);
|
|
82
|
+
await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
79
83
|
expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(new URL(endpoint), { sessionId: undefined, requestInit: { headers: {} } });
|
|
80
84
|
});
|
|
81
85
|
});
|
|
82
86
|
describe("reconnect", () => {
|
|
83
87
|
it("should create new transport and client instances and call connect when reconnect() is called (default behavior)", async () => {
|
|
84
88
|
const endpoint = "https://api.example.com/mcp";
|
|
85
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
89
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
86
90
|
// Clear previous calls to focus on reconnect behavior
|
|
87
91
|
jest.clearAllMocks();
|
|
88
92
|
// Create new mock instances to verify new instances are created
|
|
@@ -108,13 +112,13 @@ describe("MCPClient", () => {
|
|
|
108
112
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
109
113
|
name: "tambo-mcp-client",
|
|
110
114
|
version: "1.0.0",
|
|
111
|
-
});
|
|
115
|
+
}, { capabilities: {} });
|
|
112
116
|
// Verify new client's connect was called with new transport
|
|
113
117
|
expect(newMockClientInstance.connect).toHaveBeenCalledWith(newMockTransportInstance);
|
|
114
118
|
});
|
|
115
119
|
it("should reconnect without session ID for SSE transport", async () => {
|
|
116
120
|
const endpoint = "https://api.example.com/mcp";
|
|
117
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.SSE);
|
|
121
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.SSE, undefined, undefined, undefined);
|
|
118
122
|
// Clear previous calls
|
|
119
123
|
jest.clearAllMocks();
|
|
120
124
|
await client.reconnect();
|
|
@@ -126,7 +130,7 @@ describe("MCPClient", () => {
|
|
|
126
130
|
});
|
|
127
131
|
it("should handle close errors when reportErrorOnClose is true", async () => {
|
|
128
132
|
const endpoint = "https://api.example.com/mcp";
|
|
129
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
133
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
130
134
|
const consoleSpy = jest.spyOn(console, "error").mockImplementation();
|
|
131
135
|
// Make close throw an error
|
|
132
136
|
mockClientInstance.close.mockRejectedValue(new Error("Close failed"));
|
|
@@ -136,7 +140,7 @@ describe("MCPClient", () => {
|
|
|
136
140
|
});
|
|
137
141
|
it("should not log close errors when reportErrorOnClose is false", async () => {
|
|
138
142
|
const endpoint = "https://api.example.com/mcp";
|
|
139
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
143
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
140
144
|
const consoleSpy = jest.spyOn(console, "error").mockImplementation();
|
|
141
145
|
// Make close throw an error
|
|
142
146
|
mockClientInstance.close.mockRejectedValue(new Error("Close failed"));
|
|
@@ -146,7 +150,7 @@ describe("MCPClient", () => {
|
|
|
146
150
|
});
|
|
147
151
|
it("should create new session when newSession is true", async () => {
|
|
148
152
|
const endpoint = "https://api.example.com/mcp";
|
|
149
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
153
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
150
154
|
// Clear previous calls to focus on reconnect behavior
|
|
151
155
|
jest.clearAllMocks();
|
|
152
156
|
// Create new mock instances to verify new instances are created
|
|
@@ -172,13 +176,13 @@ describe("MCPClient", () => {
|
|
|
172
176
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
173
177
|
name: "tambo-mcp-client",
|
|
174
178
|
version: "1.0.0",
|
|
175
|
-
});
|
|
179
|
+
}, { capabilities: {} });
|
|
176
180
|
// Verify new client's connect was called with new transport
|
|
177
181
|
expect(newMockClientInstance.connect).toHaveBeenCalledWith(newMockTransportInstance);
|
|
178
182
|
});
|
|
179
183
|
it("should reuse existing session when newSession is false (default)", async () => {
|
|
180
184
|
const endpoint = "https://api.example.com/mcp";
|
|
181
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
185
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
182
186
|
// Clear previous calls to focus on reconnect behavior
|
|
183
187
|
jest.clearAllMocks();
|
|
184
188
|
// Create new mock instances to verify new instances are created
|
|
@@ -204,7 +208,7 @@ describe("MCPClient", () => {
|
|
|
204
208
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
205
209
|
name: "tambo-mcp-client",
|
|
206
210
|
version: "1.0.0",
|
|
207
|
-
});
|
|
211
|
+
}, { capabilities: {} });
|
|
208
212
|
// Verify new client's connect was called with new transport
|
|
209
213
|
expect(newMockClientInstance.connect).toHaveBeenCalledWith(newMockTransportInstance);
|
|
210
214
|
});
|
|
@@ -212,7 +216,7 @@ describe("MCPClient", () => {
|
|
|
212
216
|
describe("onclose", () => {
|
|
213
217
|
it("should reconnect MCPClient when client is closed by external means (no backoff on manual preemption)", async () => {
|
|
214
218
|
const endpoint = "https://api.example.com/mcp";
|
|
215
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
219
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
216
220
|
jest.useFakeTimers();
|
|
217
221
|
const consoleSpy = jest.spyOn(console, "warn").mockImplementation();
|
|
218
222
|
// Create new mock instances to verify reconnection creates new instances
|
|
@@ -247,7 +251,7 @@ describe("MCPClient", () => {
|
|
|
247
251
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
248
252
|
name: "tambo-mcp-client",
|
|
249
253
|
version: "1.0.0",
|
|
250
|
-
});
|
|
254
|
+
}, { capabilities: {} });
|
|
251
255
|
// Verify new client's connect was called with new transport
|
|
252
256
|
expect(newMockClientInstance.connect).toHaveBeenCalledWith(newMockTransportInstance);
|
|
253
257
|
// Ensure only a single reconnect attempt occurred
|
|
@@ -260,7 +264,7 @@ describe("MCPClient", () => {
|
|
|
260
264
|
describe("reconnect re-entrancy and single-flight", () => {
|
|
261
265
|
it("prevents re-entrant onclose during deliberate close and coalesces concurrent calls", async () => {
|
|
262
266
|
const endpoint = "https://api.example.com/mcp";
|
|
263
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
267
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
264
268
|
// Simulate an implementation where closing the client would call its own onclose handler
|
|
265
269
|
const closeImpl = jest.fn(async () => {
|
|
266
270
|
if (typeof mockClientInstance.onclose === "function") {
|
|
@@ -302,7 +306,7 @@ describe("MCPClient", () => {
|
|
|
302
306
|
const setTimeoutSpy = jest.spyOn(global, "setTimeout");
|
|
303
307
|
const randSpy = jest.spyOn(Math, "random").mockReturnValue(0.0); // extreme low jitter
|
|
304
308
|
const endpoint = "https://api.example.com/mcp";
|
|
305
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
309
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
306
310
|
// Prepare one attempt that will succeed to avoid rescheduling
|
|
307
311
|
MockedClient.mockImplementation(() => ({
|
|
308
312
|
connect: jest.fn().mockResolvedValue(undefined),
|
|
@@ -340,7 +344,7 @@ describe("MCPClient", () => {
|
|
|
340
344
|
describe("listTools", () => {
|
|
341
345
|
it("should list all tools with pagination", async () => {
|
|
342
346
|
const endpoint = "https://api.example.com/mcp";
|
|
343
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
347
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
344
348
|
const mockTools = [
|
|
345
349
|
{
|
|
346
350
|
name: "tool1",
|
|
@@ -395,7 +399,7 @@ describe("MCPClient", () => {
|
|
|
395
399
|
});
|
|
396
400
|
it("should handle single page of tools", async () => {
|
|
397
401
|
const endpoint = "https://api.example.com/mcp";
|
|
398
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
402
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
399
403
|
const mockTools = [
|
|
400
404
|
{
|
|
401
405
|
name: "tool1",
|
|
@@ -426,7 +430,7 @@ describe("MCPClient", () => {
|
|
|
426
430
|
});
|
|
427
431
|
it("should throw error for invalid input schema", async () => {
|
|
428
432
|
const endpoint = "https://api.example.com/mcp";
|
|
429
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
433
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
430
434
|
const mockTools = [
|
|
431
435
|
{
|
|
432
436
|
name: "invalid-tool",
|
|
@@ -445,7 +449,7 @@ describe("MCPClient", () => {
|
|
|
445
449
|
describe("callTool", () => {
|
|
446
450
|
it("should call a tool with arguments", async () => {
|
|
447
451
|
const endpoint = "https://api.example.com/mcp";
|
|
448
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
452
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
449
453
|
const mockResult = { success: true, data: "test result" };
|
|
450
454
|
mockClientInstance.callTool.mockResolvedValue(mockResult);
|
|
451
455
|
const result = await client.callTool("testTool", {
|
|
@@ -460,7 +464,7 @@ describe("MCPClient", () => {
|
|
|
460
464
|
});
|
|
461
465
|
it("should handle tool call errors", async () => {
|
|
462
466
|
const endpoint = "https://api.example.com/mcp";
|
|
463
|
-
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP);
|
|
467
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
464
468
|
const error = new Error("Tool call failed");
|
|
465
469
|
mockClientInstance.callTool.mockRejectedValue(error);
|
|
466
470
|
await expect(client.callTool("testTool", {})).rejects.toThrow("Tool call failed");
|
|
@@ -470,13 +474,13 @@ describe("MCPClient", () => {
|
|
|
470
474
|
it("should initialize HTTP transport with session ID", async () => {
|
|
471
475
|
const endpoint = "https://api.example.com/mcp";
|
|
472
476
|
const headers = { Authorization: "Bearer token" };
|
|
473
|
-
await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, headers);
|
|
477
|
+
await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, headers, undefined, undefined);
|
|
474
478
|
expect(MockedStreamableHTTPClientTransport).toHaveBeenCalledWith(new URL(endpoint), { sessionId: undefined, requestInit: { headers } });
|
|
475
479
|
});
|
|
476
480
|
it("should initialize SSE transport without session ID", async () => {
|
|
477
481
|
const endpoint = "https://api.example.com/mcp";
|
|
478
482
|
const headers = { Authorization: "Bearer token" };
|
|
479
|
-
await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.SSE, headers);
|
|
483
|
+
await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.SSE, headers, undefined, undefined);
|
|
480
484
|
expect(MockedSSEClientTransport).toHaveBeenCalledWith(new URL(endpoint), {
|
|
481
485
|
requestInit: { headers },
|
|
482
486
|
});
|
|
@@ -485,18 +489,60 @@ describe("MCPClient", () => {
|
|
|
485
489
|
describe("client initialization", () => {
|
|
486
490
|
it("should initialize client with correct name and version", async () => {
|
|
487
491
|
const endpoint = "https://api.example.com/mcp";
|
|
488
|
-
await mcp_client_1.MCPClient.create(endpoint);
|
|
492
|
+
await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
489
493
|
expect(MockedClient).toHaveBeenCalledWith({
|
|
490
494
|
name: "tambo-mcp-client",
|
|
491
495
|
version: "1.0.0",
|
|
492
|
-
});
|
|
496
|
+
}, { capabilities: {} });
|
|
493
497
|
});
|
|
494
498
|
it("should set onclose handler", async () => {
|
|
495
499
|
const endpoint = "https://api.example.com/mcp";
|
|
496
|
-
const _client = await mcp_client_1.MCPClient.create(endpoint);
|
|
500
|
+
const _client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined);
|
|
497
501
|
expect(mockClientInstance.onclose).toBeDefined();
|
|
498
502
|
expect(typeof mockClientInstance.onclose).toBe("function");
|
|
499
503
|
});
|
|
500
504
|
});
|
|
505
|
+
describe("handlers (elicitation/sampling)", () => {
|
|
506
|
+
it("sets handlers on create when provided", async () => {
|
|
507
|
+
const endpoint = "https://api.example.com/mcp";
|
|
508
|
+
const elicitation = jest.fn(async () => ({}));
|
|
509
|
+
const sampling = jest.fn(async () => ({}));
|
|
510
|
+
await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined, { elicitation, sampling });
|
|
511
|
+
expect(MockedClient).toHaveBeenLastCalledWith({
|
|
512
|
+
name: "tambo-mcp-client",
|
|
513
|
+
version: "1.0.0",
|
|
514
|
+
}, {
|
|
515
|
+
capabilities: {
|
|
516
|
+
elicitation: {},
|
|
517
|
+
sampling: {},
|
|
518
|
+
},
|
|
519
|
+
});
|
|
520
|
+
// Request handlers should be set for both
|
|
521
|
+
expect(mockClientInstance.setRequestHandler).toHaveBeenCalled();
|
|
522
|
+
expect(mockClientInstance.setRequestHandler.mock.calls.length).toBeGreaterThanOrEqual(2);
|
|
523
|
+
});
|
|
524
|
+
it("removes elicitation handler when set to undefined", async () => {
|
|
525
|
+
const endpoint = "https://api.example.com/mcp";
|
|
526
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined, {
|
|
527
|
+
elicitation: async () => ({}),
|
|
528
|
+
});
|
|
529
|
+
const removeSpy = mockClientInstance.removeRequestHandler;
|
|
530
|
+
// then remove
|
|
531
|
+
removeSpy.mockClear();
|
|
532
|
+
await client.updateElicitationHandler(undefined);
|
|
533
|
+
expect(removeSpy).toHaveBeenCalledWith(expect.any(String));
|
|
534
|
+
});
|
|
535
|
+
it("removes sampling handler when set to undefined", async () => {
|
|
536
|
+
const endpoint = "https://api.example.com/mcp";
|
|
537
|
+
const client = await mcp_client_1.MCPClient.create(endpoint, mcp_client_1.MCPTransport.HTTP, undefined, undefined, undefined, {
|
|
538
|
+
sampling: async () => ({}),
|
|
539
|
+
});
|
|
540
|
+
const removeSpy = mockClientInstance.removeRequestHandler;
|
|
541
|
+
// then remove
|
|
542
|
+
removeSpy.mockClear();
|
|
543
|
+
await client.updateSamplingHandler(undefined);
|
|
544
|
+
expect(removeSpy).toHaveBeenCalledWith(expect.any(String));
|
|
545
|
+
});
|
|
546
|
+
});
|
|
501
547
|
});
|
|
502
548
|
//# sourceMappingURL=mcp-client.test.js.map
|