@openbuilder/cli 0.50.44 → 0.50.46

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.
Files changed (46) hide show
  1. package/dist/chunks/{Banner-BlktOjfl.js → Banner-BKC6yG6z.js} +2 -2
  2. package/dist/chunks/{Banner-BlktOjfl.js.map → Banner-BKC6yG6z.js.map} +1 -1
  3. package/dist/chunks/{cli-auth-ChCnxlFl.js → cli-auth-BgiGSBOt.js} +4 -4
  4. package/dist/chunks/{cli-auth-ChCnxlFl.js.map → cli-auth-BgiGSBOt.js.map} +1 -1
  5. package/dist/chunks/{index-oFqGtEeF.js → index-ZNRLfdj5.js} +2 -2
  6. package/dist/chunks/{index-oFqGtEeF.js.map → index-ZNRLfdj5.js.map} +1 -1
  7. package/dist/chunks/{init-BsQ3dhwf.js → init-IQRjA1g3.js} +5 -6
  8. package/dist/chunks/{init-BsQ3dhwf.js.map → init-IQRjA1g3.js.map} +1 -1
  9. package/dist/chunks/{init-tui-Dvk6Ndvl.js → init-tui-B4jfmo3U.js} +5 -6
  10. package/dist/chunks/{init-tui-Dvk6Ndvl.js.map → init-tui-B4jfmo3U.js.map} +1 -1
  11. package/dist/chunks/{login-BhtodVsj.js → login-CrIcDJpS.js} +2 -2
  12. package/dist/chunks/{login-BhtodVsj.js.map → login-CrIcDJpS.js.map} +1 -1
  13. package/dist/chunks/{logout-CDDASeuQ.js → logout-BxgiczmY.js} +2 -2
  14. package/dist/chunks/{logout-CDDASeuQ.js.map → logout-BxgiczmY.js.map} +1 -1
  15. package/dist/chunks/{main-tui-Cklcr3FX.js → main-tui-NPDVPKol.js} +7 -8
  16. package/dist/chunks/{main-tui-Cklcr3FX.js.map → main-tui-NPDVPKol.js.map} +1 -1
  17. package/dist/chunks/{port-allocator-Ct3ioni4.js → port-allocator-DuAZe2_S.js} +3 -4
  18. package/dist/chunks/{port-allocator-Ct3ioni4.js.map → port-allocator-DuAZe2_S.js.map} +1 -1
  19. package/dist/chunks/{run-wycadErJ.js → run-Yh3YjeLl.js} +10 -16
  20. package/dist/chunks/{run-wycadErJ.js.map → run-Yh3YjeLl.js.map} +1 -1
  21. package/dist/chunks/{start-CQKEEma-.js → start-B-brfyVy.js} +5 -6
  22. package/dist/chunks/{start-CQKEEma-.js.map → start-B-brfyVy.js.map} +1 -1
  23. package/dist/chunks/{theme-CktnrDZj.js → theme-DOjeB8BU.js} +13 -8
  24. package/dist/chunks/{theme-CktnrDZj.js.map → theme-DOjeB8BU.js.map} +1 -1
  25. package/dist/chunks/{use-app-Cj2bzWaw.js → use-app-DozfqdJj.js} +2 -2
  26. package/dist/chunks/{use-app-Cj2bzWaw.js.map → use-app-DozfqdJj.js.map} +1 -1
  27. package/dist/chunks/{useBuildState-pcDGDakI.js → useBuildState-DV6wurQ2.js} +2 -2
  28. package/dist/chunks/{useBuildState-pcDGDakI.js.map → useBuildState-DV6wurQ2.js.map} +1 -1
  29. package/dist/cli/index.js +7 -7
  30. package/dist/index.js +205 -2734
  31. package/dist/index.js.map +1 -1
  32. package/dist/instrument.js +7 -64162
  33. package/dist/instrument.js.map +1 -1
  34. package/package.json +2 -11
  35. package/dist/chunks/_commonjsHelpers-h-Bqc03Z.js +0 -34
  36. package/dist/chunks/_commonjsHelpers-h-Bqc03Z.js.map +0 -1
  37. package/dist/chunks/exports-ij9sv4UM.js +0 -7793
  38. package/dist/chunks/exports-ij9sv4UM.js.map +0 -1
  39. package/scripts/install-vendor-deps.js +0 -34
  40. package/scripts/install-vendor.js +0 -167
  41. package/scripts/prepare-release.js +0 -83
  42. package/vendor/ai-sdk-provider-claude-code-LOCAL.tgz +0 -0
  43. package/vendor/sentry-core-LOCAL.tgz +0 -0
  44. package/vendor/sentry-nextjs-LOCAL.tgz +0 -0
  45. package/vendor/sentry-node-LOCAL.tgz +0 -0
  46. package/vendor/sentry-node-core-LOCAL.tgz +0 -0
package/dist/index.js CHANGED
@@ -1,2004 +1,38 @@
1
1
  // OpenBuilder CLI - Built with Rollup
2
+ import * as Sentry from '@sentry/node';
2
3
  import { query } from '@anthropic-ai/claude-agent-sdk';
3
4
  import { Codex } from '@openai/codex-sdk';
4
- import { a as streamLog, f as fileLog, i as initRunnerLogger, s as setFileLoggerTuiMode, b as getLogger$1 } from './chunks/runner-logger-instance-nDWv2h2T.js';
5
+ import { a as streamLog, f as fileLog, i as initRunnerLogger, s as setFileLoggerTuiMode, b as getLogger } from './chunks/runner-logger-instance-nDWv2h2T.js';
5
6
  import { config as config$1 } from 'dotenv';
6
- import require$$1, { resolve, relative, isAbsolute, dirname, join as join$1 } from 'node:path';
7
+ import path$1, { resolve, relative, isAbsolute, dirname, join as join$1 } from 'node:path';
7
8
  import { fileURLToPath } from 'node:url';
