@ai-sdk/devtools 1.0.0-beta.3 → 1.0.0-beta.31

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.
@@ -10,8 +10,8 @@
10
10
  href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600;700&display=swap"
11
11
  rel="stylesheet"
12
12
  />
13
- <script type="module" crossorigin src="/assets/index-DmPGHSLs.js"></script>
14
- <link rel="stylesheet" crossorigin href="/assets/index-BkyOIjbt.css">
13
+ <script type="module" crossorigin src="/assets/index-DKzNaLaQ.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/assets/index-BVPj3Knk.css">
15
15
  </head>
16
16
  <body>
17
17
  <div id="root"></div>
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { LanguageModelV4Middleware } from '@ai-sdk/provider';
2
+ import { Telemetry } from 'ai';
2
3
 
3
4
  /**
4
5
  * Factory function that creates a devtools middleware instance.
@@ -18,4 +19,21 @@ import { LanguageModelV4Middleware } from '@ai-sdk/provider';
18
19
  */
19
20
  declare const devToolsMiddleware: () => LanguageModelV4Middleware;
20
21
 
21
- export { devToolsMiddleware };
22
+ /**
23
+ * Creates a devtools telemetry integration that logs all AI SDK operations
24
+ * to the devtools viewer.
25
+ *
26
+ * Usage:
27
+ * ```ts
28
+ * import { registerTelemetry } from 'ai';
29
+ * import { DevToolsTelemetry } from '@ai-sdk/devtools';
30
+ *
31
+ * registerTelemetry(DevToolsTelemetry());
32
+ * ```
33
+ *
34
+ * Telemetry is enabled by default — no need to set `telemetry`
35
+ * unless you want to configure `functionId`, `recordInputs`, or `recordOutputs`.
36
+ */
37
+ declare function DevToolsTelemetry(): Telemetry;
38
+
39
+ export { DevToolsTelemetry, devToolsMiddleware };
package/dist/index.js CHANGED
@@ -1,8 +1,11 @@
1
1
  // src/db.ts
2
2
  import path from "path";
3
3
  import fs from "fs";
4
- var DB_DIR = path.join(process.cwd(), ".devtools");
5
- var DB_PATH = path.join(DB_DIR, "generations.json");
4
+ var DEVTOOLS_DB_DIR = ".devtools";
5
+ var DEVTOOLS_DB_FILE = "generations.json";
6
+ var MAX_DB_BYTES = 100 * 1024 * 1024;
7
+ var DB_DIR = path.join(process.cwd(), DEVTOOLS_DB_DIR);
8
+ var DB_PATH = path.join(DB_DIR, DEVTOOLS_DB_FILE);
6
9
  var DEVTOOLS_PORT = process.env.AI_SDK_DEVTOOLS_PORT ? parseInt(process.env.AI_SDK_DEVTOOLS_PORT) : 4983;
