evalution 1.0.2 → 1.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/dist/cli/index.js +139 -126
- package/dist/client/assets/{index-CORbBplP.js → index-DR7qdRRh.js} +35 -35
- package/dist/client/index.html +1 -1
- package/dist/index.d.ts +83 -55
- package/dist/index.js +92 -126
- package/dist/{vercel-ai-sdk-CareWPDM.js → vercel-ai-sdk-B5BwUGKp.js} +128 -34
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as MemoryTraceProvider, i as setupStepCommand, r as CONFIG_FILE_RELATIVE_PATH, t as VercelAISDK } from "../vercel-ai-sdk-
|
|
1
|
+
import { a as MemoryTraceProvider, i as setupStepCommand, r as CONFIG_FILE_RELATIVE_PATH, t as VercelAISDK } from "../vercel-ai-sdk-B5BwUGKp.js";
|
|
2
2
|
import module from "node:module";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
@@ -74,123 +74,15 @@ var PromptRegistry = class {
|
|
|
74
74
|
}
|
|
75
75
|
};
|
|
76
76
|
//#endregion
|
|
77
|
-
//#region src/sdk/registry.ts
|
|
78
|
-
/**
|
|
79
|
-
* Every AI SDK offered in manual onboarding, in display order. This is the
|
|
80
|
-
* single source of truth for which SDKs exist and their task ids — adding one
|
|
81
|
-
* to onboarding means giving its adapter a static `setupTask` and listing it
|
|
82
|
-
* here.
|
|
83
|
-
*/
|
|
84
|
-
const AI_SDK_REGISTRY = [VercelAISDK];
|
|
85
|
-
/** Look up a {@link SetupTask} by its id, or `undefined` if none matches. */
|
|
86
|
-
function findSetupTask(taskId) {
|
|
87
|
-
for (const cls of AI_SDK_REGISTRY) if (cls.setupTask.id === taskId) return cls.setupTask;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Look up a step within a task by both ids, or `undefined` if either is
|
|
91
|
-
* unknown.
|
|
92
|
-
*/
|
|
93
|
-
function findSetupStep(taskId, stepId) {
|
|
94
|
-
return findSetupTask(taskId)?.steps.find((s) => s.id === stepId);
|
|
95
|
-
}
|
|
96
|
-
//#endregion
|
|
97
|
-
//#region src/server/setup-tasks.ts
|
|
98
|
-
/**
|
|
99
|
-
* Thrown when a requested task or step id does not exist in the registry. The
|
|
100
|
-
* route layer maps this to a 404, distinguishing it from execution failures.
|
|
101
|
-
*/
|
|
102
|
-
var SetupStepNotFoundError = class extends Error {
|
|
103
|
-
constructor(message) {
|
|
104
|
-
super(message);
|
|
105
|
-
this.name = "SetupStepNotFoundError";
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
/**
|
|
109
|
-
* Executes a single onboarding step, resolved from the server-side registry by
|
|
110
|
-
* `taskId`/`stepId`.
|
|
111
|
-
*
|
|
112
|
-
* The client only sends ids; the step definition (file contents, command, ...)
|
|
113
|
-
* comes entirely from {@link AI_SDK_REGISTRY}, so a request can never write
|
|
114
|
-
* arbitrary files or run arbitrary commands.
|
|
115
|
-
*
|
|
116
|
-
* @param rootPath - Absolute path to the project root.
|
|
117
|
-
* @param taskId - Id of the {@link SetupTask} to run a step from.
|
|
118
|
-
* @param stepId - Id of the step within that task.
|
|
119
|
-
* @throws {SetupStepNotFoundError} if the task or step id is unknown.
|
|
120
|
-
* @throws if the step kind is unsupported or execution fails (e.g. the config
|
|
121
|
-
* file already exists).
|
|
122
|
-
*/
|
|
123
|
-
async function executeSetupStep(rootPath, taskId, stepId) {
|
|
124
|
-
const step = findSetupStep(taskId, stepId);
|
|
125
|
-
if (!step) throw new SetupStepNotFoundError(`Unknown step '${stepId}' for task '${taskId}'`);
|
|
126
|
-
switch (step.kind) {
|
|
127
|
-
case "create_config": return { path: await writeConfigFile(rootPath, step) };
|
|
128
|
-
case "run_command":
|
|
129
|
-
case "install_package": throw new Error(`${step.kind} steps are not yet supported`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Returns the onboarding tasks with each step's runtime
|
|
134
|
-
* {@link SetupStepBase.completed | completion status} resolved against the
|
|
135
|
-
* project at `rootPath` (config file present, package installed).
|
|
136
|
-
*
|
|
137
|
-
* @param rootPath - Absolute path to the project root.
|
|
138
|
-
*/
|
|
139
|
-
function resolveSetupTasks(rootPath) {
|
|
140
|
-
return AI_SDK_REGISTRY.map((cls) => ({
|
|
141
|
-
...cls.setupTask,
|
|
142
|
-
steps: cls.setupTask.steps.map((step) => resolveStepStatus(rootPath, step))
|
|
143
|
-
}));
|
|
144
|
-
}
|
|
145
|
-
/** Adds the runtime `completed` flag to a single step where determinable. */
|
|
146
|
-
function resolveStepStatus(rootPath, step) {
|
|
147
|
-
switch (step.kind) {
|
|
148
|
-
case "install_package": return {
|
|
149
|
-
...step,
|
|
150
|
-
completed: isPackageInstalled(rootPath, step.package)
|
|
151
|
-
};
|
|
152
|
-
case "create_config": return {
|
|
153
|
-
...step,
|
|
154
|
-
completed: fs$1.existsSync(path.join(rootPath, step.path))
|
|
155
|
-
};
|
|
156
|
-
case "run_command": return step;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Whether `pkg` is installed for the project at `rootPath`, walking up the
|
|
161
|
-
* directory tree to honour hoisted/workspace `node_modules`.
|
|
162
|
-
*
|
|
163
|
-
* @param rootPath - Absolute path to start the search from.
|
|
164
|
-
* @param pkg - The npm package name to look for.
|
|
165
|
-
*/
|
|
166
|
-
function isPackageInstalled(rootPath, pkg) {
|
|
167
|
-
let dir = rootPath;
|
|
168
|
-
while (true) {
|
|
169
|
-
if (fs$1.existsSync(path.join(dir, "node_modules", pkg, "package.json"))) return true;
|
|
170
|
-
const parent = path.dirname(dir);
|
|
171
|
-
if (parent === dir) return false;
|
|
172
|
-
dir = parent;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Writes the config file for a `create_config` step, creating parent
|
|
177
|
-
* directories as needed. Refuses to clobber an existing file.
|
|
178
|
-
*/
|
|
179
|
-
async function writeConfigFile(rootPath, step) {
|
|
180
|
-
const filePath = path.join(rootPath, step.path);
|
|
181
|
-
try {
|
|
182
|
-
await fs.access(filePath);
|
|
183
|
-
throw new Error(`${step.path} already exists`);
|
|
184
|
-
} catch (err) {
|
|
185
|
-
if (err?.code !== "ENOENT") throw err;
|
|
186
|
-
}
|
|
187
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
188
|
-
await fs.writeFile(filePath, step.contents, "utf8");
|
|
189
|
-
return step.path;
|
|
190
|
-
}
|
|
191
|
-
//#endregion
|
|
192
77
|
//#region src/server/api-routes.ts
|
|
193
|
-
|
|
78
|
+
/** Decodes a URL-safe base64 prompt id produced by `encodePromptId`. Uses the
|
|
79
|
+
* Web `atob` (rather than Node's `Buffer`) so it works in browser/worker
|
|
80
|
+
* bundles too. */
|
|
81
|
+
function decodePromptId(encoded) {
|
|
82
|
+
const b64 = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
83
|
+
return atob(b64);
|
|
84
|
+
}
|
|
85
|
+
function setupRoutes({ app, promptProviders, traceProviders, promptRegistry, hotReloadSubscribers, rootPath, hasConfig, tracer, defaultTraceProviderId, setupTasks, executeDisabledMessage }) {
|
|
194
86
|
const resolveSpanPrompt = (span) => {
|
|
195
87
|
if (!span.prompt) return span;
|
|
196
88
|
const resolved = promptRegistry.resolve(span.prompt.id, span.prompt.providerId);
|
|
@@ -207,13 +99,14 @@ function setupRoutes({ app, promptProviders, traceProviders, promptRegistry, hot
|
|
|
207
99
|
rootPath,
|
|
208
100
|
configured: hasConfig
|
|
209
101
|
}));
|
|
210
|
-
app.get("/api/setup-tasks", (c) => c.json(
|
|
102
|
+
app.get("/api/setup-tasks", (c) => c.json(setupTasks ? setupTasks.resolve(rootPath) : []));
|
|
211
103
|
app.post("/api/setup-tasks/:taskId/steps/:stepId/execute", async (c) => {
|
|
104
|
+
if (!setupTasks) return c.json({ error: "Setup tasks are not available" }, 404);
|
|
212
105
|
const { taskId, stepId } = c.req.param();
|
|
213
106
|
try {
|
|
214
|
-
return c.json(await
|
|
107
|
+
return c.json(await setupTasks.executeStep(rootPath, taskId, stepId));
|
|
215
108
|
} catch (error) {
|
|
216
|
-
const status = error
|
|
109
|
+
const status = error?.name === "SetupStepNotFoundError" ? 404 : 400;
|
|
217
110
|
return c.json({ error: error.message }, status);
|
|
218
111
|
}
|
|
219
112
|
});
|
|
@@ -270,7 +163,7 @@ function setupRoutes({ app, promptProviders, traceProviders, promptRegistry, hot
|
|
|
270
163
|
const { providerId, id } = c.req.param();
|
|
271
164
|
const provider = promptProviders.get(providerId);
|
|
272
165
|
if (!provider) return c.json({ error: "Provider not found" }, 404);
|
|
273
|
-
const decodedId =
|
|
166
|
+
const decodedId = decodePromptId(id);
|
|
274
167
|
const prompt = await provider.getPrompt(decodedId);
|
|
275
168
|
if (!prompt) return c.json({ error: "Prompt not found" }, 404);
|
|
276
169
|
return c.json({
|
|
@@ -288,7 +181,7 @@ function setupRoutes({ app, promptProviders, traceProviders, promptRegistry, hot
|
|
|
288
181
|
const provider = promptProviders.get(providerId);
|
|
289
182
|
if (!provider) return c.json({ error: "Provider not found" }, 404);
|
|
290
183
|
if (!provider.renamePrompt) return c.json({ error: "This provider does not support renaming" }, 405);
|
|
291
|
-
const decodedId =
|
|
184
|
+
const decodedId = decodePromptId(id);
|
|
292
185
|
const updatedPrompt = await provider.renamePrompt(decodedId, newName);
|
|
293
186
|
return c.json({
|
|
294
187
|
...updatedPrompt,
|
|
@@ -304,7 +197,7 @@ function setupRoutes({ app, promptProviders, traceProviders, promptRegistry, hot
|
|
|
304
197
|
const provider = promptProviders.get(providerId);
|
|
305
198
|
if (!provider) return c.json({ error: "Provider not found" }, 404);
|
|
306
199
|
if (!provider.updatePromptProperties) return c.json({ error: "This provider does not support editing" }, 405);
|
|
307
|
-
const decodedId =
|
|
200
|
+
const decodedId = decodePromptId(id);
|
|
308
201
|
const updatedPrompt = await provider.updatePromptProperties(decodedId, await c.req.json());
|
|
309
202
|
return c.json({
|
|
310
203
|
...updatedPrompt,
|
|
@@ -316,16 +209,17 @@ function setupRoutes({ app, promptProviders, traceProviders, promptRegistry, hot
|
|
|
316
209
|
});
|
|
317
210
|
app.post("/api/prompts/:providerId/:id/execute", async (c) => {
|
|
318
211
|
try {
|
|
212
|
+
if (executeDisabledMessage) return c.json({ error: executeDisabledMessage }, 400);
|
|
319
213
|
const { providerId, id } = c.req.param();
|
|
320
214
|
const provider = promptProviders.get(providerId);
|
|
321
215
|
if (!provider) return c.json({ error: "Provider not found" }, 404);
|
|
322
|
-
const decodedId =
|
|
216
|
+
const decodedId = decodePromptId(id);
|
|
323
217
|
const { functionParams = [] } = await c.req.json().catch(() => ({}));
|
|
324
218
|
const prompt = await provider.getPrompt(decodedId);
|
|
325
219
|
if (!prompt) return c.json({ error: "Prompt not found" }, 404);
|
|
326
220
|
const response = tracer.startActiveSpan(prompt.name, (span) => {
|
|
327
221
|
const { traceId } = span.spanContext();
|
|
328
|
-
provider.execute(decodedId, functionParams
|
|
222
|
+
provider.execute(decodedId, functionParams).then(() => {
|
|
329
223
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
330
224
|
}, (err) => {
|
|
331
225
|
console.error("prompt execution failed:", err);
|
|
@@ -420,6 +314,121 @@ function setupRoutes({ app, promptProviders, traceProviders, promptRegistry, hot
|
|
|
420
314
|
}));
|
|
421
315
|
}
|
|
422
316
|
//#endregion
|
|
317
|
+
//#region src/sdk/registry.ts
|
|
318
|
+
/**
|
|
319
|
+
* Every AI SDK offered in manual onboarding, in display order. This is the
|
|
320
|
+
* single source of truth for which SDKs exist and their task ids — adding one
|
|
321
|
+
* to onboarding means giving its adapter a static `setupTask` and listing it
|
|
322
|
+
* here.
|
|
323
|
+
*/
|
|
324
|
+
const AI_SDK_REGISTRY = [VercelAISDK];
|
|
325
|
+
/** Look up a {@link SetupTask} by its id, or `undefined` if none matches. */
|
|
326
|
+
function findSetupTask(taskId) {
|
|
327
|
+
for (const cls of AI_SDK_REGISTRY) if (cls.setupTask.id === taskId) return cls.setupTask;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Look up a step within a task by both ids, or `undefined` if either is
|
|
331
|
+
* unknown.
|
|
332
|
+
*/
|
|
333
|
+
function findSetupStep(taskId, stepId) {
|
|
334
|
+
return findSetupTask(taskId)?.steps.find((s) => s.id === stepId);
|
|
335
|
+
}
|
|
336
|
+
//#endregion
|
|
337
|
+
//#region src/server/setup-tasks.ts
|
|
338
|
+
/**
|
|
339
|
+
* Thrown when a requested task or step id does not exist in the registry. The
|
|
340
|
+
* route layer maps this to a 404, distinguishing it from execution failures.
|
|
341
|
+
*/
|
|
342
|
+
var SetupStepNotFoundError = class extends Error {
|
|
343
|
+
constructor(message) {
|
|
344
|
+
super(message);
|
|
345
|
+
this.name = "SetupStepNotFoundError";
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
/**
|
|
349
|
+
* Executes a single onboarding step, resolved from the server-side registry by
|
|
350
|
+
* `taskId`/`stepId`.
|
|
351
|
+
*
|
|
352
|
+
* The client only sends ids; the step definition (file contents, command, ...)
|
|
353
|
+
* comes entirely from {@link AI_SDK_REGISTRY}, so a request can never write
|
|
354
|
+
* arbitrary files or run arbitrary commands.
|
|
355
|
+
*
|
|
356
|
+
* @param rootPath - Absolute path to the project root.
|
|
357
|
+
* @param taskId - Id of the {@link SetupTask} to run a step from.
|
|
358
|
+
* @param stepId - Id of the step within that task.
|
|
359
|
+
* @throws {SetupStepNotFoundError} if the task or step id is unknown.
|
|
360
|
+
* @throws if the step kind is unsupported or execution fails (e.g. the config
|
|
361
|
+
* file already exists).
|
|
362
|
+
*/
|
|
363
|
+
async function executeSetupStep(rootPath, taskId, stepId) {
|
|
364
|
+
const step = findSetupStep(taskId, stepId);
|
|
365
|
+
if (!step) throw new SetupStepNotFoundError(`Unknown step '${stepId}' for task '${taskId}'`);
|
|
366
|
+
switch (step.kind) {
|
|
367
|
+
case "create_config": return { path: await writeConfigFile(rootPath, step) };
|
|
368
|
+
case "run_command":
|
|
369
|
+
case "install_package": throw new Error(`${step.kind} steps are not yet supported`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Returns the onboarding tasks with each step's runtime
|
|
374
|
+
* {@link SetupStepBase.completed | completion status} resolved against the
|
|
375
|
+
* project at `rootPath` (config file present, package installed).
|
|
376
|
+
*
|
|
377
|
+
* @param rootPath - Absolute path to the project root.
|
|
378
|
+
*/
|
|
379
|
+
function resolveSetupTasks(rootPath) {
|
|
380
|
+
return AI_SDK_REGISTRY.map((cls) => ({
|
|
381
|
+
...cls.setupTask,
|
|
382
|
+
steps: cls.setupTask.steps.map((step) => resolveStepStatus(rootPath, step))
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
385
|
+
/** Adds the runtime `completed` flag to a single step where determinable. */
|
|
386
|
+
function resolveStepStatus(rootPath, step) {
|
|
387
|
+
switch (step.kind) {
|
|
388
|
+
case "install_package": return {
|
|
389
|
+
...step,
|
|
390
|
+
completed: isPackageInstalled(rootPath, step.package)
|
|
391
|
+
};
|
|
392
|
+
case "create_config": return {
|
|
393
|
+
...step,
|
|
394
|
+
completed: fs$1.existsSync(path.join(rootPath, step.path))
|
|
395
|
+
};
|
|
396
|
+
case "run_command": return step;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Whether `pkg` is installed for the project at `rootPath`, walking up the
|
|
401
|
+
* directory tree to honour hoisted/workspace `node_modules`.
|
|
402
|
+
*
|
|
403
|
+
* @param rootPath - Absolute path to start the search from.
|
|
404
|
+
* @param pkg - The npm package name to look for.
|
|
405
|
+
*/
|
|
406
|
+
function isPackageInstalled(rootPath, pkg) {
|
|
407
|
+
let dir = rootPath;
|
|
408
|
+
while (true) {
|
|
409
|
+
if (fs$1.existsSync(path.join(dir, "node_modules", pkg, "package.json"))) return true;
|
|
410
|
+
const parent = path.dirname(dir);
|
|
411
|
+
if (parent === dir) return false;
|
|
412
|
+
dir = parent;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Writes the config file for a `create_config` step, creating parent
|
|
417
|
+
* directories as needed. Refuses to clobber an existing file.
|
|
418
|
+
*/
|
|
419
|
+
async function writeConfigFile(rootPath, step) {
|
|
420
|
+
const filePath = path.join(rootPath, step.path);
|
|
421
|
+
try {
|
|
422
|
+
await fs.access(filePath);
|
|
423
|
+
throw new Error(`${step.path} already exists`);
|
|
424
|
+
} catch (err) {
|
|
425
|
+
if (err?.code !== "ENOENT") throw err;
|
|
426
|
+
}
|
|
427
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
428
|
+
await fs.writeFile(filePath, step.contents, "utf8");
|
|
429
|
+
return step.path;
|
|
430
|
+
}
|
|
431
|
+
//#endregion
|
|
423
432
|
//#region src/server/terminal.ts
|
|
424
433
|
/** Shell used to run a resolved step command, so shell syntax in it works. */
|
|
425
434
|
const SHELL = process.env.SHELL || (process.platform === "win32" ? "powershell.exe" : "bash");
|
|
@@ -562,7 +571,11 @@ async function startServer(options) {
|
|
|
562
571
|
rootPath,
|
|
563
572
|
hasConfig,
|
|
564
573
|
tracer,
|
|
565
|
-
defaultTraceProviderId
|
|
574
|
+
defaultTraceProviderId,
|
|
575
|
+
setupTasks: {
|
|
576
|
+
resolve: resolveSetupTasks,
|
|
577
|
+
executeStep: executeSetupStep
|
|
578
|
+
}
|
|
566
579
|
});
|
|
567
580
|
registerTerminalRoute(app, upgradeWebSocket, rootPath);
|
|
568
581
|
const clientRoot = fileURLToPath(new URL("../client/", import.meta.url));
|