@assistant-ui/next 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/SPEC.md +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -3
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +1 -1
- package/dist/loader.js.map +1 -1
- package/package.json +3 -12
- package/src/index.ts +0 -2
- package/src/loader.ts +5 -2
- package/dist/compile.d.ts +0 -30
- package/dist/compile.d.ts.map +0 -1
- package/dist/compile.js +0 -235
- package/dist/compile.js.map +0 -1
- package/dist/constants.d.ts +0 -8
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -7
- package/dist/constants.js.map +0 -1
- package/dist/define-toolkit.d.ts +0 -19
- package/dist/define-toolkit.d.ts.map +0 -1
- package/dist/define-toolkit.js +0 -20
- package/dist/define-toolkit.js.map +0 -1
- package/dist/hitl.d.ts +0 -18
- package/dist/hitl.d.ts.map +0 -1
- package/dist/hitl.js +0 -21
- package/dist/hitl.js.map +0 -1
- package/src/compile.test.ts +0 -267
- package/src/compile.ts +0 -472
- package/src/constants.ts +0 -5
- package/src/define-toolkit.test.ts +0 -8
- package/src/define-toolkit.ts +0 -22
- package/src/hitl.ts +0 -21
package/src/compile.test.ts
DELETED
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
compileGenerative,
|
|
4
|
-
isGenerativeModule,
|
|
5
|
-
GenerativeCompileError,
|
|
6
|
-
} from "./compile";
|
|
7
|
-
|
|
8
|
-
const source = `"use generative";
|
|
9
|
-
import { z } from "zod";
|
|
10
|
-
import { db } from "@/db";
|
|
11
|
-
import { track } from "@/analytics";
|
|
12
|
-
import { Chart } from "@/ui/chart";
|
|
13
|
-
import { defineToolkit } from "@assistant-ui/next";
|
|
14
|
-
|
|
15
|
-
export default defineToolkit({
|
|
16
|
-
weather: {
|
|
17
|
-
description: "Show the weather.",
|
|
18
|
-
parameters: z.object({ city: z.string() }),
|
|
19
|
-
execute: async ({ city }) => db.weather.get(city),
|
|
20
|
-
render: (props) => <Chart data={props} />,
|
|
21
|
-
},
|
|
22
|
-
toast: {
|
|
23
|
-
description: "Show a toast.",
|
|
24
|
-
parameters: z.object({ msg: z.string() }),
|
|
25
|
-
execute: async ({ msg }) => {
|
|
26
|
-
"use client";
|
|
27
|
-
return track(msg);
|
|
28
|
-
},
|
|
29
|
-
render: (props) => <div>{props.msg}</div>,
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
`;
|
|
33
|
-
|
|
34
|
-
const server = () => compileGenerative(source, { target: "server" }).code;
|
|
35
|
-
const client = () => compileGenerative(source, { target: "client" }).code;
|
|
36
|
-
|
|
37
|
-
describe("compileGenerative — server target", () => {
|
|
38
|
-
const code = server();
|
|
39
|
-
|
|
40
|
-
it("keeps the schema", () => {
|
|
41
|
-
expect(code).toContain('import { z } from "zod"');
|
|
42
|
-
expect(code).toContain("z.object");
|
|
43
|
-
expect(code).toContain('description: "Show the weather."');
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("keeps a backend execute and guards it with server-only", () => {
|
|
47
|
-
expect(code).toContain('import "server-only"');
|
|
48
|
-
expect(code).toContain("db.weather.get");
|
|
49
|
-
expect(code).toContain('import { db } from "@/db"');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("writes the inferred type back onto each tool", () => {
|
|
53
|
-
expect(code).toContain('type: "backend"'); // weather: execute, no "use client"
|
|
54
|
-
expect(code).toContain('type: "frontend"'); // toast: execute + "use client"
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("drops all render and its client imports", () => {
|
|
58
|
-
expect(code).not.toContain("Chart");
|
|
59
|
-
expect(code).not.toContain("<div");
|
|
60
|
-
expect(code).not.toMatch(/render\s*:/);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("drops a frontend execute and its client imports", () => {
|
|
64
|
-
expect(code).not.toContain("track");
|
|
65
|
-
expect(code).not.toContain("@/analytics");
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it("strips the use generative directive and adds no use client", () => {
|
|
69
|
-
expect(code).not.toContain("use generative");
|
|
70
|
-
expect(code).not.toContain("use client");
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
describe("compileGenerative — client target", () => {
|
|
75
|
-
const code = client();
|
|
76
|
-
|
|
77
|
-
it("marks the module use client and keeps render", () => {
|
|
78
|
-
expect(code.trimStart().startsWith('"use client"')).toBe(true);
|
|
79
|
-
expect(code).toContain("<Chart");
|
|
80
|
-
expect(code).toContain("<div");
|
|
81
|
-
expect(code).toContain('import { Chart } from "@/ui/chart"');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("keeps the schema for parsing", () => {
|
|
85
|
-
expect(code).toContain('import { z } from "zod"');
|
|
86
|
-
expect(code).toContain("z.object");
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("keeps a frontend execute (and drops its `use client` marker)", () => {
|
|
90
|
-
expect(code).toContain("track(msg)");
|
|
91
|
-
expect(code).toContain("@/analytics");
|
|
92
|
-
// exactly one "use client" — the module directive, not the execute body's
|
|
93
|
-
expect(code.match(/use client/g)?.length).toBe(1);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it("writes the inferred type back onto each tool", () => {
|
|
97
|
-
expect(code).toContain('type: "backend"'); // weather (schema-only on client)
|
|
98
|
-
expect(code).toContain('type: "frontend"'); // toast
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it("drops a backend execute and its server-only imports", () => {
|
|
102
|
-
expect(code).not.toContain("db.weather.get");
|
|
103
|
-
expect(code).not.toContain("@/db");
|
|
104
|
-
expect(code).not.toContain("server-only");
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
describe("compileGenerative — local dead-code elimination", () => {
|
|
109
|
-
const withHelpers = `"use generative";
|
|
110
|
-
import { z } from "zod";
|
|
111
|
-
import { cn } from "@/lib/utils";
|
|
112
|
-
import { db } from "@/db";
|
|
113
|
-
|
|
114
|
-
const Badge = ({ label }) => <span className={cn("badge")}>{label}</span>;
|
|
115
|
-
import { defineToolkit } from "@assistant-ui/next";
|
|
116
|
-
|
|
117
|
-
export default defineToolkit({
|
|
118
|
-
weather: {
|
|
119
|
-
description: "weather",
|
|
120
|
-
parameters: z.object({ city: z.string() }),
|
|
121
|
-
execute: async ({ city }) => db.weather.get(city),
|
|
122
|
-
render: (props) => <Badge label={props.city} />,
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
`;
|
|
126
|
-
|
|
127
|
-
it("strips a local helper component (and its imports) from the server", () => {
|
|
128
|
-
const code = compileGenerative(withHelpers, { target: "server" }).code;
|
|
129
|
-
expect(code).not.toContain("Badge");
|
|
130
|
-
expect(code).not.toContain("@/lib/utils");
|
|
131
|
-
expect(code).not.toContain("className");
|
|
132
|
-
expect(code).toContain("db.weather.get");
|
|
133
|
-
expect(code).toContain('import "server-only"');
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it("keeps the local helper on the client", () => {
|
|
137
|
-
const code = compileGenerative(withHelpers, { target: "client" }).code;
|
|
138
|
-
expect(code).toContain("Badge");
|
|
139
|
-
expect(code).toContain("@/lib/utils");
|
|
140
|
-
expect(code).not.toContain("@/db");
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("prunes an unused destructured server binding from the client", () => {
|
|
144
|
-
const src = `"use generative";
|
|
145
|
-
import { defineToolkit } from "@assistant-ui/next";
|
|
146
|
-
import { db } from "@/db";
|
|
147
|
-
const { getWeather } = db;
|
|
148
|
-
export default defineToolkit({
|
|
149
|
-
weather: {
|
|
150
|
-
execute: async ({ city }) => getWeather(city),
|
|
151
|
-
render: () => null,
|
|
152
|
-
},
|
|
153
|
-
});`;
|
|
154
|
-
const client = compileGenerative(src, { target: "client" }).code;
|
|
155
|
-
expect(client).not.toContain("getWeather");
|
|
156
|
-
expect(client).not.toContain("@/db");
|
|
157
|
-
expect(compileGenerative(src, { target: "server" }).code).toContain(
|
|
158
|
-
"getWeather",
|
|
159
|
-
);
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
describe("compileGenerative — diagnostics", () => {
|
|
164
|
-
it("rejects a module without the directive", () => {
|
|
165
|
-
expect(() =>
|
|
166
|
-
compileGenerative(`export default {} satisfies Toolkit;`, {
|
|
167
|
-
target: "server",
|
|
168
|
-
}),
|
|
169
|
-
).toThrow(GenerativeCompileError);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it("strips a define-style wrapper and prunes its import", () => {
|
|
173
|
-
const wrapped = `"use generative";
|
|
174
|
-
import { z } from "zod";
|
|
175
|
-
import { db } from "@/db";
|
|
176
|
-
import { defineToolkit } from "@assistant-ui/next";
|
|
177
|
-
export default defineToolkit({
|
|
178
|
-
weather: {
|
|
179
|
-
parameters: z.object({ city: z.string() }),
|
|
180
|
-
execute: async ({ city }) => db.get(city),
|
|
181
|
-
render: (props) => <span>{props.city}</span>,
|
|
182
|
-
},
|
|
183
|
-
});`;
|
|
184
|
-
const serverCode = compileGenerative(wrapped, { target: "server" }).code;
|
|
185
|
-
// wrapper + its import gone; bare object with execute remains.
|
|
186
|
-
expect(serverCode).not.toContain("defineToolkit");
|
|
187
|
-
expect(serverCode).not.toContain("@assistant-ui/next");
|
|
188
|
-
expect(serverCode).toContain("db.get");
|
|
189
|
-
expect(serverCode).not.toContain("<span");
|
|
190
|
-
|
|
191
|
-
const clientCode = compileGenerative(wrapped, { target: "client" }).code;
|
|
192
|
-
expect(clientCode).not.toContain("defineToolkit");
|
|
193
|
-
expect(clientCode).not.toContain("@assistant-ui/next");
|
|
194
|
-
expect(clientCode).toContain("<span");
|
|
195
|
-
expect(clientCode).not.toContain("@/db");
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it("requires the defineToolkit() wrapper", () => {
|
|
199
|
-
expect(() =>
|
|
200
|
-
compileGenerative(
|
|
201
|
-
`"use generative";\nexport default { a: { execute: async () => 1 } };`,
|
|
202
|
-
{ target: "server" },
|
|
203
|
-
),
|
|
204
|
-
).toThrow(/defineToolkit/);
|
|
205
|
-
expect(() =>
|
|
206
|
-
compileGenerative(`"use generative";\nexport default makeToolkit();`, {
|
|
207
|
-
target: "server",
|
|
208
|
-
}),
|
|
209
|
-
).toThrow(/defineToolkit/);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it("rejects a tool that isn't an inline object literal", () => {
|
|
213
|
-
expect(() =>
|
|
214
|
-
compileGenerative(
|
|
215
|
-
`"use generative";\nimport { defineToolkit } from "@assistant-ui/next";\nexport default defineToolkit({ weather: makeTool() });`,
|
|
216
|
-
{ target: "server" },
|
|
217
|
-
),
|
|
218
|
-
).toThrow(/inline object literal/);
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
it("requires a render for human/frontend tools", () => {
|
|
222
|
-
expect(() =>
|
|
223
|
-
compileGenerative(
|
|
224
|
-
`"use generative";\nimport { defineToolkit, hitl } from "@assistant-ui/next";\nexport default defineToolkit({ ask: { execute: hitl() } });`,
|
|
225
|
-
{ target: "client" },
|
|
226
|
-
),
|
|
227
|
-
).toThrow(/must declare a `render`/);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it("requires every tool to declare an execute", () => {
|
|
231
|
-
expect(() =>
|
|
232
|
-
compileGenerative(
|
|
233
|
-
`"use generative";\nimport { defineToolkit } from "@assistant-ui/next";\nexport default defineToolkit({ ask: { render: () => null } });`,
|
|
234
|
-
{ target: "client" },
|
|
235
|
-
),
|
|
236
|
-
).toThrow(/must declare an `execute`/);
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
it("infers `human` from execute: hitl() and drops it on both builds", () => {
|
|
240
|
-
const src = `"use generative";\nimport { defineToolkit, hitl } from "@assistant-ui/next";\nexport default defineToolkit({ ask: { execute: hitl(), render: () => null } });`;
|
|
241
|
-
const server = compileGenerative(src, { target: "server" }).code;
|
|
242
|
-
expect(server).toContain('type: "human"');
|
|
243
|
-
expect(server).not.toContain("hitl"); // sentinel + its import pruned
|
|
244
|
-
const client = compileGenerative(src, { target: "client" }).code;
|
|
245
|
-
expect(client).toContain('type: "human"');
|
|
246
|
-
expect(client).not.toContain("hitl");
|
|
247
|
-
expect(client).toContain("render");
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it("infers `frontend` from a `use client` execute and keeps it client-side", () => {
|
|
251
|
-
const src = `"use generative";\nimport { defineToolkit } from "@assistant-ui/next";\nimport { track } from "@/a";\nexport default defineToolkit({ t: { execute: async () => { "use client"; return track(); }, render: () => null } });`;
|
|
252
|
-
const server = compileGenerative(src, { target: "server" }).code;
|
|
253
|
-
expect(server).toContain('type: "frontend"');
|
|
254
|
-
expect(server).not.toContain("track"); // frontend execute dropped on server
|
|
255
|
-
const client = compileGenerative(src, { target: "client" }).code;
|
|
256
|
-
expect(client).toContain('type: "frontend"');
|
|
257
|
-
expect(client).toContain("track()");
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
it("detects generative modules by directive", () => {
|
|
261
|
-
expect(isGenerativeModule(`"use generative";\nexport default {};`)).toBe(
|
|
262
|
-
true,
|
|
263
|
-
);
|
|
264
|
-
expect(isGenerativeModule(`// a comment\n"use generative";\n`)).toBe(true);
|
|
265
|
-
expect(isGenerativeModule(`export default {};`)).toBe(false);
|
|
266
|
-
});
|
|
267
|
-
});
|