Fix NaN cost display and show request count in usage summary
Amolith
and
Shelley
created 1 month ago
When model cost config is zero (local/free models), the cost math
produced NaN. Now cost is only shown when it's a valid positive number.
Usage summary now includes the number of LLM requests (assistant
messages) for better observability: 'usage: N tokens across M requests'.
Co-authored-by: Shelley <shelley@exe.dev>
Change summary
src/agent/runner.ts | 4 ++++
src/cli/commands/repo.ts | 2 +-
src/cli/commands/web.ts | 2 +-
src/cli/output.ts | 18 +++++++++++++++---
4 files changed, 21 insertions(+), 5 deletions(-)
Detailed changes
@@ -16,6 +16,7 @@ export interface AgentRunOptions {
export interface AgentRunResult {
message: string;
usage?: unknown;
+ requestCount: number;
}
/**
@@ -82,8 +83,11 @@ export async function runAgent(query: string, options: AgentRunOptions): Promise
throw new AgentError("Agent returned no text response");
}
+ const requestCount = agent.state.messages.filter((msg) => msg.role === "assistant").length;
+
return {
message: text,
usage: last?.usage,
+ requestCount,
};
}
@@ -90,7 +90,7 @@ export async function runRepoCommand(options: RepoCommandOptions): Promise<void>
});
process.stdout.write(result.message + "\n");
- printUsageSummary(result.usage as any);
+ printUsageSummary(result.usage as any, result.requestCount);
} finally {
await workspace.cleanup();
}
@@ -97,7 +97,7 @@ export async function runWebCommand(options: WebCommandOptions): Promise<void> {
});
process.stdout.write(result.message + "\n");
- printUsageSummary(result.usage as any);
+ printUsageSummary(result.usage as any, result.requestCount);
} finally {
await workspace.cleanup();
}
@@ -44,10 +44,22 @@ export function createEventLogger(options: OutputOptions) {
};
}
-export function printUsageSummary(usage: { cost?: { total?: number }; totalTokens?: number; output?: number; input?: number } | undefined) {
+export function printUsageSummary(
+ usage: { cost?: { total?: number }; totalTokens?: number; output?: number; input?: number } | undefined,
+ requestCount?: number,
+) {
if (!usage) return;
- const cost = usage.cost?.total ?? 0;
const tokens = usage.totalTokens ?? (usage.output ?? 0) + (usage.input ?? 0);
- console.error(`\nusage: ${tokens} tokens, cost $${cost.toFixed(4)}`);
+ const rawCost = usage.cost?.total;
+ const cost = typeof rawCost === "number" && !isNaN(rawCost) && rawCost > 0 ? rawCost : undefined;
+
+ let line = `\nusage: ${tokens} tokens`;
+ if (requestCount !== undefined && requestCount > 0) {
+ line += ` across ${requestCount} ${requestCount === 1 ? "request" : "requests"}`;
+ }
+ if (cost !== undefined) {
+ line += `, cost $${cost.toFixed(4)}`;
+ }
+ console.error(line);
}