8
- import { generateText, streamText } from 'ai';
9
- import 'zod/v4';
10
- import 'zod/v3';
11
- import { parse } from 'jsonc-parser';
12
- import { z } from 'zod';
13
- import { existsSync, mkdirSync as mkdirSync$1 } from 'fs';
14
- import { existsSync as existsSync$1, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
9
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
15
10
  import { readFile } from 'fs/promises';
16
11
  import * as path from 'path';
17
- import { join } from 'path';
18
- import WebSocket$1, { WebSocketServer, WebSocket } from 'ws';
19
- import { drizzle } from 'drizzle-orm/node-postgres';
20
- import pg from 'pg';
21
- import { pgTable, timestamp, boolean, text, uuid, index, uniqueIndex, integer, jsonb } from 'drizzle-orm/pg-core';
22
- import { sql, eq, and, desc, isNull } from 'drizzle-orm';
23
- import { randomUUID, createHash } from 'crypto';
24
- import { migrate } from 'drizzle-orm/node-postgres/migrator';
25
- import { ak as addBreadcrumb, aa as captureException, a as getActiveSpan, a0 as getTraceData, ap as startInactiveSpan, bh as flush, bn as continueTrace, af as startSpan, by as setTag, bF as count, bG as distribution, bH as info, bI as fmt } from './chunks/exports-ij9sv4UM.js';
26
- import os__default from 'node:os';
27
- import { randomUUID as randomUUID$1 } from 'node:crypto';
28
- import express from 'express';
29
- import { spawn } from 'node:child_process';
30
- import { EventEmitter } from 'node:events';
31
- import { createServer, createConnection } from 'node:net';
32
- import { readFile as readFile$1, rm, writeFile, readdir } from 'node:fs/promises';
33
- import { simpleGit } from 'simple-git';
34
- import * as os from 'os';
35
- import { tunnelManager } from './chunks/manager-CvGX9qqe.js';
36
- import 'chalk';
37
- import 'node:util';
38
- import 'http';
39
- import 'http-proxy';
40
- import 'zlib';
41
-
42
- // src/errors/ai-sdk-error.ts
43
- var marker = "vercel.ai.error";
44
- var symbol = Symbol.for(marker);
45
- var _a;
46
- var _AISDKError = class _AISDKError extends Error {
47
- /**
48
- * Creates an AI SDK Error.
49
- *
50
- * @param {Object} params - The parameters for creating the error.
51
- * @param {string} params.name - The name of the error.
52
- * @param {string} params.message - The error message.
53
- * @param {unknown} [params.cause] - The underlying cause of the error.
54
- */
55
- constructor({
56
- name: name14,
57
- message,
58
- cause
59
- }) {
60
- super(message);
61
- this[_a] = true;
62
- this.name = name14;
63
- this.cause = cause;
64
- }
65
- /**
66
- * Checks if the given error is an AI SDK Error.
67
- * @param {unknown} error - The error to check.
68
- * @returns {boolean} True if the error is an AI SDK Error, false otherwise.
69
- */
70
- static isInstance(error) {
71
- return _AISDKError.hasMarker(error, marker);
72
- }
73
- static hasMarker(error, marker15) {
74
- const markerSymbol = Symbol.for(marker15);
75
- return error != null && typeof error === "object" && markerSymbol in error && typeof error[markerSymbol] === "boolean" && error[markerSymbol] === true;
76
- }
77
- };
78
- _a = symbol;
79
- var AISDKError = _AISDKError;
80
-
81
- // src/errors/api-call-error.ts
82
- var name = "AI_APICallError";
83
- var marker2 = `vercel.ai.error.${name}`;
84
- var symbol2 = Symbol.for(marker2);
85
- var _a2;
86
- var APICallError = class extends AISDKError {
87
- constructor({
88
- message,
89
- url,
90
- requestBodyValues,
91
- statusCode,
92
- responseHeaders,
93
- responseBody,
94
- cause,
95
- isRetryable = statusCode != null && (statusCode === 408 || // request timeout
96
- statusCode === 409 || // conflict
97
- statusCode === 429 || // too many requests
98
- statusCode >= 500),
99
- // server error
100
- data
101
- }) {
102
- super({ name, message, cause });
103
- this[_a2] = true;
104
- this.url = url;
105
- this.requestBodyValues = requestBodyValues;
106
- this.statusCode = statusCode;
107
- this.responseHeaders = responseHeaders;
108
- this.responseBody = responseBody;
109
- this.isRetryable = isRetryable;
110
- this.data = data;
111
- }
112
- static isInstance(error) {
113
- return AISDKError.hasMarker(error, marker2);
114
- }
115
- };
116
- _a2 = symbol2;
117
-
118
- // src/errors/invalid-argument-error.ts
119
- var name3 = "AI_InvalidArgumentError";
120
- var marker4 = `vercel.ai.error.${name3}`;
121
- var symbol4 = Symbol.for(marker4);
122
- var _a4;
123
- var InvalidArgumentError = class extends AISDKError {
124
- constructor({
125
- message,
126
- cause,
127
- argument
128
- }) {
129
- super({ name: name3, message, cause });
130
- this[_a4] = true;
131
- this.argument = argument;
132
- }
133
- static isInstance(error) {
134
- return AISDKError.hasMarker(error, marker4);
135
- }
136
- };
137
- _a4 = symbol4;
138
-
139
- // src/errors/load-api-key-error.ts
140
- var name7 = "AI_LoadAPIKeyError";
141
- var marker8 = `vercel.ai.error.${name7}`;
142
- var symbol8 = Symbol.for(marker8);
143
- var _a8;
144
- var LoadAPIKeyError = class extends AISDKError {
145
- // used in isInstance
146
- constructor({ message }) {
147
- super({ name: name7, message });
148
- this[_a8] = true;
149
- }
150
- static isInstance(error) {
151
- return AISDKError.hasMarker(error, marker8);
152
- }
153
- };
154
- _a8 = symbol8;
155
-
156
- // src/errors/no-such-model-error.ts
157
- var name10 = "AI_NoSuchModelError";
158
- var marker11 = `vercel.ai.error.${name10}`;
159
- var symbol11 = Symbol.for(marker11);
160
- var _a11;
161
- var NoSuchModelError = class extends AISDKError {
162
- constructor({
163
- errorName = name10,
164
- modelId,
165
- modelType,
166
- message = `No such ${modelType}: ${modelId}`
167
- }) {
168
- super({ name: errorName, message });
169
- this[_a11] = true;
170
- this.modelId = modelId;
171
- this.modelType = modelType;
172
- }
173
- static isInstance(error) {
174
- return AISDKError.hasMarker(error, marker11);
175
- }
176
- };
177
- _a11 = symbol11;
178
-
179
- // src/combine-headers.ts
180
- var createIdGenerator = ({
181
- prefix,
182
- size = 16,
183
- alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
184
- separator = "-"
185
- } = {}) => {
186
- const generator = () => {
187
- const alphabetLength = alphabet.length;
188
- const chars = new Array(size);
189
- for (let i = 0; i < size; i++) {
190
- chars[i] = alphabet[Math.random() * alphabetLength | 0];
191
- }
192
- return chars.join("");
193
- };
194
- if (prefix == null) {
195
- return generator;
196
- }
197
- if (alphabet.includes(separator)) {
198
- throw new InvalidArgumentError({
199
- argument: "separator",
200
- message: `The separator "${separator}" must not be part of the alphabet "${alphabet}".`
201
- });
202
- }
203
- return () => `${prefix}${separator}${generator()}`;
204
- };
205
- var generateId = createIdGenerator();
206
- new Set(
207
- "ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789"
208
- );
209
-
210
- // src/claude-code-provider.ts
211
-
212
- // src/convert-to-claude-code-messages.ts
213
- var IMAGE_URL_WARNING = "Image URLs are not supported by this provider; supply base64/data URLs.";
214
- var IMAGE_CONVERSION_WARNING = "Unable to convert image content; supply base64/data URLs.";
215
- function normalizeBase64(base64) {
216
- return base64.replace(/\s+/g, "");
217
- }
218
- function isImageMimeType(mimeType) {
219
- return typeof mimeType === "string" && mimeType.trim().toLowerCase().startsWith("image/");
220
- }
221
- function createImageContent(mediaType, data) {
222
- const trimmedType = mediaType.trim();
223
- const trimmedData = normalizeBase64(data.trim());
224
- if (!trimmedType || !trimmedData) {
225
- return void 0;
226
- }
227
- return {
228
- type: "image",
229
- source: {
230
- type: "base64",
231
- media_type: trimmedType,
232
- data: trimmedData
233
- }
234
- };
235
- }
236
- function extractMimeType(candidate) {
237
- if (typeof candidate === "string" && candidate.trim()) {
238
- return candidate.trim();
239
- }
240
- return void 0;
241
- }
242
- function parseObjectImage(imageObj, fallbackMimeType) {
243
- const data = typeof imageObj.data === "string" ? imageObj.data : void 0;
244
- const mimeType = extractMimeType(
245
- imageObj.mimeType ?? imageObj.mediaType ?? imageObj.media_type ?? fallbackMimeType
246
- );
247
- if (!data || !mimeType) {
248
- return void 0;
249
- }
250
- return createImageContent(mimeType, data);
251
- }
252
- function parseStringImage(value, fallbackMimeType) {
253
- const trimmed = value.trim();
254
- if (/^https?:\/\//i.test(trimmed)) {
255
- return { warning: IMAGE_URL_WARNING };
256
- }
257
- const dataUrlMatch = trimmed.match(/^data:([^;]+);base64,(.+)$/i);
258
- if (dataUrlMatch) {
259
- const [, mediaType, data] = dataUrlMatch;
260
- const content = createImageContent(mediaType, data);
261
- return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
262
- }
263
- const base64Match = trimmed.match(/^base64:([^,]+),(.+)$/i);
264
- if (base64Match) {
265
- const [, explicitMimeType, data] = base64Match;
266
- const content = createImageContent(explicitMimeType, data);
267
- return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
268
- }
269
- if (fallbackMimeType) {
270
- const content = createImageContent(fallbackMimeType, trimmed);
271
- if (content) {
272
- return { content };
273
- }
274
- }
275
- return { warning: IMAGE_CONVERSION_WARNING };
276
- }
277
- function parseImagePart(part) {
278
- if (!part || typeof part !== "object") {
279
- return { warning: IMAGE_CONVERSION_WARNING };
280
- }
281
- const imageValue = part.image;
282
- const mimeType = extractMimeType(part.mimeType);
283
- if (typeof imageValue === "string") {
284
- return parseStringImage(imageValue, mimeType);
285
- }
286
- if (imageValue && typeof imageValue === "object") {
287
- const content = parseObjectImage(imageValue, mimeType);
288
- return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
289
- }
290
- return { warning: IMAGE_CONVERSION_WARNING };
291
- }
292
- function convertBinaryToBase64(data) {
293
- if (typeof Buffer !== "undefined") {
294
- const buffer = data instanceof Uint8Array ? Buffer.from(data) : Buffer.from(new Uint8Array(data));
295
- return buffer.toString("base64");
296
- }
297
- if (typeof btoa === "function") {
298
- const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
299
- let binary = "";
300
- const chunkSize = 32768;
301
- for (let i = 0; i < bytes.length; i += chunkSize) {
302
- const chunk = bytes.subarray(i, i + chunkSize);
303
- binary += String.fromCharCode(...chunk);
304
- }
305
- return btoa(binary);
306
- }
307
- return void 0;
308
- }
309
- function parseFilePart(part) {
310
- const mimeType = extractMimeType(part.mediaType ?? part.mimeType);
311
- if (!mimeType || !isImageMimeType(mimeType)) {
312
- return {};
313
- }
314
- const data = part.data;
315
- if (typeof data === "string") {
316
- const content = createImageContent(mimeType, data);
317
- return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
318
- }
319
- if (data instanceof Uint8Array || typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) {
320
- const base64 = convertBinaryToBase64(data);
321
- if (!base64) {
322
- return { warning: IMAGE_CONVERSION_WARNING };
323
- }
324
- const content = createImageContent(mimeType, base64);
325
- return content ? { content } : { warning: IMAGE_CONVERSION_WARNING };
326
- }
327
- return { warning: IMAGE_CONVERSION_WARNING };
328
- }
329
- function convertToClaudeCodeMessages(prompt, mode = { type: "regular" }, jsonSchema) {
330
- const messages = [];
331
- const warnings = [];
332
- let systemPrompt;
333
- const streamingSegments = [];
334
- const imageMap = /* @__PURE__ */ new Map();
335
- let hasImageParts = false;
336
- const addSegment = (formatted) => {
337
- streamingSegments.push({ formatted });
338
- return streamingSegments.length - 1;
339
- };
340
- const addImageForSegment = (segmentIndex, content) => {
341
- hasImageParts = true;
342
- if (!imageMap.has(segmentIndex)) {
343
- imageMap.set(segmentIndex, []);
344
- }
345
- imageMap.get(segmentIndex)?.push(content);
346
- };
347
- for (const message of prompt) {
348
- switch (message.role) {
349
- case "system":
350
- systemPrompt = message.content;
351
- if (typeof message.content === "string" && message.content.trim().length > 0) {
352
- addSegment(message.content);
353
- } else {
354
- addSegment("");
355
- }
356
- break;
357
- case "user":
358
- if (typeof message.content === "string") {
359
- messages.push(message.content);
360
- addSegment(`Human: ${message.content}`);
361
- } else {
362
- const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
363
- const segmentIndex = addSegment(textParts ? `Human: ${textParts}` : "");
364
- if (textParts) {
365
- messages.push(textParts);
366
- }
367
- for (const part of message.content) {
368
- if (part.type === "image") {
369
- const { content, warning } = parseImagePart(part);
370
- if (content) {
371
- addImageForSegment(segmentIndex, content);
372
- } else if (warning) {
373
- warnings.push(warning);
374
- }
375
- } else if (part.type === "file") {
376
- const { content, warning } = parseFilePart(part);
377
- if (content) {
378
- addImageForSegment(segmentIndex, content);
379
- } else if (warning) {
380
- warnings.push(warning);
381
- }
382
- }
383
- }
384
- }
385
- break;
386
- case "assistant": {
387
- let assistantContent = "";
388
- if (typeof message.content === "string") {
389
- assistantContent = message.content;
390
- } else {
391
- const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
392
- if (textParts) {
393
- assistantContent = textParts;
394
- }
395
- const toolCalls = message.content.filter((part) => part.type === "tool-call");
396
- if (toolCalls.length > 0) {
397
- assistantContent += `
398
- [Tool calls made]`;
399
- }
400
- }
401
- const formattedAssistant = `Assistant: ${assistantContent}`;
402
- messages.push(formattedAssistant);
403
- addSegment(formattedAssistant);
404
- break;
405
- }
406
- case "tool":
407
- for (const tool3 of message.content) {
408
- const resultText = tool3.output.type === "text" ? tool3.output.value : JSON.stringify(tool3.output.value);
409
- const formattedToolResult = `Tool Result (${tool3.toolName}): ${resultText}`;
410
- messages.push(formattedToolResult);
411
- addSegment(formattedToolResult);
412
- }
413
- break;
414
- }
415
- }
416
- let finalPrompt = "";
417
- if (systemPrompt) {
418
- finalPrompt = systemPrompt;
419
- }
420
- if (messages.length > 0) {
421
- const formattedMessages = [];
422
- for (let i = 0; i < messages.length; i++) {
423
- const msg = messages[i];
424
- if (msg.startsWith("Assistant:") || msg.startsWith("Tool Result")) {
425
- formattedMessages.push(msg);
426
- } else {
427
- formattedMessages.push(`Human: ${msg}`);
428
- }
429
- }
430
- if (finalPrompt) {
431
- const joinedMessages = formattedMessages.join("\n\n");
432
- finalPrompt = joinedMessages ? `${finalPrompt}
433
-
434
- ${joinedMessages}` : finalPrompt;
435
- } else {
436
- finalPrompt = formattedMessages.join("\n\n");
437
- }
438
- }
439
- let streamingParts = [];
440
- const imagePartsInOrder = [];
441
- const appendImagesForIndex = (index) => {
442
- const images = imageMap.get(index);
443
- if (!images) {
444
- return;
445
- }
446
- images.forEach((image) => {
447
- streamingParts.push(image);
448
- imagePartsInOrder.push(image);
449
- });
450
- };
451
- if (streamingSegments.length > 0) {
452
- let accumulatedText = "";
453
- let emittedText = false;
454
- const flushText = () => {
455
- if (!accumulatedText) {
456
- return;
457
- }
458
- streamingParts.push({ type: "text", text: accumulatedText });
459
- accumulatedText = "";
460
- emittedText = true;
461
- };
462
- streamingSegments.forEach((segment, index) => {
463
- const segmentText = segment.formatted;
464
- if (segmentText) {
465
- if (!accumulatedText) {
466
- accumulatedText = emittedText ? `
467
-
468
- ${segmentText}` : segmentText;
469
- } else {
470
- accumulatedText += `
471
-
472
- ${segmentText}`;
473
- }
474
- }
475
- if (imageMap.has(index)) {
476
- flushText();
477
- appendImagesForIndex(index);
478
- }
479
- });
480
- flushText();
481
- }
482
- if (mode?.type === "object-json" && jsonSchema) {
483
- const schemaStr = JSON.stringify(jsonSchema, null, 2);
484
- finalPrompt = `CRITICAL: You MUST respond with ONLY a JSON object. NO other text, NO explanations, NO questions.
485
-
486
- Your response MUST start with { and end with }
487
-
488
- The JSON MUST match this EXACT schema:
489
- ${schemaStr}
490
-
491
- Now, based on the following conversation, generate ONLY the JSON object with the exact fields specified above:
492
-
493
- ${finalPrompt}
494
-
495
- Remember: Your ENTIRE response must be ONLY the JSON object, starting with { and ending with }`;
496
- streamingParts = [{ type: "text", text: finalPrompt }, ...imagePartsInOrder];
497
- }
498
- return {
499
- messagesPrompt: finalPrompt,
500
- systemPrompt,
501
- ...warnings.length > 0 && { warnings },
502
- streamingContentParts: streamingParts.length > 0 ? streamingParts : [
503
- { type: "text", text: finalPrompt },
504
- ...imagePartsInOrder
505
- ],
506
- hasImageParts
507
- };
508
- }
509
- function extractJson(text) {
510
- let content = text.trim();
511
- const fenceMatch = /```(?:json)?\s*([\s\S]*?)\s*```/i.exec(content);
512
- if (fenceMatch) {
513
- content = fenceMatch[1];
514
- }
515
- const varMatch = /^\s*(?:const|let|var)\s+\w+\s*=\s*([\s\S]*)/i.exec(content);
516
- if (varMatch) {
517
- content = varMatch[1];
518
- if (content.trim().endsWith(";")) {
519
- content = content.trim().slice(0, -1);
520
- }
521
- }
522
- const firstObj = content.indexOf("{");
523
- const firstArr = content.indexOf("[");
524
- if (firstObj === -1 && firstArr === -1) {
525
- return text;
526
- }
527
- const start = firstArr === -1 ? firstObj : firstObj === -1 ? firstArr : Math.min(firstObj, firstArr);
528
- content = content.slice(start);
529
- const tryParse = (value) => {
530
- const errors = [];
531
- try {
532
- const result = parse(value, errors, { allowTrailingComma: true });
533
- if (errors.length === 0) {
534
- return JSON.stringify(result, null, 2);
535
- }
536
- } catch {
537
- }
538
- return void 0;
539
- };
540
- const parsed = tryParse(content);
541
- if (parsed !== void 0) {
542
- return parsed;
543
- }
544
- const openChar = content[0];
545
- const closeChar = openChar === "{" ? "}" : "]";
546
- const closingPositions = [];
547
- let depth = 0;
548
- let inString = false;
549
- let escapeNext = false;
550
- for (let i = 0; i < content.length; i++) {
551
- const char = content[i];
552
- if (escapeNext) {
553
- escapeNext = false;
554
- continue;
555
- }
556
- if (char === "\\") {
557
- escapeNext = true;
558
- continue;
559
- }
560
- if (char === '"' && !inString) {
561
- inString = true;
562
- continue;
563
- }
564
- if (char === '"' && inString) {
565
- inString = false;
566
- continue;
567
- }
568
- if (inString) continue;
569
- if (char === openChar) {
570
- depth++;
571
- } else if (char === closeChar) {
572
- depth--;
573
- if (depth === 0) {
574
- closingPositions.push(i + 1);
575
- }
576
- }
577
- }
578
- for (let i = closingPositions.length - 1; i >= 0; i--) {
579
- const attempt = tryParse(content.slice(0, closingPositions[i]));
580
- if (attempt !== void 0) {
581
- return attempt;
582
- }
583
- }
584
- const searchStart = Math.max(0, content.length - 1e3);
585
- for (let end = content.length - 1; end > searchStart; end--) {
586
- const attempt = tryParse(content.slice(0, end));
587
- if (attempt !== void 0) {
588
- return attempt;
589
- }
590
- }
591
- return text;
592
- }
593
- function createAPICallError({
594
- message,
595
- code,
596
- exitCode,
597
- stderr,
598
- promptExcerpt,
599
- isRetryable = false
600
- }) {
601
- const metadata = {
602
- code,
603
- exitCode,
604
- stderr,
605
- promptExcerpt
606
- };
607
- return new APICallError({
608
- message,
609
- isRetryable,
610
- url: "claude-code-cli://command",
611
- requestBodyValues: promptExcerpt ? { prompt: promptExcerpt } : void 0,
612
- data: metadata
613
- });
614
- }
615
- function createAuthenticationError({ message }) {
616
- return new LoadAPIKeyError({
617
- message: message || "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
618
- });
619
- }
620
- function createTimeoutError({
621
- message,
622
- promptExcerpt,
623
- timeoutMs
624
- }) {
625
- const metadata = {
626
- code: "TIMEOUT",
627
- promptExcerpt
628
- };
629
- return new APICallError({
630
- message,
631
- isRetryable: true,
632
- url: "claude-code-cli://command",
633
- requestBodyValues: promptExcerpt ? { prompt: promptExcerpt } : void 0,
634
- data: timeoutMs !== void 0 ? { ...metadata, timeoutMs } : metadata
635
- });
636
- }
637
-
638
- // src/map-claude-code-finish-reason.ts
639
- function mapClaudeCodeFinishReason(subtype) {
640
- switch (subtype) {
641
- case "success":
642
- return "stop";
643
- case "error_max_turns":
644
- return "length";
645
- case "error_during_execution":
646
- return "error";
647
- default:
648
- return "stop";
649
- }
650
- }
651
- var loggerFunctionSchema = z.object({
652
- debug: z.any().refine((val) => typeof val === "function", {
653
- message: "debug must be a function"
654
- }),
655
- info: z.any().refine((val) => typeof val === "function", {
656
- message: "info must be a function"
657
- }),
658
- warn: z.any().refine((val) => typeof val === "function", {
659
- message: "warn must be a function"
660
- }),
661
- error: z.any().refine((val) => typeof val === "function", {
662
- message: "error must be a function"
663
- })
664
- });
665
- var claudeCodeSettingsSchema = z.object({
666
- pathToClaudeCodeExecutable: z.string().optional(),
667
- customSystemPrompt: z.string().optional(),
668
- appendSystemPrompt: z.string().optional(),
669
- systemPrompt: z.union([
670
- z.string(),
671
- z.object({
672
- type: z.literal("preset"),
673
- preset: z.literal("claude_code"),
674
- append: z.string().optional()
675
- })
676
- ]).optional(),
677
- maxTurns: z.number().int().min(1).max(100).optional(),
678
- maxThinkingTokens: z.number().int().positive().max(1e5).optional(),
679
- cwd: z.string().refine(
680
- (val) => {
681
- if (typeof process === "undefined" || !process.versions?.node) {
682
- return true;
683
- }
684
- return !val || existsSync(val);
685
- },
686
- { message: "Working directory must exist" }
687
- ).optional(),
688
- executable: z.enum(["bun", "deno", "node"]).optional(),
689
- executableArgs: z.array(z.string()).optional(),
690
- permissionMode: z.enum(["default", "acceptEdits", "bypassPermissions", "plan"]).optional(),
691
- permissionPromptToolName: z.string().optional(),
692
- continue: z.boolean().optional(),
693
- resume: z.string().optional(),
694
- allowedTools: z.array(z.string()).optional(),
695
- disallowedTools: z.array(z.string()).optional(),
696
- settingSources: z.array(z.enum(["user", "project", "local"])).optional(),
697
- streamingInput: z.enum(["auto", "always", "off"]).optional(),
698
- // Hooks and tool-permission callback (permissive validation of shapes)
699
- canUseTool: z.any().refine((v) => v === void 0 || typeof v === "function", {
700
- message: "canUseTool must be a function"
701
- }).optional(),
702
- hooks: z.record(
703
- z.string(),
704
- z.array(
705
- z.object({
706
- matcher: z.string().optional(),
707
- hooks: z.array(z.any()).nonempty()
708
- })
709
- )
710
- ).optional(),
711
- mcpServers: z.record(
712
- z.string(),
713
- z.union([
714
- // McpStdioServerConfig
715
- z.object({
716
- type: z.literal("stdio").optional(),
717
- command: z.string(),
718
- args: z.array(z.string()).optional(),
719
- env: z.record(z.string(), z.string()).optional()
720
- }),
721
- // McpSSEServerConfig
722
- z.object({
723
- type: z.literal("sse"),
724
- url: z.string(),
725
- headers: z.record(z.string(), z.string()).optional()
726
- }),
727
- // McpHttpServerConfig
728
- z.object({
729
- type: z.literal("http"),
730
- url: z.string(),
731
- headers: z.record(z.string(), z.string()).optional()
732
- }),
733
- // McpSdkServerConfig (in-process custom tools)
734
- z.object({
735
- type: z.literal("sdk"),
736
- name: z.string(),
737
- instance: z.any()
738
- })
739
- ])
740
- ).optional(),
741
- verbose: z.boolean().optional(),
742
- logger: z.union([z.literal(false), loggerFunctionSchema]).optional(),
743
- env: z.record(z.string(), z.string().optional()).optional(),
744
- additionalDirectories: z.array(z.string()).optional(),
745
- agents: z.record(
746
- z.string(),
747
- z.object({
748
- description: z.string(),
749
- tools: z.array(z.string()).optional(),
750
- prompt: z.string(),
751
- model: z.enum(["sonnet", "opus", "haiku", "inherit"]).optional()
752
- })
753
- ).optional(),
754
- includePartialMessages: z.boolean().optional(),
755
- fallbackModel: z.string().optional(),
756
- forkSession: z.boolean().optional(),
757
- stderr: z.any().refine((val) => val === void 0 || typeof val === "function", {
758
- message: "stderr must be a function"
759
- }).optional(),
760
- strictMcpConfig: z.boolean().optional(),
761
- extraArgs: z.record(z.string(), z.union([z.string(), z.null()])).optional(),
762
- queryFunction: z.any().refine((val) => val === void 0 || typeof val === "function", {
763
- message: "queryFunction must be a function"
764
- }).optional()
765
- }).strict();
766
- function validateModelId(modelId) {
767
- const knownModels = ["opus", "sonnet", "haiku"];
768
- if (!modelId || modelId.trim() === "") {
769
- throw new Error("Model ID cannot be empty");
770
- }
771
- if (!knownModels.includes(modelId)) {
772
- return `Unknown model ID: '${modelId}'. Proceeding with custom model. Known models are: ${knownModels.join(", ")}`;
773
- }
774
- return void 0;
775
- }
776
- function validateSettings(settings) {
777
- const warnings = [];
778
- const errors = [];
779
- try {
780
- const result = claudeCodeSettingsSchema.safeParse(settings);
781
- if (!result.success) {
782
- const errorObject = result.error;
783
- const issues = errorObject.errors || errorObject.issues || [];
784
- issues.forEach((err) => {
785
- const path = err.path.join(".");
786
- errors.push(`${path ? `${path}: ` : ""}${err.message}`);
787
- });
788
- return { valid: false, warnings, errors };
789
- }
790
- const validSettings = result.data;
791
- if (validSettings.maxTurns && validSettings.maxTurns > 20) {
792
- warnings.push(
793
- `High maxTurns value (${validSettings.maxTurns}) may lead to long-running conversations`
794
- );
795
- }
796
- if (validSettings.maxThinkingTokens && validSettings.maxThinkingTokens > 5e4) {
797
- warnings.push(
798
- `Very high maxThinkingTokens (${validSettings.maxThinkingTokens}) may increase response time`
799
- );
800
- }
801
- if (validSettings.allowedTools && validSettings.disallowedTools) {
802
- warnings.push(
803
- "Both allowedTools and disallowedTools are specified. Only allowedTools will be used."
804
- );
805
- }
806
- const validateToolNames = (tools, type) => {
807
- tools.forEach((tool3) => {
808
- if (!/^[a-zA-Z_][a-zA-Z0-9_]*(\([^)]*\))?$/.test(tool3) && !tool3.startsWith("mcp__")) {
809
- warnings.push(`Unusual ${type} tool name format: '${tool3}'`);
810
- }
811
- });
812
- };
813
- if (validSettings.allowedTools) {
814
- validateToolNames(validSettings.allowedTools, "allowed");
815
- }
816
- if (validSettings.disallowedTools) {
817
- validateToolNames(validSettings.disallowedTools, "disallowed");
818
- }
819
- return { valid: true, warnings, errors };
820
- } catch (error) {
821
- errors.push(`Validation error: ${error instanceof Error ? error.message : String(error)}`);
822
- return { valid: false, warnings, errors };
823
- }
824
- }
825
- function validatePrompt(prompt) {
826
- const MAX_PROMPT_LENGTH = 1e5;
827
- if (prompt.length > MAX_PROMPT_LENGTH) {
828
- return `Very long prompt (${prompt.length} characters) may cause performance issues or timeouts`;
829
- }
830
- return void 0;
831
- }
832
- function validateSessionId(sessionId) {
833
- if (sessionId && !/^[a-zA-Z0-9-_]+$/.test(sessionId)) {
834
- return `Unusual session ID format. This may cause issues with session resumption.`;
835
- }
836
- return void 0;
837
- }
838
-
839
- // src/logger.ts
840
- var defaultLogger = {
841
- debug: (message) => console.debug(`[DEBUG] ${message}`),
842
- info: (message) => console.info(`[INFO] ${message}`),
843
- warn: (message) => console.warn(`[WARN] ${message}`),
844
- error: (message) => console.error(`[ERROR] ${message}`)
845
- };
846
- var noopLogger = {
847
- debug: () => {
848
- },
849
- info: () => {
850
- },
851
- warn: () => {
852
- },
853
- error: () => {
854
- }
855
- };
856
- function getLogger(logger) {
857
- if (logger === false) {
858
- return noopLogger;
859
- }
860
- if (logger === void 0) {
861
- return defaultLogger;
862
- }
863
- return logger;
864
- }
865
- function createVerboseLogger(logger, verbose = false) {
866
- if (verbose) {
867
- return logger;
868
- }
869
- return {
870
- debug: () => {
871
- },
872
- // No-op when not verbose
873
- info: () => {
874
- },
875
- // No-op when not verbose
876
- warn: logger.warn.bind(logger),
877
- error: logger.error.bind(logger)
878
- };
879
- }
880
- var CLAUDE_CODE_TRUNCATION_WARNING = "Claude Code SDK output ended unexpectedly; returning truncated response from buffered text. Await upstream fix to avoid data loss.";
881
- var MIN_TRUNCATION_LENGTH = 512;
882
- function isClaudeCodeTruncationError(error, bufferedText) {
883
- const isSyntaxError = error instanceof SyntaxError || // eslint-disable-next-line @typescript-eslint/no-explicit-any
884
- typeof error?.name === "string" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
885
- error.name.toLowerCase() === "syntaxerror";
886
- if (!isSyntaxError) {
887
- return false;
888
- }
889
- if (!bufferedText) {
890
- return false;
891
- }
892
- const rawMessage = typeof error?.message === "string" ? error.message : "";
893
- const message = rawMessage.toLowerCase();
894
- const truncationIndicators = [
895
- "unexpected end of json input",
896
- "unexpected end of input",
897
- "unexpected end of string",
898
- "unexpected eof",
899
- "end of file",
900
- "unterminated string",
901
- "unterminated string constant"
902
- ];
903
- if (!truncationIndicators.some((indicator) => message.includes(indicator))) {
904
- return false;
905
- }
906
- if (bufferedText.length < MIN_TRUNCATION_LENGTH) {
907
- return false;
908
- }
909
- return true;
910
- }
911
- function isAbortError(err) {
912
- if (err && typeof err === "object") {
913
- const e = err;
914
- if (typeof e.name === "string" && e.name === "AbortError") return true;
915
- if (typeof e.code === "string" && e.code.toUpperCase() === "ABORT_ERR") return true;
916
- }
917
- return false;
918
- }
919
- var STREAMING_FEATURE_WARNING = "Claude Agent SDK features (hooks/MCP/images) require streaming input. Set `streamingInput: 'always'` or provide `canUseTool` (auto streams only when canUseTool is set).";
920
- function toAsyncIterablePrompt(messagesPrompt, outputStreamEnded, sessionId, contentParts) {
921
- const content = contentParts && contentParts.length > 0 ? contentParts : [{ type: "text", text: messagesPrompt }];
922
- const msg = {
923
- type: "user",
924
- message: {
925
- role: "user",
926
- content
927
- },
928
- parent_tool_use_id: null,
929
- session_id: sessionId ?? ""
930
- };
931
- return {
932
- async *[Symbol.asyncIterator]() {
933
- yield msg;
934
- await outputStreamEnded;
935
- }
936
- };
937
- }
938
- var modelMap = {
939
- opus: "opus",
940
- sonnet: "sonnet",
941
- haiku: "haiku"
942
- };
943
- var ClaudeCodeLanguageModel = class _ClaudeCodeLanguageModel {
944
- specificationVersion = "v2";
945
- defaultObjectGenerationMode = "json";
946
- supportsImageUrls = false;
947
- supportedUrls = {};
948
- supportsStructuredOutputs = false;
949
- // Fallback/magic string constants
950
- static UNKNOWN_TOOL_NAME = "unknown-tool";
951
- // Tool input safety limits
952
- static MAX_TOOL_INPUT_SIZE = 1048576;
953
- // 1MB hard limit
954
- static MAX_TOOL_INPUT_WARN = 102400;
955
- // 100KB warning threshold
956
- static MAX_DELTA_CALC_SIZE = 1e4;
957
- // 10KB delta computation threshold
958
- modelId;
959
- settings;
960
- sessionId;
961
- modelValidationWarning;
962
- settingsValidationWarnings;
963
- logger;
964
- queryFn;
965
- constructor(options) {
966
- this.modelId = options.id;
967
- this.settings = options.settings ?? {};
968
- this.settingsValidationWarnings = options.settingsValidationWarnings ?? [];
969
- this.queryFn = this.settings.queryFunction ?? query;
970
- const baseLogger = getLogger(this.settings.logger);
971
- this.logger = createVerboseLogger(baseLogger, this.settings.verbose ?? false);
972
- if (!this.modelId || typeof this.modelId !== "string" || this.modelId.trim() === "") {
973
- throw new NoSuchModelError({
974
- modelId: this.modelId,
975
- modelType: "languageModel"
976
- });
977
- }
978
- this.modelValidationWarning = validateModelId(this.modelId);
979
- if (this.modelValidationWarning) {
980
- this.logger.warn(`Claude Code Model: ${this.modelValidationWarning}`);
981
- }
982
- }
983
- get provider() {
984
- return "claude-code";
985
- }
986
- getModel() {
987
- const mapped = modelMap[this.modelId];
988
- return mapped ?? this.modelId;
989
- }
990
- extractToolUses(content) {
991
- if (!Array.isArray(content)) {
992
- return [];
993
- }
994
- return content.filter(
995
- (item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_use"
996
- ).map((item) => {
997
- const { id, name, input } = item;
998
- return {
999
- id: typeof id === "string" && id.length > 0 ? id : generateId(),
1000
- name: typeof name === "string" && name.length > 0 ? name : _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME,
1001
- input
1002
- };
1003
- });
1004
- }
1005
- extractToolResults(content) {
1006
- if (!Array.isArray(content)) {
1007
- return [];
1008
- }
1009
- return content.filter(
1010
- (item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_result"
1011
- ).map((item) => {
1012
- const { tool_use_id, content: content2, is_error, name } = item;
1013
- return {
1014
- id: typeof tool_use_id === "string" && tool_use_id.length > 0 ? tool_use_id : generateId(),
1015
- name: typeof name === "string" && name.length > 0 ? name : void 0,
1016
- result: content2,
1017
- isError: Boolean(is_error)
1018
- };
1019
- });
1020
- }
1021
- extractToolErrors(content) {
1022
- if (!Array.isArray(content)) {
1023
- return [];
1024
- }
1025
- return content.filter(
1026
- (item) => typeof item === "object" && item !== null && "type" in item && item.type === "tool_error"
1027
- ).map((item) => {
1028
- const { tool_use_id, error, name } = item;
1029
- return {
1030
- id: typeof tool_use_id === "string" && tool_use_id.length > 0 ? tool_use_id : generateId(),
1031
- name: typeof name === "string" && name.length > 0 ? name : void 0,
1032
- error
1033
- };
1034
- });
1035
- }
1036
- serializeToolInput(input) {
1037
- if (typeof input === "string") {
1038
- return this.checkInputSize(input);
1039
- }
1040
- if (input === void 0) {
1041
- return "";
1042
- }
1043
- try {
1044
- const serialized = JSON.stringify(input);
1045
- return this.checkInputSize(serialized);
1046
- } catch {
1047
- const fallback = String(input);
1048
- return this.checkInputSize(fallback);
1049
- }
1050
- }
1051
- checkInputSize(str) {
1052
- const length = str.length;
1053
- if (length > _ClaudeCodeLanguageModel.MAX_TOOL_INPUT_SIZE) {
1054
- throw new Error(
1055
- `Tool input exceeds maximum size of ${_ClaudeCodeLanguageModel.MAX_TOOL_INPUT_SIZE} bytes (got ${length} bytes). This may indicate a malformed request or an attempt to process excessively large data.`
1056
- );
1057
- }
1058
- if (length > _ClaudeCodeLanguageModel.MAX_TOOL_INPUT_WARN) {
1059
- this.logger.warn(
1060
- `[claude-code] Large tool input detected: ${length} bytes. Performance may be impacted. Consider chunking or reducing input size.`
1061
- );
1062
- }
1063
- return str;
1064
- }
1065
- normalizeToolResult(result) {
1066
- if (typeof result === "string") {
1067
- try {
1068
- return JSON.parse(result);
1069
- } catch {
1070
- return result;
1071
- }
1072
- }
1073
- return result;
1074
- }
1075
- generateAllWarnings(options, prompt) {
1076
- const warnings = [];
1077
- const unsupportedParams = [];
1078
- if (options.temperature !== void 0) unsupportedParams.push("temperature");
1079
- if (options.topP !== void 0) unsupportedParams.push("topP");
1080
- if (options.topK !== void 0) unsupportedParams.push("topK");
1081
- if (options.presencePenalty !== void 0) unsupportedParams.push("presencePenalty");
1082
- if (options.frequencyPenalty !== void 0) unsupportedParams.push("frequencyPenalty");
1083
- if (options.stopSequences !== void 0 && options.stopSequences.length > 0)
1084
- unsupportedParams.push("stopSequences");
1085
- if (options.seed !== void 0) unsupportedParams.push("seed");
1086
- if (unsupportedParams.length > 0) {
1087
- for (const param of unsupportedParams) {
1088
- warnings.push({
1089
- type: "unsupported-setting",
1090
- setting: param,
1091
- details: `Claude Code SDK does not support the ${param} parameter. It will be ignored.`
1092
- });
1093
- }
1094
- }
1095
- if (this.modelValidationWarning) {
1096
- warnings.push({
1097
- type: "other",
1098
- message: this.modelValidationWarning
1099
- });
1100
- }
1101
- this.settingsValidationWarnings.forEach((warning) => {
1102
- warnings.push({
1103
- type: "other",
1104
- message: warning
1105
- });
1106
- });
1107
- const promptWarning = validatePrompt(prompt);
1108
- if (promptWarning) {
1109
- warnings.push({
1110
- type: "other",
1111
- message: promptWarning
1112
- });
1113
- }
1114
- return warnings;
1115
- }
1116
- handleJsonExtraction(text, warnings) {
1117
- const extracted = extractJson(text);
1118
- const validation = this.validateJsonExtraction(text, extracted);
1119
- if (!validation.valid && validation.warning) {
1120
- warnings.push(validation.warning);
1121
- }
1122
- return extracted;
1123
- }
1124
- createQueryOptions(abortController) {
1125
- const opts = {
1126
- model: this.getModel(),
1127
- abortController,
1128
- resume: this.settings.resume ?? this.sessionId,
1129
- pathToClaudeCodeExecutable: this.settings.pathToClaudeCodeExecutable,
1130
- maxTurns: this.settings.maxTurns,
1131
- maxThinkingTokens: this.settings.maxThinkingTokens,
1132
- cwd: this.settings.cwd,
1133
- executable: this.settings.executable,
1134
- executableArgs: this.settings.executableArgs,
1135
- permissionMode: this.settings.permissionMode,
1136
- permissionPromptToolName: this.settings.permissionPromptToolName,
1137
- continue: this.settings.continue,
1138
- allowedTools: this.settings.allowedTools,
1139
- disallowedTools: this.settings.disallowedTools,
1140
- mcpServers: this.settings.mcpServers,
1141
- canUseTool: this.settings.canUseTool
1142
- };
1143
- if (this.settings.systemPrompt !== void 0) {
1144
- opts.systemPrompt = this.settings.systemPrompt;
1145
- } else if (this.settings.customSystemPrompt !== void 0) {
1146
- this.logger.warn(
1147
- "[claude-code] 'customSystemPrompt' is deprecated and will be removed in a future major release. Please use 'systemPrompt' instead (string or { type: 'preset', preset: 'claude_code', append? })."
1148
- );
1149
- opts.systemPrompt = this.settings.customSystemPrompt;
1150
- } else if (this.settings.appendSystemPrompt !== void 0) {
1151
- this.logger.warn(
1152
- "[claude-code] 'appendSystemPrompt' is deprecated and will be removed in a future major release. Please use 'systemPrompt: { type: 'preset', preset: 'claude_code', append: <text> }' instead."
1153
- );
1154
- opts.systemPrompt = {
1155
- type: "preset",
1156
- preset: "claude_code",
1157
- append: this.settings.appendSystemPrompt
1158
- };
1159
- }
1160
- if (this.settings.settingSources !== void 0) {
1161
- opts.settingSources = this.settings.settingSources;
1162
- }
1163
- if (this.settings.additionalDirectories !== void 0) {
1164
- opts.additionalDirectories = this.settings.additionalDirectories;
1165
- }
1166
- if (this.settings.agents !== void 0) {
1167
- opts.agents = this.settings.agents;
1168
- }
1169
- if (this.settings.includePartialMessages !== void 0) {
1170
- opts.includePartialMessages = this.settings.includePartialMessages;
1171
- }
1172
- if (this.settings.fallbackModel !== void 0) {
1173
- opts.fallbackModel = this.settings.fallbackModel;
1174
- }
1175
- if (this.settings.forkSession !== void 0) {
1176
- opts.forkSession = this.settings.forkSession;
1177
- }
1178
- if (this.settings.stderr !== void 0) {
1179
- opts.stderr = this.settings.stderr;
1180
- }
1181
- if (this.settings.strictMcpConfig !== void 0) {
1182
- opts.strictMcpConfig = this.settings.strictMcpConfig;
1183
- }
1184
- if (this.settings.extraArgs !== void 0) {
1185
- opts.extraArgs = this.settings.extraArgs;
1186
- }
1187
- if (this.settings.hooks) {
1188
- opts.hooks = this.settings.hooks;
1189
- }
1190
- if (this.settings.env !== void 0) {
1191
- opts.env = { ...process.env, ...this.settings.env };
1192
- }
1193
- return opts;
1194
- }
1195
- handleClaudeCodeError(error, messagesPrompt) {
1196
- if (isAbortError(error)) {
1197
- throw error;
1198
- }
1199
- const isErrorWithMessage = (err) => {
1200
- return typeof err === "object" && err !== null && "message" in err;
1201
- };
1202
- const isErrorWithCode = (err) => {
1203
- return typeof err === "object" && err !== null;
1204
- };
1205
- const authErrorPatterns = [
1206
- "not logged in",
1207
- "authentication",
1208
- "unauthorized",
1209
- "auth failed",
1210
- "please login",
1211
- "claude login"
1212
- ];
1213
- const errorMessage = isErrorWithMessage(error) && error.message ? error.message.toLowerCase() : "";
1214
- const exitCode = isErrorWithCode(error) && typeof error.exitCode === "number" ? error.exitCode : void 0;
1215
- const isAuthError = authErrorPatterns.some((pattern) => errorMessage.includes(pattern)) || exitCode === 401;
1216
- if (isAuthError) {
1217
- return createAuthenticationError({
1218
- message: isErrorWithMessage(error) && error.message ? error.message : "Authentication failed. Please ensure Claude Code SDK is properly authenticated."
1219
- });
1220
- }
1221
- const errorCode = isErrorWithCode(error) && typeof error.code === "string" ? error.code : "";
1222
- if (errorCode === "ETIMEDOUT" || errorMessage.includes("timeout")) {
1223
- return createTimeoutError({
1224
- message: isErrorWithMessage(error) && error.message ? error.message : "Request timed out",
1225
- promptExcerpt: messagesPrompt.substring(0, 200)
1226
- // Don't specify timeoutMs since we don't know the actual timeout value
1227
- // It's controlled by the consumer via AbortSignal
1228
- });
1229
- }
1230
- const isRetryable = errorCode === "ENOENT" || errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorCode === "ECONNRESET";
1231
- return createAPICallError({
1232
- message: isErrorWithMessage(error) && error.message ? error.message : "Claude Code SDK error",
1233
- code: errorCode || void 0,
1234
- exitCode,
1235
- stderr: isErrorWithCode(error) && typeof error.stderr === "string" ? error.stderr : void 0,
1236
- promptExcerpt: messagesPrompt.substring(0, 200),
1237
- isRetryable
1238
- });
1239
- }
1240
- setSessionId(sessionId) {
1241
- this.sessionId = sessionId;
1242
- const warning = validateSessionId(sessionId);
1243
- if (warning) {
1244
- this.logger.warn(`Claude Code Session: ${warning}`);
1245
- }
1246
- }
1247
- validateJsonExtraction(originalText, extractedJson) {
1248
- if (extractedJson === originalText) {
1249
- return {
1250
- valid: false,
1251
- warning: {
1252
- type: "other",
1253
- message: "JSON extraction from model response may be incomplete or modified. The model may not have returned valid JSON."
1254
- }
1255
- };
1256
- }
1257
- try {
1258
- JSON.parse(extractedJson);
1259
- return { valid: true };
1260
- } catch {
1261
- return {
1262
- valid: false,
1263
- warning: {
1264
- type: "other",
1265
- message: "JSON extraction resulted in invalid JSON. The response may be malformed."
1266
- }
1267
- };
1268
- }
1269
- }
1270
- async doGenerate(options) {
1271
- this.logger.debug(`[claude-code] Starting doGenerate request with model: ${this.modelId}`);
1272
- const mode = options.responseFormat?.type === "json" ? { type: "object-json" } : { type: "regular" };
1273
- this.logger.debug(
1274
- `[claude-code] Request mode: ${mode.type}, response format: ${options.responseFormat?.type ?? "none"}`
1275
- );
1276
- const {
1277
- messagesPrompt,
1278
- warnings: messageWarnings,
1279
- streamingContentParts,
1280
- hasImageParts
1281
- } = convertToClaudeCodeMessages(
1282
- options.prompt,
1283
- mode,
1284
- options.responseFormat?.type === "json" ? options.responseFormat.schema : void 0
1285
- );
1286
- this.logger.debug(
1287
- `[claude-code] Converted ${options.prompt.length} messages, hasImageParts: ${hasImageParts}`
1288
- );
1289
- const abortController = new AbortController();
1290
- let abortListener;
1291
- if (options.abortSignal?.aborted) {
1292
- abortController.abort(options.abortSignal.reason);
1293
- } else if (options.abortSignal) {
1294
- abortListener = () => abortController.abort(options.abortSignal?.reason);
1295
- options.abortSignal.addEventListener("abort", abortListener, { once: true });
1296
- }
1297
- const queryOptions = this.createQueryOptions(abortController);
1298
- let text = "";
1299
- let usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
1300
- let finishReason = "stop";
1301
- let wasTruncated = false;
1302
- let costUsd;
1303
- let durationMs;
1304
- let rawUsage;
1305
- const warnings = this.generateAllWarnings(
1306
- options,
1307
- messagesPrompt
1308
- );
1309
- if (messageWarnings) {
1310
- messageWarnings.forEach((warning) => {
1311
- warnings.push({
1312
- type: "other",
1313
- message: warning
1314
- });
1315
- });
1316
- }
1317
- const modeSetting = this.settings.streamingInput ?? "auto";
1318
- const wantsStreamInput = modeSetting === "always" || modeSetting === "auto" && !!this.settings.canUseTool;
1319
- if (!wantsStreamInput && hasImageParts) {
1320
- warnings.push({
1321
- type: "other",
1322
- message: STREAMING_FEATURE_WARNING
1323
- });
1324
- }
1325
- let done = () => {
1326
- };
1327
- const outputStreamEnded = new Promise((resolve) => {
1328
- done = () => resolve(void 0);
1329
- });
1330
- try {
1331
- if (this.settings.canUseTool && this.settings.permissionPromptToolName) {
1332
- throw new Error(
1333
- "canUseTool requires streamingInput mode ('auto' or 'always') and cannot be used with permissionPromptToolName (SDK constraint). Set streamingInput: 'auto' (or 'always') and remove permissionPromptToolName, or remove canUseTool."
1334
- );
1335
- }
1336
- const sdkPrompt = wantsStreamInput ? toAsyncIterablePrompt(
1337
- messagesPrompt,
1338
- outputStreamEnded,
1339
- this.settings.resume ?? this.sessionId,
1340
- streamingContentParts
1341
- ) : messagesPrompt;
1342
- this.logger.debug(
1343
- `[claude-code] Executing query with streamingInput: ${wantsStreamInput}, session: ${this.settings.resume ?? this.sessionId ?? "new"}`
1344
- );
1345
- const response = this.queryFn({
1346
- prompt: sdkPrompt,
1347
- options: queryOptions
1348
- });
1349
- for await (const message of response) {
1350
- this.logger.debug(`[claude-code] Received message type: ${message.type}`);
1351
- if (message.type === "assistant") {
1352
- text += message.message.content.map((c) => c.type === "text" ? c.text : "").join("");
1353
- } else if (message.type === "result") {
1354
- done();
1355
- this.setSessionId(message.session_id);
1356
- costUsd = message.total_cost_usd;
1357
- durationMs = message.duration_ms;
1358
- this.logger.info(
1359
- `[claude-code] Request completed - Session: ${message.session_id}, Cost: $${costUsd?.toFixed(4) ?? "N/A"}, Duration: ${durationMs ?? "N/A"}ms`
1360
- );
1361
- if ("usage" in message) {
1362
- rawUsage = message.usage;
1363
- usage = {
1364
- inputTokens: (message.usage.cache_creation_input_tokens ?? 0) + (message.usage.cache_read_input_tokens ?? 0) + (message.usage.input_tokens ?? 0),
1365
- outputTokens: message.usage.output_tokens ?? 0,
1366
- totalTokens: (message.usage.cache_creation_input_tokens ?? 0) + (message.usage.cache_read_input_tokens ?? 0) + (message.usage.input_tokens ?? 0) + (message.usage.output_tokens ?? 0)
1367
- };
1368
- this.logger.debug(
1369
- `[claude-code] Token usage - Input: ${usage.inputTokens}, Output: ${usage.outputTokens}, Total: ${usage.totalTokens}`
1370
- );
1371
- }
1372
- finishReason = mapClaudeCodeFinishReason(message.subtype);
1373
- this.logger.debug(`[claude-code] Finish reason: ${finishReason}`);
1374
- } else if (message.type === "system" && message.subtype === "init") {
1375
- this.setSessionId(message.session_id);
1376
- this.logger.info(`[claude-code] Session initialized: ${message.session_id}`);
1377
- }
1378
- }
1379
- } catch (error) {
1380
- done();
1381
- this.logger.debug(
1382
- `[claude-code] Error during doGenerate: ${error instanceof Error ? error.message : String(error)}`
1383
- );
1384
- if (isAbortError(error)) {
1385
- this.logger.debug("[claude-code] Request aborted by user");
1386
- throw options.abortSignal?.aborted ? options.abortSignal.reason : error;
1387
- }
1388
- if (isClaudeCodeTruncationError(error, text)) {
1389
- this.logger.warn(
1390
- `[claude-code] Detected truncated response, returning ${text.length} characters of buffered text`
1391
- );
1392
- wasTruncated = true;
1393
- finishReason = "length";
1394
- warnings.push({
1395
- type: "other",
1396
- message: CLAUDE_CODE_TRUNCATION_WARNING
1397
- });
1398
- } else {
1399
- throw this.handleClaudeCodeError(error, messagesPrompt);
1400
- }
1401
- } finally {
1402
- if (options.abortSignal && abortListener) {
1403
- options.abortSignal.removeEventListener("abort", abortListener);
1404
- }
1405
- }
1406
- if (options.responseFormat?.type === "json" && text) {
1407
- text = this.handleJsonExtraction(text, warnings);
1408
- }
1409
- return {
1410
- content: [{ type: "text", text }],
1411
- usage,
1412
- finishReason,
1413
- warnings,
1414
- response: {
1415
- id: generateId(),
1416
- timestamp: /* @__PURE__ */ new Date(),
1417
- modelId: this.modelId
1418
- },
1419
- request: {
1420
- body: messagesPrompt
1421
- },
1422
- providerMetadata: {
1423
- "claude-code": {
1424
- ...this.sessionId !== void 0 && { sessionId: this.sessionId },
1425
- ...costUsd !== void 0 && { costUsd },
1426
- ...durationMs !== void 0 && { durationMs },
1427
- ...rawUsage !== void 0 && { rawUsage },
1428
- ...wasTruncated && { truncated: true }
1429
- }
1430
- }
1431
- };
1432
- }
1433
- async doStream(options) {
1434
- this.logger.debug(`[claude-code] Starting doStream request with model: ${this.modelId}`);
1435
- const mode = options.responseFormat?.type === "json" ? { type: "object-json" } : { type: "regular" };
1436
- this.logger.debug(
1437
- `[claude-code] Stream mode: ${mode.type}, response format: ${options.responseFormat?.type ?? "none"}`
1438
- );
1439
- const {
1440
- messagesPrompt,
1441
- warnings: messageWarnings,
1442
- streamingContentParts,
1443
- hasImageParts
1444
- } = convertToClaudeCodeMessages(
1445
- options.prompt,
1446
- mode,
1447
- options.responseFormat?.type === "json" ? options.responseFormat.schema : void 0
1448
- );
1449
- this.logger.debug(
1450
- `[claude-code] Converted ${options.prompt.length} messages for streaming, hasImageParts: ${hasImageParts}`
1451
- );
1452
- const abortController = new AbortController();
1453
- let abortListener;
1454
- if (options.abortSignal?.aborted) {
1455
- abortController.abort(options.abortSignal.reason);
1456
- } else if (options.abortSignal) {
1457
- abortListener = () => abortController.abort(options.abortSignal?.reason);
1458
- options.abortSignal.addEventListener("abort", abortListener, { once: true });
1459
- }
1460
- const queryOptions = this.createQueryOptions(abortController);
1461
- const warnings = this.generateAllWarnings(
1462
- options,
1463
- messagesPrompt
1464
- );
1465
- if (messageWarnings) {
1466
- messageWarnings.forEach((warning) => {
1467
- warnings.push({
1468
- type: "other",
1469
- message: warning
1470
- });
1471
- });
1472
- }
1473
- const modeSetting = this.settings.streamingInput ?? "auto";
1474
- const wantsStreamInput = modeSetting === "always" || modeSetting === "auto" && !!this.settings.canUseTool;
1475
- if (!wantsStreamInput && hasImageParts) {
1476
- warnings.push({
1477
- type: "other",
1478
- message: STREAMING_FEATURE_WARNING
1479
- });
1480
- }
1481
- const stream = new ReadableStream({
1482
- start: async (controller) => {
1483
- let done = () => {
1484
- };
1485
- const outputStreamEnded = new Promise((resolve) => {
1486
- done = () => resolve(void 0);
1487
- });
1488
- const toolStates = /* @__PURE__ */ new Map();
1489
- const streamWarnings = [];
1490
- const closeToolInput = (toolId, state) => {
1491
- if (!state.inputClosed && state.inputStarted) {
1492
- controller.enqueue({
1493
- type: "tool-input-end",
1494
- id: toolId
1495
- });
1496
- state.inputClosed = true;
1497
- }
1498
- };
1499
- const emitToolCall = (toolId, state) => {
1500
- if (state.callEmitted) {
1501
- return;
1502
- }
1503
- closeToolInput(toolId, state);
1504
- controller.enqueue({
1505
- type: "tool-call",
1506
- toolCallId: toolId,
1507
- toolName: state.name,
1508
- input: state.lastSerializedInput ?? "",
1509
- providerExecuted: true,
1510
- dynamic: true,
1511
- // V3 field: indicates tool is provider-defined (not in user's tools map)
1512
- providerMetadata: {
1513
- "claude-code": {
1514
- // rawInput preserves the original serialized format before AI SDK normalization.
1515
- // Use this if you need the exact string sent to the Claude CLI, which may differ
1516
- // from the `input` field after AI SDK processing.
1517
- rawInput: state.lastSerializedInput ?? ""
1518
- }
1519
- }
1520
- });
1521
- state.callEmitted = true;
1522
- };
1523
- const finalizeToolCalls = () => {
1524
- for (const [toolId, state] of toolStates) {
1525
- emitToolCall(toolId, state);
1526
- }
1527
- toolStates.clear();
1528
- };
1529
- let usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
1530
- let accumulatedText = "";
1531
- let textPartId;
1532
- try {
1533
- controller.enqueue({ type: "stream-start", warnings });
1534
- if (this.settings.canUseTool && this.settings.permissionPromptToolName) {
1535
- throw new Error(
1536
- "canUseTool requires streamingInput mode ('auto' or 'always') and cannot be used with permissionPromptToolName (SDK constraint). Set streamingInput: 'auto' (or 'always') and remove permissionPromptToolName, or remove canUseTool."
1537
- );
1538
- }
1539
- const sdkPrompt = wantsStreamInput ? toAsyncIterablePrompt(
1540
- messagesPrompt,
1541
- outputStreamEnded,
1542
- this.settings.resume ?? this.sessionId,
1543
- streamingContentParts
1544
- ) : messagesPrompt;
1545
- this.logger.debug(
1546
- `[claude-code] Starting stream query with streamingInput: ${wantsStreamInput}, session: ${this.settings.resume ?? this.sessionId ?? "new"}`
1547
- );
1548
- const response = this.queryFn({
1549
- prompt: sdkPrompt,
1550
- options: queryOptions
1551
- });
1552
- for await (const message of response) {
1553
- this.logger.debug(`[claude-code] Stream received message type: ${message.type}`);
1554
- if (message.type === "assistant") {
1555
- if (!message.message?.content) {
1556
- this.logger.warn(
1557
- `[claude-code] Unexpected assistant message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
1558
- );
1559
- continue;
1560
- }
1561
- const content = message.message.content;
1562
- for (const tool3 of this.extractToolUses(content)) {
1563
- const toolId = tool3.id;
1564
- let state = toolStates.get(toolId);
1565
- if (!state) {
1566
- state = {
1567
- name: tool3.name,
1568
- inputStarted: false,
1569
- inputClosed: false,
1570
- callEmitted: false
1571
- };
1572
- toolStates.set(toolId, state);
1573
- this.logger.debug(
1574
- `[claude-code] New tool use detected - Tool: ${tool3.name}, ID: ${toolId}`
1575
- );
1576
- }
1577
- state.name = tool3.name;
1578
- if (!state.inputStarted) {
1579
- this.logger.debug(
1580
- `[claude-code] Tool input started - Tool: ${tool3.name}, ID: ${toolId}`
1581
- );
1582
- controller.enqueue({
1583
- type: "tool-input-start",
1584
- id: toolId,
1585
- toolName: tool3.name,
1586
- providerExecuted: true,
1587
- dynamic: true
1588
- // V3 field: indicates tool is provider-defined
1589
- });
1590
- state.inputStarted = true;
1591
- }
1592
- const serializedInput = this.serializeToolInput(tool3.input);
1593
- if (serializedInput) {
1594
- let deltaPayload = "";
1595
- if (state.lastSerializedInput === void 0) {
1596
- if (serializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE) {
1597
- deltaPayload = serializedInput;
1598
- }
1599
- } else if (serializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE && state.lastSerializedInput.length <= _ClaudeCodeLanguageModel.MAX_DELTA_CALC_SIZE && serializedInput.startsWith(state.lastSerializedInput)) {
1600
- deltaPayload = serializedInput.slice(state.lastSerializedInput.length);
1601
- } else if (serializedInput !== state.lastSerializedInput) {
1602
- deltaPayload = "";
1603
- }
1604
- if (deltaPayload) {
1605
- controller.enqueue({
1606
- type: "tool-input-delta",
1607
- id: toolId,
1608
- delta: deltaPayload
1609
- });
1610
- }
1611
- state.lastSerializedInput = serializedInput;
1612
- }
1613
- }
1614
- const text = content.map((c) => c.type === "text" ? c.text : "").join("");
1615
- if (text) {
1616
- accumulatedText += text;
1617
- if (options.responseFormat?.type !== "json") {
1618
- if (!textPartId) {
1619
- textPartId = generateId();
1620
- controller.enqueue({
1621
- type: "text-start",
1622
- id: textPartId
1623
- });
1624
- }
1625
- controller.enqueue({
1626
- type: "text-delta",
1627
- id: textPartId,
1628
- delta: text
1629
- });
1630
- }
1631
- }
1632
- } else if (message.type === "user") {
1633
- if (!message.message?.content) {
1634
- this.logger.warn(
1635
- `[claude-code] Unexpected user message structure: missing content field. Message type: ${message.type}. This may indicate an SDK protocol violation.`
1636
- );
1637
- continue;
1638
- }
1639
- const content = message.message.content;
1640
- for (const result of this.extractToolResults(content)) {
1641
- let state = toolStates.get(result.id);
1642
- const toolName = result.name ?? state?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
1643
- this.logger.debug(
1644
- `[claude-code] Tool result received - Tool: ${toolName}, ID: ${result.id}`
1645
- );
1646
- if (!state) {
1647
- this.logger.warn(
1648
- `[claude-code] Received tool result for unknown tool ID: ${result.id}`
1649
- );
1650
- state = {
1651
- name: toolName,
1652
- inputStarted: false,
1653
- inputClosed: false,
1654
- callEmitted: false
1655
- };
1656
- toolStates.set(result.id, state);
1657
- if (!state.inputStarted) {
1658
- controller.enqueue({
1659
- type: "tool-input-start",
1660
- id: result.id,
1661
- toolName,
1662
- providerExecuted: true,
1663
- dynamic: true
1664
- // V3 field: indicates tool is provider-defined
1665
- });
1666
- state.inputStarted = true;
1667
- }
1668
- if (!state.inputClosed) {
1669
- controller.enqueue({
1670
- type: "tool-input-end",
1671
- id: result.id
1672
- });
1673
- state.inputClosed = true;
1674
- }
1675
- }
1676
- state.name = toolName;
1677
- const normalizedResult = this.normalizeToolResult(result.result);
1678
- const rawResult = typeof result.result === "string" ? result.result : (() => {
1679
- try {
1680
- return JSON.stringify(result.result);
1681
- } catch {
1682
- return String(result.result);
1683
- }
1684
- })();
1685
- emitToolCall(result.id, state);
1686
- controller.enqueue({
1687
- type: "tool-result",
1688
- toolCallId: result.id,
1689
- toolName,
1690
- result: normalizedResult,
1691
- isError: result.isError,
1692
- providerExecuted: true,
1693
- dynamic: true,
1694
- // V3 field: indicates tool is provider-defined
1695
- providerMetadata: {
1696
- "claude-code": {
1697
- // rawResult preserves the original CLI output string before JSON parsing.
1698
- // Use this when you need the exact string returned by the tool, especially
1699
- // if the `result` field has been parsed/normalized and you need the original format.
1700
- rawResult
1701
- }
1702
- }
1703
- });
1704
- }
1705
- for (const error of this.extractToolErrors(content)) {
1706
- let state = toolStates.get(error.id);
1707
- const toolName = error.name ?? state?.name ?? _ClaudeCodeLanguageModel.UNKNOWN_TOOL_NAME;
1708
- this.logger.debug(
1709
- `[claude-code] Tool error received - Tool: ${toolName}, ID: ${error.id}`
1710
- );
1711
- if (!state) {
1712
- this.logger.warn(
1713
- `[claude-code] Received tool error for unknown tool ID: ${error.id}`
1714
- );
1715
- state = {
1716
- name: toolName,
1717
- inputStarted: true,
1718
- inputClosed: true,
1719
- callEmitted: false
1720
- };
1721
- toolStates.set(error.id, state);
1722
- }
1723
- emitToolCall(error.id, state);
1724
- const rawError = typeof error.error === "string" ? error.error : typeof error.error === "object" && error.error !== null ? (() => {
1725
- try {
1726
- return JSON.stringify(error.error);
1727
- } catch {
1728
- return String(error.error);
1729
- }
1730
- })() : String(error.error);
1731
- controller.enqueue({
1732
- type: "tool-error",
1733
- toolCallId: error.id,
1734
- toolName,
1735
- error: rawError,
1736
- providerExecuted: true,
1737
- dynamic: true,
1738
- // V3 field: indicates tool is provider-defined
1739
- providerMetadata: {
1740
- "claude-code": {
1741
- rawError
1742
- }
1743
- }
1744
- });
1745
- }
1746
- } else if (message.type === "result") {
1747
- done();
1748
- this.logger.info(
1749
- `[claude-code] Stream completed - Session: ${message.session_id}, Cost: $${message.total_cost_usd?.toFixed(4) ?? "N/A"}, Duration: ${message.duration_ms ?? "N/A"}ms`
1750
- );
1751
- let rawUsage;
1752
- if ("usage" in message) {
1753
- rawUsage = message.usage;
1754
- usage = {
1755
- inputTokens: (message.usage.cache_creation_input_tokens ?? 0) + (message.usage.cache_read_input_tokens ?? 0) + (message.usage.input_tokens ?? 0),
1756
- outputTokens: message.usage.output_tokens ?? 0,
1757
- totalTokens: (message.usage.cache_creation_input_tokens ?? 0) + (message.usage.cache_read_input_tokens ?? 0) + (message.usage.input_tokens ?? 0) + (message.usage.output_tokens ?? 0)
1758
- };
1759
- this.logger.debug(
1760
- `[claude-code] Stream token usage - Input: ${usage.inputTokens}, Output: ${usage.outputTokens}, Total: ${usage.totalTokens}`
1761
- );
1762
- }
1763
- const finishReason = mapClaudeCodeFinishReason(
1764
- message.subtype
1765
- );
1766
- this.logger.debug(`[claude-code] Stream finish reason: ${finishReason}`);
1767
- this.setSessionId(message.session_id);
1768
- if (options.responseFormat?.type === "json" && accumulatedText) {
1769
- const extractedJson = this.handleJsonExtraction(accumulatedText, streamWarnings);
1770
- const jsonTextId = generateId();
1771
- controller.enqueue({
1772
- type: "text-start",
1773
- id: jsonTextId
1774
- });
1775
- controller.enqueue({
1776
- type: "text-delta",
1777
- id: jsonTextId,
1778
- delta: extractedJson
1779
- });
1780
- controller.enqueue({
1781
- type: "text-end",
1782
- id: jsonTextId
1783
- });
1784
- } else if (textPartId) {
1785
- controller.enqueue({
1786
- type: "text-end",
1787
- id: textPartId
1788
- });
1789
- }
1790
- finalizeToolCalls();
1791
- const warningsJson = this.serializeWarningsForMetadata(streamWarnings);
1792
- controller.enqueue({
1793
- type: "finish",
1794
- finishReason,
1795
- usage,
1796
- providerMetadata: {
1797
- "claude-code": {
1798
- sessionId: message.session_id,
1799
- ...message.total_cost_usd !== void 0 && {
1800
- costUsd: message.total_cost_usd
1801
- },
1802
- ...message.duration_ms !== void 0 && { durationMs: message.duration_ms },
1803
- ...rawUsage !== void 0 && { rawUsage },
1804
- // JSON validation warnings are collected during streaming and included
1805
- // in providerMetadata since the AI SDK's finish event doesn't support
1806
- // a top-level warnings field (unlike stream-start which was already emitted)
1807
- ...streamWarnings.length > 0 && {
1808
- warnings: warningsJson
1809
- }
1810
- }
1811
- }
1812
- });
1813
- } else if (message.type === "system" && message.subtype === "init") {
1814
- this.setSessionId(message.session_id);
1815
- this.logger.info(`[claude-code] Stream session initialized: ${message.session_id}`);
1816
- controller.enqueue({
1817
- type: "response-metadata",
1818
- id: message.session_id,
1819
- timestamp: /* @__PURE__ */ new Date(),
1820
- modelId: this.modelId
1821
- });
1822
- }
1823
- }
1824
- finalizeToolCalls();
1825
- this.logger.debug("[claude-code] Stream finalized, closing stream");
1826
- controller.close();
1827
- } catch (error) {
1828
- done();
1829
- this.logger.debug(
1830
- `[claude-code] Error during doStream: ${error instanceof Error ? error.message : String(error)}`
1831
- );
1832
- if (isClaudeCodeTruncationError(error, accumulatedText)) {
1833
- this.logger.warn(
1834
- `[claude-code] Detected truncated stream response, returning ${accumulatedText.length} characters of buffered text`
1835
- );
1836
- const truncationWarning = {
1837
- type: "other",
1838
- message: CLAUDE_CODE_TRUNCATION_WARNING
1839
- };
1840
- streamWarnings.push(truncationWarning);
1841
- const emitJsonText = () => {
1842
- const extractedJson = this.handleJsonExtraction(accumulatedText, streamWarnings);
1843
- const jsonTextId = generateId();
1844
- controller.enqueue({
1845
- type: "text-start",
1846
- id: jsonTextId
1847
- });
1848
- controller.enqueue({
1849
- type: "text-delta",
1850
- id: jsonTextId,
1851
- delta: extractedJson
1852
- });
1853
- controller.enqueue({
1854
- type: "text-end",
1855
- id: jsonTextId
1856
- });
1857
- };
1858
- if (options.responseFormat?.type === "json") {
1859
- emitJsonText();
1860
- } else if (textPartId) {
1861
- controller.enqueue({
1862
- type: "text-end",
1863
- id: textPartId
1864
- });
1865
- } else if (accumulatedText) {
1866
- const fallbackTextId = generateId();
1867
- controller.enqueue({
1868
- type: "text-start",
1869
- id: fallbackTextId
1870
- });
1871
- controller.enqueue({
1872
- type: "text-delta",
1873
- id: fallbackTextId,
1874
- delta: accumulatedText
1875
- });
1876
- controller.enqueue({
1877
- type: "text-end",
1878
- id: fallbackTextId
1879
- });
1880
- }
1881
- finalizeToolCalls();
1882
- const warningsJson = this.serializeWarningsForMetadata(streamWarnings);
1883
- controller.enqueue({
1884
- type: "finish",
1885
- finishReason: "length",
1886
- usage,
1887
- providerMetadata: {
1888
- "claude-code": {
1889
- ...this.sessionId !== void 0 && { sessionId: this.sessionId },
1890
- truncated: true,
1891
- ...streamWarnings.length > 0 && {
1892
- warnings: warningsJson
1893
- }
1894
- }
1895
- }
1896
- });
1897
- controller.close();
1898
- return;
1899
- }
1900
- finalizeToolCalls();
1901
- let errorToEmit;
1902
- if (isAbortError(error)) {
1903
- errorToEmit = options.abortSignal?.aborted ? options.abortSignal.reason : error;
1904
- } else {
1905
- errorToEmit = this.handleClaudeCodeError(error, messagesPrompt);
1906
- }
1907
- controller.enqueue({
1908
- type: "error",
1909
- error: errorToEmit
1910
- });
1911
- controller.close();
1912
- } finally {
1913
- if (options.abortSignal && abortListener) {
1914
- options.abortSignal.removeEventListener("abort", abortListener);
1915
- }
1916
- }
1917
- },
1918
- cancel: () => {
1919
- if (options.abortSignal && abortListener) {
1920
- options.abortSignal.removeEventListener("abort", abortListener);
1921
- }
1922
- }
1923
- });
1924
- return {
1925
- stream,
1926
- request: {
1927
- body: messagesPrompt
1928
- }
1929
- };
1930
- }
1931
- serializeWarningsForMetadata(warnings) {
1932
- const result = warnings.map((w) => {
1933
- const base = { type: w.type };
1934
- if ("message" in w) {
1935
- const m = w.message;
1936
- if (m !== void 0) base.message = String(m);
1937
- }
1938
- if (w.type === "unsupported-setting") {
1939
- const setting = w.setting;
1940
- if (setting !== void 0) base.setting = String(setting);
1941
- if ("details" in w) {
1942
- const d = w.details;
1943
- if (d !== void 0) base.details = String(d);
1944
- }
1945
- }
1946
- return base;
1947
- });
1948
- return result;
1949
- }
1950
- };
1951
-
1952
- // src/claude-code-provider.ts
1953
- function createClaudeCode(options = {}) {
1954
- const logger = getLogger(options.defaultSettings?.logger);
1955
- if (options.defaultSettings) {
1956
- const validation = validateSettings(options.defaultSettings);
1957
- if (!validation.valid) {
1958
- throw new Error(`Invalid default settings: ${validation.errors.join(", ")}`);
1959
- }
1960
- if (validation.warnings.length > 0) {
1961
- validation.warnings.forEach((warning) => logger.warn(`Claude Code Provider: ${warning}`));
1962
- }
1963
- }
1964
- const createModel = (modelId, settings = {}) => {
1965
- const mergedSettings = {
1966
- ...options.defaultSettings,
1967
- ...settings
1968
- };
1969
- const validation = validateSettings(mergedSettings);
1970
- if (!validation.valid) {
1971
- throw new Error(`Invalid settings: ${validation.errors.join(", ")}`);
1972
- }
1973
- return new ClaudeCodeLanguageModel({
1974
- id: modelId,
1975
- settings: mergedSettings,
1976
- settingsValidationWarnings: validation.warnings
1977
- });
1978
- };
1979
- const provider = function(modelId, settings) {
1980
- if (new.target) {
1981
- throw new Error("The Claude Code model function cannot be called with the new keyword.");
1982
- }
1983
- return createModel(modelId, settings);
1984
- };
1985
- provider.languageModel = createModel;
1986
- provider.chat = createModel;
1987
- provider.textEmbeddingModel = (modelId) => {
1988
- throw new NoSuchModelError({
1989
- modelId,
1990
- modelType: "textEmbeddingModel"
1991
- });
1992
- };
1993
- provider.imageModel = (modelId) => {
1994
- throw new NoSuchModelError({
1995
- modelId,
1996
- modelType: "imageModel"
1997
- });
1998
- };
1999
- return provider;
2000
- }
2001
- var claudeCode = createClaudeCode();
12
+ import { join } from 'path';
13
+ import WebSocket$1, { WebSocketServer, WebSocket } from 'ws';
14
+ import { drizzle } from 'drizzle-orm/node-postgres';
15
+ import pg from 'pg';
16
+ import { pgTable, timestamp, boolean, text, uuid, index, uniqueIndex, integer, jsonb } from 'drizzle-orm/pg-core';
17
+ import { sql, eq, and, desc, isNull } from 'drizzle-orm';
18
+ import { randomUUID, createHash } from 'crypto';
19
+ import { migrate } from 'drizzle-orm/node-postgres/migrator';
20
+ import { z } from 'zod';
21
+ import os$1 from 'node:os';
22
+ import { randomUUID as randomUUID$1 } from 'node:crypto';
23
+ import express from 'express';
24
+ import { spawn } from 'node:child_process';
25
+ import { EventEmitter } from 'node:events';
26
+ import { createServer, createConnection } from 'node:net';
27
+ import { readFile as readFile$1, rm, writeFile, readdir } from 'node:fs/promises';
28
+ import { simpleGit } from 'simple-git';
29
+ import * as os from 'os';
30
+ import { existsSync as existsSync$1, mkdirSync as mkdirSync$1 } from 'fs';
31
+ import { tunnelManager } from './chunks/manager-CvGX9qqe.js';
32
+ import 'chalk';
33
+ import 'http';
34
+ import 'http-proxy';
35
+ import 'zlib';
2002
36
 
2003
37
  /**
2004
38
  * Creates a permission handler that restricts Claude to a specific project directory
@@ -4133,7 +2167,7 @@ var BuildLogger$1 = class BuildLogger {
4133
2167
  if (typeof process !== "undefined" && process.env.NODE_ENV !== "test") {
4134
2168
  try {
4135
2169
  if (level === "warn" || level === "error") {
4136
- addBreadcrumb({
2170
+ Sentry.addBreadcrumb({
4137
2171
  category: `build-logger.${context}`,
4138
2172
  message,
4139
2173
  level: level === "error" ? "error" : "warning",
@@ -5605,7 +3639,7 @@ var BuildWebSocketServer = class {
5605
3639
  pingInterval,
5606
3640
  userId: runnerUserId
5607
3641
  });
5608
- addBreadcrumb({
3642
+ Sentry.addBreadcrumb({
5609
3643
  category: "websocket",
5610
3644
  message: `Runner connected: ${runnerId}`,
5611
3645
  level: "info"
@@ -5639,7 +3673,7 @@ var BuildWebSocketServer = class {
5639
3673
  }
5640
3674
  } catch (error) {
5641
3675
  this.runnerTotalErrors++;
5642
- captureException(error, {
3676
+ Sentry.captureException(error, {
5643
3677
  tags: { runnerId, source: "websocket_message" },
5644
3678
  level: "error"
5645
3679
  });
@@ -5656,7 +3690,7 @@ var BuildWebSocketServer = class {
5656
3690
  httpProxyManager.cancelRequestsForRunner(runnerId);
5657
3691
  hmrProxyManager$1.disconnectRunner(runnerId);
5658
3692
  this.cleanupRunnerProcesses(runnerId);
5659
- addBreadcrumb({
3693
+ Sentry.addBreadcrumb({
5660
3694
  category: "websocket",
5661
3695
  message: `Runner disconnected: ${runnerId}`,
5662
3696
  level: "info",
@@ -5666,7 +3700,7 @@ var BuildWebSocketServer = class {
5666
3700
  ws.on("error", (error) => {
5667
3701
  buildLogger$2.websocket.error("Runner socket error", error, { runnerId });
5668
3702
  this.runnerTotalErrors++;
5669
- captureException(error, {
3703
+ Sentry.captureException(error, {
5670
3704
  tags: { runnerId, source: "websocket_error" },
5671
3705
  level: "error"
5672
3706
  });
@@ -5707,10 +3741,10 @@ var BuildWebSocketServer = class {
5707
3741
  return false;
5708
3742
  }
5709
3743
  try {
5710
- const activeSpan = getActiveSpan();
3744
+ const activeSpan = Sentry.getActiveSpan();
5711
3745
  const hasTrace = !!activeSpan;
5712
3746
  if (activeSpan) {
5713
- const traceData = getTraceData();
3747
+ const traceData = Sentry.getTraceData();
5714
3748
  if (traceData["sentry-trace"]) {
5715
3749
  command._sentry = {
5716
3750
  trace: traceData["sentry-trace"],
@@ -5727,7 +3761,7 @@ var BuildWebSocketServer = class {
5727
3761
  return true;
5728
3762
  } catch (error) {
5729
3763
  this.runnerTotalErrors++;
5730
- captureException(error, {
3764
+ Sentry.captureException(error, {
5731
3765
  tags: { runnerId, commandType: command.type },
5732
3766
  level: "error"
5733
3767
  });
@@ -5793,7 +3827,7 @@ var BuildWebSocketServer = class {
5793
3827
  for (const [runnerId, conn] of this.runnerConnections.entries()) {
5794
3828
  if (now - conn.lastHeartbeat > this.RUNNER_HEARTBEAT_TIMEOUT) {
5795
3829
  buildLogger$2.websocket.runnerStaleRemoved(runnerId);
5796
- addBreadcrumb({
3830
+ Sentry.addBreadcrumb({
5797
3831
  category: "websocket",
5798
3832
  message: `Stale runner connection removed: ${runnerId}`,
5799
3833
  level: "warning",
@@ -5836,7 +3870,7 @@ var BuildWebSocketServer = class {
5836
3870
  runnerId,
5837
3871
  projectIds
5838
3872
  });
5839
- addBreadcrumb({
3873
+ Sentry.addBreadcrumb({
5840
3874
  category: "websocket",
5841
3875
  message: `Cleaned up processes for disconnected runner`,
5842
3876
  level: "info",
@@ -5851,7 +3885,7 @@ var BuildWebSocketServer = class {
5851
3885
  }
5852
3886
  } catch (error) {
5853
3887
  buildLogger$2.websocket.error("Failed to cleanup runner processes", error, { runnerId });
5854
- captureException(error, {
3888
+ Sentry.captureException(error, {
5855
3889
  tags: { runnerId, source: "runner_cleanup" },
5856
3890
  level: "error"
5857
3891
  });
@@ -6002,10 +4036,10 @@ var BuildWebSocketServer = class {
6002
4036
  updates: []
6003
4037
  });
6004
4038
  }
6005
- const activeSpan = getActiveSpan();
4039
+ const activeSpan = Sentry.getActiveSpan();
6006
4040
  const traceContext = activeSpan ? {
6007
- trace: getTraceData()["sentry-trace"],
6008
- baggage: getTraceData().baggage
4041
+ trace: Sentry.getTraceData()["sentry-trace"],
4042
+ baggage: Sentry.getTraceData().baggage
6009
4043
  } : void 0;
6010
4044
  const batch = this.pendingUpdates.get(key);
6011
4045
  batch.updates.push({
@@ -6037,10 +4071,10 @@ var BuildWebSocketServer = class {
6037
4071
  updates: []
6038
4072
  });
6039
4073
  }
6040
- const activeSpan = getActiveSpan();
4074
+ const activeSpan = Sentry.getActiveSpan();
6041
4075
  const traceContext = activeSpan ? {
6042
- trace: getTraceData()["sentry-trace"],
6043
- baggage: getTraceData().baggage
4076
+ trace: Sentry.getTraceData()["sentry-trace"],
4077
+ baggage: Sentry.getTraceData().baggage
6044
4078
  } : void 0;
6045
4079
  const batch = this.pendingUpdates.get(key);
6046
4080
  batch.updates.push({
@@ -6483,34 +4517,34 @@ var AVAILABLE_ICONS = [
6483
4517
  ];
6484
4518
 
6485
4519
  var AgentCore = /*#__PURE__*/Object.freeze({
6486
- __proto__: null,
6487
- AVAILABLE_ICONS: AVAILABLE_ICONS,
6488
- CLAUDE_SYSTEM_PROMPT: CLAUDE_SYSTEM_PROMPT,
6489
- CODEX_SYSTEM_PROMPT: CODEX_SYSTEM_PROMPT,
6490
- DEFAULT_AGENT_ID: DEFAULT_AGENT_ID,
6491
- DEFAULT_CLAUDE_MODEL_ID: DEFAULT_CLAUDE_MODEL_ID,
6492
- DEFAULT_OPENCODE_MODEL_ID: DEFAULT_OPENCODE_MODEL_ID,
6493
- GITHUB_CHAT_MESSAGES: GITHUB_CHAT_MESSAGES,
6494
- LEGACY_MODEL_MAP: LEGACY_MODEL_MAP,
6495
- MODEL_METADATA: MODEL_METADATA,
6496
- NEONDB_CHAT_MESSAGES: NEONDB_CHAT_MESSAGES,
6497
- ProjectMetadataSchema: ProjectMetadataSchema,
6498
- ProjectNamingSchema: ProjectNamingSchema,
6499
- TemplateAnalysisSchema: TemplateAnalysisSchema,
6500
- buildLogger: buildLogger$2,
6501
- buildWebSocketServer: buildWebSocketServer,
6502
- db: db,
6503
- getDb: getDb,
6504
- getModelLabel: getModelLabel,
6505
- initializeDatabase: initializeDatabase,
6506
- isRunnerCommand: isRunnerCommand,
6507
- isRunnerEvent: isRunnerEvent,
6508
- normalizeModelId: normalizeModelId,
6509
- parseModelId: parseModelId,
6510
- resetDatabase: resetDatabase,
6511
- resolveAgentStrategy: resolveAgentStrategy$1,
6512
- runMigrations: runMigrations,
6513
- setTemplatesPath: setTemplatesPath$1
4520
+ __proto__: null,
4521
+ AVAILABLE_ICONS: AVAILABLE_ICONS,
4522
+ CLAUDE_SYSTEM_PROMPT: CLAUDE_SYSTEM_PROMPT,
4523
+ CODEX_SYSTEM_PROMPT: CODEX_SYSTEM_PROMPT,
4524
+ DEFAULT_AGENT_ID: DEFAULT_AGENT_ID,
4525
+ DEFAULT_CLAUDE_MODEL_ID: DEFAULT_CLAUDE_MODEL_ID,
4526
+ DEFAULT_OPENCODE_MODEL_ID: DEFAULT_OPENCODE_MODEL_ID,
4527
+ GITHUB_CHAT_MESSAGES: GITHUB_CHAT_MESSAGES,
4528
+ LEGACY_MODEL_MAP: LEGACY_MODEL_MAP,
4529
+ MODEL_METADATA: MODEL_METADATA,
4530
+ NEONDB_CHAT_MESSAGES: NEONDB_CHAT_MESSAGES,
4531
+ ProjectMetadataSchema: ProjectMetadataSchema,
4532
+ ProjectNamingSchema: ProjectNamingSchema,
4533
+ TemplateAnalysisSchema: TemplateAnalysisSchema,
4534
+ buildLogger: buildLogger$2,
4535
+ buildWebSocketServer: buildWebSocketServer,
4536
+ db: db,
4537
+ getDb: getDb,
4538
+ getModelLabel: getModelLabel,
4539
+ initializeDatabase: initializeDatabase,
4540
+ isRunnerCommand: isRunnerCommand,
4541
+ isRunnerEvent: isRunnerEvent,
4542
+ normalizeModelId: normalizeModelId,
4543
+ parseModelId: parseModelId,
4544
+ resetDatabase: resetDatabase,
4545
+ resolveAgentStrategy: resolveAgentStrategy$1,
4546
+ runMigrations: runMigrations,
4547
+ setTemplatesPath: setTemplatesPath$1
6514
4548
  });
6515
4549
 
6516
4550
  /**
@@ -6529,9 +4563,9 @@ var AgentCore = /*#__PURE__*/Object.freeze({
6529
4563
  * - Direct streaming without adaptation layer
6530
4564
  */
6531
4565
  // Debug logging helper - suppressed in TUI mode (SILENT_MODE=1)
6532
- const debugLog$4 = (message) => {
4566
+ const debugLog$3 = (message) => {
6533
4567
  if (process.env.SILENT_MODE !== '1' && process.env.DEBUG_BUILD === '1') {
6534
- debugLog$4();
4568
+ debugLog$3();
6535
4569
  }
6536
4570
  };
6537
4571
  /**
@@ -6650,10 +4684,10 @@ function buildPromptWithImages(prompt, messageParts) {
6650
4684
  */
6651
4685
  function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortController) {
6652
4686
  return async function* nativeClaudeQuery(prompt, workingDirectory, systemPrompt, _agent, _codexThreadId, messageParts) {
6653
- debugLog$4();
6654
- debugLog$4();
6655
- debugLog$4();
6656
- debugLog$4(`[runner] [native-sdk] Prompt length: ${prompt.length}\n`);
4687
+ debugLog$3();
4688
+ debugLog$3();
4689
+ debugLog$3();
4690
+ debugLog$3(`[runner] [native-sdk] Prompt length: ${prompt.length}\n`);
6657
4691
  // Build combined system prompt
6658
4692
  const systemPromptSegments = [CLAUDE_SYSTEM_PROMPT.trim()];
6659
4693
  if (systemPrompt && systemPrompt.trim().length > 0) {
@@ -6661,7 +4695,7 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
6661
4695
  }
6662
4696
  const appendedSystemPrompt = systemPromptSegments.join('\n\n');
6663
4697
  // Ensure working directory exists
6664
- if (!existsSync$1(workingDirectory)) {
4698
+ if (!existsSync(workingDirectory)) {
6665
4699
  console.log(`[native-sdk] Creating working directory: ${workingDirectory}`);
6666
4700
  mkdirSync(workingDirectory, { recursive: true });
6667
4701
  }
@@ -6669,7 +4703,7 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
6669
4703
  const hasImages = messageParts?.some(p => p.type === 'image');
6670
4704
  if (hasImages) {
6671
4705
  messageParts?.filter(p => p.type === 'image').length || 0;
6672
- debugLog$4();
4706
+ debugLog$3();
6673
4707
  }
6674
4708
  // Build the final prompt
6675
4709
  const finalPrompt = buildPromptWithImages(prompt);
@@ -6703,7 +4737,7 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
6703
4737
  // See: https://github.com/anthropics/claude-agent-sdk-typescript/issues/46
6704
4738
  abortController,
6705
4739
  };
6706
- debugLog$4();
4740
+ debugLog$3();
6707
4741
  let messageCount = 0;
6708
4742
  let toolCallCount = 0;
6709
4743
  let textBlockCount = 0;
@@ -6720,7 +4754,7 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
6720
4754
  for (const block of transformed.message.content) {
6721
4755
  if (block.type === 'tool_use') {
6722
4756
  toolCallCount++;
6723
- debugLog$4(`[runner] [native-sdk] 🔧 Tool call: ${block.name}\n`);
4757
+ debugLog$3(`[runner] [native-sdk] 🔧 Tool call: ${block.name}\n`);
6724
4758
  }
6725
4759
  else if (block.type === 'text') {
6726
4760
  textBlockCount++;
@@ -6732,29 +4766,22 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
6732
4766
  // Log result messages
6733
4767
  if (sdkMessage.type === 'result') {
6734
4768
  if (sdkMessage.subtype === 'success') {
6735
- debugLog$4(`[runner] [native-sdk] ✅ Query complete - ${sdkMessage.num_turns} turns, $${sdkMessage.total_cost_usd?.toFixed(4)} USD\n`);
4769
+ debugLog$3(`[runner] [native-sdk] ✅ Query complete - ${sdkMessage.num_turns} turns, $${sdkMessage.total_cost_usd?.toFixed(4)} USD\n`);
6736
4770
  }
6737
4771
  else {
6738
- debugLog$4(`[runner] [native-sdk] ⚠️ Query ended with: ${sdkMessage.subtype}\n`);
4772
+ debugLog$3(`[runner] [native-sdk] ⚠️ Query ended with: ${sdkMessage.subtype}\n`);
6739
4773
  }
6740
4774
  }
6741
4775
  }
6742
- debugLog$4(`[runner] [native-sdk] 📊 Stream complete - ${messageCount} messages, ${toolCallCount} tool calls, ${textBlockCount} text blocks\n`);
4776
+ debugLog$3(`[runner] [native-sdk] 📊 Stream complete - ${messageCount} messages, ${toolCallCount} tool calls, ${textBlockCount} text blocks\n`);
6743
4777
  }
6744
4778
  catch (error) {
6745
- debugLog$4(`[runner] [native-sdk] ❌ Error: ${error instanceof Error ? error.message : String(error)}\n`);
6746
- captureException(error);
4779
+ debugLog$3(`[runner] [native-sdk] ❌ Error: ${error instanceof Error ? error.message : String(error)}\n`);
4780
+ Sentry.captureException(error);
6747
4781
  throw error;
6748
4782
  }
6749
4783
  };
6750
4784
  }
6751
- /**
6752
- * Feature flag to control which implementation to use
6753
- *
6754
- * Default: Native SDK is enabled (true)
6755
- * Set USE_LEGACY_AI_SDK=1 to use the old AI SDK + community provider path
6756
- */
6757
- const USE_NATIVE_SDK = process.env.USE_LEGACY_AI_SDK !== '1';
6758
4785
 
6759
4786
  /**
6760
4787
  * OpenCode SDK Integration
@@ -6769,7 +4796,7 @@ const USE_NATIVE_SDK = process.env.USE_LEGACY_AI_SDK !== '1';
6769
4796
  * - Runner receives events and transforms them to SSE format for the frontend
6770
4797
  */
6771
4798
  // Debug logging helper
6772
- const debugLog$3 = (message) => {
4799
+ const debugLog$2 = (message) => {
6773
4800
  if (process.env.SILENT_MODE !== '1' && process.env.DEBUG_BUILD === '1') {
6774
4801
  console.error(message);
6775
4802
  }
@@ -6934,12 +4961,12 @@ function parseSSEEvent(data) {
6934
4961
  */
6935
4962
  function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
6936
4963
  return async function* openCodeQuery(prompt, workingDirectory, systemPrompt, _agent, _codexThreadId, messageParts) {
6937
- debugLog$3('[runner] [opencode-sdk] Starting OpenCode query');
6938
- debugLog$3(`[runner] [opencode-sdk] Model: ${modelId}`);
6939
- debugLog$3(`[runner] [opencode-sdk] Working dir: ${workingDirectory}`);
6940
- debugLog$3(`[runner] [opencode-sdk] Prompt length: ${prompt.length}`);
4964
+ debugLog$2('[runner] [opencode-sdk] Starting OpenCode query');
4965
+ debugLog$2(`[runner] [opencode-sdk] Model: ${modelId}`);
4966
+ debugLog$2(`[runner] [opencode-sdk] Working dir: ${workingDirectory}`);
4967
+ debugLog$2(`[runner] [opencode-sdk] Prompt length: ${prompt.length}`);
6941
4968
  // Ensure working directory exists
6942
- if (!existsSync$1(workingDirectory)) {
4969
+ if (!existsSync(workingDirectory)) {
6943
4970
  console.log(`[opencode-sdk] Creating working directory: ${workingDirectory}`);
6944
4971
  mkdirSync(workingDirectory, { recursive: true });
6945
4972
  }
@@ -6963,7 +4990,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
6963
4990
  let sessionId = null;
6964
4991
  // Start Sentry AI agent span for the entire OpenCode query
6965
4992
  // This provides visibility into AI operations in Sentry's trace view
6966
- const aiSpan = startInactiveSpan({
4993
+ const aiSpan = Sentry.startInactiveSpan({
6967
4994
  name: 'opencode.query',
6968
4995
  op: 'ai.pipeline',
6969
4996
  attributes: {
@@ -6977,7 +5004,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
6977
5004
  });
6978
5005
  try {
6979
5006
  // Step 1: Create a session
6980
- debugLog$3('[runner] [opencode-sdk] Creating session...');
5007
+ debugLog$2('[runner] [opencode-sdk] Creating session...');
6981
5008
  const sessionResponse = await fetch(`${baseUrl}/session`, {
6982
5009
  method: 'POST',
6983
5010
  headers,
@@ -6991,13 +5018,13 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
6991
5018
  }
6992
5019
  const session = await sessionResponse.json();
6993
5020
  sessionId = session.id;
6994
- debugLog$3(`[runner] [opencode-sdk] Session created: ${sessionId}`);
5021
+ debugLog$2(`[runner] [opencode-sdk] Session created: ${sessionId}`);
6995
5022
  // Update span with session info
6996
5023
  if (sessionId) {
6997
5024
  aiSpan?.setAttribute('opencode.session_id', sessionId);
6998
5025
  }
6999
5026
  // Step 2: Subscribe to events
7000
- debugLog$3('[runner] [opencode-sdk] Subscribing to events...');
5027
+ debugLog$2('[runner] [opencode-sdk] Subscribing to events...');
7001
5028
  const eventResponse = await fetch(`${baseUrl}/event`, {
7002
5029
  headers: {
7003
5030
  ...headers,
@@ -7018,7 +5045,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
7018
5045
  image: part.image,
7019
5046
  mimeType: part.mimeType || 'image/png',
7020
5047
  });
7021
- debugLog$3('[runner] [opencode-sdk] Added image part');
5048
+ debugLog$2('[runner] [opencode-sdk] Added image part');
7022
5049
  }
7023
5050
  }
7024
5051
  }
@@ -7028,7 +5055,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
7028
5055
  text: prompt,
7029
5056
  });
7030
5057
  // Step 4: Send the prompt (don't await - we'll stream the response)
7031
- debugLog$3('[runner] [opencode-sdk] Sending prompt...');
5058
+ debugLog$2('[runner] [opencode-sdk] Sending prompt...');
7032
5059
  const promptPromise = fetch(`${baseUrl}/session/${sessionId}/message`, {
7033
5060
  method: 'POST',
7034
5061
  headers,
@@ -7052,7 +5079,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
7052
5079
  while (!completed) {
7053
5080
  const { done, value } = await reader.read();
7054
5081
  if (done) {
7055
- debugLog$3('[runner] [opencode-sdk] Event stream ended');
5082
+ debugLog$2('[runner] [opencode-sdk] Event stream ended');
7056
5083
  break;
7057
5084
  }
7058
5085
  buffer += decoder.decode(value, { stream: true });
@@ -7120,15 +5147,15 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
7120
5147
  subtype: 'success',
7121
5148
  };
7122
5149
  }
7123
- debugLog$3('[runner] [opencode-sdk] Query complete');
5150
+ debugLog$2('[runner] [opencode-sdk] Query complete');
7124
5151
  // Update span with final metrics
7125
5152
  aiSpan?.setAttribute('opencode.tool_calls', toolCallCount);
7126
5153
  aiSpan?.setAttribute('opencode.messages', messageCount);
7127
5154
  aiSpan?.setStatus({ code: 1 }); // OK status
7128
5155
  }
7129
5156
  catch (error) {
7130
- debugLog$3(`[runner] [opencode-sdk] Error: ${error instanceof Error ? error.message : String(error)}`);
7131
- captureException(error);
5157
+ debugLog$2(`[runner] [opencode-sdk] Error: ${error instanceof Error ? error.message : String(error)}`);
5158
+ Sentry.captureException(error);
7132
5159
  // Mark span as errored
7133
5160
  aiSpan?.setStatus({ code: 2, message: error instanceof Error ? error.message : String(error) });
7134
5161
  // Yield error result
@@ -7155,141 +5182,6 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
7155
5182
  */
7156
5183
  const USE_OPENCODE_SDK = process.env.USE_OPENCODE_SDK === '1' && !!process.env.OPENCODE_URL;
7157
5184
 
7158
- // src/lib/claude/tools.ts
7159
- var genericInput = z.any();
7160
- var genericObject = z.record(z.string(), z.any());
7161
- var dynamicMcpTool = {
7162
- description: "Generic MCP tool passthrough",
7163
- type: "dynamic",
7164
- inputSchema: genericObject
7165
- };
7166
- var fallbackTool = {
7167
- description: "Fallback Claude CLI tool",
7168
- inputSchema: genericInput
7169
- };
7170
- var builtinTools = {
7171
- Agent: {
7172
- description: "Launches a nested Claude agent",
7173
- inputSchema: genericObject
7174
- },
7175
- Bash: {
7176
- description: "Execute shell commands via Claude CLI",
7177
- inputSchema: genericObject
7178
- },
7179
- BashOutput: {
7180
- description: "Fetch output from a background bash process",
7181
- inputSchema: genericObject
7182
- },
7183
- ExitPlanMode: {
7184
- description: "Exit plan/approval mode with a summary",
7185
- inputSchema: genericObject
7186
- },
7187
- Read: {
7188
- description: "Read file contents",
7189
- inputSchema: genericObject
7190
- },
7191
- Write: {
7192
- description: "Write entire file contents",
7193
- inputSchema: genericObject
7194
- },
7195
- Edit: {
7196
- description: "Edit part of a file by replacing text",
7197
- inputSchema: genericObject
7198
- },
7199
- Glob: {
7200
- description: "Match files using glob patterns",
7201
- inputSchema: genericObject
7202
- },
7203
- Grep: {
7204
- description: "Search files for a regex pattern",
7205
- inputSchema: genericObject
7206
- },
7207
- KillShell: {
7208
- description: "Stop a running bash session",
7209
- inputSchema: genericObject
7210
- },
7211
- ListMcpResources: {
7212
- description: "Enumerate MCP resources",
7213
- inputSchema: genericObject
7214
- },
7215
- Mcp: {
7216
- description: "Invoke an MCP tool",
7217
- inputSchema: genericObject
7218
- },
7219
- NotebookEdit: {
7220
- description: "Edit Jupyter notebooks",
7221
- inputSchema: genericObject
7222
- },
7223
- ReadMcpResource: {
7224
- description: "Read a particular MCP resource",
7225
- inputSchema: genericObject
7226
- },
7227
- TimeMachine: {
7228
- description: "Rewind conversation with a course correction",
7229
- inputSchema: genericObject
7230
- },
7231
- TodoWrite: {
7232
- description: "Emit TODO status updates",
7233
- inputSchema: genericObject
7234
- },
7235
- WebFetch: {
7236
- description: "Fetch and summarize a URL",
7237
- inputSchema: genericObject
7238
- },
7239
- WebSearch: {
7240
- description: "Search the web with constraints",
7241
- inputSchema: genericObject
7242
- },
7243
- MultipleChoiceQuestion: {
7244
- description: "Ask the user a multiple choice question",
7245
- inputSchema: genericObject
7246
- },
7247
- // Common aliases seen in telemetry/logs
7248
- LS: {
7249
- description: "List files in the working directory",
7250
- inputSchema: genericObject
7251
- },
7252
- TodoRead: {
7253
- description: "Read TODO state emitted from runner",
7254
- inputSchema: genericObject
7255
- }
7256
- };
7257
- var proxyHandler = {
7258
- get(target, prop) {
7259
- if (typeof prop !== "string") {
7260
- return Reflect.get(target, prop);
7261
- }
7262
- if (Reflect.has(target, prop)) {
7263
- return Reflect.get(target, prop);
7264
- }
7265
- if (prop.startsWith("mcp__")) {
7266
- return dynamicMcpTool;
7267
- }
7268
- return fallbackTool;
7269
- },
7270
- has(target, prop) {
7271
- if (typeof prop === "string") {
7272
- if (Reflect.has(target, prop) || prop.startsWith("mcp__")) {
7273
- return true;
7274
- }
7275
- }
7276
- return Reflect.has(target, prop);
7277
- },
7278
- ownKeys(target) {
7279
- return Reflect.ownKeys(target);
7280
- },
7281
- getOwnPropertyDescriptor(target, prop) {
7282
- if (Reflect.has(target, prop)) {
7283
- return Object.getOwnPropertyDescriptor(target, prop);
7284
- }
7285
- return void 0;
7286
- }
7287
- };
7288
- function createClaudeToolRegistry() {
7289
- return new Proxy(builtinTools, proxyHandler);
7290
- }
7291
- var CLAUDE_CLI_TOOL_REGISTRY = createClaudeToolRegistry();
7292
-
7293
5185
  // src/lib/logging/build-logger.ts
7294
5186
  var BuildLogger = class {
7295
5187
  buildId = null;
@@ -7344,7 +5236,7 @@ var BuildLogger = class {
7344
5236
  if (typeof process !== "undefined" && process.env.NODE_ENV !== "test") {
7345
5237
  try {
7346
5238
  if (level === "warn" || level === "error") {
7347
- addBreadcrumb({
5239
+ Sentry.addBreadcrumb({
7348
5240
  category: `build-logger.${context}`,
7349
5241
  message,
7350
5242
  level: level === "error" ? "error" : "warning",
@@ -8830,9 +6722,9 @@ async function resolveAgentStrategy(agentId) {
8830
6722
  }
8831
6723
 
8832
6724
  // Debug logging helper - suppressed in TUI mode (SILENT_MODE=1)
8833
- const debugLog$2 = (message) => {
6725
+ const debugLog$1 = (message) => {
8834
6726
  if (process.env.SILENT_MODE !== '1' && process.env.DEBUG_BUILD === '1') {
8835
- debugLog$2();
6727
+ debugLog$1();
8836
6728
  }
8837
6729
  };
8838
6730
  /**
@@ -8843,7 +6735,7 @@ async function createBuildStream(options) {
8843
6735
  // For Codex on NEW projects, use parent directory as CWD (Codex will create the project dir)
8844
6736
  // For everything else, use the project directory
8845
6737
  const strategy = await resolveAgentStrategy(agent);
8846
- const projectName = options.projectName || require$$1.basename(workingDirectory);
6738
+ const projectName = options.projectName || path$1.basename(workingDirectory);
8847
6739
  const strategyContext = {
8848
6740
  projectId: options.projectId,
8849
6741
  projectName,
@@ -8858,7 +6750,7 @@ async function createBuildStream(options) {
8858
6750
  if (process.env.DEBUG_BUILD === '1')
8859
6751
  console.log(`[engine] Strategy adjusted CWD to: ${actualWorkingDir}`);
8860
6752
  }
8861
- else if (!existsSync$1(workingDirectory)) {
6753
+ else if (!existsSync(workingDirectory)) {
8862
6754
  mkdirSync(workingDirectory, { recursive: true });
8863
6755
  }
8864
6756
  if (!resolvedDir) {
@@ -8877,19 +6769,19 @@ async function createBuildStream(options) {
8877
6769
  // Pass prompt, working directory, and system prompt to the query function
8878
6770
  // The buildQuery wrapper will configure the SDK with all options
8879
6771
  // Use actualWorkingDir so the query function gets the correct CWD
8880
- debugLog$2();
6772
+ debugLog$1();
8881
6773
  const generator = query(fullPrompt, actualWorkingDir, systemPrompt, agent, options.codexThreadId, messageParts);
8882
- debugLog$2();
6774
+ debugLog$1();
8883
6775
  // Create a ReadableStream from the AsyncGenerator
8884
6776
  const stream = new ReadableStream({
8885
6777
  async start(controller) {
8886
- debugLog$2();
6778
+ debugLog$1();
8887
6779
  let chunkCount = 0;
8888
6780
  try {
8889
6781
  for await (const chunk of generator) {
8890
6782
  chunkCount++;
8891
6783
  if (chunkCount % 5 === 0) {
8892
- debugLog$2(`[runner] [build-engine] Processed ${chunkCount} chunks from generator\n`);
6784
+ debugLog$1(`[runner] [build-engine] Processed ${chunkCount} chunks from generator\n`);
8893
6785
  }
8894
6786
  // Convert chunk to appropriate format
8895
6787
  if (typeof chunk === 'string') {
@@ -8902,11 +6794,11 @@ async function createBuildStream(options) {
8902
6794
  controller.enqueue(new TextEncoder().encode(JSON.stringify(chunk)));
8903
6795
  }
8904
6796
  }
8905
- debugLog$2(`[runner] [build-engine] ✅ Generator exhausted after ${chunkCount} chunks, closing stream\n`);
6797
+ debugLog$1(`[runner] [build-engine] ✅ Generator exhausted after ${chunkCount} chunks, closing stream\n`);
8906
6798
  controller.close();
8907
6799
  }
8908
6800
  catch (error) {
8909
- debugLog$2();
6801
+ debugLog$1();
8910
6802
  controller.error(error);
8911
6803
  }
8912
6804
  finally {
@@ -8915,7 +6807,7 @@ async function createBuildStream(options) {
8915
6807
  }
8916
6808
  },
8917
6809
  });
8918
- debugLog$2();
6810
+ debugLog$1();
8919
6811
  return stream;
8920
6812
  }
8921
6813
 
@@ -9134,7 +7026,7 @@ function classifyStartupError(error, processInfo) {
9134
7026
  suggestion: 'Check file permissions and ownership'
9135
7027
  };
9136
7028
  }
9137
- if (processInfo.cwd && !existsSync$1(processInfo.cwd)) {
7029
+ if (processInfo.cwd && !existsSync(processInfo.cwd)) {
9138
7030
  return {
9139
7031
  reason: FailureReason.DIRECTORY_MISSING,
9140
7032
  message: `Working directory does not exist: ${processInfo.cwd}`,
@@ -9198,7 +7090,7 @@ function startDevServer(options) {
9198
7090
  buildLogger$1.processManager.processStarting(projectId, command, cwd);
9199
7091
  const emitter = new EventEmitter();
9200
7092
  // Verify CWD exists
9201
- if (!existsSync$1(cwd)) {
7093
+ if (!existsSync(cwd)) {
9202
7094
  const error = new Error(`Working directory does not exist: ${cwd}`);
9203
7095
  buildLogger$1.processManager.error('Failed to spawn process', error, { projectId });
9204
7096
  emitter.emit('error', error);
@@ -9435,7 +7327,7 @@ async function waitForPortRelease(port, maxWaitMs = 10000, pollIntervalMs = 500)
9435
7327
  */
9436
7328
  function fixPackageJsonPort(cwd, targetPort) {
9437
7329
  const packageJsonPath = join$1(cwd, 'package.json');
9438
- if (!existsSync$1(packageJsonPath)) {
7330
+ if (!existsSync(packageJsonPath)) {
9439
7331
  buildLogger$1.log('debug', 'process-manager', 'No package.json found to fix', { cwd });
9440
7332
  return false;
9441
7333
  }
@@ -9562,19 +7454,19 @@ async function stopAllDevServers(tunnelManager) {
9562
7454
  }
9563
7455
 
9564
7456
  var processManager = /*#__PURE__*/Object.freeze({
9565
- __proto__: null,
9566
- get FailureReason () { return FailureReason; },
9567
- get ProcessState () { return ProcessState; },
9568
- checkPortInUse: checkPortInUse,
9569
- findAvailablePort: findAvailablePort,
9570
- getAllActiveProjectIds: getAllActiveProjectIds,
9571
- runHealthCheck: runHealthCheck,
9572
- setSilentMode: setSilentMode$1,
9573
- startDevServer: startDevServer,
9574
- startDevServerAsync: startDevServerAsync,
9575
- stopAllDevServers: stopAllDevServers,
9576
- stopDevServer: stopDevServer,
9577
- waitForPortRelease: waitForPortRelease
7457
+ __proto__: null,
7458
+ get FailureReason () { return FailureReason; },
7459
+ get ProcessState () { return ProcessState; },
7460
+ checkPortInUse: checkPortInUse,
7461
+ findAvailablePort: findAvailablePort,
7462
+ getAllActiveProjectIds: getAllActiveProjectIds,
7463
+ runHealthCheck: runHealthCheck,
7464
+ setSilentMode: setSilentMode$1,
7465
+ startDevServer: startDevServer,
7466
+ startDevServerAsync: startDevServerAsync,
7467
+ stopAllDevServers: stopAllDevServers,
7468
+ stopDevServer: stopDevServer,
7469
+ waitForPortRelease: waitForPortRelease
9578
7470
  });
9579
7471
 
9580
7472
  /**
@@ -9584,7 +7476,7 @@ var processManager = /*#__PURE__*/Object.freeze({
9584
7476
  function getWorkspaceRoot() {
9585
7477
  // Check environment variable first
9586
7478
  const envWorkspace = process.env.WORKSPACE_ROOT;
9587
- if (envWorkspace && existsSync$1(envWorkspace)) {
7479
+ if (envWorkspace && existsSync(envWorkspace)) {
9588
7480
  return resolve(envWorkspace);
9589
7481
  }
9590
7482
  // Default to a workspace directory in the user's home
@@ -9897,296 +7789,6 @@ function transformAgentMessageToSSE(agentMessage) {
9897
7789
  return events;
9898
7790
  }
9899
7791
 
9900
- // Debug logging helper - suppressed in TUI mode (SILENT_MODE=1)
9901
- const debugLog$1 = (message) => {
9902
- if (process.env.SILENT_MODE !== '1' && process.env.DEBUG_BUILD === '1') {
9903
- debugLog$1();
9904
- }
9905
- };
9906
- /**
9907
- * Truncate strings for logging to prevent excessive output
9908
- */
9909
- function truncate$1(str, maxLength = 200) {
9910
- if (str.length <= maxLength)
9911
- return str;
9912
- return str.substring(0, maxLength) + '...';
9913
- }
9914
- /**
9915
- * Truncate JSON objects for logging
9916
- */
9917
- function truncateJSON$1(obj, maxLength = 200) {
9918
- const json = JSON.stringify(obj, null, 2);
9919
- return truncate$1(json, maxLength);
9920
- }
9921
- /**
9922
- * Transforms AI SDK stream events into messages compatible with our message transformer
9923
- */
9924
- async function* transformAISDKStream(stream) {
9925
- const DEBUG = process.env.DEBUG_BUILD === '1';
9926
- let currentMessageId = `msg-${Date.now()}`; // Always have a default ID
9927
- let currentTextContent = '';
9928
- const toolInputBuffer = new Map();
9929
- const toolResults = new Map();
9930
- let eventCount = 0;
9931
- let yieldCount = 0;
9932
- // Track active tool spans for proper duration measurement
9933
- const activeToolSpans = new Map();
9934
- // ALWAYS log start - write to stderr to bypass TUI console interceptor
9935
- debugLog$1();
9936
- streamLog.info('━━━ STREAM TRANSFORMATION STARTED ━━━');
9937
- for await (const part of stream) {
9938
- eventCount++;
9939
- // Log ALL events to file (first 50)
9940
- if (eventCount <= 50) {
9941
- streamLog.event(eventCount, part.type, part);
9942
- }
9943
- // DEBUG: Log first 20 events with full JSON to see what we're actually getting
9944
- if (DEBUG && eventCount <= 20) {
9945
- debugLog$1(`[runner] [ai-sdk-adapter] Event #${eventCount}: type="${part.type}"\n`);
9946
- debugLog$1(`[runner] [ai-sdk-adapter] Full JSON: ${truncateJSON$1(part, 500)}\n`);
9947
- }
9948
- if (DEBUG)
9949
- console.log('[ai-sdk-adapter] Event:', part.type, part);
9950
- // DEBUG: Log every 10 events to show progress
9951
- if (DEBUG && eventCount % 10 === 0) {
9952
- debugLog$1();
9953
- }
9954
- switch (part.type) {
9955
- case 'start':
9956
- case 'start-step':
9957
- // Update message ID if provided
9958
- if (part.id) {
9959
- currentMessageId = part.id;
9960
- if (DEBUG)
9961
- debugLog$1();
9962
- }
9963
- break;
9964
- case 'text-start':
9965
- // Capture message ID from text-start event
9966
- if (part.id) {
9967
- currentMessageId = part.id;
9968
- if (DEBUG)
9969
- debugLog$1();
9970
- }
9971
- break;
9972
- case 'text-delta':
9973
- // Just accumulate text content - DON'T yield for every token!
9974
- // We'll only yield when there's a tool call or the message finishes
9975
- const textChunk = part.delta ?? part.text ?? part.textDelta;
9976
- if (typeof textChunk === 'string') {
9977
- currentTextContent += textChunk;
9978
- // Update message ID if provided in the event
9979
- if (part.id) {
9980
- currentMessageId = part.id;
9981
- }
9982
- }
9983
- break;
9984
- case 'tool-input-start':
9985
- // Start buffering tool input
9986
- toolInputBuffer.set(part.id, {
9987
- name: part.toolName,
9988
- input: '',
9989
- });
9990
- break;
9991
- case 'tool-input-delta':
9992
- // Accumulate tool input
9993
- const buffer = toolInputBuffer.get(part.id);
9994
- if (buffer) {
9995
- buffer.input += part.delta || '';
9996
- }
9997
- break;
9998
- case 'tool-input-end':
9999
- case 'tool-call':
10000
- // Tool call is complete - emit it
10001
- const toolCallId = part.toolCallId || part.id;
10002
- const toolName = part.toolName;
10003
- let toolInput = part.args || part.input;
10004
- // If we have buffered input, parse it
10005
- if (!toolInput && toolInputBuffer.has(toolCallId) && typeof toolCallId === 'string') {
10006
- const buffered = toolInputBuffer.get(toolCallId);
10007
- if (buffered?.input) {
10008
- if (typeof buffered.input === 'string') {
10009
- try {
10010
- toolInput = JSON.parse(buffered.input);
10011
- }
10012
- catch {
10013
- toolInput = { raw: buffered.input };
10014
- }
10015
- }
10016
- try {
10017
- toolInput = JSON.parse(buffered.input);
10018
- }
10019
- catch {
10020
- toolInput = { raw: buffered.input };
10021
- }
10022
- }
10023
- toolInputBuffer.delete(toolCallId);
10024
- }
10025
- if (toolName) {
10026
- // First, yield any accumulated text as a separate message
10027
- if (currentTextContent.trim().length > 0) {
10028
- const textMessage = {
10029
- type: 'assistant',
10030
- message: {
10031
- id: currentMessageId,
10032
- content: [{ type: 'text', text: currentTextContent }],
10033
- },
10034
- };
10035
- yieldCount++;
10036
- debugLog$1(`[runner] [ai-sdk-adapter] 💬 Yielding text before tool: ${currentTextContent.length} chars\n`);
10037
- yield textMessage;
10038
- // Reset so it's not included in the tool message
10039
- currentTextContent = '';
10040
- }
10041
- // Now yield the tool call as a separate message
10042
- const toolMessage = {
10043
- type: 'assistant',
10044
- message: {
10045
- id: `${currentMessageId}-tool-${toolCallId}`,
10046
- content: [
10047
- {
10048
- type: 'tool_use',
10049
- id: toolCallId,
10050
- name: toolName,
10051
- input: toolInput || {},
10052
- },
10053
- ],
10054
- },
10055
- };
10056
- yieldCount++;
10057
- debugLog$1();
10058
- debugLog$1(`[runner] [ai-sdk-adapter] Tool input: ${truncateJSON$1(toolInput)}\n`);
10059
- // Log to file
10060
- streamLog.yield('tool-call', { toolName, toolCallId, toolInput, message: toolMessage });
10061
- yield toolMessage;
10062
- }
10063
- break;
10064
- case 'tool-result':
10065
- // Store tool result
10066
- const resultId = part.toolCallId;
10067
- const toolResult = part.result ?? part.output;
10068
- toolResults.set(resultId, toolResult);
10069
- // Emit tool result as a user message
10070
- const resultMessage = {
10071
- type: 'user',
10072
- message: {
10073
- id: `result-${resultId}`,
10074
- content: [
10075
- {
10076
- type: 'tool_result',
10077
- tool_use_id: resultId,
10078
- content: JSON.stringify(toolResult),
10079
- },
10080
- ],
10081
- },
10082
- };
10083
- yieldCount++;
10084
- debugLog$1(`[runner] [ai-sdk-adapter] 📥 Tool result for: ${part.toolName || resultId}\n`);
10085
- // Special handling for verbose tool results
10086
- if (part.toolName === 'TodoWrite') {
10087
- debugLog$1();
10088
- }
10089
- else {
10090
- debugLog$1(`[runner] [ai-sdk-adapter] Result: ${truncateJSON$1(toolResult)}\n`);
10091
- }
10092
- yield resultMessage;
10093
- break;
10094
- case 'tool-error':
10095
- // Emit tool error as a user message
10096
- const errorId = part.toolCallId || part.id;
10097
- const errorMessage = {
10098
- type: 'user',
10099
- message: {
10100
- id: `error-${errorId}`,
10101
- content: [
10102
- {
10103
- type: 'tool_result',
10104
- tool_use_id: errorId,
10105
- content: JSON.stringify({ error: part.error }),
10106
- is_error: true,
10107
- },
10108
- ],
10109
- },
10110
- };
10111
- yieldCount++;
10112
- debugLog$1(`[runner] [ai-sdk-adapter] ⚠️ Tool error: ${part.toolName || errorId}\n`);
10113
- debugLog$1(`[runner] [ai-sdk-adapter] Error: ${truncate$1(JSON.stringify(part.error), 150)}\n`);
10114
- yield errorMessage;
10115
- break;
10116
- case 'text-end':
10117
- // Text block is complete - yield the accumulated text
10118
- if (currentTextContent.trim().length > 0) {
10119
- const message = {
10120
- type: 'assistant',
10121
- message: {
10122
- id: currentMessageId,
10123
- content: [{ type: 'text', text: currentTextContent }],
10124
- },
10125
- };
10126
- yieldCount++;
10127
- debugLog$1(`[runner] [ai-sdk-adapter] Yielding complete text block: ${currentTextContent.length} chars\n`);
10128
- yield message;
10129
- // Reset text content for next block
10130
- currentTextContent = '';
10131
- }
10132
- break;
10133
- case 'finish':
10134
- case 'finish-step':
10135
- // Final message - yield any remaining text
10136
- if (currentTextContent.trim().length > 0) {
10137
- yieldCount++;
10138
- if (DEBUG)
10139
- debugLog$1(`[runner] [ai-sdk-adapter] Yielding final text: ${currentTextContent.length} chars\n`);
10140
- yield {
10141
- type: 'assistant',
10142
- message: {
10143
- id: currentMessageId,
10144
- content: [{ type: 'text', text: currentTextContent }],
10145
- },
10146
- };
10147
- }
10148
- break;
10149
- case 'error':
10150
- // Emit error
10151
- const errorPayload = part.error ?? { message: 'Unknown Claude stream error' };
10152
- const errorText = typeof errorPayload === 'object' && errorPayload !== null
10153
- ? JSON.stringify(errorPayload)
10154
- : String(errorPayload);
10155
- const wrappedError = new Error(`Claude stream error: ${errorText}`);
10156
- Object.assign(wrappedError, { cause: errorPayload });
10157
- debugLog$1();
10158
- throw wrappedError;
10159
- // Ignore other event types
10160
- case 'stream-start':
10161
- case 'response-metadata':
10162
- break;
10163
- default:
10164
- // Log unknown event types for debugging
10165
- if (process.env.DEBUG_BUILD === '1') {
10166
- console.log('[ai-sdk-adapter] Unknown event type:', part.type);
10167
- }
10168
- break;
10169
- }
10170
- }
10171
- // Clean up any orphaned tool spans (tool calls that never received results)
10172
- if (activeToolSpans.size > 0) {
10173
- debugLog$1(`[runner] [ai-sdk-adapter] ⚠️ Cleaning up ${activeToolSpans.size} orphaned tool spans\n`);
10174
- for (const [toolId, span] of activeToolSpans) {
10175
- span.setStatus({ code: 2, message: 'Tool execution incomplete - no result received' });
10176
- span.end();
10177
- debugLog$1();
10178
- }
10179
- activeToolSpans.clear();
10180
- }
10181
- // DEBUG: Log completion stats
10182
- if (DEBUG) {
10183
- debugLog$1();
10184
- }
10185
- streamLog.info('━━━ STREAM TRANSFORMATION COMPLETE ━━━');
10186
- streamLog.info(`Total events: ${eventCount}`);
10187
- streamLog.info(`Total yields: ${yieldCount}`);
10188
- }
10189
-
10190
7792
  /**
10191
7793
  * Adapter to transform Codex SDK events into the unified format expected by message transformer
10192
7794
  *
@@ -11076,10 +8678,10 @@ async function selectTemplateFromPrompt(userPrompt) {
11076
8678
  }
11077
8679
 
11078
8680
  var config = /*#__PURE__*/Object.freeze({
11079
- __proto__: null,
11080
- getAllTemplates: getAllTemplates,
11081
- loadTemplateConfig: loadTemplateConfig,
11082
- selectTemplateFromPrompt: selectTemplateFromPrompt
8681
+ __proto__: null,
8682
+ getAllTemplates: getAllTemplates,
8683
+ loadTemplateConfig: loadTemplateConfig,
8684
+ selectTemplateFromPrompt: selectTemplateFromPrompt
11083
8685
  });
11084
8686
 
11085
8687
  /**
@@ -11097,7 +8699,7 @@ async function downloadTemplate(template, targetPath) {
11097
8699
  console.log(` Target: ${targetPath}`);
11098
8700
  // Check if target already exists and add random suffix if needed
11099
8701
  let finalTargetPath = targetPath;
11100
- if (existsSync$1(targetPath)) {
8702
+ if (existsSync(targetPath)) {
11101
8703
  // Generate a unique 4-character suffix
11102
8704
  const randomSuffix = Math.random().toString(36).substring(2, 6);
11103
8705
  finalTargetPath = `${targetPath}-${randomSuffix}`;
@@ -11169,12 +8771,12 @@ async function downloadTemplateWithGit(template, targetPath) {
11169
8771
  // Handle multi-package projects with client/server subdirectories
11170
8772
  const clientPkgPath = join$1(targetPath, 'client', 'package.json');
11171
8773
  const serverPkgPath = join$1(targetPath, 'server', 'package.json');
11172
- if (existsSync$1(clientPkgPath)) {
8774
+ if (existsSync(clientPkgPath)) {
11173
8775
  await updatePackageName(join$1(targetPath, 'client'), `${projectName}-client`);
11174
8776
  await removeHardcodedPorts(join$1(targetPath, 'client'));
11175
8777
  await ensureVitePortConfig(join$1(targetPath, 'client'));
11176
8778
  }
11177
- if (existsSync$1(serverPkgPath)) {
8779
+ if (existsSync(serverPkgPath)) {
11178
8780
  await updatePackageName(join$1(targetPath, 'server'), `${projectName}-server`);
11179
8781
  await removeHardcodedPorts(join$1(targetPath, 'server'));
11180
8782
  await ensureVitePortConfig(join$1(targetPath, 'server'));
@@ -11209,7 +8811,7 @@ shamefully-hoist=false
11209
8811
  */
11210
8812
  async function updatePackageName(projectPath, newName) {
11211
8813
  const pkgPath = join$1(projectPath, 'package.json');
11212
- if (!existsSync$1(pkgPath)) {
8814
+ if (!existsSync(pkgPath)) {
11213
8815
  if (process.env.DEBUG_BUILD === '1')
11214
8816
  console.log(` No package.json found in ${projectPath}, skipping name update`);
11215
8817
  return;
@@ -11232,7 +8834,7 @@ async function updatePackageName(projectPath, newName) {
11232
8834
  */
11233
8835
  async function removeHardcodedPorts(projectPath) {
11234
8836
  const pkgPath = join$1(projectPath, 'package.json');
11235
- if (!existsSync$1(pkgPath)) {
8837
+ if (!existsSync(pkgPath)) {
11236
8838
  return;
11237
8839
  }
11238
8840
  try {
@@ -11281,11 +8883,11 @@ async function ensureVitePortConfig(projectPath) {
11281
8883
  const viteConfigJs = join$1(projectPath, 'vite.config.js');
11282
8884
  const viteConfigMts = join$1(projectPath, 'vite.config.mts');
11283
8885
  let configPath = null;
11284
- if (existsSync$1(viteConfigTs))
8886
+ if (existsSync(viteConfigTs))
11285
8887
  configPath = viteConfigTs;
11286
- else if (existsSync$1(viteConfigMts))
8888
+ else if (existsSync(viteConfigMts))
11287
8889
  configPath = viteConfigMts;
11288
- else if (existsSync$1(viteConfigJs))
8890
+ else if (existsSync(viteConfigJs))
11289
8891
  configPath = viteConfigJs;
11290
8892
  if (!configPath)
11291
8893
  return;
@@ -11423,7 +9025,7 @@ async function orchestrateBuild(context) {
11423
9025
  }
11424
9026
  // Verify directory state for logging
11425
9027
  try {
11426
- if (existsSync$1(workingDirectory)) {
9028
+ if (existsSync(workingDirectory)) {
11427
9029
  const files = await readdir(workingDirectory);
11428
9030
  if (process.env.DEBUG_BUILD === '1')
11429
9031
  console.log(`[orchestrator] Directory status: ${files.length} files found`);
@@ -11910,7 +9512,7 @@ function getCleanEnv() {
11910
9512
  * Ensure a directory exists
11911
9513
  */
11912
9514
  function ensureDir(dir) {
11913
- if (!existsSync(dir)) {
9515
+ if (!existsSync$1(dir)) {
11914
9516
  mkdirSync$1(dir, { recursive: true });
11915
9517
  }
11916
9518
  }
@@ -11954,7 +9556,7 @@ CRITICAL: Your response must START with { and END with }. Output only the JSON o
11954
9556
  }
11955
9557
  catch (error) {
11956
9558
  console.error('[project-analyzer] SDK query failed:', error);
11957
- captureException(error);
9559
+ Sentry.captureException(error);
11958
9560
  throw error;
11959
9561
  }
11960
9562
  if (!responseText) {
@@ -12344,10 +9946,10 @@ async function waitForPort(port, maxRetries = 10, delayMs = 500) {
12344
9946
  }
12345
9947
 
12346
9948
  var portChecker = /*#__PURE__*/Object.freeze({
12347
- __proto__: null,
12348
- isPortReady: isPortReady,
12349
- setSilentMode: setSilentMode,
12350
- waitForPort: waitForPort
9949
+ __proto__: null,
9950
+ isPortReady: isPortReady,
9951
+ setSilentMode: setSilentMode,
9952
+ waitForPort: waitForPort
12351
9953
  });
12352
9954
 
12353
9955
  /**
@@ -12492,7 +10094,7 @@ const hmrProxyManager = new HmrProxyManager();
12492
10094
 
12493
10095
  // Sentry is initialized via --import flag (see package.json scripts)
12494
10096
  // This ensures instrumentation loads before any other modules
12495
- globalThis.AI_SDK_LOG_WARNINGS = false;
10097
+ // AI SDK log warnings disabled (legacy - no longer using AI SDK)
12496
10098
  /**
12497
10099
  * Truncate strings for logging to prevent excessive output
12498
10100
  */
@@ -12524,7 +10126,7 @@ const DEBUG_BUILD = process.env.DEBUG_BUILD === "1" || false;
12524
10126
  const log = (...args) => {
12525
10127
  const message = args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ');
12526
10128
  try {
12527
- const logger = getLogger$1();
10129
+ const logger = getLogger();
12528
10130
  logger.info('system', message);
12529
10131
  }
12530
10132
  catch {
@@ -12538,7 +10140,7 @@ const log = (...args) => {
12538
10140
  const buildLog = (...args) => {
12539
10141
  const message = args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ');
12540
10142
  try {
12541
- const logger = getLogger$1();
10143
+ const logger = getLogger();
12542
10144
  logger.info('build', message);
12543
10145
  }
12544
10146
  catch {
@@ -12554,7 +10156,7 @@ const debugLog = (...args) => {
12554
10156
  return;
12555
10157
  const message = args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ');
12556
10158
  try {
12557
- const logger = getLogger$1();
10159
+ const logger = getLogger();
12558
10160
  logger.debug('system', message);
12559
10161
  }
12560
10162
  catch {
@@ -12563,146 +10165,6 @@ const debugLog = (...args) => {
12563
10165
  };
12564
10166
  const DEFAULT_AGENT = "claude-code";
12565
10167
  const CODEX_MODEL = "gpt-5-codex";
12566
- // Stderr debug logging - suppressed in TUI mode (SILENT_MODE=1)
12567
- const stderrDebug = (message) => {
12568
- if (process.env.SILENT_MODE !== '1' && DEBUG_BUILD) {
12569
- process.stderr.write(message);
12570
- }
12571
- };
12572
- /**
12573
- * Create Claude query function using AI SDK
12574
- *
12575
- * NOTE: This function prepends CLAUDE_SYSTEM_PROMPT to the systemPrompt from orchestrator.
12576
- * The orchestrator provides context-specific sections only (no base prompt).
12577
- */
12578
- function createClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID) {
12579
- return async function* (prompt, workingDirectory, systemPrompt, agent, codexThreadId, messageParts) {
12580
- // Note: query is auto-instrumented by Sentry's claudeCodeAgentSdkIntegration via OpenTelemetry
12581
- stderrDebug("[runner] [createClaudeQuery] 🎯 Query function called\n");
12582
- stderrDebug(`[runner] [createClaudeQuery] Model: ${modelId}\n`);
12583
- stderrDebug(`[runner] [createClaudeQuery] Working dir: ${workingDirectory}\n`);
12584
- stderrDebug(`[runner] [createClaudeQuery] Prompt length: ${prompt.length}\n`);
12585
- // Check if we have image parts
12586
- const hasImages = messageParts?.some(p => p.type === 'image');
12587
- if (hasImages) {
12588
- const imageCount = messageParts?.filter(p => p.type === 'image').length || 0;
12589
- stderrDebug(`[runner] [createClaudeQuery] 🖼️ Multi-modal message with ${imageCount} image(s)\n`);
12590
- }
12591
- // Build combined system prompt
12592
- const systemPromptSegments = [CLAUDE_SYSTEM_PROMPT.trim()];
12593
- if (systemPrompt && systemPrompt.trim().length > 0) {
12594
- systemPromptSegments.push(systemPrompt.trim());
12595
- }
12596
- const appendedSystemPrompt = systemPromptSegments.join("\n\n");
12597
- // Use the full model ID as-is (claude-haiku-4-5, claude-sonnet-4-5, claude-opus-4-5)
12598
- const aiSdkModelId = modelId || "claude-haiku-4-5";
12599
- // Ensure working directory exists before passing to Claude Code
12600
- if (!existsSync$1(workingDirectory)) {
12601
- console.log(`[createClaudeQuery] Creating working directory: ${workingDirectory}`);
12602
- mkdirSync(workingDirectory, { recursive: true });
12603
- }
12604
- // NOTE: The community provider (ai-sdk-provider-claude-code) bundles an older
12605
- // version of the SDK types. We cast to `any` to avoid type conflicts.
12606
- // This legacy path is deprecated in favor of the native SDK implementation.
12607
- const model = claudeCode(aiSdkModelId, {
12608
- queryFunction: query, // Cast to avoid SDK version type conflict
12609
- systemPrompt: {
12610
- type: "preset",
12611
- preset: "claude_code",
12612
- append: appendedSystemPrompt,
12613
- },
12614
- cwd: workingDirectory,
12615
- permissionMode: "bypassPermissions",
12616
- maxTurns: 100,
12617
- additionalDirectories: [workingDirectory],
12618
- env: {
12619
- // Claude Code CLI default output cap is 32k; bumping to 64k per
12620
- // https://docs.claude.com/en/docs/claude-code/settings#environment-variables
12621
- CLAUDE_CODE_MAX_OUTPUT_TOKENS: process.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS ?? "64000",
12622
- },
12623
- // Explicitly allow all tools to prevent "No tools are available" errors
12624
- canUseTool: createProjectScopedPermissionHandler(workingDirectory), // Cast for type compat
12625
- streamingInput: "always", // REQUIRED when using canUseTool - enables tool callbacks
12626
- includePartialMessages: true,
12627
- settingSources: ["user", "project"], // Load skills from user and project directories
12628
- });
12629
- // Build user message - either simple text or multi-part with images
12630
- let userMessage;
12631
- if (messageParts && messageParts.length > 0) {
12632
- // Multi-part message with images
12633
- const contentParts = [];
12634
- // Add image parts first (Claude best practice)
12635
- for (const part of messageParts) {
12636
- if (part.type === 'image' && part.image) {
12637
- // AI SDK expects images as data URLs, which we already have
12638
- contentParts.push({
12639
- type: 'image',
12640
- image: part.image, // Already a base64 data URL
12641
- });
12642
- // Extract media type for logging
12643
- const match = part.image.match(/^data:(.+);base64,/);
12644
- if (match) {
12645
- stderrDebug(`[runner] [createClaudeQuery] ✅ Added image part (${match[1]})\n`);
12646
- }
12647
- }
12648
- else if (part.type === 'text' && part.text) {
12649
- contentParts.push({
12650
- type: 'text',
12651
- text: part.text
12652
- });
12653
- }
12654
- }
12655
- // Add prompt text if not already in parts
12656
- if (!contentParts.some(p => p.type === 'text')) {
12657
- contentParts.push({
12658
- type: 'text',
12659
- text: prompt
12660
- });
12661
- }
12662
- userMessage = contentParts;
12663
- stderrDebug(`[runner] [createClaudeQuery] 📦 Built multi-part message with ${contentParts.length} part(s)\n`);
12664
- }
12665
- else {
12666
- // Simple text message (existing behavior)
12667
- userMessage = prompt;
12668
- }
12669
- // Stream with telemetry enabled for Sentry
12670
- // Use 'messages' param for multi-part content, 'prompt' for simple text
12671
- // IMPORTANT: experimental_telemetry is REQUIRED for the Vercel AI SDK integration to work
12672
- const streamOptions = {
12673
- model,
12674
- tools: CLAUDE_CLI_TOOL_REGISTRY,
12675
- experimental_telemetry: {
12676
- isEnabled: true,
12677
- functionId: 'createClaudeQuery',
12678
- recordInputs: true,
12679
- recordOutputs: true,
12680
- },
12681
- };
12682
- const result = Array.isArray(userMessage)
12683
- ? streamText({
12684
- ...streamOptions,
12685
- messages: [{ role: 'user', content: userMessage }],
12686
- })
12687
- : streamText({
12688
- ...streamOptions,
12689
- prompt: userMessage,
12690
- });
12691
- // Transform AI SDK stream format to our message format
12692
- if (process.env.DEBUG_BUILD === "1") {
12693
- console.log("[createClaudeQuery] Starting stream consumption...");
12694
- }
12695
- for await (const message of transformAISDKStream(result.fullStream)) {
12696
- if (process.env.DEBUG_BUILD === "1") {
12697
- console.log("[createClaudeQuery] Yielding message:", message.type);
12698
- }
12699
- yield message;
12700
- }
12701
- if (process.env.DEBUG_BUILD === "1") {
12702
- console.log("[createClaudeQuery] Stream consumption complete");
12703
- }
12704
- };
12705
- }
12706
10168
  /**
12707
10169
  * Create Codex query function using ORIGINAL Codex SDK (NOT AI SDK)
12708
10170
  *
@@ -12797,7 +10259,7 @@ function createCodexQuery() {
12797
10259
  log(`🚀 [codex-query] Turn ${turnCount}: ${turnCount === 1 ? 'Initial request' : 'Continuing work'}...`);
12798
10260
  // Log full prompt being sent to Codex
12799
10261
  if (turnCount === 1) {
12800
- info(fmt `Full Codex prompt (Turn 1) ${{
10262
+ Sentry.logger.info(Sentry.logger.fmt `Full Codex prompt (Turn 1) ${{
12801
10263
  prompt: turnPrompt,
12802
10264
  promptLength: turnPrompt.length,
12803
10265
  promptPreview: turnPrompt.substring(0, 200),
@@ -12865,13 +10327,8 @@ function createBuildQuery(agent, modelId, abortController) {
12865
10327
  console.log('[runner] 🔄 Using direct Codex SDK (fallback mode)');
12866
10328
  return createCodexQuery();
12867
10329
  }
12868
- // Use legacy AI SDK path when explicitly requested
12869
- if (!USE_NATIVE_SDK) {
12870
- console.log('[runner] 🔄 Using AI SDK with claude-code provider (legacy mode)');
12871
- return createClaudeQuery(modelId ?? DEFAULT_CLAUDE_MODEL_ID);
12872
- }
12873
10330
  // Default: Use native Claude Agent SDK (direct integration)
12874
- console.log('[runner] 🔄 Using NATIVE Claude Agent SDK v0.1.76');
10331
+ console.log('[runner] 🔄 Using NATIVE Claude Agent SDK');
12875
10332
  return createNativeClaudeQuery(modelId ?? DEFAULT_CLAUDE_MODEL_ID, abortController);
12876
10333
  }
12877
10334
  /**
@@ -13047,7 +10504,7 @@ async function startRunner(options = {}) {
13047
10504
  const RUNNER_ID = options.runnerId ||
13048
10505
  process.env.RUNNER_ID ||
13049
10506
  process.env.RAILWAY_REPLICA_ID ||
13050
- `runner-${os__default.hostname()}`;
10507
+ `runner-${os$1.hostname()}`;
13051
10508
  // WebSocket URL for direct connection to Next.js server
13052
10509
  // Supports both new RUNNER_WS_URL and legacy RUNNER_BROKER_URL for backward compatibility
13053
10510
  const WS_URL = options.wsUrl ||
@@ -13078,7 +10535,7 @@ async function startRunner(options = {}) {
13078
10535
  }
13079
10536
  const runnerSharedSecret = SHARED_SECRET; // Guaranteed to be string after validation check
13080
10537
  // Ensure workspace directory exists
13081
- if (!existsSync$1(WORKSPACE_ROOT)) {
10538
+ if (!existsSync(WORKSPACE_ROOT)) {
13082
10539
  console.log(`📁 Creating workspace directory: ${WORKSPACE_ROOT}`);
13083
10540
  mkdirSync(WORKSPACE_ROOT, { recursive: true });
13084
10541
  }
@@ -13109,14 +10566,14 @@ async function startRunner(options = {}) {
13109
10566
  id: RUNNER_ID,
13110
10567
  connected: socket?.readyState === WebSocket$1.OPEN,
13111
10568
  workspace: WORKSPACE_ROOT,
13112
- workspaceExists: existsSync$1(WORKSPACE_ROOT),
10569
+ workspaceExists: existsSync(WORKSPACE_ROOT),
13113
10570
  },
13114
10571
  uptime: process.uptime(),
13115
10572
  timestamp: new Date().toISOString(),
13116
10573
  });
13117
10574
  });
13118
10575
  healthApp.get('/ready', (req, res) => {
13119
- const isReady = socket?.readyState === WebSocket$1.OPEN && existsSync$1(WORKSPACE_ROOT);
10576
+ const isReady = socket?.readyState === WebSocket$1.OPEN && existsSync(WORKSPACE_ROOT);
13120
10577
  res.status(isReady ? 200 : 503).json({
13121
10578
  ready: isReady,
13122
10579
  runnerId: RUNNER_ID,
@@ -13182,7 +10639,7 @@ async function startRunner(options = {}) {
13182
10639
  throw lastError || new Error('Persistence failed after retries');
13183
10640
  }
13184
10641
  async function persistBuildEventDirect(context, event) {
13185
- return startSpan({
10642
+ return Sentry.startSpan({
13186
10643
  name: `persist.build-event.${event.type}`,
13187
10644
  op: 'http.client',
13188
10645
  attributes: {
@@ -13193,7 +10650,7 @@ async function startRunner(options = {}) {
13193
10650
  },
13194
10651
  }, async () => {
13195
10652
  // Get trace context for propagation
13196
- const traceData = getTraceData();
10653
+ const traceData = Sentry.getTraceData();
13197
10654
  const headers = {
13198
10655
  'Authorization': `Bearer ${runnerSharedSecret}`,
13199
10656
  'Content-Type': 'application/json',
@@ -13301,7 +10758,7 @@ async function startRunner(options = {}) {
13301
10758
  */
13302
10759
  async function persistRunnerEvent(event) {
13303
10760
  // Wrap in Sentry span to create proper trace hierarchy
13304
- return startSpan({
10761
+ return Sentry.startSpan({
13305
10762
  name: `persist.runner-event.${event.type}`,
13306
10763
  op: 'http.client',
13307
10764
  attributes: {
@@ -13355,9 +10812,9 @@ async function startRunner(options = {}) {
13355
10812
  try {
13356
10813
  // Attach trace context to ALL events for distributed tracing
13357
10814
  // This allows events to be linked back to the originating frontend request
13358
- const span = getActiveSpan();
10815
+ const span = Sentry.getActiveSpan();
13359
10816
  if (span) {
13360
- const traceData = getTraceData();
10817
+ const traceData = Sentry.getTraceData();
13361
10818
  event._sentry = {
13362
10819
  trace: traceData['sentry-trace'],
13363
10820
  baggage: traceData.baggage,
@@ -13862,7 +11319,7 @@ async function startRunner(options = {}) {
13862
11319
  logger.tunnel({ port, url: tunnelUrl, status: 'created' });
13863
11320
  // Instrument tunnel startup timing
13864
11321
  const tunnelDuration = Date.now() - tunnelStartTime;
13865
- distribution('tunnel_startup_duration', tunnelDuration, {
11322
+ Sentry.metrics.distribution('tunnel_startup_duration', tunnelDuration, {
13866
11323
  unit: 'millisecond',
13867
11324
  attributes: {
13868
11325
  port: port.toString(),
@@ -13880,7 +11337,7 @@ async function startRunner(options = {}) {
13880
11337
  console.error("Failed to create tunnel:", error);
13881
11338
  // Instrument failed tunnel startup timing
13882
11339
  const tunnelDuration = Date.now() - tunnelStartTime;
13883
- distribution('tunnel_startup_duration', tunnelDuration, {
11340
+ Sentry.metrics.distribution('tunnel_startup_duration', tunnelDuration, {
13884
11341
  unit: 'millisecond',
13885
11342
  attributes: {
13886
11343
  port: command.payload.port.toString(),
@@ -14553,7 +12010,7 @@ async function startRunner(options = {}) {
14553
12010
  // Detect framework from generated files
14554
12011
  let detectedFramework = null;
14555
12012
  try {
14556
- const { detectFrameworkFromFilesystem } = await import('./chunks/port-allocator-Ct3ioni4.js');
12013
+ const { detectFrameworkFromFilesystem } = await import('./chunks/port-allocator-DuAZe2_S.js');
14557
12014
  const framework = await detectFrameworkFromFilesystem(projectDirectory);
14558
12015
  detectedFramework = framework;
14559
12016
  if (framework) {
@@ -14592,11 +12049,25 @@ ${filesArray.length > 0 ? `Files modified:\n${filesArray.map(f => `- ${f}`).join
14592
12049
  ${completedTodoSnapshot.length > 0 ? `Tasks completed:\n${completedTodoSnapshot.map(t => `- ${t}`).join('\n')}` : ''}
14593
12050
 
14594
12051
  Write a brief, professional summary (1-3 sentences) describing what was accomplished. Focus on the outcome, not the process. Do not use phrases like "I did" or "The assistant". Just describe what was built or changed.`;
14595
- const summaryResult = await generateText({
14596
- model: claudeCode("claude-haiku-4-5"),
12052
+ // Use native Claude Agent SDK for summary generation
12053
+ let summaryText = '';
12054
+ for await (const msg of query({
14597
12055
  prompt: summaryPrompt,
14598
- });
14599
- const summaryText = summaryResult.text?.trim();
12056
+ options: {
12057
+ model: 'claude-haiku-4-5',
12058
+ maxTurns: 1,
12059
+ permissionMode: 'default',
12060
+ },
12061
+ })) {
12062
+ if (msg.type === 'assistant' && msg.message?.content) {
12063
+ for (const block of msg.message.content) {
12064
+ if (block.type === 'text') {
12065
+ summaryText += block.text;
12066
+ }
12067
+ }
12068
+ }
12069
+ }
12070
+ summaryText = summaryText.trim();
14600
12071
  if (summaryText) {
14601
12072
  buildLog(` ✅ AI summary generated (${summaryText.length} chars)`);
14602
12073
  sendEvent({
@@ -14641,7 +12112,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
14641
12112
  catch (error) {
14642
12113
  const errorMessage = error instanceof Error ? error.message : "Failed to run build";
14643
12114
  logger.buildFailed(errorMessage);
14644
- getActiveSpan()?.setStatus({
12115
+ Sentry.getActiveSpan()?.setStatus({
14645
12116
  code: 2, // SPAN_STATUS_ERROR
14646
12117
  message: "Build failed",
14647
12118
  });
@@ -14858,15 +12329,15 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
14858
12329
  }
14859
12330
  function publishStatus(projectId, commandId) {
14860
12331
  const uptimeSeconds = Math.round(process.uptime());
14861
- const load = os__default.loadavg?.()[0];
12332
+ const load = os$1.loadavg?.()[0];
14862
12333
  sendEvent({
14863
12334
  type: "runner-status",
14864
12335
  ...buildEventBase(projectId, commandId),
14865
12336
  payload: {
14866
12337
  status: "online",
14867
12338
  version: "prototype",
14868
- hostname: os__default.hostname(),
14869
- platform: os__default.platform(),
12339
+ hostname: os$1.hostname(),
12340
+ platform: os$1.platform(),
14870
12341
  uptimeSeconds,
14871
12342
  load,
14872
12343
  },
@@ -14994,12 +12465,12 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
14994
12465
  // This creates a span within the continued trace for the runner's work
14995
12466
  if (command._sentry?.trace) {
14996
12467
  console.log("[runner] Continuing trace from frontend:", command._sentry.trace.substring(0, 50));
14997
- await continueTrace({
12468
+ await Sentry.continueTrace({
14998
12469
  sentryTrace: command._sentry.trace,
14999
12470
  baggage: command._sentry.baggage,
15000
12471
  }, async () => {
15001
12472
  // Create a span for this command execution within the continued trace
15002
- await startSpan({
12473
+ await Sentry.startSpan({
15003
12474
  name: `runner.${command.type}`,
15004
12475
  op: command.type === 'start-build' ? 'build.runner' : `runner.${command.type}`,
15005
12476
  attributes: {
@@ -15010,9 +12481,9 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
15010
12481
  },
15011
12482
  }, async (span) => {
15012
12483
  try {
15013
- setTag("command_type", command.type);
15014
- setTag("project_id", projectIdForTelemetry);
15015
- setTag("command_id", command.id);
12484
+ Sentry.setTag("command_type", command.type);
12485
+ Sentry.setTag("project_id", projectIdForTelemetry);
12486
+ Sentry.setTag("command_id", command.id);
15016
12487
  // Capture build metrics for start-build commands
15017
12488
  if (command.type === 'start-build' && command.payload) {
15018
12489
  const agent = command.payload.agent ?? 'claude-code';
@@ -15022,7 +12493,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
15022
12493
  command.payload.claudeModel === 'claude-opus-4-5')
15023
12494
  ? command.payload.claudeModel
15024
12495
  : 'claude-sonnet-4-5';
15025
- count('runner.build.started', 1, {
12496
+ Sentry.metrics.count('runner.build.started', 1, {
15026
12497
  attributes: {
15027
12498
  project_id: command.projectId,
15028
12499
  model: agent === 'claude-code' ? claudeModel : agent,
@@ -15043,7 +12514,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
15043
12514
  else {
15044
12515
  console.log("[runner] No trace context - starting isolated span");
15045
12516
  // Create an isolated span when no trace context is provided
15046
- await startSpan({
12517
+ await Sentry.startSpan({
15047
12518
  name: `runner.${command.type}`,
15048
12519
  op: command.type === 'start-build' ? 'build.runner' : `runner.${command.type}`,
15049
12520
  attributes: {
@@ -15054,9 +12525,9 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
15054
12525
  },
15055
12526
  }, async (span) => {
15056
12527
  try {
15057
- setTag("command_type", command.type);
15058
- setTag("project_id", projectIdForTelemetry);
15059
- setTag("command_id", command.id);
12528
+ Sentry.setTag("command_type", command.type);
12529
+ Sentry.setTag("project_id", projectIdForTelemetry);
12530
+ Sentry.setTag("command_id", command.id);
15060
12531
  // Capture build metrics for start-build commands
15061
12532
  if (command.type === 'start-build' && command.payload) {
15062
12533
  const agent = command.payload.agent ?? 'claude-code';
@@ -15066,7 +12537,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
15066
12537
  command.payload.claudeModel === 'claude-opus-4-5')
15067
12538
  ? command.payload.claudeModel
15068
12539
  : 'claude-sonnet-4-5';
15069
- count('runner.build.started', 1, {
12540
+ Sentry.metrics.count('runner.build.started', 1, {
15070
12541
  attributes: {
15071
12542
  project_id: command.projectId,
15072
12543
  model: agent === 'claude-code' ? claudeModel : agent,
@@ -15086,7 +12557,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
15086
12557
  }
15087
12558
  catch (error) {
15088
12559
  console.error("Failed to parse command", error);
15089
- captureException(error);
12560
+ Sentry.captureException(error);
15090
12561
  sendEvent({
15091
12562
  type: "error",
15092
12563
  ...buildEventBase(undefined, randomUUID$1()),
@@ -15178,7 +12649,7 @@ Write a brief, professional summary (1-3 sentences) describing what was accompli
15178
12649
  // Final cleanup of any remaining tunnels
15179
12650
  await tunnelManager.closeAll();
15180
12651
  // Flush Sentry events before exiting
15181
- await flush(2000);
12652
+ await Sentry.flush(2000);
15182
12653
  log("shutdown complete");
15183
12654
  };
15184
12655
  process.on("SIGINT", async () => {