@tambo-ai/react 0.48.0 → 0.50.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.
Files changed (91) hide show
  1. package/dist/hooks/__tests__/use-message-images.test.d.ts +2 -0
  2. package/dist/hooks/__tests__/use-message-images.test.d.ts.map +1 -0
  3. package/dist/hooks/__tests__/use-message-images.test.js +66 -0
  4. package/dist/hooks/__tests__/use-message-images.test.js.map +1 -0
  5. package/dist/hooks/use-message-images.d.ts +25 -0
  6. package/dist/hooks/use-message-images.d.ts.map +1 -0
  7. package/dist/hooks/use-message-images.js +66 -0
  8. package/dist/hooks/use-message-images.js.map +1 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/providers/__tests__/tambo-registry-provider.test.d.ts +2 -0
  14. package/dist/providers/__tests__/tambo-registry-provider.test.d.ts.map +1 -0
  15. package/dist/providers/__tests__/tambo-registry-provider.test.js +224 -0
  16. package/dist/providers/__tests__/tambo-registry-provider.test.js.map +1 -0
  17. package/dist/providers/__tests__/tambo-thread-provider.test.js +99 -0
  18. package/dist/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
  19. package/dist/providers/tambo-provider.d.ts.map +1 -1
  20. package/dist/providers/tambo-provider.js +2 -2
  21. package/dist/providers/tambo-provider.js.map +1 -1
  22. package/dist/providers/tambo-registry-provider.d.ts +12 -0
  23. package/dist/providers/tambo-registry-provider.d.ts.map +1 -1
  24. package/dist/providers/tambo-registry-provider.js +3 -1
  25. package/dist/providers/tambo-registry-provider.js.map +1 -1
  26. package/dist/providers/tambo-thread-input-provider.d.ts +11 -0
  27. package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -1
  28. package/dist/providers/tambo-thread-input-provider.js +63 -12
  29. package/dist/providers/tambo-thread-input-provider.js.map +1 -1
  30. package/dist/providers/tambo-thread-provider.d.ts +1 -0
  31. package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
  32. package/dist/providers/tambo-thread-provider.js +12 -6
  33. package/dist/providers/tambo-thread-provider.js.map +1 -1
  34. package/dist/util/__tests__/message-builder.test.d.ts +2 -0
  35. package/dist/util/__tests__/message-builder.test.d.ts.map +1 -0
  36. package/dist/util/__tests__/message-builder.test.js +191 -0
  37. package/dist/util/__tests__/message-builder.test.js.map +1 -0
  38. package/dist/util/message-builder.d.ts +10 -0
  39. package/dist/util/message-builder.d.ts.map +1 -0
  40. package/dist/util/message-builder.js +31 -0
  41. package/dist/util/message-builder.js.map +1 -0
  42. package/dist/util/tool-caller.d.ts +1 -1
  43. package/dist/util/tool-caller.d.ts.map +1 -1
  44. package/dist/util/tool-caller.js +11 -2
  45. package/dist/util/tool-caller.js.map +1 -1
  46. package/esm/hooks/__tests__/use-message-images.test.d.ts +2 -0
  47. package/esm/hooks/__tests__/use-message-images.test.d.ts.map +1 -0
  48. package/esm/hooks/__tests__/use-message-images.test.js +64 -0
  49. package/esm/hooks/__tests__/use-message-images.test.js.map +1 -0
  50. package/esm/hooks/use-message-images.d.ts +25 -0
  51. package/esm/hooks/use-message-images.d.ts.map +1 -0
  52. package/esm/hooks/use-message-images.js +63 -0
  53. package/esm/hooks/use-message-images.js.map +1 -0
  54. package/esm/index.d.ts +1 -0
  55. package/esm/index.d.ts.map +1 -1
  56. package/esm/index.js +1 -0
  57. package/esm/index.js.map +1 -1
  58. package/esm/providers/__tests__/tambo-registry-provider.test.d.ts +2 -0
  59. package/esm/providers/__tests__/tambo-registry-provider.test.d.ts.map +1 -0
  60. package/esm/providers/__tests__/tambo-registry-provider.test.js +219 -0
  61. package/esm/providers/__tests__/tambo-registry-provider.test.js.map +1 -0
  62. package/esm/providers/__tests__/tambo-thread-provider.test.js +99 -0
  63. package/esm/providers/__tests__/tambo-thread-provider.test.js.map +1 -1
  64. package/esm/providers/tambo-provider.d.ts.map +1 -1
  65. package/esm/providers/tambo-provider.js +2 -2
  66. package/esm/providers/tambo-provider.js.map +1 -1
  67. package/esm/providers/tambo-registry-provider.d.ts +12 -0
  68. package/esm/providers/tambo-registry-provider.d.ts.map +1 -1
  69. package/esm/providers/tambo-registry-provider.js +3 -1
  70. package/esm/providers/tambo-registry-provider.js.map +1 -1
  71. package/esm/providers/tambo-thread-input-provider.d.ts +11 -0
  72. package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -1
  73. package/esm/providers/tambo-thread-input-provider.js +63 -12
  74. package/esm/providers/tambo-thread-input-provider.js.map +1 -1
  75. package/esm/providers/tambo-thread-provider.d.ts +1 -0
  76. package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
  77. package/esm/providers/tambo-thread-provider.js +12 -6
  78. package/esm/providers/tambo-thread-provider.js.map +1 -1
  79. package/esm/util/__tests__/message-builder.test.d.ts +2 -0
  80. package/esm/util/__tests__/message-builder.test.d.ts.map +1 -0
  81. package/esm/util/__tests__/message-builder.test.js +189 -0
  82. package/esm/util/__tests__/message-builder.test.js.map +1 -0
  83. package/esm/util/message-builder.d.ts +10 -0
  84. package/esm/util/message-builder.d.ts.map +1 -0
  85. package/esm/util/message-builder.js +28 -0
  86. package/esm/util/message-builder.js.map +1 -0
  87. package/esm/util/tool-caller.d.ts +1 -1
  88. package/esm/util/tool-caller.d.ts.map +1 -1
  89. package/esm/util/tool-caller.js +11 -2
  90. package/esm/util/tool-caller.js.map +1 -1
  91. package/package.json +2 -2
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=use-message-images.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-message-images.test.d.ts","sourceRoot":"","sources":["../../../src/hooks/__tests__/use-message-images.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const react_1 = require("@testing-library/react");
4
+ const use_message_images_1 = require("../use-message-images");
5
+ // Mock crypto.randomUUID
6
+ global.crypto = {
7
+ randomUUID: jest.fn(() => "mock-uuid-" + Math.random()),
8
+ };
9
+ // Mock FileReader
10
+ const mockFileReader = {
11
+ readAsDataURL: jest.fn(),
12
+ onload: null,
13
+ onerror: null,
14
+ result: "data:image/png;base64,mock-data",
15
+ };
16
+ global.FileReader = jest.fn(() => {
17
+ const reader = { ...mockFileReader };
18
+ reader.readAsDataURL = jest.fn(() => {
19
+ setTimeout(() => {
20
+ if (reader.onload) {
21
+ reader.onload({});
22
+ }
23
+ }, 0);
24
+ });
25
+ return reader;
26
+ });
27
+ describe("useMessageImages", () => {
28
+ beforeEach(() => {
29
+ jest.clearAllMocks();
30
+ });
31
+ it("should initialize with empty images array", () => {
32
+ const { result } = (0, react_1.renderHook)(() => (0, use_message_images_1.useMessageImages)());
33
+ expect(result.current.images).toEqual([]);
34
+ });
35
+ it("should reject non-image files", async () => {
36
+ const { result } = (0, react_1.renderHook)(() => (0, use_message_images_1.useMessageImages)());
37
+ const mockFile = new File(["test"], "test-document.pdf", {
38
+ type: "application/pdf",
39
+ });
40
+ await expect(result.current.addImage(mockFile)).rejects.toThrow("Only image files are allowed");
41
+ });
42
+ it("should clear all images", () => {
43
+ const { result } = (0, react_1.renderHook)(() => (0, use_message_images_1.useMessageImages)());
44
+ (0, react_1.act)(() => {
45
+ result.current.clearImages();
46
+ });
47
+ expect(result.current.images).toHaveLength(0);
48
+ });
49
+ it("should handle image validation correctly", () => {
50
+ const { result } = (0, react_1.renderHook)(() => (0, use_message_images_1.useMessageImages)());
51
+ // Test that hooks are available
52
+ expect(typeof result.current.addImage).toBe("function");
53
+ expect(typeof result.current.addImages).toBe("function");
54
+ expect(typeof result.current.removeImage).toBe("function");
55
+ expect(typeof result.current.clearImages).toBe("function");
56
+ });
57
+ it("should reject when no valid image files provided to addImages", async () => {
58
+ const { result } = (0, react_1.renderHook)(() => (0, use_message_images_1.useMessageImages)());
59
+ const mockFiles = [
60
+ new File(["test"], "document.pdf", { type: "application/pdf" }),
61
+ new File(["test"], "text.txt", { type: "text/plain" }),
62
+ ];
63
+ await expect(result.current.addImages(mockFiles)).rejects.toThrow("No valid image files provided");
64
+ });
65
+ });
66
+ //# sourceMappingURL=use-message-images.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-message-images.test.js","sourceRoot":"","sources":["../../../src/hooks/__tests__/use-message-images.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { act, renderHook } from \"@testing-library/react\";\nimport { useMessageImages } from \"../use-message-images\";\n\n// Mock crypto.randomUUID\nglobal.crypto = {\n randomUUID: jest.fn(() => \"mock-uuid-\" + Math.random()),\n} as any;\n\n// Mock FileReader\nconst mockFileReader = {\n readAsDataURL: jest.fn(),\n onload: null as any,\n onerror: null as any,\n result: \"data:image/png;base64,mock-data\",\n};\n\n(global as any).FileReader = jest.fn(() => {\n const reader = { ...mockFileReader };\n reader.readAsDataURL = jest.fn(() => {\n setTimeout(() => {\n if (reader.onload) {\n reader.onload({} as any);\n }\n }, 0);\n });\n return reader;\n});\n\ndescribe(\"useMessageImages\", () => {\n beforeEach(() => {\n jest.clearAllMocks();\n });\n\n it(\"should initialize with empty images array\", () => {\n const { result } = renderHook(() => useMessageImages());\n expect(result.current.images).toEqual([]);\n });\n\n it(\"should reject non-image files\", async () => {\n const { result } = renderHook(() => useMessageImages());\n const mockFile = new File([\"test\"], \"test-document.pdf\", {\n type: \"application/pdf\",\n });\n\n await expect(result.current.addImage(mockFile)).rejects.toThrow(\n \"Only image files are allowed\",\n );\n });\n\n it(\"should clear all images\", () => {\n const { result } = renderHook(() => useMessageImages());\n\n act(() => {\n result.current.clearImages();\n });\n\n expect(result.current.images).toHaveLength(0);\n });\n\n it(\"should handle image validation correctly\", () => {\n const { result } = renderHook(() => useMessageImages());\n\n // Test that hooks are available\n expect(typeof result.current.addImage).toBe(\"function\");\n expect(typeof result.current.addImages).toBe(\"function\");\n expect(typeof result.current.removeImage).toBe(\"function\");\n expect(typeof result.current.clearImages).toBe(\"function\");\n });\n\n it(\"should reject when no valid image files provided to addImages\", async () => {\n const { result } = renderHook(() => useMessageImages());\n const mockFiles = [\n new File([\"test\"], \"document.pdf\", { type: \"application/pdf\" }),\n new File([\"test\"], \"text.txt\", { type: \"text/plain\" }),\n ];\n\n await expect(result.current.addImages(mockFiles)).rejects.toThrow(\n \"No valid image files provided\",\n );\n });\n});\n"]}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Represents an image staged for upload
3
+ */
4
+ export interface StagedImage {
5
+ id: string;
6
+ name: string;
7
+ dataUrl: string;
8
+ file: File;
9
+ size: number;
10
+ type: string;
11
+ }
12
+ interface UseMessageImagesReturn {
13
+ images: StagedImage[];
14
+ addImage: (file: File) => Promise<void>;
15
+ addImages: (files: File[]) => Promise<void>;
16
+ removeImage: (id: string) => void;
17
+ clearImages: () => void;
18
+ }
19
+ /**
20
+ * Hook for managing images in message input
21
+ * @returns Object with images array and management functions
22
+ */
23
+ export declare function useMessageImages(): UseMessageImagesReturn;
24
+ export {};
25
+ //# sourceMappingURL=use-message-images.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-message-images.d.ts","sourceRoot":"","sources":["../../src/hooks/use-message-images.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,sBAAsB;IAC9B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,SAAS,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,sBAAsB,CAqEzD"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useMessageImages = useMessageImages;
4
+ const react_1 = require("react");
5
+ /**
6
+ * Hook for managing images in message input
7
+ * @returns Object with images array and management functions
8
+ */
9
+ function useMessageImages() {
10
+ const [images, setImages] = (0, react_1.useState)([]);
11
+ const fileToDataUrl = async (file) => {
12
+ return await new Promise((resolve, reject) => {
13
+ const reader = new FileReader();
14
+ reader.onload = () => resolve(reader.result);
15
+ reader.onerror = reject;
16
+ reader.readAsDataURL(file);
17
+ });
18
+ };
19
+ const addImage = (0, react_1.useCallback)(async (file) => {
20
+ if (!file.type.startsWith("image/")) {
21
+ throw new Error("Only image files are allowed");
22
+ }
23
+ const dataUrl = await fileToDataUrl(file);
24
+ const newImage = {
25
+ id: crypto.randomUUID(),
26
+ name: file.name,
27
+ dataUrl,
28
+ file,
29
+ size: file.size,
30
+ type: file.type,
31
+ };
32
+ setImages((prev) => [...prev, newImage]);
33
+ }, []);
34
+ const addImages = (0, react_1.useCallback)(async (files) => {
35
+ const imageFiles = files.filter((file) => file.type.startsWith("image/"));
36
+ if (imageFiles.length === 0) {
37
+ throw new Error("No valid image files provided");
38
+ }
39
+ const newImages = await Promise.all(imageFiles.map(async (file) => {
40
+ const dataUrl = await fileToDataUrl(file);
41
+ return {
42
+ id: crypto.randomUUID(),
43
+ name: file.name,
44
+ dataUrl,
45
+ file,
46
+ size: file.size,
47
+ type: file.type,
48
+ };
49
+ }));
50
+ setImages((prev) => [...prev, ...newImages]);
51
+ }, []);
52
+ const removeImage = (0, react_1.useCallback)((id) => {
53
+ setImages((prev) => prev.filter((img) => img.id !== id));
54
+ }, []);
55
+ const clearImages = (0, react_1.useCallback)(() => {
56
+ setImages([]);
57
+ }, []);
58
+ return {
59
+ images,
60
+ addImage,
61
+ addImages,
62
+ removeImage,
63
+ clearImages,
64
+ };
65
+ }
66
+ //# sourceMappingURL=use-message-images.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-message-images.js","sourceRoot":"","sources":["../../src/hooks/use-message-images.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useState } from \"react\";\n\n/**\n * Represents an image staged for upload\n */\nexport interface StagedImage {\n id: string;\n name: string;\n dataUrl: string;\n file: File;\n size: number;\n type: string;\n}\n\ninterface UseMessageImagesReturn {\n images: StagedImage[];\n addImage: (file: File) => Promise<void>;\n addImages: (files: File[]) => Promise<void>;\n removeImage: (id: string) => void;\n clearImages: () => void;\n}\n\n/**\n * Hook for managing images in message input\n * @returns Object with images array and management functions\n */\nexport function useMessageImages(): UseMessageImagesReturn {\n const [images, setImages] = useState<StagedImage[]>([]);\n\n const fileToDataUrl = async (file: File): Promise<string> => {\n return await new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = reject;\n reader.readAsDataURL(file);\n });\n };\n\n const addImage = useCallback(async (file: File) => {\n if (!file.type.startsWith(\"image/\")) {\n throw new Error(\"Only image files are allowed\");\n }\n\n const dataUrl = await fileToDataUrl(file);\n const newImage: StagedImage = {\n id: crypto.randomUUID(),\n name: file.name,\n dataUrl,\n file,\n size: file.size,\n type: file.type,\n };\n\n setImages((prev) => [...prev, newImage]);\n }, []);\n\n const addImages = useCallback(async (files: File[]) => {\n const imageFiles = files.filter((file) => file.type.startsWith(\"image/\"));\n\n if (imageFiles.length === 0) {\n throw new Error(\"No valid image files provided\");\n }\n\n const newImages = await Promise.all(\n imageFiles.map(async (file) => {\n const dataUrl = await fileToDataUrl(file);\n return {\n id: crypto.randomUUID(),\n name: file.name,\n dataUrl,\n file,\n size: file.size,\n type: file.type,\n };\n }),\n );\n\n setImages((prev) => [...prev, ...newImages]);\n }, []);\n\n const removeImage = useCallback((id: string) => {\n setImages((prev) => prev.filter((img) => img.id !== id));\n }, []);\n\n const clearImages = useCallback(() => {\n setImages([]);\n }, []);\n\n return {\n images,\n addImage,\n addImages,\n removeImage,\n clearImages,\n };\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /** Exports for the library. Only publically available exports are re-exported here. Anything not exported here is not supported and may change or break at any time. */
2
2
  export { useTamboComponentState } from "./hooks/use-component-state";
