@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.js
CHANGED
|
@@ -2682,6 +2682,7 @@ import { AsyncLocalStorage } from "async_hooks";
|
|
|
2682
2682
|
import { Buffer as Buffer3 } from "buffer";
|
|
2683
2683
|
import { appendFile, mkdir, writeFile } from "fs/promises";
|
|
2684
2684
|
import path3 from "path";
|
|
2685
|
+
var DEFAULT_THOUGHT_DELTA_LOG_THROTTLE_MS = 4e3;
|
|
2685
2686
|
function toIsoNow() {
|
|
2686
2687
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2687
2688
|
}
|
|
@@ -2705,6 +2706,9 @@ function ensureTrailingNewline(value) {
|
|
|
2705
2706
|
return value.endsWith("\n") ? value : `${value}
|
|
2706
2707
|
`;
|
|
2707
2708
|
}
|
|
2709
|
+
function hasNonEmptyText(value) {
|
|
2710
|
+
return typeof value === "string" && value.length > 0;
|
|
2711
|
+
}
|
|
2708
2712
|
function redactDataUrlPayload(value) {
|
|
2709
2713
|
if (!value.toLowerCase().startsWith("data:")) {
|
|
2710
2714
|
return value;
|
|
@@ -2845,6 +2849,63 @@ function appendAgentStreamEventLog(options) {
|
|
|
2845
2849
|
}
|
|
2846
2850
|
}
|
|
2847
2851
|
}
|
|
2852
|
+
function createAgentStreamEventLogger(options) {
|
|
2853
|
+
const thoughtDeltaThrottleMs = Math.max(
|
|
2854
|
+
0,
|
|
2855
|
+
options.thoughtDeltaThrottleMs ?? DEFAULT_THOUGHT_DELTA_LOG_THROTTLE_MS
|
|
2856
|
+
);
|
|
2857
|
+
let pendingThoughtDelta = "";
|
|
2858
|
+
let thoughtFlushTimer = null;
|
|
2859
|
+
const cancelThoughtFlushTimer = () => {
|
|
2860
|
+
if (thoughtFlushTimer === null) {
|
|
2861
|
+
return;
|
|
2862
|
+
}
|
|
2863
|
+
clearTimeout(thoughtFlushTimer);
|
|
2864
|
+
thoughtFlushTimer = null;
|
|
2865
|
+
};
|
|
2866
|
+
const flushThoughtDelta = () => {
|
|
2867
|
+
cancelThoughtFlushTimer();
|
|
2868
|
+
if (pendingThoughtDelta.length === 0) {
|
|
2869
|
+
return;
|
|
2870
|
+
}
|
|
2871
|
+
options.append(`thought_delta: ${pendingThoughtDelta}`);
|
|
2872
|
+
pendingThoughtDelta = "";
|
|
2873
|
+
};
|
|
2874
|
+
const scheduleThoughtFlush = () => {
|
|
2875
|
+
if (thoughtFlushTimer !== null || thoughtDeltaThrottleMs === 0) {
|
|
2876
|
+
return;
|
|
2877
|
+
}
|
|
2878
|
+
thoughtFlushTimer = setTimeout(() => {
|
|
2879
|
+
thoughtFlushTimer = null;
|
|
2880
|
+
flushThoughtDelta();
|
|
2881
|
+
}, thoughtDeltaThrottleMs);
|
|
2882
|
+
thoughtFlushTimer.unref?.();
|
|
2883
|
+
};
|
|
2884
|
+
return {
|
|
2885
|
+
appendEvent: (event) => {
|
|
2886
|
+
if (event.type === "delta" && event.channel === "thought") {
|
|
2887
|
+
if (event.text.length === 0) {
|
|
2888
|
+
return;
|
|
2889
|
+
}
|
|
2890
|
+
pendingThoughtDelta += event.text;
|
|
2891
|
+
if (thoughtDeltaThrottleMs === 0) {
|
|
2892
|
+
flushThoughtDelta();
|
|
2893
|
+
return;
|
|
2894
|
+
}
|
|
2895
|
+
scheduleThoughtFlush();
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2898
|
+
flushThoughtDelta();
|
|
2899
|
+
appendAgentStreamEventLog({
|
|
2900
|
+
event,
|
|
2901
|
+
append: options.append
|
|
2902
|
+
});
|
|
2903
|
+
},
|
|
2904
|
+
flush: () => {
|
|
2905
|
+
flushThoughtDelta();
|
|
2906
|
+
}
|
|
2907
|
+
};
|
|
2908
|
+
}
|
|
2848
2909
|
var AgentLoggingSessionImpl = class {
|
|
2849
2910
|
workspaceDir;
|
|
2850
2911
|
logsRootDir;
|
|
@@ -2896,6 +2957,25 @@ var AgentLoggingSessionImpl = class {
|
|
|
2896
2957
|
}
|
|
2897
2958
|
this.enqueueLineWrite(timestamped);
|
|
2898
2959
|
}
|
|
2960
|
+
async writeAttachments(baseDir, attachments) {
|
|
2961
|
+
const usedNames = /* @__PURE__ */ new Set();
|
|
2962
|
+
for (const attachment of attachments ?? []) {
|
|
2963
|
+
let filename = normalisePathSegment(attachment.filename);
|
|
2964
|
+
if (!filename.includes(".")) {
|
|
2965
|
+
filename = `${filename}.bin`;
|
|
2966
|
+
}
|
|
2967
|
+
const ext = path3.extname(filename);
|
|
2968
|
+
const base = ext.length > 0 ? filename.slice(0, -ext.length) : filename;
|
|
2969
|
+
let candidate = filename;
|
|
2970
|
+
let duplicateIndex = 2;
|
|
2971
|
+
while (usedNames.has(candidate)) {
|
|
2972
|
+
candidate = `${base}-${duplicateIndex.toString()}${ext}`;
|
|
2973
|
+
duplicateIndex += 1;
|
|
2974
|
+
}
|
|
2975
|
+
usedNames.add(candidate);
|
|
2976
|
+
await writeFile(path3.join(baseDir, candidate), attachment.bytes);
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2899
2979
|
startLlmCall(input) {
|
|
2900
2980
|
const callNumber = this.callCounter + 1;
|
|
2901
2981
|
this.callCounter = callNumber;
|
|
@@ -2908,6 +2988,9 @@ var AgentLoggingSessionImpl = class {
|
|
|
2908
2988
|
);
|
|
2909
2989
|
const responsePath = path3.join(baseDir, "response.txt");
|
|
2910
2990
|
const thoughtsPath = path3.join(baseDir, "thoughts.txt");
|
|
2991
|
+
const toolCallPath = path3.join(baseDir, "tool_call.txt");
|
|
2992
|
+
const toolCallResponsePath = path3.join(baseDir, "tool_call_response.txt");
|
|
2993
|
+
const errorPath = path3.join(baseDir, "error.txt");
|
|
2911
2994
|
const responseMetadataPath = path3.join(baseDir, "response.metadata.json");
|
|
2912
2995
|
let chain = this.ensureReady.then(async () => {
|
|
2913
2996
|
await mkdir(baseDir, { recursive: true });
|
|
@@ -2929,22 +3012,13 @@ var AgentLoggingSessionImpl = class {
|
|
|
2929
3012
|
`,
|
|
2930
3013
|
"utf8"
|
|
2931
3014
|
);
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
const base = ext.length > 0 ? filename.slice(0, -ext.length) : filename;
|
|
2940
|
-
let candidate = filename;
|
|
2941
|
-
let duplicateIndex = 2;
|
|
2942
|
-
while (usedNames.has(candidate)) {
|
|
2943
|
-
candidate = `${base}-${duplicateIndex.toString()}${ext}`;
|
|
2944
|
-
duplicateIndex += 1;
|
|
2945
|
-
}
|
|
2946
|
-
usedNames.add(candidate);
|
|
2947
|
-
await writeFile(path3.join(baseDir, candidate), attachment.bytes);
|
|
3015
|
+
await this.writeAttachments(baseDir, input.attachments);
|
|
3016
|
+
if (hasNonEmptyText(input.toolCallResponseText)) {
|
|
3017
|
+
await writeFile(
|
|
3018
|
+
toolCallResponsePath,
|
|
3019
|
+
ensureTrailingNewline(input.toolCallResponseText),
|
|
3020
|
+
"utf8"
|
|
3021
|
+
);
|
|
2948
3022
|
}
|
|
2949
3023
|
}).catch(() => void 0);
|
|
2950
3024
|
this.track(chain);
|
|
@@ -2972,18 +3046,25 @@ var AgentLoggingSessionImpl = class {
|
|
|
2972
3046
|
await appendFile(responsePath, text, "utf8");
|
|
2973
3047
|
});
|
|
2974
3048
|
},
|
|
2975
|
-
complete: (
|
|
3049
|
+
complete: (options) => {
|
|
2976
3050
|
if (closed) {
|
|
2977
3051
|
return;
|
|
2978
3052
|
}
|
|
2979
3053
|
closed = true;
|
|
2980
3054
|
enqueue(async () => {
|
|
3055
|
+
if (hasNonEmptyText(options?.responseText)) {
|
|
3056
|
+
await writeFile(responsePath, options.responseText, "utf8");
|
|
3057
|
+
}
|
|
3058
|
+
if (hasNonEmptyText(options?.toolCallText)) {
|
|
3059
|
+
await writeFile(toolCallPath, ensureTrailingNewline(options.toolCallText), "utf8");
|
|
3060
|
+
}
|
|
3061
|
+
await this.writeAttachments(baseDir, options?.attachments);
|
|
2981
3062
|
const payload = {
|
|
2982
3063
|
capturedAt: toIsoNow(),
|
|
2983
3064
|
status: "completed"
|
|
2984
3065
|
};
|
|
2985
|
-
if (metadata) {
|
|
2986
|
-
const sanitised = sanitiseLogValue(metadata);
|
|
3066
|
+
if (options?.metadata) {
|
|
3067
|
+
const sanitised = sanitiseLogValue(options.metadata);
|
|
2987
3068
|
if (sanitised && typeof sanitised === "object" && !Array.isArray(sanitised)) {
|
|
2988
3069
|
Object.assign(payload, sanitised);
|
|
2989
3070
|
} else if (sanitised !== void 0) {
|
|
@@ -2994,19 +3075,27 @@ var AgentLoggingSessionImpl = class {
|
|
|
2994
3075
|
`, "utf8");
|
|
2995
3076
|
});
|
|
2996
3077
|
},
|
|
2997
|
-
fail: (error,
|
|
3078
|
+
fail: (error, options) => {
|
|
2998
3079
|
if (closed) {
|
|
2999
3080
|
return;
|
|
3000
3081
|
}
|
|
3001
3082
|
closed = true;
|
|
3002
3083
|
enqueue(async () => {
|
|
3084
|
+
if (hasNonEmptyText(options?.responseText)) {
|
|
3085
|
+
await writeFile(responsePath, options.responseText, "utf8");
|
|
3086
|
+
}
|
|
3087
|
+
if (hasNonEmptyText(options?.toolCallText)) {
|
|
3088
|
+
await writeFile(toolCallPath, ensureTrailingNewline(options.toolCallText), "utf8");
|
|
3089
|
+
}
|
|
3090
|
+
await this.writeAttachments(baseDir, options?.attachments);
|
|
3091
|
+
await writeFile(errorPath, ensureTrailingNewline(toErrorMessage(error)), "utf8");
|
|
3003
3092
|
const payload = {
|
|
3004
3093
|
capturedAt: toIsoNow(),
|
|
3005
3094
|
status: "failed",
|
|
3006
3095
|
error: toErrorMessage(error)
|
|
3007
3096
|
};
|
|
3008
|
-
if (metadata) {
|
|
3009
|
-
const sanitised = sanitiseLogValue(metadata);
|
|
3097
|
+
if (options?.metadata) {
|
|
3098
|
+
const sanitised = sanitiseLogValue(options.metadata);
|
|
3010
3099
|
if (sanitised && typeof sanitised === "object" && !Array.isArray(sanitised)) {
|
|
3011
3100
|
Object.assign(payload, sanitised);
|
|
3012
3101
|
} else if (sanitised !== void 0) {
|
|
@@ -4849,7 +4938,10 @@ function resolveAttachmentExtension(mimeType) {
|
|
|
4849
4938
|
}
|
|
4850
4939
|
}
|
|
4851
4940
|
}
|
|
4852
|
-
function
|
|
4941
|
+
function buildLoggedAttachmentFilename(prefix, index, mimeType) {
|
|
4942
|
+
return `${prefix}-${index.toString()}.${resolveAttachmentExtension(mimeType)}`;
|
|
4943
|
+
}
|
|
4944
|
+
function decodeDataUrlAttachment(value, options) {
|
|
4853
4945
|
const trimmed = value.trim();
|
|
4854
4946
|
if (!trimmed.toLowerCase().startsWith("data:")) {
|
|
4855
4947
|
return null;
|
|
@@ -4865,7 +4957,7 @@ function decodeDataUrlAttachment(value, basename) {
|
|
|
4865
4957
|
try {
|
|
4866
4958
|
const bytes = isBase64 ? Buffer4.from(payload, "base64") : Buffer4.from(decodeURIComponent(payload), "utf8");
|
|
4867
4959
|
return {
|
|
4868
|
-
filename:
|
|
4960
|
+
filename: buildLoggedAttachmentFilename(options.prefix, options.index, mimeType),
|
|
4869
4961
|
bytes
|
|
4870
4962
|
};
|
|
4871
4963
|
} catch {
|
|
@@ -4874,10 +4966,10 @@ function decodeDataUrlAttachment(value, basename) {
|
|
|
4874
4966
|
}
|
|
4875
4967
|
function collectPayloadAttachments(value, options) {
|
|
4876
4968
|
if (typeof value === "string") {
|
|
4877
|
-
const attachment = decodeDataUrlAttachment(
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
);
|
|
4969
|
+
const attachment = decodeDataUrlAttachment(value, {
|
|
4970
|
+
prefix: options.prefix,
|
|
4971
|
+
index: options.counter
|
|
4972
|
+
});
|
|
4881
4973
|
if (attachment) {
|
|
4882
4974
|
options.attachments.push(attachment);
|
|
4883
4975
|
options.counter += 1;
|
|
@@ -4902,7 +4994,7 @@ function collectPayloadAttachments(value, options) {
|
|
|
4902
4994
|
if (typeof record.data === "string" && mimeType) {
|
|
4903
4995
|
try {
|
|
4904
4996
|
options.attachments.push({
|
|
4905
|
-
filename:
|
|
4997
|
+
filename: buildLoggedAttachmentFilename(options.prefix, options.counter, mimeType),
|
|
4906
4998
|
bytes: decodeInlineDataBuffer(record.data)
|
|
4907
4999
|
});
|
|
4908
5000
|
options.counter += 1;
|
|
@@ -4922,27 +5014,166 @@ function serialiseRequestPayloadForLogging(value) {
|
|
|
4922
5014
|
`;
|
|
4923
5015
|
}
|
|
4924
5016
|
}
|
|
5017
|
+
function serialiseLogArtifactText(value) {
|
|
5018
|
+
if (value === null || value === void 0) {
|
|
5019
|
+
return void 0;
|
|
5020
|
+
}
|
|
5021
|
+
if (typeof value === "string") {
|
|
5022
|
+
if (value.length === 0) {
|
|
5023
|
+
return void 0;
|
|
5024
|
+
}
|
|
5025
|
+
return value.endsWith("\n") ? value : `${value}
|
|
5026
|
+
`;
|
|
5027
|
+
}
|
|
5028
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
5029
|
+
return void 0;
|
|
5030
|
+
}
|
|
5031
|
+
if (isPlainRecord(value) && Object.keys(value).length === 0) {
|
|
5032
|
+
return void 0;
|
|
5033
|
+
}
|
|
5034
|
+
try {
|
|
5035
|
+
return `${JSON.stringify(sanitiseLogValue(value), null, 2)}
|
|
5036
|
+
`;
|
|
5037
|
+
} catch {
|
|
5038
|
+
return `${String(value)}
|
|
5039
|
+
`;
|
|
5040
|
+
}
|
|
5041
|
+
}
|
|
5042
|
+
function collectLoggedAttachmentsFromLlmParts(parts, prefix) {
|
|
5043
|
+
const attachments = [];
|
|
5044
|
+
let index = 1;
|
|
5045
|
+
for (const part of parts) {
|
|
5046
|
+
if (part.type !== "inlineData") {
|
|
5047
|
+
continue;
|
|
5048
|
+
}
|
|
5049
|
+
attachments.push({
|
|
5050
|
+
filename: buildLoggedAttachmentFilename(prefix, index, part.mimeType),
|
|
5051
|
+
bytes: decodeInlineDataBuffer(part.data)
|
|
5052
|
+
});
|
|
5053
|
+
index += 1;
|
|
5054
|
+
}
|
|
5055
|
+
return attachments;
|
|
5056
|
+
}
|
|
5057
|
+
function collectLoggedAttachmentsFromGeminiParts(parts, prefix) {
|
|
5058
|
+
return collectLoggedAttachmentsFromLlmParts(convertGooglePartsToLlmParts(parts), prefix);
|
|
5059
|
+
}
|
|
5060
|
+
function extractToolCallResponseTextFromOpenAiInput(input) {
|
|
5061
|
+
if (!Array.isArray(input)) {
|
|
5062
|
+
return void 0;
|
|
5063
|
+
}
|
|
5064
|
+
const responses = input.filter((item) => isPlainRecord(item)).flatMap((item) => {
|
|
5065
|
+
const type = typeof item.type === "string" ? item.type : "";
|
|
5066
|
+
if (type !== "function_call_output" && type !== "custom_tool_call_output") {
|
|
5067
|
+
return [];
|
|
5068
|
+
}
|
|
5069
|
+
return [
|
|
5070
|
+
{
|
|
5071
|
+
type,
|
|
5072
|
+
callId: typeof item.call_id === "string" ? item.call_id : void 0,
|
|
5073
|
+
output: "output" in item ? sanitiseLogValue(item.output) : void 0
|
|
5074
|
+
}
|
|
5075
|
+
];
|
|
5076
|
+
});
|
|
5077
|
+
return serialiseLogArtifactText(responses);
|
|
5078
|
+
}
|
|
5079
|
+
function extractToolCallResponseTextFromFireworksMessages(messages) {
|
|
5080
|
+
if (!Array.isArray(messages)) {
|
|
5081
|
+
return void 0;
|
|
5082
|
+
}
|
|
5083
|
+
const responses = messages.filter((message) => isPlainRecord(message)).flatMap((message) => {
|
|
5084
|
+
if (message.role !== "tool") {
|
|
5085
|
+
return [];
|
|
5086
|
+
}
|
|
5087
|
+
return [
|
|
5088
|
+
{
|
|
5089
|
+
toolCallId: typeof message.tool_call_id === "string" ? message.tool_call_id : void 0,
|
|
5090
|
+
content: sanitiseLogValue(message.content)
|
|
5091
|
+
}
|
|
5092
|
+
];
|
|
5093
|
+
});
|
|
5094
|
+
return serialiseLogArtifactText(responses);
|
|
5095
|
+
}
|
|
5096
|
+
function extractToolCallResponseTextFromGeminiContents(contents) {
|
|
5097
|
+
if (!Array.isArray(contents)) {
|
|
5098
|
+
return void 0;
|
|
5099
|
+
}
|
|
5100
|
+
const responses = [];
|
|
5101
|
+
for (const content of contents) {
|
|
5102
|
+
if (!content || typeof content !== "object") {
|
|
5103
|
+
continue;
|
|
5104
|
+
}
|
|
5105
|
+
const parts = content.parts;
|
|
5106
|
+
if (!Array.isArray(parts)) {
|
|
5107
|
+
continue;
|
|
5108
|
+
}
|
|
5109
|
+
for (const part of parts) {
|
|
5110
|
+
if (!part || typeof part !== "object") {
|
|
5111
|
+
continue;
|
|
5112
|
+
}
|
|
5113
|
+
const functionResponse = part.functionResponse;
|
|
5114
|
+
if (functionResponse) {
|
|
5115
|
+
responses.push(sanitiseLogValue(functionResponse));
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
}
|
|
5119
|
+
return serialiseLogArtifactText(responses);
|
|
5120
|
+
}
|
|
5121
|
+
function serialiseOpenAiStyleToolCallsForLogging(calls) {
|
|
5122
|
+
return serialiseLogArtifactText(
|
|
5123
|
+
calls.map((call) => {
|
|
5124
|
+
if (call.kind === "custom") {
|
|
5125
|
+
return {
|
|
5126
|
+
kind: call.kind,
|
|
5127
|
+
name: call.name,
|
|
5128
|
+
callId: call.callId,
|
|
5129
|
+
itemId: call.itemId,
|
|
5130
|
+
input: call.input
|
|
5131
|
+
};
|
|
5132
|
+
}
|
|
5133
|
+
const { value, error } = parseOpenAiToolArguments(call.arguments);
|
|
5134
|
+
return {
|
|
5135
|
+
kind: call.kind,
|
|
5136
|
+
name: call.name,
|
|
5137
|
+
callId: call.callId,
|
|
5138
|
+
itemId: call.itemId,
|
|
5139
|
+
arguments: value,
|
|
5140
|
+
...error ? { parseError: error, rawArguments: call.arguments } : {}
|
|
5141
|
+
};
|
|
5142
|
+
})
|
|
5143
|
+
);
|
|
5144
|
+
}
|
|
5145
|
+
function serialiseGeminiToolCallsForLogging(calls) {
|
|
5146
|
+
return serialiseLogArtifactText(
|
|
5147
|
+
calls.map((call) => ({
|
|
5148
|
+
name: call.name ?? "unknown",
|
|
5149
|
+
callId: typeof call.id === "string" ? call.id : void 0,
|
|
5150
|
+
arguments: sanitiseLogValue(call.args ?? {})
|
|
5151
|
+
}))
|
|
5152
|
+
);
|
|
5153
|
+
}
|
|
4925
5154
|
function startLlmCallLoggerFromContents(options) {
|
|
4926
5155
|
const session = getCurrentAgentLoggingSession();
|
|
4927
5156
|
if (!session) {
|
|
4928
5157
|
return void 0;
|
|
4929
5158
|
}
|
|
4930
5159
|
const attachments = [];
|
|
5160
|
+
let attachmentIndex = 1;
|
|
4931
5161
|
const sections = [];
|
|
4932
5162
|
for (const [messageIndex, message] of options.contents.entries()) {
|
|
4933
5163
|
sections.push(`### message_${(messageIndex + 1).toString()} role=${message.role}`);
|
|
4934
|
-
for (const
|
|
5164
|
+
for (const part of message.parts) {
|
|
4935
5165
|
if (part.type === "text") {
|
|
4936
5166
|
const channel = part.thought === true ? "thought" : "response";
|
|
4937
5167
|
sections.push(`[text:${channel}]`);
|
|
4938
5168
|
sections.push(part.text);
|
|
4939
5169
|
continue;
|
|
4940
5170
|
}
|
|
4941
|
-
const filename =
|
|
5171
|
+
const filename = buildLoggedAttachmentFilename("input", attachmentIndex, part.mimeType);
|
|
4942
5172
|
attachments.push({
|
|
4943
5173
|
filename,
|
|
4944
5174
|
bytes: decodeInlineDataBuffer(part.data)
|
|
4945
5175
|
});
|
|
5176
|
+
attachmentIndex += 1;
|
|
4946
5177
|
sections.push(
|
|
4947
5178
|
`[inlineData] file=${filename} mime=${part.mimeType ?? "application/octet-stream"} bytes=${attachments[attachments.length - 1]?.bytes.byteLength ?? 0}`
|
|
4948
5179
|
);
|
|
@@ -4986,11 +5217,18 @@ function startLlmCallLoggerFromPayload(options) {
|
|
|
4986
5217
|
}
|
|
4987
5218
|
const attachments = [];
|
|
4988
5219
|
collectPayloadAttachments(options.requestPayload, {
|
|
4989
|
-
prefix:
|
|
5220
|
+
prefix: "input",
|
|
4990
5221
|
attachments,
|
|
4991
5222
|
seen: /* @__PURE__ */ new WeakSet(),
|
|
4992
5223
|
counter: 1
|
|
4993
5224
|
});
|
|
5225
|
+
const toolCallResponseText = options.provider === "openai" || options.provider === "chatgpt" ? extractToolCallResponseTextFromOpenAiInput(
|
|
5226
|
+
options.requestPayload.input
|
|
5227
|
+
) : options.provider === "fireworks" ? extractToolCallResponseTextFromFireworksMessages(
|
|
5228
|
+
options.requestPayload.messages
|
|
5229
|
+
) : extractToolCallResponseTextFromGeminiContents(
|
|
5230
|
+
options.requestPayload.contents
|
|
5231
|
+
);
|
|
4994
5232
|
return session.startLlmCall({
|
|
4995
5233
|
provider: options.provider,
|
|
4996
5234
|
modelId: options.modelId,
|
|
@@ -4999,7 +5237,8 @@ function startLlmCallLoggerFromPayload(options) {
|
|
|
4999
5237
|
step: options.step,
|
|
5000
5238
|
...getCurrentToolCallContext() ? { toolContext: getCurrentToolCallContext() } : {}
|
|
5001
5239
|
},
|
|
5002
|
-
attachments
|
|
5240
|
+
attachments,
|
|
5241
|
+
toolCallResponseText
|
|
5003
5242
|
});
|
|
5004
5243
|
}
|
|
5005
5244
|
async function runTextCall(params) {
|
|
@@ -5304,6 +5543,7 @@ async function runTextCall(params) {
|
|
|
5304
5543
|
const mergedParts = mergeConsecutiveTextParts(responseParts);
|
|
5305
5544
|
const content = mergedParts.length > 0 ? { role: responseRole ?? "assistant", parts: mergedParts } : void 0;
|
|
5306
5545
|
const { text, thoughts } = extractTextByChannel(content);
|
|
5546
|
+
const outputAttachments = collectLoggedAttachmentsFromLlmParts(mergedParts, "output");
|
|
5307
5547
|
const costUsd = estimateCallCostUsd({
|
|
5308
5548
|
modelId: modelVersion,
|
|
5309
5549
|
tokens: latestUsage,
|
|
@@ -5314,16 +5554,20 @@ async function runTextCall(params) {
|
|
|
5314
5554
|
queue.push({ type: "usage", usage: latestUsage, costUsd, modelVersion });
|
|
5315
5555
|
}
|
|
5316
5556
|
callLogger?.complete({
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5557
|
+
responseText: text,
|
|
5558
|
+
attachments: outputAttachments,
|
|
5559
|
+
metadata: {
|
|
5560
|
+
provider,
|
|
5561
|
+
model: request.model,
|
|
5562
|
+
modelVersion,
|
|
5563
|
+
blocked,
|
|
5564
|
+
costUsd,
|
|
5565
|
+
usage: latestUsage,
|
|
5566
|
+
grounding: grounding ? sanitiseLogValue(grounding) : void 0,
|
|
5567
|
+
responseChars: text.length,
|
|
5568
|
+
thoughtChars: thoughts.length,
|
|
5569
|
+
responseImages
|
|
5570
|
+
}
|
|
5327
5571
|
});
|
|
5328
5572
|
return {
|
|
5329
5573
|
provider,
|
|
@@ -5338,14 +5582,21 @@ async function runTextCall(params) {
|
|
|
5338
5582
|
grounding
|
|
5339
5583
|
};
|
|
5340
5584
|
} catch (error) {
|
|
5585
|
+
const partialParts = mergeConsecutiveTextParts(responseParts);
|
|
5586
|
+
const partialContent = partialParts.length > 0 ? { role: responseRole ?? "assistant", parts: partialParts } : void 0;
|
|
5587
|
+
const { text: partialText } = extractTextByChannel(partialContent);
|
|
5341
5588
|
callLogger?.fail(error, {
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5589
|
+
responseText: partialText,
|
|
5590
|
+
attachments: collectLoggedAttachmentsFromLlmParts(partialParts, "output"),
|
|
5591
|
+
metadata: {
|
|
5592
|
+
provider,
|
|
5593
|
+
model: request.model,
|
|
5594
|
+
modelVersion,
|
|
5595
|
+
blocked,
|
|
5596
|
+
usage: latestUsage,
|
|
5597
|
+
partialResponseParts: responseParts.length,
|
|
5598
|
+
responseImages
|
|
5599
|
+
}
|
|
5349
5600
|
});
|
|
5350
5601
|
throw error;
|
|
5351
5602
|
}
|
|
@@ -5812,6 +6063,9 @@ async function runToolLoop(request) {
|
|
|
5812
6063
|
let usageTokens;
|
|
5813
6064
|
let thoughtDeltaEmitted = false;
|
|
5814
6065
|
let blocked = false;
|
|
6066
|
+
let responseText = "";
|
|
6067
|
+
let reasoningSummary = "";
|
|
6068
|
+
let stepToolCallText;
|
|
5815
6069
|
const stepRequestPayload = {
|
|
5816
6070
|
model: providerInfo.model,
|
|
5817
6071
|
input,
|
|
@@ -5904,8 +6158,8 @@ async function runToolLoop(request) {
|
|
|
5904
6158
|
throw new Error(message);
|
|
5905
6159
|
}
|
|
5906
6160
|
usageTokens = extractOpenAiUsageTokens(finalResponse.usage);
|
|
5907
|
-
|
|
5908
|
-
|
|
6161
|
+
responseText = extractOpenAiResponseParts(finalResponse).parts.filter((p) => p.type === "text" && p.thought !== true).map((p) => p.text).join("").trim();
|
|
6162
|
+
reasoningSummary = extractOpenAiReasoningSummary(finalResponse).trim();
|
|
5909
6163
|
if (!thoughtDeltaEmitted && reasoningSummary.length > 0) {
|
|
5910
6164
|
stepCallLogger?.appendThoughtDelta(reasoningSummary);
|
|
5911
6165
|
emitEvent({ type: "delta", channel: "thought", text: reasoningSummary });
|
|
@@ -5921,6 +6175,23 @@ async function runToolLoop(request) {
|
|
|
5921
6175
|
emitEvent({ type: "usage", usage: usageTokens, costUsd: stepCostUsd, modelVersion });
|
|
5922
6176
|
}
|
|
5923
6177
|
const responseToolCalls = extractOpenAiToolCalls(finalResponse.output);
|
|
6178
|
+
stepToolCallText = serialiseOpenAiStyleToolCallsForLogging(
|
|
6179
|
+
responseToolCalls.map(
|
|
6180
|
+
(call) => call.kind === "custom" ? {
|
|
6181
|
+
kind: call.kind,
|
|
6182
|
+
name: call.name,
|
|
6183
|
+
input: call.input,
|
|
6184
|
+
callId: call.call_id,
|
|
6185
|
+
itemId: call.id
|
|
6186
|
+
} : {
|
|
6187
|
+
kind: call.kind,
|
|
6188
|
+
name: call.name,
|
|
6189
|
+
arguments: call.arguments,
|
|
6190
|
+
callId: call.call_id,
|
|
6191
|
+
itemId: call.id
|
|
6192
|
+
}
|
|
6193
|
+
)
|
|
6194
|
+
);
|
|
5924
6195
|
const stepToolCalls = [];
|
|
5925
6196
|
if (responseToolCalls.length === 0) {
|
|
5926
6197
|
const steeringInput2 = steeringInternal?.drainPendingContents() ?? [];
|
|
@@ -5948,17 +6219,20 @@ async function runToolLoop(request) {
|
|
|
5948
6219
|
timing: timing2
|
|
5949
6220
|
});
|
|
5950
6221
|
stepCallLogger?.complete({
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
6222
|
+
responseText,
|
|
6223
|
+
metadata: {
|
|
6224
|
+
provider: "openai",
|
|
6225
|
+
model: request.model,
|
|
6226
|
+
modelVersion,
|
|
6227
|
+
step: turn,
|
|
6228
|
+
usage: usageTokens,
|
|
6229
|
+
costUsd: stepCostUsd,
|
|
6230
|
+
blocked,
|
|
6231
|
+
responseChars: responseText.length,
|
|
6232
|
+
thoughtChars: reasoningSummary.length,
|
|
6233
|
+
toolCalls: 0,
|
|
6234
|
+
finalStep: steeringItems2.length === 0
|
|
6235
|
+
}
|
|
5962
6236
|
});
|
|
5963
6237
|
if (steeringItems2.length === 0) {
|
|
5964
6238
|
return { text: finalText, thoughts: finalThoughts, steps, totalCostUsd };
|
|
@@ -6081,28 +6355,36 @@ async function runToolLoop(request) {
|
|
|
6081
6355
|
const steeringInput = steeringInternal?.drainPendingContents() ?? [];
|
|
6082
6356
|
const steeringItems = steeringInput.length > 0 ? toOpenAiInput(steeringInput) : [];
|
|
6083
6357
|
stepCallLogger?.complete({
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6358
|
+
responseText,
|
|
6359
|
+
toolCallText: stepToolCallText,
|
|
6360
|
+
metadata: {
|
|
6361
|
+
provider: "openai",
|
|
6362
|
+
model: request.model,
|
|
6363
|
+
modelVersion,
|
|
6364
|
+
step: turn,
|
|
6365
|
+
usage: usageTokens,
|
|
6366
|
+
costUsd: stepCostUsd,
|
|
6367
|
+
blocked,
|
|
6368
|
+
responseChars: responseText.length,
|
|
6369
|
+
thoughtChars: reasoningSummary.length,
|
|
6370
|
+
toolCalls: stepToolCalls.length,
|
|
6371
|
+
finalStep: false
|
|
6372
|
+
}
|
|
6095
6373
|
});
|
|
6096
6374
|
previousResponseId = finalResponse.id;
|
|
6097
6375
|
input = steeringItems.length > 0 ? toolOutputs.concat(steeringItems) : toolOutputs;
|
|
6098
6376
|
} catch (error) {
|
|
6099
6377
|
stepCallLogger?.fail(error, {
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6378
|
+
responseText,
|
|
6379
|
+
toolCallText: stepToolCallText,
|
|
6380
|
+
metadata: {
|
|
6381
|
+
provider: "openai",
|
|
6382
|
+
model: request.model,
|
|
6383
|
+
modelVersion,
|
|
6384
|
+
step: turn,
|
|
6385
|
+
usage: usageTokens,
|
|
6386
|
+
blocked
|
|
6387
|
+
}
|
|
6106
6388
|
});
|
|
6107
6389
|
throw error;
|
|
6108
6390
|
}
|
|
@@ -6128,6 +6410,7 @@ async function runToolLoop(request) {
|
|
|
6128
6410
|
let usageTokens;
|
|
6129
6411
|
let responseText = "";
|
|
6130
6412
|
let reasoningSummaryText = "";
|
|
6413
|
+
let stepToolCallText;
|
|
6131
6414
|
const markFirstModelEvent = () => {
|
|
6132
6415
|
if (firstModelEventAtMs === void 0) {
|
|
6133
6416
|
firstModelEventAtMs = Date.now();
|
|
@@ -6196,6 +6479,23 @@ async function runToolLoop(request) {
|
|
|
6196
6479
|
stepCallLogger?.appendResponseDelta(responseText);
|
|
6197
6480
|
}
|
|
6198
6481
|
const responseToolCalls = response.toolCalls ?? [];
|
|
6482
|
+
stepToolCallText = serialiseOpenAiStyleToolCallsForLogging(
|
|
6483
|
+
responseToolCalls.map(
|
|
6484
|
+
(call) => call.kind === "custom" ? {
|
|
6485
|
+
kind: call.kind,
|
|
6486
|
+
name: call.name,
|
|
6487
|
+
input: call.input,
|
|
6488
|
+
callId: call.callId,
|
|
6489
|
+
itemId: call.id
|
|
6490
|
+
} : {
|
|
6491
|
+
kind: call.kind,
|
|
6492
|
+
name: call.name,
|
|
6493
|
+
arguments: call.arguments,
|
|
6494
|
+
callId: call.callId,
|
|
6495
|
+
itemId: call.id
|
|
6496
|
+
}
|
|
6497
|
+
)
|
|
6498
|
+
);
|
|
6199
6499
|
if (responseToolCalls.length === 0) {
|
|
6200
6500
|
const steeringInput2 = steeringInternal?.drainPendingContents() ?? [];
|
|
6201
6501
|
const steeringItems2 = steeringInput2.length > 0 ? toChatGptInput(steeringInput2).input : [];
|
|
@@ -6221,16 +6521,19 @@ async function runToolLoop(request) {
|
|
|
6221
6521
|
timing: timing2
|
|
6222
6522
|
});
|
|
6223
6523
|
stepCallLogger?.complete({
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6524
|
+
responseText,
|
|
6525
|
+
metadata: {
|
|
6526
|
+
provider: "chatgpt",
|
|
6527
|
+
model: request.model,
|
|
6528
|
+
modelVersion,
|
|
6529
|
+
step: turn,
|
|
6530
|
+
usage: usageTokens,
|
|
6531
|
+
costUsd: stepCostUsd,
|
|
6532
|
+
responseChars: responseText.length,
|
|
6533
|
+
thoughtChars: reasoningSummaryText.length,
|
|
6534
|
+
toolCalls: 0,
|
|
6535
|
+
finalStep: steeringItems2.length === 0
|
|
6536
|
+
}
|
|
6234
6537
|
});
|
|
6235
6538
|
if (steeringItems2.length === 0) {
|
|
6236
6539
|
return { text: finalText, thoughts: finalThoughts, steps, totalCostUsd };
|
|
@@ -6363,25 +6666,33 @@ async function runToolLoop(request) {
|
|
|
6363
6666
|
const steeringInput = steeringInternal?.drainPendingContents() ?? [];
|
|
6364
6667
|
const steeringItems = steeringInput.length > 0 ? toChatGptInput(steeringInput).input : [];
|
|
6365
6668
|
stepCallLogger?.complete({
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6669
|
+
responseText,
|
|
6670
|
+
toolCallText: stepToolCallText,
|
|
6671
|
+
metadata: {
|
|
6672
|
+
provider: "chatgpt",
|
|
6673
|
+
model: request.model,
|
|
6674
|
+
modelVersion,
|
|
6675
|
+
step: turn,
|
|
6676
|
+
usage: usageTokens,
|
|
6677
|
+
costUsd: stepCostUsd,
|
|
6678
|
+
responseChars: responseText.length,
|
|
6679
|
+
thoughtChars: reasoningSummaryText.length,
|
|
6680
|
+
toolCalls: toolCalls.length,
|
|
6681
|
+
finalStep: false
|
|
6682
|
+
}
|
|
6376
6683
|
});
|
|
6377
6684
|
input = steeringItems.length > 0 ? input.concat(toolOutputs, steeringItems) : input.concat(toolOutputs);
|
|
6378
6685
|
} catch (error) {
|
|
6379
6686
|
stepCallLogger?.fail(error, {
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6687
|
+
responseText,
|
|
6688
|
+
toolCallText: stepToolCallText,
|
|
6689
|
+
metadata: {
|
|
6690
|
+
provider: "chatgpt",
|
|
6691
|
+
model: request.model,
|
|
6692
|
+
modelVersion,
|
|
6693
|
+
step: turn,
|
|
6694
|
+
usage: usageTokens
|
|
6695
|
+
}
|
|
6385
6696
|
});
|
|
6386
6697
|
throw error;
|
|
6387
6698
|
}
|
|
@@ -6404,6 +6715,7 @@ async function runToolLoop(request) {
|
|
|
6404
6715
|
let usageTokens;
|
|
6405
6716
|
let responseText = "";
|
|
6406
6717
|
let blocked = false;
|
|
6718
|
+
let stepToolCallText;
|
|
6407
6719
|
const stepRequestPayload = {
|
|
6408
6720
|
model: providerInfo.model,
|
|
6409
6721
|
messages,
|
|
@@ -6468,6 +6780,14 @@ async function runToolLoop(request) {
|
|
|
6468
6780
|
});
|
|
6469
6781
|
}
|
|
6470
6782
|
const responseToolCalls = extractFireworksToolCalls(message);
|
|
6783
|
+
stepToolCallText = serialiseOpenAiStyleToolCallsForLogging(
|
|
6784
|
+
responseToolCalls.map((call) => ({
|
|
6785
|
+
kind: "function",
|
|
6786
|
+
name: call.name,
|
|
6787
|
+
arguments: call.arguments,
|
|
6788
|
+
callId: call.id
|
|
6789
|
+
}))
|
|
6790
|
+
);
|
|
6471
6791
|
if (responseToolCalls.length === 0) {
|
|
6472
6792
|
const steeringInput2 = steeringInternal?.drainPendingContents() ?? [];
|
|
6473
6793
|
const steeringMessages = steeringInput2.length > 0 ? toFireworksMessages(steeringInput2) : [];
|
|
@@ -6493,17 +6813,20 @@ async function runToolLoop(request) {
|
|
|
6493
6813
|
timing: timing2
|
|
6494
6814
|
});
|
|
6495
6815
|
stepCallLogger?.complete({
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6816
|
+
responseText,
|
|
6817
|
+
metadata: {
|
|
6818
|
+
provider: "fireworks",
|
|
6819
|
+
model: request.model,
|
|
6820
|
+
modelVersion,
|
|
6821
|
+
step: turn,
|
|
6822
|
+
usage: usageTokens,
|
|
6823
|
+
costUsd: stepCostUsd,
|
|
6824
|
+
blocked,
|
|
6825
|
+
responseChars: responseText.length,
|
|
6826
|
+
thoughtChars: 0,
|
|
6827
|
+
toolCalls: 0,
|
|
6828
|
+
finalStep: steeringMessages.length === 0
|
|
6829
|
+
}
|
|
6507
6830
|
});
|
|
6508
6831
|
if (steeringMessages.length === 0) {
|
|
6509
6832
|
return { text: finalText, thoughts: finalThoughts, steps, totalCostUsd };
|
|
@@ -6615,17 +6938,21 @@ async function runToolLoop(request) {
|
|
|
6615
6938
|
timing
|
|
6616
6939
|
});
|
|
6617
6940
|
stepCallLogger?.complete({
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6941
|
+
responseText,
|
|
6942
|
+
toolCallText: stepToolCallText,
|
|
6943
|
+
metadata: {
|
|
6944
|
+
provider: "fireworks",
|
|
6945
|
+
model: request.model,
|
|
6946
|
+
modelVersion,
|
|
6947
|
+
step: turn,
|
|
6948
|
+
usage: usageTokens,
|
|
6949
|
+
costUsd: stepCostUsd,
|
|
6950
|
+
blocked,
|
|
6951
|
+
responseChars: responseText.length,
|
|
6952
|
+
thoughtChars: 0,
|
|
6953
|
+
toolCalls: stepToolCalls.length,
|
|
6954
|
+
finalStep: false
|
|
6955
|
+
}
|
|
6629
6956
|
});
|
|
6630
6957
|
messages.push({
|
|
6631
6958
|
role: "assistant",
|
|
@@ -6639,12 +6966,16 @@ async function runToolLoop(request) {
|
|
|
6639
6966
|
}
|
|
6640
6967
|
} catch (error) {
|
|
6641
6968
|
stepCallLogger?.fail(error, {
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6969
|
+
responseText,
|
|
6970
|
+
toolCallText: stepToolCallText,
|
|
6971
|
+
metadata: {
|
|
6972
|
+
provider: "fireworks",
|
|
6973
|
+
model: request.model,
|
|
6974
|
+
modelVersion,
|
|
6975
|
+
step: turn,
|
|
6976
|
+
usage: usageTokens,
|
|
6977
|
+
blocked
|
|
6978
|
+
}
|
|
6648
6979
|
});
|
|
6649
6980
|
throw error;
|
|
6650
6981
|
}
|
|
@@ -6664,6 +6995,7 @@ async function runToolLoop(request) {
|
|
|
6664
6995
|
let usageTokens;
|
|
6665
6996
|
let responseText = "";
|
|
6666
6997
|
let thoughtsText = "";
|
|
6998
|
+
let stepToolCallText;
|
|
6667
6999
|
const markFirstModelEvent = () => {
|
|
6668
7000
|
if (firstModelEventAtMs === void 0) {
|
|
6669
7001
|
firstModelEventAtMs = Date.now();
|
|
@@ -6784,12 +7116,17 @@ async function runToolLoop(request) {
|
|
|
6784
7116
|
modelVersion = response.modelVersion ?? request.model;
|
|
6785
7117
|
responseText = response.responseText.trim();
|
|
6786
7118
|
thoughtsText = response.thoughtsText.trim();
|
|
7119
|
+
const responseOutputAttachments = collectLoggedAttachmentsFromGeminiParts(
|
|
7120
|
+
response.modelParts,
|
|
7121
|
+
"output"
|
|
7122
|
+
);
|
|
6787
7123
|
const stepCostUsd = estimateCallCostUsd({
|
|
6788
7124
|
modelId: modelVersion,
|
|
6789
7125
|
tokens: usageTokens,
|
|
6790
7126
|
responseImages: 0
|
|
6791
7127
|
});
|
|
6792
7128
|
totalCostUsd += stepCostUsd;
|
|
7129
|
+
stepToolCallText = serialiseGeminiToolCallsForLogging(response.functionCalls);
|
|
6793
7130
|
if (response.functionCalls.length === 0) {
|
|
6794
7131
|
const steeringInput2 = steeringInternal?.drainPendingContents() ?? [];
|
|
6795
7132
|
finalText = responseText;
|
|
@@ -6815,16 +7152,20 @@ async function runToolLoop(request) {
|
|
|
6815
7152
|
timing: timing2
|
|
6816
7153
|
});
|
|
6817
7154
|
stepCallLogger?.complete({
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
7155
|
+
responseText,
|
|
7156
|
+
attachments: responseOutputAttachments,
|
|
7157
|
+
metadata: {
|
|
7158
|
+
provider: "gemini",
|
|
7159
|
+
model: request.model,
|
|
7160
|
+
modelVersion,
|
|
7161
|
+
step: turn,
|
|
7162
|
+
usage: usageTokens,
|
|
7163
|
+
costUsd: stepCostUsd,
|
|
7164
|
+
responseChars: responseText.length,
|
|
7165
|
+
thoughtChars: thoughtsText.length,
|
|
7166
|
+
toolCalls: 0,
|
|
7167
|
+
finalStep: steeringInput2.length === 0
|
|
7168
|
+
}
|
|
6828
7169
|
});
|
|
6829
7170
|
if (steeringInput2.length === 0) {
|
|
6830
7171
|
return { text: finalText, thoughts: finalThoughts, steps, totalCostUsd };
|
|
@@ -6951,16 +7292,21 @@ async function runToolLoop(request) {
|
|
|
6951
7292
|
timing
|
|
6952
7293
|
});
|
|
6953
7294
|
stepCallLogger?.complete({
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
7295
|
+
responseText,
|
|
7296
|
+
attachments: responseOutputAttachments,
|
|
7297
|
+
toolCallText: stepToolCallText,
|
|
7298
|
+
metadata: {
|
|
7299
|
+
provider: "gemini",
|
|
7300
|
+
model: request.model,
|
|
7301
|
+
modelVersion,
|
|
7302
|
+
step: turn,
|
|
7303
|
+
usage: usageTokens,
|
|
7304
|
+
costUsd: stepCostUsd,
|
|
7305
|
+
responseChars: responseText.length,
|
|
7306
|
+
thoughtChars: thoughtsText.length,
|
|
7307
|
+
toolCalls: toolCalls.length,
|
|
7308
|
+
finalStep: false
|
|
7309
|
+
}
|
|
6964
7310
|
});
|
|
6965
7311
|
geminiContents.push({ role: "user", parts: responseParts });
|
|
6966
7312
|
const steeringInput = steeringInternal?.drainPendingContents() ?? [];
|
|
@@ -6969,13 +7315,17 @@ async function runToolLoop(request) {
|
|
|
6969
7315
|
}
|
|
6970
7316
|
} catch (error) {
|
|
6971
7317
|
stepCallLogger?.fail(error, {
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
7318
|
+
responseText,
|
|
7319
|
+
toolCallText: stepToolCallText,
|
|
7320
|
+
metadata: {
|
|
7321
|
+
provider: "gemini",
|
|
7322
|
+
model: request.model,
|
|
7323
|
+
modelVersion,
|
|
7324
|
+
step: turn,
|
|
7325
|
+
usage: usageTokens,
|
|
7326
|
+
responseChars: responseText.length,
|
|
7327
|
+
thoughtChars: thoughtsText.length
|
|
7328
|
+
}
|
|
6979
7329
|
});
|
|
6980
7330
|
throw error;
|
|
6981
7331
|
}
|
|
@@ -10024,19 +10374,17 @@ async function runAgentLoopInternal(request, context) {
|
|
|
10024
10374
|
);
|
|
10025
10375
|
const sourceOnEvent = toolLoopRequestWithSteering.onEvent;
|
|
10026
10376
|
const includeLlmStreamEvents = telemetrySession?.includeLlmStreamEvents === true;
|
|
10377
|
+
const streamEventLogger = loggingSession ? createAgentStreamEventLogger({
|
|
10378
|
+
append: (line) => {
|
|
10379
|
+
loggingSession.logLine(`[agent:${runId}] ${line}`);
|
|
10380
|
+
}
|
|
10381
|
+
}) : void 0;
|
|
10027
10382
|
const wrappedOnEvent = sourceOnEvent || includeLlmStreamEvents ? (event) => {
|
|
10028
10383
|
sourceOnEvent?.(event);
|
|
10029
10384
|
if (includeLlmStreamEvents) {
|
|
10030
10385
|
emitTelemetry({ type: "agent.run.stream", event });
|
|
10031
10386
|
}
|
|
10032
|
-
|
|
10033
|
-
appendAgentStreamEventLog({
|
|
10034
|
-
event,
|
|
10035
|
-
append: (line) => {
|
|
10036
|
-
loggingSession.logLine(`[agent:${runId}] ${line}`);
|
|
10037
|
-
}
|
|
10038
|
-
});
|
|
10039
|
-
}
|
|
10387
|
+
streamEventLogger?.appendEvent(event);
|
|
10040
10388
|
} : void 0;
|
|
10041
10389
|
try {
|
|
10042
10390
|
const result = await runToolLoop({
|
|
@@ -10045,6 +10393,7 @@ async function runAgentLoopInternal(request, context) {
|
|
|
10045
10393
|
...wrappedOnEvent ? { onEvent: wrappedOnEvent } : {},
|
|
10046
10394
|
tools: mergedTools
|
|
10047
10395
|
});
|
|
10396
|
+
streamEventLogger?.flush();
|
|
10048
10397
|
emitTelemetry({
|
|
10049
10398
|
type: "agent.run.completed",
|
|
10050
10399
|
success: true,
|
|
@@ -10077,6 +10426,7 @@ async function runAgentLoopInternal(request, context) {
|
|
|
10077
10426
|
}
|
|
10078
10427
|
return result;
|
|
10079
10428
|
} catch (error) {
|
|
10429
|
+
streamEventLogger?.flush();
|
|
10080
10430
|
emitTelemetry({
|
|
10081
10431
|
type: "agent.run.completed",
|
|
10082
10432
|
success: false,
|
|
@@ -10093,6 +10443,7 @@ async function runAgentLoopInternal(request, context) {
|
|
|
10093
10443
|
);
|
|
10094
10444
|
throw error;
|
|
10095
10445
|
} finally {
|
|
10446
|
+
streamEventLogger?.flush();
|
|
10096
10447
|
await subagentController?.closeAll();
|
|
10097
10448
|
}
|
|
10098
10449
|
}
|