mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:40:44 +00:00
fix(gateway): fall back to lastCallUsage on /v1/chat/completions
This commit is contained in:
committed by
Peter Steinberger
parent
139dfd97bb
commit
bad38150cb
@@ -1,7 +1,12 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import type { ImageContent } from "../agents/command/types.js";
|
||||
import { normalizeUsage, toOpenAiChatCompletionsUsage } from "../agents/usage.js";
|
||||
import {
|
||||
hasNonzeroUsage,
|
||||
normalizeUsage,
|
||||
toOpenAiChatCompletionsUsage,
|
||||
type NormalizedUsage,
|
||||
} from "../agents/usage.js";
|
||||
import { createDefaultDeps } from "../cli/deps.js";
|
||||
import { agentCommandFromIngress } from "../commands/agent.js";
|
||||
import type { GatewayHttpChatCompletionsConfig } from "../config/types.gateway.js";
|
||||
@@ -369,6 +374,7 @@ async function resolveImagesForRequest(
|
||||
export const __testOnlyOpenAiHttp = {
|
||||
resolveImagesForRequest,
|
||||
resolveOpenAiChatCompletionsLimits,
|
||||
resolveChatCompletionUsage,
|
||||
};
|
||||
|
||||
function buildAgentPrompt(
|
||||
@@ -466,16 +472,26 @@ type AgentUsageMeta = {
|
||||
total?: number;
|
||||
};
|
||||
|
||||
function resolveRawAgentUsage(result: unknown): AgentUsageMeta | undefined {
|
||||
return (
|
||||
function resolveAgentRunUsage(result: unknown): NormalizedUsage | undefined {
|
||||
const agentMeta = (
|
||||
result as {
|
||||
meta?: {
|
||||
agentMeta?: {
|
||||
usage?: AgentUsageMeta;
|
||||
lastCallUsage?: AgentUsageMeta;
|
||||
};
|
||||
};
|
||||
} | null
|
||||
)?.meta?.agentMeta?.usage;
|
||||
)?.meta?.agentMeta;
|
||||
const primary = normalizeUsage(agentMeta?.usage);
|
||||
if (hasNonzeroUsage(primary)) {
|
||||
return primary;
|
||||
}
|
||||
const fallback = normalizeUsage(agentMeta?.lastCallUsage);
|
||||
if (hasNonzeroUsage(fallback)) {
|
||||
return fallback;
|
||||
}
|
||||
return primary ?? fallback;
|
||||
}
|
||||
|
||||
function resolveChatCompletionUsage(result: unknown): {
|
||||
@@ -483,7 +499,7 @@ function resolveChatCompletionUsage(result: unknown): {
|
||||
completion_tokens: number;
|
||||
total_tokens: number;
|
||||
} {
|
||||
return toOpenAiChatCompletionsUsage(normalizeUsage(resolveRawAgentUsage(result)));
|
||||
return toOpenAiChatCompletionsUsage(resolveAgentRunUsage(result));
|
||||
}
|
||||
|
||||
function resolveIncludeUsageForStreaming(payload: OpenAiChatCompletionRequest): boolean {
|
||||
|
||||
78
src/gateway/openai-http.usage.test.ts
Normal file
78
src/gateway/openai-http.usage.test.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { __testOnlyOpenAiHttp } from "./openai-http.js";
|
||||
|
||||
const { resolveChatCompletionUsage } = __testOnlyOpenAiHttp;
|
||||
|
||||
describe("resolveChatCompletionUsage", () => {
|
||||
it("maps agentMeta.usage to OpenAI prompt/completion/total fields", () => {
|
||||
const result = {
|
||||
meta: {
|
||||
agentMeta: {
|
||||
usage: { input: 120, output: 42, cacheRead: 10, total: 172 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(resolveChatCompletionUsage(result)).toEqual({
|
||||
prompt_tokens: 130,
|
||||
completion_tokens: 42,
|
||||
total_tokens: 172,
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to agentMeta.lastCallUsage when agentMeta.usage is missing", () => {
|
||||
const result = {
|
||||
meta: {
|
||||
agentMeta: {
|
||||
lastCallUsage: { input: 80, output: 20, total: 100 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(resolveChatCompletionUsage(result)).toEqual({
|
||||
prompt_tokens: 80,
|
||||
completion_tokens: 20,
|
||||
total_tokens: 100,
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to agentMeta.lastCallUsage when agentMeta.usage is all zero", () => {
|
||||
const result = {
|
||||
meta: {
|
||||
agentMeta: {
|
||||
usage: { input: 0, output: 0, total: 0 },
|
||||
lastCallUsage: { input: 55, output: 7, total: 62 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
expect(resolveChatCompletionUsage(result)).toEqual({
|
||||
prompt_tokens: 55,
|
||||
completion_tokens: 7,
|
||||
total_tokens: 62,
|
||||
});
|
||||
});
|
||||
|
||||
it("returns zeros when both agentMeta.usage and lastCallUsage are absent", () => {
|
||||
const result = { meta: { agentMeta: {} } };
|
||||
|
||||
expect(resolveChatCompletionUsage(result)).toEqual({
|
||||
prompt_tokens: 0,
|
||||
completion_tokens: 0,
|
||||
total_tokens: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it("returns zeros when the result has no meta at all", () => {
|
||||
expect(resolveChatCompletionUsage({})).toEqual({
|
||||
prompt_tokens: 0,
|
||||
completion_tokens: 0,
|
||||
total_tokens: 0,
|
||||
});
|
||||
expect(resolveChatCompletionUsage(null)).toEqual({
|
||||
prompt_tokens: 0,
|
||||
completion_tokens: 0,
|
||||
total_tokens: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user