3
3
  export { TamboMessageProvider, useTamboCurrentMessage, } from "./hooks/use-current-message";
4
+ export { useMessageImages, type StagedImage } from "./hooks/use-message-images";
4
5
  export { useTamboStreamingProps } from "./hooks/use-streaming-props";
5
6
  export * from "./hooks/use-suggestions";
6
7
  export { useTamboStreamStatus, type PropStatus, type StreamStatus, } from "./hooks/use-tambo-stream-status";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wKAAwK;AAExK,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,cAAc,yBAAyB,CAAC;AACxC,OAAO,EACL,oBAAoB,EACpB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,2BAA2B,EAC3B,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACnB,uBAAuB,EACvB,QAAQ,EACR,cAAc,EACd,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,+BAA+B,EACpC,KAAK,gCAAgC,EACrC,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,GAClC,MAAM,aAAa,CAAC;AAGrB,YAAY,EACV,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,UAAU,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EACL,KAAK,4BAA4B,EACjC,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,SAAS,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,GACxB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,YAAY,EACV,0BAA0B,IAAI,qBAAqB,EACnD,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,qBAAqB,IAAI,gBAAgB,EACzC,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,GAChC,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EACL,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,cAAc,GACf,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wKAAwK;AAExK,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACL,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,cAAc,yBAAyB,CAAC;AACxC,OAAO,EACL,oBAAoB,EACpB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,2BAA2B,EAC3B,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACnB,uBAAuB,EACvB,QAAQ,EACR,cAAc,EACd,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,+BAA+B,EACpC,KAAK,gCAAgC,EACrC,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,GAClC,MAAM,aAAa,CAAC;AAGrB,YAAY,EACV,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,UAAU,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EACL,KAAK,4BAA4B,EACjC,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,SAAS,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,GACxB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,YAAY,EACV,0BAA0B,IAAI,qBAAqB,EACnD,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,qBAAqB,IAAI,gBAAgB,EACzC,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,GAChC,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EACL,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,cAAc,GACf,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -15,12 +15,14 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.currentTimeContextHelper = exports.currentPageContextHelper = exports.useCurrentInteractablesSnapshot = exports.useTamboInteractable = exports.withInteractable = exports.GenerationStage = exports.useTamboThreadList = exports.useTamboThreadInput = exports.useTamboThread = exports.useTamboStream = exports.useTamboGenerationStage = exports.useTamboContextHelpers = exports.useTamboClient = exports.useTambo = exports.useIsTamboTokenUpdating = exports.TamboThreadProvider = exports.TamboThreadInputProvider = exports.TamboStubProvider = exports.TamboProvider = exports.TamboPropStreamProvider = exports.TamboContextHelpersProvider = exports.TamboComponentProvider = exports.TamboClientProvider = exports.useTamboStreamStatus = exports.useTamboStreamingProps = exports.useTamboCurrentMessage = exports.TamboMessageProvider = exports.useTamboComponentState = void 0;
