@tambo-ai/react 0.67.0 → 0.68.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/LICENSE +21 -0
- package/README.md +2 -4
- package/dist/context-helpers/current-interactables-context-helper.d.ts.map +1 -1
- package/dist/context-helpers/current-interactables-context-helper.js +4 -1
- package/dist/context-helpers/current-interactables-context-helper.js.map +1 -1
- package/dist/hoc/with-tambo-interactable.d.ts +50 -4
- package/dist/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/dist/hoc/with-tambo-interactable.js +20 -5
- package/dist/hoc/with-tambo-interactable.js.map +1 -1
- package/dist/hooks/use-component-state.d.ts +3 -8
- package/dist/hooks/use-component-state.d.ts.map +1 -1
- package/dist/hooks/use-component-state.js +8 -0
- package/dist/hooks/use-component-state.js.map +1 -1
- package/dist/hooks/use-component-state.test.js +37 -0
- package/dist/hooks/use-component-state.test.js.map +1 -1
- package/dist/hooks/use-tambo-threads.d.ts +3 -8
- package/dist/hooks/use-tambo-threads.d.ts.map +1 -1
- package/dist/hooks/use-tambo-threads.js +5 -3
- package/dist/hooks/use-tambo-threads.js.map +1 -1
- package/dist/hooks/use-tambo-threads.test.js +12 -2
- package/dist/hooks/use-tambo-threads.test.js.map +1 -1
- package/dist/mcp/mcp-constants.d.ts +19 -0
- package/dist/mcp/mcp-constants.d.ts.map +1 -0
- package/dist/mcp/mcp-constants.js +21 -0
- package/dist/mcp/mcp-constants.js.map +1 -0
- package/dist/mcp/mcp-hooks.d.ts +32 -3
- package/dist/mcp/mcp-hooks.d.ts.map +1 -1
- package/dist/mcp/mcp-hooks.js +40 -29
- package/dist/mcp/mcp-hooks.js.map +1 -1
- package/dist/mcp/mcp-hooks.test.js +8 -5
- package/dist/mcp/mcp-hooks.test.js.map +1 -1
- package/dist/mcp/tambo-mcp-provider.d.ts +7 -0
- package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.js +202 -155
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/model/component-metadata.d.ts +1 -1
- package/dist/model/component-metadata.d.ts.map +1 -1
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/model/tambo-interactable.d.ts +7 -5
- package/dist/model/tambo-interactable.d.ts.map +1 -1
- package/dist/model/tambo-interactable.js.map +1 -1
- package/dist/providers/__tests__/thread-input-resource-resolution.test.d.ts +2 -0
- package/dist/providers/__tests__/thread-input-resource-resolution.test.d.ts.map +1 -0
- package/dist/providers/__tests__/thread-input-resource-resolution.test.js +592 -0
- package/dist/providers/__tests__/thread-input-resource-resolution.test.js.map +1 -0
- package/dist/providers/tambo-interactable-provider-partial-updates.test.js +22 -21
- package/dist/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts +3 -2
- package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +98 -14
- package/dist/providers/tambo-interactable-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.test.js +242 -0
- package/dist/providers/tambo-interactable-provider.test.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts +1 -2
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js +10 -8
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-stubs.d.ts.map +1 -1
- package/dist/providers/tambo-stubs.js +1 -0
- package/dist/providers/tambo-stubs.js.map +1 -1
- package/dist/providers/tambo-stubs.test.js +1 -1
- package/dist/providers/tambo-stubs.test.js.map +1 -1
- package/dist/providers/tambo-thread-input-provider.d.ts +1 -6
- package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-input-provider.js +25 -8
- package/dist/providers/tambo-thread-input-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts +5 -0
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js +5 -2
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +2 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/json-schema.d.ts +7 -0
- package/dist/schema/json-schema.d.ts.map +1 -1
- package/dist/schema/json-schema.js +11 -0
- package/dist/schema/json-schema.js.map +1 -1
- package/dist/schema/json-schema.test.d.ts +2 -0
- package/dist/schema/json-schema.test.d.ts.map +1 -0
- package/dist/schema/json-schema.test.js +204 -0
- package/dist/schema/json-schema.test.js.map +1 -0
- package/dist/setupTests.js +3 -0
- package/dist/setupTests.js.map +1 -1
- package/dist/util/message-builder.d.ts +3 -1
- package/dist/util/message-builder.d.ts.map +1 -1
- package/dist/util/message-builder.js +20 -3
- package/dist/util/message-builder.js.map +1 -1
- package/dist/util/message-builder.test.js +269 -0
- package/dist/util/message-builder.test.js.map +1 -1
- package/dist/util/resource-content-resolver.d.ts +20 -0
- package/dist/util/resource-content-resolver.d.ts.map +1 -0
- package/dist/util/resource-content-resolver.js +93 -0
- package/dist/util/resource-content-resolver.js.map +1 -0
- package/dist/util/resource-content-resolver.test.d.ts +2 -0
- package/dist/util/resource-content-resolver.test.d.ts.map +1 -0
- package/dist/util/resource-content-resolver.test.js +254 -0
- package/dist/util/resource-content-resolver.test.js.map +1 -0
- package/esm/context-helpers/current-interactables-context-helper.d.ts.map +1 -1
- package/esm/context-helpers/current-interactables-context-helper.js +4 -1
- package/esm/context-helpers/current-interactables-context-helper.js.map +1 -1
- package/esm/hoc/with-tambo-interactable.d.ts +50 -4
- package/esm/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/esm/hoc/with-tambo-interactable.js +20 -5
- package/esm/hoc/with-tambo-interactable.js.map +1 -1
- package/esm/hooks/use-component-state.d.ts +3 -8
- package/esm/hooks/use-component-state.d.ts.map +1 -1
- package/esm/hooks/use-component-state.js +8 -0
- package/esm/hooks/use-component-state.js.map +1 -1
- package/esm/hooks/use-component-state.test.js +37 -0
- package/esm/hooks/use-component-state.test.js.map +1 -1
- package/esm/hooks/use-tambo-threads.d.ts +3 -8
- package/esm/hooks/use-tambo-threads.d.ts.map +1 -1
- package/esm/hooks/use-tambo-threads.js +5 -3
- package/esm/hooks/use-tambo-threads.js.map +1 -1
- package/esm/hooks/use-tambo-threads.test.js +12 -2
- package/esm/hooks/use-tambo-threads.test.js.map +1 -1
- package/esm/mcp/mcp-constants.d.ts +19 -0
- package/esm/mcp/mcp-constants.d.ts.map +1 -0
- package/esm/mcp/mcp-constants.js +18 -0
- package/esm/mcp/mcp-constants.js.map +1 -0
- package/esm/mcp/mcp-hooks.d.ts +32 -3
- package/esm/mcp/mcp-hooks.d.ts.map +1 -1
- package/esm/mcp/mcp-hooks.js +40 -30
- package/esm/mcp/mcp-hooks.js.map +1 -1
- package/esm/mcp/mcp-hooks.test.js +8 -5
- package/esm/mcp/mcp-hooks.test.js.map +1 -1
- package/esm/mcp/tambo-mcp-provider.d.ts +7 -0
- package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.js +201 -154
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/model/component-metadata.d.ts +1 -1
- package/esm/model/component-metadata.d.ts.map +1 -1
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/model/tambo-interactable.d.ts +7 -5
- package/esm/model/tambo-interactable.d.ts.map +1 -1
- package/esm/model/tambo-interactable.js.map +1 -1
- package/esm/providers/__tests__/thread-input-resource-resolution.test.d.ts +2 -0
- package/esm/providers/__tests__/thread-input-resource-resolution.test.d.ts.map +1 -0
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js +587 -0
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js.map +1 -0
- package/esm/providers/tambo-interactable-provider-partial-updates.test.js +22 -21
- package/esm/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts +3 -2
- package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/esm/providers/tambo-interactable-provider.js +98 -14
- package/esm/providers/tambo-interactable-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.test.js +242 -0
- package/esm/providers/tambo-interactable-provider.test.js.map +1 -1
- package/esm/providers/tambo-provider.d.ts +1 -2
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js +11 -9
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-stubs.d.ts.map +1 -1
- package/esm/providers/tambo-stubs.js +1 -0
- package/esm/providers/tambo-stubs.js.map +1 -1
- package/esm/providers/tambo-stubs.test.js +1 -1
- package/esm/providers/tambo-stubs.test.js.map +1 -1
- package/esm/providers/tambo-thread-input-provider.d.ts +1 -6
- package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-input-provider.js +25 -8
- package/esm/providers/tambo-thread-input-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts +5 -0
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js +5 -2
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/schema/index.d.ts +1 -1
- package/esm/schema/index.d.ts.map +1 -1
- package/esm/schema/index.js +1 -1
- package/esm/schema/index.js.map +1 -1
- package/esm/schema/json-schema.d.ts +7 -0
- package/esm/schema/json-schema.d.ts.map +1 -1
- package/esm/schema/json-schema.js +10 -0
- package/esm/schema/json-schema.js.map +1 -1
- package/esm/schema/json-schema.test.d.ts +2 -0
- package/esm/schema/json-schema.test.d.ts.map +1 -0
- package/esm/schema/json-schema.test.js +202 -0
- package/esm/schema/json-schema.test.js.map +1 -0
- package/esm/setupTests.js +3 -0
- package/esm/setupTests.js.map +1 -1
- package/esm/util/message-builder.d.ts +3 -1
- package/esm/util/message-builder.d.ts.map +1 -1
- package/esm/util/message-builder.js +20 -3
- package/esm/util/message-builder.js.map +1 -1
- package/esm/util/message-builder.test.js +269 -0
- package/esm/util/message-builder.test.js.map +1 -1
- package/esm/util/resource-content-resolver.d.ts +20 -0
- package/esm/util/resource-content-resolver.d.ts.map +1 -0
- package/esm/util/resource-content-resolver.js +89 -0
- package/esm/util/resource-content-resolver.js.map +1 -0
- package/esm/util/resource-content-resolver.test.d.ts +2 -0
- package/esm/util/resource-content-resolver.test.d.ts.map +1 -0
- package/esm/util/resource-content-resolver.test.js +252 -0
- package/esm/util/resource-content-resolver.test.js.map +1 -0
- package/package.json +8 -6
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const json_schema_1 = require("./json-schema");
|
|
4
|
+
describe("looksLikeJSONSchema", () => {
|
|
5
|
+
it("should return true for a valid object schema", () => {
|
|
6
|
+
const schema = {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
name: { type: "string" },
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
expect((0, json_schema_1.looksLikeJSONSchema)(schema)).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
it("should return true for a schema with only properties", () => {
|
|
15
|
+
const schema = {
|
|
16
|
+
properties: {
|
|
17
|
+
name: { type: "string" },
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
expect((0, json_schema_1.looksLikeJSONSchema)(schema)).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
it("should return true for a schema with items (array)", () => {
|
|
23
|
+
const schema = {
|
|
24
|
+
type: "array",
|
|
25
|
+
items: { type: "string" },
|
|
26
|
+
};
|
|
27
|
+
expect((0, json_schema_1.looksLikeJSONSchema)(schema)).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
it("should return true for a schema with enum", () => {
|
|
30
|
+
const schema = {
|
|
31
|
+
enum: ["a", "b", "c"],
|
|
32
|
+
};
|
|
33
|
+
expect((0, json_schema_1.looksLikeJSONSchema)(schema)).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it("should return true for a schema with const", () => {
|
|
36
|
+
const schema = {
|
|
37
|
+
const: "fixed-value",
|
|
38
|
+
};
|
|
39
|
+
expect((0, json_schema_1.looksLikeJSONSchema)(schema)).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
it("should return true for a schema with $ref", () => {
|
|
42
|
+
const schema = {
|
|
43
|
+
$ref: "#/definitions/Person",
|
|
44
|
+
};
|
|
45
|
+
expect((0, json_schema_1.looksLikeJSONSchema)(schema)).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
it("should return false for null", () => {
|
|
48
|
+
expect((0, json_schema_1.looksLikeJSONSchema)(null)).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
it("should return false for non-object", () => {
|
|
51
|
+
expect((0, json_schema_1.looksLikeJSONSchema)("string")).toBe(false);
|
|
52
|
+
expect((0, json_schema_1.looksLikeJSONSchema)(123)).toBe(false);
|
|
53
|
+
expect((0, json_schema_1.looksLikeJSONSchema)(undefined)).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
it("should return false for empty object", () => {
|
|
56
|
+
expect((0, json_schema_1.looksLikeJSONSchema)({})).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
it("should return false for object without schema keys", () => {
|
|
59
|
+
const notSchema = {
|
|
60
|
+
foo: "bar",
|
|
61
|
+
baz: 123,
|
|
62
|
+
};
|
|
63
|
+
expect((0, json_schema_1.looksLikeJSONSchema)(notSchema)).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe("isJsonSchemaTuple", () => {
|
|
67
|
+
it("should return true for draft-07 tuple (items as array)", () => {
|
|
68
|
+
const schema = {
|
|
69
|
+
type: "array",
|
|
70
|
+
items: [{ type: "string" }, { type: "number" }],
|
|
71
|
+
};
|
|
72
|
+
expect((0, json_schema_1.isJsonSchemaTuple)(schema)).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
it("should return true for draft 2020-12 tuple (prefixItems)", () => {
|
|
75
|
+
const schema = {
|
|
76
|
+
type: "array",
|
|
77
|
+
prefixItems: [{ type: "string" }, { type: "number" }],
|
|
78
|
+
};
|
|
79
|
+
expect((0, json_schema_1.isJsonSchemaTuple)(schema)).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
it("should return false for regular array schema (items as object)", () => {
|
|
82
|
+
const schema = {
|
|
83
|
+
type: "array",
|
|
84
|
+
items: { type: "string" },
|
|
85
|
+
};
|
|
86
|
+
expect((0, json_schema_1.isJsonSchemaTuple)(schema)).toBe(false);
|
|
87
|
+
});
|
|
88
|
+
it("should return false for non-array schema", () => {
|
|
89
|
+
const schema = {
|
|
90
|
+
type: "object",
|
|
91
|
+
properties: {},
|
|
92
|
+
};
|
|
93
|
+
expect((0, json_schema_1.isJsonSchemaTuple)(schema)).toBe(false);
|
|
94
|
+
});
|
|
95
|
+
it("should return false for array without items or prefixItems", () => {
|
|
96
|
+
const schema = {
|
|
97
|
+
type: "array",
|
|
98
|
+
};
|
|
99
|
+
expect((0, json_schema_1.isJsonSchemaTuple)(schema)).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe("getJsonSchemaTupleItems", () => {
|
|
103
|
+
it("should return items for draft-07 tuple", () => {
|
|
104
|
+
const items = [{ type: "string" }, { type: "number" }];
|
|
105
|
+
const schema = {
|
|
106
|
+
type: "array",
|
|
107
|
+
items: items,
|
|
108
|
+
};
|
|
109
|
+
expect((0, json_schema_1.getJsonSchemaTupleItems)(schema)).toEqual(items);
|
|
110
|
+
});
|
|
111
|
+
it("should return prefixItems for draft 2020-12 tuple", () => {
|
|
112
|
+
const prefixItems = [{ type: "string" }, { type: "number" }];
|
|
113
|
+
const schema = {
|
|
114
|
+
type: "array",
|
|
115
|
+
prefixItems: prefixItems,
|
|
116
|
+
};
|
|
117
|
+
expect((0, json_schema_1.getJsonSchemaTupleItems)(schema)).toEqual(prefixItems);
|
|
118
|
+
});
|
|
119
|
+
it("should return undefined for non-array schema", () => {
|
|
120
|
+
const schema = {
|
|
121
|
+
type: "object",
|
|
122
|
+
};
|
|
123
|
+
expect((0, json_schema_1.getJsonSchemaTupleItems)(schema)).toBeUndefined();
|
|
124
|
+
});
|
|
125
|
+
it("should return undefined for array without tuple items", () => {
|
|
126
|
+
const schema = {
|
|
127
|
+
type: "array",
|
|
128
|
+
items: { type: "string" },
|
|
129
|
+
};
|
|
130
|
+
expect((0, json_schema_1.getJsonSchemaTupleItems)(schema)).toBeUndefined();
|
|
131
|
+
});
|
|
132
|
+
it("should prefer prefixItems over items when both present", () => {
|
|
133
|
+
const prefixItems = [{ type: "boolean" }];
|
|
134
|
+
const items = [{ type: "string" }];
|
|
135
|
+
const schema = {
|
|
136
|
+
type: "array",
|
|
137
|
+
prefixItems: prefixItems,
|
|
138
|
+
items: items,
|
|
139
|
+
};
|
|
140
|
+
expect((0, json_schema_1.getJsonSchemaTupleItems)(schema)).toEqual(prefixItems);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe("makeJsonSchemaPartial", () => {
|
|
144
|
+
it("should remove required array from schema", () => {
|
|
145
|
+
const schema = {
|
|
146
|
+
type: "object",
|
|
147
|
+
properties: {
|
|
148
|
+
name: { type: "string" },
|
|
149
|
+
age: { type: "number" },
|
|
150
|
+
},
|
|
151
|
+
required: ["name", "age"],
|
|
152
|
+
};
|
|
153
|
+
const partial = (0, json_schema_1.makeJsonSchemaPartial)(schema);
|
|
154
|
+
expect(partial.required).toBeUndefined();
|
|
155
|
+
expect(partial.type).toBe("object");
|
|
156
|
+
expect(partial.properties).toEqual(schema.properties);
|
|
157
|
+
});
|
|
158
|
+
it("should preserve all other properties", () => {
|
|
159
|
+
const schema = {
|
|
160
|
+
type: "object",
|
|
161
|
+
properties: {
|
|
162
|
+
name: { type: "string", description: "The name" },
|
|
163
|
+
},
|
|
164
|
+
required: ["name"],
|
|
165
|
+
additionalProperties: false,
|
|
166
|
+
description: "A person schema",
|
|
167
|
+
title: "Person",
|
|
168
|
+
};
|
|
169
|
+
const partial = (0, json_schema_1.makeJsonSchemaPartial)(schema);
|
|
170
|
+
expect(partial.required).toBeUndefined();
|
|
171
|
+
expect(partial.type).toBe("object");
|
|
172
|
+
expect(partial.properties).toEqual(schema.properties);
|
|
173
|
+
expect(partial.additionalProperties).toBe(false);
|
|
174
|
+
expect(partial.description).toBe("A person schema");
|
|
175
|
+
expect(partial.title).toBe("Person");
|
|
176
|
+
});
|
|
177
|
+
it("should handle schema without required array", () => {
|
|
178
|
+
const schema = {
|
|
179
|
+
type: "object",
|
|
180
|
+
properties: {
|
|
181
|
+
name: { type: "string" },
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
const partial = (0, json_schema_1.makeJsonSchemaPartial)(schema);
|
|
185
|
+
expect(partial.required).toBeUndefined();
|
|
186
|
+
expect(partial.type).toBe("object");
|
|
187
|
+
expect(partial.properties).toEqual(schema.properties);
|
|
188
|
+
});
|
|
189
|
+
it("should not mutate the original schema", () => {
|
|
190
|
+
const schema = {
|
|
191
|
+
type: "object",
|
|
192
|
+
properties: {
|
|
193
|
+
name: { type: "string" },
|
|
194
|
+
},
|
|
195
|
+
required: ["name"],
|
|
196
|
+
};
|
|
197
|
+
const partial = (0, json_schema_1.makeJsonSchemaPartial)(schema);
|
|
198
|
+
// Original should be unchanged
|
|
199
|
+
expect(schema.required).toEqual(["name"]);
|
|
200
|
+
// Partial should not have required
|
|
201
|
+
expect(partial.required).toBeUndefined();
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
//# sourceMappingURL=json-schema.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-schema.test.js","sourceRoot":"","sources":["../../src/schema/json-schema.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { JSONSchema7 } from \"json-schema\";\nimport {\n getJsonSchemaTupleItems,\n isJsonSchemaTuple,\n JSONSchema7Extended,\n looksLikeJSONSchema,\n makeJsonSchemaPartial,\n} from \"./json-schema\";\n\ndescribe(\"looksLikeJSONSchema\", () => {\n it(\"should return true for a valid object schema\", () => {\n const schema = {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n },\n };\n expect(looksLikeJSONSchema(schema)).toBe(true);\n });\n\n it(\"should return true for a schema with only properties\", () => {\n const schema = {\n properties: {\n name: { type: \"string\" },\n },\n };\n expect(looksLikeJSONSchema(schema)).toBe(true);\n });\n\n it(\"should return true for a schema with items (array)\", () => {\n const schema = {\n type: \"array\",\n items: { type: \"string\" },\n };\n expect(looksLikeJSONSchema(schema)).toBe(true);\n });\n\n it(\"should return true for a schema with enum\", () => {\n const schema = {\n enum: [\"a\", \"b\", \"c\"],\n };\n expect(looksLikeJSONSchema(schema)).toBe(true);\n });\n\n it(\"should return true for a schema with const\", () => {\n const schema = {\n const: \"fixed-value\",\n };\n expect(looksLikeJSONSchema(schema)).toBe(true);\n });\n\n it(\"should return true for a schema with $ref\", () => {\n const schema = {\n $ref: \"#/definitions/Person\",\n };\n expect(looksLikeJSONSchema(schema)).toBe(true);\n });\n\n it(\"should return false for null\", () => {\n expect(looksLikeJSONSchema(null)).toBe(false);\n });\n\n it(\"should return false for non-object\", () => {\n expect(looksLikeJSONSchema(\"string\")).toBe(false);\n expect(looksLikeJSONSchema(123)).toBe(false);\n expect(looksLikeJSONSchema(undefined)).toBe(false);\n });\n\n it(\"should return false for empty object\", () => {\n expect(looksLikeJSONSchema({})).toBe(false);\n });\n\n it(\"should return false for object without schema keys\", () => {\n const notSchema = {\n foo: \"bar\",\n baz: 123,\n };\n expect(looksLikeJSONSchema(notSchema)).toBe(false);\n });\n});\n\ndescribe(\"isJsonSchemaTuple\", () => {\n it(\"should return true for draft-07 tuple (items as array)\", () => {\n const schema: JSONSchema7Extended = {\n type: \"array\",\n items: [{ type: \"string\" }, { type: \"number\" }],\n };\n expect(isJsonSchemaTuple(schema)).toBe(true);\n });\n\n it(\"should return true for draft 2020-12 tuple (prefixItems)\", () => {\n const schema: JSONSchema7Extended = {\n type: \"array\",\n prefixItems: [{ type: \"string\" }, { type: \"number\" }],\n };\n expect(isJsonSchemaTuple(schema)).toBe(true);\n });\n\n it(\"should return false for regular array schema (items as object)\", () => {\n const schema: JSONSchema7Extended = {\n type: \"array\",\n items: { type: \"string\" },\n };\n expect(isJsonSchemaTuple(schema)).toBe(false);\n });\n\n it(\"should return false for non-array schema\", () => {\n const schema: JSONSchema7Extended = {\n type: \"object\",\n properties: {},\n };\n expect(isJsonSchemaTuple(schema)).toBe(false);\n });\n\n it(\"should return false for array without items or prefixItems\", () => {\n const schema: JSONSchema7Extended = {\n type: \"array\",\n };\n expect(isJsonSchemaTuple(schema)).toBe(false);\n });\n});\n\ndescribe(\"getJsonSchemaTupleItems\", () => {\n it(\"should return items for draft-07 tuple\", () => {\n const items = [{ type: \"string\" }, { type: \"number\" }];\n const schema: JSONSchema7Extended = {\n type: \"array\",\n items: items as JSONSchema7[],\n };\n expect(getJsonSchemaTupleItems(schema)).toEqual(items);\n });\n\n it(\"should return prefixItems for draft 2020-12 tuple\", () => {\n const prefixItems = [{ type: \"string\" }, { type: \"number\" }];\n const schema: JSONSchema7Extended = {\n type: \"array\",\n prefixItems: prefixItems as JSONSchema7[],\n };\n expect(getJsonSchemaTupleItems(schema)).toEqual(prefixItems);\n });\n\n it(\"should return undefined for non-array schema\", () => {\n const schema: JSONSchema7Extended = {\n type: \"object\",\n };\n expect(getJsonSchemaTupleItems(schema)).toBeUndefined();\n });\n\n it(\"should return undefined for array without tuple items\", () => {\n const schema: JSONSchema7Extended = {\n type: \"array\",\n items: { type: \"string\" },\n };\n expect(getJsonSchemaTupleItems(schema)).toBeUndefined();\n });\n\n it(\"should prefer prefixItems over items when both present\", () => {\n const prefixItems = [{ type: \"boolean\" }];\n const items = [{ type: \"string\" }];\n const schema: JSONSchema7Extended = {\n type: \"array\",\n prefixItems: prefixItems as JSONSchema7[],\n items: items as JSONSchema7[],\n };\n expect(getJsonSchemaTupleItems(schema)).toEqual(prefixItems);\n });\n});\n\ndescribe(\"makeJsonSchemaPartial\", () => {\n it(\"should remove required array from schema\", () => {\n const schema: JSONSchema7 = {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n age: { type: \"number\" },\n },\n required: [\"name\", \"age\"],\n };\n\n const partial = makeJsonSchemaPartial(schema);\n\n expect(partial.required).toBeUndefined();\n expect(partial.type).toBe(\"object\");\n expect(partial.properties).toEqual(schema.properties);\n });\n\n it(\"should preserve all other properties\", () => {\n const schema: JSONSchema7 = {\n type: \"object\",\n properties: {\n name: { type: \"string\", description: \"The name\" },\n },\n required: [\"name\"],\n additionalProperties: false,\n description: \"A person schema\",\n title: \"Person\",\n };\n\n const partial = makeJsonSchemaPartial(schema);\n\n expect(partial.required).toBeUndefined();\n expect(partial.type).toBe(\"object\");\n expect(partial.properties).toEqual(schema.properties);\n expect(partial.additionalProperties).toBe(false);\n expect(partial.description).toBe(\"A person schema\");\n expect(partial.title).toBe(\"Person\");\n });\n\n it(\"should handle schema without required array\", () => {\n const schema: JSONSchema7 = {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n },\n };\n\n const partial = makeJsonSchemaPartial(schema);\n\n expect(partial.required).toBeUndefined();\n expect(partial.type).toBe(\"object\");\n expect(partial.properties).toEqual(schema.properties);\n });\n\n it(\"should not mutate the original schema\", () => {\n const schema: JSONSchema7 = {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n },\n required: [\"name\"],\n };\n\n const partial = makeJsonSchemaPartial(schema);\n\n // Original should be unchanged\n expect(schema.required).toEqual([\"name\"]);\n // Partial should not have required\n expect(partial.required).toBeUndefined();\n });\n});\n"]}
|
package/dist/setupTests.js
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
require("@testing-library/jest-dom");
|
|
4
4
|
const util_1 = require("util");
|
|
5
|
+
const web_1 = require("stream/web");
|
|
5
6
|
// Mock Date.now() to return a fixed timestamp for consistent testing
|
|
6
7
|
const mockDate = new Date(2025, 0, 5, 12, 32, 58, 936);
|
|
7
8
|
global.Date.now = jest.fn(() => mockDate.getTime());
|
|
8
9
|
// Add TextEncoder/TextDecoder polyfills for Node.js test environment
|
|
9
10
|
Object.assign(global, { TextEncoder: util_1.TextEncoder, TextDecoder: util_1.TextDecoder });
|
|
11
|
+
// Add Web Streams API polyfills for jsdom environment (used by @modelcontextprotocol/sdk)
|
|
12
|
+
Object.assign(global, { TransformStream: web_1.TransformStream, ReadableStream: web_1.ReadableStream, WritableStream: web_1.WritableStream });
|
|
10
13
|
// Mock react-media-recorder for tests (browser APIs not available in Node.js)
|
|
11
14
|
jest.mock("react-media-recorder", () => ({
|
|
12
15
|
useReactMediaRecorder: () => ({
|
package/dist/setupTests.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupTests.js","sourceRoot":"","sources":["../src/setupTests.ts"],"names":[],"mappings":";;AAAA,qCAAmC;AACnC,+BAAgD;
|
|
1
|
+
{"version":3,"file":"setupTests.js","sourceRoot":"","sources":["../src/setupTests.ts"],"names":[],"mappings":";;AAAA,qCAAmC;AACnC,+BAAgD;AAChD,oCAA6E;AAE7E,qEAAqE;AACrE,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;AACvD,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;AAEpD,qEAAqE;AACrE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,WAAW,EAAX,kBAAW,EAAE,WAAW,EAAX,kBAAW,EAAE,CAAC,CAAC;AAEpD,0FAA0F;AAC1F,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,eAAe,EAAf,qBAAe,EAAE,cAAc,EAAd,oBAAc,EAAE,cAAc,EAAd,oBAAc,EAAE,CAAC,CAAC;AAE3E,8EAA8E;AAC9E,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC;IACvC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5B,MAAM,EAAE,MAAM;QACd,cAAc,EAAE,IAAI,CAAC,EAAE,EAAE;QACzB,aAAa,EAAE,IAAI,CAAC,EAAE,EAAE;QACxB,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,IAAI;KACZ,CAAC;CACH,CAAC,CAAC,CAAC","sourcesContent":["import \"@testing-library/jest-dom\";\nimport { TextDecoder, TextEncoder } from \"util\";\nimport { TransformStream, ReadableStream, WritableStream } from \"stream/web\";\n\n// Mock Date.now() to return a fixed timestamp for consistent testing\nconst mockDate = new Date(2025, 0, 5, 12, 32, 58, 936);\nglobal.Date.now = jest.fn(() => mockDate.getTime());\n\n// Add TextEncoder/TextDecoder polyfills for Node.js test environment\nObject.assign(global, { TextEncoder, TextDecoder });\n\n// Add Web Streams API polyfills for jsdom environment (used by @modelcontextprotocol/sdk)\nObject.assign(global, { TransformStream, ReadableStream, WritableStream });\n\n// Mock react-media-recorder for tests (browser APIs not available in Node.js)\njest.mock(\"react-media-recorder\", () => ({\n useReactMediaRecorder: () => ({\n status: \"idle\",\n startRecording: jest.fn(),\n stopRecording: jest.fn(),\n mediaBlobUrl: null,\n error: null,\n }),\n}));\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
|
|
1
2
|
import type TamboAI from "@tambo-ai/typescript-sdk";
|
|
2
3
|
import { StagedImage } from "../hooks/use-message-images";
|
|
3
4
|
/**
|
|
@@ -5,7 +6,8 @@ import { StagedImage } from "../hooks/use-message-images";
|
|
|
5
6
|
* @param text - The text content, may include \@serverKey:uri resource references
|
|
6
7
|
* @param images - Array of staged images
|
|
7
8
|
* @param resourceNames - Map of resource IDs (serverKey:uri) to their display names
|
|
9
|
+
* @param resourceContent - Optional map of prefixed URIs to resolved content (for client-side resources)
|
|
8
10
|
* @returns Array of message content parts
|
|
9
11
|
*/
|
|
10
|
-
export declare function buildMessageContent(text: string, images: StagedImage[], resourceNames?: Record<string, string>): TamboAI.Beta.Threads.ChatCompletionContentPart[];
|
|
12
|
+
export declare function buildMessageContent(text: string, images: StagedImage[], resourceNames?: Record<string, string>, resourceContent?: Map<string, ReadResourceResult>): TamboAI.Beta.Threads.ChatCompletionContentPart[];
|
|
11
13
|
//# sourceMappingURL=message-builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-builder.d.ts","sourceRoot":"","sources":["../../src/util/message-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"message-builder.d.ts","sourceRoot":"","sources":["../../src/util/message-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,OAAO,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAwG1D;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,EAAE,EACrB,aAAa,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAC1C,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAChD,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,yBAAyB,EAAE,CA4BlD"}
|
|
@@ -25,9 +25,10 @@ const RESOURCE_REFERENCE_PATTERN = /@([a-zA-Z0-9-]+):(\S+)/g;
|
|
|
25
25
|
* - The backend routes resources based on the thread's MCP server configuration, not client-side keys
|
|
26
26
|
* @param text - Text potentially containing resource references
|
|
27
27
|
* @param resourceNames - Map of full resource IDs (serverKey:uri) to their display names
|
|
28
|
+
* @param resourceContent - Optional map of prefixed URIs to resolved content (for client-side resources)
|
|
28
29
|
* @returns Array of content parts in order (text and resource parts interleaved)
|
|
29
30
|
*/
|
|
30
|
-
function parseResourceReferences(text, resourceNames) {
|
|
31
|
+
function parseResourceReferences(text, resourceNames, resourceContent) {
|
|
31
32
|
const parts = [];
|
|
32
33
|
// Use matchAll to avoid global regex state issues
|
|
33
34
|
const matches = Array.from(text.matchAll(RESOURCE_REFERENCE_PATTERN));
|
|
@@ -51,6 +52,21 @@ function parseResourceReferences(text, resourceNames) {
|
|
|
51
52
|
if (name) {
|
|
52
53
|
resource.name = name;
|
|
53
54
|
}
|
|
55
|
+
// Include resolved content for client-side resources (MCP and registry)
|
|
56
|
+
// Server-side resources won't be in the map - backend resolves them by URI
|
|
57
|
+
const resolvedContent = resourceContent?.get(fullId);
|
|
58
|
+
if (resolvedContent?.contents?.[0]) {
|
|
59
|
+
const content = resolvedContent.contents[0];
|
|
60
|
+
if ("text" in content && content.text) {
|
|
61
|
+
resource.text = content.text;
|
|
62
|
+
}
|
|
63
|
+
else if ("blob" in content && content.blob) {
|
|
64
|
+
resource.blob = content.blob;
|
|
65
|
+
}
|
|
66
|
+
if ("mimeType" in content && content.mimeType) {
|
|
67
|
+
resource.mimeType = content.mimeType;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
54
70
|
parts.push({ type: "resource", resource });
|
|
55
71
|
if (match.index !== undefined) {
|
|
56
72
|
lastIndex = match.index + fullMatch.length;
|
|
@@ -77,16 +93,17 @@ function parseResourceReferences(text, resourceNames) {
|
|
|
77
93
|
* @param text - The text content, may include \@serverKey:uri resource references
|
|
78
94
|
* @param images - Array of staged images
|
|
79
95
|
* @param resourceNames - Map of resource IDs (serverKey:uri) to their display names
|
|
96
|
+
* @param resourceContent - Optional map of prefixed URIs to resolved content (for client-side resources)
|
|
80
97
|
* @returns Array of message content parts
|
|
81
98
|
*/
|
|
82
|
-
function buildMessageContent(text, images, resourceNames = {}) {
|
|
99
|
+
function buildMessageContent(text, images, resourceNames = {}, resourceContent) {
|
|
83
100
|
const content = [];
|
|
84
101
|
const hasNonWhitespaceText = text.trim().length > 0;
|
|
85
102
|
if (hasNonWhitespaceText) {
|
|
86
103
|
// Parse resource references from the original text so that all
|
|
87
104
|
// user-visible whitespace (including leading/trailing spaces and
|
|
88
105
|
// internal spacing) is preserved in the resulting content parts.
|
|
89
|
-
const parts = parseResourceReferences(text, resourceNames);
|
|
106
|
+
const parts = parseResourceReferences(text, resourceNames, resourceContent);
|
|
90
107
|
content.push(...parts);
|
|
91
108
|
}
|
|
92
109
|
// Add images at the end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-builder.js","sourceRoot":"","sources":["../../src/util/message-builder.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"message-builder.js","sourceRoot":"","sources":["../../src/util/message-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReadResourceResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport type TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { StagedImage } from \"../hooks/use-message-images\";\n\n/**\n * Regular expression to match MCP resource references in the format: \\@serverKey:uri\n *\n * Examples:\n * - \\@tambo-1hfs429:tambo:test://static/resource/1\n * - \\@linear:file://path/to/file\n *\n * Pattern breakdown:\n * - \\@ - Literal \\@ symbol\n * - ([a-zA-Z0-9-]+) - Server key (alphanumeric + hyphens, client-side routing key)\n * - : - Literal colon separator\n * - (\\S+) - URI (non-whitespace characters, actual resource URI)\n */\nconst RESOURCE_REFERENCE_PATTERN = /@([a-zA-Z0-9-]+):(\\S+)/g;\n\n/**\n * Parses text with resource references and returns interleaved content parts.\n * Resource references have the format: \\@serverKey:uri\n *\n * The serverKey prefix is stripped before sending to the backend because:\n * - It's a client-side routing key (e.g., \"tambo-1hfs429\") used by React SDK to route to the correct MCP connection\n * - The backend only needs the actual resource URI (e.g., \"tambo:test://static/resource/1\")\n * - The backend routes resources based on the thread's MCP server configuration, not client-side keys\n * @param text - Text potentially containing resource references\n * @param resourceNames - Map of full resource IDs (serverKey:uri) to their display names\n * @param resourceContent - Optional map of prefixed URIs to resolved content (for client-side resources)\n * @returns Array of content parts in order (text and resource parts interleaved)\n */\nfunction parseResourceReferences(\n text: string,\n resourceNames: Record<string, string>,\n resourceContent?: Map<string, ReadResourceResult>,\n): TamboAI.Beta.Threads.ChatCompletionContentPart[] {\n const parts: TamboAI.Beta.Threads.ChatCompletionContentPart[] = [];\n\n // Use matchAll to avoid global regex state issues\n const matches = Array.from(text.matchAll(RESOURCE_REFERENCE_PATTERN));\n let lastIndex = 0;\n\n // Find all resource references and interleave with text\n for (const match of matches) {\n const [fullMatch, serverKey, uri] = match;\n const fullId = `${serverKey}:${uri}`;\n\n // Add text before this resource reference (preserve whitespace)\n if (match.index !== undefined && match.index > lastIndex) {\n const textBefore = text.slice(lastIndex, match.index);\n if (textBefore.length > 0) {\n parts.push({\n type: \"text\",\n text: textBefore,\n });\n }\n }\n\n const resource: TamboAI.Resource = { uri };\n const name = resourceNames[fullId];\n if (name) {\n resource.name = name;\n }\n\n // Include resolved content for client-side resources (MCP and registry)\n // Server-side resources won't be in the map - backend resolves them by URI\n const resolvedContent = resourceContent?.get(fullId);\n if (resolvedContent?.contents?.[0]) {\n const content = resolvedContent.contents[0];\n if (\"text\" in content && content.text) {\n resource.text = content.text;\n } else if (\"blob\" in content && content.blob) {\n resource.blob = content.blob;\n }\n if (\"mimeType\" in content && content.mimeType) {\n resource.mimeType = content.mimeType;\n }\n }\n\n parts.push({ type: \"resource\", resource });\n\n if (match.index !== undefined) {\n lastIndex = match.index + fullMatch.length;\n }\n }\n\n // Add remaining text after the last resource reference (preserve whitespace)\n if (lastIndex < text.length) {\n const textAfter = text.slice(lastIndex);\n if (textAfter.length > 0) {\n parts.push({\n type: \"text\",\n text: textAfter,\n });\n }\n }\n\n // If no resource references were found, return the whole text as a single text part\n if (parts.length === 0 && text.trim()) {\n parts.push({ type: \"text\", text });\n }\n\n return parts;\n}\n\n/**\n * Builds message content with text, MCP resource references, and images\n * @param text - The text content, may include \\@serverKey:uri resource references\n * @param images - Array of staged images\n * @param resourceNames - Map of resource IDs (serverKey:uri) to their display names\n * @param resourceContent - Optional map of prefixed URIs to resolved content (for client-side resources)\n * @returns Array of message content parts\n */\nexport function buildMessageContent(\n text: string,\n images: StagedImage[],\n resourceNames: Record<string, string> = {},\n resourceContent?: Map<string, ReadResourceResult>,\n): TamboAI.Beta.Threads.ChatCompletionContentPart[] {\n const content: TamboAI.Beta.Threads.ChatCompletionContentPart[] = [];\n\n const hasNonWhitespaceText = text.trim().length > 0;\n\n if (hasNonWhitespaceText) {\n // Parse resource references from the original text so that all\n // user-visible whitespace (including leading/trailing spaces and\n // internal spacing) is preserved in the resulting content parts.\n const parts = parseResourceReferences(text, resourceNames, resourceContent);\n content.push(...parts);\n }\n\n // Add images at the end\n for (const image of images) {\n content.push({\n type: \"image_url\",\n image_url: {\n url: image.dataUrl,\n },\n });\n }\n\n if (content.length === 0) {\n throw new Error(\"Message must contain text or images\");\n }\n\n return content;\n}\n"]}
|
|
@@ -674,5 +674,274 @@ describe("buildMessageContent", () => {
|
|
|
674
674
|
expect(result[0].type).toBe("resource");
|
|
675
675
|
});
|
|
676
676
|
});
|
|
677
|
+
describe("resource content resolution", () => {
|
|
678
|
+
it("should include text content from resolved resource", () => {
|
|
679
|
+
const resourceContent = new Map([
|
|
680
|
+
[
|
|
681
|
+
"registry:file:///doc.txt",
|
|
682
|
+
{
|
|
683
|
+
contents: [
|
|
684
|
+
{
|
|
685
|
+
uri: "file:///doc.txt",
|
|
686
|
+
mimeType: "text/plain",
|
|
687
|
+
text: "This is the document content",
|
|
688
|
+
},
|
|
689
|
+
],
|
|
690
|
+
},
|
|
691
|
+
],
|
|
692
|
+
]);
|
|
693
|
+
const result = (0, message_builder_1.buildMessageContent)("Check @registry:file:///doc.txt", [], {}, resourceContent);
|
|
694
|
+
expect(result).toEqual([
|
|
695
|
+
{
|
|
696
|
+
type: "text",
|
|
697
|
+
text: "Check ",
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
type: "resource",
|
|
701
|
+
resource: {
|
|
702
|
+
uri: "file:///doc.txt",
|
|
703
|
+
text: "This is the document content",
|
|
704
|
+
mimeType: "text/plain",
|
|
705
|
+
},
|
|
706
|
+
},
|
|
707
|
+
]);
|
|
708
|
+
});
|
|
709
|
+
it("should include blob content from resolved resource", () => {
|
|
710
|
+
const resourceContent = new Map([
|
|
711
|
+
[
|
|
712
|
+
"registry:file:///image.png",
|
|
713
|
+
{
|
|
714
|
+
contents: [
|
|
715
|
+
{
|
|
716
|
+
uri: "file:///image.png",
|
|
717
|
+
mimeType: "image/png",
|
|
718
|
+
blob: "base64encodeddata",
|
|
719
|
+
},
|
|
720
|
+
],
|
|
721
|
+
},
|
|
722
|
+
],
|
|
723
|
+
]);
|
|
724
|
+
const result = (0, message_builder_1.buildMessageContent)("Check @registry:file:///image.png", [], {}, resourceContent);
|
|
725
|
+
expect(result).toEqual([
|
|
726
|
+
{
|
|
727
|
+
type: "text",
|
|
728
|
+
text: "Check ",
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
type: "resource",
|
|
732
|
+
resource: {
|
|
733
|
+
uri: "file:///image.png",
|
|
734
|
+
blob: "base64encodeddata",
|
|
735
|
+
mimeType: "image/png",
|
|
736
|
+
},
|
|
737
|
+
},
|
|
738
|
+
]);
|
|
739
|
+
});
|
|
740
|
+
it("should include name and resolved content together", () => {
|
|
741
|
+
const resourceNames = {
|
|
742
|
+
"registry:file:///doc.txt": "Important Document",
|
|
743
|
+
};
|
|
744
|
+
const resourceContent = new Map([
|
|
745
|
+
[
|
|
746
|
+
"registry:file:///doc.txt",
|
|
747
|
+
{
|
|
748
|
+
contents: [
|
|
749
|
+
{
|
|
750
|
+
uri: "file:///doc.txt",
|
|
751
|
+
mimeType: "text/plain",
|
|
752
|
+
text: "Document content here",
|
|
753
|
+
},
|
|
754
|
+
],
|
|
755
|
+
},
|
|
756
|
+
],
|
|
757
|
+
]);
|
|
758
|
+
const result = (0, message_builder_1.buildMessageContent)("@registry:file:///doc.txt", [], resourceNames, resourceContent);
|
|
759
|
+
expect(result).toEqual([
|
|
760
|
+
{
|
|
761
|
+
type: "resource",
|
|
762
|
+
resource: {
|
|
763
|
+
uri: "file:///doc.txt",
|
|
764
|
+
name: "Important Document",
|
|
765
|
+
text: "Document content here",
|
|
766
|
+
mimeType: "text/plain",
|
|
767
|
+
},
|
|
768
|
+
},
|
|
769
|
+
]);
|
|
770
|
+
});
|
|
771
|
+
it("should handle multiple resources with mixed resolved content", () => {
|
|
772
|
+
const resourceContent = new Map([
|
|
773
|
+
[
|
|
774
|
+
"registry:file:///doc1.txt",
|
|
775
|
+
{
|
|
776
|
+
contents: [
|
|
777
|
+
{
|
|
778
|
+
uri: "file:///doc1.txt",
|
|
779
|
+
text: "First doc content",
|
|
780
|
+
},
|
|
781
|
+
],
|
|
782
|
+
},
|
|
783
|
+
],
|
|
784
|
+
// doc2 is NOT in resourceContent - simulates internal server resource
|
|
785
|
+
]);
|
|
786
|
+
const result = (0, message_builder_1.buildMessageContent)("@registry:file:///doc1.txt and @tambo-abc:tambo://doc2", [], {}, resourceContent);
|
|
787
|
+
expect(result).toEqual([
|
|
788
|
+
{
|
|
789
|
+
type: "resource",
|
|
790
|
+
resource: {
|
|
791
|
+
uri: "file:///doc1.txt",
|
|
792
|
+
text: "First doc content",
|
|
793
|
+
},
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
type: "text",
|
|
797
|
+
text: " and ",
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
type: "resource",
|
|
801
|
+
resource: {
|
|
802
|
+
uri: "tambo://doc2",
|
|
803
|
+
// No text/blob - internal server resource
|
|
804
|
+
},
|
|
805
|
+
},
|
|
806
|
+
]);
|
|
807
|
+
});
|
|
808
|
+
it("should handle resolved content without mimeType", () => {
|
|
809
|
+
const resourceContent = new Map([
|
|
810
|
+
[
|
|
811
|
+
"server:file:///doc.txt",
|
|
812
|
+
{
|
|
813
|
+
contents: [
|
|
814
|
+
{
|
|
815
|
+
uri: "file:///doc.txt",
|
|
816
|
+
text: "Content without mimeType",
|
|
817
|
+
},
|
|
818
|
+
],
|
|
819
|
+
},
|
|
820
|
+
],
|
|
821
|
+
]);
|
|
822
|
+
const result = (0, message_builder_1.buildMessageContent)("@server:file:///doc.txt", [], {}, resourceContent);
|
|
823
|
+
expect(result).toEqual([
|
|
824
|
+
{
|
|
825
|
+
type: "resource",
|
|
826
|
+
resource: {
|
|
827
|
+
uri: "file:///doc.txt",
|
|
828
|
+
text: "Content without mimeType",
|
|
829
|
+
},
|
|
830
|
+
},
|
|
831
|
+
]);
|
|
832
|
+
});
|
|
833
|
+
it("should handle empty resourceContent map gracefully", () => {
|
|
834
|
+
const result = (0, message_builder_1.buildMessageContent)("@registry:file:///doc.txt", [], {}, new Map());
|
|
835
|
+
expect(result).toEqual([
|
|
836
|
+
{
|
|
837
|
+
type: "resource",
|
|
838
|
+
resource: {
|
|
839
|
+
uri: "file:///doc.txt",
|
|
840
|
+
},
|
|
841
|
+
},
|
|
842
|
+
]);
|
|
843
|
+
});
|
|
844
|
+
it("should handle undefined resourceContent gracefully", () => {
|
|
845
|
+
const result = (0, message_builder_1.buildMessageContent)("@registry:file:///doc.txt", [], {}, undefined);
|
|
846
|
+
expect(result).toEqual([
|
|
847
|
+
{
|
|
848
|
+
type: "resource",
|
|
849
|
+
resource: {
|
|
850
|
+
uri: "file:///doc.txt",
|
|
851
|
+
},
|
|
852
|
+
},
|
|
853
|
+
]);
|
|
854
|
+
});
|
|
855
|
+
it("should handle resolved content with empty contents array", () => {
|
|
856
|
+
const resourceContent = new Map([
|
|
857
|
+
[
|
|
858
|
+
"registry:file:///doc.txt",
|
|
859
|
+
{
|
|
860
|
+
contents: [],
|
|
861
|
+
},
|
|
862
|
+
],
|
|
863
|
+
]);
|
|
864
|
+
const result = (0, message_builder_1.buildMessageContent)("@registry:file:///doc.txt", [], {}, resourceContent);
|
|
865
|
+
expect(result).toEqual([
|
|
866
|
+
{
|
|
867
|
+
type: "resource",
|
|
868
|
+
resource: {
|
|
869
|
+
uri: "file:///doc.txt",
|
|
870
|
+
},
|
|
871
|
+
},
|
|
872
|
+
]);
|
|
873
|
+
});
|
|
874
|
+
it("should include resolved content with MCP server resources", () => {
|
|
875
|
+
const resourceContent = new Map([
|
|
876
|
+
[
|
|
877
|
+
"linear:linear://issue/123",
|
|
878
|
+
{
|
|
879
|
+
contents: [
|
|
880
|
+
{
|
|
881
|
+
uri: "linear://issue/123",
|
|
882
|
+
mimeType: "application/json",
|
|
883
|
+
text: '{"title": "Bug fix", "status": "open"}',
|
|
884
|
+
},
|
|
885
|
+
],
|
|
886
|
+
},
|
|
887
|
+
],
|
|
888
|
+
]);
|
|
889
|
+
const result = (0, message_builder_1.buildMessageContent)("Check issue @linear:linear://issue/123", [], {}, resourceContent);
|
|
890
|
+
expect(result).toEqual([
|
|
891
|
+
{
|
|
892
|
+
type: "text",
|
|
893
|
+
text: "Check issue ",
|
|
894
|
+
},
|
|
895
|
+
{
|
|
896
|
+
type: "resource",
|
|
897
|
+
resource: {
|
|
898
|
+
uri: "linear://issue/123",
|
|
899
|
+
text: '{"title": "Bug fix", "status": "open"}',
|
|
900
|
+
mimeType: "application/json",
|
|
901
|
+
},
|
|
902
|
+
},
|
|
903
|
+
]);
|
|
904
|
+
});
|
|
905
|
+
it("should combine resolved content with images", () => {
|
|
906
|
+
const resourceContent = new Map([
|
|
907
|
+
[
|
|
908
|
+
"registry:file:///doc.txt",
|
|
909
|
+
{
|
|
910
|
+
contents: [
|
|
911
|
+
{
|
|
912
|
+
uri: "file:///doc.txt",
|
|
913
|
+
text: "Document content",
|
|
914
|
+
},
|
|
915
|
+
],
|
|
916
|
+
},
|
|
917
|
+
],
|
|
918
|
+
]);
|
|
919
|
+
const images = [
|
|
920
|
+
createMockStagedImage({
|
|
921
|
+
dataUrl: "data:image/png;base64,imagedata",
|
|
922
|
+
}),
|
|
923
|
+
];
|
|
924
|
+
const result = (0, message_builder_1.buildMessageContent)("Check @registry:file:///doc.txt", images, {}, resourceContent);
|
|
925
|
+
expect(result).toEqual([
|
|
926
|
+
{
|
|
927
|
+
type: "text",
|
|
928
|
+
text: "Check ",
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
type: "resource",
|
|
932
|
+
resource: {
|
|
933
|
+
uri: "file:///doc.txt",
|
|
934
|
+
text: "Document content",
|
|
935
|
+
},
|
|
936
|
+
},
|
|
937
|
+
{
|
|
938
|
+
type: "image_url",
|
|
939
|
+
image_url: {
|
|
940
|
+
url: "data:image/png;base64,imagedata",
|
|
941
|
+
},
|
|
942
|
+
},
|
|
943
|
+
]);
|
|
944
|
+
});
|
|
945
|
+
});
|
|
677
946
|
});
|
|
678
947
|
//# sourceMappingURL=message-builder.test.js.map
|