@ljoukov/llm 4.1.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -32
- package/dist/index.cjs +632 -305
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +90 -44
- package/dist/index.d.ts +90 -44
- package/dist/index.js +632 -307
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -53,6 +53,7 @@ __export(index_exports, {
|
|
|
53
53
|
applyPatch: () => applyPatch,
|
|
54
54
|
configureGemini: () => configureGemini,
|
|
55
55
|
configureModelConcurrency: () => configureModelConcurrency,
|
|
56
|
+
configureTelemetry: () => configureTelemetry,
|
|
56
57
|
convertGooglePartsToLlmParts: () => convertGooglePartsToLlmParts,
|
|
57
58
|
createApplyPatchTool: () => createApplyPatchTool,
|
|
58
59
|
createCodexApplyPatchTool: () => createCodexApplyPatchTool,
|
|
@@ -101,6 +102,7 @@ __export(index_exports, {
|
|
|
101
102
|
parseJsonFromLlmText: () => parseJsonFromLlmText,
|
|
102
103
|
refreshChatGptOauthToken: () => refreshChatGptOauthToken,
|
|
103
104
|
resetModelConcurrencyConfig: () => resetModelConcurrencyConfig,
|
|
105
|
+
resetTelemetry: () => resetTelemetry,
|
|
104
106
|
resolveFilesystemToolProfile: () => resolveFilesystemToolProfile,
|
|
105
107
|
resolveFireworksModelId: () => resolveFireworksModelId,
|
|
106
108
|
runAgentLoop: () => runAgentLoop,
|
|
@@ -2674,7 +2676,7 @@ function getOpenAiFetch() {
|
|
|
2674
2676
|
headersTimeout: timeoutMs
|
|
2675
2677
|
});
|
|
2676
2678
|
openAiClientState.cachedFetch = ((input, init) => {
|
|
2677
|
-
return
|
|
2679
|
+
return fetch(input, {
|
|
2678
2680
|
...init ?? {},
|
|
2679
2681
|
dispatcher
|
|
2680
2682
|
});
|
|
@@ -3384,6 +3386,9 @@ var OPENAI_UPLOAD_PART_MAX_BYTES = 64 * 1024 * 1024;
|
|
|
3384
3386
|
var GEMINI_FILE_POLL_INTERVAL_MS = 1e3;
|
|
3385
3387
|
var GEMINI_FILE_POLL_TIMEOUT_MS = 6e4;
|
|
3386
3388
|
var FILES_TEMP_ROOT = import_node_path4.default.join(import_node_os3.default.tmpdir(), "ljoukov-llm-files");
|
|
3389
|
+
var FILES_CACHE_ROOT = import_node_path4.default.join(FILES_TEMP_ROOT, "cache");
|
|
3390
|
+
var FILES_CACHE_CONTENT_ROOT = import_node_path4.default.join(FILES_CACHE_ROOT, "content");
|
|
3391
|
+
var FILES_CACHE_METADATA_ROOT = import_node_path4.default.join(FILES_CACHE_ROOT, "metadata");
|
|
3387
3392
|
var filesState = getRuntimeSingleton(/* @__PURE__ */ Symbol.for("@ljoukov/llm.filesState"), () => ({
|
|
3388
3393
|
metadataById: /* @__PURE__ */ new Map(),
|
|
3389
3394
|
openAiUploadCacheByKey: /* @__PURE__ */ new Map(),
|
|
@@ -3529,6 +3534,12 @@ function toStoredFile(file) {
|
|
|
3529
3534
|
function buildCacheKey(filename, mimeType, sha256Hex) {
|
|
3530
3535
|
return `${sha256Hex}\0${filename}\0${mimeType}`;
|
|
3531
3536
|
}
|
|
3537
|
+
function buildCachedContentPath(sha256Hex) {
|
|
3538
|
+
return import_node_path4.default.join(FILES_CACHE_CONTENT_ROOT, sha256Hex);
|
|
3539
|
+
}
|
|
3540
|
+
function buildCachedMetadataPath(fileId) {
|
|
3541
|
+
return import_node_path4.default.join(FILES_CACHE_METADATA_ROOT, `${fileId}.json`);
|
|
3542
|
+
}
|
|
3532
3543
|
function isFresh(file) {
|
|
3533
3544
|
if (!file.expires_at) {
|
|
3534
3545
|
return true;
|
|
@@ -3549,6 +3560,82 @@ function recordMetadata(metadata) {
|
|
|
3549
3560
|
}
|
|
3550
3561
|
return metadata;
|
|
3551
3562
|
}
|
|
3563
|
+
async function ensureFilesCacheReady() {
|
|
3564
|
+
await (0, import_promises2.mkdir)(FILES_CACHE_CONTENT_ROOT, { recursive: true });
|
|
3565
|
+
await (0, import_promises2.mkdir)(FILES_CACHE_METADATA_ROOT, { recursive: true });
|
|
3566
|
+
}
|
|
3567
|
+
async function cacheBufferLocally(bytes, sha256Hex) {
|
|
3568
|
+
await ensureFilesCacheReady();
|
|
3569
|
+
const localPath = buildCachedContentPath(sha256Hex);
|
|
3570
|
+
try {
|
|
3571
|
+
await (0, import_promises2.writeFile)(localPath, bytes, { flag: "wx" });
|
|
3572
|
+
} catch (error) {
|
|
3573
|
+
const code = error.code;
|
|
3574
|
+
if (code !== "EEXIST") {
|
|
3575
|
+
throw error;
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
return localPath;
|
|
3579
|
+
}
|
|
3580
|
+
async function cacheFileLocally(filePath, sha256Hex) {
|
|
3581
|
+
await ensureFilesCacheReady();
|
|
3582
|
+
const localPath = buildCachedContentPath(sha256Hex);
|
|
3583
|
+
try {
|
|
3584
|
+
await (0, import_promises2.copyFile)(filePath, localPath);
|
|
3585
|
+
} catch (error) {
|
|
3586
|
+
const code = error.code;
|
|
3587
|
+
if (code !== "EEXIST") {
|
|
3588
|
+
throw error;
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
return localPath;
|
|
3592
|
+
}
|
|
3593
|
+
async function persistMetadataToDisk(metadata) {
|
|
3594
|
+
await ensureFilesCacheReady();
|
|
3595
|
+
const payload = {
|
|
3596
|
+
file: metadata.file,
|
|
3597
|
+
filename: metadata.filename,
|
|
3598
|
+
bytes: metadata.bytes,
|
|
3599
|
+
mimeType: metadata.mimeType,
|
|
3600
|
+
sha256Hex: metadata.sha256Hex,
|
|
3601
|
+
localPath: metadata.localPath
|
|
3602
|
+
};
|
|
3603
|
+
await (0, import_promises2.writeFile)(
|
|
3604
|
+
buildCachedMetadataPath(metadata.file.id),
|
|
3605
|
+
`${JSON.stringify(payload, null, 2)}
|
|
3606
|
+
`
|
|
3607
|
+
);
|
|
3608
|
+
}
|
|
3609
|
+
async function loadPersistedMetadata(fileId) {
|
|
3610
|
+
try {
|
|
3611
|
+
const payload = JSON.parse(
|
|
3612
|
+
await (0, import_promises2.readFile)(buildCachedMetadataPath(fileId), "utf8")
|
|
3613
|
+
);
|
|
3614
|
+
if (!payload || typeof payload !== "object" || !payload.file) {
|
|
3615
|
+
return void 0;
|
|
3616
|
+
}
|
|
3617
|
+
if (payload.localPath) {
|
|
3618
|
+
try {
|
|
3619
|
+
const localStats = await (0, import_promises2.stat)(payload.localPath);
|
|
3620
|
+
if (!localStats.isFile()) {
|
|
3621
|
+
return void 0;
|
|
3622
|
+
}
|
|
3623
|
+
} catch {
|
|
3624
|
+
return void 0;
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
3627
|
+
return recordMetadata({
|
|
3628
|
+
file: payload.file,
|
|
3629
|
+
filename: payload.filename,
|
|
3630
|
+
bytes: payload.bytes,
|
|
3631
|
+
mimeType: payload.mimeType,
|
|
3632
|
+
sha256Hex: payload.sha256Hex,
|
|
3633
|
+
localPath: payload.localPath
|
|
3634
|
+
});
|
|
3635
|
+
} catch {
|
|
3636
|
+
return void 0;
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3552
3639
|
async function uploadOpenAiFileFromBytes(params) {
|
|
3553
3640
|
const cacheKey = buildCacheKey(params.filename, params.mimeType, params.sha256Hex);
|
|
3554
3641
|
const cached = filesState.openAiUploadCacheByKey.get(cacheKey);
|
|
@@ -3697,17 +3784,23 @@ async function retrieveOpenAiFile(fileId) {
|
|
|
3697
3784
|
if (cached && isFresh(cached.file)) {
|
|
3698
3785
|
return cached;
|
|
3699
3786
|
}
|
|
3787
|
+
const persisted = await loadPersistedMetadata(fileId);
|
|
3788
|
+
if (persisted && isFresh(persisted.file)) {
|
|
3789
|
+
return persisted;
|
|
3790
|
+
}
|
|
3700
3791
|
const client = getOpenAiClient();
|
|
3701
3792
|
const retrieved = await client.files.retrieve(fileId);
|
|
3702
3793
|
const file = toStoredFile(retrieved);
|
|
3703
|
-
|
|
3794
|
+
const metadata = recordMetadata({
|
|
3704
3795
|
file,
|
|
3705
3796
|
filename: file.filename,
|
|
3706
3797
|
bytes: file.bytes,
|
|
3707
|
-
mimeType: cached?.mimeType ?? resolveMimeType(file.filename, void 0),
|
|
3708
|
-
sha256Hex: cached?.sha256Hex,
|
|
3709
|
-
localPath: cached?.localPath
|
|
3798
|
+
mimeType: cached?.mimeType ?? persisted?.mimeType ?? resolveMimeType(file.filename, void 0),
|
|
3799
|
+
sha256Hex: cached?.sha256Hex ?? persisted?.sha256Hex,
|
|
3800
|
+
localPath: cached?.localPath ?? persisted?.localPath
|
|
3710
3801
|
});
|
|
3802
|
+
await persistMetadataToDisk(metadata);
|
|
3803
|
+
return metadata;
|
|
3711
3804
|
}
|
|
3712
3805
|
function buildGeminiMirrorName(sha256Hex) {
|
|
3713
3806
|
return `files/${sha256Hex.slice(0, 40)}`;
|
|
@@ -3819,6 +3912,7 @@ async function materializeOpenAiFile(fileId) {
|
|
|
3819
3912
|
sha256Hex,
|
|
3820
3913
|
localPath
|
|
3821
3914
|
});
|
|
3915
|
+
await persistMetadataToDisk(updated);
|
|
3822
3916
|
return {
|
|
3823
3917
|
file: updated.file,
|
|
3824
3918
|
filename: updated.filename,
|
|
@@ -3982,7 +4076,13 @@ async function filesCreate(params) {
|
|
|
3982
4076
|
sha256Hex: sha256Hex2,
|
|
3983
4077
|
bytes: info.size
|
|
3984
4078
|
});
|
|
3985
|
-
|
|
4079
|
+
const localPath2 = await cacheFileLocally(filePath, sha256Hex2);
|
|
4080
|
+
const cached2 = recordMetadata({
|
|
4081
|
+
...uploaded2,
|
|
4082
|
+
localPath: localPath2
|
|
4083
|
+
});
|
|
4084
|
+
await persistMetadataToDisk(cached2);
|
|
4085
|
+
return cached2.file;
|
|
3986
4086
|
}
|
|
3987
4087
|
const filename = normaliseFilename(params.filename);
|
|
3988
4088
|
const bytes = toBuffer(params.data);
|
|
@@ -3996,7 +4096,13 @@ async function filesCreate(params) {
|
|
|
3996
4096
|
expiresAfterSeconds,
|
|
3997
4097
|
sha256Hex
|
|
3998
4098
|
});
|
|
3999
|
-
|
|
4099
|
+
const localPath = await cacheBufferLocally(bytes, sha256Hex);
|
|
4100
|
+
const cached = recordMetadata({
|
|
4101
|
+
...uploaded,
|
|
4102
|
+
localPath
|
|
4103
|
+
});
|
|
4104
|
+
await persistMetadataToDisk(cached);
|
|
4105
|
+
return cached.file;
|
|
4000
4106
|
}
|
|
4001
4107
|
async function filesRetrieve(fileId) {
|
|
4002
4108
|
return (await retrieveOpenAiFile(fileId)).file;
|
|
@@ -4029,6 +4135,10 @@ async function filesDelete(fileId) {
|
|
|
4029
4135
|
const response = await getOpenAiClient().files.delete(fileId);
|
|
4030
4136
|
filesState.metadataById.delete(fileId);
|
|
4031
4137
|
filesState.materializedById.delete(fileId);
|
|
4138
|
+
try {
|
|
4139
|
+
await (0, import_promises2.unlink)(buildCachedMetadataPath(fileId));
|
|
4140
|
+
} catch {
|
|
4141
|
+
}
|
|
4032
4142
|
return {
|
|
4033
4143
|
id: response.id,
|
|
4034
4144
|
deleted: response.deleted,
|
|
@@ -4057,6 +4167,71 @@ var files = {
|
|
|
4057
4167
|
content: filesContent
|
|
4058
4168
|
};
|
|
4059
4169
|
|
|
4170
|
+
// src/telemetry.ts
|
|
4171
|
+
var telemetryState = getRuntimeSingleton(
|
|
4172
|
+
/* @__PURE__ */ Symbol.for("@ljoukov/llm.telemetryState"),
|
|
4173
|
+
() => ({
|
|
4174
|
+
configuredTelemetry: void 0
|
|
4175
|
+
})
|
|
4176
|
+
);
|
|
4177
|
+
function configureTelemetry(telemetry = void 0) {
|
|
4178
|
+
telemetryState.configuredTelemetry = telemetry === void 0 || telemetry === false ? void 0 : telemetry;
|
|
4179
|
+
}
|
|
4180
|
+
function resetTelemetry() {
|
|
4181
|
+
telemetryState.configuredTelemetry = void 0;
|
|
4182
|
+
}
|
|
4183
|
+
function isPromiseLike2(value) {
|
|
4184
|
+
return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.then === "function";
|
|
4185
|
+
}
|
|
4186
|
+
function resolveTelemetrySelection(telemetry) {
|
|
4187
|
+
if (telemetry === false) {
|
|
4188
|
+
return void 0;
|
|
4189
|
+
}
|
|
4190
|
+
if (telemetry !== void 0) {
|
|
4191
|
+
return telemetry;
|
|
4192
|
+
}
|
|
4193
|
+
return telemetryState.configuredTelemetry;
|
|
4194
|
+
}
|
|
4195
|
+
function createTelemetrySession(telemetry) {
|
|
4196
|
+
const config = resolveTelemetrySelection(telemetry);
|
|
4197
|
+
if (!config) {
|
|
4198
|
+
return void 0;
|
|
4199
|
+
}
|
|
4200
|
+
const pending = /* @__PURE__ */ new Set();
|
|
4201
|
+
const trackPromise = (promise) => {
|
|
4202
|
+
pending.add(promise);
|
|
4203
|
+
promise.finally(() => {
|
|
4204
|
+
pending.delete(promise);
|
|
4205
|
+
});
|
|
4206
|
+
};
|
|
4207
|
+
const emit = (event) => {
|
|
4208
|
+
try {
|
|
4209
|
+
const output = config.sink.emit(event);
|
|
4210
|
+
if (isPromiseLike2(output)) {
|
|
4211
|
+
const task = Promise.resolve(output).then(() => void 0).catch(() => void 0);
|
|
4212
|
+
trackPromise(task);
|
|
4213
|
+
}
|
|
4214
|
+
} catch {
|
|
4215
|
+
}
|
|
4216
|
+
};
|
|
4217
|
+
const flush = async () => {
|
|
4218
|
+
while (pending.size > 0) {
|
|
4219
|
+
await Promise.allSettled([...pending]);
|
|
4220
|
+
}
|
|
4221
|
+
if (typeof config.sink.flush === "function") {
|
|
4222
|
+
try {
|
|
4223
|
+
await config.sink.flush();
|
|
4224
|
+
} catch {
|
|
4225
|
+
}
|
|
4226
|
+
}
|
|
4227
|
+
};
|
|
4228
|
+
return {
|
|
4229
|
+
includeStreamEvents: config.includeStreamEvents === true,
|
|
4230
|
+
emit,
|
|
4231
|
+
flush
|
|
4232
|
+
};
|
|
4233
|
+
}
|
|
4234
|
+
|
|
4060
4235
|
// src/llm.ts
|
|
4061
4236
|
var toolCallContextStorage = getRuntimeSingleton(
|
|
4062
4237
|
/* @__PURE__ */ Symbol.for("@ljoukov/llm.toolCallContextStorage"),
|
|
@@ -4508,8 +4683,7 @@ function toGeminiPart(part) {
|
|
|
4508
4683
|
return {
|
|
4509
4684
|
fileData: {
|
|
4510
4685
|
fileUri: buildCanonicalGeminiFileUri(part.file_id),
|
|
4511
|
-
mimeType: inferToolOutputMimeTypeFromFilename(part.filename) ?? "application/octet-stream"
|
|
4512
|
-
displayName: part.filename ?? void 0
|
|
4686
|
+
mimeType: inferToolOutputMimeTypeFromFilename(part.filename) ?? "application/octet-stream"
|
|
4513
4687
|
}
|
|
4514
4688
|
};
|
|
4515
4689
|
}
|
|
@@ -4527,8 +4701,7 @@ function toGeminiPart(part) {
|
|
|
4527
4701
|
return {
|
|
4528
4702
|
fileData: {
|
|
4529
4703
|
fileUri: part.image_url,
|
|
4530
|
-
mimeType: inferToolOutputMimeTypeFromFilename(part.filename) ?? "application/octet-stream"
|
|
4531
|
-
displayName: part.filename ?? void 0
|
|
4704
|
+
mimeType: inferToolOutputMimeTypeFromFilename(part.filename) ?? "application/octet-stream"
|
|
4532
4705
|
}
|
|
4533
4706
|
};
|
|
4534
4707
|
}
|
|
@@ -4537,8 +4710,7 @@ function toGeminiPart(part) {
|
|
|
4537
4710
|
return {
|
|
4538
4711
|
fileData: {
|
|
4539
4712
|
fileUri: buildCanonicalGeminiFileUri(part.file_id),
|
|
4540
|
-
mimeType: inferToolOutputMimeTypeFromFilename(part.filename) ?? "application/octet-stream"
|
|
4541
|
-
displayName: part.filename ?? void 0
|
|
4713
|
+
mimeType: inferToolOutputMimeTypeFromFilename(part.filename) ?? "application/octet-stream"
|
|
4542
4714
|
}
|
|
4543
4715
|
};
|
|
4544
4716
|
}
|
|
@@ -4564,8 +4736,7 @@ function toGeminiPart(part) {
|
|
|
4564
4736
|
return {
|
|
4565
4737
|
fileData: {
|
|
4566
4738
|
fileUri: part.file_url,
|
|
4567
|
-
mimeType: inferToolOutputMimeTypeFromFilename(part.filename) ?? "application/octet-stream"
|
|
4568
|
-
displayName: part.filename ?? void 0
|
|
4739
|
+
mimeType: inferToolOutputMimeTypeFromFilename(part.filename) ?? "application/octet-stream"
|
|
4569
4740
|
}
|
|
4570
4741
|
};
|
|
4571
4742
|
}
|
|
@@ -4797,7 +4968,7 @@ async function prepareOpenAiPromptContentItem(item) {
|
|
|
4797
4968
|
mimeType,
|
|
4798
4969
|
filename
|
|
4799
4970
|
});
|
|
4800
|
-
return { type: "input_file", file_id: uploaded.fileId
|
|
4971
|
+
return { type: "input_file", file_id: uploaded.fileId };
|
|
4801
4972
|
}
|
|
4802
4973
|
if (typeof item.file_url === "string" && item.file_url.trim().toLowerCase().startsWith("data:")) {
|
|
4803
4974
|
const parsed = parseDataUrlPayload(item.file_url);
|
|
@@ -4812,7 +4983,7 @@ async function prepareOpenAiPromptContentItem(item) {
|
|
|
4812
4983
|
guessInlineDataFilename(parsed.mimeType)
|
|
4813
4984
|
)
|
|
4814
4985
|
});
|
|
4815
|
-
return { type: "input_file", file_id: uploaded.fileId
|
|
4986
|
+
return { type: "input_file", file_id: uploaded.fileId };
|
|
4816
4987
|
}
|
|
4817
4988
|
return item;
|
|
4818
4989
|
}
|
|
@@ -4877,21 +5048,16 @@ async function prepareGeminiPromptContents(contents) {
|
|
|
4877
5048
|
for (const part of content.parts ?? []) {
|
|
4878
5049
|
const canonicalFileId = parseCanonicalGeminiFileId(part.fileData?.fileUri);
|
|
4879
5050
|
if (canonicalFileId) {
|
|
4880
|
-
|
|
5051
|
+
await getCanonicalFileMetadata(canonicalFileId);
|
|
4881
5052
|
if (backend === "api") {
|
|
4882
5053
|
const mirrored = await ensureGeminiFileMirror(canonicalFileId);
|
|
4883
|
-
|
|
4884
|
-
if (metadata.filename && mirroredPart.fileData) {
|
|
4885
|
-
mirroredPart.fileData.displayName = metadata.filename;
|
|
4886
|
-
}
|
|
4887
|
-
parts.push(mirroredPart);
|
|
5054
|
+
parts.push((0, import_genai2.createPartFromUri)(mirrored.uri, mirrored.mimeType));
|
|
4888
5055
|
} else {
|
|
4889
5056
|
const mirrored = await ensureVertexFileMirror(canonicalFileId);
|
|
4890
5057
|
parts.push({
|
|
4891
5058
|
fileData: {
|
|
4892
5059
|
fileUri: mirrored.fileUri,
|
|
4893
|
-
mimeType: mirrored.mimeType
|
|
4894
|
-
displayName: metadata.filename
|
|
5060
|
+
mimeType: mirrored.mimeType
|
|
4895
5061
|
}
|
|
4896
5062
|
});
|
|
4897
5063
|
}
|
|
@@ -4910,18 +5076,13 @@ async function prepareGeminiPromptContents(contents) {
|
|
|
4910
5076
|
});
|
|
4911
5077
|
if (backend === "api") {
|
|
4912
5078
|
const mirrored = await ensureGeminiFileMirror(stored.fileId);
|
|
4913
|
-
|
|
4914
|
-
if (filename && mirroredPart.fileData) {
|
|
4915
|
-
mirroredPart.fileData.displayName = filename;
|
|
4916
|
-
}
|
|
4917
|
-
parts.push(mirroredPart);
|
|
5079
|
+
parts.push((0, import_genai2.createPartFromUri)(mirrored.uri, mirrored.mimeType));
|
|
4918
5080
|
} else {
|
|
4919
5081
|
const mirrored = await ensureVertexFileMirror(stored.fileId);
|
|
4920
5082
|
parts.push({
|
|
4921
5083
|
fileData: {
|
|
4922
5084
|
fileUri: mirrored.fileUri,
|
|
4923
|
-
mimeType: mirrored.mimeType
|
|
4924
|
-
displayName: filename
|
|
5085
|
+
mimeType: mirrored.mimeType
|
|
4925
5086
|
}
|
|
4926
5087
|
});
|
|
4927
5088
|
}
|
|
@@ -5442,7 +5603,7 @@ function toOpenAiInput(contents) {
|
|
|
5442
5603
|
...part.file_id ? { file_id: part.file_id } : {},
|
|
5443
5604
|
...part.file_data ? { file_data: part.file_data } : {},
|
|
5444
5605
|
...part.file_url ? { file_url: part.file_url } : {},
|
|
5445
|
-
|
|
5606
|
+
...!part.file_id && part.filename ? { filename: part.filename } : {}
|
|
5446
5607
|
});
|
|
5447
5608
|
break;
|
|
5448
5609
|
default:
|
|
@@ -5527,7 +5688,7 @@ function toChatGptInput(contents) {
|
|
|
5527
5688
|
...part.file_id ? { file_id: part.file_id } : {},
|
|
5528
5689
|
...part.file_data ? { file_data: part.file_data } : {},
|
|
5529
5690
|
...part.file_url ? { file_url: part.file_url } : {},
|
|
5530
|
-
|
|
5691
|
+
...!part.file_id && part.filename ? { filename: part.filename } : {}
|
|
5531
5692
|
});
|
|
5532
5693
|
break;
|
|
5533
5694
|
default:
|
|
@@ -5657,6 +5818,65 @@ function mergeTokenUpdates(current, next) {
|
|
|
5657
5818
|
toolUsePromptTokens: next.toolUsePromptTokens ?? current.toolUsePromptTokens
|
|
5658
5819
|
};
|
|
5659
5820
|
}
|
|
5821
|
+
function sumUsageValue(current, next) {
|
|
5822
|
+
if (typeof next !== "number" || !Number.isFinite(next)) {
|
|
5823
|
+
return current;
|
|
5824
|
+
}
|
|
5825
|
+
const normalizedNext = Math.max(0, next);
|
|
5826
|
+
if (typeof current !== "number" || !Number.isFinite(current)) {
|
|
5827
|
+
return normalizedNext;
|
|
5828
|
+
}
|
|
5829
|
+
return Math.max(0, current) + normalizedNext;
|
|
5830
|
+
}
|
|
5831
|
+
function sumUsageTokens(current, next) {
|
|
5832
|
+
if (!next) {
|
|
5833
|
+
return current;
|
|
5834
|
+
}
|
|
5835
|
+
return {
|
|
5836
|
+
promptTokens: sumUsageValue(current?.promptTokens, next.promptTokens),
|
|
5837
|
+
cachedTokens: sumUsageValue(current?.cachedTokens, next.cachedTokens),
|
|
5838
|
+
responseTokens: sumUsageValue(current?.responseTokens, next.responseTokens),
|
|
5839
|
+
responseImageTokens: sumUsageValue(current?.responseImageTokens, next.responseImageTokens),
|
|
5840
|
+
thinkingTokens: sumUsageValue(current?.thinkingTokens, next.thinkingTokens),
|
|
5841
|
+
totalTokens: sumUsageValue(current?.totalTokens, next.totalTokens),
|
|
5842
|
+
toolUsePromptTokens: sumUsageValue(current?.toolUsePromptTokens, next.toolUsePromptTokens)
|
|
5843
|
+
};
|
|
5844
|
+
}
|
|
5845
|
+
function countInlineImagesInContent(content) {
|
|
5846
|
+
if (!content) {
|
|
5847
|
+
return 0;
|
|
5848
|
+
}
|
|
5849
|
+
let count = 0;
|
|
5850
|
+
for (const part of content.parts) {
|
|
5851
|
+
if (part.type === "inlineData" && isInlineImageMime(part.mimeType)) {
|
|
5852
|
+
count += 1;
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5855
|
+
return count;
|
|
5856
|
+
}
|
|
5857
|
+
function createLlmTelemetryEmitter(params) {
|
|
5858
|
+
const session = createTelemetrySession(params.telemetry);
|
|
5859
|
+
const callId = (0, import_node_crypto2.randomBytes)(8).toString("hex");
|
|
5860
|
+
return {
|
|
5861
|
+
includeStreamEvents: session?.includeStreamEvents === true,
|
|
5862
|
+
emit: (event) => {
|
|
5863
|
+
if (!session) {
|
|
5864
|
+
return;
|
|
5865
|
+
}
|
|
5866
|
+
session.emit({
|
|
5867
|
+
...event,
|
|
5868
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5869
|
+
callId,
|
|
5870
|
+
operation: params.operation,
|
|
5871
|
+
provider: params.provider,
|
|
5872
|
+
model: params.model
|
|
5873
|
+
});
|
|
5874
|
+
},
|
|
5875
|
+
flush: async () => {
|
|
5876
|
+
await session?.flush();
|
|
5877
|
+
}
|
|
5878
|
+
};
|
|
5879
|
+
}
|
|
5660
5880
|
function toMaybeNumber(value) {
|
|
5661
5881
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
5662
5882
|
return value;
|
|
@@ -6134,8 +6354,7 @@ function buildGeminiToolOutputMediaPart(item) {
|
|
|
6134
6354
|
return {
|
|
6135
6355
|
fileData: {
|
|
6136
6356
|
fileUri: buildCanonicalGeminiFileUri(item.file_id),
|
|
6137
|
-
mimeType: inferToolOutputMimeTypeFromFilename(item.filename) ?? "application/octet-stream"
|
|
6138
|
-
displayName: item.filename ?? void 0
|
|
6357
|
+
mimeType: inferToolOutputMimeTypeFromFilename(item.filename) ?? "application/octet-stream"
|
|
6139
6358
|
}
|
|
6140
6359
|
};
|
|
6141
6360
|
}
|
|
@@ -6154,8 +6373,7 @@ function buildGeminiToolOutputMediaPart(item) {
|
|
|
6154
6373
|
return {
|
|
6155
6374
|
fileData: {
|
|
6156
6375
|
fileUri: item.image_url,
|
|
6157
|
-
mimeType: inferToolOutputMimeTypeFromFilename(item.filename) ?? "application/octet-stream"
|
|
6158
|
-
displayName: item.filename ?? void 0
|
|
6376
|
+
mimeType: inferToolOutputMimeTypeFromFilename(item.filename) ?? "application/octet-stream"
|
|
6159
6377
|
}
|
|
6160
6378
|
};
|
|
6161
6379
|
}
|
|
@@ -6164,8 +6382,7 @@ function buildGeminiToolOutputMediaPart(item) {
|
|
|
6164
6382
|
return {
|
|
6165
6383
|
fileData: {
|
|
6166
6384
|
fileUri: buildCanonicalGeminiFileUri(item.file_id),
|
|
6167
|
-
mimeType: inferToolOutputMimeTypeFromFilename(item.filename) ?? "application/octet-stream"
|
|
6168
|
-
displayName: item.filename ?? void 0
|
|
6385
|
+
mimeType: inferToolOutputMimeTypeFromFilename(item.filename) ?? "application/octet-stream"
|
|
6169
6386
|
}
|
|
6170
6387
|
};
|
|
6171
6388
|
}
|
|
@@ -6188,12 +6405,7 @@ function buildGeminiToolOutputMediaPart(item) {
|
|
|
6188
6405
|
return part;
|
|
6189
6406
|
}
|
|
6190
6407
|
if (typeof item.file_url === "string" && item.file_url.trim().length > 0 && inferredMimeType) {
|
|
6191
|
-
|
|
6192
|
-
const displayName = item.filename?.trim();
|
|
6193
|
-
if (displayName && part.fileData) {
|
|
6194
|
-
part.fileData.displayName = displayName;
|
|
6195
|
-
}
|
|
6196
|
-
return part;
|
|
6408
|
+
return (0, import_genai2.createPartFromUri)(item.file_url, inferredMimeType);
|
|
6197
6409
|
}
|
|
6198
6410
|
}
|
|
6199
6411
|
return null;
|
|
@@ -7074,6 +7286,10 @@ async function runTextCall(params) {
|
|
|
7074
7286
|
let responseRole;
|
|
7075
7287
|
let latestUsage;
|
|
7076
7288
|
let responseImages = 0;
|
|
7289
|
+
const pushEvent = (event) => {
|
|
7290
|
+
queue.push(event);
|
|
7291
|
+
params.onEvent?.(event);
|
|
7292
|
+
};
|
|
7077
7293
|
const pushDelta = (channel, text) => {
|
|
7078
7294
|
if (!text) {
|
|
7079
7295
|
return;
|
|
@@ -7084,7 +7300,7 @@ async function runTextCall(params) {
|
|
|
7084
7300
|
} else {
|
|
7085
7301
|
callLogger?.appendResponseDelta(text);
|
|
7086
7302
|
}
|
|
7087
|
-
|
|
7303
|
+
pushEvent({ type: "delta", channel, text });
|
|
7088
7304
|
};
|
|
7089
7305
|
const pushInline = (data, mimeType) => {
|
|
7090
7306
|
if (!data) {
|
|
@@ -7154,7 +7370,7 @@ async function runTextCall(params) {
|
|
|
7154
7370
|
}
|
|
7155
7371
|
case "response.refusal.delta": {
|
|
7156
7372
|
blocked = true;
|
|
7157
|
-
|
|
7373
|
+
pushEvent({ type: "blocked" });
|
|
7158
7374
|
break;
|
|
7159
7375
|
}
|
|
7160
7376
|
default:
|
|
@@ -7163,7 +7379,7 @@ async function runTextCall(params) {
|
|
|
7163
7379
|
}
|
|
7164
7380
|
const finalResponse = await stream.finalResponse();
|
|
7165
7381
|
modelVersion = typeof finalResponse.model === "string" ? finalResponse.model : request.model;
|
|
7166
|
-
|
|
7382
|
+
pushEvent({ type: "model", modelVersion });
|
|
7167
7383
|
if (finalResponse.error) {
|
|
7168
7384
|
const message = typeof finalResponse.error.message === "string" ? finalResponse.error.message : "OpenAI response failed";
|
|
7169
7385
|
throw new Error(message);
|
|
@@ -7227,11 +7443,11 @@ async function runTextCall(params) {
|
|
|
7227
7443
|
});
|
|
7228
7444
|
blocked = blocked || result2.blocked;
|
|
7229
7445
|
if (blocked) {
|
|
7230
|
-
|
|
7446
|
+
pushEvent({ type: "blocked" });
|
|
7231
7447
|
}
|
|
7232
7448
|
if (result2.model) {
|
|
7233
7449
|
modelVersion = providerInfo.serviceTier ? request.model : `chatgpt-${result2.model}`;
|
|
7234
|
-
|
|
7450
|
+
pushEvent({ type: "model", modelVersion });
|
|
7235
7451
|
}
|
|
7236
7452
|
latestUsage = extractChatGptUsageTokens(result2.usage);
|
|
7237
7453
|
const fallbackText = typeof result2.text === "string" ? result2.text : "";
|
|
@@ -7269,11 +7485,11 @@ async function runTextCall(params) {
|
|
|
7269
7485
|
{ signal }
|
|
7270
7486
|
);
|
|
7271
7487
|
modelVersion = typeof response.model === "string" ? response.model : request.model;
|
|
7272
|
-
|
|
7488
|
+
pushEvent({ type: "model", modelVersion });
|
|
7273
7489
|
const choice = Array.isArray(response.choices) ? response.choices[0] : void 0;
|
|
7274
7490
|
if (choice?.finish_reason === "content_filter") {
|
|
7275
7491
|
blocked = true;
|
|
7276
|
-
|
|
7492
|
+
pushEvent({ type: "blocked" });
|
|
7277
7493
|
}
|
|
7278
7494
|
const textOutput = extractFireworksMessageText(
|
|
7279
7495
|
choice?.message
|
|
@@ -7315,11 +7531,11 @@ async function runTextCall(params) {
|
|
|
7315
7531
|
for await (const chunk of stream) {
|
|
7316
7532
|
if (chunk.modelVersion) {
|
|
7317
7533
|
modelVersion = chunk.modelVersion;
|
|
7318
|
-
|
|
7534
|
+
pushEvent({ type: "model", modelVersion });
|
|
7319
7535
|
}
|
|
7320
7536
|
if (chunk.promptFeedback?.blockReason) {
|
|
7321
7537
|
blocked = true;
|
|
7322
|
-
|
|
7538
|
+
pushEvent({ type: "blocked" });
|
|
7323
7539
|
}
|
|
7324
7540
|
latestUsage = mergeTokenUpdates(
|
|
7325
7541
|
latestUsage,
|
|
@@ -7332,7 +7548,7 @@ async function runTextCall(params) {
|
|
|
7332
7548
|
const primary = candidates[0];
|
|
7333
7549
|
if (primary && isModerationFinish(primary.finishReason)) {
|
|
7334
7550
|
blocked = true;
|
|
7335
|
-
|
|
7551
|
+
pushEvent({ type: "blocked" });
|
|
7336
7552
|
}
|
|
7337
7553
|
for (const candidate of candidates) {
|
|
7338
7554
|
const candidateContent = candidate.content;
|
|
@@ -7369,7 +7585,7 @@ async function runTextCall(params) {
|
|
|
7369
7585
|
imageSize: request.imageSize
|
|
7370
7586
|
});
|
|
7371
7587
|
if (latestUsage) {
|
|
7372
|
-
|
|
7588
|
+
pushEvent({ type: "usage", usage: latestUsage, costUsd, modelVersion });
|
|
7373
7589
|
}
|
|
7374
7590
|
callLogger?.complete({
|
|
7375
7591
|
responseText: text,
|
|
@@ -7423,18 +7639,76 @@ async function runTextCall(params) {
|
|
|
7423
7639
|
});
|
|
7424
7640
|
return result;
|
|
7425
7641
|
}
|
|
7426
|
-
function
|
|
7642
|
+
function startTextStream(request, operation) {
|
|
7427
7643
|
const queue = createAsyncQueue();
|
|
7428
7644
|
const abortController = new AbortController();
|
|
7645
|
+
const provider = resolveProvider(request.model).provider;
|
|
7646
|
+
const telemetry = createLlmTelemetryEmitter({
|
|
7647
|
+
telemetry: request.telemetry,
|
|
7648
|
+
operation,
|
|
7649
|
+
provider,
|
|
7650
|
+
model: request.model
|
|
7651
|
+
});
|
|
7652
|
+
const startedAtMs = Date.now();
|
|
7653
|
+
telemetry.emit({
|
|
7654
|
+
type: "llm.call.started",
|
|
7655
|
+
inputMode: typeof request.input === "string" ? "string" : "messages",
|
|
7656
|
+
toolCount: request.tools?.length ?? 0,
|
|
7657
|
+
responseModalities: request.responseModalities
|
|
7658
|
+
});
|
|
7429
7659
|
const result = (async () => {
|
|
7660
|
+
let uploadMetrics = emptyFileUploadMetrics();
|
|
7430
7661
|
try {
|
|
7431
|
-
|
|
7662
|
+
let output;
|
|
7663
|
+
await collectFileUploadMetrics(async () => {
|
|
7664
|
+
try {
|
|
7665
|
+
output = await runTextCall({
|
|
7666
|
+
request,
|
|
7667
|
+
queue,
|
|
7668
|
+
abortController,
|
|
7669
|
+
onEvent: telemetry.includeStreamEvents ? (event) => {
|
|
7670
|
+
telemetry.emit({ type: "llm.call.stream", event });
|
|
7671
|
+
} : void 0
|
|
7672
|
+
});
|
|
7673
|
+
} finally {
|
|
7674
|
+
uploadMetrics = getCurrentFileUploadMetrics();
|
|
7675
|
+
}
|
|
7676
|
+
});
|
|
7677
|
+
if (!output) {
|
|
7678
|
+
throw new Error("LLM text call returned no result.");
|
|
7679
|
+
}
|
|
7680
|
+
telemetry.emit({
|
|
7681
|
+
type: "llm.call.completed",
|
|
7682
|
+
success: true,
|
|
7683
|
+
durationMs: Math.max(0, Date.now() - startedAtMs),
|
|
7684
|
+
modelVersion: output.modelVersion,
|
|
7685
|
+
blocked: output.blocked,
|
|
7686
|
+
usage: output.usage,
|
|
7687
|
+
costUsd: output.costUsd,
|
|
7688
|
+
outputTextChars: output.text.length,
|
|
7689
|
+
thoughtChars: output.thoughts.length,
|
|
7690
|
+
responseImages: countInlineImagesInContent(output.content),
|
|
7691
|
+
uploadCount: uploadMetrics.count,
|
|
7692
|
+
uploadBytes: uploadMetrics.totalBytes,
|
|
7693
|
+
uploadLatencyMs: uploadMetrics.totalLatencyMs
|
|
7694
|
+
});
|
|
7432
7695
|
queue.close();
|
|
7433
7696
|
return output;
|
|
7434
7697
|
} catch (error) {
|
|
7435
7698
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
7699
|
+
telemetry.emit({
|
|
7700
|
+
type: "llm.call.completed",
|
|
7701
|
+
success: false,
|
|
7702
|
+
durationMs: Math.max(0, Date.now() - startedAtMs),
|
|
7703
|
+
uploadCount: uploadMetrics.count,
|
|
7704
|
+
uploadBytes: uploadMetrics.totalBytes,
|
|
7705
|
+
uploadLatencyMs: uploadMetrics.totalLatencyMs,
|
|
7706
|
+
error: err.message
|
|
7707
|
+
});
|
|
7436
7708
|
queue.fail(err);
|
|
7437
7709
|
throw err;
|
|
7710
|
+
} finally {
|
|
7711
|
+
await telemetry.flush();
|
|
7438
7712
|
}
|
|
7439
7713
|
})();
|
|
7440
7714
|
return {
|
|
@@ -7443,8 +7717,11 @@ function streamText(request) {
|
|
|
7443
7717
|
abort: () => abortController.abort()
|
|
7444
7718
|
};
|
|
7445
7719
|
}
|
|
7720
|
+
function streamText(request) {
|
|
7721
|
+
return startTextStream(request, "streamText");
|
|
7722
|
+
}
|
|
7446
7723
|
async function generateText(request) {
|
|
7447
|
-
const call =
|
|
7724
|
+
const call = startTextStream(request, "generateText");
|
|
7448
7725
|
for await (const _event of call.events) {
|
|
7449
7726
|
}
|
|
7450
7727
|
return await call.result;
|
|
@@ -7470,9 +7747,26 @@ function buildJsonSchemaConfig(request) {
|
|
|
7470
7747
|
} : void 0;
|
|
7471
7748
|
return { providerInfo, responseJsonSchema, openAiTextFormat };
|
|
7472
7749
|
}
|
|
7473
|
-
function
|
|
7750
|
+
function startJsonStream(request, operation) {
|
|
7474
7751
|
const queue = createAsyncQueue();
|
|
7475
7752
|
const abortController = new AbortController();
|
|
7753
|
+
const provider = resolveProvider(request.model).provider;
|
|
7754
|
+
const telemetry = createLlmTelemetryEmitter({
|
|
7755
|
+
telemetry: request.telemetry,
|
|
7756
|
+
operation,
|
|
7757
|
+
provider,
|
|
7758
|
+
model: request.model
|
|
7759
|
+
});
|
|
7760
|
+
const startedAtMs = Date.now();
|
|
7761
|
+
const maxAttempts = Math.max(1, Math.floor(request.maxAttempts ?? 2));
|
|
7762
|
+
const streamMode = request.streamMode ?? "partial";
|
|
7763
|
+
telemetry.emit({
|
|
7764
|
+
type: "llm.call.started",
|
|
7765
|
+
inputMode: typeof request.input === "string" ? "string" : "messages",
|
|
7766
|
+
toolCount: request.tools?.length ?? 0,
|
|
7767
|
+
maxAttempts,
|
|
7768
|
+
streamMode
|
|
7769
|
+
});
|
|
7476
7770
|
const resolveAbortSignal = () => {
|
|
7477
7771
|
if (!request.signal) {
|
|
7478
7772
|
return abortController.signal;
|
|
@@ -7491,135 +7785,155 @@ function streamJson(request) {
|
|
|
7491
7785
|
return abortController.signal;
|
|
7492
7786
|
};
|
|
7493
7787
|
const result = (async () => {
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
let openAiTextFormatForAttempt = openAiTextFormat;
|
|
7500
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
7501
|
-
let rawText = "";
|
|
7502
|
-
let lastPartial = "";
|
|
7503
|
-
try {
|
|
7504
|
-
const call = streamText({
|
|
7505
|
-
model: request.model,
|
|
7506
|
-
input: request.input,
|
|
7507
|
-
instructions: request.instructions,
|
|
7508
|
-
tools: request.tools,
|
|
7509
|
-
responseMimeType: request.responseMimeType ?? "application/json",
|
|
7510
|
-
responseJsonSchema,
|
|
7511
|
-
thinkingLevel: request.thinkingLevel,
|
|
7512
|
-
...openAiTextFormatForAttempt ? { openAiTextFormat: openAiTextFormatForAttempt } : {},
|
|
7513
|
-
signal
|
|
7514
|
-
});
|
|
7788
|
+
let uploadMetrics = emptyFileUploadMetrics();
|
|
7789
|
+
let attemptsUsed = 0;
|
|
7790
|
+
try {
|
|
7791
|
+
let output;
|
|
7792
|
+
await collectFileUploadMetrics(async () => {
|
|
7515
7793
|
try {
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7794
|
+
const signal = resolveAbortSignal();
|
|
7795
|
+
const { providerInfo, responseJsonSchema, openAiTextFormat } = buildJsonSchemaConfig(request);
|
|
7796
|
+
const failures = [];
|
|
7797
|
+
let openAiTextFormatForAttempt = openAiTextFormat;
|
|
7798
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
7799
|
+
attemptsUsed = attempt;
|
|
7800
|
+
let rawText = "";
|
|
7801
|
+
let lastPartial = "";
|
|
7802
|
+
try {
|
|
7803
|
+
const call = streamText({
|
|
7804
|
+
model: request.model,
|
|
7805
|
+
input: request.input,
|
|
7806
|
+
instructions: request.instructions,
|
|
7807
|
+
tools: request.tools,
|
|
7808
|
+
responseMimeType: request.responseMimeType ?? "application/json",
|
|
7809
|
+
responseJsonSchema,
|
|
7810
|
+
thinkingLevel: request.thinkingLevel,
|
|
7811
|
+
...openAiTextFormatForAttempt ? { openAiTextFormat: openAiTextFormatForAttempt } : {},
|
|
7812
|
+
telemetry: false,
|
|
7813
|
+
signal
|
|
7814
|
+
});
|
|
7815
|
+
try {
|
|
7816
|
+
for await (const event of call.events) {
|
|
7817
|
+
queue.push(event);
|
|
7818
|
+
if (telemetry.includeStreamEvents) {
|
|
7819
|
+
telemetry.emit({ type: "llm.call.stream", event });
|
|
7820
|
+
}
|
|
7821
|
+
if (event.type === "delta" && event.channel === "response") {
|
|
7822
|
+
rawText += event.text;
|
|
7823
|
+
if (streamMode === "partial") {
|
|
7824
|
+
const partial = parsePartialJsonFromLlmText(rawText);
|
|
7825
|
+
if (partial !== null) {
|
|
7826
|
+
const serialized = JSON.stringify(partial);
|
|
7827
|
+
if (serialized !== lastPartial) {
|
|
7828
|
+
lastPartial = serialized;
|
|
7829
|
+
queue.push({
|
|
7830
|
+
type: "json",
|
|
7831
|
+
stage: "partial",
|
|
7832
|
+
value: partial
|
|
7833
|
+
});
|
|
7834
|
+
}
|
|
7835
|
+
}
|
|
7836
|
+
}
|
|
7531
7837
|
}
|
|
7532
7838
|
}
|
|
7839
|
+
} catch (streamError) {
|
|
7840
|
+
await call.result.catch(() => void 0);
|
|
7841
|
+
throw streamError;
|
|
7842
|
+
}
|
|
7843
|
+
const result2 = await call.result;
|
|
7844
|
+
rawText = rawText || result2.text;
|
|
7845
|
+
const cleanedText = normalizeJsonText(rawText);
|
|
7846
|
+
const repairedText = escapeNewlinesInStrings(cleanedText);
|
|
7847
|
+
const payload = JSON.parse(repairedText);
|
|
7848
|
+
const normalized = typeof request.normalizeJson === "function" ? request.normalizeJson(payload) : payload;
|
|
7849
|
+
const parsed = request.schema.parse(normalized);
|
|
7850
|
+
queue.push({ type: "json", stage: "final", value: parsed });
|
|
7851
|
+
output = { value: parsed, rawText, result: result2 };
|
|
7852
|
+
return;
|
|
7853
|
+
} catch (error) {
|
|
7854
|
+
const handled = error instanceof Error ? error : new Error(String(error));
|
|
7855
|
+
failures.push({ attempt, rawText, error: handled });
|
|
7856
|
+
if (providerInfo.provider === "chatgpt" && openAiTextFormatForAttempt) {
|
|
7857
|
+
openAiTextFormatForAttempt = void 0;
|
|
7858
|
+
}
|
|
7859
|
+
if (attempt >= maxAttempts) {
|
|
7860
|
+
throw new LlmJsonCallError(
|
|
7861
|
+
`LLM JSON call failed after ${attempt} attempt(s)`,
|
|
7862
|
+
failures
|
|
7863
|
+
);
|
|
7533
7864
|
}
|
|
7534
7865
|
}
|
|
7535
7866
|
}
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
}
|
|
7540
|
-
const result2 = await call.result;
|
|
7541
|
-
rawText = rawText || result2.text;
|
|
7542
|
-
const cleanedText = normalizeJsonText(rawText);
|
|
7543
|
-
const repairedText = escapeNewlinesInStrings(cleanedText);
|
|
7544
|
-
const payload = JSON.parse(repairedText);
|
|
7545
|
-
const normalized = typeof request.normalizeJson === "function" ? request.normalizeJson(payload) : payload;
|
|
7546
|
-
const parsed = request.schema.parse(normalized);
|
|
7547
|
-
queue.push({ type: "json", stage: "final", value: parsed });
|
|
7548
|
-
queue.close();
|
|
7549
|
-
return { value: parsed, rawText, result: result2 };
|
|
7550
|
-
} catch (error) {
|
|
7551
|
-
const handled = error instanceof Error ? error : new Error(String(error));
|
|
7552
|
-
failures.push({ attempt, rawText, error: handled });
|
|
7553
|
-
if (providerInfo.provider === "chatgpt" && openAiTextFormatForAttempt) {
|
|
7554
|
-
openAiTextFormatForAttempt = void 0;
|
|
7555
|
-
}
|
|
7556
|
-
if (attempt >= maxAttempts) {
|
|
7557
|
-
throw new LlmJsonCallError(`LLM JSON call failed after ${attempt} attempt(s)`, failures);
|
|
7867
|
+
throw new LlmJsonCallError("LLM JSON call failed", failures);
|
|
7868
|
+
} finally {
|
|
7869
|
+
uploadMetrics = getCurrentFileUploadMetrics();
|
|
7558
7870
|
}
|
|
7559
|
-
}
|
|
7871
|
+
});
|
|
7872
|
+
if (!output) {
|
|
7873
|
+
throw new Error("LLM JSON call returned no result.");
|
|
7874
|
+
}
|
|
7875
|
+
telemetry.emit({
|
|
7876
|
+
type: "llm.call.completed",
|
|
7877
|
+
success: true,
|
|
7878
|
+
durationMs: Math.max(0, Date.now() - startedAtMs),
|
|
7879
|
+
modelVersion: output.result.modelVersion,
|
|
7880
|
+
blocked: output.result.blocked,
|
|
7881
|
+
usage: output.result.usage,
|
|
7882
|
+
costUsd: output.result.costUsd,
|
|
7883
|
+
rawTextChars: output.rawText.length,
|
|
7884
|
+
attempts: attemptsUsed,
|
|
7885
|
+
uploadCount: uploadMetrics.count,
|
|
7886
|
+
uploadBytes: uploadMetrics.totalBytes,
|
|
7887
|
+
uploadLatencyMs: uploadMetrics.totalLatencyMs
|
|
7888
|
+
});
|
|
7889
|
+
queue.close();
|
|
7890
|
+
return output;
|
|
7891
|
+
} catch (error) {
|
|
7892
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
7893
|
+
telemetry.emit({
|
|
7894
|
+
type: "llm.call.completed",
|
|
7895
|
+
success: false,
|
|
7896
|
+
durationMs: Math.max(0, Date.now() - startedAtMs),
|
|
7897
|
+
attempts: attemptsUsed > 0 ? attemptsUsed : void 0,
|
|
7898
|
+
uploadCount: uploadMetrics.count,
|
|
7899
|
+
uploadBytes: uploadMetrics.totalBytes,
|
|
7900
|
+
uploadLatencyMs: uploadMetrics.totalLatencyMs,
|
|
7901
|
+
error: err.message
|
|
7902
|
+
});
|
|
7903
|
+
queue.fail(err);
|
|
7904
|
+
throw err;
|
|
7905
|
+
} finally {
|
|
7906
|
+
await telemetry.flush();
|
|
7560
7907
|
}
|
|
7561
|
-
|
|
7562
|
-
})().catch((error) => {
|
|
7563
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
7564
|
-
queue.fail(err);
|
|
7565
|
-
throw err;
|
|
7566
|
-
});
|
|
7908
|
+
})();
|
|
7567
7909
|
return {
|
|
7568
7910
|
events: queue.iterable,
|
|
7569
7911
|
result,
|
|
7570
7912
|
abort: () => abortController.abort()
|
|
7571
7913
|
};
|
|
7572
7914
|
}
|
|
7915
|
+
function streamJson(request) {
|
|
7916
|
+
return startJsonStream(request, "streamJson");
|
|
7917
|
+
}
|
|
7573
7918
|
async function generateJson(request) {
|
|
7574
|
-
const
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
tools: request.tools,
|
|
7586
|
-
responseMimeType: request.responseMimeType ?? "application/json",
|
|
7587
|
-
responseJsonSchema,
|
|
7588
|
-
thinkingLevel: request.thinkingLevel,
|
|
7589
|
-
...openAiTextFormatForAttempt ? { openAiTextFormat: openAiTextFormatForAttempt } : {},
|
|
7590
|
-
signal: request.signal
|
|
7591
|
-
});
|
|
7592
|
-
try {
|
|
7593
|
-
for await (const event of call.events) {
|
|
7594
|
-
request.onEvent?.(event);
|
|
7595
|
-
if (event.type === "delta" && event.channel === "response") {
|
|
7596
|
-
rawText += event.text;
|
|
7597
|
-
}
|
|
7598
|
-
}
|
|
7599
|
-
} catch (streamError) {
|
|
7600
|
-
await call.result.catch(() => void 0);
|
|
7601
|
-
throw streamError;
|
|
7602
|
-
}
|
|
7603
|
-
const result = await call.result;
|
|
7604
|
-
rawText = rawText || result.text;
|
|
7605
|
-
const cleanedText = normalizeJsonText(rawText);
|
|
7606
|
-
const repairedText = escapeNewlinesInStrings(cleanedText);
|
|
7607
|
-
const payload = JSON.parse(repairedText);
|
|
7608
|
-
const normalized = typeof request.normalizeJson === "function" ? request.normalizeJson(payload) : payload;
|
|
7609
|
-
const parsed = request.schema.parse(normalized);
|
|
7610
|
-
return { value: parsed, rawText, result };
|
|
7611
|
-
} catch (error) {
|
|
7612
|
-
const handled = error instanceof Error ? error : new Error(String(error));
|
|
7613
|
-
failures.push({ attempt, rawText, error: handled });
|
|
7614
|
-
if (providerInfo.provider === "chatgpt" && openAiTextFormatForAttempt) {
|
|
7615
|
-
openAiTextFormatForAttempt = void 0;
|
|
7616
|
-
}
|
|
7617
|
-
if (attempt >= maxAttempts) {
|
|
7618
|
-
throw new LlmJsonCallError(`LLM JSON call failed after ${attempt} attempt(s)`, failures);
|
|
7919
|
+
const call = startJsonStream(
|
|
7920
|
+
{
|
|
7921
|
+
...request,
|
|
7922
|
+
streamMode: "final"
|
|
7923
|
+
},
|
|
7924
|
+
"generateJson"
|
|
7925
|
+
);
|
|
7926
|
+
try {
|
|
7927
|
+
for await (const event of call.events) {
|
|
7928
|
+
if (event.type !== "json") {
|
|
7929
|
+
request.onEvent?.(event);
|
|
7619
7930
|
}
|
|
7620
7931
|
}
|
|
7932
|
+
} catch (streamError) {
|
|
7933
|
+
await call.result.catch(() => void 0);
|
|
7934
|
+
throw streamError;
|
|
7621
7935
|
}
|
|
7622
|
-
|
|
7936
|
+
return await call.result;
|
|
7623
7937
|
}
|
|
7624
7938
|
var DEFAULT_TOOL_LOOP_MAX_STEPS = 8;
|
|
7625
7939
|
function resolveToolLoopContents(input) {
|
|
@@ -9235,7 +9549,10 @@ function streamToolLoop(request) {
|
|
|
9235
9549
|
abort: () => abortController.abort()
|
|
9236
9550
|
};
|
|
9237
9551
|
}
|
|
9238
|
-
var
|
|
9552
|
+
var IMAGE_GRADE_VALUE_SCHEMA = import_zod3.z.enum(["pass", "fail"]);
|
|
9553
|
+
var IMAGE_GRADE_SCHEMA = import_zod3.z.object({
|
|
9554
|
+
grade: IMAGE_GRADE_VALUE_SCHEMA
|
|
9555
|
+
});
|
|
9239
9556
|
async function gradeGeneratedImage(params) {
|
|
9240
9557
|
const parts = [
|
|
9241
9558
|
{
|
|
@@ -9246,7 +9563,7 @@ async function gradeGeneratedImage(params) {
|
|
|
9246
9563
|
"Image prompt to grade:",
|
|
9247
9564
|
params.imagePrompt,
|
|
9248
9565
|
"",
|
|
9249
|
-
'Respond with
|
|
9566
|
+
'Respond with JSON like {"grade":"pass"} or {"grade":"fail"}.'
|
|
9250
9567
|
].join("\\n")
|
|
9251
9568
|
},
|
|
9252
9569
|
{
|
|
@@ -9255,12 +9572,13 @@ async function gradeGeneratedImage(params) {
|
|
|
9255
9572
|
mimeType: params.image.mimeType ?? "image/png"
|
|
9256
9573
|
}
|
|
9257
9574
|
];
|
|
9258
|
-
const { value } = await generateJson({
|
|
9575
|
+
const { value, result } = await generateJson({
|
|
9259
9576
|
model: params.model,
|
|
9260
9577
|
input: [{ role: "user", content: parts }],
|
|
9261
|
-
schema: IMAGE_GRADE_SCHEMA
|
|
9578
|
+
schema: IMAGE_GRADE_SCHEMA,
|
|
9579
|
+
telemetry: false
|
|
9262
9580
|
});
|
|
9263
|
-
return value;
|
|
9581
|
+
return { grade: value.grade, result };
|
|
9264
9582
|
}
|
|
9265
9583
|
async function generateImages(request) {
|
|
9266
9584
|
const maxAttempts = Math.max(1, Math.floor(request.maxAttempts ?? 4));
|
|
@@ -9280,6 +9598,19 @@ async function generateImages(request) {
|
|
|
9280
9598
|
if (!gradingPrompt) {
|
|
9281
9599
|
throw new Error("imageGradingPrompt must be a non-empty string");
|
|
9282
9600
|
}
|
|
9601
|
+
const telemetry = createLlmTelemetryEmitter({
|
|
9602
|
+
telemetry: request.telemetry,
|
|
9603
|
+
operation: "generateImages",
|
|
9604
|
+
provider: resolveProvider(request.model).provider,
|
|
9605
|
+
model: request.model
|
|
9606
|
+
});
|
|
9607
|
+
const startedAtMs = Date.now();
|
|
9608
|
+
telemetry.emit({
|
|
9609
|
+
type: "llm.call.started",
|
|
9610
|
+
imagePromptCount: promptList.length,
|
|
9611
|
+
styleImageCount: request.styleImages?.length ?? 0,
|
|
9612
|
+
maxAttempts
|
|
9613
|
+
});
|
|
9283
9614
|
const addText = (parts, text) => {
|
|
9284
9615
|
const lastPart = parts[parts.length - 1];
|
|
9285
9616
|
if (lastPart !== void 0 && lastPart.type === "text") {
|
|
@@ -9337,6 +9668,9 @@ async function generateImages(request) {
|
|
|
9337
9668
|
const inputMessages = [{ role: "user", content: buildInitialPromptParts() }];
|
|
9338
9669
|
const orderedEntries = [...promptEntries];
|
|
9339
9670
|
const resolvedImages = /* @__PURE__ */ new Map();
|
|
9671
|
+
let totalCostUsd = 0;
|
|
9672
|
+
let totalUsage;
|
|
9673
|
+
let attemptsUsed = 0;
|
|
9340
9674
|
const removeResolvedEntries = (resolved) => {
|
|
9341
9675
|
if (resolved.size === 0) {
|
|
9342
9676
|
return;
|
|
@@ -9351,70 +9685,118 @@ async function generateImages(request) {
|
|
|
9351
9685
|
}
|
|
9352
9686
|
}
|
|
9353
9687
|
};
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9688
|
+
let uploadMetrics = emptyFileUploadMetrics();
|
|
9689
|
+
try {
|
|
9690
|
+
await collectFileUploadMetrics(async () => {
|
|
9691
|
+
try {
|
|
9692
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
9693
|
+
attemptsUsed = attempt;
|
|
9694
|
+
const result = await generateText({
|
|
9695
|
+
model: request.model,
|
|
9696
|
+
input: inputMessages,
|
|
9697
|
+
responseModalities: ["IMAGE", "TEXT"],
|
|
9698
|
+
imageAspectRatio: request.imageAspectRatio,
|
|
9699
|
+
imageSize: request.imageSize ?? "2K",
|
|
9700
|
+
telemetry: false
|
|
9701
|
+
});
|
|
9702
|
+
totalCostUsd += result.costUsd;
|
|
9703
|
+
totalUsage = sumUsageTokens(totalUsage, result.usage);
|
|
9704
|
+
if (result.blocked || !result.content) {
|
|
9705
|
+
continue;
|
|
9706
|
+
}
|
|
9707
|
+
const images = extractImages(result.content);
|
|
9708
|
+
if (images.length > 0 && promptEntries.length > 0) {
|
|
9709
|
+
const assignedCount = Math.min(images.length, promptEntries.length);
|
|
9710
|
+
const pendingAssignments = promptEntries.slice(0, assignedCount);
|
|
9711
|
+
const assignedImages = images.slice(0, assignedCount);
|
|
9712
|
+
const gradeResults = await Promise.all(
|
|
9713
|
+
pendingAssignments.map(
|
|
9714
|
+
(entry, index) => gradeGeneratedImage({
|
|
9715
|
+
gradingPrompt,
|
|
9716
|
+
imagePrompt: entry.prompt,
|
|
9717
|
+
image: (() => {
|
|
9718
|
+
const image = assignedImages[index];
|
|
9719
|
+
if (!image) {
|
|
9720
|
+
throw new Error("Image generation returned fewer images than expected.");
|
|
9721
|
+
}
|
|
9722
|
+
return image;
|
|
9723
|
+
})(),
|
|
9724
|
+
model: "gpt-5.2"
|
|
9725
|
+
})
|
|
9726
|
+
)
|
|
9727
|
+
);
|
|
9728
|
+
const passedEntries = /* @__PURE__ */ new Set();
|
|
9729
|
+
for (let i = 0; i < gradeResults.length; i += 1) {
|
|
9730
|
+
const gradeResult = gradeResults[i];
|
|
9731
|
+
const entry = pendingAssignments[i];
|
|
9732
|
+
const image = assignedImages[i];
|
|
9733
|
+
if (!gradeResult || !entry || !image) {
|
|
9734
|
+
continue;
|
|
9379
9735
|
}
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9736
|
+
totalCostUsd += gradeResult.result.costUsd;
|
|
9737
|
+
totalUsage = sumUsageTokens(totalUsage, gradeResult.result.usage);
|
|
9738
|
+
if (gradeResult.grade === "pass") {
|
|
9739
|
+
resolvedImages.set(entry.index, image);
|
|
9740
|
+
passedEntries.add(entry.index);
|
|
9741
|
+
}
|
|
9742
|
+
}
|
|
9743
|
+
removeResolvedEntries(passedEntries);
|
|
9744
|
+
}
|
|
9745
|
+
if (promptEntries.length === 0) {
|
|
9746
|
+
break;
|
|
9747
|
+
}
|
|
9748
|
+
inputMessages.push({
|
|
9749
|
+
role: "assistant",
|
|
9750
|
+
content: result.content.parts
|
|
9751
|
+
});
|
|
9752
|
+
inputMessages.push({
|
|
9753
|
+
role: "user",
|
|
9754
|
+
content: buildContinuationPromptParts(promptEntries)
|
|
9755
|
+
});
|
|
9397
9756
|
}
|
|
9757
|
+
} finally {
|
|
9758
|
+
uploadMetrics = getCurrentFileUploadMetrics();
|
|
9398
9759
|
}
|
|
9399
|
-
removeResolvedEntries(passedEntries);
|
|
9400
|
-
}
|
|
9401
|
-
if (promptEntries.length === 0) {
|
|
9402
|
-
break;
|
|
9403
|
-
}
|
|
9404
|
-
inputMessages.push({
|
|
9405
|
-
role: "assistant",
|
|
9406
|
-
content: result.content.parts
|
|
9407
9760
|
});
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
orderedImages.push(image);
|
|
9761
|
+
const orderedImages = [];
|
|
9762
|
+
for (const entry of orderedEntries) {
|
|
9763
|
+
const image = resolvedImages.get(entry.index);
|
|
9764
|
+
if (image) {
|
|
9765
|
+
orderedImages.push(image);
|
|
9766
|
+
}
|
|
9415
9767
|
}
|
|
9768
|
+
const outputImages = orderedImages.slice(0, numImages);
|
|
9769
|
+
telemetry.emit({
|
|
9770
|
+
type: "llm.call.completed",
|
|
9771
|
+
success: true,
|
|
9772
|
+
durationMs: Math.max(0, Date.now() - startedAtMs),
|
|
9773
|
+
usage: totalUsage,
|
|
9774
|
+
costUsd: totalCostUsd,
|
|
9775
|
+
imageCount: outputImages.length,
|
|
9776
|
+
attempts: attemptsUsed,
|
|
9777
|
+
uploadCount: uploadMetrics.count,
|
|
9778
|
+
uploadBytes: uploadMetrics.totalBytes,
|
|
9779
|
+
uploadLatencyMs: uploadMetrics.totalLatencyMs
|
|
9780
|
+
});
|
|
9781
|
+
return outputImages;
|
|
9782
|
+
} catch (error) {
|
|
9783
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
9784
|
+
telemetry.emit({
|
|
9785
|
+
type: "llm.call.completed",
|
|
9786
|
+
success: false,
|
|
9787
|
+
durationMs: Math.max(0, Date.now() - startedAtMs),
|
|
9788
|
+
usage: totalUsage,
|
|
9789
|
+
costUsd: totalCostUsd,
|
|
9790
|
+
attempts: attemptsUsed > 0 ? attemptsUsed : void 0,
|
|
9791
|
+
uploadCount: uploadMetrics.count,
|
|
9792
|
+
uploadBytes: uploadMetrics.totalBytes,
|
|
9793
|
+
uploadLatencyMs: uploadMetrics.totalLatencyMs,
|
|
9794
|
+
error: err.message
|
|
9795
|
+
});
|
|
9796
|
+
throw err;
|
|
9797
|
+
} finally {
|
|
9798
|
+
await telemetry.flush();
|
|
9416
9799
|
}
|
|
9417
|
-
return orderedImages.slice(0, numImages);
|
|
9418
9800
|
}
|
|
9419
9801
|
async function generateImageInBatches(request) {
|
|
9420
9802
|
const {
|
|
@@ -12065,7 +12447,7 @@ function isNoEntError(error) {
|
|
|
12065
12447
|
|
|
12066
12448
|
// src/agent.ts
|
|
12067
12449
|
async function runAgentLoop(request) {
|
|
12068
|
-
const telemetry =
|
|
12450
|
+
const telemetry = createTelemetrySession(request.telemetry);
|
|
12069
12451
|
const logging = createRootAgentLoggingSession(request);
|
|
12070
12452
|
try {
|
|
12071
12453
|
return await runWithAgentLoggingSession(logging, async () => {
|
|
@@ -12151,7 +12533,7 @@ async function runAgentLoopInternal(request, context) {
|
|
|
12151
12533
|
logging: _logging,
|
|
12152
12534
|
...toolLoopRequest
|
|
12153
12535
|
} = request;
|
|
12154
|
-
const telemetrySession = context.telemetry ??
|
|
12536
|
+
const telemetrySession = context.telemetry ?? createTelemetrySession(telemetry);
|
|
12155
12537
|
const loggingSession = context.logging;
|
|
12156
12538
|
const runId = randomRunId();
|
|
12157
12539
|
const startedAtMs = Date.now();
|
|
@@ -12214,15 +12596,15 @@ async function runAgentLoopInternal(request, context) {
|
|
|
12214
12596
|
].join(" ")
|
|
12215
12597
|
);
|
|
12216
12598
|
const sourceOnEvent = toolLoopRequestWithSteering.onEvent;
|
|
12217
|
-
const
|
|
12599
|
+
const includeStreamEvents = telemetrySession?.includeStreamEvents === true;
|
|
12218
12600
|
const streamEventLogger = loggingSession ? createAgentStreamEventLogger({
|
|
12219
12601
|
append: (line) => {
|
|
12220
12602
|
loggingSession.logLine(`[agent:${runId}] ${line}`);
|
|
12221
12603
|
}
|
|
12222
12604
|
}) : void 0;
|
|
12223
|
-
const wrappedOnEvent = sourceOnEvent ||
|
|
12605
|
+
const wrappedOnEvent = sourceOnEvent || includeStreamEvents ? (event) => {
|
|
12224
12606
|
sourceOnEvent?.(event);
|
|
12225
|
-
if (
|
|
12607
|
+
if (includeStreamEvents) {
|
|
12226
12608
|
emitTelemetry({ type: "agent.run.stream", event });
|
|
12227
12609
|
}
|
|
12228
12610
|
streamEventLogger?.appendEvent(event);
|
|
@@ -12460,7 +12842,7 @@ function countToolCalls(result) {
|
|
|
12460
12842
|
}
|
|
12461
12843
|
return count;
|
|
12462
12844
|
}
|
|
12463
|
-
function
|
|
12845
|
+
function sumUsageValue2(current, next) {
|
|
12464
12846
|
if (typeof next !== "number" || !Number.isFinite(next)) {
|
|
12465
12847
|
return current;
|
|
12466
12848
|
}
|
|
@@ -12478,20 +12860,17 @@ function summarizeResultUsage(result) {
|
|
|
12478
12860
|
continue;
|
|
12479
12861
|
}
|
|
12480
12862
|
summary = {
|
|
12481
|
-
promptTokens:
|
|
12482
|
-
cachedTokens:
|
|
12483
|
-
responseTokens:
|
|
12484
|
-
responseImageTokens:
|
|
12485
|
-
thinkingTokens:
|
|
12486
|
-
totalTokens:
|
|
12487
|
-
toolUsePromptTokens:
|
|
12863
|
+
promptTokens: sumUsageValue2(summary?.promptTokens, usage.promptTokens),
|
|
12864
|
+
cachedTokens: sumUsageValue2(summary?.cachedTokens, usage.cachedTokens),
|
|
12865
|
+
responseTokens: sumUsageValue2(summary?.responseTokens, usage.responseTokens),
|
|
12866
|
+
responseImageTokens: sumUsageValue2(summary?.responseImageTokens, usage.responseImageTokens),
|
|
12867
|
+
thinkingTokens: sumUsageValue2(summary?.thinkingTokens, usage.thinkingTokens),
|
|
12868
|
+
totalTokens: sumUsageValue2(summary?.totalTokens, usage.totalTokens),
|
|
12869
|
+
toolUsePromptTokens: sumUsageValue2(summary?.toolUsePromptTokens, usage.toolUsePromptTokens)
|
|
12488
12870
|
};
|
|
12489
12871
|
}
|
|
12490
12872
|
return summary;
|
|
12491
12873
|
}
|
|
12492
|
-
function isPromiseLike2(value) {
|
|
12493
|
-
return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.then === "function";
|
|
12494
|
-
}
|
|
12495
12874
|
function resolveAgentLoggingSelection(value) {
|
|
12496
12875
|
if (value === false) {
|
|
12497
12876
|
return void 0;
|
|
@@ -12525,60 +12904,6 @@ function createRootAgentLoggingSession(request) {
|
|
|
12525
12904
|
mirrorToConsole: selected.mirrorToConsole !== false
|
|
12526
12905
|
});
|
|
12527
12906
|
}
|
|
12528
|
-
function isAgentTelemetrySink(value) {
|
|
12529
|
-
return typeof value === "object" && value !== null && typeof value.emit === "function";
|
|
12530
|
-
}
|
|
12531
|
-
function resolveTelemetrySelection(telemetry) {
|
|
12532
|
-
if (!telemetry) {
|
|
12533
|
-
return void 0;
|
|
12534
|
-
}
|
|
12535
|
-
if (isAgentTelemetrySink(telemetry)) {
|
|
12536
|
-
return { sink: telemetry };
|
|
12537
|
-
}
|
|
12538
|
-
if (isAgentTelemetrySink(telemetry.sink)) {
|
|
12539
|
-
return telemetry;
|
|
12540
|
-
}
|
|
12541
|
-
throw new Error("Invalid runAgentLoop telemetry config: expected a sink with emit(event).");
|
|
12542
|
-
}
|
|
12543
|
-
function createAgentTelemetrySession(telemetry) {
|
|
12544
|
-
const config = resolveTelemetrySelection(telemetry);
|
|
12545
|
-
if (!config) {
|
|
12546
|
-
return void 0;
|
|
12547
|
-
}
|
|
12548
|
-
const pending = /* @__PURE__ */ new Set();
|
|
12549
|
-
const trackPromise = (promise) => {
|
|
12550
|
-
pending.add(promise);
|
|
12551
|
-
promise.finally(() => {
|
|
12552
|
-
pending.delete(promise);
|
|
12553
|
-
});
|
|
12554
|
-
};
|
|
12555
|
-
const emit = (event) => {
|
|
12556
|
-
try {
|
|
12557
|
-
const output = config.sink.emit(event);
|
|
12558
|
-
if (isPromiseLike2(output)) {
|
|
12559
|
-
const task = Promise.resolve(output).then(() => void 0).catch(() => void 0);
|
|
12560
|
-
trackPromise(task);
|
|
12561
|
-
}
|
|
12562
|
-
} catch {
|
|
12563
|
-
}
|
|
12564
|
-
};
|
|
12565
|
-
const flush = async () => {
|
|
12566
|
-
while (pending.size > 0) {
|
|
12567
|
-
await Promise.allSettled([...pending]);
|
|
12568
|
-
}
|
|
12569
|
-
if (typeof config.sink.flush === "function") {
|
|
12570
|
-
try {
|
|
12571
|
-
await config.sink.flush();
|
|
12572
|
-
} catch {
|
|
12573
|
-
}
|
|
12574
|
-
}
|
|
12575
|
-
};
|
|
12576
|
-
return {
|
|
12577
|
-
includeLlmStreamEvents: config.includeLlmStreamEvents === true,
|
|
12578
|
-
emit,
|
|
12579
|
-
flush
|
|
12580
|
-
};
|
|
12581
|
-
}
|
|
12582
12907
|
function createAgentTelemetryEmitter(params) {
|
|
12583
12908
|
return (event) => {
|
|
12584
12909
|
if (!params.session) {
|
|
@@ -13272,6 +13597,7 @@ async function runCandidateEvolution(options) {
|
|
|
13272
13597
|
applyPatch,
|
|
13273
13598
|
configureGemini,
|
|
13274
13599
|
configureModelConcurrency,
|
|
13600
|
+
configureTelemetry,
|
|
13275
13601
|
convertGooglePartsToLlmParts,
|
|
13276
13602
|
createApplyPatchTool,
|
|
13277
13603
|
createCodexApplyPatchTool,
|
|
@@ -13320,6 +13646,7 @@ async function runCandidateEvolution(options) {
|
|
|
13320
13646
|
parseJsonFromLlmText,
|
|
13321
13647
|
refreshChatGptOauthToken,
|
|
13322
13648
|
resetModelConcurrencyConfig,
|
|
13649
|
+
resetTelemetry,
|
|
13323
13650
|
resolveFilesystemToolProfile,
|
|
13324
13651
|
resolveFireworksModelId,
|
|
13325
13652
|
runAgentLoop,
|