18
+ exports.currentTimeContextHelper = exports.currentPageContextHelper = exports.useCurrentInteractablesSnapshot = exports.useTamboInteractable = exports.withInteractable = exports.GenerationStage = exports.useTamboThreadList = exports.useTamboThreadInput = exports.useTamboThread = exports.useTamboStream = exports.useTamboGenerationStage = exports.useTamboContextHelpers = exports.useTamboClient = exports.useTambo = exports.useIsTamboTokenUpdating = exports.TamboThreadProvider = exports.TamboThreadInputProvider = exports.TamboStubProvider = exports.TamboProvider = exports.TamboPropStreamProvider = exports.TamboContextHelpersProvider = exports.TamboComponentProvider = exports.TamboClientProvider = exports.useTamboStreamStatus = exports.useTamboStreamingProps = exports.useMessageImages = exports.useTamboCurrentMessage = exports.TamboMessageProvider = exports.useTamboComponentState = void 0;
19
19
  var use_component_state_1 = require("./hooks/use-component-state");
20
20
  Object.defineProperty(exports, "useTamboComponentState", { enumerable: true, get: function () { return use_component_state_1.useTamboComponentState; } });
21
21
  var use_current_message_1 = require("./hooks/use-current-message");
22
22
  Object.defineProperty(exports, "TamboMessageProvider", { enumerable: true, get: function () { return use_current_message_1.TamboMessageProvider; } });
