forked from EduCraft/curriculum-project-hub
feat: add agent cost reporting
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
export function formatRunCostLine(costUsd: number | undefined): string {
|
||||
return costUsd === undefined
|
||||
? "本次成本: 未记录"
|
||||
: `本次成本: ${formatUsd(costUsd)}`;
|
||||
}
|
||||
|
||||
export function formatInteger(value: number): string {
|
||||
return new Intl.NumberFormat("en-US").format(value);
|
||||
}
|
||||
|
||||
export function formatUsd(value: number): string {
|
||||
const digits = value > 0 && value < 0.01 ? 4 : 2;
|
||||
return `$${value.toFixed(digits)}`;
|
||||
}
|
||||
|
||||
export function decimalToNumberOrNull(value: unknown): number | null {
|
||||
if (value === null || value === undefined) return null;
|
||||
const numberValue = typeof value === "number" ? value : Number(value);
|
||||
if (!Number.isFinite(numberValue)) {
|
||||
throw new Error("invalid cost value");
|
||||
}
|
||||
return numberValue;
|
||||
}
|
||||
@@ -73,6 +73,8 @@ export interface RunResult {
|
||||
readonly status: RunStatus;
|
||||
readonly text: string;
|
||||
readonly usage: { inputTokens: number; outputTokens: number };
|
||||
/** Provider- or gateway-reported cost for this run, in USD. */
|
||||
readonly costUsd?: number | undefined;
|
||||
readonly numTurns: number;
|
||||
readonly sdkSessionId?: string | undefined;
|
||||
readonly error?: string;
|
||||
@@ -123,6 +125,7 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
|
||||
|
||||
let fullText = "";
|
||||
let usage = { inputTokens: 0, outputTokens: 0 };
|
||||
let costUsd: number | undefined;
|
||||
let numTurns = 0;
|
||||
let sdkSessionId: string | undefined;
|
||||
let error: string | undefined;
|
||||
@@ -248,6 +251,7 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
|
||||
case "result": {
|
||||
const result = message as SDKResultMessage;
|
||||
sdkSessionId = result.session_id;
|
||||
costUsd = Number.isFinite(result.total_cost_usd) ? result.total_cost_usd : undefined;
|
||||
if (result.subtype !== "success") {
|
||||
error = `result_${result.subtype}`;
|
||||
}
|
||||
@@ -261,6 +265,7 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
|
||||
status: error !== undefined ? "failed" : "completed",
|
||||
text: fullText,
|
||||
usage,
|
||||
...(costUsd !== undefined ? { costUsd } : {}),
|
||||
numTurns,
|
||||
sdkSessionId,
|
||||
...(error !== undefined ? { error } : {}),
|
||||
@@ -271,6 +276,7 @@ export async function runAgent(req: RunRequest): Promise<RunResult> {
|
||||
status: aborted ? "interrupted" : "failed",
|
||||
text: fullText,
|
||||
usage,
|
||||
...(costUsd !== undefined ? { costUsd } : {}),
|
||||
numTurns,
|
||||
sdkSessionId,
|
||||
...(aborted ? {} : { error: e instanceof Error ? e.message : String(e) }),
|
||||
|
||||
Reference in New Issue
Block a user