Skip to content

Commit 35b788f

Browse files
committed
2 parents c9e4ffb + f6752fe commit 35b788f

9 files changed

Lines changed: 337 additions & 169 deletions

File tree

agent/middleware/sequenceDebug.ts

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { AIMessage } from "@langchain/core/messages";
2+
import { convertMessagesToResponsesInput } from "@langchain/openai";
23
import { createMiddleware } from "langchain";
34
import YAML from "yaml";
45
import type { ToolCallEvent } from "../toolCallEvents.js";
@@ -120,44 +121,36 @@ function finalizeSequenceDebug(sequence: PendingSequenceDebug): SequenceDebug {
120121
};
121122
}
122123

124+
type OpenAiResponsesDebugModel = {
125+
model: string;
126+
zdrEnabled?: boolean;
127+
invocationParams: (options?: Record<string, unknown>) => Record<string, unknown>;
128+
};
129+
123130
function stringifyPromptForDebug(params: {
124-
systemMessage: { toDict(): unknown };
125-
messages: Array<{ toDict(): unknown }>;
131+
model: OpenAiResponsesDebugModel;
132+
systemMessage: { text: string };
133+
messages: unknown[];
126134
tools: unknown[];
135+
toolChoice?: unknown;
127136
modelSettings?: Record<string, unknown>;
128137
}) {
129-
const { systemMessage, messages, tools, modelSettings } = params;
138+
const { model, systemMessage, messages, tools, toolChoice, modelSettings } = params;
130139

131140
return YAML.stringify({
132-
systemMessage: systemMessage.toDict(),
133-
messages: messages.map((message) => message.toDict()),
134-
tools: tools.map((tool) => {
135-
if (
136-
typeof tool === "object" &&
137-
tool !== null &&
138-
"name" in tool &&
139-
typeof tool.name === "string"
140-
) {
141-
return tool.name;
142-
}
143-
144-
if (
145-
typeof tool === "object" &&
146-
tool !== null &&
147-
"schema" in tool &&
148-
typeof tool.schema === "object" &&
149-
tool.schema !== null &&
150-
"name" in tool.schema &&
151-
typeof tool.schema.name === "string"
152-
) {
153-
return tool.schema.name;
154-
}
155-
156-
return "";
141+
input: convertMessagesToResponsesInput({
142+
messages: [
143+
...(systemMessage.text === "" ? [] : [systemMessage]),
144+
...messages,
145+
] as any[],
146+
zdrEnabled: model.zdrEnabled ?? false,
147+
model: model.model,
148+
}),
149+
...model.invocationParams({
150+
...(modelSettings ?? {}),
151+
...(tools.length > 0 ? { tools } : {}),
152+
...(toolChoice !== undefined ? { tool_choice: toolChoice } : {}),
157153
}),
158-
...(modelSettings && Object.keys(modelSettings).length > 0
159-
? { modelSettings }
160-
: {}),
161154
});
162155
}
163156

@@ -356,9 +349,11 @@ export function createSequenceDebugMiddleware(
356349
name: "SequenceDebugMiddleware",
357350
async wrapModelCall(request, handler) {
358351
const prompt = stringifyPromptForDebug({
352+
model: request.model as unknown as OpenAiResponsesDebugModel,
359353
systemMessage: request.systemMessage,
360354
messages: request.messages,
361355
tools: request.tools,
356+
toolChoice: request.toolChoice,
362357
modelSettings: request.modelSettings,
363358
});
364359

agent/simpleAgent.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ export function createAgentChatModel(params: {
187187
maxTokens: params.maxTokens,
188188
useResponsesApi: true,
189189
outputVersion: "v1",
190-
190+
streaming: true,
191191
promptCacheKey: `adminforth-agent:${model}:system-v1:tools-v1`,
192192

193193
promptCacheRetention: "in_memory",

agent/toolCallEvents.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,46 @@ export type ToolCallEvent =
2020

2121
export type ToolCallEventSink = (event: ToolCallEvent) => void;
2222

23+
const TOOL_MESSAGE_DEBUG_KEYS = new Set([
24+
"metadata",
25+
"additional_kwargs",
26+
"response_metadata",
27+
]);
28+
29+
function getToolCallDebugPayload(outputRecord: Record<string, unknown>) {
30+
const lcKwargs =
31+
typeof outputRecord.lc_kwargs === "object" && outputRecord.lc_kwargs !== null
32+
? outputRecord.lc_kwargs as Record<string, unknown>
33+
: null;
34+
35+
if (lcKwargs && "tool_call_id" in lcKwargs) {
36+
return lcKwargs;
37+
}
38+
39+
if ("tool_call_id" in outputRecord) {
40+
return outputRecord;
41+
}
42+
43+
return null;
44+
}
45+
46+
function sanitizeToolCallOutputForDebug(output: unknown) {
47+
if (typeof output !== "object" || output === null) {
48+
return output;
49+
}
50+
51+
const outputRecord = output as Record<string, unknown>;
52+
const debugPayload = getToolCallDebugPayload(outputRecord);
53+
54+
if (!debugPayload) {
55+
return output;
56+
}
57+
58+
return Object.fromEntries(
59+
Object.entries(debugPayload).filter(([key]) => !TOOL_MESSAGE_DEBUG_KEYS.has(key)),
60+
);
61+
}
62+
2363
export function createToolCallTracker(params: {
2464
emit: ToolCallEventSink;
2565
toolCallId?: string;
@@ -45,7 +85,7 @@ export function createToolCallTracker(params: {
4585
toolName: params.toolName,
4686
phase: "end",
4787
durationMs: Date.now() - startedAt,
48-
output: YAML.stringify(output).trimEnd(),
88+
output: YAML.stringify(sanitizeToolCallOutputForDebug(output)).trimEnd(),
4989
error: null,
5090
});
5191
},

0 commit comments

Comments
 (0)