//#region src/stats.ts
/**
* Effective input tokens for a single `TurnUsage`-shaped record — the sum of
* `input + cacheRead + cacheCreation`, i.e. every token the model actually saw
* for that turn regardless of how it was billed. See {@link effectiveInputTokens}
* for the cumulative `AgentStats` analogue and the prompt-caching rationale.
*/
function effectiveInputFromTurn(usage) {
	if (!usage) return 0;
	return (usage.input ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheCreation ?? 0);
}
/**
* Clamp to a non-negative finite integer. Used to defend display logic
*  against providers that report `NaN`, `Infinity`, or negatives in their
*  usage payloads — the rendered string stays readable instead of leaking
*  `NaN`s into the footer / spawn-end markers.
*/
function safeNumber(n) {
	if (typeof n !== "number" || !Number.isFinite(n) || n < 0) return 0;
	return n;
}
function normalize(stats) {
	return {
		input: safeNumber(stats.totalIn),
		output: safeNumber(stats.totalOut),
		cacheRead: safeNumber(stats.totalCacheRead),
		cacheCreation: safeNumber(stats.totalCacheCreation)
	};
}
/**
* Render a one-line token summary suitable for spawn-end markers, child
* tool-result text, and any other per-run "what did this cost?" surface.
*
*   `in 52413 (cache 50000) / 4075 out`
*
* The `in` total includes cached reads and cache-creation tokens (see
* {@link effectiveInputTokens}); the `(cache N)` parenthetical breaks out
* the cached portion so the user can tell at a glance how much was reused
* vs new. The parenthetical is omitted when its value is zero, so
* non-caching providers and brand-new runs read simply as `in N / M out`.
*
* Output-side caching is not a concept any current provider exposes —
* Anthropic's `cacheRead` / `cacheCreation` are both input-billed. If a
* future provider ships an output cache, extend `TokenUsageLike` with
* output-cache fields and add a parallel `(cache N)` slot on the `out`
* side here; today the right side is always plain `${N} out`.
*/
function formatTokenUsage(stats) {
	const { input, output, cacheRead, cacheCreation } = normalize(stats);
	const inputTotal = input + cacheRead + cacheCreation;
	const inputCache = cacheRead + cacheCreation;
	return `${inputCache > 0 ? `in ${inputTotal} (cache ${inputCache})` : `in ${inputTotal}`} / ${output} out`;
}
/**
* Depth-first walk over the stats tree, returning every `TurnUsage` entry
* — parent loop first, then each child subtree in completion order.
*
* Closes the cache-token aggregation gap: `TurnUsage.cacheRead` /
* `cacheCreation` live only on per-turn entries, and the top-level
* `AgentStats` deliberately doesn't carry cumulative forms (one source of
* truth, no risk of drift). Anything that needs a tree-wide sum walks
* through this.
*/
function flattenTurns(stats) {
	const out = [];
	collectTurns(stats, out);
	return out;
}
function collectTurns(stats, out) {
	if (stats.turnUsage) out.push(...stats.turnUsage);
	if (stats.children) for (const child of stats.children) collectTurns(child.stats, out);
}
/**
* Group cumulative usage by `TurnUsage.modelId`. Each entry sums the input,
* output, cache, cost, and turn-count across every turn the tree attributed
* to that model — naturally handling cross-model runs (vision-fallback,
* model-shifted subagents, mixed-provider workflows).
*
* Turns missing `modelId` (mock providers, providers that don't echo a model
* id) are bucketed under the literal string `'(unknown)'`.
*/
function statsByModel(stats) {
	const out = /* @__PURE__ */ new Map();
	for (const turn of flattenTurns(stats)) {
		const key = turn.modelId ?? "(unknown)";
		let entry = out.get(key);
		if (!entry) {
			entry = {
				input: 0,
				output: 0,
				cost: 0,
				cacheRead: 0,
				cacheCreation: 0,
				turns: 0
			};
			out.set(key, entry);
		}
		entry.input += turn.input;
		entry.output += turn.output;
		entry.cost += turn.cost ?? 0;
		entry.cacheRead += turn.cacheRead ?? 0;
		entry.cacheCreation += turn.cacheCreation ?? 0;
		entry.turns += 1;
	}
	return out;
}
//#endregion
export { statsByModel as i, flattenTurns as n, formatTokenUsage as r, effectiveInputFromTurn as t };

//# sourceMappingURL=stats-DAKBEKjc.js.map