7
10
  var notifyServer = (event) => {
8
11
  notifyServerAsync(event);
@@ -12,7 +15,7 @@ var notifyServerAsync = async (event) => {
12
15
  await fetch(`http://localhost:${DEVTOOLS_PORT}/api/notify`, {
13
16
  method: "POST",
14
17
  headers: { "Content-Type": "application/json" },
15
- body: JSON.stringify({ event, timestamp: Date.now() })
18
+ body: JSON.stringify({ event, timestamp: Date.now(), dbPath: DB_PATH })
16
19
  });
17
20
  } catch {
18
21
  }
@@ -64,14 +67,20 @@ var saveDb = (db) => {
64
67
  dbCache = db;
65
68
  writeDb(db);
66
69
  };
67
- var createRun = async (id) => {
70
+ var createRun = async (id, parent, functionId) => {
68
71
  const db = getDb();
69
72
  const started_at = (/* @__PURE__ */ new Date()).toISOString();
70
73
  const existing = db.runs.find((r) => r.id === id);
71
74
  if (existing) {
72
75
  return existing;
73
76
  }
74
- const run = { id, started_at };
77
+ const run = {
78
+ id,
79
+ started_at,
80
+ parent_run_id: parent?.runId ?? null,
81
+ parent_step_id: parent?.stepId ?? null,
82
+ function_id: functionId ?? null
83
+ };
75
84
  db.runs.push(run);
76
85
  saveDb(db);
77
86
  notifyServer("run");
@@ -379,6 +388,289 @@ var devToolsMiddleware = () => {
379
388
  }
380
389
  };
381
390
  };
391
+
392
+ // src/integration.ts
393
+ var activeSteps2 = /* @__PURE__ */ new Map();
394
+ var signalHandlersRegistered2 = false;
395
+ var registerSignalHandlers2 = () => {
396
+ if (signalHandlersRegistered2) return;
397
+ signalHandlersRegistered2 = true;
398
+ const cleanup = async () => {
399
+ if (activeSteps2.size === 0) return;
400
+ const promises = Array.from(activeSteps2.entries()).map(
401
+ async ([stepId, data]) => {
402
+ const durationMs = Date.now() - data.startTime;
403
+ await updateStepResult(stepId, {
404
+ duration_ms: durationMs,
405
+ output: null,
406
+ usage: null,
407
+ error: "Request aborted",
408
+ raw_request: null,
409
+ raw_response: null,
410
+ raw_chunks: null
411
+ });
412
+ }
413
+ );
414
+ await Promise.all(promises);
415
+ await notifyServerAsync("step-update");
416
+ };
417
+ process.on("SIGINT", () => {
418
+ cleanup().then(() => process.exit(130));
419
+ });
420
+ process.on("SIGTERM", () => {
421
+ cleanup().then(() => process.exit(143));
422
+ });
423
+ };
424
+ var generateRunId2 = () => {
425
+ const now = /* @__PURE__ */ new Date();
426
+ const timestamp = now.toISOString().replace(/[-:T.Z]/g, "").slice(0, 17);
427
+ const uniqueId = crypto.randomUUID().slice(0, 8);
428
+ return `${timestamp}-${uniqueId}`;
429
+ };
430
+ function getOperationType(operationId) {
431
+ if (operationId === "ai.streamText" || operationId === "ai.streamObject") {
432
+ return "stream";
433
+ }
434
+ return "generate";
435
+ }
436
+ function DevToolsTelemetry() {
437
+ if (process.env.NODE_ENV === "production") {
438
+ throw new Error(
439
+ "@ai-sdk/devtools should not be used in production. Remove DevToolsTelemetry from your telemetry configuration for production builds."
440
+ );
441
+ }
442
+ registerSignalHandlers2();
443
+ const callStates = /* @__PURE__ */ new Map();
444
+ const toolContextMap = /* @__PURE__ */ new Map();
445
+ let currentToolCallId = null;
446
+ function resolveParentInfo() {
447
+ if (!currentToolCallId) return void 0;
448
+ const toolCallContext = toolContextMap.get(currentToolCallId);
449
+ if (!toolCallContext) return void 0;
450
+ const parentState = callStates.get(toolCallContext.parentCallId);
451
+ if (!parentState) return void 0;
452
+ let latestStepId;
453
+ let latestStepNumber = -1;
454
+ for (const [stepNumber, stepState] of parentState.stepStates) {
455
+ if (stepNumber > latestStepNumber) {
456
+ latestStepNumber = stepNumber;
457
+ latestStepId = stepState.stepId;
458
+ }
459
+ }
460
+ if (!latestStepId) return void 0;
461
+ return { runId: parentState.runId, stepId: latestStepId };
462
+ }
463
+ function getOrCreateCallState(callId, operationId, event) {
464
+ let state = callStates.get(callId);
465
+ if (state) return state;
466
+ state = {
467
+ runId: generateRunId2(),
468
+ operationType: getOperationType(operationId),
469
+ functionId: event.functionId,
470
+ settings: {
471
+ maxOutputTokens: event.maxOutputTokens,
472
+ temperature: event.temperature,
473
+ topP: event.topP,
474
+ topK: event.topK,
475
+ presencePenalty: event.presencePenalty,
476
+ frequencyPenalty: event.frequencyPenalty,
477
+ seed: event.seed
478
+ },
479
+ stepStates: /* @__PURE__ */ new Map()
480
+ };
481
+ callStates.set(callId, state);
482
+ return state;
483
+ }
484
+ const integration = {
485
+ onStart: async (event) => {
486
+ const operationId = event.operationId;
487
+ if (operationId === "ai.embed" || operationId === "ai.embedMany" || operationId === "ai.rerank") {
488
+ return;
489
+ }
490
+ const startEvent = event;
491
+ const parentInfo = resolveParentInfo();
492
+ const state = getOrCreateCallState(
493
+ startEvent.callId,
494
+ operationId,
495
+ startEvent
496
+ );
497
+ await createRun(state.runId, parentInfo, state.functionId);
498
+ },
499
+ onStepStart: async (event) => {
500
+ const stepStartEvent = event;
501
+ const state = callStates.get(stepStartEvent.callId);
502
+ if (!state) return;
503
+ const stepId = crypto.randomUUID();
504
+ const startTime = Date.now();
505
+ const stepState = {
506
+ stepId,
507
+ startTime
508
+ };
509
+ const stepNumber = stepStartEvent.steps.length;
510
+ state.stepStates.set(stepNumber, stepState);
511
+ activeSteps2.set(stepId, stepState);
512
+ const prompt = stepStartEvent.promptMessages ?? stepStartEvent.messages;
513
+ await createStep({
514
+ id: stepId,
515
+ run_id: state.runId,
516
+ step_number: stepNumber + 1,
517
+ type: state.operationType,
518
+ model_id: stepStartEvent.modelId,
519
+ provider: stepStartEvent.provider ?? null,
520
+ started_at: (/* @__PURE__ */ new Date()).toISOString(),
521
+ input: JSON.stringify({
522
+ prompt,
523
+ tools: stepStartEvent.tools ? Object.entries(stepStartEvent.tools).map(([name, tool]) => ({
524
+ name,
525
+ description: tool.description,
526
+ parameters: tool.parameters
527
+ })) : void 0,
528
+ toolChoice: stepStartEvent.toolChoice,
529
+ maxOutputTokens: state.settings.maxOutputTokens,
530
+ temperature: state.settings.temperature,
531
+ topP: state.settings.topP,
532
+ topK: state.settings.topK,
533
+ presencePenalty: state.settings.presencePenalty,
534
+ frequencyPenalty: state.settings.frequencyPenalty,
535
+ seed: state.settings.seed
536
+ }),
537
+ provider_options: stepStartEvent.providerOptions ? JSON.stringify(stepStartEvent.providerOptions) : null
538
+ });
539
+ },
540
+ onObjectStepStart: async (event) => {
541
+ const stepStartEvent = event;
542
+ const state = callStates.get(stepStartEvent.callId);
543
+ if (!state) return;
544
+ const stepId = crypto.randomUUID();
545
+ const startTime = Date.now();
546
+ const stepState = {
547
+ stepId,
548
+ startTime
549
+ };
550
+ state.stepStates.set(stepStartEvent.stepNumber, stepState);
551
+ activeSteps2.set(stepId, stepState);
552
+ await createStep({
553
+ id: stepId,
554
+ run_id: state.runId,
555
+ step_number: stepStartEvent.stepNumber + 1,
556
+ type: state.operationType,
557
+ model_id: stepStartEvent.modelId,
558
+ provider: stepStartEvent.provider ?? null,
559
+ started_at: (/* @__PURE__ */ new Date()).toISOString(),
560
+ input: JSON.stringify({
561
+ prompt: stepStartEvent.promptMessages,
562
+ maxOutputTokens: state.settings.maxOutputTokens,
563
+ temperature: state.settings.temperature,
564
+ topP: state.settings.topP,
565
+ topK: state.settings.topK,
566
+ presencePenalty: state.settings.presencePenalty,
567
+ frequencyPenalty: state.settings.frequencyPenalty,
568
+ seed: state.settings.seed
569
+ }),
570
+ provider_options: stepStartEvent.providerOptions ? JSON.stringify(stepStartEvent.providerOptions) : null
571
+ });
572
+ },
573
+ onStepEnd: async (event) => {
574
+ const stepResult = event;
575
+ const state = callStates.get(stepResult.callId);
576
+ if (!state) return;
577
+ const stepState = state.stepStates.get(stepResult.stepNumber);
578
+ if (!stepState) return;
579
+ activeSteps2.delete(stepState.stepId);
580
+ const durationMs = Date.now() - stepState.startTime;
581
+ const output = {
582
+ content: stepResult.content,
583
+ finishReason: stepResult.finishReason,
584
+ response: {
585
+ id: stepResult.response.id,
586
+ modelId: stepResult.response.modelId,
587
+ timestamp: stepResult.response.timestamp,
588
+ messages: stepResult.response.messages
589
+ }
590
+ };
591
+ await updateStepResult(stepState.stepId, {
592
+ duration_ms: durationMs,
593
+ output: JSON.stringify(output),
594
+ usage: stepResult.usage ? JSON.stringify(stepResult.usage) : null,
595
+ error: null,
596
+ raw_request: stepResult.request?.body ? JSON.stringify(stepResult.request.body) : null,
597
+ raw_response: stepResult.response?.body ? JSON.stringify(stepResult.response.body) : null,
598
+ raw_chunks: null
599
+ });
600
+ state.stepStates.delete(stepResult.stepNumber);
601
+ },
602
+ onObjectStepEnd: async (event) => {
603
+ const stepResult = event;
604
+ const state = callStates.get(stepResult.callId);
605
+ if (!state) return;
606
+ const stepState = state.stepStates.get(stepResult.stepNumber);
607
+ if (!stepState) return;
608
+ activeSteps2.delete(stepState.stepId);
609
+ const durationMs = Date.now() - stepState.startTime;
610
+ const output = {
611
+ finishReason: stepResult.finishReason,
612
+ objectText: stepResult.objectText,
613
+ response: {
614
+ id: stepResult.response.id,
615
+ modelId: stepResult.response.modelId,
616
+ timestamp: stepResult.response.timestamp
617
+ }
618
+ };
619
+ await updateStepResult(stepState.stepId, {
620
+ duration_ms: durationMs,
621
+ output: JSON.stringify(output),
622
+ usage: stepResult.usage ? JSON.stringify(stepResult.usage) : null,
623
+ error: null,
624
+ raw_request: stepResult.request?.body ? JSON.stringify(stepResult.request.body) : null,
625
+ raw_response: stepResult.response?.body ? JSON.stringify(stepResult.response.body) : null
626
+ });
627
+ state.stepStates.delete(stepResult.stepNumber);
628
+ },
629
+ onEnd: async (event) => {
630
+ const endEvent = event;
631
+ callStates.delete(endEvent.callId);
632
+ },
633
+ onError: async (error) => {
634
+ const errorObj = error;
635
+ const callId = errorObj?.callId;
636
+ if (!callId) return;
637
+ const state = callStates.get(callId);
638
+ if (!state) return;
639
+ const cause = errorObj?.error ?? error;
640
+ const errorMessage = cause instanceof Error ? cause.message : String(cause);
641
+ for (const [, stepState] of state.stepStates) {
642
+ activeSteps2.delete(stepState.stepId);
643
+ const durationMs = Date.now() - stepState.startTime;
644
+ await updateStepResult(stepState.stepId, {
645
+ duration_ms: durationMs,
646
+ output: null,
647
+ usage: null,
648
+ error: errorMessage,
649
+ raw_request: null,
650
+ raw_response: null,
651
+ raw_chunks: null
652
+ });
653
+ }
654
+ callStates.delete(callId);
655
+ },
656
+ executeTool: async ({ callId, toolCallId, execute }) => {
657
+ toolContextMap.set(toolCallId, {
658
+ parentCallId: callId,
659
+ parentToolCallId: toolCallId
660
+ });
661
+ const previousToolCallId = currentToolCallId;
662
+ currentToolCallId = toolCallId;
663
+ try {
664
+ return await execute();
665
+ } finally {
666
+ currentToolCallId = previousToolCallId;
667
+ toolContextMap.delete(toolCallId);
668
+ }
669
+ }
670
+ };
671
+ return integration;
672
+ }
382
673
  export {
674
+ DevToolsTelemetry,
383
675
  devToolsMiddleware
384
676
  };
@@ -2,7 +2,6 @@
2
2
  import { serve } from "@hono/node-server";
3
3
  import { serveStatic } from "@hono/node-server/serve-static";
4
4
  import { Hono } from "hono";
5
- import { cors } from "hono/cors";
6
5
  import { streamSSE } from "hono/streaming";
7
6
  import path2 from "path";
8
7
  import fs2 from "fs";
@@ -11,8 +10,11 @@ import { fileURLToPath } from "url";
11
10
  // src/db.ts
12
11
  import path from "path";
13
12
  import fs from "fs";
14
- var DB_DIR = path.join(process.cwd(), ".devtools");
15
- var DB_PATH = path.join(DB_DIR, "generations.json");
13
+ var DEVTOOLS_DB_DIR = ".devtools";
14
+ var DEVTOOLS_DB_FILE = "generations.json";
15
+ var MAX_DB_BYTES = 100 * 1024 * 1024;
16
+ var DB_DIR = path.join(process.cwd(), DEVTOOLS_DB_DIR);
17
+ var DB_PATH = path.join(DB_DIR, DEVTOOLS_DB_FILE);
16
18
  var DEVTOOLS_PORT = process.env.AI_SDK_DEVTOOLS_PORT ? parseInt(process.env.AI_SDK_DEVTOOLS_PORT) : 4983;
17
19
  var notifyServer = (event) => {
18
20
  notifyServerAsync(event);
@@ -22,7 +24,7 @@ var notifyServerAsync = async (event) => {
22
24
  await fetch(`http://localhost:${DEVTOOLS_PORT}/api/notify`, {
23
25
  method: "POST",
24
26
  headers: { "Content-Type": "application/json" },
25
- body: JSON.stringify({ event, timestamp: Date.now() })
27
+ body: JSON.stringify({ event, timestamp: Date.now(), dbPath: DB_PATH })
26
28
  });
27
29
  } catch {
28
30
  }
@@ -74,7 +76,43 @@ var saveDb = (db) => {
74
76
  dbCache = db;
75
77
  writeDb(db);
76
78
  };
77
- var reloadDb = async () => {
79
+ var normalizeDevtoolsDbPath = (dbPath) => {
80
+ const resolvedPath = path.resolve(dbPath);
81
+ const dbDir = path.dirname(resolvedPath);
82
+ if (path.basename(resolvedPath) !== DEVTOOLS_DB_FILE || path.basename(dbDir) !== DEVTOOLS_DB_DIR) {
83
+ return void 0;
84
+ }
85
+ return resolvedPath;
86
+ };
87
+ var validateRemoteDbPath = (dbPath) => {
88
+ if (typeof dbPath !== "string") {
89
+ return void 0;
90
+ }
91
+ const normalizedPath = normalizeDevtoolsDbPath(dbPath);
92
+ if (!normalizedPath) {
93
+ return void 0;
94
+ }
95
+ try {
96
+ const stats = fs.statSync(normalizedPath);
97
+ if (!stats.isFile() || stats.size > MAX_DB_BYTES) {
98
+ return void 0;
99
+ }
100
+ const realPath = fs.realpathSync(normalizedPath);
101
+ return normalizeDevtoolsDbPath(realPath);
102
+ } catch {
103
+ return void 0;
104
+ }
105
+ };
106
+ var reloadDb = async (remoteDbPath2) => {
107
+ const validatedRemoteDbPath = validateRemoteDbPath(remoteDbPath2);
108
+ if (validatedRemoteDbPath) {
109
+ try {
110
+ const content = fs.readFileSync(validatedRemoteDbPath, "utf-8");
111
+ dbCache = JSON.parse(content);
112
+ return;
113
+ } catch {
114
+ }
115
+ }
78
116
  dbCache = readDb();
79
117
  };
80
118
  var getRuns = async () => {
@@ -120,12 +158,39 @@ var devEnv = process.env.AI_SDK_DEVTOOLS_DEV;
120
158
  var isDevMode = devEnv !== void 0 && devEnv !== "false" && devEnv !== "0";
121
159
  var projectRoot = path2.resolve(__dirname, "../..");
122
160
  var clientDir = path2.join(projectRoot, "dist/client");
161
+ var remoteDbPath;
162
+ var viewerPort = 4983;
123
163
  var app = new Hono();
124
- app.use("/*", cors());
164
+ var getAllowedHosts = () => /* @__PURE__ */ new Set([
165
+ `localhost:${viewerPort}`,
166
+ `127.0.0.1:${viewerPort}`,
167
+ `[::1]:${viewerPort}`
168
+ ]);
169
+ var getAllowedOrigins = () => /* @__PURE__ */ new Set([
170
+ `http://localhost:${viewerPort}`,
171
+ `http://127.0.0.1:${viewerPort}`,
172
+ `http://[::1]:${viewerPort}`,
173
+ "http://localhost:5173",
174
+ "http://127.0.0.1:5173",
175
+ "http://[::1]:5173"
176
+ ]);
177
+ app.use("/api/*", async (c, next) => {
178
+ const host = c.req.header("host");
179
+ if (!host || !getAllowedHosts().has(host)) {
180
+ return c.text("Forbidden", 403);
181
+ }
182
+ const origin = c.req.header("origin");
183
+ if (origin && !getAllowedOrigins().has(origin)) {
184
+ return c.text("Forbidden", 403);
185
+ }
186
+ await next();
187
+ });
125
188
  app.get("/api/runs", async (c) => {
189
+ await reloadDb(remoteDbPath);
126
190
  const runs = await getRuns();
191
+ const rootRuns = runs.filter((r) => !r.parent_run_id);
127
192
  const runsWithMeta = await Promise.all(
128
- runs.map(async (run) => {
193
+ rootRuns.map(async (run) => {
129
194
  const steps = await getStepsForRun(run.id);
130
195
  let firstMessage = "No user message";
131
196
  let hasError = false;
@@ -159,14 +224,35 @@ app.get("/api/runs", async (c) => {
159
224
  return c.json(runsWithMeta);
160
225
  });
161
226
  app.get("/api/runs/:id", async (c) => {
227
+ await reloadDb(remoteDbPath);
162
228
  const data = await getRunWithSteps(c.req.param("id"));
163
229
  if (!data) {
164
230
  return c.json({ error: "Run not found" }, 404);
165
231
  }
166
232
  const isInProgress = data.steps.some((s) => s.duration_ms === null && !s.error);
233
+ const allRuns = await getRuns();
234
+ async function getDescendantRuns(parentRunId) {
235
+ const children = allRuns.filter((r) => r.parent_run_id === parentRunId);
236
+ return Promise.all(
237
+ children.map(async (childRun) => {
238
+ const childSteps = await getStepsForRun(childRun.id);
239
+ const childIsInProgress = childSteps.some(
240
+ (s) => s.duration_ms === null && !s.error
241
+ );
242
+ const grandchildren = await getDescendantRuns(childRun.id);
243
+ return {
244
+ run: { ...childRun, isInProgress: childIsInProgress },
245
+ steps: childSteps,
246
+ childRuns: grandchildren
247
+ };
248
+ })
249
+ );
250
+ }
251
+ const childRuns = await getDescendantRuns(data.run.id);
167
252
  return c.json({
168
253
  run: { ...data.run, isInProgress },
169
- steps: data.steps
254
+ steps: data.steps,
255
+ childRuns
170
256
  });
171
257
  });
172
258
  app.post("/api/clear", async (c) => {
@@ -224,7 +310,14 @@ app.get("/api/events", (c) => {
224
310
  });
225
311
  app.post("/api/notify", async (c) => {
226
312
  const body = await c.req.json();
227
- await reloadDb();
313
+ if (body.dbPath !== void 0) {
314
+ const validatedDbPath = validateRemoteDbPath(body.dbPath);
315
+ if (!validatedDbPath) {
316
+ return c.text("Invalid dbPath", 400);
317
+ }
318
+ remoteDbPath = validatedDbPath;
319
+ }
320
+ await reloadDb(remoteDbPath);
228
321
  broadcastToClients("update", body);
229
322
  return c.json({ success: true });
230
323
  });
@@ -269,10 +362,12 @@ app.get("*", async (c) => {
269
362
  }
270
363
  });
271
364
  var startViewer = (port = 4983) => {
365
+ viewerPort = port;
272
366
  const server = serve(
273
367
  {
274
368
  fetch: app.fetch,
275
- port
369
+ port,
370
+ hostname: "localhost"
276
371
  },
277
372
  () => {
278
373
  if (isDevMode) {
@@ -309,5 +404,6 @@ if (isDirectRun) {
309
404
  startViewer(port);
310
405
  }
311
406
  export {
407
+ app,
312
408
  startViewer
313
409
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/devtools",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.0.0-beta.31",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -25,38 +25,60 @@
25
25
  "bin"
26
26
  ],
27
27
  "dependencies": {
28
- "@hono/node-server": "^1.13.7",
29
- "hono": "^4.6.14",
30
- "@ai-sdk/provider": "4.0.0-beta.3"
28
+ "@hono/node-server": "^1.19.14",
29
+ "hono": "^4.12.18",
30
+ "@ai-sdk/provider": "4.0.0-beta.19"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@radix-ui/react-collapsible": "^1.1.12",
34
34
  "@radix-ui/react-scroll-area": "^1.2.10",
35
35
  "@radix-ui/react-slot": "^1.2.4",
36
36
  "@radix-ui/react-tooltip": "^1.2.8",
37
- "@tailwindcss/vite": "^4.1.17",
38
- "@types/node": "20.17.24",
39
- "@types/react": "^18",
40
- "@types/react-dom": "^18",
41
- "@vitejs/plugin-react": "^4.3.4",
37
+ "@tailwindcss/vite": "^4.3.0",
38
+ "@types/node": "22.19.19",
39
+ "@types/react": "^18.3.28",
40
+ "@types/react-dom": "^18.3.7",
41
+ "@vitejs/plugin-react": "^4.7.0",
42
42
  "class-variance-authority": "^0.7.1",
43
43
  "clsx": "^2.1.1",
44
- "concurrently": "^9.1.0",
45
- "dotenv": "^17.2.3",
44
+ "concurrently": "^9.2.1",
45
+ "dotenv": "^17.4.2",
46
46
  "lucide-react": "^0.556.0",
47
- "react": "^18 || ^19",
48
- "react-dom": "^18 || ^19",
49
- "tailwind-merge": "^3.4.0",
50
- "tailwindcss": "^4.1.17",
51
- "tsup": "^8",
52
- "tsx": "^4.19.2",
47
+ "react": "^19.2.6",
48
+ "react-dom": "^19.2.6",
49
+ "tailwind-merge": "^3.6.0",
50
+ "tailwindcss": "^4.3.0",
51
+ "tsup": "^8.5.1",
52
+ "tsx": "^4.22.0",
53
53
  "tw-animate-css": "^1.4.0",
54
54
  "typescript": "5.8.3",
55
55
  "vaul": "^1.1.2",
56
- "vite": "^6.0.3",
56
+ "vite": "^6.4.2",
57
+ "vitest": "^4.1.6",
57
58
  "zod": "3.25.76",
58
- "ai": "7.0.0-beta.25"
59
+ "ai": "7.0.0-beta.177"
59
60
  },
61
+ "publishConfig": {
62
+ "access": "public",
63
+ "provenance": true
64
+ },
65
+ "homepage": "https://ai-sdk.dev/docs",
66
+ "repository": {
67
+ "type": "git",
68
+ "url": "https://github.com/vercel/ai",
69
+ "directory": "packages/devtools"
70
+ },
71
+ "bugs": {
72
+ "url": "https://github.com/vercel/ai/issues"
73
+ },
74
+ "license": "Apache-2.0",
75
+ "sideEffects": false,
76
+ "engines": {
77
+ "node": ">=22"
78
+ },
79
+ "keywords": [
80
+ "ai"
81
+ ],
60
82
  "scripts": {
61
83
  "dev": "concurrently -k \"pnpm dev:api\" \"pnpm dev:client\"",
62
84
  "dev:api": "AI_SDK_DEVTOOLS_DEV=true tsx src/viewer/server.ts",
@@ -65,6 +87,8 @@
65
87
  "start": "node dist/viewer/server.js",
66
88
  "build": "pnpm build:client && pnpm build:server",
67
89
  "build:client": "vite build",
68
- "build:server": "tsup"
90
+ "build:server": "tsup --tsconfig tsconfig.build.json",
91
+ "test": "vitest --config vitest.node.config.js --run",
92
+ "test:watch": "vitest --config vitest.node.config.js"
69
93
  }
70
94
  }