@ljoukov/llm 4.0.5 → 4.0.7
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 +4 -3
- package/dist/index.cjs +519 -168
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -12
- package/dist/index.d.ts +12 -12
- package/dist/index.js +519 -168
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2794,6 +2794,7 @@ var import_node_async_hooks = require("async_hooks");
|
|
|
2794
2794
|
var import_node_buffer2 = require("buffer");
|
|
2795
2795
|
var import_promises = require("fs/promises");
|
|
2796
2796
|
var import_node_path3 = __toESM(require("path"), 1);
|
|
2797
|
+
var DEFAULT_THOUGHT_DELTA_LOG_THROTTLE_MS = 4e3;
|
|
2797
2798
|
function toIsoNow() {
|
|
2798
2799
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2799
2800
|
}
|
|
@@ -2817,6 +2818,9 @@ function ensureTrailingNewline(value) {
|
|
|
2817
2818
|
return value.endsWith("\n") ? value : `${value}
|
|
2818
2819
|
`;
|
|
2819
2820
|
}
|
|
2821
|
+
function hasNonEmptyText(value) {
|
|
2822
|
+
return typeof value === "string" && value.length > 0;
|
|
2823
|
+
}
|
|
2820
2824
|
function redactDataUrlPayload(value) {
|
|
2821
2825
|
if (!value.toLowerCase().startsWith("data:")) {
|
|
2822
2826
|
return value;
|
|
@@ -2957,6 +2961,63 @@ function appendAgentStreamEventLog(options) {
|
|
|
2957
2961
|
}
|
|
2958
2962
|
}
|
|
2959
2963
|
}
|
|
2964
|
+
function createAgentStreamEventLogger(options) {
|
|
2965
|
+
const thoughtDeltaThrottleMs = Math.max(
|
|
2966
|
+
0,
|
|
2967
|
+
options.thoughtDeltaThrottleMs ?? DEFAULT_THOUGHT_DELTA_LOG_THROTTLE_MS
|
|
2968
|
+
);
|
|
2969
|
+
let pendingThoughtDelta = "";
|
|
2970
|
+
let thoughtFlushTimer = null;
|
|
2971
|
+
const cancelThoughtFlushTimer = () => {
|
|
2972
|
+
if (thoughtFlushTimer === null) {
|
|
2973
|
+
return;
|
|
2974
|
+
}
|
|
2975
|
+
clearTimeout(thoughtFlushTimer);
|
|
2976
|
+
thoughtFlushTimer = null;
|
|
2977
|
+
};
|
|
2978
|
+
const flushThoughtDelta = () => {
|
|
2979
|
+
cancelThoughtFlushTimer();
|
|
2980
|
+
if (pendingThoughtDelta.length === 0) {
|
|
2981
|
+
return;
|
|
2982
|
+
}
|
|
2983
|
+
options.append(`thought_delta: ${pendingThoughtDelta}`);
|
|
2984
|
+
pendingThoughtDelta = "";
|
|
2985
|
+
};
|
|
2986
|
+
const scheduleThoughtFlush = () => {
|
|
2987
|
+
if (thoughtFlushTimer !== null || thoughtDeltaThrottleMs === 0) {
|
|
2988
|
+
return;
|
|
2989
|
+
}
|
|
2990
|
+
thoughtFlushTimer = setTimeout(() => {
|
|
2991
|
+
thoughtFlushTimer = null;
|
|
2992
|
+
flushThoughtDelta();
|
|
2993
|
+
}, thoughtDeltaThrottleMs);
|
|
2994
|
+
thoughtFlushTimer.unref?.();
|
|
2995
|
+
};
|
|
2996
|
+
return {
|
|
2997
|
+
appendEvent: (event) => {
|
|
2998
|
+
if (event.type === "delta" && event.channel === "thought") {
|
|
2999
|
+
if (event.text.length === 0) {
|
|
3000
|
+
return;
|
|
3001
|
+
}
|
|
3002
|
+
pendingThoughtDelta += event.text;
|
|
3003
|
+
if (thoughtDeltaThrottleMs === 0) {
|
|
3004
|
+
flushThoughtDelta();
|
|
3005
|
+
return;
|
|
3006
|
+
}
|
|
3007
|
+
scheduleThoughtFlush();
|
|
3008
|
+
return;
|
|
3009
|
+
}
|
|
3010
|
+
flushThoughtDelta();
|
|
3011
|
+
appendAgentStreamEventLog({
|
|
3012
|
+
event,
|
|
3013
|
+
append: options.append
|
|
3014
|
+
});
|
|
3015
|
+
},
|
|
3016
|
+
flush: () => {
|
|
3017
|
+
flushThoughtDelta();
|
|
3018
|
+
}
|
|
3019
|
+
};
|
|
3020
|
+
}
|
|
2960
3021
|
var AgentLoggingSessionImpl = class {
|
|
2961
3022
|
workspaceDir;
|
|
2962
3023
|
logsRootDir;
|
|
@@ -3008,6 +3069,25 @@ var AgentLoggingSessionImpl = class {
|
|
|
3008
3069
|
}
|
|
3009
3070
|
this.enqueueLineWrite(timestamped);
|
|
3010
3071
|
}
|
|
3072
|
+
async writeAttachments(baseDir, attachments) {
|
|
3073
|
+
const usedNames = /* @__PURE__ */ new Set();
|
|
3074
|
+
for (const attachment of attachments ?? []) {
|
|
3075
|
+
let filename = normalisePathSegment(attachment.filename);
|
|
3076
|
+
if (!filename.includes(".")) {
|
|
3077
|
+
filename = `${filename}.bin`;
|
|
3078
|
+
}
|
|
3079
|
+
const ext = import_node_path3.default.extname(filename);
|
|
3080
|
+
const base = ext.length > 0 ? filename.slice(0, -ext.length) : filename;
|
|
3081
|
+
let candidate = filename;
|
|
3082
|
+
let duplicateIndex = 2;
|
|
3083
|
+
while (usedNames.has(candidate)) {
|
|
3084
|
+
candidate = `${base}-${duplicateIndex.toString()}${ext}`;
|
|
3085
|
+
duplicateIndex += 1;
|
|
3086
|
+
}
|
|
3087
|
+
usedNames.add(candidate);
|
|
3088
|
+
await (0, import_promises.writeFile)(import_node_path3.default.join(baseDir, candidate), attachment.bytes);
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3011
3091
|
startLlmCall(input) {
|
|
3012
3092
|
const callNumber = this.callCounter + 1;
|
|
3013
3093
|
this.callCounter = callNumber;
|
|
@@ -3020,6 +3100,9 @@ var AgentLoggingSessionImpl = class {
|
|
|
3020
3100
|
);
|
|
3021
3101
|
const responsePath = import_node_path3.default.join(baseDir, "response.txt");
|
|
3022
3102
|
const thoughtsPath = import_node_path3.default.join(baseDir, "thoughts.txt");
|
|
3103
|
+
const toolCallPath = import_node_path3.default.join(baseDir, "tool_call.txt");
|
|
3104
|
+
const toolCallResponsePath = import_node_path3.default.join(baseDir, "tool_call_response.txt");
|
|
3105
|
+
const errorPath = import_node_path3.default.join(baseDir, "error.txt");
|
|
3023
3106
|
const responseMetadataPath = import_node_path3.default.join(baseDir, "response.metadata.json");
|
|
3024
3107
|
let chain = this.ensureReady.then(async () => {
|
|
3025
3108
|
await (0, import_promises.mkdir)(baseDir, { recursive: true });
|
|
@@ -3041,22 +3124,13 @@ var AgentLoggingSessionImpl = class {
|
|
|
3041
3124
|
`,
|
|
3042
3125
|
"utf8"
|
|
3043
3126
|
);
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
const base = ext.length > 0 ? filename.slice(0, -ext.length) : filename;
|
|
3052
|
-
let candidate = filename;
|
|
3053
|
-
let duplicateIndex = 2;
|
|
3054
|
-
while (usedNames.has(candidate)) {
|
|
3055
|
-
candidate = `${base}-${duplicateIndex.toString()}${ext}`;
|
|
3056
|
-
duplicateIndex += 1;
|
|
3057
|
-
}
|
|
3058
|
-
usedNames.add(candidate);
|
|
3059
|
-
await (0, import_promises.writeFile)(import_node_path3.default.join(baseDir, candidate), attachment.bytes);
|
|
3127
|
+
await this.writeAttachments(baseDir, input.attachments);
|
|
3128
|
+
if (hasNonEmptyText(input.toolCallResponseText)) {
|
|
3129
|
+
await (0, import_promises.writeFile)(
|
|
3130
|
+
toolCallResponsePath,
|
|
3131
|
+
ensureTrailingNewline(input.toolCallResponseText),
|
|
3132
|
+
"utf8"
|
|
3133
|
+
);
|
|
3060
3134
|
}
|
|
3061
3135
|
}).catch(() => void 0);
|
|
3062
3136
|
this.track(chain);
|
|
@@ -3084,18 +3158,25 @@ var AgentLoggingSessionImpl = class {
|
|
|
3084
3158
|
await (0, import_promises.appendFile)(responsePath, text, "utf8");
|
|
3085
3159
|
});
|
|
3086
3160
|
},
|
|
3087
|
-
complete: (
|
|
3161
|
+
complete: (options) => {
|
|
3088
3162
|
if (closed) {
|
|
3089
3163
|
return;
|
|
3090
3164
|
}
|
|
3091
3165
|
closed = true;
|
|
3092
3166
|
enqueue(async () => {
|
|
3167
|
+
if (hasNonEmptyText(options?.responseText)) {
|
|
3168
|
+
await (0, import_promises.writeFile)(responsePath, options.responseText, "utf8");
|
|
3169
|
+
}
|
|
3170
|
+
if (hasNonEmptyText(options?.toolCallText)) {
|
|
3171
|
+
await (0, import_promises.writeFile)(toolCallPath, ensureTrailingNewline(options.toolCallText), "utf8");
|
|
3172
|
+
}
|
|
3173
|
+
await this.writeAttachments(baseDir, options?.attachments);
|
|
3093
3174
|
const payload = {
|
|
3094
3175
|
capturedAt: toIsoNow(),
|
|
3095
3176
|
status: "completed"
|
|
3096
3177
|
};
|
|
3097
|
-
if (metadata) {
|
|
3098
|
-
const sanitised = sanitiseLogValue(metadata);
|
|
3178
|
+
if (options?.metadata) {
|
|
3179
|
+
const sanitised = sanitiseLogValue(options.metadata);
|
|
3099
3180
|
if (sanitised && typeof sanitised === "object" && !Array.isArray(sanitised)) {
|
|
3100
3181
|
Object.assign(payload, sanitised);
|
|
3101
3182
|
} else if (sanitised !== void 0) {
|
|
@@ -3106,19 +3187,27 @@ var AgentLoggingSessionImpl = class {
|
|
|
3106
3187
|
`, "utf8");
|
|
3107
3188
|
});
|
|
3108
3189
|
},
|
|
3109
|
-
fail: (error,
|
|
3190
|
+
fail: (error, options) => {
|
|
3110
3191
|
if (closed) {
|
|
3111
3192
|
return;
|
|
3112
3193
|
}
|
|
3113
3194
|
closed = true;
|
|
3114
3195
|
enqueue(async () => {
|
|
3196
|
+
if (hasNonEmptyText(options?.responseText)) {
|
|
3197
|
+
await (0, import_promises.writeFile)(responsePath, options.responseText, "utf8");
|
|
3198
|
+
}
|
|
3199
|
+
if (hasNonEmptyText(options?.toolCallText)) {
|
|
3200
|
+
await (0, import_promises.writeFile)(toolCallPath, ensureTrailingNewline(options.toolCallText), "utf8");
|
|
3201
|
+
}
|
|
3202
|
+
await this.writeAttachments(baseDir, options?.attachments);
|
|
3203
|
+
await (0, import_promises.writeFile)(errorPath, ensureTrailingNewline(toErrorMessage(error)), "utf8");
|
|
3115
3204
|
const payload = {
|
|
3116
3205
|
capturedAt: toIsoNow(),
|
|
3117
3206
|
status: "failed",
|
|
3118
3207
|
error: toErrorMessage(error)
|
|
3119
3208
|
};
|
|
3120
|
-
if (metadata) {
|
|
3121
|
-
const sanitised = sanitiseLogValue(metadata);
|
|
3209
|
+
if (options?.metadata) {
|
|
3210
|
+
const sanitised = sanitiseLogValue(options.metadata);
|
|
3122
3211
|
if (sanitised && typeof sanitised === "object" && !Array.isArray(sanitised)) {
|
|
3123
3212
|
Object.assign(payload, sanitised);
|
|
3124
3213
|
} else if (sanitised !== void 0) {
|
|
@@ -4961,7 +5050,10 @@ function resolveAttachmentExtension(mimeType) {
|
|
|
4961
5050
|
}
|
|
4962
5051
|
}
|
|
4963
5052
|
}
|
|
4964
|
-
function
|
|
5053
|
+
function buildLoggedAttachmentFilename(prefix, index, mimeType) {
|
|
5054
|
+
return `${prefix}-${index.toString()}.${resolveAttachmentExtension(mimeType)}`;
|
|
5055
|
+
}
|
|
5056
|
+
function decodeDataUrlAttachment(value, options) {
|
|
4965
5057
|
const trimmed = value.trim();
|
|
4966
5058
|
if (!trimmed.toLowerCase().startsWith("data:")) {
|
|
4967
5059
|
return null;
|
|
@@ -4977,7 +5069,7 @@ function decodeDataUrlAttachment(value, basename) {
|
|
|
4977
5069
|
try {
|
|
4978
5070
|
const bytes = isBase64 ? import_node_buffer3.Buffer.from(payload, "base64") : import_node_buffer3.Buffer.from(decodeURIComponent(payload), "utf8");
|
|
4979
5071
|
return {
|
|
4980
|
-
filename:
|
|
5072
|
+
filename: buildLoggedAttachmentFilename(options.prefix, options.index, mimeType),
|
|
4981
5073
|
bytes
|
|
4982
5074
|
};
|
|
4983
5075
|
} catch {
|
|
@@ -4986,10 +5078,10 @@ function decodeDataUrlAttachment(value, basename) {
|
|
|
4986
5078
|
}
|
|
4987
5079
|
function collectPayloadAttachments(value, options) {
|
|
4988
5080
|
if (typeof value === "string") {
|
|
4989
|
-
const attachment = decodeDataUrlAttachment(
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
);
|
|
5081
|
+
const attachment = decodeDataUrlAttachment(value, {
|
|
5082
|
+
prefix: options.prefix,
|
|
5083
|
+
index: options.counter
|
|
5084
|
+
});
|
|
4993
5085
|
if (attachment) {
|
|
4994
5086
|
options.attachments.push(attachment);
|
|
4995
5087
|
options.counter += 1;
|
|
@@ -5014,7 +5106,7 @@ function collectPayloadAttachments(value, options) {
|
|
|
5014
5106
|
if (typeof record.data === "string" && mimeType) {
|
|
5015
5107
|
try {
|
|
5016
5108
|
options.attachments.push({
|
|
5017
|
-
filename:
|
|
5109
|
+
filename: buildLoggedAttachmentFilename(options.prefix, options.counter, mimeType),
|
|
5018
5110
|
bytes: decodeInlineDataBuffer(record.data)
|
|
5019
5111
|
});
|
|
5020
5112
|
options.counter += 1;
|
|
@@ -5034,27 +5126,166 @@ function serialiseRequestPayloadForLogging(value) {
|
|
|
5034
5126
|
`;
|
|
5035
5127
|
}
|
|
5036
5128
|
}
|
|
5129
|
+
function serialiseLogArtifactText(value) {
|
|
5130
|
+
if (value === null || value === void 0) {
|
|
5131
|
+
return void 0;
|
|
5132
|
+
}
|
|
5133
|
+
if (typeof value === "string") {
|
|
5134
|
+
if (value.length === 0) {
|
|
5135
|
+
return void 0;
|
|
5136
|
+
}
|
|
5137
|
+
return value.endsWith("\n") ? value : `${value}
|
|
5138
|
+
`;
|
|
5139
|
+
}
|
|
5140
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
5141
|
+
return void 0;
|
|
5142
|
+
}
|
|
5143
|
+
if (isPlainRecord(value) && Object.keys(value).length === 0) {
|
|
5144
|
+
return void 0;
|
|
5145
|
+
}
|
|
5146
|
+
try {
|
|
5147
|
+
return `${JSON.stringify(sanitiseLogValue(value), null, 2)}
|
|
5148
|
+
`;
|
|
5149
|
+
} catch {
|
|
5150
|
+
return `${String(value)}
|
|
5151
|
+
`;
|
|
5152
|
+
}
|
|
5153
|
+
}
|
|
5154
|
+
function collectLoggedAttachmentsFromLlmParts(parts, prefix) {
|
|
5155
|
+
const attachments = [];
|
|
5156
|
+
let index = 1;
|
|
5157
|
+
for (const part of parts) {
|
|
5158
|
+
if (part.type !== "inlineData") {
|
|
5159
|
+
continue;
|
|
5160
|
+
}
|
|
5161
|
+
attachments.push({
|
|
5162
|
+
filename: buildLoggedAttachmentFilename(prefix, index, part.mimeType),
|
|
5163
|
+
bytes: decodeInlineDataBuffer(part.data)
|
|
5164
|
+
});
|
|
5165
|
+
index += 1;
|
|
5166
|
+
}
|
|
5167
|
+
return attachments;
|
|
5168
|
+
}
|
|
5169
|
+
function collectLoggedAttachmentsFromGeminiParts(parts, prefix) {
|
|
5170
|
+
return collectLoggedAttachmentsFromLlmParts(convertGooglePartsToLlmParts(parts), prefix);
|
|
5171
|
+
}
|
|
5172
|
+
function extractToolCallResponseTextFromOpenAiInput(input) {
|
|
5173
|
+
if (!Array.isArray(input)) {
|
|
5174
|
+
return void 0;
|
|
5175
|
+
}
|
|
5176
|
+
const responses = input.filter((item) => isPlainRecord(item)).flatMap((item) => {
|
|
5177
|
+
const type = typeof item.type === "string" ? item.type : "";
|
|
5178
|
+
if (type !== "function_call_output" && type !== "custom_tool_call_output") {
|
|
5179
|
+
return [];
|
|
5180
|
+
}
|
|
5181
|
+
return [
|
|
5182
|
+
{
|
|
5183
|
+
type,
|
|
5184
|
+
callId: typeof item.call_id === "string" ? item.call_id : void 0,
|
|
5185
|
+
output: "output" in item ? sanitiseLogValue(item.output) : void 0
|
|
5186
|
+
}
|
|
5187
|
+
];
|
|
5188
|
+
});
|
|
5189
|
+
return serialiseLogArtifactText(responses);
|
|
5190
|
+
}
|
|
5191
|
+
function extractToolCallResponseTextFromFireworksMessages(messages) {
|
|
5192
|
+
if (!Array.isArray(messages)) {
|
|
5193
|
+
return void 0;
|
|
5194
|
+
}
|
|
5195
|
+
const responses = messages.filter((message) => isPlainRecord(message)).flatMap((message) => {
|
|
5196
|
+
if (message.role !== "tool") {
|
|
5197
|
+
return [];
|
|
5198
|
+
}
|
|
5199
|
+
return [
|
|
5200
|
+
{
|
|
5201
|
+
toolCallId: typeof message.tool_call_id === "string" ? message.tool_call_id : void 0,
|
|
5202
|
+
content: sanitiseLogValue(message.content)
|
|
5203
|
+
}
|
|
5204
|
+
];
|
|
5205
|
+
});
|
|
5206
|
+
return serialiseLogArtifactText(responses);
|
|
5207
|
+
}
|
|
5208
|
+
function extractToolCallResponseTextFromGeminiContents(contents) {
|
|
5209
|
+
if (!Array.isArray(contents)) {
|
|
5210
|
+
return void 0;
|
|
5211
|
+
}
|
|
5212
|
+
const responses = [];
|
|
5213
|
+
for (const content of contents) {
|
|
5214
|
+
if (!content || typeof content !== "object") {
|
|
5215
|
+
continue;
|
|
5216
|
+
}
|
|
5217
|
+
const parts = content.parts;
|
|
5218
|
+
if (!Array.isArray(parts)) {
|
|
5219
|
+
continue;
|
|
5220
|
+
}
|
|
5221
|
+
for (const part of parts) {
|
|
5222
|
+
if (!part || typeof part !== "object") {
|
|
5223
|
+
continue;
|
|
5224
|
+
}
|
|
5225
|
+
const functionResponse = part.functionResponse;
|
|
5226
|
+
if (functionResponse) {
|
|
5227
|
+
responses.push(sanitiseLogValue(functionResponse));
|
|
5228
|
+
}
|
|
5229
|
+
}
|
|
5230
|
+
}
|
|
5231
|
+
return serialiseLogArtifactText(responses);
|
|
5232
|
+
}
|
|
5233
|
+
function serialiseOpenAiStyleToolCallsForLogging(calls) {
|
|
5234
|
+
return serialiseLogArtifactText(
|
|
5235
|
+
calls.map((call) => {
|
|
5236
|
+
if (call.kind === "custom") {
|
|
5237
|
+
return {
|
|
5238
|
+
kind: call.kind,
|
|
5239
|
+
name: call.name,
|
|
5240
|
+
callId: call.callId,
|
|
5241
|
+
itemId: call.itemId,
|
|
5242
|
+
input: call.input
|
|
5243
|
+
};
|
|
5244
|
+
}
|
|
5245
|
+
const { value, error } = parseOpenAiToolArguments(call.arguments);
|
|
5246
|
+
return {
|
|
5247
|
+
kind: call.kind,
|
|
5248
|
+
name: call.name,
|
|
5249
|
+
callId: call.callId,
|
|
5250
|
+
itemId: call.itemId,
|
|
5251
|
+
arguments: value,
|
|
5252
|
+
...error ? { parseError: error, rawArguments: call.arguments } : {}
|
|
5253
|
+
};
|
|
5254
|
+
})
|
|
5255
|
+
);
|
|
5256
|
+
}
|
|
5257
|
+
function serialiseGeminiToolCallsForLogging(calls) {
|
|
5258
|
+
return serialiseLogArtifactText(
|
|
5259
|
+
calls.map((call) => ({
|
|
5260
|
+
name: call.name ?? "unknown",
|
|
5261
|
+
callId: typeof call.id === "string" ? call.id : void 0,
|
|
5262
|
+
arguments: sanitiseLogValue(call.args ?? {})
|
|
5263
|
+
}))
|
|
5264
|
+
);
|
|
5265
|
+
}
|
|
5037
5266
|
function startLlmCallLoggerFromContents(options) {
|
|
5038
5267
|
const session = getCurrentAgentLoggingSession();
|
|
5039
5268
|
if (!session) {
|
|
5040
5269
|
return void 0;
|
|
5041
5270
|
}
|
|
5042
5271
|
const attachments = [];
|
|
5272
|
+
let attachmentIndex = 1;
|
|
5043
5273
|
const sections = [];
|
|
5044
5274
|
for (const [messageIndex, message] of options.contents.entries()) {
|
|
5045
5275
|
sections.push(`### message_${(messageIndex + 1).toString()} role=${message.role}`);
|
|
5046
|
-
for (const
|
|
5276
|
+
for (const part of message.parts) {
|
|
5047
5277
|
if (part.type === "text") {
|
|
5048
5278
|
const channel = part.thought === true ? "thought" : "response";
|
|
5049
5279
|
sections.push(`[text:${channel}]`);
|
|
5050
5280
|
sections.push(part.text);
|
|
5051
5281
|
continue;
|
|
5052
5282
|
}
|
|
5053
|
-
const filename =
|
|
5283
|
+
const filename = buildLoggedAttachmentFilename("input", attachmentIndex, part.mimeType);
|
|
5054
5284
|
attachments.push({
|
|
5055
5285
|
filename,
|
|
5056
5286
|
bytes: decodeInlineDataBuffer(part.data)
|
|
5057
5287
|
});
|
|
5288
|
+
attachmentIndex += 1;
|
|
5058
5289
|
sections.push(
|
|
5059
5290
|
`[inlineData] file=${filename} mime=${part.mimeType ?? "application/octet-stream"} bytes=${attachments[attachments.length - 1]?.bytes.byteLength ?? 0}`
|
|
5060
5291
|
);
|
|
@@ -5098,11 +5329,18 @@ function startLlmCallLoggerFromPayload(options) {
|
|
|
5098
5329
|
}
|
|
5099
5330
|
const attachments = [];
|
|
5100
5331
|
collectPayloadAttachments(options.requestPayload, {
|
|
5101
|
-
prefix:
|
|
5332
|
+
prefix: "input",
|
|
5102
5333
|
attachments,
|
|
5103
5334
|
seen: /* @__PURE__ */ new WeakSet(),
|
|
5104
5335
|
counter: 1
|
|
5105
5336
|
});
|
|
5337
|
+
const toolCallResponseText = options.provider === "openai" || options.provider === "chatgpt" ? extractToolCallResponseTextFromOpenAiInput(
|
|
5338
|
+
options.requestPayload.input
|
|
5339
|
+
) : options.provider === "fireworks" ? extractToolCallResponseTextFromFireworksMessages(
|
|
5340
|
+
options.requestPayload.messages
|
|
5341
|
+
) : extractToolCallResponseTextFromGeminiContents(
|
|
5342
|
+
options.requestPayload.contents
|
|
5343
|
+
);
|
|
5106
5344
|
return session.startLlmCall({
|
|
5107
5345
|
provider: options.provider,
|
|
5108
5346
|
modelId: options.modelId,
|
|
@@ -5111,7 +5349,8 @@ function startLlmCallLoggerFromPayload(options) {
|
|
|
5111
5349
|
step: options.step,
|
|
5112
5350
|
...getCurrentToolCallContext() ? { toolContext: getCurrentToolCallContext() } : {}
|
|
5113
5351
|
},
|
|
5114
|
-
attachments
|
|
5352
|
+
attachments,
|
|
5353
|
+
toolCallResponseText
|
|
5115
5354
|
});
|
|
5116
5355
|
}
|
|
5117
5356
|
async function runTextCall(params) {
|
|
@@ -5416,6 +5655,7 @@ async function runTextCall(params) {
|
|
|
5416
5655
|
const mergedParts = mergeConsecutiveTextParts(responseParts);
|
|
5417
5656
|
const content = mergedParts.length > 0 ? { role: responseRole ?? "assistant", parts: mergedParts } : void 0;
|
|
5418
5657
|
const { text, thoughts } = extractTextByChannel(content);
|
|
5658
|
+
const outputAttachments = collectLoggedAttachmentsFromLlmParts(mergedParts, "output");
|
|
5419
5659
|
const costUsd = estimateCallCostUsd({
|
|
5420
5660
|
modelId: modelVersion,
|
|
5421
5661
|
tokens: latestUsage,
|
|
@@ -5426,16 +5666,20 @@ async function runTextCall(params) {
|
|
|
5426
5666
|
queue.push({ type: "usage", usage: latestUsage, costUsd, modelVersion });
|
|
5427
5667
|
}
|
|
5428
5668
|
callLogger?.complete({
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5669
|
+
responseText: text,
|
|
5670
|
+
attachments: outputAttachments,
|
|
5671
|
+
metadata: {
|
|
5672
|
+
provider,
|
|
5673
|
+
model: request.model,
|
|
5674
|
+
modelVersion,
|
|
5675
|
+
blocked,
|
|
5676
|
+
costUsd,
|
|
5677
|
+
usage: latestUsage,
|
|
5678
|
+
grounding: grounding ? sanitiseLogValue(grounding) : void 0,
|
|
5679
|
+
responseChars: text.length,
|
|
5680
|
+
thoughtChars: thoughts.length,
|
|
5681
|
+
responseImages
|
|
5682
|
+
}
|
|
5439
5683
|
});
|
|
5440
5684
|
return {
|
|
5441
5685
|
provider,
|
|
@@ -5450,14 +5694,21 @@ async function runTextCall(params) {
|
|
|
5450
5694
|
grounding
|
|
5451
5695
|
};
|
|
5452
5696
|
} catch (error) {
|
|
5697
|
+
const partialParts = mergeConsecutiveTextParts(responseParts);
|
|
5698
|
+
const partialContent = partialParts.length > 0 ? { role: responseRole ?? "assistant", parts: partialParts } : void 0;
|
|
5699
|
+
const { text: partialText } = extractTextByChannel(partialContent);
|
|
5453
5700
|
callLogger?.fail(error, {
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5701
|
+
responseText: partialText,
|
|
5702
|
+
attachments: collectLoggedAttachmentsFromLlmParts(partialParts, "output"),
|
|
5703
|
+
metadata: {
|
|
5704
|
+
provider,
|
|
5705
|
+
model: request.model,
|
|
5706
|
+
modelVersion,
|
|
5707
|
+
blocked,
|
|
5708
|
+
usage: latestUsage,
|
|
5709
|
+
partialResponseParts: responseParts.length,
|
|
5710
|
+
responseImages
|
|
5711
|
+
}
|
|
5461
5712
|
});
|
|
5462
5713
|
throw error;
|
|
5463
5714
|
}
|
|
@@ -5924,6 +6175,9 @@ async function runToolLoop(request) {
|
|
|
5924
6175
|
let usageTokens;
|
|
5925
6176
|
let thoughtDeltaEmitted = false;
|
|
5926
6177
|
let blocked = false;
|
|
6178
|
+
let responseText = "";
|
|
6179
|
+
let reasoningSummary = "";
|
|
6180
|
+
let stepToolCallText;
|
|
5927
6181
|
const stepRequestPayload = {
|
|
5928
6182
|
model: providerInfo.model,
|
|
5929
6183
|
input,
|
|
@@ -6016,8 +6270,8 @@ async function runToolLoop(request) {
|
|
|
6016
6270
|
throw new Error(message);
|
|
6017
6271
|
}
|
|
6018
6272
|
usageTokens = extractOpenAiUsageTokens(finalResponse.usage);
|
|
6019
|
-
|
|
6020
|
-
|
|
6273
|
+
responseText = extractOpenAiResponseParts(finalResponse).parts.filter((p) => p.type === "text" && p.thought !== true).map((p) => p.text).join("").trim();
|
|
6274
|
+
reasoningSummary = extractOpenAiReasoningSummary(finalResponse).trim();
|
|
6021
6275
|
if (!thoughtDeltaEmitted && reasoningSummary.length > 0) {
|
|
6022
6276
|
stepCallLogger?.appendThoughtDelta(reasoningSummary);
|
|
6023
6277
|
emitEvent({ type: "delta", channel: "thought", text: reasoningSummary });
|
|
@@ -6033,6 +6287,23 @@ async function runToolLoop(request) {
|
|
|
6033
6287
|
emitEvent({ type: "usage", usage: usageTokens, costUsd: stepCostUsd, modelVersion });
|
|
6034
6288
|
}
|
|
6035
6289
|
const responseToolCalls = extractOpenAiToolCalls(finalResponse.output);
|
|
6290
|
+
stepToolCallText = serialiseOpenAiStyleToolCallsForLogging(
|
|
6291
|
+
responseToolCalls.map(
|
|
6292
|
+
(call) => call.kind === "custom" ? {
|
|
6293
|
+
kind: call.kind,
|
|
6294
|
+
name: call.name,
|
|
6295
|
+
input: call.input,
|
|
6296
|
+
callId: call.call_id,
|
|
6297
|
+
itemId: call.id
|
|
6298
|
+
} : {
|
|
6299
|
+
kind: call.kind,
|
|
6300
|
+
name: call.name,
|
|
6301
|
+
arguments: call.arguments,
|
|
6302
|
+
callId: call.call_id,
|
|
6303
|
+
itemId: call.id
|
|
6304
|
+
}
|
|
6305
|
+
)
|
|
6306
|
+
);
|
|
6036
6307
|
const stepToolCalls = [];
|
|
6037
6308
|
if (responseToolCalls.length === 0) {
|
|
6038
6309
|
const steeringInput2 = steeringInternal?.drainPendingContents() ?? [];
|
|
@@ -6060,17 +6331,20 @@ async function runToolLoop(request) {
|
|
|
6060
6331
|
timing: timing2
|
|
6061
6332
|
});
|
|
6062
6333
|
stepCallLogger?.complete({
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6334
|
+
responseText,
|
|
6335
|
+
metadata: {
|
|
6336
|
+
provider: "openai",
|
|
6337
|
+
model: request.model,
|
|
6338
|
+
modelVersion,
|
|
6339
|
+
step: turn,
|
|
6340
|
+
usage: usageTokens,
|
|
6341
|
+
costUsd: stepCostUsd,
|
|
6342
|
+
blocked,
|
|
6343
|
+
responseChars: responseText.length,
|
|
6344
|
+
thoughtChars: reasoningSummary.length,
|
|
6345
|
+
toolCalls: 0,
|
|
6346
|
+
finalStep: steeringItems2.length === 0
|
|
6347
|
+
}
|
|
6074
6348
|
});
|
|
6075
6349
|
if (steeringItems2.length === 0) {
|
|
6076
6350
|
return { text: finalText, thoughts: finalThoughts, steps, totalCostUsd };
|
|
@@ -6193,28 +6467,36 @@ async function runToolLoop(request) {
|
|
|
6193
6467
|
const steeringInput = steeringInternal?.drainPendingContents() ?? [];
|
|
6194
6468
|
const steeringItems = steeringInput.length > 0 ? toOpenAiInput(steeringInput) : [];
|
|
6195
6469
|
stepCallLogger?.complete({
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6470
|
+
responseText,
|
|
6471
|
+
toolCallText: stepToolCallText,
|
|
6472
|
+
metadata: {
|
|
6473
|
+
provider: "openai",
|
|
6474
|
+
model: request.model,
|
|
6475
|
+
modelVersion,
|
|
6476
|
+
step: turn,
|
|
6477
|
+
usage: usageTokens,
|
|
6478
|
+
costUsd: stepCostUsd,
|
|
6479
|
+
blocked,
|
|
6480
|
+
responseChars: responseText.length,
|
|
6481
|
+
thoughtChars: reasoningSummary.length,
|
|
6482
|
+
toolCalls: stepToolCalls.length,
|
|
6483
|
+
finalStep: false
|
|
6484
|
+
}
|
|
6207
6485
|
});
|
|
6208
6486
|
previousResponseId = finalResponse.id;
|
|
6209
6487
|
input = steeringItems.length > 0 ? toolOutputs.concat(steeringItems) : toolOutputs;
|
|
6210
6488
|
} catch (error) {
|
|
6211
6489
|
stepCallLogger?.fail(error, {
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6490
|
+
responseText,
|
|
6491
|
+
toolCallText: stepToolCallText,
|
|
6492
|
+
metadata: {
|
|
6493
|
+
provider: "openai",
|
|
6494
|
+
model: request.model,
|
|
6495
|
+
modelVersion,
|
|
6496
|
+
step: turn,
|
|
6497
|
+
usage: usageTokens,
|
|
6498
|
+
blocked
|
|
6499
|
+
}
|
|
6218
6500
|
});
|
|
6219
6501
|
throw error;
|
|
6220
6502
|
}
|
|
@@ -6240,6 +6522,7 @@ async function runToolLoop(request) {
|
|
|
6240
6522
|
let usageTokens;
|
|
6241
6523
|
let responseText = "";
|
|
6242
6524
|
let reasoningSummaryText = "";
|
|
6525
|
+
let stepToolCallText;
|
|
6243
6526
|
const markFirstModelEvent = () => {
|
|
6244
6527
|
if (firstModelEventAtMs === void 0) {
|
|
6245
6528
|
firstModelEventAtMs = Date.now();
|
|
@@ -6308,6 +6591,23 @@ async function runToolLoop(request) {
|
|
|
6308
6591
|
stepCallLogger?.appendResponseDelta(responseText);
|
|
6309
6592
|
}
|
|
6310
6593
|
const responseToolCalls = response.toolCalls ?? [];
|
|
6594
|
+
stepToolCallText = serialiseOpenAiStyleToolCallsForLogging(
|
|
6595
|
+
responseToolCalls.map(
|
|
6596
|
+
(call) => call.kind === "custom" ? {
|
|
6597
|
+
kind: call.kind,
|
|
6598
|
+
name: call.name,
|
|
6599
|
+
input: call.input,
|
|
6600
|
+
callId: call.callId,
|
|
6601
|
+
itemId: call.id
|
|
6602
|
+
} : {
|
|
6603
|
+
kind: call.kind,
|
|
6604
|
+
name: call.name,
|
|
6605
|
+
arguments: call.arguments,
|
|
6606
|
+
callId: call.callId,
|
|
6607
|
+
itemId: call.id
|
|
6608
|
+
}
|
|
6609
|
+
)
|
|
6610
|
+
);
|
|
6311
6611
|
if (responseToolCalls.length === 0) {
|
|
6312
6612
|
const steeringInput2 = steeringInternal?.drainPendingContents() ?? [];
|
|
6313
6613
|
const steeringItems2 = steeringInput2.length > 0 ? toChatGptInput(steeringInput2).input : [];
|
|
@@ -6333,16 +6633,19 @@ async function runToolLoop(request) {
|
|
|
6333
6633
|
timing: timing2
|
|
6334
6634
|
});
|
|
6335
6635
|
stepCallLogger?.complete({
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6636
|
+
responseText,
|
|
6637
|
+
metadata: {
|
|
6638
|
+
provider: "chatgpt",
|
|
6639
|
+
model: request.model,
|
|
6640
|
+
modelVersion,
|
|
6641
|
+
step: turn,
|
|
6642
|
+
usage: usageTokens,
|
|
6643
|
+
costUsd: stepCostUsd,
|
|
6644
|
+
responseChars: responseText.length,
|
|
6645
|
+
thoughtChars: reasoningSummaryText.length,
|
|
6646
|
+
toolCalls: 0,
|
|
6647
|
+
finalStep: steeringItems2.length === 0
|
|
6648
|
+
}
|
|
6346
6649
|
});
|
|
6347
6650
|
if (steeringItems2.length === 0) {
|
|
6348
6651
|
return { text: finalText, thoughts: finalThoughts, steps, totalCostUsd };
|
|
@@ -6475,25 +6778,33 @@ async function runToolLoop(request) {
|
|
|
6475
6778
|
const steeringInput = steeringInternal?.drainPendingContents() ?? [];
|
|
6476
6779
|
const steeringItems = steeringInput.length > 0 ? toChatGptInput(steeringInput).input : [];
|
|
6477
6780
|
stepCallLogger?.complete({
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6781
|
+
responseText,
|
|
6782
|
+
toolCallText: stepToolCallText,
|
|
6783
|
+
metadata: {
|
|
6784
|
+
provider: "chatgpt",
|
|
6785
|
+
model: request.model,
|
|
6786
|
+
modelVersion,
|
|
6787
|
+
step: turn,
|
|
6788
|
+
usage: usageTokens,
|
|
6789
|
+
costUsd: stepCostUsd,
|
|
6790
|
+
responseChars: responseText.length,
|
|
6791
|
+
thoughtChars: reasoningSummaryText.length,
|
|
6792
|
+
toolCalls: toolCalls.length,
|
|
6793
|
+
finalStep: false
|
|
6794
|
+
}
|
|
6488
6795
|
});
|
|
6489
6796
|
input = steeringItems.length > 0 ? input.concat(toolOutputs, steeringItems) : input.concat(toolOutputs);
|
|
6490
6797
|
} catch (error) {
|
|
6491
6798
|
stepCallLogger?.fail(error, {
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6799
|
+
responseText,
|
|
6800
|
+
toolCallText: stepToolCallText,
|
|
6801
|
+
metadata: {
|
|
6802
|
+
provider: "chatgpt",
|
|
6803
|
+
model: request.model,
|
|
6804
|
+
modelVersion,
|
|
6805
|
+
step: turn,
|
|
6806
|
+
usage: usageTokens
|
|
6807
|
+
}
|
|
6497
6808
|
});
|
|
6498
6809
|
throw error;
|
|
6499
6810
|
}
|
|
@@ -6516,6 +6827,7 @@ async function runToolLoop(request) {
|
|
|
6516
6827
|
let usageTokens;
|
|
6517
6828
|
let responseText = "";
|
|
6518
6829
|
let blocked = false;
|
|
6830
|
+
let stepToolCallText;
|
|
6519
6831
|
const stepRequestPayload = {
|
|
6520
6832
|
model: providerInfo.model,
|
|
6521
6833
|
messages,
|
|
@@ -6580,6 +6892,14 @@ async function runToolLoop(request) {
|
|
|
6580
6892
|
});
|
|
6581
6893
|
}
|
|
6582
6894
|
const responseToolCalls = extractFireworksToolCalls(message);
|
|
6895
|
+
stepToolCallText = serialiseOpenAiStyleToolCallsForLogging(
|
|
6896
|
+
responseToolCalls.map((call) => ({
|
|
6897
|
+
kind: "function",
|
|
6898
|
+
name: call.name,
|
|
6899
|
+
arguments: call.arguments,
|
|
6900
|
+
callId: call.id
|
|
6901
|
+
}))
|
|
6902
|
+
);
|
|
6583
6903
|
if (responseToolCalls.length === 0) {
|
|
6584
6904
|
const steeringInput2 = steeringInternal?.drainPendingContents() ?? [];
|
|
6585
6905
|
const steeringMessages = steeringInput2.length > 0 ? toFireworksMessages(steeringInput2) : [];
|
|
@@ -6605,17 +6925,20 @@ async function runToolLoop(request) {
|
|
|
6605
6925
|
timing: timing2
|
|
6606
6926
|
});
|
|
6607
6927
|
stepCallLogger?.complete({
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6928
|
+
responseText,
|
|
6929
|
+
metadata: {
|
|
6930
|
+
provider: "fireworks",
|
|
6931
|
+
model: request.model,
|
|
6932
|
+
modelVersion,
|
|
6933
|
+
step: turn,
|
|
6934
|
+
usage: usageTokens,
|
|
6935
|
+
costUsd: stepCostUsd,
|
|
6936
|
+
blocked,
|
|
6937
|
+
responseChars: responseText.length,
|
|
6938
|
+
thoughtChars: 0,
|
|
6939
|
+
toolCalls: 0,
|
|
6940
|
+
finalStep: steeringMessages.length === 0
|
|
6941
|
+
}
|
|
6619
6942
|
});
|
|
6620
6943
|
if (steeringMessages.length === 0) {
|
|
6621
6944
|
return { text: finalText, thoughts: finalThoughts, steps, totalCostUsd };
|
|
@@ -6727,17 +7050,21 @@ async function runToolLoop(request) {
|
|
|
6727
7050
|
timing
|
|
6728
7051
|
});
|
|
6729
7052
|
stepCallLogger?.complete({
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
7053
|
+
responseText,
|
|
7054
|
+
toolCallText: stepToolCallText,
|
|
7055
|
+
metadata: {
|
|
7056
|
+
provider: "fireworks",
|
|
7057
|
+
model: request.model,
|
|
7058
|
+
modelVersion,
|
|
7059
|
+
step: turn,
|
|
7060
|
+
usage: usageTokens,
|
|
7061
|
+
costUsd: stepCostUsd,
|
|
7062
|
+
blocked,
|
|
7063
|
+
responseChars: responseText.length,
|
|
7064
|
+
thoughtChars: 0,
|
|
7065
|
+
toolCalls: stepToolCalls.length,
|
|
7066
|
+
finalStep: false
|
|
7067
|
+
}
|
|
6741
7068
|
});
|
|
6742
7069
|
messages.push({
|
|
6743
7070
|
role: "assistant",
|
|
@@ -6751,12 +7078,16 @@ async function runToolLoop(request) {
|
|
|
6751
7078
|
}
|
|
6752
7079
|
} catch (error) {
|
|
6753
7080
|
stepCallLogger?.fail(error, {
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
7081
|
+
responseText,
|
|
7082
|
+
toolCallText: stepToolCallText,
|
|
7083
|
+
metadata: {
|
|
7084
|
+
provider: "fireworks",
|
|
7085
|
+
model: request.model,
|
|
7086
|
+
modelVersion,
|
|
7087
|
+
step: turn,
|
|
7088
|
+
usage: usageTokens,
|
|
7089
|
+
blocked
|
|
7090
|
+
}
|
|
6760
7091
|
});
|
|
6761
7092
|
throw error;
|
|
6762
7093
|
}
|
|
@@ -6776,6 +7107,7 @@ async function runToolLoop(request) {
|
|
|
6776
7107
|
let usageTokens;
|
|
6777
7108
|
let responseText = "";
|
|
6778
7109
|
let thoughtsText = "";
|
|
7110
|
+
let stepToolCallText;
|
|
6779
7111
|
const markFirstModelEvent = () => {
|
|
6780
7112
|
if (firstModelEventAtMs === void 0) {
|
|
6781
7113
|
firstModelEventAtMs = Date.now();
|
|
@@ -6896,12 +7228,17 @@ async function runToolLoop(request) {
|
|
|
6896
7228
|
modelVersion = response.modelVersion ?? request.model;
|
|
6897
7229
|
responseText = response.responseText.trim();
|
|
6898
7230
|
thoughtsText = response.thoughtsText.trim();
|
|
7231
|
+
const responseOutputAttachments = collectLoggedAttachmentsFromGeminiParts(
|
|
7232
|
+
response.modelParts,
|
|
7233
|
+
"output"
|
|
7234
|
+
);
|
|
6899
7235
|
const stepCostUsd = estimateCallCostUsd({
|
|
6900
7236
|
modelId: modelVersion,
|
|
6901
7237
|
tokens: usageTokens,
|
|
6902
7238
|
responseImages: 0
|
|
6903
7239
|
});
|
|
6904
7240
|
totalCostUsd += stepCostUsd;
|
|
7241
|
+
stepToolCallText = serialiseGeminiToolCallsForLogging(response.functionCalls);
|
|
6905
7242
|
if (response.functionCalls.length === 0) {
|
|
6906
7243
|
const steeringInput2 = steeringInternal?.drainPendingContents() ?? [];
|
|
6907
7244
|
finalText = responseText;
|
|
@@ -6927,16 +7264,20 @@ async function runToolLoop(request) {
|
|
|
6927
7264
|
timing: timing2
|
|
6928
7265
|
});
|
|
6929
7266
|
stepCallLogger?.complete({
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
7267
|
+
responseText,
|
|
7268
|
+
attachments: responseOutputAttachments,
|
|
7269
|
+
metadata: {
|
|
7270
|
+
provider: "gemini",
|
|
7271
|
+
model: request.model,
|
|
7272
|
+
modelVersion,
|
|
7273
|
+
step: turn,
|
|
7274
|
+
usage: usageTokens,
|
|
7275
|
+
costUsd: stepCostUsd,
|
|
7276
|
+
responseChars: responseText.length,
|
|
7277
|
+
thoughtChars: thoughtsText.length,
|
|
7278
|
+
toolCalls: 0,
|
|
7279
|
+
finalStep: steeringInput2.length === 0
|
|
7280
|
+
}
|
|
6940
7281
|
});
|
|
6941
7282
|
if (steeringInput2.length === 0) {
|
|
6942
7283
|
return { text: finalText, thoughts: finalThoughts, steps, totalCostUsd };
|
|
@@ -7063,16 +7404,21 @@ async function runToolLoop(request) {
|
|
|
7063
7404
|
timing
|
|
7064
7405
|
});
|
|
7065
7406
|
stepCallLogger?.complete({
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
|
|
7407
|
+
responseText,
|
|
7408
|
+
attachments: responseOutputAttachments,
|
|
7409
|
+
toolCallText: stepToolCallText,
|
|
7410
|
+
metadata: {
|
|
7411
|
+
provider: "gemini",
|
|
7412
|
+
model: request.model,
|
|
7413
|
+
modelVersion,
|
|
7414
|
+
step: turn,
|
|
7415
|
+
usage: usageTokens,
|
|
7416
|
+
costUsd: stepCostUsd,
|
|
7417
|
+
responseChars: responseText.length,
|
|
7418
|
+
thoughtChars: thoughtsText.length,
|
|
7419
|
+
toolCalls: toolCalls.length,
|
|
7420
|
+
finalStep: false
|
|
7421
|
+
}
|
|
7076
7422
|
});
|
|
7077
7423
|
geminiContents.push({ role: "user", parts: responseParts });
|
|
7078
7424
|
const steeringInput = steeringInternal?.drainPendingContents() ?? [];
|
|
@@ -7081,13 +7427,17 @@ async function runToolLoop(request) {
|
|
|
7081
7427
|
}
|
|
7082
7428
|
} catch (error) {
|
|
7083
7429
|
stepCallLogger?.fail(error, {
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
|
|
7430
|
+
responseText,
|
|
7431
|
+
toolCallText: stepToolCallText,
|
|
7432
|
+
metadata: {
|
|
7433
|
+
provider: "gemini",
|
|
7434
|
+
model: request.model,
|
|
7435
|
+
modelVersion,
|
|
7436
|
+
step: turn,
|
|
7437
|
+
usage: usageTokens,
|
|
7438
|
+
responseChars: responseText.length,
|
|
7439
|
+
thoughtChars: thoughtsText.length
|
|
7440
|
+
}
|
|
7091
7441
|
});
|
|
7092
7442
|
throw error;
|
|
7093
7443
|
}
|
|
@@ -10136,19 +10486,17 @@ async function runAgentLoopInternal(request, context) {
|
|
|
10136
10486
|
);
|
|
10137
10487
|
const sourceOnEvent = toolLoopRequestWithSteering.onEvent;
|
|
10138
10488
|
const includeLlmStreamEvents = telemetrySession?.includeLlmStreamEvents === true;
|
|
10489
|
+
const streamEventLogger = loggingSession ? createAgentStreamEventLogger({
|
|
10490
|
+
append: (line) => {
|
|
10491
|
+
loggingSession.logLine(`[agent:${runId}] ${line}`);
|
|
10492
|
+
}
|
|
10493
|
+
}) : void 0;
|
|
10139
10494
|
const wrappedOnEvent = sourceOnEvent || includeLlmStreamEvents ? (event) => {
|
|
10140
10495
|
sourceOnEvent?.(event);
|
|
10141
10496
|
if (includeLlmStreamEvents) {
|
|
10142
10497
|
emitTelemetry({ type: "agent.run.stream", event });
|
|
10143
10498
|
}
|
|
10144
|
-
|
|
10145
|
-
appendAgentStreamEventLog({
|
|
10146
|
-
event,
|
|
10147
|
-
append: (line) => {
|
|
10148
|
-
loggingSession.logLine(`[agent:${runId}] ${line}`);
|
|
10149
|
-
}
|
|
10150
|
-
});
|
|
10151
|
-
}
|
|
10499
|
+
streamEventLogger?.appendEvent(event);
|
|
10152
10500
|
} : void 0;
|
|
10153
10501
|
try {
|
|
10154
10502
|
const result = await runToolLoop({
|
|
@@ -10157,6 +10505,7 @@ async function runAgentLoopInternal(request, context) {
|
|
|
10157
10505
|
...wrappedOnEvent ? { onEvent: wrappedOnEvent } : {},
|
|
10158
10506
|
tools: mergedTools
|
|
10159
10507
|
});
|
|
10508
|
+
streamEventLogger?.flush();
|
|
10160
10509
|
emitTelemetry({
|
|
10161
10510
|
type: "agent.run.completed",
|
|
10162
10511
|
success: true,
|
|
@@ -10189,6 +10538,7 @@ async function runAgentLoopInternal(request, context) {
|
|
|
10189
10538
|
}
|
|
10190
10539
|
return result;
|
|
10191
10540
|
} catch (error) {
|
|
10541
|
+
streamEventLogger?.flush();
|
|
10192
10542
|
emitTelemetry({
|
|
10193
10543
|
type: "agent.run.completed",
|
|
10194
10544
|
success: false,
|
|
@@ -10205,6 +10555,7 @@ async function runAgentLoopInternal(request, context) {
|
|
|
10205
10555
|
);
|
|
10206
10556
|
throw error;
|
|
10207
10557
|
} finally {
|
|
10558
|
+
streamEventLogger?.flush();
|
|
10208
10559
|
await subagentController?.closeAll();
|
|
10209
10560
|
}
|
|
10210
10561
|
}
|