@ai-sdk/devtools 1.0.55 → 1.0.57
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 +3 -91
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -14
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/integration.ts +28 -13
package/README.md
CHANGED
|
@@ -4,25 +4,14 @@ A local development tool for debugging and inspecting AI SDK applications. View
|
|
|
4
4
|
|
|
5
5
|
> **Note**: This package is experimental and intended for local development only. Do not use in production environments.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Setup
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm
|
|
11
|
-
# or
|
|
12
|
-
pnpm add @ai-sdk/devtools
|
|
10
|
+
npm i ai @ai-sdk/devtools
|
|
13
11
|
```
|
|
14
12
|
|
|
15
|
-
## Requirements
|
|
16
|
-
|
|
17
|
-
- AI SDK v7 canary (`ai@canary`)
|
|
18
|
-
- Node.js compatible runtime
|
|
19
|
-
|
|
20
13
|
## Usage
|
|
21
14
|
|
|
22
|
-
### 1. Register the telemetry integration
|
|
23
|
-
|
|
24
|
-
Register `DevToolsTelemetry` globally so it captures all AI SDK calls:
|
|
25
|
-
|
|
26
15
|
```typescript
|
|
27
16
|
import { registerTelemetry } from 'ai';
|
|
28
17
|
import { DevToolsTelemetry } from '@ai-sdk/devtools';
|
|
@@ -30,81 +19,4 @@ import { DevToolsTelemetry } from '@ai-sdk/devtools';
|
|
|
30
19
|
registerTelemetry(DevToolsTelemetry());
|
|
31
20
|
```
|
|
32
21
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
import { generateText } from 'ai';
|
|
37
|
-
|
|
38
|
-
const result = await generateText({
|
|
39
|
-
model: yourModel,
|
|
40
|
-
prompt: 'What cities are in the United States?',
|
|
41
|
-
});
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
You can also pass the integration to individual calls instead of registering it
|
|
45
|
-
globally:
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
import { streamText } from 'ai';
|
|
49
|
-
import { DevToolsTelemetry } from '@ai-sdk/devtools';
|
|
50
|
-
|
|
51
|
-
const result = streamText({
|
|
52
|
-
model: yourModel,
|
|
53
|
-
prompt: 'Hello!',
|
|
54
|
-
telemetry: {
|
|
55
|
-
integrations: [DevToolsTelemetry()],
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### 2. Run the viewer
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
npx @ai-sdk/devtools@latest
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Open http://localhost:4983 to view your AI SDK interactions.
|
|
67
|
-
|
|
68
|
-
The viewer uses the dark theme by default. Use the theme button in the header to
|
|
69
|
-
switch between dark and light themes. The browser remembers your selection for
|
|
70
|
-
the next time you open the viewer at the same origin.
|
|
71
|
-
|
|
72
|
-
If you are using a monorepo, start DevTools from the same workspace where your
|
|
73
|
-
AI SDK code runs. The explicit `@latest` tag ensures that `npx` installs an
|
|
74
|
-
executable copy instead of selecting a transitive dependency whose binary is
|
|
75
|
-
not linked into that workspace.
|
|
76
|
-
|
|
77
|
-
## How it works
|
|
78
|
-
|
|
79
|
-
The `DevToolsTelemetry` integration hooks into the AI SDK telemetry lifecycle to
|
|
80
|
-
capture `generateText`, `streamText`, `generateObject`, and `streamObject` calls.
|
|
81
|
-
It captures:
|
|
82
|
-
|
|
83
|
-
- Input parameters and prompts
|
|
84
|
-
- Output content and tool calls
|
|
85
|
-
- Token usage and timing
|
|
86
|
-
- Raw provider data
|
|
87
|
-
|
|
88
|
-
Data is stored locally in a JSON file (`.devtools/generations.json`) and served through a web UI.
|
|
89
|
-
|
|
90
|
-
### Data flow
|
|
91
|
-
|
|
92
|
-
```
|
|
93
|
-
AI SDK call -> DevToolsTelemetry -> JSON file -> Hono API -> React UI
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### Key concepts
|
|
97
|
-
|
|
98
|
-
- **Run**: A complete multi-step AI interaction, grouped by initial prompt
|
|
99
|
-
- **Step**: A single LLM call within a run
|
|
100
|
-
|
|
101
|
-
## Development
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
pnpm install
|
|
105
|
-
pnpm dev # Start dev server at http://localhost:5173
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## License
|
|
109
|
-
|
|
110
|
-
MIT
|
|
22
|
+
See the [DevTools documentation](https://ai-sdk.dev/docs/ai-sdk-core/devtools) for more information.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/middleware.ts","../src/integration.ts"],"mappings":";;;;;;;;;;;;;;;;;;;qBAoGa,0BAAyB;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/middleware.ts","../src/integration.ts"],"mappings":";;;;;;;;;;;;;;;;;;;qBAoGa,0BAAyB;;;UChErB;;;;;EAKf;;;;;;;;;;;;;;;;;wBAqFc,kBACd,UAAS,2BACR"}
|
package/dist/index.js
CHANGED
|
@@ -459,6 +459,18 @@ const devToolsMiddleware = () => {
|
|
|
459
459
|
//#endregion
|
|
460
460
|
//#region src/integration.ts
|
|
461
461
|
const activeSteps = /* @__PURE__ */ new Map();
|
|
462
|
+
async function failStep(stepState, error) {
|
|
463
|
+
activeSteps.delete(stepState.stepId);
|
|
464
|
+
await updateStepResult(stepState.stepId, {
|
|
465
|
+
duration_ms: Date.now() - stepState.startTime,
|
|
466
|
+
output: null,
|
|
467
|
+
usage: null,
|
|
468
|
+
error: error instanceof Error ? error.message : String(error),
|
|
469
|
+
raw_request: null,
|
|
470
|
+
raw_response: null,
|
|
471
|
+
raw_chunks: null
|
|
472
|
+
});
|
|
473
|
+
}
|
|
462
474
|
let signalHandlersRegistered = false;
|
|
463
475
|
const registerSignalHandlers = () => {
|
|
464
476
|
if (signalHandlersRegistered) return;
|
|
@@ -696,6 +708,15 @@ function DevToolsTelemetry(options = {}) {
|
|
|
696
708
|
});
|
|
697
709
|
state.stepStates.delete(stepResult.stepNumber);
|
|
698
710
|
},
|
|
711
|
+
onStepError: async (event) => {
|
|
712
|
+
const stepErrorEvent = event;
|
|
713
|
+
const state = callStates.get(stepErrorEvent.callId);
|
|
714
|
+
if (!state) return;
|
|
715
|
+
const stepState = state.stepStates.get(stepErrorEvent.stepNumber);
|
|
716
|
+
if (!stepState) return;
|
|
717
|
+
await failStep(stepState, stepErrorEvent.error);
|
|
718
|
+
state.stepStates.delete(stepErrorEvent.stepNumber);
|
|
719
|
+
},
|
|
699
720
|
onEnd: async (event) => {
|
|
700
721
|
const endEvent = event;
|
|
701
722
|
callStates.delete(endEvent.callId);
|
|
@@ -707,20 +728,7 @@ function DevToolsTelemetry(options = {}) {
|
|
|
707
728
|
const state = callStates.get(callId);
|
|
708
729
|
if (!state) return;
|
|
709
730
|
const cause = errorObj?.error ?? error;
|
|
710
|
-
const
|
|
711
|
-
for (const [, stepState] of state.stepStates) {
|
|
712
|
-
activeSteps.delete(stepState.stepId);
|
|
713
|
-
const durationMs = Date.now() - stepState.startTime;
|
|
714
|
-
await updateStepResult(stepState.stepId, {
|
|
715
|
-
duration_ms: durationMs,
|
|
716
|
-
output: null,
|
|
717
|
-
usage: null,
|
|
718
|
-
error: errorMessage,
|
|
719
|
-
raw_request: null,
|
|
720
|
-
raw_response: null,
|
|
721
|
-
raw_chunks: null
|
|
722
|
-
});
|
|
723
|
-
}
|
|
731
|
+
for (const [, stepState] of state.stepStates) await failStep(stepState, cause);
|
|
724
732
|
callStates.delete(callId);
|
|
725
733
|
},
|
|
726
734
|
executeTool: async ({ callId, toolCallId, execute }) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["activeSteps","signalHandlersRegistered","registerSignalHandlers","generateRunId"],"sources":["../src/db.ts","../src/serialize.ts","../src/middleware.ts","../src/integration.ts"],"sourcesContent":["import path from 'node:path';\nimport fs from 'node:fs';\n\nconst DEVTOOLS_DB_DIR = '.devtools';\nconst DEVTOOLS_DB_FILE = 'generations.json';\n// Cap how many bytes we read from a remote database file. Guards against a\n// synchronous hang / OOM if the file is enormous.\nconst MAX_DB_BYTES = 100 * 1024 * 1024; // 100 MB\nconst DB_DIR = path.join(process.cwd(), DEVTOOLS_DB_DIR);\nconst DB_PATH = path.join(DB_DIR, DEVTOOLS_DB_FILE);\nconst DEVTOOLS_PORT = process.env.AI_SDK_DEVTOOLS_PORT\n ? parseInt(process.env.AI_SDK_DEVTOOLS_PORT)\n : 4983;\n\n/**\n * Notify the devtools server that data has changed.\n * Fire-and-forget: doesn't block, ignores errors if server isn't running.\n */\nconst notifyServer = (event: 'run' | 'step' | 'step-update' | 'clear') => {\n notifyServerAsync(event);\n};\n\n/**\n * Notify the devtools server and wait for the request to complete.\n * Used during process cleanup to ensure notifications are sent before exit.\n */\nexport const notifyServerAsync = async (\n event: 'run' | 'step' | 'step-update' | 'clear',\n): Promise<void> => {\n try {\n await fetch(`http://localhost:${DEVTOOLS_PORT}/api/notify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ event, timestamp: Date.now(), dbPath: DB_PATH }),\n });\n } catch {\n // Ignore errors - server might not be running\n }\n};\n\nexport interface Run {\n id: string;\n started_at: string;\n parent_run_id: string | null;\n parent_step_id: string | null;\n function_id: string | null;\n}\n\nexport interface Step {\n id: string;\n run_id: string;\n step_number: number;\n type: 'generate' | 'stream';\n model_id: string;\n provider: string | null;\n started_at: string;\n duration_ms: number | null;\n input: string;\n output: string | null;\n usage: string | null;\n error: string | null;\n raw_request: string | null;\n raw_response: string | null;\n raw_chunks: string | null;\n provider_options: string | null;\n}\n\nexport interface StepResult {\n duration_ms: number;\n output: string | null;\n usage: string | null;\n error: string | null;\n raw_request?: string | null;\n raw_response?: string | null;\n raw_chunks?: string | null;\n}\n\ninterface Database {\n runs: Run[];\n steps: Step[];\n}\n\n/**\n * Ensure .devtools is in .gitignore.\n * Only writes if .gitignore exists and doesn't already contain .devtools.\n */\nconst ensureGitignore = (): void => {\n const gitignorePath = path.join(process.cwd(), '.gitignore');\n\n if (!fs.existsSync(gitignorePath)) {\n return;\n }\n\n const content = fs.readFileSync(gitignorePath, 'utf-8');\n const lines = content.split('\\n');\n\n // Check if .devtools is already ignored (exact match or with trailing slash)\n const alreadyIgnored = lines.some(\n line => line.trim() === '.devtools' || line.trim() === '.devtools/',\n );\n\n if (!alreadyIgnored) {\n const newContent = content.endsWith('\\n')\n ? `${content}.devtools\\n`\n : `${content}\\n.devtools\\n`;\n fs.writeFileSync(gitignorePath, newContent);\n }\n};\n\nconst readDb = (): Database => {\n try {\n if (fs.existsSync(DB_PATH)) {\n const content = fs.readFileSync(DB_PATH, 'utf-8');\n return JSON.parse(content);\n }\n } catch {\n // If file is corrupted, start fresh\n }\n return { runs: [], steps: [] };\n};\n\nconst writeDb = (db: Database): void => {\n const isFirstRun = !fs.existsSync(DB_DIR);\n\n if (isFirstRun) {\n fs.mkdirSync(DB_DIR, { recursive: true });\n ensureGitignore();\n }\n\n fs.writeFileSync(DB_PATH, JSON.stringify(db, null, 2));\n};\n\n// In-memory cache for performance\nlet dbCache: Database | null = null;\n\nconst getDb = (): Database => {\n if (!dbCache) {\n dbCache = readDb();\n }\n return dbCache;\n};\n\nconst saveDb = (db: Database): void => {\n dbCache = db;\n writeDb(db);\n};\n\nconst normalizeDevtoolsDbPath = (dbPath: string): string | undefined => {\n const resolvedPath = path.resolve(dbPath);\n const dbDir = path.dirname(resolvedPath);\n\n if (\n path.basename(resolvedPath) !== DEVTOOLS_DB_FILE ||\n path.basename(dbDir) !== DEVTOOLS_DB_DIR\n ) {\n return undefined;\n }\n\n return resolvedPath;\n};\n\nexport const validateRemoteDbPath = (dbPath: unknown): string | undefined => {\n if (typeof dbPath !== 'string') {\n return undefined;\n }\n\n const normalizedPath = normalizeDevtoolsDbPath(dbPath);\n if (!normalizedPath) {\n return undefined;\n }\n\n try {\n const stats = fs.statSync(normalizedPath);\n if (!stats.isFile() || stats.size > MAX_DB_BYTES) {\n return undefined;\n }\n\n const realPath = fs.realpathSync(normalizedPath);\n return normalizeDevtoolsDbPath(realPath);\n } catch {\n return undefined;\n }\n};\n\n/**\n * Reload the database from disk.\n * Used by the viewer server to pick up changes made by the middleware/integration.\n * When a valid remote dbPath is provided (from a notify POST), reads from that\n * path instead of the local CWD-based path, so the viewer works regardless of\n * where it was started.\n */\nexport const reloadDb = async (remoteDbPath?: string): Promise<void> => {\n const validatedRemoteDbPath = validateRemoteDbPath(remoteDbPath);\n if (validatedRemoteDbPath) {\n try {\n const content = fs.readFileSync(validatedRemoteDbPath, 'utf-8');\n dbCache = JSON.parse(content);\n return;\n } catch {\n // Fall through to default\n }\n }\n dbCache = readDb();\n};\n\nexport const createRun = async (\n id: string,\n parent?: { runId: string; stepId: string },\n functionId?: string,\n): Promise<Run> => {\n const db = getDb();\n const started_at = new Date().toISOString();\n\n // Check if run already exists\n const existing = db.runs.find(r => r.id === id);\n if (existing) {\n return existing;\n }\n\n const run: Run = {\n id,\n started_at,\n parent_run_id: parent?.runId ?? null,\n parent_step_id: parent?.stepId ?? null,\n function_id: functionId ?? null,\n };\n db.runs.push(run);\n saveDb(db);\n notifyServer('run');\n return run;\n};\n\nexport const createStep = async (\n step: Omit<\n Step,\n | 'duration_ms'\n | 'output'\n | 'usage'\n | 'error'\n | 'raw_request'\n | 'raw_response'\n | 'raw_chunks'\n >,\n): Promise<void> => {\n const db = getDb();\n const newStep: Step = {\n ...step,\n duration_ms: null,\n output: null,\n usage: null,\n error: null,\n raw_request: null,\n raw_response: null,\n raw_chunks: null,\n };\n db.steps.push(newStep);\n saveDb(db);\n notifyServer('step');\n};\n\nexport const updateStepResult = async (\n stepId: string,\n result: StepResult,\n): Promise<void> => {\n const db = getDb();\n const step = db.steps.find(s => s.id === stepId);\n if (step) {\n step.duration_ms = result.duration_ms;\n step.output = result.output;\n step.usage = result.usage;\n step.error = result.error;\n step.raw_request = result.raw_request ?? null;\n step.raw_response = result.raw_response ?? null;\n step.raw_chunks = result.raw_chunks ?? null;\n saveDb(db);\n notifyServer('step-update');\n }\n};\n\nexport const getRuns = async (): Promise<Run[]> => {\n const db = getDb();\n // Return runs sorted by started_at DESC\n return [...db.runs].sort(\n (a, b) =>\n new Date(b.started_at).getTime() - new Date(a.started_at).getTime(),\n );\n};\n\nexport const getStepsForRun = async (runId: string): Promise<Step[]> => {\n const db = getDb();\n return db.steps\n .filter(s => s.run_id === runId)\n .sort((a, b) => a.step_number - b.step_number);\n};\n\nexport const getRunWithSteps = async (\n runId: string,\n): Promise<{ run: Run; steps: Step[] } | null> => {\n const db = getDb();\n const run = db.runs.find(r => r.id === runId);\n if (!run) return null;\n const steps = await getStepsForRun(runId);\n return { run, steps };\n};\n\nexport const clearDatabase = async (): Promise<void> => {\n const db: Database = { runs: [], steps: [] };\n saveDb(db);\n notifyServer('clear');\n};\n","function normalizeBinaryData(value: unknown): unknown {\n if (value instanceof ArrayBuffer) {\n return Buffer.from(value).toString('base64');\n }\n\n if (ArrayBuffer.isView(value)) {\n return Buffer.from(\n value.buffer,\n value.byteOffset,\n value.byteLength,\n ).toString('base64');\n }\n\n return value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction collectMediaBinaryValues(value: unknown): WeakSet<object> {\n const mediaBinaryValues = new WeakSet<object>();\n const visited = new WeakSet<object>();\n\n const markBinary = (candidate: unknown) => {\n if (candidate instanceof ArrayBuffer || ArrayBuffer.isView(candidate)) {\n mediaBinaryValues.add(candidate);\n }\n };\n\n const markGeneratedFile = (candidate: unknown) => {\n if (!isRecord(candidate)) return;\n\n if (Object.hasOwn(candidate, 'uint8Array')) {\n markBinary(candidate.uint8Array);\n }\n markBinary(candidate.uint8ArrayData);\n };\n\n const markDataContent = (candidate: unknown) => {\n markBinary(candidate);\n\n if (!isRecord(candidate)) return;\n\n if (candidate.type === 'data') {\n markBinary(candidate.data);\n }\n };\n\n const visit = (candidate: unknown) => {\n if (\n candidate == null ||\n typeof candidate !== 'object' ||\n candidate instanceof ArrayBuffer ||\n ArrayBuffer.isView(candidate) ||\n visited.has(candidate)\n ) {\n return;\n }\n visited.add(candidate);\n\n if (isRecord(candidate) && typeof candidate.type === 'string') {\n switch (candidate.type) {\n case 'file':\n case 'reasoning-file':\n markDataContent(candidate.data);\n markGeneratedFile(candidate);\n markGeneratedFile(candidate.file);\n break;\n case 'image':\n markDataContent(candidate.image);\n break;\n case 'media':\n case 'file-data':\n case 'image-data':\n markBinary(candidate.data);\n break;\n }\n }\n\n for (const child of Array.isArray(candidate)\n ? candidate\n : Object.values(candidate)) {\n visit(child);\n }\n };\n\n visit(value);\n return mediaBinaryValues;\n}\n\n/**\n * Serializes captured DevTools values while preserving binary values in\n * recognized media-bearing fields as base64. Unrelated binary values retain\n * their normal JSON.stringify representation.\n */\nexport function serializeForDevTools(value: unknown): string {\n const mediaBinaryValues = collectMediaBinaryValues(value);\n\n return JSON.stringify(value, function (key, serializedValue) {\n // JSON.stringify invokes toJSON before the replacer. Read the original\n // property from the holder so binary values can still be normalized while\n // preserving custom toJSON behavior for every other object.\n const originalValue = (this as Record<string, unknown>)[key];\n return originalValue != null &&\n typeof originalValue === 'object' &&\n mediaBinaryValues.has(originalValue)\n ? normalizeBinaryData(originalValue)\n : serializedValue;\n });\n}\n","import type {\n LanguageModelV4FinishReason,\n LanguageModelV4Usage,\n LanguageModelV4Middleware,\n LanguageModelV4StreamPart,\n} from '@ai-sdk/provider';\nimport {\n createRun,\n createStep,\n updateStepResult,\n notifyServerAsync,\n} from './db.js';\nimport { serializeForDevTools } from './serialize.js';\n\nconst generateId = () => crypto.randomUUID();\n\n// Track active streaming steps for cleanup on process exit\nconst activeSteps = new Map<\n string,\n {\n startTime: number;\n collectedOutput: unknown;\n request: unknown;\n fullStreamChunks: unknown[];\n rawChunks: unknown[];\n }\n>();\n\n// Handle process termination signals\nlet signalHandlersRegistered = false;\nconst registerSignalHandlers = () => {\n if (signalHandlersRegistered) return;\n signalHandlersRegistered = true;\n\n const cleanup = async () => {\n if (activeSteps.size === 0) return;\n\n const promises = Array.from(activeSteps.entries()).map(\n async ([stepId, data]) => {\n const durationMs = Date.now() - data.startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: serializeForDevTools(data.collectedOutput),\n usage: null,\n error: 'Request aborted',\n raw_request:\n data.request &&\n typeof data.request === 'object' &&\n 'body' in data.request\n ? JSON.stringify((data.request as { body: unknown }).body)\n : null,\n raw_response: JSON.stringify(data.fullStreamChunks),\n raw_chunks: JSON.stringify(data.rawChunks),\n });\n },\n );\n await Promise.all(promises);\n\n // Wait for the server notification to complete before process exits\n await notifyServerAsync('step-update');\n };\n\n process.on('SIGINT', () => {\n cleanup().then(() => process.exit(130));\n });\n\n process.on('SIGTERM', () => {\n cleanup().then(() => process.exit(143));\n });\n};\n\n/**\n * Generate a unique run ID with timestamp prefix for sorting.\n */\nconst generateRunId = (): string => {\n const now = new Date();\n const timestamp = now\n .toISOString()\n .replace(/[-:T.Z]/g, '')\n .slice(0, 17);\n const uniqueId = crypto.randomUUID().slice(0, 8);\n return `${timestamp}-${uniqueId}`;\n};\n\n/**\n * Factory function that creates a devtools middleware instance.\n * Each call generates a unique run ID, so all steps within a single\n * streamText/generateText call share the same run.\n *\n * Usage:\n * ```ts\n * const result = streamText({\n * model: wrapLanguageModel({\n * middleware: devToolsMiddleware(),\n * model: yourModel,\n * }),\n * prompt: \"...\",\n * });\n * ```\n */\nexport const devToolsMiddleware = (): LanguageModelV4Middleware => {\n if (process.env.NODE_ENV === 'production') {\n throw new Error(\n '@ai-sdk/devtools should not be used in production. ' +\n 'Remove devToolsMiddleware from your model configuration for production builds.',\n );\n }\n\n // Register signal handlers once for cleanup on process exit\n registerSignalHandlers();\n\n const runId = generateRunId();\n let runCreated = false;\n let stepCounter = 0;\n\n const ensureRunCreated = async () => {\n if (!runCreated) {\n await createRun(runId);\n runCreated = true;\n }\n };\n\n const getNextStepNumber = () => {\n stepCounter++;\n return stepCounter;\n };\n\n return {\n specificationVersion: 'v4',\n\n wrapGenerate: async ({ doGenerate, params, model }) => {\n const startTime = Date.now();\n const stepId = generateId();\n const stepNumber = getNextStepNumber();\n await ensureRunCreated();\n\n // Log step start\n await createStep({\n id: stepId,\n run_id: runId,\n step_number: stepNumber,\n type: 'generate',\n model_id: model.modelId,\n // @ts-expect-error broken type\n provider: model.config?.provider,\n started_at: new Date().toISOString(),\n input: serializeForDevTools({\n prompt: params.prompt,\n tools: params.tools,\n toolChoice: params.toolChoice,\n maxOutputTokens: params.maxOutputTokens,\n temperature: params.temperature,\n topP: params.topP,\n topK: params.topK,\n presencePenalty: params.presencePenalty,\n frequencyPenalty: params.frequencyPenalty,\n seed: params.seed,\n responseFormat: params.responseFormat,\n }),\n provider_options: params.providerOptions\n ? JSON.stringify(params.providerOptions)\n : null,\n });\n\n try {\n const result = await doGenerate();\n const durationMs = Date.now() - startTime;\n\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: serializeForDevTools({\n content: result.content,\n finishReason: result.finishReason,\n response: result.response,\n }),\n usage: result.usage ? JSON.stringify(result.usage) : null,\n error: null,\n raw_request: result.request?.body\n ? JSON.stringify(result.request.body)\n : null,\n raw_response: result.response?.body\n ? JSON.stringify(result.response.body)\n : null,\n });\n\n return result;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: null,\n usage: null,\n error: error instanceof Error ? error.message : String(error),\n raw_request: null,\n raw_response: null,\n });\n throw error;\n }\n },\n\n wrapStream: async ({ doStream, params, model }) => {\n const startTime = Date.now();\n const stepId = generateId();\n const stepNumber = getNextStepNumber();\n await ensureRunCreated();\n\n // Store original setting before overriding\n const userRequestedRawChunks = params.includeRawChunks === true;\n params.includeRawChunks = true;\n\n // Log step start\n await createStep({\n id: stepId,\n run_id: runId,\n step_number: stepNumber,\n type: 'stream',\n model_id: model.modelId,\n // @ts-expect-error broken type\n provider: model.config?.provider,\n started_at: new Date().toISOString(),\n input: serializeForDevTools({\n prompt: params.prompt,\n tools: params.tools,\n toolChoice: params.toolChoice,\n maxOutputTokens: params.maxOutputTokens,\n temperature: params.temperature,\n topP: params.topP,\n topK: params.topK,\n presencePenalty: params.presencePenalty,\n frequencyPenalty: params.frequencyPenalty,\n seed: params.seed,\n responseFormat: params.responseFormat,\n }),\n provider_options: params.providerOptions\n ? JSON.stringify(params.providerOptions)\n : null,\n });\n\n try {\n const { stream, request, response, ...rest } = await doStream();\n\n // Collect stream output for logging\n const collectedOutput: {\n textParts: Array<{ id: string; text: string }>;\n reasoningParts: Array<{ id: string; text: string }>;\n toolCalls: LanguageModelV4StreamPart[];\n content?: LanguageModelV4StreamPart[];\n finishReason?: LanguageModelV4FinishReason;\n usage?: LanguageModelV4Usage;\n } = {\n textParts: [],\n reasoningParts: [],\n toolCalls: [],\n };\n\n const currentText: Map<string, string> = new Map();\n const currentReasoning: Map<string, string> = new Map();\n const fullStreamChunks: LanguageModelV4StreamPart[] = [];\n const rawChunks: unknown[] = [];\n\n // Track this step for cleanup on process exit\n activeSteps.set(stepId, {\n startTime,\n collectedOutput,\n request,\n fullStreamChunks,\n rawChunks,\n });\n\n const transformStream = new TransformStream<\n LanguageModelV4StreamPart,\n LanguageModelV4StreamPart\n >({\n transform(chunk, controller) {\n // Separate raw provider chunks from other stream chunks\n if (chunk.type === 'raw') {\n // Store just the unwrapped rawValue for cleaner data\n rawChunks.push(chunk.rawValue);\n // Only pass raw chunks through if user originally requested them\n if (userRequestedRawChunks) {\n controller.enqueue(chunk);\n }\n return;\n }\n\n // Collect all non-raw chunks for full stream logging\n fullStreamChunks.push(chunk);\n\n // Collect relevant data from stream\n switch (chunk.type) {\n case 'text-start':\n currentText.set(chunk.id, '');\n break;\n case 'text-delta':\n currentText.set(\n chunk.id,\n (currentText.get(chunk.id) ?? '') + chunk.delta,\n );\n break;\n case 'text-end':\n collectedOutput.textParts.push({\n id: chunk.id,\n text: currentText.get(chunk.id) ?? '',\n });\n break;\n case 'reasoning-start':\n currentReasoning.set(chunk.id, '');\n break;\n case 'reasoning-delta':\n currentReasoning.set(\n chunk.id,\n (currentReasoning.get(chunk.id) ?? '') + chunk.delta,\n );\n break;\n case 'reasoning-end':\n collectedOutput.reasoningParts.push({\n id: chunk.id,\n text: currentReasoning.get(chunk.id) ?? '',\n });\n break;\n case 'tool-call':\n collectedOutput.toolCalls.push(chunk);\n break;\n case 'file':\n case 'reasoning-file':\n case 'tool-result':\n (collectedOutput.content ??= []).push(chunk);\n break;\n case 'finish':\n collectedOutput.finishReason = chunk.finishReason;\n collectedOutput.usage = chunk.usage;\n break;\n }\n\n controller.enqueue(chunk);\n },\n\n async flush() {\n // Remove from active tracking - stream completed normally\n activeSteps.delete(stepId);\n\n const durationMs = Date.now() - startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: serializeForDevTools(collectedOutput),\n usage: collectedOutput.usage\n ? JSON.stringify(collectedOutput.usage)\n : null,\n error: null,\n raw_request: request?.body ? JSON.stringify(request.body) : null,\n raw_response: JSON.stringify(fullStreamChunks),\n raw_chunks: JSON.stringify(rawChunks),\n });\n },\n\n // @ts-expect-error - cancel is valid per WHATWG Streams spec but missing from TS types\n async cancel() {\n // Remove from active tracking - stream was cancelled\n activeSteps.delete(stepId);\n\n const durationMs = Date.now() - startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: serializeForDevTools(collectedOutput),\n usage: collectedOutput.usage\n ? JSON.stringify(collectedOutput.usage)\n : null,\n error: 'Request aborted',\n raw_request: request?.body ? JSON.stringify(request.body) : null,\n raw_response: JSON.stringify(fullStreamChunks),\n raw_chunks: JSON.stringify(rawChunks),\n });\n },\n });\n\n return {\n stream: stream.pipeThrough(transformStream),\n request,\n response,\n ...rest,\n };\n } catch (error) {\n activeSteps.delete(stepId);\n\n const durationMs = Date.now() - startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: null,\n usage: null,\n error: error instanceof Error ? error.message : String(error),\n raw_request: null,\n raw_response: null,\n raw_chunks: null,\n });\n throw error;\n }\n },\n };\n};\n","import type {\n GenerateTextStartEvent,\n GenerateTextStepStartEvent,\n GenerateTextStepEndEvent,\n GenerateObjectStartEvent,\n GenerateObjectStepStartEvent,\n GenerateObjectStepEndEvent,\n Telemetry,\n ToolSet,\n} from 'ai';\nimport {\n createRun,\n createStep,\n getStepsForRun,\n updateStepResult,\n notifyServerAsync,\n} from './db.js';\nimport { serializeForDevTools } from './serialize.js';\n\ntype OperationType = 'generate' | 'stream';\n\ninterface StepState {\n stepId: string;\n startTime: number;\n}\n\ninterface CallState {\n runId: string;\n operationType: OperationType;\n functionId: string | undefined;\n settings: Record<string, unknown>;\n stepStates: Map<number, StepState>;\n stepNumberOffset: number;\n}\n\nexport interface DevToolsTelemetryOptions {\n /**\n * Identifier used to group multiple AI SDK calls into one DevTools run.\n * Reuse the same value when resuming an interrupted interaction.\n */\n runId?: string;\n}\n\nconst activeSteps = new Map<string, StepState>();\n\nlet signalHandlersRegistered = false;\nconst registerSignalHandlers = () => {\n if (signalHandlersRegistered) return;\n signalHandlersRegistered = true;\n\n const cleanup = async () => {\n if (activeSteps.size === 0) return;\n\n const promises = Array.from(activeSteps.entries()).map(\n async ([stepId, data]) => {\n const durationMs = Date.now() - data.startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: null,\n usage: null,\n error: 'Request aborted',\n raw_request: null,\n raw_response: null,\n raw_chunks: null,\n });\n },\n );\n await Promise.all(promises);\n await notifyServerAsync('step-update');\n };\n\n process.on('SIGINT', () => {\n cleanup().then(() => process.exit(130));\n });\n\n process.on('SIGTERM', () => {\n cleanup().then(() => process.exit(143));\n });\n};\n\nconst generateRunId = (): string => {\n const now = new Date();\n const timestamp = now\n .toISOString()\n .replace(/[-:T.Z]/g, '')\n .slice(0, 17);\n const uniqueId = crypto.randomUUID().slice(0, 8);\n return `${timestamp}-${uniqueId}`;\n};\n\nfunction getOperationType(operationId: string): OperationType {\n if (operationId === 'ai.streamText' || operationId === 'ai.streamObject') {\n return 'stream';\n }\n return 'generate';\n}\n\n/**\n * Creates a devtools telemetry integration that logs all AI SDK operations\n * to the devtools viewer.\n *\n * Usage:\n * ```ts\n * import { registerTelemetry } from 'ai';\n * import { DevToolsTelemetry } from '@ai-sdk/devtools';\n *\n * registerTelemetry(DevToolsTelemetry());\n * ```\n *\n * Telemetry is enabled by default — no need to set `telemetry`\n * unless you want to configure `functionId`, `recordInputs`, or `recordOutputs`.\n */\nexport function DevToolsTelemetry(\n options: DevToolsTelemetryOptions = {},\n): Telemetry {\n if (process.env.NODE_ENV === 'production') {\n throw new Error(\n '@ai-sdk/devtools should not be used in production. ' +\n 'Remove DevToolsTelemetry from your telemetry configuration for production builds.',\n );\n }\n\n registerSignalHandlers();\n\n const callStates = new Map<string, CallState>();\n\n // When executeTool runs a tool's execute function, any nested generateText/\n // streamText call inside that tool gets its own callId. We track the nesting\n // so that the inner call's run can be linked to the parent.\n //\n // We use a per-toolCallId Map instead of a single variable so that parallel\n // tool calls\n const toolContextMap = new Map<\n string,\n { parentCallId: string; parentToolCallId: string }\n >();\n let currentToolCallId: string | null = null;\n\n function resolveParentInfo(): { runId: string; stepId: string } | undefined {\n if (!currentToolCallId) return undefined;\n\n const toolCallContext = toolContextMap.get(currentToolCallId);\n if (!toolCallContext) return undefined;\n\n const parentState = callStates.get(toolCallContext.parentCallId);\n if (!parentState) return undefined;\n\n // Find the step that is currently executing the tool call.\n // This is the most recent (highest step number) step in the parent call.\n let latestStepId: string | undefined;\n let latestStepNumber = -1;\n for (const [stepNumber, stepState] of parentState.stepStates) {\n if (stepNumber > latestStepNumber) {\n latestStepNumber = stepNumber;\n latestStepId = stepState.stepId;\n }\n }\n\n if (!latestStepId) return undefined;\n\n return { runId: parentState.runId, stepId: latestStepId };\n }\n\n function getOrCreateCallState(\n callId: string,\n operationId: string,\n event: {\n functionId?: string | undefined;\n maxOutputTokens?: number | undefined;\n temperature?: number | undefined;\n topP?: number | undefined;\n topK?: number | undefined;\n presencePenalty?: number | undefined;\n frequencyPenalty?: number | undefined;\n seed?: number | undefined;\n },\n ): CallState {\n let state = callStates.get(callId);\n if (state) return state;\n\n state = {\n runId: generateRunId(),\n operationType: getOperationType(operationId),\n functionId: event.functionId,\n settings: {\n maxOutputTokens: event.maxOutputTokens,\n temperature: event.temperature,\n topP: event.topP,\n topK: event.topK,\n presencePenalty: event.presencePenalty,\n frequencyPenalty: event.frequencyPenalty,\n seed: event.seed,\n },\n stepStates: new Map(),\n stepNumberOffset: 0,\n };\n callStates.set(callId, state);\n return state;\n }\n\n const integration: Telemetry = {\n onStart: async event => {\n const operationId = (event as { operationId: string }).operationId;\n\n if (\n operationId === 'ai.embed' ||\n operationId === 'ai.embedMany' ||\n operationId === 'ai.rerank' ||\n operationId === 'ai.generateSpeech' ||\n operationId === 'ai.transcribe'\n ) {\n return;\n }\n\n const startEvent = event as (\n | GenerateTextStartEvent<ToolSet>\n | GenerateObjectStartEvent\n ) & {\n functionId?: string | undefined;\n };\n\n const parentInfo = resolveParentInfo();\n\n const state = getOrCreateCallState(\n startEvent.callId,\n operationId,\n startEvent,\n );\n\n if (options.runId != null) {\n state.runId = options.runId;\n state.stepNumberOffset = (await getStepsForRun(options.runId)).length;\n }\n\n await createRun(state.runId, parentInfo, state.functionId);\n },\n\n onStepStart: async event => {\n const stepStartEvent = event as GenerateTextStepStartEvent<ToolSet> & {\n promptMessages?: unknown[];\n };\n\n const state = callStates.get(stepStartEvent.callId);\n if (!state) return;\n\n const stepId = crypto.randomUUID();\n const startTime = Date.now();\n\n const stepState: StepState = {\n stepId,\n startTime,\n };\n const stepNumber = stepStartEvent.steps.length;\n state.stepStates.set(stepNumber, stepState);\n activeSteps.set(stepId, stepState);\n\n const prompt = stepStartEvent.promptMessages ?? stepStartEvent.messages;\n\n await createStep({\n id: stepId,\n run_id: state.runId,\n step_number: state.stepNumberOffset + stepNumber + 1,\n type: state.operationType,\n model_id: stepStartEvent.modelId,\n provider: stepStartEvent.provider ?? null,\n started_at: new Date().toISOString(),\n input: serializeForDevTools({\n prompt,\n tools: stepStartEvent.tools\n ? Object.entries(stepStartEvent.tools).map(([name, tool]) => ({\n name,\n description: (tool as { description?: string }).description,\n parameters: (tool as { parameters?: unknown }).parameters,\n }))\n : undefined,\n toolChoice: stepStartEvent.toolChoice,\n maxOutputTokens: state.settings.maxOutputTokens,\n temperature: state.settings.temperature,\n topP: state.settings.topP,\n topK: state.settings.topK,\n presencePenalty: state.settings.presencePenalty,\n frequencyPenalty: state.settings.frequencyPenalty,\n seed: state.settings.seed,\n }),\n provider_options: stepStartEvent.providerOptions\n ? JSON.stringify(stepStartEvent.providerOptions)\n : null,\n });\n },\n\n onObjectStepStart: async event => {\n const stepStartEvent = event as GenerateObjectStepStartEvent & {\n promptMessages?: unknown[];\n };\n\n const state = callStates.get(stepStartEvent.callId);\n if (!state) return;\n\n const stepId = crypto.randomUUID();\n const startTime = Date.now();\n\n const stepState: StepState = {\n stepId,\n startTime,\n };\n state.stepStates.set(stepStartEvent.stepNumber, stepState);\n activeSteps.set(stepId, stepState);\n\n await createStep({\n id: stepId,\n run_id: state.runId,\n step_number: state.stepNumberOffset + stepStartEvent.stepNumber + 1,\n type: state.operationType,\n model_id: stepStartEvent.modelId,\n provider: stepStartEvent.provider ?? null,\n started_at: new Date().toISOString(),\n input: serializeForDevTools({\n prompt: stepStartEvent.promptMessages,\n maxOutputTokens: state.settings.maxOutputTokens,\n temperature: state.settings.temperature,\n topP: state.settings.topP,\n topK: state.settings.topK,\n presencePenalty: state.settings.presencePenalty,\n frequencyPenalty: state.settings.frequencyPenalty,\n seed: state.settings.seed,\n }),\n provider_options: stepStartEvent.providerOptions\n ? JSON.stringify(stepStartEvent.providerOptions)\n : null,\n });\n },\n\n onStepEnd: async event => {\n const stepResult = event as GenerateTextStepEndEvent<ToolSet>;\n\n const state = callStates.get(stepResult.callId);\n if (!state) return;\n\n const stepState = state.stepStates.get(stepResult.stepNumber);\n if (!stepState) return;\n\n activeSteps.delete(stepState.stepId);\n\n const durationMs = Date.now() - stepState.startTime;\n\n const output = {\n content: stepResult.content,\n finishReason: stepResult.finishReason,\n response: {\n id: stepResult.response.id,\n modelId: stepResult.response.modelId,\n timestamp: stepResult.response.timestamp,\n messages: stepResult.response.messages,\n },\n };\n\n await updateStepResult(stepState.stepId, {\n duration_ms: durationMs,\n output: serializeForDevTools(output),\n usage: stepResult.usage ? JSON.stringify(stepResult.usage) : null,\n error: null,\n raw_request: stepResult.request?.body\n ? JSON.stringify(stepResult.request.body)\n : null,\n raw_response: stepResult.response?.body\n ? JSON.stringify(stepResult.response.body)\n : null,\n raw_chunks: null,\n });\n\n state.stepStates.delete(stepResult.stepNumber);\n },\n\n onObjectStepEnd: async event => {\n const stepResult = event as GenerateObjectStepEndEvent;\n\n const state = callStates.get(stepResult.callId);\n if (!state) return;\n\n const stepState = state.stepStates.get(stepResult.stepNumber);\n if (!stepState) return;\n\n activeSteps.delete(stepState.stepId);\n\n const durationMs = Date.now() - stepState.startTime;\n\n const output = {\n finishReason: stepResult.finishReason,\n objectText: stepResult.objectText,\n response: {\n id: stepResult.response.id,\n modelId: stepResult.response.modelId,\n timestamp: stepResult.response.timestamp,\n },\n };\n\n await updateStepResult(stepState.stepId, {\n duration_ms: durationMs,\n output: JSON.stringify(output),\n usage: stepResult.usage ? JSON.stringify(stepResult.usage) : null,\n error: null,\n raw_request: stepResult.request?.body\n ? JSON.stringify(stepResult.request.body)\n : null,\n raw_response: stepResult.response?.body\n ? JSON.stringify(stepResult.response.body)\n : null,\n });\n\n state.stepStates.delete(stepResult.stepNumber);\n },\n\n onEnd: async event => {\n const endEvent = event as { callId: string };\n callStates.delete(endEvent.callId);\n },\n\n onError: async error => {\n const errorObj = error as\n | { callId?: string; error?: unknown }\n | undefined;\n const callId = errorObj?.callId;\n if (!callId) return;\n\n const state = callStates.get(callId);\n if (!state) return;\n\n const cause = errorObj?.error ?? error;\n const errorMessage =\n cause instanceof Error ? cause.message : String(cause);\n\n for (const [, stepState] of state.stepStates) {\n activeSteps.delete(stepState.stepId);\n const durationMs = Date.now() - stepState.startTime;\n await updateStepResult(stepState.stepId, {\n duration_ms: durationMs,\n output: null,\n usage: null,\n error: errorMessage,\n raw_request: null,\n raw_response: null,\n raw_chunks: null,\n });\n }\n\n callStates.delete(callId);\n },\n\n executeTool: async ({ callId, toolCallId, execute }) => {\n toolContextMap.set(toolCallId, {\n parentCallId: callId,\n parentToolCallId: toolCallId,\n });\n\n const previousToolCallId = currentToolCallId;\n currentToolCallId = toolCallId;\n\n try {\n return await execute();\n } finally {\n currentToolCallId = previousToolCallId;\n toolContextMap.delete(toolCallId);\n }\n },\n };\n\n return integration;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["activeSteps","signalHandlersRegistered","registerSignalHandlers","generateRunId"],"sources":["../src/db.ts","../src/serialize.ts","../src/middleware.ts","../src/integration.ts"],"sourcesContent":["import path from 'node:path';\nimport fs from 'node:fs';\n\nconst DEVTOOLS_DB_DIR = '.devtools';\nconst DEVTOOLS_DB_FILE = 'generations.json';\n// Cap how many bytes we read from a remote database file. Guards against a\n// synchronous hang / OOM if the file is enormous.\nconst MAX_DB_BYTES = 100 * 1024 * 1024; // 100 MB\nconst DB_DIR = path.join(process.cwd(), DEVTOOLS_DB_DIR);\nconst DB_PATH = path.join(DB_DIR, DEVTOOLS_DB_FILE);\nconst DEVTOOLS_PORT = process.env.AI_SDK_DEVTOOLS_PORT\n ? parseInt(process.env.AI_SDK_DEVTOOLS_PORT)\n : 4983;\n\n/**\n * Notify the devtools server that data has changed.\n * Fire-and-forget: doesn't block, ignores errors if server isn't running.\n */\nconst notifyServer = (event: 'run' | 'step' | 'step-update' | 'clear') => {\n notifyServerAsync(event);\n};\n\n/**\n * Notify the devtools server and wait for the request to complete.\n * Used during process cleanup to ensure notifications are sent before exit.\n */\nexport const notifyServerAsync = async (\n event: 'run' | 'step' | 'step-update' | 'clear',\n): Promise<void> => {\n try {\n await fetch(`http://localhost:${DEVTOOLS_PORT}/api/notify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ event, timestamp: Date.now(), dbPath: DB_PATH }),\n });\n } catch {\n // Ignore errors - server might not be running\n }\n};\n\nexport interface Run {\n id: string;\n started_at: string;\n parent_run_id: string | null;\n parent_step_id: string | null;\n function_id: string | null;\n}\n\nexport interface Step {\n id: string;\n run_id: string;\n step_number: number;\n type: 'generate' | 'stream';\n model_id: string;\n provider: string | null;\n started_at: string;\n duration_ms: number | null;\n input: string;\n output: string | null;\n usage: string | null;\n error: string | null;\n raw_request: string | null;\n raw_response: string | null;\n raw_chunks: string | null;\n provider_options: string | null;\n}\n\nexport interface StepResult {\n duration_ms: number;\n output: string | null;\n usage: string | null;\n error: string | null;\n raw_request?: string | null;\n raw_response?: string | null;\n raw_chunks?: string | null;\n}\n\ninterface Database {\n runs: Run[];\n steps: Step[];\n}\n\n/**\n * Ensure .devtools is in .gitignore.\n * Only writes if .gitignore exists and doesn't already contain .devtools.\n */\nconst ensureGitignore = (): void => {\n const gitignorePath = path.join(process.cwd(), '.gitignore');\n\n if (!fs.existsSync(gitignorePath)) {\n return;\n }\n\n const content = fs.readFileSync(gitignorePath, 'utf-8');\n const lines = content.split('\\n');\n\n // Check if .devtools is already ignored (exact match or with trailing slash)\n const alreadyIgnored = lines.some(\n line => line.trim() === '.devtools' || line.trim() === '.devtools/',\n );\n\n if (!alreadyIgnored) {\n const newContent = content.endsWith('\\n')\n ? `${content}.devtools\\n`\n : `${content}\\n.devtools\\n`;\n fs.writeFileSync(gitignorePath, newContent);\n }\n};\n\nconst readDb = (): Database => {\n try {\n if (fs.existsSync(DB_PATH)) {\n const content = fs.readFileSync(DB_PATH, 'utf-8');\n return JSON.parse(content);\n }\n } catch {\n // If file is corrupted, start fresh\n }\n return { runs: [], steps: [] };\n};\n\nconst writeDb = (db: Database): void => {\n const isFirstRun = !fs.existsSync(DB_DIR);\n\n if (isFirstRun) {\n fs.mkdirSync(DB_DIR, { recursive: true });\n ensureGitignore();\n }\n\n fs.writeFileSync(DB_PATH, JSON.stringify(db, null, 2));\n};\n\n// In-memory cache for performance\nlet dbCache: Database | null = null;\n\nconst getDb = (): Database => {\n if (!dbCache) {\n dbCache = readDb();\n }\n return dbCache;\n};\n\nconst saveDb = (db: Database): void => {\n dbCache = db;\n writeDb(db);\n};\n\nconst normalizeDevtoolsDbPath = (dbPath: string): string | undefined => {\n const resolvedPath = path.resolve(dbPath);\n const dbDir = path.dirname(resolvedPath);\n\n if (\n path.basename(resolvedPath) !== DEVTOOLS_DB_FILE ||\n path.basename(dbDir) !== DEVTOOLS_DB_DIR\n ) {\n return undefined;\n }\n\n return resolvedPath;\n};\n\nexport const validateRemoteDbPath = (dbPath: unknown): string | undefined => {\n if (typeof dbPath !== 'string') {\n return undefined;\n }\n\n const normalizedPath = normalizeDevtoolsDbPath(dbPath);\n if (!normalizedPath) {\n return undefined;\n }\n\n try {\n const stats = fs.statSync(normalizedPath);\n if (!stats.isFile() || stats.size > MAX_DB_BYTES) {\n return undefined;\n }\n\n const realPath = fs.realpathSync(normalizedPath);\n return normalizeDevtoolsDbPath(realPath);\n } catch {\n return undefined;\n }\n};\n\n/**\n * Reload the database from disk.\n * Used by the viewer server to pick up changes made by the middleware/integration.\n * When a valid remote dbPath is provided (from a notify POST), reads from that\n * path instead of the local CWD-based path, so the viewer works regardless of\n * where it was started.\n */\nexport const reloadDb = async (remoteDbPath?: string): Promise<void> => {\n const validatedRemoteDbPath = validateRemoteDbPath(remoteDbPath);\n if (validatedRemoteDbPath) {\n try {\n const content = fs.readFileSync(validatedRemoteDbPath, 'utf-8');\n dbCache = JSON.parse(content);\n return;\n } catch {\n // Fall through to default\n }\n }\n dbCache = readDb();\n};\n\nexport const createRun = async (\n id: string,\n parent?: { runId: string; stepId: string },\n functionId?: string,\n): Promise<Run> => {\n const db = getDb();\n const started_at = new Date().toISOString();\n\n // Check if run already exists\n const existing = db.runs.find(r => r.id === id);\n if (existing) {\n return existing;\n }\n\n const run: Run = {\n id,\n started_at,\n parent_run_id: parent?.runId ?? null,\n parent_step_id: parent?.stepId ?? null,\n function_id: functionId ?? null,\n };\n db.runs.push(run);\n saveDb(db);\n notifyServer('run');\n return run;\n};\n\nexport const createStep = async (\n step: Omit<\n Step,\n | 'duration_ms'\n | 'output'\n | 'usage'\n | 'error'\n | 'raw_request'\n | 'raw_response'\n | 'raw_chunks'\n >,\n): Promise<void> => {\n const db = getDb();\n const newStep: Step = {\n ...step,\n duration_ms: null,\n output: null,\n usage: null,\n error: null,\n raw_request: null,\n raw_response: null,\n raw_chunks: null,\n };\n db.steps.push(newStep);\n saveDb(db);\n notifyServer('step');\n};\n\nexport const updateStepResult = async (\n stepId: string,\n result: StepResult,\n): Promise<void> => {\n const db = getDb();\n const step = db.steps.find(s => s.id === stepId);\n if (step) {\n step.duration_ms = result.duration_ms;\n step.output = result.output;\n step.usage = result.usage;\n step.error = result.error;\n step.raw_request = result.raw_request ?? null;\n step.raw_response = result.raw_response ?? null;\n step.raw_chunks = result.raw_chunks ?? null;\n saveDb(db);\n notifyServer('step-update');\n }\n};\n\nexport const getRuns = async (): Promise<Run[]> => {\n const db = getDb();\n // Return runs sorted by started_at DESC\n return [...db.runs].sort(\n (a, b) =>\n new Date(b.started_at).getTime() - new Date(a.started_at).getTime(),\n );\n};\n\nexport const getStepsForRun = async (runId: string): Promise<Step[]> => {\n const db = getDb();\n return db.steps\n .filter(s => s.run_id === runId)\n .sort((a, b) => a.step_number - b.step_number);\n};\n\nexport const getRunWithSteps = async (\n runId: string,\n): Promise<{ run: Run; steps: Step[] } | null> => {\n const db = getDb();\n const run = db.runs.find(r => r.id === runId);\n if (!run) return null;\n const steps = await getStepsForRun(runId);\n return { run, steps };\n};\n\nexport const clearDatabase = async (): Promise<void> => {\n const db: Database = { runs: [], steps: [] };\n saveDb(db);\n notifyServer('clear');\n};\n","function normalizeBinaryData(value: unknown): unknown {\n if (value instanceof ArrayBuffer) {\n return Buffer.from(value).toString('base64');\n }\n\n if (ArrayBuffer.isView(value)) {\n return Buffer.from(\n value.buffer,\n value.byteOffset,\n value.byteLength,\n ).toString('base64');\n }\n\n return value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction collectMediaBinaryValues(value: unknown): WeakSet<object> {\n const mediaBinaryValues = new WeakSet<object>();\n const visited = new WeakSet<object>();\n\n const markBinary = (candidate: unknown) => {\n if (candidate instanceof ArrayBuffer || ArrayBuffer.isView(candidate)) {\n mediaBinaryValues.add(candidate);\n }\n };\n\n const markGeneratedFile = (candidate: unknown) => {\n if (!isRecord(candidate)) return;\n\n if (Object.hasOwn(candidate, 'uint8Array')) {\n markBinary(candidate.uint8Array);\n }\n markBinary(candidate.uint8ArrayData);\n };\n\n const markDataContent = (candidate: unknown) => {\n markBinary(candidate);\n\n if (!isRecord(candidate)) return;\n\n if (candidate.type === 'data') {\n markBinary(candidate.data);\n }\n };\n\n const visit = (candidate: unknown) => {\n if (\n candidate == null ||\n typeof candidate !== 'object' ||\n candidate instanceof ArrayBuffer ||\n ArrayBuffer.isView(candidate) ||\n visited.has(candidate)\n ) {\n return;\n }\n visited.add(candidate);\n\n if (isRecord(candidate) && typeof candidate.type === 'string') {\n switch (candidate.type) {\n case 'file':\n case 'reasoning-file':\n markDataContent(candidate.data);\n markGeneratedFile(candidate);\n markGeneratedFile(candidate.file);\n break;\n case 'image':\n markDataContent(candidate.image);\n break;\n case 'media':\n case 'file-data':\n case 'image-data':\n markBinary(candidate.data);\n break;\n }\n }\n\n for (const child of Array.isArray(candidate)\n ? candidate\n : Object.values(candidate)) {\n visit(child);\n }\n };\n\n visit(value);\n return mediaBinaryValues;\n}\n\n/**\n * Serializes captured DevTools values while preserving binary values in\n * recognized media-bearing fields as base64. Unrelated binary values retain\n * their normal JSON.stringify representation.\n */\nexport function serializeForDevTools(value: unknown): string {\n const mediaBinaryValues = collectMediaBinaryValues(value);\n\n return JSON.stringify(value, function (key, serializedValue) {\n // JSON.stringify invokes toJSON before the replacer. Read the original\n // property from the holder so binary values can still be normalized while\n // preserving custom toJSON behavior for every other object.\n const originalValue = (this as Record<string, unknown>)[key];\n return originalValue != null &&\n typeof originalValue === 'object' &&\n mediaBinaryValues.has(originalValue)\n ? normalizeBinaryData(originalValue)\n : serializedValue;\n });\n}\n","import type {\n LanguageModelV4FinishReason,\n LanguageModelV4Usage,\n LanguageModelV4Middleware,\n LanguageModelV4StreamPart,\n} from '@ai-sdk/provider';\nimport {\n createRun,\n createStep,\n updateStepResult,\n notifyServerAsync,\n} from './db.js';\nimport { serializeForDevTools } from './serialize.js';\n\nconst generateId = () => crypto.randomUUID();\n\n// Track active streaming steps for cleanup on process exit\nconst activeSteps = new Map<\n string,\n {\n startTime: number;\n collectedOutput: unknown;\n request: unknown;\n fullStreamChunks: unknown[];\n rawChunks: unknown[];\n }\n>();\n\n// Handle process termination signals\nlet signalHandlersRegistered = false;\nconst registerSignalHandlers = () => {\n if (signalHandlersRegistered) return;\n signalHandlersRegistered = true;\n\n const cleanup = async () => {\n if (activeSteps.size === 0) return;\n\n const promises = Array.from(activeSteps.entries()).map(\n async ([stepId, data]) => {\n const durationMs = Date.now() - data.startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: serializeForDevTools(data.collectedOutput),\n usage: null,\n error: 'Request aborted',\n raw_request:\n data.request &&\n typeof data.request === 'object' &&\n 'body' in data.request\n ? JSON.stringify((data.request as { body: unknown }).body)\n : null,\n raw_response: JSON.stringify(data.fullStreamChunks),\n raw_chunks: JSON.stringify(data.rawChunks),\n });\n },\n );\n await Promise.all(promises);\n\n // Wait for the server notification to complete before process exits\n await notifyServerAsync('step-update');\n };\n\n process.on('SIGINT', () => {\n cleanup().then(() => process.exit(130));\n });\n\n process.on('SIGTERM', () => {\n cleanup().then(() => process.exit(143));\n });\n};\n\n/**\n * Generate a unique run ID with timestamp prefix for sorting.\n */\nconst generateRunId = (): string => {\n const now = new Date();\n const timestamp = now\n .toISOString()\n .replace(/[-:T.Z]/g, '')\n .slice(0, 17);\n const uniqueId = crypto.randomUUID().slice(0, 8);\n return `${timestamp}-${uniqueId}`;\n};\n\n/**\n * Factory function that creates a devtools middleware instance.\n * Each call generates a unique run ID, so all steps within a single\n * streamText/generateText call share the same run.\n *\n * Usage:\n * ```ts\n * const result = streamText({\n * model: wrapLanguageModel({\n * middleware: devToolsMiddleware(),\n * model: yourModel,\n * }),\n * prompt: \"...\",\n * });\n * ```\n */\nexport const devToolsMiddleware = (): LanguageModelV4Middleware => {\n if (process.env.NODE_ENV === 'production') {\n throw new Error(\n '@ai-sdk/devtools should not be used in production. ' +\n 'Remove devToolsMiddleware from your model configuration for production builds.',\n );\n }\n\n // Register signal handlers once for cleanup on process exit\n registerSignalHandlers();\n\n const runId = generateRunId();\n let runCreated = false;\n let stepCounter = 0;\n\n const ensureRunCreated = async () => {\n if (!runCreated) {\n await createRun(runId);\n runCreated = true;\n }\n };\n\n const getNextStepNumber = () => {\n stepCounter++;\n return stepCounter;\n };\n\n return {\n specificationVersion: 'v4',\n\n wrapGenerate: async ({ doGenerate, params, model }) => {\n const startTime = Date.now();\n const stepId = generateId();\n const stepNumber = getNextStepNumber();\n await ensureRunCreated();\n\n // Log step start\n await createStep({\n id: stepId,\n run_id: runId,\n step_number: stepNumber,\n type: 'generate',\n model_id: model.modelId,\n // @ts-expect-error broken type\n provider: model.config?.provider,\n started_at: new Date().toISOString(),\n input: serializeForDevTools({\n prompt: params.prompt,\n tools: params.tools,\n toolChoice: params.toolChoice,\n maxOutputTokens: params.maxOutputTokens,\n temperature: params.temperature,\n topP: params.topP,\n topK: params.topK,\n presencePenalty: params.presencePenalty,\n frequencyPenalty: params.frequencyPenalty,\n seed: params.seed,\n responseFormat: params.responseFormat,\n }),\n provider_options: params.providerOptions\n ? JSON.stringify(params.providerOptions)\n : null,\n });\n\n try {\n const result = await doGenerate();\n const durationMs = Date.now() - startTime;\n\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: serializeForDevTools({\n content: result.content,\n finishReason: result.finishReason,\n response: result.response,\n }),\n usage: result.usage ? JSON.stringify(result.usage) : null,\n error: null,\n raw_request: result.request?.body\n ? JSON.stringify(result.request.body)\n : null,\n raw_response: result.response?.body\n ? JSON.stringify(result.response.body)\n : null,\n });\n\n return result;\n } catch (error) {\n const durationMs = Date.now() - startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: null,\n usage: null,\n error: error instanceof Error ? error.message : String(error),\n raw_request: null,\n raw_response: null,\n });\n throw error;\n }\n },\n\n wrapStream: async ({ doStream, params, model }) => {\n const startTime = Date.now();\n const stepId = generateId();\n const stepNumber = getNextStepNumber();\n await ensureRunCreated();\n\n // Store original setting before overriding\n const userRequestedRawChunks = params.includeRawChunks === true;\n params.includeRawChunks = true;\n\n // Log step start\n await createStep({\n id: stepId,\n run_id: runId,\n step_number: stepNumber,\n type: 'stream',\n model_id: model.modelId,\n // @ts-expect-error broken type\n provider: model.config?.provider,\n started_at: new Date().toISOString(),\n input: serializeForDevTools({\n prompt: params.prompt,\n tools: params.tools,\n toolChoice: params.toolChoice,\n maxOutputTokens: params.maxOutputTokens,\n temperature: params.temperature,\n topP: params.topP,\n topK: params.topK,\n presencePenalty: params.presencePenalty,\n frequencyPenalty: params.frequencyPenalty,\n seed: params.seed,\n responseFormat: params.responseFormat,\n }),\n provider_options: params.providerOptions\n ? JSON.stringify(params.providerOptions)\n : null,\n });\n\n try {\n const { stream, request, response, ...rest } = await doStream();\n\n // Collect stream output for logging\n const collectedOutput: {\n textParts: Array<{ id: string; text: string }>;\n reasoningParts: Array<{ id: string; text: string }>;\n toolCalls: LanguageModelV4StreamPart[];\n content?: LanguageModelV4StreamPart[];\n finishReason?: LanguageModelV4FinishReason;\n usage?: LanguageModelV4Usage;\n } = {\n textParts: [],\n reasoningParts: [],\n toolCalls: [],\n };\n\n const currentText: Map<string, string> = new Map();\n const currentReasoning: Map<string, string> = new Map();\n const fullStreamChunks: LanguageModelV4StreamPart[] = [];\n const rawChunks: unknown[] = [];\n\n // Track this step for cleanup on process exit\n activeSteps.set(stepId, {\n startTime,\n collectedOutput,\n request,\n fullStreamChunks,\n rawChunks,\n });\n\n const transformStream = new TransformStream<\n LanguageModelV4StreamPart,\n LanguageModelV4StreamPart\n >({\n transform(chunk, controller) {\n // Separate raw provider chunks from other stream chunks\n if (chunk.type === 'raw') {\n // Store just the unwrapped rawValue for cleaner data\n rawChunks.push(chunk.rawValue);\n // Only pass raw chunks through if user originally requested them\n if (userRequestedRawChunks) {\n controller.enqueue(chunk);\n }\n return;\n }\n\n // Collect all non-raw chunks for full stream logging\n fullStreamChunks.push(chunk);\n\n // Collect relevant data from stream\n switch (chunk.type) {\n case 'text-start':\n currentText.set(chunk.id, '');\n break;\n case 'text-delta':\n currentText.set(\n chunk.id,\n (currentText.get(chunk.id) ?? '') + chunk.delta,\n );\n break;\n case 'text-end':\n collectedOutput.textParts.push({\n id: chunk.id,\n text: currentText.get(chunk.id) ?? '',\n });\n break;\n case 'reasoning-start':\n currentReasoning.set(chunk.id, '');\n break;\n case 'reasoning-delta':\n currentReasoning.set(\n chunk.id,\n (currentReasoning.get(chunk.id) ?? '') + chunk.delta,\n );\n break;\n case 'reasoning-end':\n collectedOutput.reasoningParts.push({\n id: chunk.id,\n text: currentReasoning.get(chunk.id) ?? '',\n });\n break;\n case 'tool-call':\n collectedOutput.toolCalls.push(chunk);\n break;\n case 'file':\n case 'reasoning-file':\n case 'tool-result':\n (collectedOutput.content ??= []).push(chunk);\n break;\n case 'finish':\n collectedOutput.finishReason = chunk.finishReason;\n collectedOutput.usage = chunk.usage;\n break;\n }\n\n controller.enqueue(chunk);\n },\n\n async flush() {\n // Remove from active tracking - stream completed normally\n activeSteps.delete(stepId);\n\n const durationMs = Date.now() - startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: serializeForDevTools(collectedOutput),\n usage: collectedOutput.usage\n ? JSON.stringify(collectedOutput.usage)\n : null,\n error: null,\n raw_request: request?.body ? JSON.stringify(request.body) : null,\n raw_response: JSON.stringify(fullStreamChunks),\n raw_chunks: JSON.stringify(rawChunks),\n });\n },\n\n // @ts-expect-error - cancel is valid per WHATWG Streams spec but missing from TS types\n async cancel() {\n // Remove from active tracking - stream was cancelled\n activeSteps.delete(stepId);\n\n const durationMs = Date.now() - startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: serializeForDevTools(collectedOutput),\n usage: collectedOutput.usage\n ? JSON.stringify(collectedOutput.usage)\n : null,\n error: 'Request aborted',\n raw_request: request?.body ? JSON.stringify(request.body) : null,\n raw_response: JSON.stringify(fullStreamChunks),\n raw_chunks: JSON.stringify(rawChunks),\n });\n },\n });\n\n return {\n stream: stream.pipeThrough(transformStream),\n request,\n response,\n ...rest,\n };\n } catch (error) {\n activeSteps.delete(stepId);\n\n const durationMs = Date.now() - startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: null,\n usage: null,\n error: error instanceof Error ? error.message : String(error),\n raw_request: null,\n raw_response: null,\n raw_chunks: null,\n });\n throw error;\n }\n },\n };\n};\n","import type {\n GenerateTextStartEvent,\n GenerateTextStepStartEvent,\n GenerateTextStepEndEvent,\n GenerateTextStepErrorEvent,\n GenerateObjectStartEvent,\n GenerateObjectStepStartEvent,\n GenerateObjectStepEndEvent,\n Telemetry,\n ToolSet,\n} from 'ai';\nimport {\n createRun,\n createStep,\n getStepsForRun,\n updateStepResult,\n notifyServerAsync,\n} from './db.js';\nimport { serializeForDevTools } from './serialize.js';\n\ntype OperationType = 'generate' | 'stream';\n\ninterface StepState {\n stepId: string;\n startTime: number;\n}\n\ninterface CallState {\n runId: string;\n operationType: OperationType;\n functionId: string | undefined;\n settings: Record<string, unknown>;\n stepStates: Map<number, StepState>;\n stepNumberOffset: number;\n}\n\nexport interface DevToolsTelemetryOptions {\n /**\n * Identifier used to group multiple AI SDK calls into one DevTools run.\n * Reuse the same value when resuming an interrupted interaction.\n */\n runId?: string;\n}\n\nconst activeSteps = new Map<string, StepState>();\n\nasync function failStep(stepState: StepState, error: unknown) {\n activeSteps.delete(stepState.stepId);\n await updateStepResult(stepState.stepId, {\n duration_ms: Date.now() - stepState.startTime,\n output: null,\n usage: null,\n error: error instanceof Error ? error.message : String(error),\n raw_request: null,\n raw_response: null,\n raw_chunks: null,\n });\n}\n\nlet signalHandlersRegistered = false;\nconst registerSignalHandlers = () => {\n if (signalHandlersRegistered) return;\n signalHandlersRegistered = true;\n\n const cleanup = async () => {\n if (activeSteps.size === 0) return;\n\n const promises = Array.from(activeSteps.entries()).map(\n async ([stepId, data]) => {\n const durationMs = Date.now() - data.startTime;\n await updateStepResult(stepId, {\n duration_ms: durationMs,\n output: null,\n usage: null,\n error: 'Request aborted',\n raw_request: null,\n raw_response: null,\n raw_chunks: null,\n });\n },\n );\n await Promise.all(promises);\n await notifyServerAsync('step-update');\n };\n\n process.on('SIGINT', () => {\n cleanup().then(() => process.exit(130));\n });\n\n process.on('SIGTERM', () => {\n cleanup().then(() => process.exit(143));\n });\n};\n\nconst generateRunId = (): string => {\n const now = new Date();\n const timestamp = now\n .toISOString()\n .replace(/[-:T.Z]/g, '')\n .slice(0, 17);\n const uniqueId = crypto.randomUUID().slice(0, 8);\n return `${timestamp}-${uniqueId}`;\n};\n\nfunction getOperationType(operationId: string): OperationType {\n if (operationId === 'ai.streamText' || operationId === 'ai.streamObject') {\n return 'stream';\n }\n return 'generate';\n}\n\n/**\n * Creates a devtools telemetry integration that logs all AI SDK operations\n * to the devtools viewer.\n *\n * Usage:\n * ```ts\n * import { registerTelemetry } from 'ai';\n * import { DevToolsTelemetry } from '@ai-sdk/devtools';\n *\n * registerTelemetry(DevToolsTelemetry());\n * ```\n *\n * Telemetry is enabled by default — no need to set `telemetry`\n * unless you want to configure `functionId`, `recordInputs`, or `recordOutputs`.\n */\nexport function DevToolsTelemetry(\n options: DevToolsTelemetryOptions = {},\n): Telemetry {\n if (process.env.NODE_ENV === 'production') {\n throw new Error(\n '@ai-sdk/devtools should not be used in production. ' +\n 'Remove DevToolsTelemetry from your telemetry configuration for production builds.',\n );\n }\n\n registerSignalHandlers();\n\n const callStates = new Map<string, CallState>();\n\n // When executeTool runs a tool's execute function, any nested generateText/\n // streamText call inside that tool gets its own callId. We track the nesting\n // so that the inner call's run can be linked to the parent.\n //\n // We use a per-toolCallId Map instead of a single variable so that parallel\n // tool calls\n const toolContextMap = new Map<\n string,\n { parentCallId: string; parentToolCallId: string }\n >();\n let currentToolCallId: string | null = null;\n\n function resolveParentInfo(): { runId: string; stepId: string } | undefined {\n if (!currentToolCallId) return undefined;\n\n const toolCallContext = toolContextMap.get(currentToolCallId);\n if (!toolCallContext) return undefined;\n\n const parentState = callStates.get(toolCallContext.parentCallId);\n if (!parentState) return undefined;\n\n // Find the step that is currently executing the tool call.\n // This is the most recent (highest step number) step in the parent call.\n let latestStepId: string | undefined;\n let latestStepNumber = -1;\n for (const [stepNumber, stepState] of parentState.stepStates) {\n if (stepNumber > latestStepNumber) {\n latestStepNumber = stepNumber;\n latestStepId = stepState.stepId;\n }\n }\n\n if (!latestStepId) return undefined;\n\n return { runId: parentState.runId, stepId: latestStepId };\n }\n\n function getOrCreateCallState(\n callId: string,\n operationId: string,\n event: {\n functionId?: string | undefined;\n maxOutputTokens?: number | undefined;\n temperature?: number | undefined;\n topP?: number | undefined;\n topK?: number | undefined;\n presencePenalty?: number | undefined;\n frequencyPenalty?: number | undefined;\n seed?: number | undefined;\n },\n ): CallState {\n let state = callStates.get(callId);\n if (state) return state;\n\n state = {\n runId: generateRunId(),\n operationType: getOperationType(operationId),\n functionId: event.functionId,\n settings: {\n maxOutputTokens: event.maxOutputTokens,\n temperature: event.temperature,\n topP: event.topP,\n topK: event.topK,\n presencePenalty: event.presencePenalty,\n frequencyPenalty: event.frequencyPenalty,\n seed: event.seed,\n },\n stepStates: new Map(),\n stepNumberOffset: 0,\n };\n callStates.set(callId, state);\n return state;\n }\n\n const integration: Telemetry = {\n onStart: async event => {\n const operationId = (event as { operationId: string }).operationId;\n\n if (\n operationId === 'ai.embed' ||\n operationId === 'ai.embedMany' ||\n operationId === 'ai.rerank' ||\n operationId === 'ai.generateSpeech' ||\n operationId === 'ai.transcribe'\n ) {\n return;\n }\n\n const startEvent = event as (\n | GenerateTextStartEvent<ToolSet>\n | GenerateObjectStartEvent\n ) & {\n functionId?: string | undefined;\n };\n\n const parentInfo = resolveParentInfo();\n\n const state = getOrCreateCallState(\n startEvent.callId,\n operationId,\n startEvent,\n );\n\n if (options.runId != null) {\n state.runId = options.runId;\n state.stepNumberOffset = (await getStepsForRun(options.runId)).length;\n }\n\n await createRun(state.runId, parentInfo, state.functionId);\n },\n\n onStepStart: async event => {\n const stepStartEvent = event as GenerateTextStepStartEvent<ToolSet> & {\n promptMessages?: unknown[];\n };\n\n const state = callStates.get(stepStartEvent.callId);\n if (!state) return;\n\n const stepId = crypto.randomUUID();\n const startTime = Date.now();\n\n const stepState: StepState = {\n stepId,\n startTime,\n };\n const stepNumber = stepStartEvent.steps.length;\n state.stepStates.set(stepNumber, stepState);\n activeSteps.set(stepId, stepState);\n\n const prompt = stepStartEvent.promptMessages ?? stepStartEvent.messages;\n\n await createStep({\n id: stepId,\n run_id: state.runId,\n step_number: state.stepNumberOffset + stepNumber + 1,\n type: state.operationType,\n model_id: stepStartEvent.modelId,\n provider: stepStartEvent.provider ?? null,\n started_at: new Date().toISOString(),\n input: serializeForDevTools({\n prompt,\n tools: stepStartEvent.tools\n ? Object.entries(stepStartEvent.tools).map(([name, tool]) => ({\n name,\n description: (tool as { description?: string }).description,\n parameters: (tool as { parameters?: unknown }).parameters,\n }))\n : undefined,\n toolChoice: stepStartEvent.toolChoice,\n maxOutputTokens: state.settings.maxOutputTokens,\n temperature: state.settings.temperature,\n topP: state.settings.topP,\n topK: state.settings.topK,\n presencePenalty: state.settings.presencePenalty,\n frequencyPenalty: state.settings.frequencyPenalty,\n seed: state.settings.seed,\n }),\n provider_options: stepStartEvent.providerOptions\n ? JSON.stringify(stepStartEvent.providerOptions)\n : null,\n });\n },\n\n onObjectStepStart: async event => {\n const stepStartEvent = event as GenerateObjectStepStartEvent & {\n promptMessages?: unknown[];\n };\n\n const state = callStates.get(stepStartEvent.callId);\n if (!state) return;\n\n const stepId = crypto.randomUUID();\n const startTime = Date.now();\n\n const stepState: StepState = {\n stepId,\n startTime,\n };\n state.stepStates.set(stepStartEvent.stepNumber, stepState);\n activeSteps.set(stepId, stepState);\n\n await createStep({\n id: stepId,\n run_id: state.runId,\n step_number: state.stepNumberOffset + stepStartEvent.stepNumber + 1,\n type: state.operationType,\n model_id: stepStartEvent.modelId,\n provider: stepStartEvent.provider ?? null,\n started_at: new Date().toISOString(),\n input: serializeForDevTools({\n prompt: stepStartEvent.promptMessages,\n maxOutputTokens: state.settings.maxOutputTokens,\n temperature: state.settings.temperature,\n topP: state.settings.topP,\n topK: state.settings.topK,\n presencePenalty: state.settings.presencePenalty,\n frequencyPenalty: state.settings.frequencyPenalty,\n seed: state.settings.seed,\n }),\n provider_options: stepStartEvent.providerOptions\n ? JSON.stringify(stepStartEvent.providerOptions)\n : null,\n });\n },\n\n onStepEnd: async event => {\n const stepResult = event as GenerateTextStepEndEvent<ToolSet>;\n\n const state = callStates.get(stepResult.callId);\n if (!state) return;\n\n const stepState = state.stepStates.get(stepResult.stepNumber);\n if (!stepState) return;\n\n activeSteps.delete(stepState.stepId);\n\n const durationMs = Date.now() - stepState.startTime;\n\n const output = {\n content: stepResult.content,\n finishReason: stepResult.finishReason,\n response: {\n id: stepResult.response.id,\n modelId: stepResult.response.modelId,\n timestamp: stepResult.response.timestamp,\n messages: stepResult.response.messages,\n },\n };\n\n await updateStepResult(stepState.stepId, {\n duration_ms: durationMs,\n output: serializeForDevTools(output),\n usage: stepResult.usage ? JSON.stringify(stepResult.usage) : null,\n error: null,\n raw_request: stepResult.request?.body\n ? JSON.stringify(stepResult.request.body)\n : null,\n raw_response: stepResult.response?.body\n ? JSON.stringify(stepResult.response.body)\n : null,\n raw_chunks: null,\n });\n\n state.stepStates.delete(stepResult.stepNumber);\n },\n\n onObjectStepEnd: async event => {\n const stepResult = event as GenerateObjectStepEndEvent;\n\n const state = callStates.get(stepResult.callId);\n if (!state) return;\n\n const stepState = state.stepStates.get(stepResult.stepNumber);\n if (!stepState) return;\n\n activeSteps.delete(stepState.stepId);\n\n const durationMs = Date.now() - stepState.startTime;\n\n const output = {\n finishReason: stepResult.finishReason,\n objectText: stepResult.objectText,\n response: {\n id: stepResult.response.id,\n modelId: stepResult.response.modelId,\n timestamp: stepResult.response.timestamp,\n },\n };\n\n await updateStepResult(stepState.stepId, {\n duration_ms: durationMs,\n output: JSON.stringify(output),\n usage: stepResult.usage ? JSON.stringify(stepResult.usage) : null,\n error: null,\n raw_request: stepResult.request?.body\n ? JSON.stringify(stepResult.request.body)\n : null,\n raw_response: stepResult.response?.body\n ? JSON.stringify(stepResult.response.body)\n : null,\n });\n\n state.stepStates.delete(stepResult.stepNumber);\n },\n\n onStepError: async event => {\n const stepErrorEvent = event as GenerateTextStepErrorEvent<ToolSet>;\n\n const state = callStates.get(stepErrorEvent.callId);\n if (!state) return;\n\n const stepState = state.stepStates.get(stepErrorEvent.stepNumber);\n if (!stepState) return;\n\n await failStep(stepState, stepErrorEvent.error);\n state.stepStates.delete(stepErrorEvent.stepNumber);\n },\n\n onEnd: async event => {\n const endEvent = event as { callId: string };\n callStates.delete(endEvent.callId);\n },\n\n onError: async error => {\n const errorObj = error as\n | { callId?: string; error?: unknown }\n | undefined;\n const callId = errorObj?.callId;\n if (!callId) return;\n\n const state = callStates.get(callId);\n if (!state) return;\n\n const cause = errorObj?.error ?? error;\n\n for (const [, stepState] of state.stepStates) {\n await failStep(stepState, cause);\n }\n\n callStates.delete(callId);\n },\n\n executeTool: async ({ callId, toolCallId, execute }) => {\n toolContextMap.set(toolCallId, {\n parentCallId: callId,\n parentToolCallId: toolCallId,\n });\n\n const previousToolCallId = currentToolCallId;\n currentToolCallId = toolCallId;\n\n try {\n return await execute();\n } finally {\n currentToolCallId = previousToolCallId;\n toolContextMap.delete(toolCallId);\n }\n },\n };\n\n return integration;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/devtools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.57",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"bin"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@ai-sdk/provider": "4.0.
|
|
27
|
+
"@ai-sdk/provider": "4.0.34",
|
|
28
28
|
"@hono/node-server": "^1.19.15",
|
|
29
|
-
"ai": "7.0.
|
|
29
|
+
"ai": "7.0.154",
|
|
30
30
|
"hono": "^4.13.7"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
package/src/integration.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
GenerateTextStartEvent,
|
|
3
3
|
GenerateTextStepStartEvent,
|
|
4
4
|
GenerateTextStepEndEvent,
|
|
5
|
+
GenerateTextStepErrorEvent,
|
|
5
6
|
GenerateObjectStartEvent,
|
|
6
7
|
GenerateObjectStepStartEvent,
|
|
7
8
|
GenerateObjectStepEndEvent,
|
|
@@ -43,6 +44,19 @@ export interface DevToolsTelemetryOptions {
|
|
|
43
44
|
|
|
44
45
|
const activeSteps = new Map<string, StepState>();
|
|
45
46
|
|
|
47
|
+
async function failStep(stepState: StepState, error: unknown) {
|
|
48
|
+
activeSteps.delete(stepState.stepId);
|
|
49
|
+
await updateStepResult(stepState.stepId, {
|
|
50
|
+
duration_ms: Date.now() - stepState.startTime,
|
|
51
|
+
output: null,
|
|
52
|
+
usage: null,
|
|
53
|
+
error: error instanceof Error ? error.message : String(error),
|
|
54
|
+
raw_request: null,
|
|
55
|
+
raw_response: null,
|
|
56
|
+
raw_chunks: null,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
46
60
|
let signalHandlersRegistered = false;
|
|
47
61
|
const registerSignalHandlers = () => {
|
|
48
62
|
if (signalHandlersRegistered) return;
|
|
@@ -410,6 +424,19 @@ export function DevToolsTelemetry(
|
|
|
410
424
|
state.stepStates.delete(stepResult.stepNumber);
|
|
411
425
|
},
|
|
412
426
|
|
|
427
|
+
onStepError: async event => {
|
|
428
|
+
const stepErrorEvent = event as GenerateTextStepErrorEvent<ToolSet>;
|
|
429
|
+
|
|
430
|
+
const state = callStates.get(stepErrorEvent.callId);
|
|
431
|
+
if (!state) return;
|
|
432
|
+
|
|
433
|
+
const stepState = state.stepStates.get(stepErrorEvent.stepNumber);
|
|
434
|
+
if (!stepState) return;
|
|
435
|
+
|
|
436
|
+
await failStep(stepState, stepErrorEvent.error);
|
|
437
|
+
state.stepStates.delete(stepErrorEvent.stepNumber);
|
|
438
|
+
},
|
|
439
|
+
|
|
413
440
|
onEnd: async event => {
|
|
414
441
|
const endEvent = event as { callId: string };
|
|
415
442
|
callStates.delete(endEvent.callId);
|
|
@@ -426,21 +453,9 @@ export function DevToolsTelemetry(
|
|
|
426
453
|
if (!state) return;
|
|
427
454
|
|
|
428
455
|
const cause = errorObj?.error ?? error;
|
|
429
|
-
const errorMessage =
|
|
430
|
-
cause instanceof Error ? cause.message : String(cause);
|
|
431
456
|
|
|
432
457
|
for (const [, stepState] of state.stepStates) {
|
|
433
|
-
|
|
434
|
-
const durationMs = Date.now() - stepState.startTime;
|
|
435
|
-
await updateStepResult(stepState.stepId, {
|
|
436
|
-
duration_ms: durationMs,
|
|
437
|
-
output: null,
|
|
438
|
-
usage: null,
|
|
439
|
-
error: errorMessage,
|
|
440
|
-
raw_request: null,
|
|
441
|
-
raw_response: null,
|
|
442
|
-
raw_chunks: null,
|
|
443
|
-
});
|
|
458
|
+
await failStep(stepState, cause);
|
|
444
459
|
}
|
|
445
460
|
|
|
446
461
|
callStates.delete(callId);
|