@tambo-ai/react 0.65.3 → 0.66.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 +120 -20
- package/dist/{providers/hoc → hoc}/with-tambo-interactable.d.ts +2 -2
- package/dist/hoc/with-tambo-interactable.d.ts.map +1 -0
- package/dist/{providers/hoc → hoc}/with-tambo-interactable.js +29 -2
- package/dist/hoc/with-tambo-interactable.js.map +1 -0
- package/dist/hoc/with-tambo-interactable.test.d.ts +2 -0
- package/dist/hoc/with-tambo-interactable.test.d.ts.map +1 -0
- package/dist/hoc/with-tambo-interactable.test.js +192 -0
- package/dist/hoc/with-tambo-interactable.test.js.map +1 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-current-message.d.ts +51 -7
- package/dist/hooks/use-current-message.d.ts.map +1 -1
- package/dist/hooks/use-current-message.js +50 -6
- package/dist/hooks/use-current-message.js.map +1 -1
- package/dist/hooks/use-current-message.test.d.ts +2 -0
- package/dist/hooks/use-current-message.test.d.ts.map +1 -0
- package/dist/hooks/use-current-message.test.js +264 -0
- package/dist/hooks/use-current-message.test.js.map +1 -0
- package/dist/index.d.ts +10 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +2 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/mcp-hooks.d.ts +77 -6
- package/dist/mcp/mcp-hooks.d.ts.map +1 -1
- package/dist/mcp/mcp-hooks.js +104 -40
- package/dist/mcp/mcp-hooks.js.map +1 -1
- package/dist/mcp/mcp-hooks.test.js +83 -18
- 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 +2 -1
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/model/component-metadata.d.ts +444 -14
- package/dist/model/component-metadata.d.ts.map +1 -1
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/model/generate-component-response.d.ts +12 -1
- package/dist/model/generate-component-response.d.ts.map +1 -1
- package/dist/model/generate-component-response.js.map +1 -1
- package/dist/model/resource-info.d.ts +55 -0
- package/dist/model/resource-info.d.ts.map +1 -0
- package/dist/model/resource-info.js +3 -0
- package/dist/model/resource-info.js.map +1 -0
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/tambo-component-provider.d.ts +4 -4
- package/dist/providers/tambo-component-provider.d.ts.map +1 -1
- package/dist/providers/tambo-component-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider-partial-updates.test.js +87 -87
- package/dist/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts +2 -3
- package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +47 -41
- package/dist/providers/tambo-interactable-provider.js.map +1 -1
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js +9 -9
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/dist/providers/tambo-interactables-additional-context.test.js +11 -11
- package/dist/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/dist/providers/tambo-registry-provider.d.ts +28 -7
- package/dist/providers/tambo-registry-provider.d.ts.map +1 -1
- package/dist/providers/tambo-registry-provider.js +70 -181
- package/dist/providers/tambo-registry-provider.js.map +1 -1
- package/dist/providers/tambo-registry-provider.test.js +152 -30
- package/dist/providers/tambo-registry-provider.test.js.map +1 -1
- package/dist/providers/tambo-registry-schema-compat.test.d.ts +2 -0
- package/dist/providers/tambo-registry-schema-compat.test.d.ts.map +1 -0
- package/dist/providers/tambo-registry-schema-compat.test.js +616 -0
- package/dist/providers/tambo-registry-schema-compat.test.js.map +1 -0
- package/dist/providers/tambo-stubs.d.ts +2 -2
- package/dist/providers/tambo-stubs.d.ts.map +1 -1
- package/dist/providers/tambo-stubs.js +5 -0
- package/dist/providers/tambo-stubs.js.map +1 -1
- package/dist/providers/tambo-thread-input-provider.d.ts +1 -0
- package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-input-provider.js +3 -3
- package/dist/providers/tambo-thread-input-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.test.js +32 -36
- package/dist/providers/tambo-thread-provider.test.js.map +1 -1
- package/dist/schema/index.d.ts +6 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +18 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/json-schema.d.ts +35 -0
- package/dist/schema/json-schema.d.ts.map +1 -0
- package/dist/schema/json-schema.js +103 -0
- package/dist/schema/json-schema.js.map +1 -0
- package/dist/schema/schema.d.ts +66 -0
- package/dist/schema/schema.d.ts.map +1 -0
- package/dist/schema/schema.js +192 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/schema.test.d.ts +2 -0
- package/dist/schema/schema.test.d.ts.map +1 -0
- package/dist/schema/schema.test.js +41 -0
- package/dist/schema/schema.test.js.map +1 -0
- package/dist/schema/standard-schema.d.ts +21 -0
- package/dist/schema/standard-schema.d.ts.map +1 -0
- package/dist/schema/standard-schema.js +37 -0
- package/dist/schema/standard-schema.js.map +1 -0
- package/dist/schema/validate.d.ts +14 -0
- package/dist/schema/validate.d.ts.map +1 -0
- package/dist/schema/validate.js +148 -0
- package/dist/schema/validate.js.map +1 -0
- package/dist/schema/validate.test.d.ts +2 -0
- package/dist/schema/validate.test.d.ts.map +1 -0
- package/dist/schema/validate.test.js +128 -0
- package/dist/schema/validate.test.js.map +1 -0
- package/dist/schema/zod.d.ts +54 -0
- package/dist/schema/zod.d.ts.map +1 -0
- package/dist/schema/zod.js +135 -0
- package/dist/schema/zod.js.map +1 -0
- package/dist/testing/tools.d.ts +29 -15
- package/dist/testing/tools.d.ts.map +1 -1
- package/dist/testing/tools.js +64 -19
- package/dist/testing/tools.js.map +1 -1
- package/dist/util/generate-component.d.ts.map +1 -1
- package/dist/util/generate-component.js +3 -3
- package/dist/util/generate-component.js.map +1 -1
- package/dist/util/mcp-server-utils.d.ts +23 -0
- package/dist/util/mcp-server-utils.d.ts.map +1 -0
- package/dist/util/mcp-server-utils.js +107 -0
- package/dist/util/mcp-server-utils.js.map +1 -0
- package/dist/util/mcp-server-utils.test.d.ts +2 -0
- package/dist/util/mcp-server-utils.test.d.ts.map +1 -0
- package/dist/util/mcp-server-utils.test.js +287 -0
- package/dist/util/mcp-server-utils.test.js.map +1 -0
- package/dist/util/message-builder.d.ts +2 -1
- package/dist/util/message-builder.d.ts.map +1 -1
- package/dist/util/message-builder.js +54 -36
- package/dist/util/message-builder.js.map +1 -1
- package/dist/util/message-builder.test.js +500 -13
- package/dist/util/message-builder.test.js.map +1 -1
- package/dist/util/registry-validators.d.ts +26 -0
- package/dist/util/registry-validators.d.ts.map +1 -0
- package/dist/util/registry-validators.js +105 -0
- package/dist/util/registry-validators.js.map +1 -0
- package/dist/util/registry-validators.test.d.ts +2 -0
- package/dist/util/registry-validators.test.d.ts.map +1 -0
- package/dist/util/registry-validators.test.js +235 -0
- package/dist/util/registry-validators.test.js.map +1 -0
- package/dist/util/registry.d.ts +35 -7
- package/dist/util/registry.d.ts.map +1 -1
- package/dist/util/registry.js +60 -77
- package/dist/util/registry.js.map +1 -1
- package/dist/util/registry.test.d.ts +2 -0
- package/dist/util/registry.test.d.ts.map +1 -0
- package/dist/util/registry.test.js +204 -0
- package/dist/util/registry.test.js.map +1 -0
- package/dist/util/resource-validators.d.ts +16 -0
- package/dist/util/resource-validators.d.ts.map +1 -0
- package/dist/util/resource-validators.js +34 -0
- package/dist/util/resource-validators.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 +12 -4
- package/dist/util/tool-caller.js.map +1 -1
- package/esm/{providers/hoc → hoc}/with-tambo-interactable.d.ts +2 -2
- package/esm/hoc/with-tambo-interactable.d.ts.map +1 -0
- package/esm/{providers/hoc → hoc}/with-tambo-interactable.js +29 -2
- package/esm/hoc/with-tambo-interactable.js.map +1 -0
- package/esm/hoc/with-tambo-interactable.test.d.ts +2 -0
- package/esm/hoc/with-tambo-interactable.test.d.ts.map +1 -0
- package/esm/hoc/with-tambo-interactable.test.js +187 -0
- package/esm/hoc/with-tambo-interactable.test.js.map +1 -0
- package/esm/hooks/index.d.ts +1 -1
- package/esm/hooks/index.d.ts.map +1 -1
- package/esm/hooks/index.js +1 -1
- package/esm/hooks/index.js.map +1 -1
- package/esm/hooks/use-current-message.d.ts +51 -7
- package/esm/hooks/use-current-message.d.ts.map +1 -1
- package/esm/hooks/use-current-message.js +48 -5
- package/esm/hooks/use-current-message.js.map +1 -1
- package/esm/hooks/use-current-message.test.d.ts +2 -0
- package/esm/hooks/use-current-message.test.d.ts.map +1 -0
- package/esm/hooks/use-current-message.test.js +259 -0
- package/esm/hooks/use-current-message.test.js.map +1 -0
- package/esm/index.d.ts +10 -8
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +4 -2
- package/esm/index.js.map +1 -1
- package/esm/mcp/index.d.ts +1 -1
- package/esm/mcp/index.d.ts.map +1 -1
- package/esm/mcp/index.js +1 -1
- package/esm/mcp/index.js.map +1 -1
- package/esm/mcp/mcp-hooks.d.ts +77 -6
- package/esm/mcp/mcp-hooks.d.ts.map +1 -1
- package/esm/mcp/mcp-hooks.js +103 -40
- package/esm/mcp/mcp-hooks.js.map +1 -1
- package/esm/mcp/mcp-hooks.test.js +84 -19
- 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 +2 -1
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/model/component-metadata.d.ts +444 -14
- package/esm/model/component-metadata.d.ts.map +1 -1
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/model/generate-component-response.d.ts +12 -1
- package/esm/model/generate-component-response.d.ts.map +1 -1
- package/esm/model/generate-component-response.js.map +1 -1
- package/esm/model/resource-info.d.ts +55 -0
- package/esm/model/resource-info.d.ts.map +1 -0
- package/esm/model/resource-info.js +2 -0
- package/esm/model/resource-info.js.map +1 -0
- package/esm/providers/index.d.ts +1 -1
- package/esm/providers/index.d.ts.map +1 -1
- package/esm/providers/index.js.map +1 -1
- package/esm/providers/tambo-component-provider.d.ts +4 -4
- package/esm/providers/tambo-component-provider.d.ts.map +1 -1
- package/esm/providers/tambo-component-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider-partial-updates.test.js +1 -1
- package/esm/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts +2 -3
- package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/esm/providers/tambo-interactable-provider.js +44 -38
- package/esm/providers/tambo-interactable-provider.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js +3 -3
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context.test.js +3 -3
- package/esm/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/esm/providers/tambo-registry-provider.d.ts +28 -7
- package/esm/providers/tambo-registry-provider.d.ts.map +1 -1
- package/esm/providers/tambo-registry-provider.js +67 -175
- package/esm/providers/tambo-registry-provider.js.map +1 -1
- package/esm/providers/tambo-registry-provider.test.js +148 -26
- package/esm/providers/tambo-registry-provider.test.js.map +1 -1
- package/esm/providers/tambo-registry-schema-compat.test.d.ts +2 -0
- package/esm/providers/tambo-registry-schema-compat.test.d.ts.map +1 -0
- package/esm/providers/tambo-registry-schema-compat.test.js +578 -0
- package/esm/providers/tambo-registry-schema-compat.test.js.map +1 -0
- package/esm/providers/tambo-stubs.d.ts +2 -2
- package/esm/providers/tambo-stubs.d.ts.map +1 -1
- package/esm/providers/tambo-stubs.js +5 -0
- package/esm/providers/tambo-stubs.js.map +1 -1
- package/esm/providers/tambo-thread-input-provider.d.ts +1 -0
- package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-input-provider.js +3 -3
- package/esm/providers/tambo-thread-input-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.test.js +24 -28
- package/esm/providers/tambo-thread-provider.test.js.map +1 -1
- package/esm/schema/index.d.ts +6 -0
- package/esm/schema/index.d.ts.map +1 -0
- package/esm/schema/index.js +6 -0
- package/esm/schema/index.js.map +1 -0
- package/esm/schema/json-schema.d.ts +35 -0
- package/esm/schema/json-schema.d.ts.map +1 -0
- package/esm/schema/json-schema.js +98 -0
- package/esm/schema/json-schema.js.map +1 -0
- package/esm/schema/schema.d.ts +66 -0
- package/esm/schema/schema.d.ts.map +1 -0
- package/esm/schema/schema.js +185 -0
- package/esm/schema/schema.js.map +1 -0
- package/esm/schema/schema.test.d.ts +2 -0
- package/esm/schema/schema.test.d.ts.map +1 -0
- package/esm/schema/schema.test.js +39 -0
- package/esm/schema/schema.test.js.map +1 -0
- package/esm/schema/standard-schema.d.ts +21 -0
- package/esm/schema/standard-schema.d.ts.map +1 -0
- package/esm/schema/standard-schema.js +34 -0
- package/esm/schema/standard-schema.js.map +1 -0
- package/esm/schema/validate.d.ts +14 -0
- package/esm/schema/validate.d.ts.map +1 -0
- package/esm/schema/validate.js +145 -0
- package/esm/schema/validate.js.map +1 -0
- package/esm/schema/validate.test.d.ts +2 -0
- package/esm/schema/validate.test.d.ts.map +1 -0
- package/esm/schema/validate.test.js +126 -0
- package/esm/schema/validate.test.js.map +1 -0
- package/esm/schema/zod.d.ts +54 -0
- package/esm/schema/zod.d.ts.map +1 -0
- package/esm/schema/zod.js +124 -0
- package/esm/schema/zod.js.map +1 -0
- package/esm/testing/tools.d.ts +29 -15
- package/esm/testing/tools.d.ts.map +1 -1
- package/esm/testing/tools.js +62 -16
- package/esm/testing/tools.js.map +1 -1
- package/esm/util/generate-component.d.ts.map +1 -1
- package/esm/util/generate-component.js +3 -3
- package/esm/util/generate-component.js.map +1 -1
- package/esm/util/mcp-server-utils.d.ts +23 -0
- package/esm/util/mcp-server-utils.d.ts.map +1 -0
- package/esm/util/mcp-server-utils.js +102 -0
- package/esm/util/mcp-server-utils.js.map +1 -0
- package/esm/util/mcp-server-utils.test.d.ts +2 -0
- package/esm/util/mcp-server-utils.test.d.ts.map +1 -0
- package/esm/util/mcp-server-utils.test.js +285 -0
- package/esm/util/mcp-server-utils.test.js.map +1 -0
- package/esm/util/message-builder.d.ts +2 -1
- package/esm/util/message-builder.d.ts.map +1 -1
- package/esm/util/message-builder.js +54 -36
- package/esm/util/message-builder.js.map +1 -1
- package/esm/util/message-builder.test.js +500 -13
- package/esm/util/message-builder.test.js.map +1 -1
- package/esm/util/registry-validators.d.ts +26 -0
- package/esm/util/registry-validators.d.ts.map +1 -0
- package/esm/util/registry-validators.js +100 -0
- package/esm/util/registry-validators.js.map +1 -0
- package/esm/util/registry-validators.test.d.ts +2 -0
- package/esm/util/registry-validators.test.d.ts.map +1 -0
- package/esm/util/registry-validators.test.js +233 -0
- package/esm/util/registry-validators.test.js.map +1 -0
- package/esm/util/registry.d.ts +35 -7
- package/esm/util/registry.d.ts.map +1 -1
- package/esm/util/registry.js +57 -73
- package/esm/util/registry.js.map +1 -1
- package/esm/util/registry.test.d.ts +2 -0
- package/esm/util/registry.test.d.ts.map +1 -0
- package/esm/util/registry.test.js +169 -0
- package/esm/util/registry.test.js.map +1 -0
- package/esm/util/resource-validators.d.ts +16 -0
- package/esm/util/resource-validators.d.ts.map +1 -0
- package/esm/util/resource-validators.js +30 -0
- package/esm/util/resource-validators.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 +12 -4
- package/esm/util/tool-caller.js.map +1 -1
- package/package.json +13 -8
- package/dist/providers/hoc/with-tambo-interactable.d.ts.map +0 -1
- package/dist/providers/hoc/with-tambo-interactable.js.map +0 -1
- package/dist/util/validate-zod-schema.d.ts +0 -10
- package/dist/util/validate-zod-schema.d.ts.map +0 -1
- package/dist/util/validate-zod-schema.js +0 -100
- package/dist/util/validate-zod-schema.js.map +0 -1
- package/dist/util/validate-zod-schema.test.d.ts +0 -2
- package/dist/util/validate-zod-schema.test.d.ts.map +0 -1
- package/dist/util/validate-zod-schema.test.js +0 -96
- package/dist/util/validate-zod-schema.test.js.map +0 -1
- package/esm/providers/hoc/with-tambo-interactable.d.ts.map +0 -1
- package/esm/providers/hoc/with-tambo-interactable.js.map +0 -1
- package/esm/util/validate-zod-schema.d.ts +0 -10
- package/esm/util/validate-zod-schema.d.ts.map +0 -1
- package/esm/util/validate-zod-schema.js +0 -97
- package/esm/util/validate-zod-schema.js.map +0 -1
- package/esm/util/validate-zod-schema.test.d.ts +0 -2
- package/esm/util/validate-zod-schema.test.d.ts.map +0 -1
- package/esm/util/validate-zod-schema.test.js +0 -94
- package/esm/util/validate-zod-schema.test.js.map +0 -1
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ import {
|
|
|
79
79
|
useTamboThread,
|
|
80
80
|
useTamboThreadInput,
|
|
81
81
|
} from "@tambo-ai/react";
|
|
82
|
-
import { z } from "zod";
|
|
82
|
+
import { z } from "zod/v4";
|
|
83
83
|
|
|
84
84
|
// 1. Register your components
|
|
85
85
|
const components = [
|
|
@@ -275,25 +275,24 @@ const mcpServers = [
|
|
|
275
275
|
Sometimes you need functions that run in the browser. DOM manipulation, authenticated fetches, accessing React state. Define them as tools and the AI can call them.
|
|
276
276
|
|
|
277
277
|
```tsx
|
|
278
|
-
import {
|
|
278
|
+
import { z } from "zod/v4";
|
|
279
|
+
import { defineTool } from "@tambo-ai/react";
|
|
279
280
|
|
|
280
|
-
const tools
|
|
281
|
-
{
|
|
281
|
+
const tools = [
|
|
282
|
+
defineTool({
|
|
282
283
|
name: "getWeather",
|
|
283
284
|
description: "Fetches weather data for a location",
|
|
284
|
-
tool: async (location
|
|
285
|
+
tool: async ({ location }) =>
|
|
285
286
|
fetch(`/api/weather?q=${location}`).then((r) => r.json()),
|
|
286
|
-
|
|
287
|
-
.
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
),
|
|
296
|
-
},
|
|
287
|
+
inputSchema: z.object({
|
|
288
|
+
location: z.string(),
|
|
289
|
+
}),
|
|
290
|
+
outputSchema: z.object({
|
|
291
|
+
temperature: z.number(),
|
|
292
|
+
condition: z.string(),
|
|
293
|
+
location: z.string(),
|
|
294
|
+
}),
|
|
295
|
+
}),
|
|
297
296
|
];
|
|
298
297
|
|
|
299
298
|
<TamboProvider tools={tools} components={components}>
|
|
@@ -316,10 +315,10 @@ const tools: TamboTool[] = [
|
|
|
316
315
|
const data = await fetchImageData(imageId);
|
|
317
316
|
return { url: data.imageUrl, description: data.description };
|
|
318
317
|
},
|
|
319
|
-
toolSchema: z
|
|
320
|
-
.
|
|
321
|
-
.
|
|
322
|
-
|
|
318
|
+
toolSchema: z.function({
|
|
319
|
+
input: z.string(),
|
|
320
|
+
output: z.object({ url: z.string(), description: z.string() }),
|
|
321
|
+
}),
|
|
323
322
|
transformToContent: (result) => [
|
|
324
323
|
{ type: "text", text: result.description },
|
|
325
324
|
{ type: "image_url", image_url: { url: result.url } },
|
|
@@ -330,6 +329,107 @@ const tools: TamboTool[] = [
|
|
|
330
329
|
|
|
331
330
|
The MCP integration automatically uses `transformToContent` to pass through rich content.
|
|
332
331
|
|
|
332
|
+
### Local Resources
|
|
333
|
+
|
|
334
|
+
Resources provide context to the AI by making content accessible without requiring a full MCP server. You can register static resources, dynamic resource functions, or both.
|
|
335
|
+
|
|
336
|
+
#### Static Resources
|
|
337
|
+
|
|
338
|
+
Register individual resources directly in your provider:
|
|
339
|
+
|
|
340
|
+
```tsx
|
|
341
|
+
import { type ListResourceItem } from "@tambo-ai/react";
|
|
342
|
+
|
|
343
|
+
const resources: ListResourceItem[] = [
|
|
344
|
+
{
|
|
345
|
+
uri: "file:///config/app-settings.json",
|
|
346
|
+
name: "App Settings",
|
|
347
|
+
description: "Current application configuration",
|
|
348
|
+
mimeType: "application/json",
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
uri: "file:///docs/user-guide.md",
|
|
352
|
+
name: "User Guide",
|
|
353
|
+
description: "Getting started documentation",
|
|
354
|
+
mimeType: "text/markdown",
|
|
355
|
+
},
|
|
356
|
+
];
|
|
357
|
+
|
|
358
|
+
<TamboProvider resources={resources}>
|
|
359
|
+
<App />
|
|
360
|
+
</TamboProvider>;
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
#### Dynamic Resources
|
|
364
|
+
|
|
365
|
+
For resources that need to be fetched or computed at runtime, provide `listResources` and `getResource` functions:
|
|
366
|
+
|
|
367
|
+
```tsx
|
|
368
|
+
import { type ResourceSource, type ReadResourceResult } from "@tambo-ai/react";
|
|
369
|
+
|
|
370
|
+
const listResources = async (search?: string) => {
|
|
371
|
+
const allDocs = await fetchUserDocuments();
|
|
372
|
+
return allDocs
|
|
373
|
+
.filter((doc) => !search || doc.name.includes(search))
|
|
374
|
+
.map((doc) => ({
|
|
375
|
+
uri: `file:///docs/${doc.id}`,
|
|
376
|
+
name: doc.name,
|
|
377
|
+
description: doc.summary,
|
|
378
|
+
mimeType: "text/markdown",
|
|
379
|
+
}));
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
const getResource = async (uri: string): Promise<ReadResourceResult> => {
|
|
383
|
+
const docId = uri.split("/").pop();
|
|
384
|
+
const content = await fetchDocumentContent(docId);
|
|
385
|
+
return {
|
|
386
|
+
contents: [
|
|
387
|
+
{
|
|
388
|
+
uri,
|
|
389
|
+
mimeType: "text/markdown",
|
|
390
|
+
text: content,
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
};
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
<TamboProvider listResources={listResources} getResource={getResource}>
|
|
397
|
+
<App />
|
|
398
|
+
</TamboProvider>;
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
**Important:** Both `listResources` and `getResource` must be provided together - you cannot provide one without the other.
|
|
402
|
+
|
|
403
|
+
#### Programmatic Registration
|
|
404
|
+
|
|
405
|
+
You can also register resources programmatically:
|
|
406
|
+
|
|
407
|
+
```tsx
|
|
408
|
+
const { registerResource, registerResourceSource } = useTamboRegistry();
|
|
409
|
+
|
|
410
|
+
// Register a single resource
|
|
411
|
+
registerResource({
|
|
412
|
+
uri: "file:///runtime/state.json",
|
|
413
|
+
name: "Application State",
|
|
414
|
+
mimeType: "application/json",
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// Register a dynamic source
|
|
418
|
+
registerResourceSource({
|
|
419
|
+
listResources: async () => [...],
|
|
420
|
+
getResource: async (uri) => ({ contents: [...] }),
|
|
421
|
+
});
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
#### Resource vs MCP Server
|
|
425
|
+
|
|
426
|
+
- **Local resources**: Fast, simple, runs in the browser. Great for app state, config, cached data.
|
|
427
|
+
- **MCP servers**: Full protocol support, server-side execution. Use for databases, APIs, external services.
|
|
428
|
+
|
|
429
|
+
Local resources appear in `useTamboMcpResourceList()` alongside MCP resources, with MCP resources always prefixed by their serverKey.
|
|
430
|
+
|
|
431
|
+
[→ Learn more about resources](https://docs.tambo.co/concepts/resources)
|
|
432
|
+
|
|
333
433
|
### Streaming Status
|
|
334
434
|
|
|
335
435
|
Monitor streaming status for progressive loading:
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { SupportedSchema } from "../schema";
|
|
3
3
|
export interface InteractableConfig {
|
|
4
4
|
componentName: string;
|
|
5
5
|
description: string;
|
|
6
|
-
propsSchema?:
|
|
6
|
+
propsSchema?: SupportedSchema;
|
|
7
7
|
}
|
|
8
8
|
export interface WithTamboInteractableProps {
|
|
9
9
|
interactableId?: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-tambo-interactable.d.ts","sourceRoot":"","sources":["../../src/hoc/with-tambo-interactable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAIxE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,MAAM,WAAW,0BAA0B;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CACzD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,EACpD,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EACxC,MAAM,EAAE,kBAAkB,4CAgH3B"}
|
|
@@ -37,7 +37,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
exports.withTamboInteractable = withTamboInteractable;
|
|
39
39
|
const react_1 = __importStar(require("react"));
|
|
40
|
-
const
|
|
40
|
+
const use_current_message_1 = require("../hooks/use-current-message");
|
|
41
|
+
const tambo_interactable_provider_1 = require("../providers/tambo-interactable-provider");
|
|
41
42
|
/**
|
|
42
43
|
* Higher-Order Component that makes any component interactable by tambo.
|
|
43
44
|
* @param WrappedComponent - The component to make interactable
|
|
@@ -111,7 +112,33 @@ function withTamboInteractable(WrappedComponent, config) {
|
|
|
111
112
|
updateInteractableComponentProps,
|
|
112
113
|
onPropsUpdate,
|
|
113
114
|
]);
|
|
114
|
-
|
|
115
|
+
// If the interactable ID is not yet set, render the component without provider
|
|
116
|
+
if (!interactableId) {
|
|
117
|
+
return react_1.default.createElement(WrappedComponent, { ...effectiveProps });
|
|
118
|
+
}
|
|
119
|
+
// Create a minimal message with interactable metadata
|
|
120
|
+
// This allows useTamboCurrentComponent to work with standalone interactable components
|
|
121
|
+
const minimalMessage = {
|
|
122
|
+
id: interactableId,
|
|
123
|
+
role: "assistant",
|
|
124
|
+
content: [],
|
|
125
|
+
threadId: "",
|
|
126
|
+
createdAt: new Date().toISOString(),
|
|
127
|
+
component: {
|
|
128
|
+
componentName: config.componentName,
|
|
129
|
+
componentState: {},
|
|
130
|
+
message: "",
|
|
131
|
+
props: effectiveProps,
|
|
132
|
+
},
|
|
133
|
+
componentState: {},
|
|
134
|
+
};
|
|
135
|
+
// Wrap with TamboMessageProvider including interactable metadata
|
|
136
|
+
return (react_1.default.createElement(use_current_message_1.TamboMessageProvider, { message: minimalMessage, interactableMetadata: {
|
|
137
|
+
id: interactableId,
|
|
138
|
+
componentName: config.componentName,
|
|
139
|
+
description: config.description,
|
|
140
|
+
} },
|
|
141
|
+
react_1.default.createElement(WrappedComponent, { ...effectiveProps })));
|
|
115
142
|
};
|
|
116
143
|
TamboInteractableWrapper.displayName = `withTamboInteractable(${displayName})`;
|
|
117
144
|
return TamboInteractableWrapper;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-tambo-interactable.js","sourceRoot":"","sources":["../../src/hoc/with-tambo-interactable.tsx"],"names":[],"mappings":"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","sourcesContent":["// react-sdk/src/providers/with-interactable.tsx\n\"use client\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { TamboMessageProvider } from \"../hooks/use-current-message\";\nimport { TamboThreadMessage } from \"../model/generate-component-response\";\nimport { useTamboInteractable } from \"../providers/tambo-interactable-provider\";\nimport { SupportedSchema } from \"../schema\";\n\nexport interface InteractableConfig {\n componentName: string;\n description: string;\n propsSchema?: SupportedSchema;\n}\n\nexport interface WithTamboInteractableProps {\n interactableId?: string;\n onInteractableReady?: (id: string) => void;\n onPropsUpdate?: (newProps: Record<string, any>) => void;\n}\n\n/**\n * Higher-Order Component that makes any component interactable by tambo.\n * @param WrappedComponent - The component to make interactable\n * @param config - Configuration for the interactable component\n * @returns A new component that is automatically registered as interactable\n * @example\n * ```tsx\n * const MyInteractableNote = withTamboInteractable(MyNote, {\n * componentName: \"MyNote\",\n * description: \"A note component\",\n * propsSchema: z.object({\n * title: z.string(),\n * content: z.string(),\n * }),\n * });\n *\n * // Usage\n * <MyInteractableNote title=\"My Note\" content=\"This is my note\" />\n * ```\n */\nexport function withTamboInteractable<P extends object>(\n WrappedComponent: React.ComponentType<P>,\n config: InteractableConfig,\n) {\n const displayName =\n WrappedComponent.displayName ?? WrappedComponent.name ?? \"Component\";\n\n const TamboInteractableWrapper: React.FC<P & WithTamboInteractableProps> = (\n props,\n ) => {\n const {\n addInteractableComponent,\n updateInteractableComponentProps,\n getInteractableComponent,\n } = useTamboInteractable();\n\n const [interactableId, setInteractableId] = useState<string | null>(null);\n const isInitialized = useRef(false);\n const lastParentProps = useRef<Record<string, any>>({});\n\n // Extract interactable-specific props\n const { onInteractableReady, onPropsUpdate, ...componentProps } = props;\n\n // Get the current interactable component to track prop updates\n const currentInteractable = interactableId\n ? getInteractableComponent(interactableId)\n : null;\n\n // Use the props from the interactable component if available, otherwise use the passed props\n // We need to be careful not to create a loop, so we only use stored props if they're different from passed props\n const effectiveProps = currentInteractable?.props ?? componentProps;\n\n // Memoize the registration function\n const registerComponent = useCallback(() => {\n if (!isInitialized.current) {\n const id = addInteractableComponent({\n name: config.componentName,\n description: config.description,\n component: WrappedComponent,\n props: componentProps,\n propsSchema: config.propsSchema,\n });\n\n setInteractableId(id);\n onInteractableReady?.(id);\n isInitialized.current = true;\n }\n }, [addInteractableComponent, componentProps, onInteractableReady]);\n\n // Register the component as interactable on mount (only once)\n useEffect(() => {\n registerComponent();\n }, [registerComponent]);\n\n // Update the interactable component when props change from parent\n useEffect(() => {\n if (interactableId && isInitialized.current) {\n // Only update if the props are different from what we last sent\n const lastPropsString = JSON.stringify(lastParentProps.current);\n const currentPropsString = JSON.stringify(componentProps);\n\n if (lastPropsString !== currentPropsString) {\n updateInteractableComponentProps(interactableId, componentProps);\n onPropsUpdate?.(componentProps);\n lastParentProps.current = componentProps;\n }\n }\n }, [\n interactableId,\n componentProps,\n updateInteractableComponentProps,\n onPropsUpdate,\n ]);\n\n // If the interactable ID is not yet set, render the component without provider\n if (!interactableId) {\n return <WrappedComponent {...(effectiveProps as P)} />;\n }\n\n // Create a minimal message with interactable metadata\n // This allows useTamboCurrentComponent to work with standalone interactable components\n const minimalMessage: TamboThreadMessage = {\n id: interactableId,\n role: \"assistant\" as const,\n content: [],\n threadId: \"\",\n createdAt: new Date().toISOString(),\n component: {\n componentName: config.componentName,\n componentState: {},\n message: \"\",\n props: effectiveProps,\n },\n componentState: {},\n };\n\n // Wrap with TamboMessageProvider including interactable metadata\n return (\n <TamboMessageProvider\n message={minimalMessage}\n interactableMetadata={{\n id: interactableId,\n componentName: config.componentName,\n description: config.description,\n }}\n >\n <WrappedComponent {...(effectiveProps as P)} />\n </TamboMessageProvider>\n );\n };\n\n TamboInteractableWrapper.displayName = `withTamboInteractable(${displayName})`;\n\n return TamboInteractableWrapper;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-tambo-interactable.test.d.ts","sourceRoot":"","sources":["../../src/hoc/with-tambo-interactable.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,192 @@
|
|
|
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 v3_1 = require("zod/v3");
|
|
9
|
+
const use_current_message_1 = require("../hooks/use-current-message");
|
|
10
|
+
const tambo_interactable_provider_1 = require("../providers/tambo-interactable-provider");
|
|
11
|
+
const with_tambo_interactable_1 = require("./with-tambo-interactable");
|
|
12
|
+
// Create a consistent mock implementation
|
|
13
|
+
const mockAddInteractableComponent = jest.fn(() => "mock-id-123");
|
|
14
|
+
const mockUpdateInteractableComponentProps = jest.fn();
|
|
15
|
+
const mockGetInteractableComponent = jest.fn(() => null);
|
|
16
|
+
const mockRemoveInteractableComponent = jest.fn();
|
|
17
|
+
const mockGetInteractableComponentsByName = jest.fn(() => []);
|
|
18
|
+
const mockClearAllInteractableComponents = jest.fn();
|
|
19
|
+
// Mock the interactable provider
|
|
20
|
+
jest.mock("../providers/tambo-interactable-provider", () => ({
|
|
21
|
+
TamboInteractableProvider: ({ children }) => (react_2.default.createElement("div", { "data-testid": "interactable-provider" }, children)),
|
|
22
|
+
useTamboInteractable: () => ({
|
|
23
|
+
addInteractableComponent: mockAddInteractableComponent,
|
|
24
|
+
updateInteractableComponentProps: mockUpdateInteractableComponentProps,
|
|
25
|
+
getInteractableComponent: mockGetInteractableComponent,
|
|
26
|
+
removeInteractableComponent: mockRemoveInteractableComponent,
|
|
27
|
+
getInteractableComponentsByName: mockGetInteractableComponentsByName,
|
|
28
|
+
clearAllInteractableComponents: mockClearAllInteractableComponents,
|
|
29
|
+
interactableComponents: [],
|
|
30
|
+
}),
|
|
31
|
+
}));
|
|
32
|
+
describe("withTamboInteractable", () => {
|
|
33
|
+
const TestComponent = ({ title, count }) => (react_2.default.createElement("div", null,
|
|
34
|
+
react_2.default.createElement("h1", { "data-testid": "title" }, title),
|
|
35
|
+
count !== undefined && react_2.default.createElement("span", { "data-testid": "count" }, count)));
|
|
36
|
+
const testSchema = v3_1.z.object({
|
|
37
|
+
title: v3_1.z.string(),
|
|
38
|
+
count: v3_1.z.number().optional(),
|
|
39
|
+
});
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
jest.clearAllMocks();
|
|
42
|
+
// Reset mock implementations
|
|
43
|
+
mockAddInteractableComponent.mockReturnValue("mock-id-123");
|
|
44
|
+
mockGetInteractableComponent.mockReturnValue(null);
|
|
45
|
+
mockGetInteractableComponentsByName.mockReturnValue([]);
|
|
46
|
+
});
|
|
47
|
+
it("should render the wrapped component with provided props", () => {
|
|
48
|
+
const InteractableComponent = (0, with_tambo_interactable_1.withTamboInteractable)(TestComponent, {
|
|
49
|
+
componentName: "TestComponent",
|
|
50
|
+
description: "A test component",
|
|
51
|
+
propsSchema: testSchema,
|
|
52
|
+
});
|
|
53
|
+
(0, react_1.render)(react_2.default.createElement(tambo_interactable_provider_1.TamboInteractableProvider, null,
|
|
54
|
+
react_2.default.createElement(InteractableComponent, { title: "Hello", count: 42 })));
|
|
55
|
+
expect(react_1.screen.getByTestId("title")).toHaveTextContent("Hello");
|
|
56
|
+
expect(react_1.screen.getByTestId("count")).toHaveTextContent("42");
|
|
57
|
+
});
|
|
58
|
+
it("should set displayName correctly", () => {
|
|
59
|
+
const InteractableComponent = (0, with_tambo_interactable_1.withTamboInteractable)(TestComponent, {
|
|
60
|
+
componentName: "TestComponent",
|
|
61
|
+
description: "A test component",
|
|
62
|
+
});
|
|
63
|
+
expect(InteractableComponent.displayName).toBe("withTamboInteractable(TestComponent)");
|
|
64
|
+
});
|
|
65
|
+
it("should handle components without displayName", () => {
|
|
66
|
+
const AnonymousComponent = () => react_2.default.createElement("div", null, "Anonymous");
|
|
67
|
+
const InteractableComponent = (0, with_tambo_interactable_1.withTamboInteractable)(AnonymousComponent, {
|
|
68
|
+
componentName: "AnonymousComponent",
|
|
69
|
+
description: "An anonymous component",
|
|
70
|
+
});
|
|
71
|
+
// Anonymous components get their name from the function name
|
|
72
|
+
expect(InteractableComponent.displayName).toBe("withTamboInteractable(AnonymousComponent)");
|
|
73
|
+
});
|
|
74
|
+
it("should provide TamboMessageProvider with interactable metadata", async () => {
|
|
75
|
+
// Child component that uses the context
|
|
76
|
+
const ContextConsumer = () => {
|
|
77
|
+
const component = (0, use_current_message_1.useTamboCurrentComponent)();
|
|
78
|
+
return (react_2.default.createElement("div", null,
|
|
79
|
+
react_2.default.createElement("span", { "data-testid": "interactable-id" }, component?.interactableId),
|
|
80
|
+
react_2.default.createElement("span", { "data-testid": "component-name" }, component?.componentName),
|
|
81
|
+
react_2.default.createElement("span", { "data-testid": "description" }, component?.description)));
|
|
82
|
+
};
|
|
83
|
+
// Wrap TestComponent to include ContextConsumer
|
|
84
|
+
const TestComponentWithConsumer = (props) => (react_2.default.createElement("div", null,
|
|
85
|
+
react_2.default.createElement(TestComponent, { ...props }),
|
|
86
|
+
react_2.default.createElement(ContextConsumer, null)));
|
|
87
|
+
const InteractableWithConsumer = (0, with_tambo_interactable_1.withTamboInteractable)(TestComponentWithConsumer, {
|
|
88
|
+
componentName: "TestComponent",
|
|
89
|
+
description: "A test component",
|
|
90
|
+
propsSchema: testSchema,
|
|
91
|
+
});
|
|
92
|
+
(0, react_1.render)(react_2.default.createElement(tambo_interactable_provider_1.TamboInteractableProvider, null,
|
|
93
|
+
react_2.default.createElement(InteractableWithConsumer, { title: "Hello" })));
|
|
94
|
+
// Wait for the component to register and render
|
|
95
|
+
await (0, react_1.waitFor)(() => {
|
|
96
|
+
expect(react_1.screen.getByTestId("interactable-id")).toHaveTextContent("mock-id-123");
|
|
97
|
+
});
|
|
98
|
+
expect(react_1.screen.getByTestId("component-name")).toHaveTextContent("TestComponent");
|
|
99
|
+
expect(react_1.screen.getByTestId("description")).toHaveTextContent("A test component");
|
|
100
|
+
});
|
|
101
|
+
it("should create minimal message with correct structure", async () => {
|
|
102
|
+
// Child component that checks the message structure
|
|
103
|
+
const MessageChecker = () => {
|
|
104
|
+
const component = (0, use_current_message_1.useTamboCurrentComponent)();
|
|
105
|
+
return (react_2.default.createElement("div", null,
|
|
106
|
+
react_2.default.createElement("span", { "data-testid": "has-component-name" }, component?.componentName ? "yes" : "no"),
|
|
107
|
+
react_2.default.createElement("span", { "data-testid": "has-props" }, component?.props ? "yes" : "no"),
|
|
108
|
+
react_2.default.createElement("span", { "data-testid": "has-interactable-id" }, component?.interactableId ? "yes" : "no"),
|
|
109
|
+
react_2.default.createElement("span", { "data-testid": "has-description" }, component?.description ? "yes" : "no")));
|
|
110
|
+
};
|
|
111
|
+
const TestComponentWithChecker = (props) => (react_2.default.createElement("div", null,
|
|
112
|
+
react_2.default.createElement(TestComponent, { ...props }),
|
|
113
|
+
react_2.default.createElement(MessageChecker, null)));
|
|
114
|
+
const InteractableWithChecker = (0, with_tambo_interactable_1.withTamboInteractable)(TestComponentWithChecker, {
|
|
115
|
+
componentName: "TestComponent",
|
|
116
|
+
description: "A test component",
|
|
117
|
+
propsSchema: testSchema,
|
|
118
|
+
});
|
|
119
|
+
(0, react_1.render)(react_2.default.createElement(tambo_interactable_provider_1.TamboInteractableProvider, null,
|
|
120
|
+
react_2.default.createElement(InteractableWithChecker, { title: "Hello", count: 42 })));
|
|
121
|
+
await (0, react_1.waitFor)(() => {
|
|
122
|
+
expect(react_1.screen.getByTestId("has-component-name")).toHaveTextContent("yes");
|
|
123
|
+
});
|
|
124
|
+
expect(react_1.screen.getByTestId("has-props")).toHaveTextContent("yes");
|
|
125
|
+
expect(react_1.screen.getByTestId("has-interactable-id")).toHaveTextContent("yes");
|
|
126
|
+
expect(react_1.screen.getByTestId("has-description")).toHaveTextContent("yes");
|
|
127
|
+
});
|
|
128
|
+
it("should pass through all component props correctly", () => {
|
|
129
|
+
const InteractableComponent = (0, with_tambo_interactable_1.withTamboInteractable)(TestComponent, {
|
|
130
|
+
componentName: "TestComponent",
|
|
131
|
+
description: "A test component",
|
|
132
|
+
propsSchema: testSchema,
|
|
133
|
+
});
|
|
134
|
+
(0, react_1.render)(react_2.default.createElement(tambo_interactable_provider_1.TamboInteractableProvider, null,
|
|
135
|
+
react_2.default.createElement(InteractableComponent, { title: "Test Title", count: 100 })));
|
|
136
|
+
expect(react_1.screen.getByTestId("title")).toHaveTextContent("Test Title");
|
|
137
|
+
expect(react_1.screen.getByTestId("count")).toHaveTextContent("100");
|
|
138
|
+
});
|
|
139
|
+
it("should filter out interactable-specific props from component props", () => {
|
|
140
|
+
const ExtendedComponent = ({ title, onInteractableReady, onPropsUpdate, }) => (react_2.default.createElement("div", null,
|
|
141
|
+
react_2.default.createElement("span", { "data-testid": "title" }, title),
|
|
142
|
+
react_2.default.createElement("span", { "data-testid": "has-ready" }, onInteractableReady ? "yes" : "no"),
|
|
143
|
+
react_2.default.createElement("span", { "data-testid": "has-update" }, onPropsUpdate ? "yes" : "no")));
|
|
144
|
+
const InteractableComponent = (0, with_tambo_interactable_1.withTamboInteractable)(ExtendedComponent, {
|
|
145
|
+
componentName: "ExtendedComponent",
|
|
146
|
+
description: "An extended component",
|
|
147
|
+
});
|
|
148
|
+
const mockReady = jest.fn();
|
|
149
|
+
const mockUpdate = jest.fn();
|
|
150
|
+
(0, react_1.render)(react_2.default.createElement(tambo_interactable_provider_1.TamboInteractableProvider, null,
|
|
151
|
+
react_2.default.createElement(InteractableComponent, { title: "Test", onInteractableReady: mockReady, onPropsUpdate: mockUpdate })));
|
|
152
|
+
expect(react_1.screen.getByTestId("title")).toHaveTextContent("Test");
|
|
153
|
+
// These props should be filtered out
|
|
154
|
+
expect(react_1.screen.getByTestId("has-ready")).toHaveTextContent("no");
|
|
155
|
+
expect(react_1.screen.getByTestId("has-update")).toHaveTextContent("no");
|
|
156
|
+
});
|
|
157
|
+
it("should work without propsSchema", () => {
|
|
158
|
+
const InteractableComponent = (0, with_tambo_interactable_1.withTamboInteractable)(TestComponent, {
|
|
159
|
+
componentName: "TestComponent",
|
|
160
|
+
description: "A test component",
|
|
161
|
+
});
|
|
162
|
+
(0, react_1.render)(react_2.default.createElement(tambo_interactable_provider_1.TamboInteractableProvider, null,
|
|
163
|
+
react_2.default.createElement(InteractableComponent, { title: "No Schema" })));
|
|
164
|
+
expect(react_1.screen.getByTestId("title")).toHaveTextContent("No Schema");
|
|
165
|
+
});
|
|
166
|
+
it("should render before interactable ID is set", () => {
|
|
167
|
+
const InteractableComponent = (0, with_tambo_interactable_1.withTamboInteractable)(TestComponent, {
|
|
168
|
+
componentName: "TestComponent",
|
|
169
|
+
description: "A test component",
|
|
170
|
+
});
|
|
171
|
+
const { container } = (0, react_1.render)(react_2.default.createElement(tambo_interactable_provider_1.TamboInteractableProvider, null,
|
|
172
|
+
react_2.default.createElement(InteractableComponent, { title: "Early Render" })));
|
|
173
|
+
// Component should render even before ID is available
|
|
174
|
+
expect(container.querySelector('[data-testid="title"]')).toBeInTheDocument();
|
|
175
|
+
});
|
|
176
|
+
it("should handle null/undefined values in props", () => {
|
|
177
|
+
const NullableComponent = ({ title, optional, nullable, }) => (react_2.default.createElement("div", null,
|
|
178
|
+
react_2.default.createElement("span", { "data-testid": "title" }, title),
|
|
179
|
+
react_2.default.createElement("span", { "data-testid": "optional" }, optional ?? "undefined"),
|
|
180
|
+
react_2.default.createElement("span", { "data-testid": "nullable" }, nullable ?? "null")));
|
|
181
|
+
const InteractableComponent = (0, with_tambo_interactable_1.withTamboInteractable)(NullableComponent, {
|
|
182
|
+
componentName: "NullableComponent",
|
|
183
|
+
description: "A component with nullable props",
|
|
184
|
+
});
|
|
185
|
+
(0, react_1.render)(react_2.default.createElement(tambo_interactable_provider_1.TamboInteractableProvider, null,
|
|
186
|
+
react_2.default.createElement(InteractableComponent, { title: "Test", nullable: null })));
|
|
187
|
+
expect(react_1.screen.getByTestId("title")).toHaveTextContent("Test");
|
|
188
|
+
expect(react_1.screen.getByTestId("optional")).toHaveTextContent("undefined");
|
|
189
|
+
expect(react_1.screen.getByTestId("nullable")).toHaveTextContent("null");
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
//# sourceMappingURL=with-tambo-interactable.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-tambo-interactable.test.js","sourceRoot":"","sources":["../../src/hoc/with-tambo-interactable.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import { render, screen, waitFor } from \"@testing-library/react\";\nimport React from \"react\";\nimport { z } from \"zod/v3\";\nimport { useTamboCurrentComponent } from \"../hooks/use-current-message\";\nimport { TamboInteractableProvider } from \"../providers/tambo-interactable-provider\";\nimport { withTamboInteractable } from \"./with-tambo-interactable\";\n\n// Create a consistent mock implementation\nconst mockAddInteractableComponent = jest.fn(() => \"mock-id-123\");\nconst mockUpdateInteractableComponentProps = jest.fn();\nconst mockGetInteractableComponent = jest.fn(() => null);\nconst mockRemoveInteractableComponent = jest.fn();\nconst mockGetInteractableComponentsByName = jest.fn(() => []);\nconst mockClearAllInteractableComponents = jest.fn();\n\n// Mock the interactable provider\njest.mock(\"../providers/tambo-interactable-provider\", () => ({\n TamboInteractableProvider: ({ children }: { children: React.ReactNode }) => (\n <div data-testid=\"interactable-provider\">{children}</div>\n ),\n useTamboInteractable: () => ({\n addInteractableComponent: mockAddInteractableComponent,\n updateInteractableComponentProps: mockUpdateInteractableComponentProps,\n getInteractableComponent: mockGetInteractableComponent,\n removeInteractableComponent: mockRemoveInteractableComponent,\n getInteractableComponentsByName: mockGetInteractableComponentsByName,\n clearAllInteractableComponents: mockClearAllInteractableComponents,\n interactableComponents: [],\n }),\n}));\n\ndescribe(\"withTamboInteractable\", () => {\n // Simple test component\n interface TestComponentProps {\n title: string;\n count?: number;\n }\n\n const TestComponent: React.FC<TestComponentProps> = ({ title, count }) => (\n <div>\n <h1 data-testid=\"title\">{title}</h1>\n {count !== undefined && <span data-testid=\"count\">{count}</span>}\n </div>\n );\n\n const testSchema = z.object({\n title: z.string(),\n count: z.number().optional(),\n });\n\n beforeEach(() => {\n jest.clearAllMocks();\n // Reset mock implementations\n mockAddInteractableComponent.mockReturnValue(\"mock-id-123\");\n mockGetInteractableComponent.mockReturnValue(null);\n mockGetInteractableComponentsByName.mockReturnValue([]);\n });\n\n it(\"should render the wrapped component with provided props\", () => {\n const InteractableComponent = withTamboInteractable(TestComponent, {\n componentName: \"TestComponent\",\n description: \"A test component\",\n propsSchema: testSchema,\n });\n\n render(\n <TamboInteractableProvider>\n <InteractableComponent title=\"Hello\" count={42} />\n </TamboInteractableProvider>,\n );\n\n expect(screen.getByTestId(\"title\")).toHaveTextContent(\"Hello\");\n expect(screen.getByTestId(\"count\")).toHaveTextContent(\"42\");\n });\n\n it(\"should set displayName correctly\", () => {\n const InteractableComponent = withTamboInteractable(TestComponent, {\n componentName: \"TestComponent\",\n description: \"A test component\",\n });\n\n expect(InteractableComponent.displayName).toBe(\n \"withTamboInteractable(TestComponent)\",\n );\n });\n\n it(\"should handle components without displayName\", () => {\n const AnonymousComponent = () => <div>Anonymous</div>;\n\n const InteractableComponent = withTamboInteractable(AnonymousComponent, {\n componentName: \"AnonymousComponent\",\n description: \"An anonymous component\",\n });\n\n // Anonymous components get their name from the function name\n expect(InteractableComponent.displayName).toBe(\n \"withTamboInteractable(AnonymousComponent)\",\n );\n });\n\n it(\"should provide TamboMessageProvider with interactable metadata\", async () => {\n // Child component that uses the context\n const ContextConsumer = () => {\n const component = useTamboCurrentComponent();\n return (\n <div>\n <span data-testid=\"interactable-id\">{component?.interactableId}</span>\n <span data-testid=\"component-name\">{component?.componentName}</span>\n <span data-testid=\"description\">{component?.description}</span>\n </div>\n );\n };\n\n // Wrap TestComponent to include ContextConsumer\n const TestComponentWithConsumer: React.FC<TestComponentProps> = (props) => (\n <div>\n <TestComponent {...props} />\n <ContextConsumer />\n </div>\n );\n\n const InteractableWithConsumer = withTamboInteractable(\n TestComponentWithConsumer,\n {\n componentName: \"TestComponent\",\n description: \"A test component\",\n propsSchema: testSchema,\n },\n );\n\n render(\n <TamboInteractableProvider>\n <InteractableWithConsumer title=\"Hello\" />\n </TamboInteractableProvider>,\n );\n\n // Wait for the component to register and render\n await waitFor(() => {\n expect(screen.getByTestId(\"interactable-id\")).toHaveTextContent(\n \"mock-id-123\",\n );\n });\n\n expect(screen.getByTestId(\"component-name\")).toHaveTextContent(\n \"TestComponent\",\n );\n expect(screen.getByTestId(\"description\")).toHaveTextContent(\n \"A test component\",\n );\n });\n\n it(\"should create minimal message with correct structure\", async () => {\n // Child component that checks the message structure\n const MessageChecker = () => {\n const component = useTamboCurrentComponent();\n return (\n <div>\n <span data-testid=\"has-component-name\">\n {component?.componentName ? \"yes\" : \"no\"}\n </span>\n <span data-testid=\"has-props\">{component?.props ? \"yes\" : \"no\"}</span>\n <span data-testid=\"has-interactable-id\">\n {component?.interactableId ? \"yes\" : \"no\"}\n </span>\n <span data-testid=\"has-description\">\n {component?.description ? \"yes\" : \"no\"}\n </span>\n </div>\n );\n };\n\n const TestComponentWithChecker: React.FC<TestComponentProps> = (props) => (\n <div>\n <TestComponent {...props} />\n <MessageChecker />\n </div>\n );\n\n const InteractableWithChecker = withTamboInteractable(\n TestComponentWithChecker,\n {\n componentName: \"TestComponent\",\n description: \"A test component\",\n propsSchema: testSchema,\n },\n );\n\n render(\n <TamboInteractableProvider>\n <InteractableWithChecker title=\"Hello\" count={42} />\n </TamboInteractableProvider>,\n );\n\n await waitFor(() => {\n expect(screen.getByTestId(\"has-component-name\")).toHaveTextContent(\"yes\");\n });\n\n expect(screen.getByTestId(\"has-props\")).toHaveTextContent(\"yes\");\n expect(screen.getByTestId(\"has-interactable-id\")).toHaveTextContent(\"yes\");\n expect(screen.getByTestId(\"has-description\")).toHaveTextContent(\"yes\");\n });\n\n it(\"should pass through all component props correctly\", () => {\n const InteractableComponent = withTamboInteractable(TestComponent, {\n componentName: \"TestComponent\",\n description: \"A test component\",\n propsSchema: testSchema,\n });\n\n render(\n <TamboInteractableProvider>\n <InteractableComponent title=\"Test Title\" count={100} />\n </TamboInteractableProvider>,\n );\n\n expect(screen.getByTestId(\"title\")).toHaveTextContent(\"Test Title\");\n expect(screen.getByTestId(\"count\")).toHaveTextContent(\"100\");\n });\n\n it(\"should filter out interactable-specific props from component props\", () => {\n interface ExtendedProps extends TestComponentProps {\n onInteractableReady?: (id: string) => void;\n onPropsUpdate?: (props: Record<string, any>) => void;\n }\n\n const ExtendedComponent: React.FC<ExtendedProps> = ({\n title,\n onInteractableReady,\n onPropsUpdate,\n }) => (\n <div>\n <span data-testid=\"title\">{title}</span>\n <span data-testid=\"has-ready\">\n {onInteractableReady ? \"yes\" : \"no\"}\n </span>\n <span data-testid=\"has-update\">{onPropsUpdate ? \"yes\" : \"no\"}</span>\n </div>\n );\n\n const InteractableComponent = withTamboInteractable(ExtendedComponent, {\n componentName: \"ExtendedComponent\",\n description: \"An extended component\",\n });\n\n const mockReady = jest.fn();\n const mockUpdate = jest.fn();\n\n render(\n <TamboInteractableProvider>\n <InteractableComponent\n title=\"Test\"\n onInteractableReady={mockReady}\n onPropsUpdate={mockUpdate}\n />\n </TamboInteractableProvider>,\n );\n\n expect(screen.getByTestId(\"title\")).toHaveTextContent(\"Test\");\n // These props should be filtered out\n expect(screen.getByTestId(\"has-ready\")).toHaveTextContent(\"no\");\n expect(screen.getByTestId(\"has-update\")).toHaveTextContent(\"no\");\n });\n\n it(\"should work without propsSchema\", () => {\n const InteractableComponent = withTamboInteractable(TestComponent, {\n componentName: \"TestComponent\",\n description: \"A test component\",\n });\n\n render(\n <TamboInteractableProvider>\n <InteractableComponent title=\"No Schema\" />\n </TamboInteractableProvider>,\n );\n\n expect(screen.getByTestId(\"title\")).toHaveTextContent(\"No Schema\");\n });\n\n it(\"should render before interactable ID is set\", () => {\n const InteractableComponent = withTamboInteractable(TestComponent, {\n componentName: \"TestComponent\",\n description: \"A test component\",\n });\n\n const { container } = render(\n <TamboInteractableProvider>\n <InteractableComponent title=\"Early Render\" />\n </TamboInteractableProvider>,\n );\n\n // Component should render even before ID is available\n expect(\n container.querySelector('[data-testid=\"title\"]'),\n ).toBeInTheDocument();\n });\n\n it(\"should handle null/undefined values in props\", () => {\n interface NullableProps {\n title: string;\n optional?: string;\n nullable: string | null;\n }\n\n const NullableComponent: React.FC<NullableProps> = ({\n title,\n optional,\n nullable,\n }) => (\n <div>\n <span data-testid=\"title\">{title}</span>\n <span data-testid=\"optional\">{optional ?? \"undefined\"}</span>\n <span data-testid=\"nullable\">{nullable ?? \"null\"}</span>\n </div>\n );\n\n const InteractableComponent = withTamboInteractable(NullableComponent, {\n componentName: \"NullableComponent\",\n description: \"A component with nullable props\",\n });\n\n render(\n <TamboInteractableProvider>\n <InteractableComponent title=\"Test\" nullable={null} />\n </TamboInteractableProvider>,\n );\n\n expect(screen.getByTestId(\"title\")).toHaveTextContent(\"Test\");\n expect(screen.getByTestId(\"optional\")).toHaveTextContent(\"undefined\");\n expect(screen.getByTestId(\"nullable\")).toHaveTextContent(\"null\");\n });\n});\n"]}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./react-query-hooks";
|
|
2
2
|
export { useTamboComponentState } from "./use-component-state";
|
|
3
|
-
export { useTamboCurrentMessage } from "./use-current-message";
|
|
3
|
+
export { useTamboCurrentComponent, useTamboCurrentMessage, type TamboCurrentComponent, } from "./use-current-message";
|
|
4
4
|
export { useTamboStreamingProps } from "./use-streaming-props";
|
|
5
5
|
export * from "./use-suggestions";
|
|
6
6
|
export { useTamboStreamStatus, type PropStatus, type StreamStatus, } from "./use-tambo-stream-status";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACL,oBAAoB,EACpB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -14,12 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.useTamboVoice = exports.useTamboThreadList = exports.useTamboStreamStatus = exports.useTamboStreamingProps = exports.useTamboCurrentMessage = exports.useTamboComponentState = void 0;
|
|
17
|
+
exports.useTamboVoice = exports.useTamboThreadList = exports.useTamboStreamStatus = exports.useTamboStreamingProps = exports.useTamboCurrentMessage = exports.useTamboCurrentComponent = exports.useTamboComponentState = void 0;
|
|
18
18
|
// Export all hooks from this directory
|
|
19
19
|
__exportStar(require("./react-query-hooks"), exports);
|
|
20
20
|
var use_component_state_1 = require("./use-component-state");
|
|
21
21
|
Object.defineProperty(exports, "useTamboComponentState", { enumerable: true, get: function () { return use_component_state_1.useTamboComponentState; } });
|
|
22
22
|
var use_current_message_1 = require("./use-current-message");
|
|
23
|
+
Object.defineProperty(exports, "useTamboCurrentComponent", { enumerable: true, get: function () { return use_current_message_1.useTamboCurrentComponent; } });
|
|
23
24
|
Object.defineProperty(exports, "useTamboCurrentMessage", { enumerable: true, get: function () { return use_current_message_1.useTamboCurrentMessage; } });
|
|
24
25
|
var use_streaming_props_1 = require("./use-streaming-props");
|
|
25
26
|
Object.defineProperty(exports, "useTamboStreamingProps", { enumerable: true, get: function () { return use_streaming_props_1.useTamboStreamingProps; } });
|
package/dist/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,sDAAoC;AACpC,6DAA+D;AAAtD,6HAAA,sBAAsB,OAAA;AAC/B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,sDAAoC;AACpC,6DAA+D;AAAtD,6HAAA,sBAAsB,OAAA;AAC/B,6DAI+B;AAH7B,+HAAA,wBAAwB,OAAA;AACxB,6HAAA,sBAAsB,OAAA;AAGxB,6DAA+D;AAAtD,6HAAA,sBAAsB,OAAA;AAC/B,oDAAkC;AAClC,qEAImC;AAHjC,+HAAA,oBAAoB,OAAA;AAItB,yDAAyD;AAAhD,uHAAA,kBAAkB,OAAA;AAC3B,qDAAkD;AAAzC,gHAAA,aAAa,OAAA","sourcesContent":["// Export all hooks from this directory\nexport * from \"./react-query-hooks\";\nexport { useTamboComponentState } from \"./use-component-state\";\nexport {\n useTamboCurrentComponent,\n useTamboCurrentMessage,\n type TamboCurrentComponent,\n} from \"./use-current-message\";\nexport { useTamboStreamingProps } from \"./use-streaming-props\";\nexport * from \"./use-suggestions\";\nexport {\n useTamboStreamStatus,\n type PropStatus,\n type StreamStatus,\n} from \"./use-tambo-stream-status\";\nexport { useTamboThreadList } from \"./use-tambo-threads\";\nexport { useTamboVoice } from \"./use-tambo-voice\";\n"]}
|
|
@@ -1,27 +1,71 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { TamboThreadMessage } from "../model/generate-component-response";
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { InteractableMetadata, TamboThreadMessage } from "../model/generate-component-response";
|
|
3
|
+
export interface TamboMessageProviderProps {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
message: TamboThreadMessage;
|
|
6
|
+
/** Optional interactable metadata for components wrapped with withInteractable */
|
|
7
|
+
interactableMetadata?: InteractableMetadata;
|
|
8
|
+
}
|
|
3
9
|
/**
|
|
4
|
-
* Wraps all components, so that they can find what message they are in
|
|
10
|
+
* Wraps all components, so that they can find what message they are in.
|
|
11
|
+
* Also supports optional interactable metadata for components wrapped with withInteractable.
|
|
5
12
|
* @param props - props for the TamboMessageProvider
|
|
6
13
|
* @param props.children - The children to wrap
|
|
7
14
|
* @param props.message - The message object
|
|
15
|
+
* @param props.interactableMetadata - Optional interactable component metadata
|
|
8
16
|
* @returns The wrapped component
|
|
9
17
|
*/
|
|
10
|
-
export declare const TamboMessageProvider: React.FC<
|
|
11
|
-
message: TamboThreadMessage;
|
|
12
|
-
}>>;
|
|
18
|
+
export declare const TamboMessageProvider: React.FC<TamboMessageProviderProps>;
|
|
13
19
|
/**
|
|
14
20
|
* Wraps a component with a TamboMessageProvider - this allows the provider
|
|
15
21
|
* to be used outside of a TSX file
|
|
16
22
|
* @param children - The children to wrap
|
|
17
23
|
* @param message - The message object
|
|
24
|
+
* @param interactableMetadata - Optional interactable metadata
|
|
18
25
|
* @returns The wrapped component
|
|
19
26
|
*/
|
|
20
|
-
export declare function wrapWithTamboMessageProvider(children: React.ReactNode, message: TamboThreadMessage): React.JSX.Element;
|
|
27
|
+
export declare function wrapWithTamboMessageProvider(children: React.ReactNode, message: TamboThreadMessage, interactableMetadata?: InteractableMetadata): React.JSX.Element;
|
|
21
28
|
/**
|
|
22
29
|
* Hook used inside a component wrapped with TamboMessageProvider, to get
|
|
23
30
|
* the current message.
|
|
24
31
|
* @returns The current message that is used to render the component
|
|
25
32
|
*/
|
|
26
33
|
export declare const useTamboCurrentMessage: () => TamboThreadMessage;
|
|
34
|
+
/**
|
|
35
|
+
* Component info extracted from the current message and interactable context.
|
|
36
|
+
* Provides a unified interface for accessing component metadata.
|
|
37
|
+
*/
|
|
38
|
+
export interface TamboCurrentComponent {
|
|
39
|
+
/** Component name from the message */
|
|
40
|
+
componentName?: string;
|
|
41
|
+
/** Component props from the message */
|
|
42
|
+
props?: Record<string, any>;
|
|
43
|
+
/** Interactable ID (only present for components wrapped with withInteractable) */
|
|
44
|
+
interactableId?: string;
|
|
45
|
+
/** Description (only present for components wrapped with withInteractable) */
|
|
46
|
+
description?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Hook to access the current component information from the message context.
|
|
50
|
+
* Provides a unified interface for both AI-generated and interactable components.
|
|
51
|
+
*
|
|
52
|
+
* **Use this hook when you need component metadata regardless of the context.**
|
|
53
|
+
* @returns Component info including name, props, and interactable metadata if available, or null if used outside TamboMessageProvider
|
|
54
|
+
* @example
|
|
55
|
+
* ```tsx
|
|
56
|
+
* function MyInlineEditor() {
|
|
57
|
+
* const component = useTamboCurrentComponent();
|
|
58
|
+
*
|
|
59
|
+
* if (!component) return null; // Not inside a component
|
|
60
|
+
*
|
|
61
|
+
* return (
|
|
62
|
+
* <div>
|
|
63
|
+
* Editing: {component.componentName}
|
|
64
|
+
* {component.interactableId && <span>ID: {component.interactableId}</span>}
|
|
65
|
+
* </div>
|
|
66
|
+
* );
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare const useTamboCurrentComponent: () => TamboCurrentComponent | null;
|
|
27
71
|
//# sourceMappingURL=use-current-message.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-current-message.d.ts","sourceRoot":"","sources":["../../src/hooks/use-current-message.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"use-current-message.d.ts","sourceRoot":"","sources":["../../src/hooks/use-current-message.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,sCAAsC,CAAC;AAI9C,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;CAC7C;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAkBpE,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,KAAK,CAAC,SAAS,EACzB,OAAO,EAAE,kBAAkB,EAC3B,oBAAoB,CAAC,EAAE,oBAAoB,qBAU5C;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,0BAQlC,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,sCAAsC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,kFAAkF;IAClF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,wBAAwB,QAAO,qBAAqB,GAAG,IAgBnE,CAAC"}
|