23
23
  Object.defineProperty(exports, "useTamboCurrentMessage", { enumerable: true, get: function () { return use_current_message_1.useTamboCurrentMessage; } });
24
+ var use_message_images_1 = require("./hooks/use-message-images");
25
+ Object.defineProperty(exports, "useMessageImages", { enumerable: true, get: function () { return use_message_images_1.useMessageImages; } });
24
26
  var use_streaming_props_1 = require("./hooks/use-streaming-props");
25
27
  Object.defineProperty(exports, "useTamboStreamingProps", { enumerable: true, get: function () { return use_streaming_props_1.useTamboStreamingProps; } });
26
28
  __exportStar(require("./hooks/use-suggestions"), exports);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,wKAAwK;;;;;;;;;;;;;;;;;AAExK,mEAAqE;AAA5D,6HAAA,sBAAsB,OAAA;AAC/B,mEAGqC;AAFnC,2HAAA,oBAAoB,OAAA;AACpB,6HAAA,sBAAsB,OAAA;AAExB,mEAAqE;AAA5D,6HAAA,sBAAsB,OAAA;AAC/B,0DAAwC;AACxC,2EAIyC;AAHvC,+HAAA,oBAAoB,OAAA;AAKtB,gCAAgC;AAChC,yCAuBqB;AAtBnB,gHAAA,mBAAmB,OAAA;AACnB,mHAAA,sBAAsB,OAAA;AACtB,wHAAA,2BAA2B,OAAA;AAC3B,oHAAA,uBAAuB,OAAA;AACvB,0GAAA,aAAa,OAAA;AACb,8GAAA,iBAAiB,OAAA;AACjB,qHAAA,wBAAwB,OAAA;AACxB,gHAAA,mBAAmB,OAAA;AACnB,oHAAA,uBAAuB,OAAA;AACvB,qGAAA,QAAQ,OAAA;AACR,2GAAA,cAAc,OAAA;AACd,mHAAA,sBAAsB,OAAA;AACtB,oHAAA,uBAAuB,OAAA;AACvB,2GAAA,cAAc,OAAA;AACd,2GAAA,cAAc,OAAA;AACd,gHAAA,mBAAmB,OAAA;AAqBrB,+DAA+D;AAAtD,uHAAA,kBAAkB,OAAA;AAQ3B,mFAG6C;AAF3C,8HAAA,eAAe,OAAA;AASjB,mFAIiD;AAH/C,2HAAA,qBAAqB,OAAoB;AAI3C,uFAGiD;AAF/C,mIAAA,oBAAoB,OAAA;AACpB,8IAAA,+BAA+B,OAAA;AAGjC,0BAA0B;AAC1B,qDAG2B;AAFzB,2HAAA,wBAAwB,OAAA;AACxB,2HAAA,wBAAwB,OAAA","sourcesContent":["/** Exports for the library. Only publically available exports are re-exported here. Anything not exported here is not supported and may change or break at any time. */\n\nexport { useTamboComponentState } from \"./hooks/use-component-state\";\nexport {\n TamboMessageProvider,\n useTamboCurrentMessage,\n} from \"./hooks/use-current-message\";\nexport { useTamboStreamingProps } from \"./hooks/use-streaming-props\";\nexport * from \"./hooks/use-suggestions\";\nexport {\n useTamboStreamStatus,\n type PropStatus,\n type StreamStatus,\n} from \"./hooks/use-tambo-stream-status\";\n\n// Re-export provider components\nexport {\n TamboClientProvider,\n TamboComponentProvider,\n TamboContextHelpersProvider,\n TamboPropStreamProvider,\n TamboProvider,\n TamboStubProvider,\n TamboThreadInputProvider,\n TamboThreadProvider,\n useIsTamboTokenUpdating,\n useTambo,\n useTamboClient,\n useTamboContextHelpers,\n useTamboGenerationStage,\n useTamboStream,\n useTamboThread,\n useTamboThreadInput,\n type TamboComponent,\n type TamboContextHelpersContextProps,\n type TamboContextHelpersProviderProps,\n type TamboRegistryContext,\n type TamboStubProviderProps,\n type TamboThreadInputContextProps,\n} from \"./providers\";\n\n// Re-export types from Tambo Node SDK\nexport type {\n APIError,\n RateLimitError,\n TamboAIError,\n} from \"@tambo-ai/typescript-sdk\";\nexport type {\n Suggestion,\n SuggestionGenerateParams,\n SuggestionGenerateResponse,\n SuggestionListResponse,\n} from \"@tambo-ai/typescript-sdk/resources/beta/threads/suggestions\";\nexport { useTamboThreadList } from \"./hooks/use-tambo-threads\";\nexport {\n type ComponentContextToolMetadata,\n type ComponentRegistry,\n type ParameterSpec,\n type RegisteredComponent,\n type TamboTool,\n} from \"./model/component-metadata\";\nexport {\n GenerationStage,\n type TamboThreadMessage,\n} from \"./model/generate-component-response\";\nexport { type TamboThread } from \"./model/tambo-thread\";\n\nexport type {\n TamboInteractableComponent as InteractableComponent,\n TamboInteractableContext,\n} from \"./model/tambo-interactable\";\nexport {\n withTamboInteractable as withInteractable,\n type InteractableConfig,\n type WithTamboInteractableProps,\n} from \"./providers/hoc/with-tambo-interactable\";\nexport {\n useTamboInteractable,\n useCurrentInteractablesSnapshot,\n} from \"./providers/tambo-interactable-provider\";\n\n// Context helpers exports\nexport {\n currentPageContextHelper,\n currentTimeContextHelper,\n} from \"./context-helpers\";\nexport type {\n AdditionalContext,\n ContextHelperFn,\n ContextHelpers,\n} from \"./context-helpers\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,wKAAwK;;;;;;;;;;;;;;;;;AAExK,mEAAqE;AAA5D,6HAAA,sBAAsB,OAAA;AAC/B,mEAGqC;AAFnC,2HAAA,oBAAoB,OAAA;AACpB,6HAAA,sBAAsB,OAAA;AAExB,iEAAgF;AAAvE,sHAAA,gBAAgB,OAAA;AACzB,mEAAqE;AAA5D,6HAAA,sBAAsB,OAAA;AAC/B,0DAAwC;AACxC,2EAIyC;AAHvC,+HAAA,oBAAoB,OAAA;AAKtB,gCAAgC;AAChC,yCAuBqB;AAtBnB,gHAAA,mBAAmB,OAAA;AACnB,mHAAA,sBAAsB,OAAA;AACtB,wHAAA,2BAA2B,OAAA;AAC3B,oHAAA,uBAAuB,OAAA;AACvB,0GAAA,aAAa,OAAA;AACb,8GAAA,iBAAiB,OAAA;AACjB,qHAAA,wBAAwB,OAAA;AACxB,gHAAA,mBAAmB,OAAA;AACnB,oHAAA,uBAAuB,OAAA;AACvB,qGAAA,QAAQ,OAAA;AACR,2GAAA,cAAc,OAAA;AACd,mHAAA,sBAAsB,OAAA;AACtB,oHAAA,uBAAuB,OAAA;AACvB,2GAAA,cAAc,OAAA;AACd,2GAAA,cAAc,OAAA;AACd,gHAAA,mBAAmB,OAAA;AAqBrB,+DAA+D;AAAtD,uHAAA,kBAAkB,OAAA;AAQ3B,mFAG6C;AAF3C,8HAAA,eAAe,OAAA;AASjB,mFAIiD;AAH/C,2HAAA,qBAAqB,OAAoB;AAI3C,uFAGiD;AAF/C,mIAAA,oBAAoB,OAAA;AACpB,8IAAA,+BAA+B,OAAA;AAGjC,0BAA0B;AAC1B,qDAG2B;AAFzB,2HAAA,wBAAwB,OAAA;AACxB,2HAAA,wBAAwB,OAAA","sourcesContent":["/** Exports for the library. Only publically available exports are re-exported here. Anything not exported here is not supported and may change or break at any time. */\n\nexport { useTamboComponentState } from \"./hooks/use-component-state\";\nexport {\n TamboMessageProvider,\n useTamboCurrentMessage,\n} from \"./hooks/use-current-message\";\nexport { useMessageImages, type StagedImage } from \"./hooks/use-message-images\";\nexport { useTamboStreamingProps } from \"./hooks/use-streaming-props\";\nexport * from \"./hooks/use-suggestions\";\nexport {\n useTamboStreamStatus,\n type PropStatus,\n type StreamStatus,\n} from \"./hooks/use-tambo-stream-status\";\n\n// Re-export provider components\nexport {\n TamboClientProvider,\n TamboComponentProvider,\n TamboContextHelpersProvider,\n TamboPropStreamProvider,\n TamboProvider,\n TamboStubProvider,\n TamboThreadInputProvider,\n TamboThreadProvider,\n useIsTamboTokenUpdating,\n useTambo,\n useTamboClient,\n useTamboContextHelpers,\n useTamboGenerationStage,\n useTamboStream,\n useTamboThread,\n useTamboThreadInput,\n type TamboComponent,\n type TamboContextHelpersContextProps,\n type TamboContextHelpersProviderProps,\n type TamboRegistryContext,\n type TamboStubProviderProps,\n type TamboThreadInputContextProps,\n} from \"./providers\";\n\n// Re-export types from Tambo Node SDK\nexport type {\n APIError,\n RateLimitError,\n TamboAIError,\n} from \"@tambo-ai/typescript-sdk\";\nexport type {\n Suggestion,\n SuggestionGenerateParams,\n SuggestionGenerateResponse,\n SuggestionListResponse,\n} from \"@tambo-ai/typescript-sdk/resources/beta/threads/suggestions\";\nexport { useTamboThreadList } from \"./hooks/use-tambo-threads\";\nexport {\n type ComponentContextToolMetadata,\n type ComponentRegistry,\n type ParameterSpec,\n type RegisteredComponent,\n type TamboTool,\n} from \"./model/component-metadata\";\nexport {\n GenerationStage,\n type TamboThreadMessage,\n} from \"./model/generate-component-response\";\nexport { type TamboThread } from \"./model/tambo-thread\";\n\nexport type {\n TamboInteractableComponent as InteractableComponent,\n TamboInteractableContext,\n} from \"./model/tambo-interactable\";\nexport {\n withTamboInteractable as withInteractable,\n type InteractableConfig,\n type WithTamboInteractableProps,\n} from \"./providers/hoc/with-tambo-interactable\";\nexport {\n useTamboInteractable,\n useCurrentInteractablesSnapshot,\n} from \"./providers/tambo-interactable-provider\";\n\n// Context helpers exports\nexport {\n currentPageContextHelper,\n currentTimeContextHelper,\n} from \"./context-helpers\";\nexport type {\n AdditionalContext,\n ContextHelperFn,\n ContextHelpers,\n} from \"./context-helpers\";\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tambo-registry-provider.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tambo-registry-provider.test.d.ts","sourceRoot":"","sources":["../../../src/providers/__tests__/tambo-registry-provider.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = require("@testing-library/react");
7
+ const react_2 = __importDefault(require("react"));
8
+ const zod_1 = require("zod");
9
+ const tambo_registry_provider_1 = require("../tambo-registry-provider");
10
+ // Shared tool registry for all tests
11
+ const createMockTools = () => [
12
+ {
13
+ name: "test-tool-1",
14
+ description: "First test tool",
15
+ tool: jest.fn().mockResolvedValue("test-tool-1-result"),
16
+ toolSchema: zod_1.z
17
+ .function()
18
+ .args(zod_1.z.string().describe("input parameter"))
19
+ .returns(zod_1.z.string()),
20
+ },
21
+ {
22
+ name: "test-tool-2",
23
+ description: "Second test tool",
24
+ tool: jest.fn().mockResolvedValue("test-tool-2-result"),
25
+ toolSchema: zod_1.z
26
+ .function()
27
+ .args(zod_1.z.number().describe("number parameter"))
28
+ .returns(zod_1.z.string()),
29
+ },
30
+ ];
31
+ const createMockComponents = (tools) => [
32
+ {
33
+ name: "TestComponent",
34
+ component: () => react_2.default.createElement("div", null, "TestComponent"),
35
+ description: "Test component",
36
+ propsSchema: zod_1.z.object({
37
+ test: zod_1.z.string(),
38
+ }),
39
+ associatedTools: tools,
40
+ },
41
+ ];
42
+ describe("TamboRegistryProvider", () => {
43
+ const mockTools = createMockTools();
44
+ const mockComponents = createMockComponents(mockTools);
45
+ beforeEach(() => {
46
+ jest.clearAllMocks();
47
+ });
48
+ describe("Component and tool registration", () => {
49
+ it("should register components and tools correctly", () => {
50
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, { components: mockComponents }, children));
51
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
52
+ expect(result.current.componentList).toHaveProperty("TestComponent");
53
+ expect(result.current.toolRegistry).toHaveProperty("test-tool-1");
54
+ expect(result.current.toolRegistry).toHaveProperty("test-tool-2");
55
+ expect(result.current.componentToolAssociations).toHaveProperty("TestComponent");
56
+ expect(result.current.componentToolAssociations.TestComponent).toEqual([
57
+ "test-tool-1",
58
+ "test-tool-2",
59
+ ]);
60
+ });
61
+ it("should provide onCallUnregisteredTool in context", () => {
62
+ const mockonCallUnregisteredTool = jest
63
+ .fn()
64
+ .mockResolvedValue("test-result");
65
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, { components: mockComponents, onCallUnregisteredTool: mockonCallUnregisteredTool }, children));
66
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
67
+ // The onCallUnregisteredTool should be available in the context
68
+ expect(result.current.onCallUnregisteredTool).toBeDefined();
69
+ expect(typeof result.current.onCallUnregisteredTool).toBe("function");
70
+ });
71
+ it("should handle tool registration and association", () => {
72
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, null, children));
73
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
74
+ // Register a new tool
75
+ (0, react_1.act)(() => {
76
+ result.current.registerTool(mockTools[0]);
77
+ });
78
+ expect(result.current.toolRegistry).toHaveProperty("test-tool-1");
79
+ // Register a new component
80
+ (0, react_1.act)(() => {
81
+ result.current.registerComponent(mockComponents[0]);
82
+ });
83
+ expect(result.current.componentList).toHaveProperty("TestComponent");
84
+ expect(result.current.componentToolAssociations).toHaveProperty("TestComponent");
85
+ });
86
+ it("should handle multiple tool registration", () => {
87
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, null, children));
88
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
89
+ // Register multiple tools
90
+ (0, react_1.act)(() => {
91
+ result.current.registerTools(mockTools);
92
+ });
93
+ expect(result.current.toolRegistry).toHaveProperty("test-tool-1");
94
+ expect(result.current.toolRegistry).toHaveProperty("test-tool-2");
95
+ expect(Object.keys(result.current.toolRegistry)).toHaveLength(2);
96
+ });
97
+ it("should handle tool association with components", () => {
98
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, { components: mockComponents }, children));
99
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
100
+ // Add a new tool association
101
+ (0, react_1.act)(() => {
102
+ const newTool = {
103
+ name: "new-tool",
104
+ description: "New tool",
105
+ tool: jest.fn().mockResolvedValue("new-tool-result"),
106
+ toolSchema: zod_1.z
107
+ .function()
108
+ .args(zod_1.z.string().describe("input"))
109
+ .returns(zod_1.z.string()),
110
+ };
111
+ result.current.addToolAssociation("TestComponent", newTool);
112
+ });
113
+ expect(result.current.componentToolAssociations.TestComponent).toContain("new-tool");
114
+ });
115
+ it("should throw error when adding tool association to non-existent component", () => {
116
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, null, children));
117
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
118
+ const newTool = {
119
+ name: "new-tool",
120
+ description: "New tool",
121
+ tool: jest.fn().mockResolvedValue("new-tool-result"),
122
+ toolSchema: zod_1.z
123
+ .function()
124
+ .args(zod_1.z.string().describe("input"))
125
+ .returns(zod_1.z.string()),
126
+ };
127
+ expect(() => {
128
+ (0, react_1.act)(() => {
129
+ result.current.addToolAssociation("NonExistentComponent", newTool);
130
+ });
131
+ }).toThrow("Component NonExistentComponent not found in registry");
132
+ });
133
+ it("should validate tool schemas and throw error for invalid schemas", () => {
134
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, null, children));
135
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
136
+ const invalidTool = {
137
+ name: "invalid-tool",
138
+ description: "Invalid tool",
139
+ tool: jest.fn().mockResolvedValue("result"),
140
+ toolSchema: zod_1.z.record(zod_1.z.string()), // This should cause validation to fail
141
+ };
142
+ // This should throw during registration due to invalid schema
143
+ expect(() => {
144
+ (0, react_1.act)(() => {
145
+ result.current.registerTool(invalidTool);
146
+ });
147
+ }).toThrow('z.record() is not supported in toolSchema of tool "invalid-tool"');
148
+ });
149
+ it("should validate component schemas and throw error for invalid schemas", () => {
150
+ const invalidComponent = {
151
+ name: "InvalidComponent",
152
+ component: () => react_2.default.createElement("div", null, "Invalid"),
153
+ description: "Invalid component",
154
+ propsSchema: zod_1.z.record(zod_1.z.string()), // This should cause validation to fail
155
+ };
156
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, null, children));
157
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
158
+ // This should throw during registration due to invalid schema
159
+ expect(() => {
160
+ (0, react_1.act)(() => {
161
+ result.current.registerComponent(invalidComponent);
162
+ });
163
+ }).toThrow('z.record() is not supported in propsSchema of component "InvalidComponent"');
164
+ });
165
+ it("should throw error when component has both propsSchema and propsDefinition", () => {
166
+ const invalidComponent = {
167
+ name: "InvalidComponent",
168
+ component: () => react_2.default.createElement("div", null, "Invalid"),
169
+ description: "Invalid component",
170
+ propsSchema: zod_1.z.object({ test: zod_1.z.string() }),
171
+ propsDefinition: { test: "string" }, // Both defined - should throw
172
+ };
173
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, null, children));
174
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
175
+ expect(() => {
176
+ (0, react_1.act)(() => {
177
+ result.current.registerComponent(invalidComponent);
178
+ });
179
+ }).toThrow("Component InvalidComponent cannot have both propsSchema and propsDefinition defined");
180
+ });
181
+ it("should throw error when component has neither propsSchema nor propsDefinition", () => {
182
+ const invalidComponent = {
183
+ name: "InvalidComponent",
184
+ component: () => react_2.default.createElement("div", null, "Invalid"),
185
+ description: "Invalid component",
186
+ // Neither propsSchema nor propsDefinition defined - should throw
187
+ };
188
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, null, children));
189
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
190
+ expect(() => {
191
+ (0, react_1.act)(() => {
192
+ result.current.registerComponent(invalidComponent);
193
+ });
194
+ }).toThrow("Component InvalidComponent must have either propsSchema (recommended) or propsDefinition defined");
195
+ });
196
+ });
197
+ describe("Tool call handling", () => {
198
+ it("should provide onCallUnregisteredTool callback for handling unknown tools", async () => {
199
+ const mockonCallUnregisteredTool = jest
200
+ .fn()
201
+ .mockResolvedValue("unknown-tool-result");
202
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, { components: mockComponents, onCallUnregisteredTool: mockonCallUnregisteredTool }, children));
203
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
204
+ // Verify the callback is available
205
+ expect(result.current.onCallUnregisteredTool).toBeDefined();
206
+ expect(typeof result.current.onCallUnregisteredTool).toBe("function");
207
+ // Simulate calling the unknown tool handler
208
+ const toolName = "unknown-tool";
209
+ const args = [{ parameterName: "input", parameterValue: "test-input" }];
210
+ await (0, react_1.act)(async () => {
211
+ if (result.current.onCallUnregisteredTool) {
212
+ await result.current.onCallUnregisteredTool(toolName, args);
213
+ }
214
+ });
215
+ expect(mockonCallUnregisteredTool).toHaveBeenCalledWith(toolName, args);
216
+ });
217
+ it("should handle onCallUnregisteredTool being undefined", () => {
218
+ const wrapper = ({ children }) => (react_2.default.createElement(tambo_registry_provider_1.TamboRegistryProvider, { components: mockComponents }, children));
219
+ const { result } = (0, react_1.renderHook)(() => (0, tambo_registry_provider_1.useTamboRegistry)(), { wrapper });
220
+ expect(result.current.onCallUnregisteredTool).toBeUndefined();
221
+ });
222
+ });
223
+ });
224
+ //# sourceMappingURL=tambo-registry-provider.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tambo-registry-provider.test.js","sourceRoot":"","sources":["../../../src/providers/__tests__/tambo-registry-provider.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { act, renderHook } from \"@testing-library/react\";\nimport React from \"react\";\nimport { z } from \"zod\";\nimport { TamboComponent, TamboTool } from \"../../model/component-metadata\";\nimport {\n TamboRegistryProvider,\n useTamboRegistry,\n} from \"../tambo-registry-provider\";\n\n// Shared tool registry for all tests\nconst createMockTools = (): TamboTool[] => [\n {\n name: \"test-tool-1\",\n description: \"First test tool\",\n tool: jest.fn().mockResolvedValue(\"test-tool-1-result\"),\n toolSchema: z\n .function()\n .args(z.string().describe(\"input parameter\"))\n .returns(z.string()),\n },\n {\n name: \"test-tool-2\",\n description: \"Second test tool\",\n tool: jest.fn().mockResolvedValue(\"test-tool-2-result\"),\n toolSchema: z\n .function()\n .args(z.number().describe(\"number parameter\"))\n .returns(z.string()),\n },\n];\n\nconst createMockComponents = (tools: TamboTool[]): TamboComponent[] => [\n {\n name: \"TestComponent\",\n component: () => <div>TestComponent</div>,\n description: \"Test component\",\n propsSchema: z.object({\n test: z.string(),\n }),\n associatedTools: tools,\n },\n];\n\ndescribe(\"TamboRegistryProvider\", () => {\n const mockTools = createMockTools();\n const mockComponents = createMockComponents(mockTools);\n\n beforeEach(() => {\n jest.clearAllMocks();\n });\n\n describe(\"Component and tool registration\", () => {\n it(\"should register components and tools correctly\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider components={mockComponents}>\n {children}\n </TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.componentList).toHaveProperty(\"TestComponent\");\n expect(result.current.toolRegistry).toHaveProperty(\"test-tool-1\");\n expect(result.current.toolRegistry).toHaveProperty(\"test-tool-2\");\n expect(result.current.componentToolAssociations).toHaveProperty(\n \"TestComponent\",\n );\n expect(result.current.componentToolAssociations.TestComponent).toEqual([\n \"test-tool-1\",\n \"test-tool-2\",\n ]);\n });\n\n it(\"should provide onCallUnregisteredTool in context\", () => {\n const mockonCallUnregisteredTool = jest\n .fn()\n .mockResolvedValue(\"test-result\");\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider\n components={mockComponents}\n onCallUnregisteredTool={mockonCallUnregisteredTool}\n >\n {children}\n </TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n // The onCallUnregisteredTool should be available in the context\n expect(result.current.onCallUnregisteredTool).toBeDefined();\n expect(typeof result.current.onCallUnregisteredTool).toBe(\"function\");\n });\n\n it(\"should handle tool registration and association\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider>{children}</TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n // Register a new tool\n act(() => {\n result.current.registerTool(mockTools[0]);\n });\n\n expect(result.current.toolRegistry).toHaveProperty(\"test-tool-1\");\n\n // Register a new component\n act(() => {\n result.current.registerComponent(mockComponents[0]);\n });\n\n expect(result.current.componentList).toHaveProperty(\"TestComponent\");\n expect(result.current.componentToolAssociations).toHaveProperty(\n \"TestComponent\",\n );\n });\n\n it(\"should handle multiple tool registration\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider>{children}</TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n // Register multiple tools\n act(() => {\n result.current.registerTools(mockTools);\n });\n\n expect(result.current.toolRegistry).toHaveProperty(\"test-tool-1\");\n expect(result.current.toolRegistry).toHaveProperty(\"test-tool-2\");\n expect(Object.keys(result.current.toolRegistry)).toHaveLength(2);\n });\n\n it(\"should handle tool association with components\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider components={mockComponents}>\n {children}\n </TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n // Add a new tool association\n act(() => {\n const newTool: TamboTool = {\n name: \"new-tool\",\n description: \"New tool\",\n tool: jest.fn().mockResolvedValue(\"new-tool-result\"),\n toolSchema: z\n .function()\n .args(z.string().describe(\"input\"))\n .returns(z.string()),\n };\n result.current.addToolAssociation(\"TestComponent\", newTool);\n });\n\n expect(result.current.componentToolAssociations.TestComponent).toContain(\n \"new-tool\",\n );\n });\n\n it(\"should throw error when adding tool association to non-existent component\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider>{children}</TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n const newTool: TamboTool = {\n name: \"new-tool\",\n description: \"New tool\",\n tool: jest.fn().mockResolvedValue(\"new-tool-result\"),\n toolSchema: z\n .function()\n .args(z.string().describe(\"input\"))\n .returns(z.string()),\n };\n\n expect(() => {\n act(() => {\n result.current.addToolAssociation(\"NonExistentComponent\", newTool);\n });\n }).toThrow(\"Component NonExistentComponent not found in registry\");\n });\n\n it(\"should validate tool schemas and throw error for invalid schemas\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider>{children}</TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n const invalidTool: TamboTool = {\n name: \"invalid-tool\",\n description: \"Invalid tool\",\n tool: jest.fn().mockResolvedValue(\"result\"),\n toolSchema: z.record(z.string()), // This should cause validation to fail\n };\n\n // This should throw during registration due to invalid schema\n expect(() => {\n act(() => {\n result.current.registerTool(invalidTool);\n });\n }).toThrow(\n 'z.record() is not supported in toolSchema of tool \"invalid-tool\"',\n );\n });\n\n it(\"should validate component schemas and throw error for invalid schemas\", () => {\n const invalidComponent: TamboComponent = {\n name: \"InvalidComponent\",\n component: () => <div>Invalid</div>,\n description: \"Invalid component\",\n propsSchema: z.record(z.string()), // This should cause validation to fail\n };\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider>{children}</TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n // This should throw during registration due to invalid schema\n expect(() => {\n act(() => {\n result.current.registerComponent(invalidComponent);\n });\n }).toThrow(\n 'z.record() is not supported in propsSchema of component \"InvalidComponent\"',\n );\n });\n\n it(\"should throw error when component has both propsSchema and propsDefinition\", () => {\n const invalidComponent: TamboComponent = {\n name: \"InvalidComponent\",\n component: () => <div>Invalid</div>,\n description: \"Invalid component\",\n propsSchema: z.object({ test: z.string() }),\n propsDefinition: { test: \"string\" }, // Both defined - should throw\n };\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider>{children}</TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(() => {\n act(() => {\n result.current.registerComponent(invalidComponent);\n });\n }).toThrow(\n \"Component InvalidComponent cannot have both propsSchema and propsDefinition defined\",\n );\n });\n\n it(\"should throw error when component has neither propsSchema nor propsDefinition\", () => {\n const invalidComponent: TamboComponent = {\n name: \"InvalidComponent\",\n component: () => <div>Invalid</div>,\n description: \"Invalid component\",\n // Neither propsSchema nor propsDefinition defined - should throw\n };\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider>{children}</TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(() => {\n act(() => {\n result.current.registerComponent(invalidComponent);\n });\n }).toThrow(\n \"Component InvalidComponent must have either propsSchema (recommended) or propsDefinition defined\",\n );\n });\n });\n\n describe(\"Tool call handling\", () => {\n it(\"should provide onCallUnregisteredTool callback for handling unknown tools\", async () => {\n const mockonCallUnregisteredTool = jest\n .fn()\n .mockResolvedValue(\"unknown-tool-result\");\n\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider\n components={mockComponents}\n onCallUnregisteredTool={mockonCallUnregisteredTool}\n >\n {children}\n </TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n // Verify the callback is available\n expect(result.current.onCallUnregisteredTool).toBeDefined();\n expect(typeof result.current.onCallUnregisteredTool).toBe(\"function\");\n\n // Simulate calling the unknown tool handler\n const toolName = \"unknown-tool\";\n const args = [{ parameterName: \"input\", parameterValue: \"test-input\" }];\n\n await act(async () => {\n if (result.current.onCallUnregisteredTool) {\n await result.current.onCallUnregisteredTool(toolName, args);\n }\n });\n\n expect(mockonCallUnregisteredTool).toHaveBeenCalledWith(toolName, args);\n });\n\n it(\"should handle onCallUnregisteredTool being undefined\", () => {\n const wrapper = ({ children }: { children: React.ReactNode }) => (\n <TamboRegistryProvider components={mockComponents}>\n {children}\n </TamboRegistryProvider>\n );\n\n const { result } = renderHook(() => useTamboRegistry(), { wrapper });\n\n expect(result.current.onCallUnregisteredTool).toBeUndefined();\n });\n });\n});\n"]}