@tambo-ai/react 0.68.0 → 0.69.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 +1 -1
- package/dist/context-helpers/context-helpers.test.js +16 -4
- package/dist/context-helpers/context-helpers.test.js.map +1 -1
- package/dist/context-helpers/current-interactables-context-helper.d.ts +2 -2
- package/dist/context-helpers/current-interactables-context-helper.d.ts.map +1 -1
- package/dist/context-helpers/current-interactables-context-helper.js +31 -15
- package/dist/context-helpers/current-interactables-context-helper.js.map +1 -1
- package/dist/context-helpers/registry.d.ts +2 -2
- package/dist/context-helpers/registry.d.ts.map +1 -1
- package/dist/context-helpers/registry.js.map +1 -1
- package/dist/context-helpers/types.d.ts +2 -2
- package/dist/context-helpers/types.d.ts.map +1 -1
- package/dist/context-helpers/types.js.map +1 -1
- package/dist/hooks/use-message-images.test.js +174 -37
- package/dist/hooks/use-message-images.test.js.map +1 -1
- package/dist/hooks/use-tambo-voice.d.ts +1 -1
- package/dist/hooks/use-tambo-voice.js +1 -1
- package/dist/hooks/use-tambo-voice.js.map +1 -1
- package/dist/hooks/use-tambo-voice.test.d.ts +2 -0
- package/dist/hooks/use-tambo-voice.test.d.ts.map +1 -0
- package/dist/hooks/use-tambo-voice.test.js +239 -0
- package/dist/hooks/use-tambo-voice.test.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/elicitation.d.ts.map +1 -1
- package/dist/mcp/elicitation.js +12 -0
- package/dist/mcp/elicitation.js.map +1 -1
- package/dist/mcp/elicitation.test.js +8 -1
- package/dist/mcp/elicitation.test.js.map +1 -1
- package/dist/mcp/mcp-client.d.ts +6 -10
- package/dist/mcp/mcp-client.d.ts.map +1 -1
- package/dist/mcp/mcp-client.js.map +1 -1
- package/dist/mcp/mcp-hooks.d.ts +12 -60
- package/dist/mcp/mcp-hooks.d.ts.map +1 -1
- package/dist/mcp/mcp-hooks.js +90 -10
- package/dist/mcp/mcp-hooks.js.map +1 -1
- package/dist/mcp/mcp-hooks.test.js +423 -0
- package/dist/mcp/mcp-hooks.test.js.map +1 -1
- package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.js +3 -0
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/mcp/tambo-mcp-provider.test.js +37 -0
- package/dist/mcp/tambo-mcp-provider.test.js.map +1 -1
- package/dist/model/component-metadata.d.ts +53 -20
- package/dist/model/component-metadata.d.ts.map +1 -1
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/model/tambo-interactable.d.ts +6 -0
- package/dist/model/tambo-interactable.d.ts.map +1 -1
- package/dist/model/tambo-interactable.js.map +1 -1
- 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-client-provider.d.ts +8 -0
- package/dist/providers/tambo-client-provider.d.ts.map +1 -1
- package/dist/providers/tambo-client-provider.js +10 -11
- package/dist/providers/tambo-client-provider.js.map +1 -1
- package/dist/providers/tambo-client-provider.test.d.ts +2 -0
- package/dist/providers/tambo-client-provider.test.d.ts.map +1 -0
- package/dist/providers/tambo-client-provider.test.js +208 -0
- package/dist/providers/tambo-client-provider.test.js.map +1 -0
- package/dist/providers/tambo-context-attachment-provider.d.ts +34 -92
- package/dist/providers/tambo-context-attachment-provider.d.ts.map +1 -1
- package/dist/providers/tambo-context-attachment-provider.js +62 -105
- package/dist/providers/tambo-context-attachment-provider.js.map +1 -1
- package/dist/providers/tambo-context-attachment-provider.test.js +229 -463
- package/dist/providers/tambo-context-attachment-provider.test.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts +2 -0
- package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +29 -4
- package/dist/providers/tambo-interactable-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.test.js +1 -1
- package/dist/providers/tambo-interactable-provider.test.js.map +1 -1
- package/dist/providers/tambo-interactables-additional-context.test.js +2 -5
- package/dist/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts +2 -3
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js +5 -6
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-registry-provider.test.js +16 -0
- package/dist/providers/tambo-registry-provider.test.js.map +1 -1
- package/dist/providers/tambo-registry-schema-compat.test.js +31 -0
- package/dist/providers/tambo-registry-schema-compat.test.js.map +1 -1
- package/dist/providers/tambo-thread-input-provider.d.ts +1 -1
- package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-input-provider.js +5 -1
- package/dist/providers/tambo-thread-input-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider-initial-messages.test.js +84 -2
- package/dist/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js +53 -42
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.test.js +368 -262
- package/dist/providers/tambo-thread-provider.test.js.map +1 -1
- package/dist/schema/json-schema.js +29 -29
- package/dist/schema/json-schema.js.map +1 -1
- package/dist/schema/schema.test.js +237 -0
- package/dist/schema/schema.test.js.map +1 -1
- package/dist/schema/standard-schema.d.ts +1 -0
- package/dist/schema/standard-schema.d.ts.map +1 -1
- package/dist/schema/standard-schema.js +18 -13
- package/dist/schema/standard-schema.js.map +1 -1
- package/dist/schema/standard-schema.test.d.ts +2 -0
- package/dist/schema/standard-schema.test.d.ts.map +1 -0
- package/dist/schema/standard-schema.test.js +165 -0
- package/dist/schema/standard-schema.test.js.map +1 -0
- package/dist/schema/validate.test.js +149 -0
- package/dist/schema/validate.test.js.map +1 -1
- package/dist/schema/zod.d.ts +7 -4
- package/dist/schema/zod.d.ts.map +1 -1
- package/dist/schema/zod.js +65 -22
- package/dist/schema/zod.js.map +1 -1
- package/dist/schema/zod.test.js +112 -0
- package/dist/schema/zod.test.js.map +1 -1
- package/dist/testing/tools.d.ts +4 -1
- package/dist/testing/tools.d.ts.map +1 -1
- package/dist/testing/tools.js +6 -1
- package/dist/testing/tools.js.map +1 -1
- package/dist/util/generate-component.d.ts.map +1 -1
- package/dist/util/generate-component.js +18 -3
- package/dist/util/generate-component.js.map +1 -1
- package/dist/util/generate-component.test.d.ts +2 -0
- package/dist/util/generate-component.test.d.ts.map +1 -0
- package/dist/util/generate-component.test.js +340 -0
- package/dist/util/generate-component.test.js.map +1 -0
- package/dist/util/is-promise.d.ts +9 -0
- package/dist/util/is-promise.d.ts.map +1 -0
- package/dist/util/is-promise.js +20 -0
- package/dist/util/is-promise.js.map +1 -0
- package/dist/util/is-promise.test.d.ts +2 -0
- package/dist/util/is-promise.test.d.ts.map +1 -0
- package/dist/util/is-promise.test.js +48 -0
- package/dist/util/is-promise.test.js.map +1 -0
- package/dist/util/query-utils.test.d.ts +2 -0
- package/dist/util/query-utils.test.d.ts.map +1 -0
- package/dist/util/query-utils.test.js +382 -0
- package/dist/util/query-utils.test.js.map +1 -0
- package/dist/util/registry-validators.d.ts.map +1 -1
- package/dist/util/registry-validators.js +7 -0
- package/dist/util/registry-validators.js.map +1 -1
- package/dist/util/registry-validators.test.js +57 -0
- package/dist/util/registry-validators.test.js.map +1 -1
- package/dist/util/registry.d.ts.map +1 -1
- package/dist/util/registry.js +9 -0
- package/dist/util/registry.js.map +1 -1
- package/dist/util/registry.test.js +323 -1
- package/dist/util/registry.test.js.map +1 -1
- package/dist/util/resource-validators.test.d.ts +2 -0
- package/dist/util/resource-validators.test.d.ts.map +1 -0
- package/dist/util/resource-validators.test.js +90 -0
- package/dist/util/resource-validators.test.js.map +1 -0
- package/dist/util/tool-caller.d.ts +2 -2
- package/dist/util/tool-caller.d.ts.map +1 -1
- package/dist/util/tool-caller.js +8 -8
- package/dist/util/tool-caller.js.map +1 -1
- package/dist/util/validate-component-name.test.d.ts +2 -0
- package/dist/util/validate-component-name.test.d.ts.map +1 -0
- package/dist/util/validate-component-name.test.js +35 -0
- package/dist/util/validate-component-name.test.js.map +1 -0
- package/esm/context-helpers/context-helpers.test.js +16 -4
- package/esm/context-helpers/context-helpers.test.js.map +1 -1
- package/esm/context-helpers/current-interactables-context-helper.d.ts +2 -2
- package/esm/context-helpers/current-interactables-context-helper.d.ts.map +1 -1
- package/esm/context-helpers/current-interactables-context-helper.js +31 -15
- package/esm/context-helpers/current-interactables-context-helper.js.map +1 -1
- package/esm/context-helpers/registry.d.ts +2 -2
- package/esm/context-helpers/registry.d.ts.map +1 -1
- package/esm/context-helpers/registry.js.map +1 -1
- package/esm/context-helpers/types.d.ts +2 -2
- package/esm/context-helpers/types.d.ts.map +1 -1
- package/esm/context-helpers/types.js.map +1 -1
- package/esm/hooks/use-message-images.test.js +174 -37
- package/esm/hooks/use-message-images.test.js.map +1 -1
- package/esm/hooks/use-tambo-voice.d.ts +1 -1
- package/esm/hooks/use-tambo-voice.js +1 -1
- package/esm/hooks/use-tambo-voice.js.map +1 -1
- package/esm/hooks/use-tambo-voice.test.d.ts +2 -0
- package/esm/hooks/use-tambo-voice.test.d.ts.map +1 -0
- package/esm/hooks/use-tambo-voice.test.js +234 -0
- package/esm/hooks/use-tambo-voice.test.js.map +1 -0
- package/esm/index.d.ts +2 -2
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js.map +1 -1
- package/esm/mcp/elicitation.d.ts.map +1 -1
- package/esm/mcp/elicitation.js +12 -0
- package/esm/mcp/elicitation.js.map +1 -1
- package/esm/mcp/elicitation.test.js +8 -1
- package/esm/mcp/elicitation.test.js.map +1 -1
- package/esm/mcp/mcp-client.d.ts +6 -10
- package/esm/mcp/mcp-client.d.ts.map +1 -1
- package/esm/mcp/mcp-client.js.map +1 -1
- package/esm/mcp/mcp-hooks.d.ts +12 -60
- package/esm/mcp/mcp-hooks.d.ts.map +1 -1
- package/esm/mcp/mcp-hooks.js +57 -10
- package/esm/mcp/mcp-hooks.js.map +1 -1
- package/esm/mcp/mcp-hooks.test.js +423 -0
- package/esm/mcp/mcp-hooks.test.js.map +1 -1
- package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.js +3 -0
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/mcp/tambo-mcp-provider.test.js +37 -0
- package/esm/mcp/tambo-mcp-provider.test.js.map +1 -1
- package/esm/model/component-metadata.d.ts +53 -20
- package/esm/model/component-metadata.d.ts.map +1 -1
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/model/tambo-interactable.d.ts +6 -0
- package/esm/model/tambo-interactable.d.ts.map +1 -1
- package/esm/model/tambo-interactable.js.map +1 -1
- 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-client-provider.d.ts +8 -0
- package/esm/providers/tambo-client-provider.d.ts.map +1 -1
- package/esm/providers/tambo-client-provider.js +11 -12
- package/esm/providers/tambo-client-provider.js.map +1 -1
- package/esm/providers/tambo-client-provider.test.d.ts +2 -0
- package/esm/providers/tambo-client-provider.test.d.ts.map +1 -0
- package/esm/providers/tambo-client-provider.test.js +203 -0
- package/esm/providers/tambo-client-provider.test.js.map +1 -0
- package/esm/providers/tambo-context-attachment-provider.d.ts +34 -92
- package/esm/providers/tambo-context-attachment-provider.d.ts.map +1 -1
- package/esm/providers/tambo-context-attachment-provider.js +63 -106
- package/esm/providers/tambo-context-attachment-provider.js.map +1 -1
- package/esm/providers/tambo-context-attachment-provider.test.js +230 -464
- package/esm/providers/tambo-context-attachment-provider.test.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts +2 -0
- package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/esm/providers/tambo-interactable-provider.js +29 -4
- package/esm/providers/tambo-interactable-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.test.js +1 -1
- package/esm/providers/tambo-interactable-provider.test.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context.test.js +2 -5
- package/esm/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/esm/providers/tambo-provider.d.ts +2 -3
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js +5 -6
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-registry-provider.test.js +16 -0
- package/esm/providers/tambo-registry-provider.test.js.map +1 -1
- package/esm/providers/tambo-registry-schema-compat.test.js +31 -0
- package/esm/providers/tambo-registry-schema-compat.test.js.map +1 -1
- package/esm/providers/tambo-thread-input-provider.d.ts +1 -1
- package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-input-provider.js +5 -1
- package/esm/providers/tambo-thread-input-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider-initial-messages.test.js +84 -2
- package/esm/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js +53 -42
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.test.js +368 -262
- package/esm/providers/tambo-thread-provider.test.js.map +1 -1
- package/esm/schema/json-schema.js +1 -1
- package/esm/schema/json-schema.js.map +1 -1
- package/esm/schema/schema.test.js +238 -1
- package/esm/schema/schema.test.js.map +1 -1
- package/esm/schema/standard-schema.d.ts +1 -0
- package/esm/schema/standard-schema.d.ts.map +1 -1
- package/esm/schema/standard-schema.js +18 -13
- package/esm/schema/standard-schema.js.map +1 -1
- package/esm/schema/standard-schema.test.d.ts +2 -0
- package/esm/schema/standard-schema.test.d.ts.map +1 -0
- package/esm/schema/standard-schema.test.js +130 -0
- package/esm/schema/standard-schema.test.js.map +1 -0
- package/esm/schema/validate.test.js +149 -0
- package/esm/schema/validate.test.js.map +1 -1
- package/esm/schema/zod.d.ts +7 -4
- package/esm/schema/zod.d.ts.map +1 -1
- package/esm/schema/zod.js +65 -22
- package/esm/schema/zod.js.map +1 -1
- package/esm/schema/zod.test.js +113 -1
- package/esm/schema/zod.test.js.map +1 -1
- package/esm/testing/tools.d.ts +4 -1
- package/esm/testing/tools.d.ts.map +1 -1
- package/esm/testing/tools.js +6 -1
- package/esm/testing/tools.js.map +1 -1
- package/esm/util/generate-component.d.ts.map +1 -1
- package/esm/util/generate-component.js +18 -3
- package/esm/util/generate-component.js.map +1 -1
- package/esm/util/generate-component.test.d.ts +2 -0
- package/esm/util/generate-component.test.d.ts.map +1 -0
- package/esm/util/generate-component.test.js +302 -0
- package/esm/util/generate-component.test.js.map +1 -0
- package/esm/util/is-promise.d.ts +9 -0
- package/esm/util/is-promise.d.ts.map +1 -0
- package/esm/util/is-promise.js +17 -0
- package/esm/util/is-promise.js.map +1 -0
- package/esm/util/is-promise.test.d.ts +2 -0
- package/esm/util/is-promise.test.d.ts.map +1 -0
- package/esm/util/is-promise.test.js +46 -0
- package/esm/util/is-promise.test.js.map +1 -0
- package/esm/util/query-utils.test.d.ts +2 -0
- package/esm/util/query-utils.test.d.ts.map +1 -0
- package/esm/util/query-utils.test.js +380 -0
- package/esm/util/query-utils.test.js.map +1 -0
- package/esm/util/registry-validators.d.ts.map +1 -1
- package/esm/util/registry-validators.js +7 -0
- package/esm/util/registry-validators.js.map +1 -1
- package/esm/util/registry-validators.test.js +57 -0
- package/esm/util/registry-validators.test.js.map +1 -1
- package/esm/util/registry.d.ts.map +1 -1
- package/esm/util/registry.js +9 -0
- package/esm/util/registry.js.map +1 -1
- package/esm/util/registry.test.js +324 -2
- package/esm/util/registry.test.js.map +1 -1
- package/esm/util/resource-validators.test.d.ts +2 -0
- package/esm/util/resource-validators.test.d.ts.map +1 -0
- package/esm/util/resource-validators.test.js +88 -0
- package/esm/util/resource-validators.test.js.map +1 -0
- package/esm/util/tool-caller.d.ts +2 -2
- package/esm/util/tool-caller.d.ts.map +1 -1
- package/esm/util/tool-caller.js +8 -8
- package/esm/util/tool-caller.js.map +1 -1
- package/esm/util/validate-component-name.test.d.ts +2 -0
- package/esm/util/validate-component-name.test.d.ts.map +1 -0
- package/esm/util/validate-component-name.test.js +33 -0
- package/esm/util/validate-component-name.test.js.map +1 -0
- package/package.json +15 -23
- package/dist/schema/alias.d.ts +0 -3
- package/dist/schema/alias.d.ts.map +0 -1
- package/dist/schema/alias.js +0 -6
- package/dist/schema/alias.js.map +0 -1
- package/esm/schema/alias.d.ts +0 -3
- package/esm/schema/alias.d.ts.map +0 -1
- package/esm/schema/alias.js +0 -13
- package/esm/schema/alias.js.map +0 -1
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { renderHook } from "@testing-library/react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { TamboClientProvider, useIsTamboTokenUpdating, useTamboClient, useTamboQueryClient, } from "./tambo-client-provider";
|
|
4
|
+
// Mock the session token hook to control token fetching state
|
|
5
|
+
jest.mock("./hooks/use-tambo-session-token", () => ({
|
|
6
|
+
useTamboSessionToken: jest.fn(),
|
|
7
|
+
}));
|
|
8
|
+
import { useTamboSessionToken } from "./hooks/use-tambo-session-token";
|
|
9
|
+
// Add fetch polyfill for jsdom environment (TamboAI SDK requires it)
|
|
10
|
+
const mockFetch = jest.fn();
|
|
11
|
+
let previousFetch;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
mockFetch.mockReset();
|
|
14
|
+
previousFetch = global.fetch;
|
|
15
|
+
global.fetch = mockFetch;
|
|
16
|
+
});
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
global.fetch = previousFetch;
|
|
19
|
+
});
|
|
20
|
+
describe("TamboClientProvider", () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
// Default mock: not fetching
|
|
24
|
+
jest.mocked(useTamboSessionToken).mockReturnValue({
|
|
25
|
+
isFetching: false,
|
|
26
|
+
data: undefined,
|
|
27
|
+
error: null,
|
|
28
|
+
isLoading: false,
|
|
29
|
+
isError: false,
|
|
30
|
+
isSuccess: false,
|
|
31
|
+
status: "pending",
|
|
32
|
+
fetchStatus: "idle",
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
const createWrapper = (props) => {
|
|
36
|
+
const Wrapper = ({ children }) => (React.createElement(TamboClientProvider, { ...props }, children));
|
|
37
|
+
Wrapper.displayName = "TestWrapper";
|
|
38
|
+
return Wrapper;
|
|
39
|
+
};
|
|
40
|
+
describe("Client Configuration", () => {
|
|
41
|
+
it("should create client accessible via useTamboClient hook", () => {
|
|
42
|
+
const { result } = renderHook(() => useTamboClient(), {
|
|
43
|
+
wrapper: createWrapper({ apiKey: "test-api-key" }),
|
|
44
|
+
});
|
|
45
|
+
// Client should be a TamboAI instance with expected shape
|
|
46
|
+
expect(result.current).toBeDefined();
|
|
47
|
+
expect(result.current.beta).toBeDefined();
|
|
48
|
+
});
|
|
49
|
+
it("should provide the same client instance on re-renders", () => {
|
|
50
|
+
const { result, rerender } = renderHook(() => useTamboClient(), {
|
|
51
|
+
wrapper: createWrapper({ apiKey: "test-api-key" }),
|
|
52
|
+
});
|
|
53
|
+
const firstClient = result.current;
|
|
54
|
+
rerender();
|
|
55
|
+
const secondClient = result.current;
|
|
56
|
+
expect(firstClient).toBe(secondClient);
|
|
57
|
+
});
|
|
58
|
+
it("should configure client with provided tamboUrl", () => {
|
|
59
|
+
const { result } = renderHook(() => useTamboClient(), {
|
|
60
|
+
wrapper: createWrapper({
|
|
61
|
+
apiKey: "test-api-key",
|
|
62
|
+
tamboUrl: "https://custom.tambo.api",
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
expect(result.current.baseURL).toBe("https://custom.tambo.api");
|
|
66
|
+
});
|
|
67
|
+
it("should configure client with provided environment", async () => {
|
|
68
|
+
const { result } = renderHook(() => useTamboClient(), {
|
|
69
|
+
wrapper: createWrapper({
|
|
70
|
+
apiKey: "test-api-key",
|
|
71
|
+
environment: "staging",
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
74
|
+
const { url } = await result.current.buildRequest({
|
|
75
|
+
method: "get",
|
|
76
|
+
path: "/test-endpoint",
|
|
77
|
+
});
|
|
78
|
+
expect(url).toBe("https://hydra-api-dev.up.railway.app/test-endpoint");
|
|
79
|
+
});
|
|
80
|
+
it("should throw if both tamboUrl and environment are provided", () => {
|
|
81
|
+
const consoleSpy = jest.spyOn(console, "error").mockImplementation();
|
|
82
|
+
expect(() => {
|
|
83
|
+
renderHook(() => useTamboClient(), {
|
|
84
|
+
wrapper: createWrapper({
|
|
85
|
+
apiKey: "test-api-key",
|
|
86
|
+
tamboUrl: "https://custom.tambo.api",
|
|
87
|
+
environment: "staging",
|
|
88
|
+
}),
|
|
89
|
+
});
|
|
90
|
+
}).toThrow("Ambiguous URL; The `baseURL` option (or TAMBO_AI_BASE_URL env var) and the `environment` option are given. If you want to use the environment you must pass baseURL: null");
|
|
91
|
+
consoleSpy.mockRestore();
|
|
92
|
+
});
|
|
93
|
+
it("should include additional headers in client configuration", async () => {
|
|
94
|
+
const { result } = renderHook(() => useTamboClient(), {
|
|
95
|
+
wrapper: createWrapper({
|
|
96
|
+
apiKey: "test-api-key",
|
|
97
|
+
additionalHeaders: {
|
|
98
|
+
"X-Custom-Header": "custom-value",
|
|
99
|
+
"X-Another-Header": "another-value",
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
});
|
|
103
|
+
const { req } = await result.current.buildRequest({
|
|
104
|
+
method: "get",
|
|
105
|
+
path: "/test-endpoint",
|
|
106
|
+
});
|
|
107
|
+
expect(req.headers.get("X-Tambo-React-Version")).toBeDefined();
|
|
108
|
+
expect(req.headers.get("X-Tambo-React-Version")).toMatch(/\d+\.\d+\.\d+/); // version format
|
|
109
|
+
expect(req.headers.get("X-Custom-Header")).toBe("custom-value");
|
|
110
|
+
expect(req.headers.get("X-Another-Header")).toBe("another-value");
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
describe("Token State", () => {
|
|
114
|
+
it("should expose isUpdatingToken=true when session token is fetching", () => {
|
|
115
|
+
jest.mocked(useTamboSessionToken).mockReturnValue({
|
|
116
|
+
isFetching: true,
|
|
117
|
+
});
|
|
118
|
+
const { result } = renderHook(() => useIsTamboTokenUpdating(), {
|
|
119
|
+
wrapper: createWrapper({
|
|
120
|
+
apiKey: "test-api-key",
|
|
121
|
+
userToken: "oauth-token",
|
|
122
|
+
}),
|
|
123
|
+
});
|
|
124
|
+
expect(result.current).toBe(true);
|
|
125
|
+
});
|
|
126
|
+
it("should expose isUpdatingToken=false when not fetching", () => {
|
|
127
|
+
jest.mocked(useTamboSessionToken).mockReturnValue({
|
|
128
|
+
isFetching: false,
|
|
129
|
+
});
|
|
130
|
+
const { result } = renderHook(() => useIsTamboTokenUpdating(), {
|
|
131
|
+
wrapper: createWrapper({ apiKey: "test-api-key" }),
|
|
132
|
+
});
|
|
133
|
+
expect(result.current).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
it("should call useTamboSessionToken with userToken when provided", () => {
|
|
136
|
+
renderHook(() => useTamboClient(), {
|
|
137
|
+
wrapper: createWrapper({
|
|
138
|
+
apiKey: "test-api-key",
|
|
139
|
+
userToken: "my-oauth-token",
|
|
140
|
+
}),
|
|
141
|
+
});
|
|
142
|
+
expect(useTamboSessionToken).toHaveBeenCalledWith(expect.anything(), // client
|
|
143
|
+
expect.anything(), // queryClient
|
|
144
|
+
"my-oauth-token");
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
describe("Hook Contracts", () => {
|
|
149
|
+
beforeEach(() => {
|
|
150
|
+
jest.clearAllMocks();
|
|
151
|
+
jest.mocked(useTamboSessionToken).mockReturnValue({
|
|
152
|
+
isFetching: false,
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
const createWrapper = (props) => {
|
|
156
|
+
const Wrapper = ({ children }) => (React.createElement(TamboClientProvider, { ...props }, children));
|
|
157
|
+
Wrapper.displayName = "TestWrapper";
|
|
158
|
+
return Wrapper;
|
|
159
|
+
};
|
|
160
|
+
describe("useTamboClient", () => {
|
|
161
|
+
it("should return client instance inside provider", () => {
|
|
162
|
+
const { result } = renderHook(() => useTamboClient(), {
|
|
163
|
+
wrapper: createWrapper({ apiKey: "test-api-key" }),
|
|
164
|
+
});
|
|
165
|
+
expect(result.current).toBeDefined();
|
|
166
|
+
expect(result.current.beta).toBeDefined();
|
|
167
|
+
});
|
|
168
|
+
it("should throw descriptive error outside provider", () => {
|
|
169
|
+
// Suppress console.error for this test
|
|
170
|
+
const consoleSpy = jest.spyOn(console, "error").mockImplementation();
|
|
171
|
+
expect(() => {
|
|
172
|
+
renderHook(() => useTamboClient());
|
|
173
|
+
}).toThrow("useTamboClient must be used within a TamboClientProvider");
|
|
174
|
+
consoleSpy.mockRestore();
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
describe("useTamboQueryClient", () => {
|
|
178
|
+
it("should return QueryClient instance inside provider", () => {
|
|
179
|
+
const { result } = renderHook(() => useTamboQueryClient(), {
|
|
180
|
+
wrapper: createWrapper({ apiKey: "test-api-key" }),
|
|
181
|
+
});
|
|
182
|
+
expect(result.current).toBeDefined();
|
|
183
|
+
expect(typeof result.current.getQueryCache).toBe("function");
|
|
184
|
+
});
|
|
185
|
+
it("should throw descriptive error outside provider", () => {
|
|
186
|
+
const consoleSpy = jest.spyOn(console, "error").mockImplementation();
|
|
187
|
+
expect(() => {
|
|
188
|
+
renderHook(() => useTamboQueryClient());
|
|
189
|
+
}).toThrow("useTamboQueryClient must be used within a TamboClientProvider");
|
|
190
|
+
consoleSpy.mockRestore();
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
describe("useIsTamboTokenUpdating", () => {
|
|
194
|
+
it("should throw descriptive error outside provider", () => {
|
|
195
|
+
const consoleSpy = jest.spyOn(console, "error").mockImplementation();
|
|
196
|
+
expect(() => {
|
|
197
|
+
renderHook(() => useIsTamboTokenUpdating());
|
|
198
|
+
}).toThrow("useIsTamboTokenUpdating must be used within a TamboClientProvider");
|
|
199
|
+
consoleSpy.mockRestore();
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
//# sourceMappingURL=tambo-client-provider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tambo-client-provider.test.js","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { renderHook } from \"@testing-library/react\";\nimport React from \"react\";\nimport {\n TamboClientProvider,\n TamboClientProviderProps,\n useIsTamboTokenUpdating,\n useTamboClient,\n useTamboQueryClient,\n} from \"./tambo-client-provider\";\n\n// Mock the session token hook to control token fetching state\njest.mock(\"./hooks/use-tambo-session-token\", () => ({\n useTamboSessionToken: jest.fn(),\n}));\n\nimport { useTamboSessionToken } from \"./hooks/use-tambo-session-token\";\n\n// Add fetch polyfill for jsdom environment (TamboAI SDK requires it)\nconst mockFetch = jest.fn();\nlet previousFetch: typeof fetch;\n\nbeforeEach(() => {\n mockFetch.mockReset();\n previousFetch = global.fetch;\n global.fetch = mockFetch as unknown as typeof fetch;\n});\n\nafterEach(() => {\n global.fetch = previousFetch;\n});\n\ndescribe(\"TamboClientProvider\", () => {\n beforeEach(() => {\n jest.clearAllMocks();\n\n // Default mock: not fetching\n jest.mocked(useTamboSessionToken).mockReturnValue({\n isFetching: false,\n data: undefined,\n error: null,\n isLoading: false,\n isError: false,\n isSuccess: false,\n status: \"pending\",\n fetchStatus: \"idle\",\n } as any);\n });\n\n const createWrapper = (props: TamboClientProviderProps) => {\n const Wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboClientProvider {...props}>{children}</TamboClientProvider>\n );\n Wrapper.displayName = \"TestWrapper\";\n return Wrapper;\n };\n\n describe(\"Client Configuration\", () => {\n it(\"should create client accessible via useTamboClient hook\", () => {\n const { result } = renderHook(() => useTamboClient(), {\n wrapper: createWrapper({ apiKey: \"test-api-key\" }),\n });\n\n // Client should be a TamboAI instance with expected shape\n expect(result.current).toBeDefined();\n expect(result.current.beta).toBeDefined();\n });\n\n it(\"should provide the same client instance on re-renders\", () => {\n const { result, rerender } = renderHook(() => useTamboClient(), {\n wrapper: createWrapper({ apiKey: \"test-api-key\" }),\n });\n\n const firstClient = result.current;\n rerender();\n const secondClient = result.current;\n\n expect(firstClient).toBe(secondClient);\n });\n\n it(\"should configure client with provided tamboUrl\", () => {\n const { result } = renderHook(() => useTamboClient(), {\n wrapper: createWrapper({\n apiKey: \"test-api-key\",\n tamboUrl: \"https://custom.tambo.api\",\n }),\n });\n\n expect(result.current.baseURL).toBe(\"https://custom.tambo.api\");\n });\n\n it(\"should configure client with provided environment\", async () => {\n const { result } = renderHook(() => useTamboClient(), {\n wrapper: createWrapper({\n apiKey: \"test-api-key\",\n environment: \"staging\",\n }),\n });\n\n const { url } = await result.current.buildRequest({\n method: \"get\",\n path: \"/test-endpoint\",\n });\n\n expect(url).toBe(\"https://hydra-api-dev.up.railway.app/test-endpoint\");\n });\n\n it(\"should throw if both tamboUrl and environment are provided\", () => {\n const consoleSpy = jest.spyOn(console, \"error\").mockImplementation();\n\n expect(() => {\n renderHook(() => useTamboClient(), {\n wrapper: createWrapper({\n apiKey: \"test-api-key\",\n tamboUrl: \"https://custom.tambo.api\",\n environment: \"staging\",\n }),\n });\n }).toThrow(\n \"Ambiguous URL; The `baseURL` option (or TAMBO_AI_BASE_URL env var) and the `environment` option are given. If you want to use the environment you must pass baseURL: null\",\n );\n\n consoleSpy.mockRestore();\n });\n\n it(\"should include additional headers in client configuration\", async () => {\n const { result } = renderHook(() => useTamboClient(), {\n wrapper: createWrapper({\n apiKey: \"test-api-key\",\n additionalHeaders: {\n \"X-Custom-Header\": \"custom-value\",\n \"X-Another-Header\": \"another-value\",\n },\n }),\n });\n\n const { req } = await result.current.buildRequest({\n method: \"get\",\n path: \"/test-endpoint\",\n });\n\n expect(req.headers.get(\"X-Tambo-React-Version\")).toBeDefined();\n expect(req.headers.get(\"X-Tambo-React-Version\")).toMatch(/\\d+\\.\\d+\\.\\d+/); // version format\n expect(req.headers.get(\"X-Custom-Header\")).toBe(\"custom-value\");\n expect(req.headers.get(\"X-Another-Header\")).toBe(\"another-value\");\n });\n });\n\n describe(\"Token State\", () => {\n it(\"should expose isUpdatingToken=true when session token is fetching\", () => {\n jest.mocked(useTamboSessionToken).mockReturnValue({\n isFetching: true,\n } as any);\n\n const { result } = renderHook(() => useIsTamboTokenUpdating(), {\n wrapper: createWrapper({\n apiKey: \"test-api-key\",\n userToken: \"oauth-token\",\n }),\n });\n\n expect(result.current).toBe(true);\n });\n\n it(\"should expose isUpdatingToken=false when not fetching\", () => {\n jest.mocked(useTamboSessionToken).mockReturnValue({\n isFetching: false,\n } as any);\n\n const { result } = renderHook(() => useIsTamboTokenUpdating(), {\n wrapper: createWrapper({ apiKey: \"test-api-key\" }),\n });\n\n expect(result.current).toBe(false);\n });\n\n it(\"should call useTamboSessionToken with userToken when provided\", () => {\n renderHook(() => useTamboClient(), {\n wrapper: createWrapper({\n apiKey: \"test-api-key\",\n userToken: \"my-oauth-token\",\n }),\n });\n\n expect(useTamboSessionToken).toHaveBeenCalledWith(\n expect.anything(), // client\n expect.anything(), // queryClient\n \"my-oauth-token\",\n );\n });\n });\n});\n\ndescribe(\"Hook Contracts\", () => {\n beforeEach(() => {\n jest.clearAllMocks();\n\n jest.mocked(useTamboSessionToken).mockReturnValue({\n isFetching: false,\n } as any);\n });\n\n const createWrapper = (props: { apiKey: string }) => {\n const Wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboClientProvider {...props}>{children}</TamboClientProvider>\n );\n Wrapper.displayName = \"TestWrapper\";\n return Wrapper;\n };\n\n describe(\"useTamboClient\", () => {\n it(\"should return client instance inside provider\", () => {\n const { result } = renderHook(() => useTamboClient(), {\n wrapper: createWrapper({ apiKey: \"test-api-key\" }),\n });\n\n expect(result.current).toBeDefined();\n expect(result.current.beta).toBeDefined();\n });\n\n it(\"should throw descriptive error outside provider\", () => {\n // Suppress console.error for this test\n const consoleSpy = jest.spyOn(console, \"error\").mockImplementation();\n\n expect(() => {\n renderHook(() => useTamboClient());\n }).toThrow(\"useTamboClient must be used within a TamboClientProvider\");\n\n consoleSpy.mockRestore();\n });\n });\n\n describe(\"useTamboQueryClient\", () => {\n it(\"should return QueryClient instance inside provider\", () => {\n const { result } = renderHook(() => useTamboQueryClient(), {\n wrapper: createWrapper({ apiKey: \"test-api-key\" }),\n });\n\n expect(result.current).toBeDefined();\n expect(typeof result.current.getQueryCache).toBe(\"function\");\n });\n\n it(\"should throw descriptive error outside provider\", () => {\n const consoleSpy = jest.spyOn(console, \"error\").mockImplementation();\n\n expect(() => {\n renderHook(() => useTamboQueryClient());\n }).toThrow(\n \"useTamboQueryClient must be used within a TamboClientProvider\",\n );\n\n consoleSpy.mockRestore();\n });\n });\n\n describe(\"useIsTamboTokenUpdating\", () => {\n it(\"should throw descriptive error outside provider\", () => {\n const consoleSpy = jest.spyOn(console, \"error\").mockImplementation();\n\n expect(() => {\n renderHook(() => useIsTamboTokenUpdating());\n }).toThrow(\n \"useIsTamboTokenUpdating must be used within a TamboClientProvider\",\n );\n\n consoleSpy.mockRestore();\n });\n });\n});\n"]}
|
|
@@ -1,110 +1,52 @@
|
|
|
1
|
-
import type { Suggestion } from "@tambo-ai/typescript-sdk/resources/beta/threads/suggestions";
|
|
2
1
|
import React from "react";
|
|
3
2
|
/**
|
|
4
|
-
* Represents a context attachment that
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* @property {string}
|
|
8
|
-
* @property {
|
|
9
|
-
* @property {
|
|
10
|
-
* @
|
|
11
|
-
* ```tsx
|
|
12
|
-
* const context: ContextAttachment = {
|
|
13
|
-
* name: "Button.tsx",
|
|
14
|
-
* icon: <FileIcon />,
|
|
15
|
-
* metadata: { filePath: "/src/components/Button.tsx" }
|
|
16
|
-
* };
|
|
17
|
-
* ```
|
|
3
|
+
* Represents a context attachment that will be sent with the next user message.
|
|
4
|
+
* These are automatically registered as context helpers and will be included in
|
|
5
|
+
* the additionalContext when the next message is sent.
|
|
6
|
+
* @property {string} id - Unique identifier for this context attachment
|
|
7
|
+
* @property {string} [displayName] - Optional display name for UI rendering
|
|
8
|
+
* @property {string} context - The context value that will be used in additionalContext
|
|
9
|
+
* @property {string} [type] - Optional type identifier for grouping/rendering multiple contexts of the same type
|
|
18
10
|
*/
|
|
19
11
|
export interface ContextAttachment {
|
|
20
12
|
id: string;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
displayName?: string;
|
|
14
|
+
context: string;
|
|
15
|
+
type?: string;
|
|
24
16
|
}
|
|
25
17
|
/**
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Context state interface for managing context attachments and custom suggestions.
|
|
31
|
-
* @property {ContextAttachment[]} attachments - Array of active context attachments (badges above message input)
|
|
32
|
-
* @property {(context: Omit<ContextAttachment, "id">) => void} addContextAttachment - Add a new context attachment
|
|
18
|
+
* Context state interface for managing context attachments.
|
|
19
|
+
* @property {ContextAttachment[]} attachments - Array of active context attachments
|
|
20
|
+
* @property {(contextAttachment: Omit<ContextAttachment, "id">) => ContextAttachment} addContextAttachment - Add a new context attachment, returns the attachment
|
|
33
21
|
* @property {(id: string) => void} removeContextAttachment - Remove a context attachment by ID
|
|
34
|
-
* @property {() => void} clearContextAttachments - Remove all context attachments
|
|
35
|
-
* @property {Suggestion[] | null} customSuggestions - Custom suggestions to display instead of auto-generated ones
|
|
36
|
-
* @property {(suggestions: Suggestion[] | null) => void} setCustomSuggestions - Set or clear custom suggestions
|
|
22
|
+
* @property {() => void} clearContextAttachments - Remove all context attachments
|
|
37
23
|
*/
|
|
38
24
|
export interface ContextAttachmentState {
|
|
39
25
|
attachments: ContextAttachment[];
|
|
40
|
-
addContextAttachment: (
|
|
26
|
+
addContextAttachment: (contextAttachment: Omit<ContextAttachment, "id">) => ContextAttachment;
|
|
41
27
|
removeContextAttachment: (id: string) => void;
|
|
42
28
|
clearContextAttachments: () => void;
|
|
43
|
-
customSuggestions: Suggestion[] | null;
|
|
44
|
-
setCustomSuggestions: (suggestions: Suggestion[] | null) => void;
|
|
45
29
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Props for the TamboContextAttachmentProvider.
|
|
48
|
-
* @property {(context: ContextAttachment) => Promise<ContextHelperData> | ContextHelperData} [getContextHelperData] - Optional function to customize the data sent to the AI for each context. If not provided, uses a default structure with the context name and instruction.
|
|
49
|
-
* @example
|
|
50
|
-
* ```tsx
|
|
51
|
-
* <TamboContextAttachmentProvider
|
|
52
|
-
* getContextHelperData={(context) => ({
|
|
53
|
-
* selectedFile: {
|
|
54
|
-
* name: context.name,
|
|
55
|
-
* path: context.metadata?.filePath,
|
|
56
|
-
* instruction: "Focus on this file"
|
|
57
|
-
* }
|
|
58
|
-
* })}
|
|
59
|
-
* >
|
|
60
|
-
* {children}
|
|
61
|
-
* </TamboContextAttachmentProvider>
|
|
62
|
-
* ```
|
|
63
|
-
*/
|
|
64
30
|
export interface TamboContextAttachmentProviderProps {
|
|
65
31
|
children?: React.ReactNode;
|
|
66
|
-
getContextHelperData?: (context: ContextAttachment) => Promise<ContextHelperData> | ContextHelperData;
|
|
67
32
|
}
|
|
68
33
|
/**
|
|
69
|
-
* Provider that
|
|
70
|
-
* **When to use:**
|
|
34
|
+
* Provider that manages context attachments for the next user message.
|
|
71
35
|
* - **Included by default** in TamboProvider - no need to wrap separately
|
|
72
36
|
* - Use `useTamboContextAttachment()` hook to manage context attachments
|
|
73
37
|
* **What it does:**
|
|
74
|
-
* -
|
|
75
|
-
* -
|
|
76
|
-
* -
|
|
77
|
-
* -
|
|
78
|
-
*
|
|
38
|
+
* - Stores context attachments that will be sent with the next message
|
|
39
|
+
* - Automatically registers/deregisters context helpers for each attachment
|
|
40
|
+
* - Context helpers are automatically collected during message submission
|
|
41
|
+
* - Context attachments are cleared after message submission (one-time use)
|
|
42
|
+
*
|
|
43
|
+
* **Note:** Context attachments are automatically included in additionalContext when
|
|
44
|
+
* the next message is sent. They are cleared after submission.
|
|
79
45
|
* @param props - The props for the TamboContextAttachmentProvider
|
|
80
46
|
* @param props.children - The children to wrap
|
|
81
|
-
* @param props.getContextHelperData - The function to get the context helper data
|
|
82
47
|
* @returns The TamboContextAttachmentProvider component
|
|
83
|
-
* @example
|
|
84
|
-
* Basic usage - already included in TamboProvider
|
|
85
|
-
* ```tsx
|
|
86
|
-
* <TamboProvider apiKey="...">
|
|
87
|
-
* <App />
|
|
88
|
-
* </TamboProvider>
|
|
89
|
-
* ```
|
|
90
|
-
* @example
|
|
91
|
-
* Using TamboProvider with custom context data
|
|
92
|
-
* ```tsx
|
|
93
|
-
* <TamboProvider
|
|
94
|
-
* apiKey="..."
|
|
95
|
-
* getContextHelperData={(context) => ({
|
|
96
|
-
* selectedComponent: {
|
|
97
|
-
* name: context.name,
|
|
98
|
-
* filePath: context.metadata?.path,
|
|
99
|
-
* instruction: "Edit this component"
|
|
100
|
-
* }
|
|
101
|
-
* })}
|
|
102
|
-
* >
|
|
103
|
-
* <App />
|
|
104
|
-
* </TamboProvider>
|
|
105
|
-
* ```
|
|
106
48
|
*/
|
|
107
|
-
export declare function TamboContextAttachmentProvider({ children,
|
|
49
|
+
export declare function TamboContextAttachmentProvider({ children, }: TamboContextAttachmentProviderProps): React.JSX.Element;
|
|
108
50
|
/**
|
|
109
51
|
* Hook to access context attachment state and methods.
|
|
110
52
|
* **Must be used within a `TamboProvider`** - throws an error otherwise.
|
|
@@ -112,20 +54,20 @@ export declare function TamboContextAttachmentProvider({ children, getContextHel
|
|
|
112
54
|
* @returns The context attachment state and methods
|
|
113
55
|
* @example
|
|
114
56
|
* ```tsx
|
|
115
|
-
* const
|
|
57
|
+
* const { addContextAttachment, attachments, clearContextAttachments } = useTamboContextAttachment();
|
|
116
58
|
*
|
|
117
|
-
* // Add a context
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
59
|
+
* // Add a context attachment for the next message
|
|
60
|
+
* const attachment = addContextAttachment({
|
|
61
|
+
* context: "The contents of File.txt",
|
|
62
|
+
* displayName: "File.txt", // optional
|
|
63
|
+
* type: "file" // optional
|
|
122
64
|
* });
|
|
123
65
|
*
|
|
124
|
-
* // Remove a context
|
|
125
|
-
*
|
|
66
|
+
* // Remove a context attachment
|
|
67
|
+
* removeContextAttachment(attachment.id);
|
|
126
68
|
*
|
|
127
|
-
* //
|
|
128
|
-
*
|
|
69
|
+
* // Clear all context attachments
|
|
70
|
+
* clearContextAttachments();
|
|
129
71
|
* ```
|
|
130
72
|
*/
|
|
131
73
|
export declare function useTamboContextAttachment(): ContextAttachmentState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tambo-context-attachment-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-context-attachment-provider.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"tambo-context-attachment-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-context-attachment-provider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAON,MAAM,OAAO,CAAC;AAGf;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,oBAAoB,EAAE,CACpB,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,KAC7C,iBAAiB,CAAC;IACvB,uBAAuB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,uBAAuB,EAAE,MAAM,IAAI,CAAC;CACrC;AAMD,MAAM,WAAW,mCAAmC;IAClD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,8BAA8B,CAAC,EAC7C,QAAQ,GACT,EAAE,mCAAmC,qBAuFrC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,yBAAyB,2BAQxC"}
|
|
@@ -1,117 +1,77 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import React, { createContext, useCallback, useContext, useEffect, useMemo,
|
|
2
|
+
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react";
|
|
3
3
|
import { useTamboContextHelpers } from "./tambo-context-helpers-provider";
|
|
4
4
|
const ContextAttachmentContext = createContext(null);
|
|
5
|
+
const CONTEXT_ATTACHMENTS_HELPER_KEY = "contextAttachments";
|
|
5
6
|
/**
|
|
6
|
-
* Provider that
|
|
7
|
-
* **When to use:**
|
|
7
|
+
* Provider that manages context attachments for the next user message.
|
|
8
8
|
* - **Included by default** in TamboProvider - no need to wrap separately
|
|
9
9
|
* - Use `useTamboContextAttachment()` hook to manage context attachments
|
|
10
10
|
* **What it does:**
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
*
|
|
11
|
+
* - Stores context attachments that will be sent with the next message
|
|
12
|
+
* - Automatically registers/deregisters context helpers for each attachment
|
|
13
|
+
* - Context helpers are automatically collected during message submission
|
|
14
|
+
* - Context attachments are cleared after message submission (one-time use)
|
|
15
|
+
*
|
|
16
|
+
* **Note:** Context attachments are automatically included in additionalContext when
|
|
17
|
+
* the next message is sent. They are cleared after submission.
|
|
16
18
|
* @param props - The props for the TamboContextAttachmentProvider
|
|
17
19
|
* @param props.children - The children to wrap
|
|
18
|
-
* @param props.getContextHelperData - The function to get the context helper data
|
|
19
20
|
* @returns The TamboContextAttachmentProvider component
|
|
20
|
-
* @example
|
|
21
|
-
* Basic usage - already included in TamboProvider
|
|
22
|
-
* ```tsx
|
|
23
|
-
* <TamboProvider apiKey="...">
|
|
24
|
-
* <App />
|
|
25
|
-
* </TamboProvider>
|
|
26
|
-
* ```
|
|
27
|
-
* @example
|
|
28
|
-
* Using TamboProvider with custom context data
|
|
29
|
-
* ```tsx
|
|
30
|
-
* <TamboProvider
|
|
31
|
-
* apiKey="..."
|
|
32
|
-
* getContextHelperData={(context) => ({
|
|
33
|
-
* selectedComponent: {
|
|
34
|
-
* name: context.name,
|
|
35
|
-
* filePath: context.metadata?.path,
|
|
36
|
-
* instruction: "Edit this component"
|
|
37
|
-
* }
|
|
38
|
-
* })}
|
|
39
|
-
* >
|
|
40
|
-
* <App />
|
|
41
|
-
* </TamboProvider>
|
|
42
|
-
* ```
|
|
43
21
|
*/
|
|
44
|
-
export function TamboContextAttachmentProvider({ children,
|
|
45
|
-
const [attachments, setAttachments] = useState([]);
|
|
46
|
-
const [customSuggestions, setCustomSuggestions] = useState(null);
|
|
22
|
+
export function TamboContextAttachmentProvider({ children, }) {
|
|
47
23
|
const { addContextHelper, removeContextHelper } = useTamboContextHelpers();
|
|
48
|
-
|
|
49
|
-
const registeredIdsRef = useRef(new Set());
|
|
50
|
-
const prevGetContextHelperDataRef = useRef();
|
|
51
|
-
// Sync context helpers with attachments using useEffect
|
|
24
|
+
const [attachments, setAttachments] = useState([]);
|
|
52
25
|
useEffect(() => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
registeredIds.forEach((id) => {
|
|
57
|
-
if (!currentIds.includes(id)) {
|
|
58
|
-
removeContextHelper(id);
|
|
59
|
-
registeredIds.delete(id);
|
|
26
|
+
addContextHelper(CONTEXT_ATTACHMENTS_HELPER_KEY, () => {
|
|
27
|
+
if (attachments.length === 0) {
|
|
28
|
+
return null;
|
|
60
29
|
}
|
|
30
|
+
return attachments.map((attachment) => ({
|
|
31
|
+
id: attachment.id,
|
|
32
|
+
displayName: attachment.displayName,
|
|
33
|
+
context: attachment.context,
|
|
34
|
+
type: attachment.type,
|
|
35
|
+
}));
|
|
61
36
|
});
|
|
62
|
-
const getDataChanged = prevGetContextHelperDataRef.current !== getContextHelperData;
|
|
63
|
-
// Add or replace context helpers for attachments
|
|
64
|
-
attachments.forEach((context) => {
|
|
65
|
-
if (getDataChanged || !registeredIds.has(context.id)) {
|
|
66
|
-
addContextHelper(context.id, async () => {
|
|
67
|
-
if (getContextHelperData) {
|
|
68
|
-
return await getContextHelperData(context);
|
|
69
|
-
}
|
|
70
|
-
return {
|
|
71
|
-
selectedComponent: {
|
|
72
|
-
name: context.name,
|
|
73
|
-
instruction: "This is a Tambo interactable component that is currently selected and visible on the dashboard. You can read its current props and state, and update it by modifying its props. If multiple components are attached, you can interact with and modify any of them. Use the auto-registered interactable component tools (like get_interactable_component_by_id and update_interactable_component_<id>) to view and update the component's state.",
|
|
74
|
-
...(context.metadata ?? {}),
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
});
|
|
78
|
-
registeredIds.add(context.id);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
prevGetContextHelperDataRef.current = getContextHelperData;
|
|
82
|
-
}, [
|
|
83
|
-
attachments,
|
|
84
|
-
addContextHelper,
|
|
85
|
-
removeContextHelper,
|
|
86
|
-
getContextHelperData,
|
|
87
|
-
]);
|
|
88
|
-
// Cleanup: remove all context helpers on unmount
|
|
89
|
-
useEffect(() => {
|
|
90
|
-
const registeredIds = registeredIdsRef.current;
|
|
91
37
|
return () => {
|
|
92
|
-
|
|
93
|
-
removeContextHelper(id);
|
|
94
|
-
});
|
|
95
|
-
registeredIds.clear();
|
|
38
|
+
removeContextHelper(CONTEXT_ATTACHMENTS_HELPER_KEY);
|
|
96
39
|
};
|
|
97
|
-
}, [removeContextHelper]);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
40
|
+
}, [attachments, addContextHelper, removeContextHelper]);
|
|
41
|
+
/**
|
|
42
|
+
* Adds a new context attachment that will be included with the next user message.
|
|
43
|
+
* The attachment is automatically registered as part of the merged context helper.
|
|
44
|
+
* @param contextAttachment - The context attachment input (context, optional displayName, optional type)
|
|
45
|
+
* @returns The created ContextAttachment object with a unique ID
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* const attachment = addContextAttachment({
|
|
49
|
+
* context: "The contents of File.txt",
|
|
50
|
+
* displayName: "File.txt",
|
|
51
|
+
* type: "file"
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
const addContextAttachment = useCallback((contextAttachment) => {
|
|
56
|
+
const id = crypto.randomUUID();
|
|
57
|
+
const attachment = {
|
|
58
|
+
id,
|
|
59
|
+
displayName: contextAttachment.displayName,
|
|
60
|
+
context: contextAttachment.context,
|
|
61
|
+
type: contextAttachment.type,
|
|
62
|
+
};
|
|
63
|
+
setAttachments((prev) => [...prev, attachment]);
|
|
64
|
+
return attachment;
|
|
109
65
|
}, []);
|
|
110
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Removes a context attachment by its ID.
|
|
68
|
+
*/
|
|
111
69
|
const removeContextAttachment = useCallback((id) => {
|
|
112
70
|
setAttachments((prev) => prev.filter((c) => c.id !== id));
|
|
113
71
|
}, []);
|
|
114
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Removes all context attachments at once.
|
|
74
|
+
*/
|
|
115
75
|
const clearContextAttachments = useCallback(() => {
|
|
116
76
|
setAttachments([]);
|
|
117
77
|
}, []);
|
|
@@ -120,14 +80,11 @@ export function TamboContextAttachmentProvider({ children, getContextHelperData,
|
|
|
120
80
|
addContextAttachment,
|
|
121
81
|
removeContextAttachment,
|
|
122
82
|
clearContextAttachments,
|
|
123
|
-
customSuggestions,
|
|
124
|
-
setCustomSuggestions,
|
|
125
83
|
}), [
|
|
126
84
|
attachments,
|
|
127
85
|
addContextAttachment,
|
|
128
86
|
removeContextAttachment,
|
|
129
87
|
clearContextAttachments,
|
|
130
|
-
customSuggestions,
|
|
131
88
|
]);
|
|
132
89
|
return (React.createElement(ContextAttachmentContext.Provider, { value: value }, children));
|
|
133
90
|
}
|
|
@@ -138,20 +95,20 @@ export function TamboContextAttachmentProvider({ children, getContextHelperData,
|
|
|
138
95
|
* @returns The context attachment state and methods
|
|
139
96
|
* @example
|
|
140
97
|
* ```tsx
|
|
141
|
-
* const
|
|
98
|
+
* const { addContextAttachment, attachments, clearContextAttachments } = useTamboContextAttachment();
|
|
142
99
|
*
|
|
143
|
-
* // Add a context
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
100
|
+
* // Add a context attachment for the next message
|
|
101
|
+
* const attachment = addContextAttachment({
|
|
102
|
+
* context: "The contents of File.txt",
|
|
103
|
+
* displayName: "File.txt", // optional
|
|
104
|
+
* type: "file" // optional
|
|
148
105
|
* });
|
|
149
106
|
*
|
|
150
|
-
* // Remove a context
|
|
151
|
-
*
|
|
107
|
+
* // Remove a context attachment
|
|
108
|
+
* removeContextAttachment(attachment.id);
|
|
152
109
|
*
|
|
153
|
-
* //
|
|
154
|
-
*
|
|
110
|
+
* // Clear all context attachments
|
|
111
|
+
* clearContextAttachments();
|
|
155
112
|
* ```
|
|
156
113
|
*/
|
|
157
114
|
export function useTamboContextAttachment() {
|