/** * ollama_log_stats — F4. Aggregate the NDJSON receipts into measured * economics (no-LLM, no egress). * * Every envelope already logs tokens_in/out, elapsed_ms, tier, and (since * v2.7.0) backend/degraded provenance — but the only consumer was * ollama_log_tail (raw events). Nobody could answer "cloud vs local * split", "fallback rate", "tokens this week", "p95 per tool" without jq. * This tool is the aggregation the "measured economics" tagline promises. * * Shape discipline mirrors logTail: read the whole NDJSON, JSON.parse per * line, tolerate a torn tail line (append-only log during a concurrent * write), treat a missing file as soft-empty (zeros, log_present:false). * Aggption is coerce-before-trust: a call event with a malformed envelope * still counts as a call (honest volume) but contributes 0 tokens and no * elapsed sample — sums can never go NaN from one bad line. * * Percentiles are nearest-rank (sorted[ceil(p·N)−1]) — exact for small N, * no interpolation to explain in receipts. */ import { z } from "zod"; import type { Envelope } from "../envelope.js"; import type { RunContext } from "../runContext.js"; export declare const logStatsSchema: z.ZodObject<{ since: z.ZodOptional; }, z.core.$strip>; export type LogStatsInput = z.infer; export interface ToolStats { calls: number; tokens_in: number; tokens_out: number; /** Calls this tool served from cloud. */ cloud_calls: number; /** Calls that WANTED cloud but were served local (degraded). */ degraded_calls: number; /** Nearest-rank percentiles over this tool's elapsed_ms samples. Null when no samples. */ p50_elapsed_ms: number | null; p95_elapsed_ms: number | null; } export interface LogStatsResult { log_path: string; log_present: boolean; /** Echo of the caller's window start (null = whole log). */ since: string | null; /** Parsed event lines examined after the since filter (all kinds). */ events_scanned: number; totals: { calls: number; tokens_in: number; tokens_out: number; }; by_tool: Record; by_tier: Record; backend: { /** Calls served by cloud (envelope backend:'cloud'). */ cloud_calls: number; /** Calls explicitly served local WITHOUT degradation (standby default / backend:'local' pins). */ local_calls: number; /** Calls that wanted cloud but were served local (envelope degraded:true). */ degraded_calls: number; /** Calls with no backend field at all (local-only mode, pre-cloud receipts). */ unrouted_calls: number; /** Raw backend_fallback events in the window (corroborates degraded_calls). */ backend_fallback_events: number; /** * degraded / (cloud + degraded) — the fraction of cloud-INTENDED calls * that fell back to local. Null when no call in the window intended * cloud (rate over zero intent would be noise, not signal). */ fallback_rate: number | null; }; /** TIER degradation events (orthogonal to backend fallback — see routing.ts). */ tier_events: { timeouts: number; fallbacks: number; }; /** Nearest-rank percentiles over ALL call elapsed_ms samples. Null when no samples. */ elapsed_ms: { p50: number | null; p95: number | null; }; } export declare function handleLogStats(input: LogStatsInput, ctx: RunContext): Promise>; //# sourceMappingURL=logStats.d.ts.map