@openbuilder/cli 0.50.42 → 0.50.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{Banner-C-FTiOIR.js → Banner-BlktOjfl.js} +2 -2
- package/dist/chunks/Banner-BlktOjfl.js.map +1 -0
- package/dist/chunks/_commonjsHelpers-h-Bqc03Z.js +34 -0
- package/dist/chunks/_commonjsHelpers-h-Bqc03Z.js.map +1 -0
- package/dist/chunks/auto-update-Dq2PFvjt.js +1 -0
- package/dist/chunks/auto-update-Dq2PFvjt.js.map +1 -0
- package/dist/chunks/build-D0qYqIq0.js +1 -0
- package/dist/chunks/build-D0qYqIq0.js.map +1 -0
- package/dist/chunks/cleanup-qVTsA3tk.js +1 -0
- package/dist/chunks/cleanup-qVTsA3tk.js.map +1 -0
- package/dist/chunks/cli-auth-ChCnxlFl.js +1 -0
- package/dist/chunks/cli-auth-ChCnxlFl.js.map +1 -0
- package/dist/chunks/cli-error-BjQwvWtK.js +1 -0
- package/dist/chunks/cli-error-BjQwvWtK.js.map +1 -0
- package/dist/chunks/config-BGP1jZJ4.js +1 -0
- package/dist/chunks/config-BGP1jZJ4.js.map +1 -0
- package/dist/chunks/config-manager-BkbjtN-H.js +1 -0
- package/dist/chunks/config-manager-BkbjtN-H.js.map +1 -0
- package/dist/chunks/database-BvAbD4sP.js +1 -0
- package/dist/chunks/database-BvAbD4sP.js.map +1 -0
- package/dist/chunks/database-setup-BYjIRAmT.js +1 -0
- package/dist/chunks/database-setup-BYjIRAmT.js.map +1 -0
- package/dist/chunks/devtools-7A3EXJhY.js +75 -0
- package/dist/chunks/devtools-7A3EXJhY.js.map +1 -0
- package/dist/chunks/exports-ij9sv4UM.js +7793 -0
- package/dist/chunks/exports-ij9sv4UM.js.map +1 -0
- package/dist/chunks/index-oFqGtEeF.js +119 -0
- package/dist/chunks/index-oFqGtEeF.js.map +1 -0
- package/dist/chunks/{init-DNyPS_SR.js → init-BsQ3dhwf.js} +9 -9
- package/dist/chunks/init-BsQ3dhwf.js.map +1 -0
- package/dist/chunks/{init-tui-EFMXj-MG.js → init-tui-Dvk6Ndvl.js} +8 -8
- package/dist/chunks/init-tui-Dvk6Ndvl.js.map +1 -0
- package/dist/chunks/logger-ZpJi7chw.js +1 -0
- package/dist/chunks/logger-ZpJi7chw.js.map +1 -0
- package/dist/chunks/login-BhtodVsj.js +1 -0
- package/dist/chunks/login-BhtodVsj.js.map +1 -0
- package/dist/chunks/logout-CDDASeuQ.js +1 -0
- package/dist/chunks/logout-CDDASeuQ.js.map +1 -0
- package/dist/chunks/{main-tui-D-SG-Ba5.js → main-tui-Cklcr3FX.js} +10 -10
- package/dist/chunks/main-tui-Cklcr3FX.js.map +1 -0
- package/dist/chunks/manager-CvGX9qqe.js +1 -0
- package/dist/chunks/manager-CvGX9qqe.js.map +1 -0
- package/dist/chunks/{port-allocator-B0q7xkLs.js → port-allocator-Ct3ioni4.js} +2 -34
- package/dist/chunks/port-allocator-Ct3ioni4.js.map +1 -0
- package/dist/chunks/process-killer-CaUL7Kpl.js +1 -0
- package/dist/chunks/process-killer-CaUL7Kpl.js.map +1 -0
- package/dist/chunks/prompts-1QbE_bRr.js +1 -0
- package/dist/chunks/prompts-1QbE_bRr.js.map +1 -0
- package/dist/chunks/repo-cloner-CpOQjFSo.js +1 -0
- package/dist/chunks/repo-cloner-CpOQjFSo.js.map +1 -0
- package/dist/chunks/repo-detector-B_oj696o.js +1 -0
- package/dist/chunks/repo-detector-B_oj696o.js.map +1 -0
- package/dist/chunks/{run-Cor14S0I.js → run-wycadErJ.js} +15 -28
- package/dist/chunks/run-wycadErJ.js.map +1 -0
- package/dist/chunks/runner-logger-instance-nDWv2h2T.js +1 -0
- package/dist/chunks/runner-logger-instance-nDWv2h2T.js.map +1 -0
- package/dist/chunks/spinner-BJL9zWAJ.js +1 -0
- package/dist/chunks/spinner-BJL9zWAJ.js.map +1 -0
- package/dist/chunks/{start-k9iGDVWo.js → start-CQKEEma-.js} +8 -7
- package/dist/chunks/start-CQKEEma-.js.map +1 -0
- package/dist/chunks/start-traditional-uoLZXdxm.js +1 -0
- package/dist/chunks/start-traditional-uoLZXdxm.js.map +1 -0
- package/dist/chunks/status-cS8YwtUx.js +1 -0
- package/dist/chunks/status-cS8YwtUx.js.map +1 -0
- package/dist/chunks/{vendor-react-CXgiD1Dl.js → theme-CktnrDZj.js} +47 -227
- package/dist/chunks/theme-CktnrDZj.js.map +1 -0
- package/dist/chunks/upgrade-CKjl4HlB.js +1 -0
- package/dist/chunks/upgrade-CKjl4HlB.js.map +1 -0
- package/dist/chunks/use-app-Cj2bzWaw.js +10 -0
- package/dist/chunks/use-app-Cj2bzWaw.js.map +1 -0
- package/dist/chunks/{useBuildState-DscLOZLl.js → useBuildState-pcDGDakI.js} +2 -2
- package/dist/chunks/useBuildState-pcDGDakI.js.map +1 -0
- package/dist/cli/index.js +6 -5
- package/dist/cli/index.js.map +1 -0
- package/dist/index.js +2044 -106
- package/dist/index.js.map +1 -0
- package/dist/instrument.js +64119 -37
- package/dist/instrument.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunks/theme-DhorI2Hb.js +0 -43
- package/dist/chunks/vendor-ai-sdk-CSJ0bw9X.js +0 -1970
- package/dist/chunks/vendor-sentry-CqA9P3UG.js +0 -71910
package/dist/index.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
// OpenBuilder CLI - Built with Rollup
|
|
2
2
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
3
3
|
import { Codex } from '@openai/codex-sdk';
|
|
4
|
-
import { a as streamLog, f as fileLog, i as initRunnerLogger, s as setFileLoggerTuiMode, b as getLogger } from './chunks/runner-logger-instance-nDWv2h2T.js';
|
|
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
5
|
import { config as config$1 } from 'dotenv';
|
|
6
6
|
import require$$1, { resolve, relative, isAbsolute, dirname, join as join$1 } from 'node:path';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
import { generateText, streamText } from 'ai';
|
|
9
|
-
import
|
|
10
|
-
import
|
|
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';
|
|
11
15
|
import { readFile } from 'fs/promises';
|
|
12
16
|
import * as path from 'path';
|
|
13
17
|
import { join } from 'path';
|
|
@@ -18,8 +22,7 @@ import { pgTable, timestamp, boolean, text, uuid, index, uniqueIndex, integer, j
|
|
|
18
22
|
import { sql, eq, and, desc, isNull } from 'drizzle-orm';
|
|
19
23
|
import { randomUUID, createHash } from 'crypto';
|
|
20
24
|
import { migrate } from 'drizzle-orm/node-postgres/migrator';
|
|
21
|
-
import {
|
|
22
|
-
import { a as addBreadcrumb, c as captureException, g as getActiveSpan, b as getTraceData, s as startInactiveSpan, f as flush, d as continueTrace, e as startSpan, j as setTag, k as count, l as distribution, m as info, n as fmt } from './chunks/vendor-sentry-CqA9P3UG.js';
|
|
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';
|
|
23
26
|
import os__default from 'node:os';
|
|
24
27
|
import { randomUUID as randomUUID$1 } from 'node:crypto';
|
|
25
28
|
import express from 'express';
|
|
@@ -29,40 +32,1974 @@ import { createServer, createConnection } from 'node:net';
|
|
|
29
32
|
import { readFile as readFile$1, rm, writeFile, readdir } from 'node:fs/promises';
|
|
30
33
|
import { simpleGit } from 'simple-git';
|
|
31
34
|
import * as os from 'os';
|
|
32
|
-
import { existsSync as existsSync$1, mkdirSync as mkdirSync$1 } from 'fs';
|
|
33
35
|
import { tunnelManager } from './chunks/manager-CvGX9qqe.js';
|
|
34
36
|
import 'chalk';
|
|
35
|
-
import 'zod/v4';
|
|
36
|
-
import 'zod/v3';
|
|
37
|
-
import 'jsonc-parser';
|
|
38
|
-
import 'url';
|
|
39
|
-
import 'tty';
|
|
40
|
-
import 'util';
|
|
41
|
-
import 'worker_threads';
|
|
42
|
-
import 'process';
|
|
43
|
-
import 'node:module';
|
|
44
|
-
import 'async_hooks';
|
|
45
|
-
import 'diagnostics_channel';
|
|
46
|
-
import './chunks/vendor-react-CXgiD1Dl.js';
|
|
47
|
-
import 'module';
|
|
48
|
-
import 'events';
|
|
49
|
-
import 'assert';
|
|
50
|
-
import 'react-devtools-core';
|
|
51
|
-
import 'node:stream';
|
|
52
|
-
import 'node:process';
|
|
53
|
-
import 'node:buffer';
|
|
54
|
-
import 'node:diagnostics_channel';
|
|
55
37
|
import 'node:util';
|
|
56
|
-
import 'node:readline';
|
|
57
|
-
import 'node:worker_threads';
|
|
58
|
-
import 'node:http';
|
|
59
|
-
import 'node:https';
|
|
60
|
-
import 'node:zlib';
|
|
61
|
-
import 'node:tls';
|
|
62
38
|
import 'http';
|
|
63
39
|
import 'http-proxy';
|
|
64
40
|
import 'zlib';
|
|
65
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();
|
|
2002
|
+
|
|
66
2003
|
/**
|
|
67
2004
|
* Creates a permission handler that restricts Claude to a specific project directory
|
|
68
2005
|
*
|
|
@@ -4546,34 +6483,34 @@ var AVAILABLE_ICONS = [
|
|
|
4546
6483
|
];
|
|
4547
6484
|
|
|
4548
6485
|
var AgentCore = /*#__PURE__*/Object.freeze({
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
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
|
|
4577
6514
|
});
|
|
4578
6515
|
|
|
4579
6516
|
/**
|
|
@@ -4724,7 +6661,7 @@ function createNativeClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID, abortControl
|
|
|
4724
6661
|
}
|
|
4725
6662
|
const appendedSystemPrompt = systemPromptSegments.join('\n\n');
|
|
4726
6663
|
// Ensure working directory exists
|
|
4727
|
-
if (!existsSync(workingDirectory)) {
|
|
6664
|
+
if (!existsSync$1(workingDirectory)) {
|
|
4728
6665
|
console.log(`[native-sdk] Creating working directory: ${workingDirectory}`);
|
|
4729
6666
|
mkdirSync(workingDirectory, { recursive: true });
|
|
4730
6667
|
}
|
|
@@ -5002,7 +6939,7 @@ function createOpenCodeQuery(modelId = DEFAULT_OPENCODE_MODEL_ID) {
|
|
|
5002
6939
|
debugLog$3(`[runner] [opencode-sdk] Working dir: ${workingDirectory}`);
|
|
5003
6940
|
debugLog$3(`[runner] [opencode-sdk] Prompt length: ${prompt.length}`);
|
|
5004
6941
|
// Ensure working directory exists
|
|
5005
|
-
if (!existsSync(workingDirectory)) {
|
|
6942
|
+
if (!existsSync$1(workingDirectory)) {
|
|
5006
6943
|
console.log(`[opencode-sdk] Creating working directory: ${workingDirectory}`);
|
|
5007
6944
|
mkdirSync(workingDirectory, { recursive: true });
|
|
5008
6945
|
}
|
|
@@ -6921,7 +8858,7 @@ async function createBuildStream(options) {
|
|
|
6921
8858
|
if (process.env.DEBUG_BUILD === '1')
|
|
6922
8859
|
console.log(`[engine] Strategy adjusted CWD to: ${actualWorkingDir}`);
|
|
6923
8860
|
}
|
|
6924
|
-
else if (!existsSync(workingDirectory)) {
|
|
8861
|
+
else if (!existsSync$1(workingDirectory)) {
|
|
6925
8862
|
mkdirSync(workingDirectory, { recursive: true });
|
|
6926
8863
|
}
|
|
6927
8864
|
if (!resolvedDir) {
|
|
@@ -7197,7 +9134,7 @@ function classifyStartupError(error, processInfo) {
|
|
|
7197
9134
|
suggestion: 'Check file permissions and ownership'
|
|
7198
9135
|
};
|
|
7199
9136
|
}
|
|
7200
|
-
if (processInfo.cwd && !existsSync(processInfo.cwd)) {
|
|
9137
|
+
if (processInfo.cwd && !existsSync$1(processInfo.cwd)) {
|
|
7201
9138
|
return {
|
|
7202
9139
|
reason: FailureReason.DIRECTORY_MISSING,
|
|
7203
9140
|
message: `Working directory does not exist: ${processInfo.cwd}`,
|
|
@@ -7261,7 +9198,7 @@ function startDevServer(options) {
|
|
|
7261
9198
|
buildLogger$1.processManager.processStarting(projectId, command, cwd);
|
|
7262
9199
|
const emitter = new EventEmitter();
|
|
7263
9200
|
// Verify CWD exists
|
|
7264
|
-
if (!existsSync(cwd)) {
|
|
9201
|
+
if (!existsSync$1(cwd)) {
|
|
7265
9202
|
const error = new Error(`Working directory does not exist: ${cwd}`);
|
|
7266
9203
|
buildLogger$1.processManager.error('Failed to spawn process', error, { projectId });
|
|
7267
9204
|
emitter.emit('error', error);
|
|
@@ -7498,7 +9435,7 @@ async function waitForPortRelease(port, maxWaitMs = 10000, pollIntervalMs = 500)
|
|
|
7498
9435
|
*/
|
|
7499
9436
|
function fixPackageJsonPort(cwd, targetPort) {
|
|
7500
9437
|
const packageJsonPath = join$1(cwd, 'package.json');
|
|
7501
|
-
if (!existsSync(packageJsonPath)) {
|
|
9438
|
+
if (!existsSync$1(packageJsonPath)) {
|
|
7502
9439
|
buildLogger$1.log('debug', 'process-manager', 'No package.json found to fix', { cwd });
|
|
7503
9440
|
return false;
|
|
7504
9441
|
}
|
|
@@ -7625,19 +9562,19 @@ async function stopAllDevServers(tunnelManager) {
|
|
|
7625
9562
|
}
|
|
7626
9563
|
|
|
7627
9564
|
var processManager = /*#__PURE__*/Object.freeze({
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
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
|
|
7641
9578
|
});
|
|
7642
9579
|
|
|
7643
9580
|
/**
|
|
@@ -7647,7 +9584,7 @@ var processManager = /*#__PURE__*/Object.freeze({
|
|
|
7647
9584
|
function getWorkspaceRoot() {
|
|
7648
9585
|
// Check environment variable first
|
|
7649
9586
|
const envWorkspace = process.env.WORKSPACE_ROOT;
|
|
7650
|
-
if (envWorkspace && existsSync(envWorkspace)) {
|
|
9587
|
+
if (envWorkspace && existsSync$1(envWorkspace)) {
|
|
7651
9588
|
return resolve(envWorkspace);
|
|
7652
9589
|
}
|
|
7653
9590
|
// Default to a workspace directory in the user's home
|
|
@@ -9139,10 +11076,10 @@ async function selectTemplateFromPrompt(userPrompt) {
|
|
|
9139
11076
|
}
|
|
9140
11077
|
|
|
9141
11078
|
var config = /*#__PURE__*/Object.freeze({
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
11079
|
+
__proto__: null,
|
|
11080
|
+
getAllTemplates: getAllTemplates,
|
|
11081
|
+
loadTemplateConfig: loadTemplateConfig,
|
|
11082
|
+
selectTemplateFromPrompt: selectTemplateFromPrompt
|
|
9146
11083
|
});
|
|
9147
11084
|
|
|
9148
11085
|
/**
|
|
@@ -9160,7 +11097,7 @@ async function downloadTemplate(template, targetPath) {
|
|
|
9160
11097
|
console.log(` Target: ${targetPath}`);
|
|
9161
11098
|
// Check if target already exists and add random suffix if needed
|
|
9162
11099
|
let finalTargetPath = targetPath;
|
|
9163
|
-
if (existsSync(targetPath)) {
|
|
11100
|
+
if (existsSync$1(targetPath)) {
|
|
9164
11101
|
// Generate a unique 4-character suffix
|
|
9165
11102
|
const randomSuffix = Math.random().toString(36).substring(2, 6);
|
|
9166
11103
|
finalTargetPath = `${targetPath}-${randomSuffix}`;
|
|
@@ -9232,12 +11169,12 @@ async function downloadTemplateWithGit(template, targetPath) {
|
|
|
9232
11169
|
// Handle multi-package projects with client/server subdirectories
|
|
9233
11170
|
const clientPkgPath = join$1(targetPath, 'client', 'package.json');
|
|
9234
11171
|
const serverPkgPath = join$1(targetPath, 'server', 'package.json');
|
|
9235
|
-
if (existsSync(clientPkgPath)) {
|
|
11172
|
+
if (existsSync$1(clientPkgPath)) {
|
|
9236
11173
|
await updatePackageName(join$1(targetPath, 'client'), `${projectName}-client`);
|
|
9237
11174
|
await removeHardcodedPorts(join$1(targetPath, 'client'));
|
|
9238
11175
|
await ensureVitePortConfig(join$1(targetPath, 'client'));
|
|
9239
11176
|
}
|
|
9240
|
-
if (existsSync(serverPkgPath)) {
|
|
11177
|
+
if (existsSync$1(serverPkgPath)) {
|
|
9241
11178
|
await updatePackageName(join$1(targetPath, 'server'), `${projectName}-server`);
|
|
9242
11179
|
await removeHardcodedPorts(join$1(targetPath, 'server'));
|
|
9243
11180
|
await ensureVitePortConfig(join$1(targetPath, 'server'));
|
|
@@ -9272,7 +11209,7 @@ shamefully-hoist=false
|
|
|
9272
11209
|
*/
|
|
9273
11210
|
async function updatePackageName(projectPath, newName) {
|
|
9274
11211
|
const pkgPath = join$1(projectPath, 'package.json');
|
|
9275
|
-
if (!existsSync(pkgPath)) {
|
|
11212
|
+
if (!existsSync$1(pkgPath)) {
|
|
9276
11213
|
if (process.env.DEBUG_BUILD === '1')
|
|
9277
11214
|
console.log(` No package.json found in ${projectPath}, skipping name update`);
|
|
9278
11215
|
return;
|
|
@@ -9295,7 +11232,7 @@ async function updatePackageName(projectPath, newName) {
|
|
|
9295
11232
|
*/
|
|
9296
11233
|
async function removeHardcodedPorts(projectPath) {
|
|
9297
11234
|
const pkgPath = join$1(projectPath, 'package.json');
|
|
9298
|
-
if (!existsSync(pkgPath)) {
|
|
11235
|
+
if (!existsSync$1(pkgPath)) {
|
|
9299
11236
|
return;
|
|
9300
11237
|
}
|
|
9301
11238
|
try {
|
|
@@ -9344,11 +11281,11 @@ async function ensureVitePortConfig(projectPath) {
|
|
|
9344
11281
|
const viteConfigJs = join$1(projectPath, 'vite.config.js');
|
|
9345
11282
|
const viteConfigMts = join$1(projectPath, 'vite.config.mts');
|
|
9346
11283
|
let configPath = null;
|
|
9347
|
-
if (existsSync(viteConfigTs))
|
|
11284
|
+
if (existsSync$1(viteConfigTs))
|
|
9348
11285
|
configPath = viteConfigTs;
|
|
9349
|
-
else if (existsSync(viteConfigMts))
|
|
11286
|
+
else if (existsSync$1(viteConfigMts))
|
|
9350
11287
|
configPath = viteConfigMts;
|
|
9351
|
-
else if (existsSync(viteConfigJs))
|
|
11288
|
+
else if (existsSync$1(viteConfigJs))
|
|
9352
11289
|
configPath = viteConfigJs;
|
|
9353
11290
|
if (!configPath)
|
|
9354
11291
|
return;
|
|
@@ -9486,7 +11423,7 @@ async function orchestrateBuild(context) {
|
|
|
9486
11423
|
}
|
|
9487
11424
|
// Verify directory state for logging
|
|
9488
11425
|
try {
|
|
9489
|
-
if (existsSync(workingDirectory)) {
|
|
11426
|
+
if (existsSync$1(workingDirectory)) {
|
|
9490
11427
|
const files = await readdir(workingDirectory);
|
|
9491
11428
|
if (process.env.DEBUG_BUILD === '1')
|
|
9492
11429
|
console.log(`[orchestrator] Directory status: ${files.length} files found`);
|
|
@@ -9973,7 +11910,7 @@ function getCleanEnv() {
|
|
|
9973
11910
|
* Ensure a directory exists
|
|
9974
11911
|
*/
|
|
9975
11912
|
function ensureDir(dir) {
|
|
9976
|
-
if (!existsSync
|
|
11913
|
+
if (!existsSync(dir)) {
|
|
9977
11914
|
mkdirSync$1(dir, { recursive: true });
|
|
9978
11915
|
}
|
|
9979
11916
|
}
|
|
@@ -10407,10 +12344,10 @@ async function waitForPort(port, maxRetries = 10, delayMs = 500) {
|
|
|
10407
12344
|
}
|
|
10408
12345
|
|
|
10409
12346
|
var portChecker = /*#__PURE__*/Object.freeze({
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
|
|
12347
|
+
__proto__: null,
|
|
12348
|
+
isPortReady: isPortReady,
|
|
12349
|
+
setSilentMode: setSilentMode,
|
|
12350
|
+
waitForPort: waitForPort
|
|
10414
12351
|
});
|
|
10415
12352
|
|
|
10416
12353
|
/**
|
|
@@ -10587,7 +12524,7 @@ const DEBUG_BUILD = process.env.DEBUG_BUILD === "1" || false;
|
|
|
10587
12524
|
const log = (...args) => {
|
|
10588
12525
|
const message = args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ');
|
|
10589
12526
|
try {
|
|
10590
|
-
const logger = getLogger();
|
|
12527
|
+
const logger = getLogger$1();
|
|
10591
12528
|
logger.info('system', message);
|
|
10592
12529
|
}
|
|
10593
12530
|
catch {
|
|
@@ -10601,7 +12538,7 @@ const log = (...args) => {
|
|
|
10601
12538
|
const buildLog = (...args) => {
|
|
10602
12539
|
const message = args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ');
|
|
10603
12540
|
try {
|
|
10604
|
-
const logger = getLogger();
|
|
12541
|
+
const logger = getLogger$1();
|
|
10605
12542
|
logger.info('build', message);
|
|
10606
12543
|
}
|
|
10607
12544
|
catch {
|
|
@@ -10617,7 +12554,7 @@ const debugLog = (...args) => {
|
|
|
10617
12554
|
return;
|
|
10618
12555
|
const message = args.map(a => typeof a === 'string' ? a : JSON.stringify(a)).join(' ');
|
|
10619
12556
|
try {
|
|
10620
|
-
const logger = getLogger();
|
|
12557
|
+
const logger = getLogger$1();
|
|
10621
12558
|
logger.debug('system', message);
|
|
10622
12559
|
}
|
|
10623
12560
|
catch {
|
|
@@ -10660,7 +12597,7 @@ function createClaudeQuery(modelId = DEFAULT_CLAUDE_MODEL_ID) {
|
|
|
10660
12597
|
// Use the full model ID as-is (claude-haiku-4-5, claude-sonnet-4-5, claude-opus-4-5)
|
|
10661
12598
|
const aiSdkModelId = modelId || "claude-haiku-4-5";
|
|
10662
12599
|
// Ensure working directory exists before passing to Claude Code
|
|
10663
|
-
if (!existsSync(workingDirectory)) {
|
|
12600
|
+
if (!existsSync$1(workingDirectory)) {
|
|
10664
12601
|
console.log(`[createClaudeQuery] Creating working directory: ${workingDirectory}`);
|
|
10665
12602
|
mkdirSync(workingDirectory, { recursive: true });
|
|
10666
12603
|
}
|
|
@@ -11141,7 +13078,7 @@ async function startRunner(options = {}) {
|
|
|
11141
13078
|
}
|
|
11142
13079
|
const runnerSharedSecret = SHARED_SECRET; // Guaranteed to be string after validation check
|
|
11143
13080
|
// Ensure workspace directory exists
|
|
11144
|
-
if (!existsSync(WORKSPACE_ROOT)) {
|
|
13081
|
+
if (!existsSync$1(WORKSPACE_ROOT)) {
|
|
11145
13082
|
console.log(`📁 Creating workspace directory: ${WORKSPACE_ROOT}`);
|
|
11146
13083
|
mkdirSync(WORKSPACE_ROOT, { recursive: true });
|
|
11147
13084
|
}
|
|
@@ -11172,14 +13109,14 @@ async function startRunner(options = {}) {
|
|
|
11172
13109
|
id: RUNNER_ID,
|
|
11173
13110
|
connected: socket?.readyState === WebSocket$1.OPEN,
|
|
11174
13111
|
workspace: WORKSPACE_ROOT,
|
|
11175
|
-
workspaceExists: existsSync(WORKSPACE_ROOT),
|
|
13112
|
+
workspaceExists: existsSync$1(WORKSPACE_ROOT),
|
|
11176
13113
|
},
|
|
11177
13114
|
uptime: process.uptime(),
|
|
11178
13115
|
timestamp: new Date().toISOString(),
|
|
11179
13116
|
});
|
|
11180
13117
|
});
|
|
11181
13118
|
healthApp.get('/ready', (req, res) => {
|
|
11182
|
-
const isReady = socket?.readyState === WebSocket$1.OPEN && existsSync(WORKSPACE_ROOT);
|
|
13119
|
+
const isReady = socket?.readyState === WebSocket$1.OPEN && existsSync$1(WORKSPACE_ROOT);
|
|
11183
13120
|
res.status(isReady ? 200 : 503).json({
|
|
11184
13121
|
ready: isReady,
|
|
11185
13122
|
runnerId: RUNNER_ID,
|
|
@@ -12616,7 +14553,7 @@ async function startRunner(options = {}) {
|
|
|
12616
14553
|
// Detect framework from generated files
|
|
12617
14554
|
let detectedFramework = null;
|
|
12618
14555
|
try {
|
|
12619
|
-
const { detectFrameworkFromFilesystem } = await import('./chunks/port-allocator-
|
|
14556
|
+
const { detectFrameworkFromFilesystem } = await import('./chunks/port-allocator-Ct3ioni4.js');
|
|
12620
14557
|
const framework = await detectFrameworkFromFilesystem(projectDirectory);
|
|
12621
14558
|
detectedFramework = framework;
|
|
12622
14559
|
if (framework) {
|
|
@@ -13274,3 +15211,4 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
|
|
13274
15211
|
}
|
|
13275
15212
|
|
|
13276
15213
|
export { startRunner };
|
|
15214
|
+
//# sourceMappingURL=index.js.map
|