fix: avoid logging stale anthropic usage (#1501) (thanks @parubets)
This commit is contained in:
parent
e85abaca2b
commit
012a83cdb2
@ -76,6 +76,43 @@ describe("createAnthropicPayloadLogger", () => {
|
|||||||
expect(event.usage).toEqual({ input: 12 });
|
expect(event.usage).toEqual({ input: 12 });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("skips usage when no new assistant message was added", () => {
|
||||||
|
const lines: string[] = [];
|
||||||
|
const logger = createAnthropicPayloadLogger({
|
||||||
|
cfg: {
|
||||||
|
diagnostics: {
|
||||||
|
anthropicPayloadLog: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
env: {},
|
||||||
|
modelApi: "anthropic-messages",
|
||||||
|
writer: {
|
||||||
|
filePath: "memory",
|
||||||
|
write: (line) => lines.push(line),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
logger?.recordUsage(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
role: "assistant",
|
||||||
|
usage: {
|
||||||
|
input: 1,
|
||||||
|
},
|
||||||
|
} as unknown as {
|
||||||
|
role: string;
|
||||||
|
usage: { input: number };
|
||||||
|
},
|
||||||
|
],
|
||||||
|
undefined,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(lines.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
it("records request payloads and forwards onPayload", async () => {
|
it("records request payloads and forwards onPayload", async () => {
|
||||||
const lines: string[] = [];
|
const lines: string[] = [];
|
||||||
let forwarded: unknown;
|
let forwarded: unknown;
|
||||||
|
|||||||
@ -110,8 +110,12 @@ function isAnthropicModel(model: Model<Api> | undefined | null): boolean {
|
|||||||
return (model as { api?: unknown })?.api === "anthropic-messages";
|
return (model as { api?: unknown })?.api === "anthropic-messages";
|
||||||
}
|
}
|
||||||
|
|
||||||
function findLastAssistantUsage(messages: AgentMessage[]): Record<string, unknown> | null {
|
function findLastAssistantUsage(
|
||||||
|
messages: AgentMessage[],
|
||||||
|
minIndex = 0,
|
||||||
|
): Record<string, unknown> | null {
|
||||||
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
||||||
|
if (i < minIndex) break;
|
||||||
const msg = messages[i] as { role?: unknown; usage?: unknown };
|
const msg = messages[i] as { role?: unknown; usage?: unknown };
|
||||||
if (msg?.role === "assistant" && msg.usage && typeof msg.usage === "object") {
|
if (msg?.role === "assistant" && msg.usage && typeof msg.usage === "object") {
|
||||||
return msg.usage as Record<string, unknown>;
|
return msg.usage as Record<string, unknown>;
|
||||||
@ -124,7 +128,7 @@ export type AnthropicPayloadLogger = {
|
|||||||
enabled: true;
|
enabled: true;
|
||||||
filePath: string;
|
filePath: string;
|
||||||
wrapStreamFn: (streamFn: StreamFn) => StreamFn;
|
wrapStreamFn: (streamFn: StreamFn) => StreamFn;
|
||||||
recordUsage: (messages: AgentMessage[], error?: unknown) => void;
|
recordUsage: (messages: AgentMessage[], error?: unknown, baselineMessageCount?: number) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function createAnthropicPayloadLogger(params: {
|
export function createAnthropicPayloadLogger(params: {
|
||||||
@ -184,8 +188,12 @@ export function createAnthropicPayloadLogger(params: {
|
|||||||
return wrapped;
|
return wrapped;
|
||||||
};
|
};
|
||||||
|
|
||||||
const recordUsage: AnthropicPayloadLogger["recordUsage"] = (messages, error) => {
|
const recordUsage: AnthropicPayloadLogger["recordUsage"] = (
|
||||||
const usage = findLastAssistantUsage(messages);
|
messages,
|
||||||
|
error,
|
||||||
|
baselineMessageCount,
|
||||||
|
) => {
|
||||||
|
const usage = findLastAssistantUsage(messages, baselineMessageCount ?? 0);
|
||||||
if (!usage) {
|
if (!usage) {
|
||||||
if (error) {
|
if (error) {
|
||||||
record({
|
record({
|
||||||
|
|||||||
@ -643,6 +643,7 @@ export async function runEmbeddedAttempt(
|
|||||||
|
|
||||||
let messagesSnapshot: AgentMessage[] = [];
|
let messagesSnapshot: AgentMessage[] = [];
|
||||||
let sessionIdUsed = activeSession.sessionId;
|
let sessionIdUsed = activeSession.sessionId;
|
||||||
|
let promptStartMessageCount = activeSession.messages.length;
|
||||||
const onAbort = () => {
|
const onAbort = () => {
|
||||||
const reason = params.abortSignal ? getAbortReason(params.abortSignal) : undefined;
|
const reason = params.abortSignal ? getAbortReason(params.abortSignal) : undefined;
|
||||||
const timeout = reason ? isTimeoutError(reason) : false;
|
const timeout = reason ? isTimeoutError(reason) : false;
|
||||||
@ -714,6 +715,8 @@ export async function runEmbeddedAttempt(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
promptStartMessageCount = activeSession.messages.length;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Detect and load images referenced in the prompt for vision-capable models.
|
// Detect and load images referenced in the prompt for vision-capable models.
|
||||||
// This eliminates the need for an explicit "view" tool call by injecting
|
// This eliminates the need for an explicit "view" tool call by injecting
|
||||||
@ -789,7 +792,7 @@ export async function runEmbeddedAttempt(
|
|||||||
messages: messagesSnapshot,
|
messages: messagesSnapshot,
|
||||||
note: promptError ? "prompt error" : undefined,
|
note: promptError ? "prompt error" : undefined,
|
||||||
});
|
});
|
||||||
anthropicPayloadLogger?.recordUsage(messagesSnapshot, promptError);
|
anthropicPayloadLogger?.recordUsage(messagesSnapshot, promptError, promptStartMessageCount);
|
||||||
|
|
||||||
// Run agent_end hooks to allow plugins to analyze the conversation
|
// Run agent_end hooks to allow plugins to analyze the conversation
|
||||||
// This is fire-and-forget, so we don't await
|
// This is fire-and-forget, so we don't await
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user