@copilotkit/vue 2.0.0-rc.8 → 2.0.0-rc.9
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/dist/hooks/use-copilot-action.d.ts.map +1 -1
- package/dist/hooks/use-frontend-tool.d.ts +1 -1
- package/dist/hooks/use-frontend-tool.d.ts.map +1 -1
- package/dist/hooks/zod-parameters.d.ts +14 -0
- package/dist/hooks/zod-parameters.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +392 -290
- package/dist/index.mjs.map +1 -1
- package/dist/use-render-activity-message-B59A4R48.js +18097 -0
- package/dist/use-render-activity-message-B59A4R48.js.map +1 -0
- package/dist/use-render-activity-message-u0OVXjd8.cjs +92 -0
- package/dist/use-render-activity-message-u0OVXjd8.cjs.map +1 -0
- package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +13 -45
- package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +1 -1
- package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -1
- package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +13 -5
- package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts.map +1 -1
- package/dist/v2/components/a2ui.d.ts +3 -7
- package/dist/v2/components/a2ui.d.ts.map +1 -1
- package/dist/v2/index.cjs +1 -1
- package/dist/v2/index.mjs +173 -173
- package/dist/v2/lib/processPartialHtml.d.ts +1 -2
- package/dist/v2/lib/processPartialHtml.d.ts.map +1 -1
- package/dist/v2/providers/CopilotKitProvider.vue.d.ts +1 -1
- package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/hooks/__tests__/zod-parameters.test.ts +520 -0
- package/src/hooks/use-copilot-action.ts +2 -1
- package/src/hooks/use-frontend-tool.ts +3 -6
- package/src/hooks/zod-parameters.ts +162 -0
- package/src/v2/components/A2UIMessageRenderer.ts +3 -3
- package/src/v2/components/OpenGenerativeUIRenderer.ts +51 -373
- package/src/v2/components/__tests__/A2UICatalogContext.test.ts +1 -1
- package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +55 -6
- package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +1 -1
- package/src/v2/components/a2ui/A2UICatalogContext.ts +10 -102
- package/src/v2/components/a2ui/A2UIRecoveryStates.ts +1 -1
- package/src/v2/components/a2ui.ts +1 -1
- package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.ts +26 -9
- package/src/v2/hooks/__tests__/zod-regression.test.ts +1 -1
- package/src/v2/lib/processPartialHtml.ts +6 -21
- package/src/v2/providers/CopilotKitProvider.vue +26 -34
- package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +1 -1
- package/vite.config.ts +2 -2
- package/dist/use-render-activity-message-C5LCG9a9.js +0 -16451
- package/dist/use-render-activity-message-C5LCG9a9.js.map +0 -1
- package/dist/use-render-activity-message-CPzguixR.cjs +0 -74
- package/dist/use-render-activity-message-CPzguixR.cjs.map +0 -1
- package/src/v2/lib/__tests__/processPartialHtml.test.ts +0 -84
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import type * as CoreModule from "@copilotkit/core";
|
|
2
3
|
import { render } from "@testing-library/vue";
|
|
3
4
|
import { ref } from "vue";
|
|
4
5
|
import type { Ref } from "vue";
|
|
@@ -37,12 +38,25 @@ const mockCreate = vi.fn<MockCreateFn>(() => ({
|
|
|
37
38
|
destroy: mockDestroy,
|
|
38
39
|
}));
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
// Run the real core controller against a fake websandbox
|
|
42
|
+
vi.mock("@copilotkit/core", async (importOriginal) => {
|
|
43
|
+
const actual = await importOriginal<typeof CoreModule>();
|
|
44
|
+
class TestOpenGenerativeUIController
|
|
45
|
+
extends actual.ɵOpenGenerativeUIController
|
|
46
|
+
{
|
|
47
|
+
constructor() {
|
|
48
|
+
super({
|
|
49
|
+
loadWebsandbox: async () => ({
|
|
50
|
+
create: (localApi, options) => mockCreate(localApi, options),
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
...actual,
|
|
57
|
+
ɵOpenGenerativeUIController: TestOpenGenerativeUIController,
|
|
58
|
+
};
|
|
59
|
+
});
|
|
46
60
|
|
|
47
61
|
async function flushImport() {
|
|
48
62
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
@@ -178,6 +192,41 @@ describe("OpenGenerativeUIRenderer", () => {
|
|
|
178
192
|
expect(options.frameContent).toContain("v2");
|
|
179
193
|
});
|
|
180
194
|
|
|
195
|
+
it("sizes the container to the height the final sandbox reports", async () => {
|
|
196
|
+
const iframe = document.createElement("iframe");
|
|
197
|
+
mockCreate.mockImplementationOnce((_localApi, options) => {
|
|
198
|
+
(options.frameContainer as HTMLElement).appendChild(iframe);
|
|
199
|
+
return {
|
|
200
|
+
iframe,
|
|
201
|
+
promise: Promise.resolve(),
|
|
202
|
+
run: mockRun,
|
|
203
|
+
destroy: mockDestroy,
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
const { getByTestId } = renderRenderer({
|
|
207
|
+
initialHeight: 150,
|
|
208
|
+
html: ["<body><p>Chart</p></body>"],
|
|
209
|
+
htmlComplete: true,
|
|
210
|
+
generating: false,
|
|
211
|
+
});
|
|
212
|
+
await flushImport();
|
|
213
|
+
expect(getByTestId("open-generative-ui-renderer").style.height).toBe(
|
|
214
|
+
"150px",
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
window.dispatchEvent(
|
|
218
|
+
new MessageEvent("message", {
|
|
219
|
+
source: iframe.contentWindow,
|
|
220
|
+
data: { type: "__ck_resize", height: 420 },
|
|
221
|
+
}),
|
|
222
|
+
);
|
|
223
|
+
await flushImport();
|
|
224
|
+
|
|
225
|
+
expect(getByTestId("open-generative-ui-renderer").style.height).toBe(
|
|
226
|
+
"420px",
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
|
|
181
230
|
it("destroys sandbox on unmount", async () => {
|
|
182
231
|
const mounted = renderRenderer({
|
|
183
232
|
html: ["<head></head><body>bye</body>"],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { watch } from "vue";
|
|
2
2
|
import type { ShallowRef } from "vue";
|
|
3
|
-
import
|
|
3
|
+
import * as z from "zod";
|
|
4
4
|
import type { CopilotKitCoreVue } from "../../lib/vue-core";
|
|
5
5
|
import { defineToolCallRenderer } from "../../types/defineToolCallRenderer";
|
|
6
6
|
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { computed, watch } from "vue";
|
|
2
2
|
import type { ShallowRef } from "vue";
|
|
3
3
|
import type { Catalog, ComponentApi } from "@a2ui/web_core/v0_9";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
A2UI_SCHEMA_CONTEXT_DESCRIPTION,
|
|
6
|
+
buildCatalogContextValue as buildContextValue,
|
|
7
|
+
extractCatalogComponentSchemas,
|
|
8
|
+
} from "@copilotkit/a2ui-renderer/catalog-schema";
|
|
5
9
|
import {
|
|
6
10
|
A2UI_DEFAULT_GENERATION_GUIDELINES,
|
|
7
11
|
A2UI_DEFAULT_DESIGN_GUIDELINES,
|
|
@@ -9,22 +13,9 @@ import {
|
|
|
9
13
|
import type { CopilotKitCoreVue } from "../../lib/vue-core";
|
|
10
14
|
import { vueBasicCatalog } from "./catalog";
|
|
11
15
|
|
|
12
|
-
/**
|
|
13
|
-
* Context description used to identify the A2UI component schema in
|
|
14
|
-
* RunAgentInput.context. Must match the constant in @ag-ui/a2ui-middleware
|
|
15
|
-
* so the middleware can overwrite a frontend-provided schema with a
|
|
16
|
-
* server-side one.
|
|
17
|
-
*
|
|
18
|
-
* Duplicated from @copilotkit/a2ui-renderer/catalog-utils to avoid pulling
|
|
19
|
-
* in React dependencies.
|
|
20
|
-
*/
|
|
21
|
-
const A2UI_SCHEMA_CONTEXT_DESCRIPTION =
|
|
22
|
-
"A2UI Component Schema — available components for generating UI surfaces. " +
|
|
23
|
-
"Use these component names and properties when creating A2UI operations.";
|
|
24
|
-
|
|
25
16
|
/**
|
|
26
17
|
* Build a context string describing the available A2UI catalog.
|
|
27
|
-
*
|
|
18
|
+
* Defaults to the Vue basic catalog.
|
|
28
19
|
*
|
|
29
20
|
* When `options.includeSchema` is `false`, custom components are listed by name
|
|
30
21
|
* only and their JSON schemas are omitted.
|
|
@@ -33,92 +24,7 @@ export function buildCatalogContextValue(
|
|
|
33
24
|
catalog?: Catalog<ComponentApi>,
|
|
34
25
|
options?: { includeSchema?: boolean },
|
|
35
26
|
): string {
|
|
36
|
-
|
|
37
|
-
const BASIC_CATALOG_ID =
|
|
38
|
-
"https://a2ui.org/specification/v0_9/basic_catalog.json";
|
|
39
|
-
const lines: string[] = [];
|
|
40
|
-
lines.push("Available A2UI catalog:");
|
|
41
|
-
|
|
42
|
-
if (resolved.id === BASIC_CATALOG_ID) {
|
|
43
|
-
lines.push(`- ${resolved.id} (basic catalog)`);
|
|
44
|
-
return lines.join("\n");
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Check if the resolved catalog extends the basic catalog
|
|
48
|
-
let isSuperset = true;
|
|
49
|
-
for (const name of vueBasicCatalog.components.keys()) {
|
|
50
|
-
if (!resolved.components.has(name)) {
|
|
51
|
-
isSuperset = false;
|
|
52
|
-
break;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Identify custom components (not in basic catalog)
|
|
57
|
-
const customNames: string[] = [];
|
|
58
|
-
for (const name of resolved.components.keys()) {
|
|
59
|
-
if (!vueBasicCatalog.components.has(name)) {
|
|
60
|
-
customNames.push(name);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
lines.push(`- ${resolved.id}`);
|
|
65
|
-
if (isSuperset) {
|
|
66
|
-
lines.push(
|
|
67
|
-
" Extends the basic catalog with all standard components plus:",
|
|
68
|
-
);
|
|
69
|
-
} else {
|
|
70
|
-
lines.push(" Custom catalog (does NOT include all basic components).");
|
|
71
|
-
lines.push(" Custom components:");
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
for (const name of customNames) {
|
|
75
|
-
const comp = resolved.components.get(name);
|
|
76
|
-
if (!comp) continue;
|
|
77
|
-
if (options?.includeSchema === false) {
|
|
78
|
-
lines.push(` - ${name}`);
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
const jsonSchema = zodToJsonSchema(comp.schema);
|
|
82
|
-
lines.push(` - ${name}:`);
|
|
83
|
-
lines.push(
|
|
84
|
-
` ${JSON.stringify(jsonSchema, null, 2).split("\n").join("\n ")}`,
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return lines.join("\n");
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Extract component schemas from a catalog in A2UI v0.9 inline format.
|
|
93
|
-
* Vue-native equivalent of extractCatalogComponentSchemas.
|
|
94
|
-
*/
|
|
95
|
-
function extractCatalogComponentSchemas(catalog?: Catalog<ComponentApi>): {
|
|
96
|
-
catalogId: string;
|
|
97
|
-
components: Record<string, Record<string, unknown>>;
|
|
98
|
-
} {
|
|
99
|
-
const resolved = catalog ?? vueBasicCatalog;
|
|
100
|
-
const components: Record<string, Record<string, unknown>> = {};
|
|
101
|
-
|
|
102
|
-
for (const [name, comp] of resolved.components) {
|
|
103
|
-
const zodSchema = zodToJsonSchema(comp.schema, {
|
|
104
|
-
target: "jsonSchema2019-09",
|
|
105
|
-
}) as { properties?: Record<string, unknown>; required?: string[] };
|
|
106
|
-
|
|
107
|
-
components[name] = {
|
|
108
|
-
allOf: [
|
|
109
|
-
{ $ref: "common_types.json#/$defs/ComponentCommon" },
|
|
110
|
-
{
|
|
111
|
-
properties: {
|
|
112
|
-
component: { const: name },
|
|
113
|
-
...zodSchema.properties,
|
|
114
|
-
},
|
|
115
|
-
required: ["component", ...(zodSchema.required ?? [])],
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return { catalogId: resolved.id, components };
|
|
27
|
+
return buildContextValue(catalog ?? vueBasicCatalog, options);
|
|
122
28
|
}
|
|
123
29
|
|
|
124
30
|
/**
|
|
@@ -165,7 +71,9 @@ export function registerA2UICatalogContext(
|
|
|
165
71
|
// Register schema + generation/design guidelines
|
|
166
72
|
const schemaValue = computed(() => {
|
|
167
73
|
if (!options.includeSchema()) return null;
|
|
168
|
-
return JSON.stringify(
|
|
74
|
+
return JSON.stringify(
|
|
75
|
+
extractCatalogComponentSchemas(options.catalog() ?? vueBasicCatalog),
|
|
76
|
+
);
|
|
169
77
|
});
|
|
170
78
|
|
|
171
79
|
watch(
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from "@testing-library/vue";
|
|
8
8
|
import { defineComponent, ref, toRaw } from "vue";
|
|
9
9
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
10
|
+
import type * as CoreModule from "@copilotkit/core";
|
|
10
11
|
import type { AbstractAgent } from "@ag-ui/client";
|
|
11
12
|
import { EventType } from "@ag-ui/client";
|
|
12
13
|
import type { A2UITheme as Theme } from "../../../types";
|
|
@@ -160,11 +161,25 @@ vi.mock("phoenix", () => ({
|
|
|
160
161
|
Socket: MockPhoenixSocket,
|
|
161
162
|
}));
|
|
162
163
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
// Run the real core controller against a fake websandbox
|
|
165
|
+
vi.mock("@copilotkit/core", async (importOriginal) => {
|
|
166
|
+
const actual = await importOriginal<typeof CoreModule>();
|
|
167
|
+
class TestOpenGenerativeUIController
|
|
168
|
+
extends actual.ɵOpenGenerativeUIController
|
|
169
|
+
{
|
|
170
|
+
constructor() {
|
|
171
|
+
super({
|
|
172
|
+
loadWebsandbox: async () => ({
|
|
173
|
+
create: (...args) => mockWebsandboxCreate(...args),
|
|
174
|
+
}),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
...actual,
|
|
180
|
+
ɵOpenGenerativeUIController: TestOpenGenerativeUIController,
|
|
181
|
+
};
|
|
182
|
+
});
|
|
168
183
|
|
|
169
184
|
function jsonResponse(body: unknown, status = 200): Response {
|
|
170
185
|
return {
|
|
@@ -667,13 +682,15 @@ describe("CopilotChat activity message rendering", () => {
|
|
|
667
682
|
|
|
668
683
|
renderOpenGenerativeUIChat();
|
|
669
684
|
|
|
685
|
+
// The restored chat can remount the activity while it reconnects, so wait
|
|
686
|
+
// until exactly one sandbox, the restored one, is alive.
|
|
670
687
|
await waitFor(() => {
|
|
671
|
-
|
|
688
|
+
const created = mockWebsandboxCreate.mock.calls.length;
|
|
689
|
+
expect(created).toBeGreaterThanOrEqual(2);
|
|
690
|
+
expect(mockWebsandboxDestroy).toHaveBeenCalledTimes(created - 1);
|
|
672
691
|
});
|
|
673
|
-
expect(mockWebsandboxCreate.mock.calls
|
|
692
|
+
expect(mockWebsandboxCreate.mock.calls.at(-1)?.[1]).toMatchObject({
|
|
674
693
|
frameContent: restoredHtml,
|
|
675
694
|
});
|
|
676
|
-
|
|
677
|
-
expect(mockWebsandboxDestroy).toHaveBeenCalledTimes(1);
|
|
678
695
|
});
|
|
679
696
|
});
|
|
@@ -134,7 +134,7 @@ describe("useRenderTool Zod regression", () => {
|
|
|
134
134
|
const schema = z.object({
|
|
135
135
|
action: z.discriminatedUnion("type", [
|
|
136
136
|
z.object({ type: z.literal("search"), query: z.string() }),
|
|
137
|
-
z.object({ type: z.literal("navigate"), url: z.
|
|
137
|
+
z.object({ type: z.literal("navigate"), url: z.url() }),
|
|
138
138
|
]),
|
|
139
139
|
});
|
|
140
140
|
|
|
@@ -1,21 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
let result = html;
|
|
8
|
-
|
|
9
|
-
result = result.replace(/<[^>]*$/, "");
|
|
10
|
-
result = result.replace(/<(style|script|head)\b[^>]*>[\s\S]*?<\/\1>/gi, "");
|
|
11
|
-
result = result.replace(/<(style|script|head)\b[^>]*>[\s\S]*$/gi, "");
|
|
12
|
-
result = result.replace(/&[a-zA-Z0-9#]*$/, "");
|
|
13
|
-
|
|
14
|
-
const bodyMatch = result.match(/<body[^>]*>([\s\S]*)/i);
|
|
15
|
-
if (bodyMatch) {
|
|
16
|
-
result = bodyMatch[1]!;
|
|
17
|
-
result = result.replace(/<\/body>[\s\S]*/i, "");
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return result;
|
|
21
|
-
}
|
|
1
|
+
// The partial-HTML helpers live in @copilotkit/core; these names stay for
|
|
2
|
+
// existing imports.
|
|
3
|
+
export {
|
|
4
|
+
ɵextractCompleteStyles as extractCompleteStyles,
|
|
5
|
+
ɵprocessPartialHtml as processPartialHtml,
|
|
6
|
+
} from "@copilotkit/core";
|
|
@@ -12,11 +12,11 @@ import {
|
|
|
12
12
|
provide,
|
|
13
13
|
ref,
|
|
14
14
|
shallowRef,
|
|
15
|
+
toRaw,
|
|
15
16
|
triggerRef,
|
|
16
17
|
watch,
|
|
17
18
|
} from "vue";
|
|
18
19
|
import type { Component, FunctionalComponent } from "vue";
|
|
19
|
-
import type { z } from "zod";
|
|
20
20
|
import type { AbstractAgent } from "@ag-ui/client";
|
|
21
21
|
import { ToolCallStatus } from "@copilotkit/core";
|
|
22
22
|
import type {
|
|
@@ -25,13 +25,17 @@ import type {
|
|
|
25
25
|
CopilotKitHeadersSource,
|
|
26
26
|
FrontendTool,
|
|
27
27
|
} from "@copilotkit/core";
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
DEFAULT_OPEN_GENERATIVE_UI_DESIGN_SKILL,
|
|
30
|
+
GENERATE_SANDBOXED_UI_TOOL_NAME,
|
|
31
|
+
ɵresolveLicenseState,
|
|
32
|
+
ɵwithHeaderDefaults,
|
|
33
|
+
} from "@copilotkit/core";
|
|
29
34
|
import { schemaToJsonSchema, shouldEnableInspector } from "@copilotkit/shared";
|
|
30
35
|
import type {
|
|
31
36
|
RuntimeEntitlementResponse,
|
|
32
37
|
RuntimeLicenseStatus,
|
|
33
38
|
} from "@copilotkit/shared";
|
|
34
|
-
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
35
39
|
import { CopilotKitCoreVue } from "../lib/vue-core";
|
|
36
40
|
import { createA2UIMessageRenderer } from "../components/A2UIMessageRenderer";
|
|
37
41
|
import { registerA2UIBuiltInToolCallRenderer } from "../components/a2ui/A2UIBuiltInToolCallRenderer";
|
|
@@ -91,16 +95,6 @@ const SANDBOX_FUNCTIONS_STABLE_WARNING =
|
|
|
91
95
|
// interrupt reads the same across frameworks (see #5554).
|
|
92
96
|
const HUMAN_IN_THE_LOOP_ABORTED_MESSAGE =
|
|
93
97
|
"Human-in-the-loop interaction aborted";
|
|
94
|
-
const DEFAULT_DESIGN_SKILL = `When generating UI with generateSandboxedUi, follow these design principles inspired by shadcn/ui:
|
|
95
|
-
|
|
96
|
-
- Use a minimal, flat aesthetic. Avoid drop shadows and gradients — rely on subtle borders (1px solid, light gray like #e5e7eb) to define surfaces.
|
|
97
|
-
- Neutral base palette: white backgrounds, zinc/slate gray text (#09090b for headings, #71717a for secondary text). One accent color for interactive elements.
|
|
98
|
-
- Use system font stacks (system-ui, -apple-system, sans-serif) at readable sizes (14px body, 600 weight for headings). Tight line-heights.
|
|
99
|
-
- Small, consistent border-radius (6–8px). Cards and containers use border, not shadow, for separation.
|
|
100
|
-
- Buttons: solid fill for primary (dark bg, white text), outline for secondary (border + transparent bg). Subtle hover state (slight opacity or background shift).
|
|
101
|
-
- Use CSS Grid or Flexbox for layout. Ensure the UI looks good at any width.
|
|
102
|
-
- Minimal transitions (150ms) for hover/focus states only. No decorative animations.
|
|
103
|
-
- Keep the UI focused and dense — avoid excessive padding. Use compact spacing (8–12px gaps, 10–14px padding in controls).`;
|
|
104
98
|
|
|
105
99
|
/** The MCP Apps renderer with `mcpApps.allowSameOriginFallback` applied. */
|
|
106
100
|
const SameOriginMCPAppsActivityRenderer: FunctionalComponent = (_, { attrs }) =>
|
|
@@ -165,6 +159,12 @@ const initialRenderCustomMessages = props.renderCustomMessages;
|
|
|
165
159
|
const initialRenderActivityMessages = props.renderActivityMessages;
|
|
166
160
|
const initialSandboxFunctions = props.openGenerativeUI?.sandboxFunctions;
|
|
167
161
|
|
|
162
|
+
// Props that come from reactive state arrive as deep proxies. Zod 4 schemas
|
|
163
|
+
// break behind a Vue proxy (their `_zod` property is read-only and
|
|
164
|
+
// non-configurable), so read tools and renderers through their raw objects.
|
|
165
|
+
const rawEntries = <T>(entries: readonly T[] | undefined): T[] =>
|
|
166
|
+
[...toRaw(entries ?? [])].map((entry) => toRaw(entry));
|
|
167
|
+
|
|
168
168
|
watch(
|
|
169
169
|
() => props.frontendTools,
|
|
170
170
|
(next) => {
|
|
@@ -297,7 +297,7 @@ const processedHumanInTheLoop = computed(() => {
|
|
|
297
297
|
const tools: FrontendTool[] = [];
|
|
298
298
|
const renderToolCalls: VueToolCallRenderer<unknown>[] = [];
|
|
299
299
|
|
|
300
|
-
for (const tool of props.humanInTheLoop) {
|
|
300
|
+
for (const tool of rawEntries(props.humanInTheLoop)) {
|
|
301
301
|
tools.push({
|
|
302
302
|
type: "human-in-the-loop",
|
|
303
303
|
name: tool.name,
|
|
@@ -374,7 +374,7 @@ const processedHumanInTheLoop = computed(() => {
|
|
|
374
374
|
|
|
375
375
|
const allTools = computed(() => {
|
|
376
376
|
const tools: FrontendTool[] = [];
|
|
377
|
-
for (const t of props.frontendTools) {
|
|
377
|
+
for (const t of rawEntries(props.frontendTools)) {
|
|
378
378
|
tools.push(t as FrontendTool);
|
|
379
379
|
}
|
|
380
380
|
for (const t of builtInFrontendTools.value) {
|
|
@@ -386,9 +386,12 @@ const allTools = computed(() => {
|
|
|
386
386
|
|
|
387
387
|
const allRenderToolCalls = computed(() => {
|
|
388
388
|
const combined: VueToolCallRenderer<unknown>[] = [
|
|
389
|
-
...(props.renderToolCalls
|
|
389
|
+
...rawEntries(props.renderToolCalls),
|
|
390
390
|
];
|
|
391
|
-
for (const tool of [
|
|
391
|
+
for (const tool of [
|
|
392
|
+
...rawEntries(props.frontendTools),
|
|
393
|
+
...builtInFrontendTools.value,
|
|
394
|
+
]) {
|
|
392
395
|
if (tool.render) {
|
|
393
396
|
const args =
|
|
394
397
|
tool.parameters ?? (tool.name === "*" ? ɵanySchema : undefined);
|
|
@@ -433,23 +436,14 @@ const resolvedProperties = computed(() =>
|
|
|
433
436
|
? { ...props.properties, a2uiCatalogAvailable: true }
|
|
434
437
|
: props.properties,
|
|
435
438
|
);
|
|
436
|
-
const sandboxFunctions = computed<readonly SandboxFunction[]>(
|
|
437
|
-
(
|
|
439
|
+
const sandboxFunctions = computed<readonly SandboxFunction[]>(() =>
|
|
440
|
+
rawEntries(props.openGenerativeUI?.sandboxFunctions),
|
|
438
441
|
);
|
|
439
|
-
const zodToJsonSchemaCompat = (
|
|
440
|
-
schema: unknown,
|
|
441
|
-
options?: { $refStrategy?: string },
|
|
442
|
-
): Record<string, unknown> =>
|
|
443
|
-
zodToJsonSchema(
|
|
444
|
-
schema as z.ZodTypeAny,
|
|
445
|
-
options as { $refStrategy?: "none" | "relative" | "root" | "seen" },
|
|
446
|
-
) as Record<string, unknown>;
|
|
447
|
-
|
|
448
442
|
const builtInFrontendTools = computed<VueFrontendTool[]>(() => {
|
|
449
443
|
if (!openGenerativeUIActive.value) return [];
|
|
450
444
|
return [
|
|
451
445
|
{
|
|
452
|
-
name:
|
|
446
|
+
name: GENERATE_SANDBOXED_UI_TOOL_NAME,
|
|
453
447
|
description: GENERATE_SANDBOXED_UI_DESCRIPTION,
|
|
454
448
|
parameters: GenerateSandboxedUiArgsSchema,
|
|
455
449
|
handler: async () => "UI generated",
|
|
@@ -499,7 +493,7 @@ const builtInActivityRenderers = computed<
|
|
|
499
493
|
});
|
|
500
494
|
|
|
501
495
|
const allRenderActivityMessages = computed(() => [
|
|
502
|
-
...(props.renderActivityMessages
|
|
496
|
+
...rawEntries(props.renderActivityMessages),
|
|
503
497
|
...builtInActivityRenderers.value,
|
|
504
498
|
]);
|
|
505
499
|
|
|
@@ -849,7 +843,7 @@ watch(
|
|
|
849
843
|
copilotkit.value.addContext({
|
|
850
844
|
description:
|
|
851
845
|
"Design guidelines for the generateSandboxedUi tool. Follow these when building UI.",
|
|
852
|
-
value: designSkill ??
|
|
846
|
+
value: designSkill ?? DEFAULT_OPEN_GENERATIVE_UI_DESIGN_SKILL,
|
|
853
847
|
}),
|
|
854
848
|
);
|
|
855
849
|
|
|
@@ -858,9 +852,7 @@ watch(
|
|
|
858
852
|
functions.map((fn) => ({
|
|
859
853
|
name: fn.name,
|
|
860
854
|
description: fn.description,
|
|
861
|
-
parameters: schemaToJsonSchema(fn.parameters,
|
|
862
|
-
zodToJsonSchema: zodToJsonSchemaCompat,
|
|
863
|
-
}),
|
|
855
|
+
parameters: schemaToJsonSchema(fn.parameters),
|
|
864
856
|
})),
|
|
865
857
|
);
|
|
866
858
|
ids.push(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
import { defineComponent, h, ref } from "vue";
|
|
3
3
|
import { mount } from "@vue/test-utils";
|
|
4
|
-
import { z } from "zod";
|
|
4
|
+
import { z } from "zod-v3";
|
|
5
5
|
import { Catalog } from "@a2ui/web_core/v0_9";
|
|
6
6
|
import type { ComponentApi } from "@a2ui/web_core/v0_9";
|
|
7
7
|
import CopilotKitProvider from "../CopilotKitProvider.vue";
|
package/vite.config.ts
CHANGED
|
@@ -28,6 +28,8 @@ export default defineConfig({
|
|
|
28
28
|
"@a2ui/web_core/v0_9/basic_catalog",
|
|
29
29
|
"@ag-ui/client",
|
|
30
30
|
"@ag-ui/core",
|
|
31
|
+
// The framework-neutral A2UI catalog description subpath (no React).
|
|
32
|
+
"@copilotkit/a2ui-renderer/catalog-schema",
|
|
31
33
|
// Core and its `/styles` subpath, so the stylesheet isn't bundled here.
|
|
32
34
|
/^@copilotkit\/core(\/.*)?$/,
|
|
33
35
|
// Keep the shared MCP Apps host + its subpaths external. The root entry
|
|
@@ -46,9 +48,7 @@ export default defineConfig({
|
|
|
46
48
|
// (duplicate top-level lit binding → "Identifier 'h' has already been
|
|
47
49
|
// declared") and risks double custom-element registration.
|
|
48
50
|
/^@copilotkit\/web-components(\/.*)?$/,
|
|
49
|
-
"@jetbrains/websandbox",
|
|
50
51
|
"zod",
|
|
51
|
-
"zod-to-json-schema",
|
|
52
52
|
],
|
|
53
53
|
output: {
|
|
54
54
|
globals: { vue: "Vue" },
|