@linxiraos/pi-stats 1.1.22 → 1.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,12 @@ export { getGainDashboardStats } from "./gain-aggregator.js";
7
7
  export { formatStatsDashboardUrl, type StartServerOptions, startServer } from "./server.js";
8
8
  export type { GainDashboardStats, GainSource, GainSourceTotals, GainTimeSeriesPoint } from "./shared-types.js";
9
9
  export type { AggregatedStats, DashboardStats, FolderStats, MessageStats, ModelPerformancePoint, ModelStats, ModelTimeSeriesPoint, TimeSeriesPoint, ToolDashboardStats, ToolModelStats, ToolTimeSeriesPoint, ToolUsageStats, } from "./types.js";
10
- /** Parsed arguments for the standalone `omp-stats` entry point. */
10
+ /**
11
+ * Print the dashboard summary to the console. Shared by `zeta-c stats --summary`
12
+ * and the standalone `zeta-stats --sync`.
13
+ */
14
+ export declare function printStatsSummary(): Promise<void>;
15
+ /** Parsed arguments for the standalone `zeta-stats` entry point. */
11
16
  export interface StandaloneStatsArgs {
12
17
  port: number;
13
18
  host: string;
@@ -15,5 +20,5 @@ export interface StandaloneStatsArgs {
15
20
  sync: boolean;
16
21
  help: boolean;
17
22
  }
18
- /** Parse the standalone `omp-stats` arguments used by the production entry point. */
23
+ /** Parse the standalone `zeta-stats` arguments used by the production entry point. */
19
24
  export declare function parseStandaloneStatsArgs(args: string[]): StandaloneStatsArgs;
@@ -1,7 +1,7 @@
1
1
  /** Header stamped on every dashboard response so reuse probes can identify us. */
2
- export declare const STATS_DASHBOARD_HEADER = "x-omp-stats-dashboard";
2
+ export declare const STATS_DASHBOARD_HEADER = "x-zeta-stats-dashboard";
3
3
  /** Header recording the server's requested bind host so reuse cannot change its exposure scope. */
4
- export declare const STATS_DASHBOARD_HOSTNAME_HEADER = "x-omp-stats-hostname";
4
+ export declare const STATS_DASHBOARD_HOSTNAME_HEADER = "x-zeta-stats-hostname";
5
5
  /** Identity-header value for dashboards enforcing an explicit bind host and same-origin access. */
6
6
  export declare const STATS_DASHBOARD_SECURITY_VERSION = "3";
7
7
  /** IPv4 loopback address shared by the dashboard server and reuse probe. */
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@linxiraos/pi-stats",
4
- "version": "1.1.22",
5
- "description": "Local observability dashboard for omp AI usage statistics",
4
+ "version": "1.1.24",
5
+ "description": "Local observability dashboard for zeta AI usage statistics",
6
6
  "homepage": "https://linxira-os.github.io/zeta/",
7
7
  "author": "Linxira-OS",
8
8
  "license": "MIT",
@@ -39,9 +39,9 @@
39
39
  "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
40
40
  },
41
41
  "dependencies": {
42
- "@linxiraos/pi-ai": "1.1.22",
43
- "@linxiraos/pi-catalog": "1.1.22",
44
- "@linxiraos/pi-utils": "1.1.22",
42
+ "@linxiraos/pi-ai": "1.1.24",
43
+ "@linxiraos/pi-catalog": "1.1.24",
44
+ "@linxiraos/pi-utils": "1.1.24",
45
45
  "lucide-react": "^1.24.0",
46
46
  "react": "19.2.7",
47
47
  "react-dom": "19.2.7"
package/src/client/api.ts CHANGED
@@ -57,7 +57,7 @@ async function fetchJson<T>(endpoint: string, options?: RequestInit): Promise<T>
57
57
  * Spend-incurring actions carry this custom header. It forces a CORS preflight
58
58
  * the server never approves, so a cross-site page cannot trigger them.
59
59
  */
60
- const ACTION_HEADERS = { "X-Omp-Stats-Action": "1" };
60
+ const ACTION_HEADERS = { "X-Zeta-Stats-Action": "1" };
61
61
 
62
62
  export async function getOverviewStats(range: TimeRange = "24h", signal?: AbortSignal): Promise<OverviewStats> {
63
63
  return fetchJson<OverviewStats>(`${API_BASE}/stats/overview?range=${encodeURIComponent(range)}`, {
@@ -58,15 +58,25 @@ export function Shell({ section, onSectionChange, range, onRangeChange, children
58
58
  <div className="topbar-brand">
59
59
  <svg className="topbar-mark" viewBox="0 0 64 64" width="22" height="22" aria-hidden="true">
60
60
  <defs>
61
- <linearGradient id="omp-mark-grad" x1="0" y1="0" x2="1" y2="1">
61
+ <linearGradient id="zeta-mark-grad" x1="0" y1="0" x2="1" y2="1">
62
62
  <stop offset="0" stopColor="oklch(0.7 0.24 340)" />
63
63
  <stop offset=".5" stopColor="oklch(0.62 0.21 295)" />
64
64
  <stop offset="1" stopColor="oklch(0.81 0.14 200)" />
65
65
  </linearGradient>
66
66
  </defs>
67
- <path fill="url(#omp-mark-grad)" d="M10 14h44v9H43v33h-9V23h-9v22h-9V23H10z" />
67
+ <text
68
+ x="32"
69
+ y="47"
70
+ textAnchor="middle"
71
+ fontSize="52"
72
+ fontWeight="700"
73
+ fontFamily="Georgia, 'Times New Roman', serif"
74
+ fill="url(#zeta-mark-grad)"
75
+ >
76
+ ζ
77
+ </text>
68
78
  </svg>
69
- <span>omp</span>
79
+ <span>zeta</span>
70
80
  <span className="topbar-slash">/</span>
71
81
  <span className="topbar-title">stats</span>
72
82
  </div>
@@ -189,7 +189,7 @@ interface JudgePanelProps {
189
189
  }
190
190
 
191
191
  const UNAVAILABLE_HINT =
192
- "Judging needs the omp host process: open the dashboard with omp stats and configure a judge model. Until then messages are classified by regex signals.";
192
+ "Judging needs the zeta host process: open the dashboard with zeta-c stats and configure a judge model. Until then messages are classified by regex signals.";
193
193
 
194
194
  function JudgePanel({ active, range, judgeAvailable, job, onRunStarted, onRunChanged }: JudgePanelProps) {
195
195
  const [modalOpen, setModalOpen] = useState(false);
@@ -94,7 +94,10 @@ export function OverviewRoute({ active, range, onRequestClick }: OverviewRoutePr
94
94
 
95
95
  return (
96
96
  <div className="page">
97
- <PageHeader title="Overview" description={`Everything omp did across your sessions in ${meta.windowLabel}.`} />
97
+ <PageHeader
98
+ title="Overview"
99
+ description={`Everything zeta did across your sessions in ${meta.windowLabel}.`}
100
+ />
98
101
 
99
102
  <QueryView query={overview} skeleton={<ChartSkeleton height={112} />}>
100
103
  {({ overall }) => (
@@ -66,7 +66,8 @@ const TOKEN_MIX = [
66
66
  { key: "output", label: "Output", color: "var(--chart-secondary)" },
67
67
  ] as const;
68
68
 
69
- const SNAPSHOT_HINT = "Usage snapshots accumulate whenever usage limits are fetched (TUI footer, /usage, omp usage).";
69
+ const SNAPSHOT_HINT =
70
+ "Usage snapshots accumulate whenever usage limits are fetched (TUI footer, /usage, zeta-c usage).";
70
71
 
71
72
  interface WindowRef {
72
73
  provider: string;
@@ -106,7 +106,7 @@ export function RequestsRoute({ active, range, onRequestClick }: RequestsRoutePr
106
106
  <div className="page">
107
107
  <PageHeader
108
108
  title="Requests"
109
- description={`Every model call omp made in ${meta.windowLabel}, newest first. Open a row for its full payload.`}
109
+ description={`Every model call zeta made in ${meta.windowLabel}, newest first. Open a row for its full payload.`}
110
110
  />
111
111
 
112
112
  <QueryView query={log} skeleton={<Skeleton height={96} style={{ borderRadius: 12 }} />}>
@@ -73,7 +73,7 @@ export function ToolsRoute({ active, range }: ToolsRouteProps) {
73
73
  <div className="page">
74
74
  <PageHeader
75
75
  title="Tools"
76
- description={`Which tools omp called in ${meta.windowLabel}, how often they failed, and what they cost.`}
76
+ description={`Which tools zeta called in ${meta.windowLabel}, how often they failed, and what they cost.`}
77
77
  />
78
78
 
79
79
  <QueryView query={tools} skeleton={<ChartSkeleton height={112} />}>
@@ -1,5 +1,5 @@
1
1
  /* ==========================================================================
2
- omp stats — design system
2
+ zeta stats — design system
3
3
  Pure-black chassis, one inset panel, hairline edges, one accent gradient.
4
4
  Page-specific styles live next to their route (`routes/*.css`).
5
5
  ========================================================================== */
@@ -30,7 +30,7 @@
30
30
  --ink-4: #46464c;
31
31
  --ink-inverse: #0a0a0b;
32
32
 
33
- /* Accent: omp cyan → pink. Solid `--accent` for text/strokes, gradient for hero marks. */
33
+ /* Accent: zeta cyan → pink. Solid `--accent` for text/strokes, gradient for hero marks. */
34
34
  --accent-a: #5ad8e6;
35
35
  --accent-b: #ed4abf;
36
36
  --accent: #f068c8;
@@ -3,7 +3,7 @@ import { useSyncExternalStore } from "react";
3
3
  export type SystemTheme = "light" | "dark";
4
4
  export type ThemePreference = "system" | "light" | "dark";
5
5
 
6
- const STORAGE_KEY = "omp-stats-theme";
6
+ const STORAGE_KEY = "zeta-stats-theme";
7
7
  const DARK_SCHEME_QUERY = "(prefers-color-scheme: dark)";
8
8
 
9
9
  function readStoredPreference(): ThemePreference {
package/src/index.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
3
  import { parseArgs } from "node:util";
4
- import { formatDuration, formatNumber, formatPercent } from "@linxiraos/pi-utils";
4
+ import { formatDuration, formatNumber, formatPercent, normalizePremiumRequests } from "@linxiraos/pi-utils";
5
+ import chalk from "@linxiraos/pi-utils/chalk";
5
6
  import { getDashboardStats, getTotalMessageCount, syncAllSessions } from "./aggregator";
6
7
  import { closeDb } from "./db";
7
8
  import { refreshRollups } from "./rollup";
@@ -45,20 +46,17 @@ function formatCost(n: number, unpricedRequests = 0): string {
45
46
  return `$${n.toFixed(2)}`;
46
47
  }
47
48
 
48
- function normalizePremiumRequests(n: number): number {
49
- return Math.round((n + Number.EPSILON) * 100) / 100;
50
- }
51
-
52
49
  /**
53
- * Print stats summary to console.
50
+ * Print the dashboard summary to the console. Shared by `zeta-c stats --summary`
51
+ * and the standalone `zeta-stats --sync`.
54
52
  */
55
- async function printStats(): Promise<void> {
53
+ export async function printStatsSummary(): Promise<void> {
56
54
  const stats = await getDashboardStats();
57
55
  const { overall, byModel, byFolder } = stats;
58
56
 
59
- console.log("\n=== AI Usage Statistics ===\n");
57
+ console.log(chalk.bold("\n=== AI Usage Statistics ===\n"));
60
58
 
61
- console.log("Overall:");
59
+ console.log(chalk.bold("Overall:"));
62
60
  console.log(` Requests: ${formatNumber(overall.totalRequests)} (${formatNumber(overall.failedRequests)} errors)`);
63
61
  console.log(` Error Rate: ${formatPercent(overall.errorRate)}`);
64
62
  console.log(` Total Tokens: ${formatNumber(overall.totalInputTokens + overall.totalOutputTokens)}`);
@@ -75,7 +73,7 @@ async function printStats(): Promise<void> {
75
73
  }
76
74
 
77
75
  if (byModel.length > 0) {
78
- console.log("\nBy Model (API-equivalent estimates):");
76
+ console.log(chalk.bold("\nBy Model (API-equivalent estimates):"));
79
77
  for (const m of byModel.slice(0, 10)) {
80
78
  console.log(
81
79
  ` ${m.model}: ${formatNumber(m.totalRequests)} reqs, ${formatCost(m.totalCost, m.unpricedRequests)}, ${formatPercent(m.cacheRate)} cache rate, ${formatPercent(m.cacheSavings)} cache savings`,
@@ -84,7 +82,7 @@ async function printStats(): Promise<void> {
84
82
  }
85
83
 
86
84
  if (byFolder.length > 0) {
87
- console.log("\nBy Folder (API-equivalent estimates):");
85
+ console.log(chalk.bold("\nBy Folder (API-equivalent estimates):"));
88
86
  for (const f of byFolder.slice(0, 10)) {
89
87
  console.log(
90
88
  ` ${f.folder}: ${formatNumber(f.totalRequests)} reqs, ${formatCost(f.totalCost, f.unpricedRequests)}`,
@@ -95,7 +93,7 @@ async function printStats(): Promise<void> {
95
93
  console.log("");
96
94
  }
97
95
 
98
- /** Parsed arguments for the standalone `omp-stats` entry point. */
96
+ /** Parsed arguments for the standalone `zeta-stats` entry point. */
99
97
  export interface StandaloneStatsArgs {
100
98
  port: number;
101
99
  host: string;
@@ -104,7 +102,7 @@ export interface StandaloneStatsArgs {
104
102
  help: boolean;
105
103
  }
106
104
 
107
- /** Parse the standalone `omp-stats` arguments used by the production entry point. */
105
+ /** Parse the standalone `zeta-stats` arguments used by the production entry point. */
108
106
  export function parseStandaloneStatsArgs(args: string[]): StandaloneStatsArgs {
109
107
  const { values } = parseArgs({
110
108
  args,
@@ -134,10 +132,10 @@ async function main(): Promise<void> {
134
132
 
135
133
  if (values.help) {
136
134
  console.log(`
137
- omp-stats - AI Usage Statistics Dashboard
135
+ zeta-stats - AI Usage Statistics Dashboard
138
136
 
139
137
  Usage:
140
- omp-stats [options]
138
+ zeta-stats [options]
141
139
 
142
140
  Options:
143
141
  -p, --port <port> Port for the dashboard server (default: 3847)
@@ -147,10 +145,10 @@ Options:
147
145
  -h, --help Show this help message
148
146
 
149
147
  Examples:
150
- omp-stats # Start dashboard server
151
- omp-stats --json # Print stats as JSON
152
- omp-stats --host 0.0.0.0 # Explicitly expose on all IPv4 interfaces
153
- omp-stats --sync # Sync and show summary
148
+ zeta-stats # Start dashboard server
149
+ zeta-stats --json # Print stats as JSON
150
+ zeta-stats --host 0.0.0.0 # Explicitly expose on all IPv4 interfaces
151
+ zeta-stats --sync # Sync and show summary
154
152
  `);
155
153
  return;
156
154
  }
@@ -199,7 +197,7 @@ Examples:
199
197
  if (values.json) {
200
198
  console.log(JSON.stringify(await getDashboardStats(), null, 2));
201
199
  } else {
202
- await printStats();
200
+ await printStatsSummary();
203
201
  }
204
202
  } catch (error) {
205
203
  console.error("Error:", error);
@@ -7,7 +7,18 @@ import { $ } from "bun";
7
7
  const STATS_PROBE_TIMEOUT_MS = 500;
8
8
  const PROCESS_EXIT_POLL_MS = 50;
9
9
  const PROCESS_EXIT_POLLS = 10;
10
- const STATS_RUNTIME_IMAGES: Record<string, true> = { bun: true, node: true, omp: true, "omp-stats": true };
10
+ const STATS_RUNTIME_IMAGES: Record<string, true> = {
11
+ bun: true,
12
+ node: true,
13
+ // Zeta runtime images: the compiled CLI and the standalone npm bin.
14
+ "zeta-c": true,
15
+ "zeta-cli": true,
16
+ zetacode: true,
17
+ "zeta-stats": true,
18
+ // Upstream OMP images kept so a leftover upstream dashboard is still reclaimable.
19
+ omp: true,
20
+ "omp-stats": true,
21
+ };
11
22
 
12
23
  interface PortHolder {
13
24
  pid: number;
@@ -16,9 +27,9 @@ interface PortHolder {
16
27
  }
17
28
 
18
29
  /** Header stamped on every dashboard response so reuse probes can identify us. */
19
- export const STATS_DASHBOARD_HEADER = "x-omp-stats-dashboard";
30
+ export const STATS_DASHBOARD_HEADER = "x-zeta-stats-dashboard";
20
31
  /** Header recording the server's requested bind host so reuse cannot change its exposure scope. */
21
- export const STATS_DASHBOARD_HOSTNAME_HEADER = "x-omp-stats-hostname";
32
+ export const STATS_DASHBOARD_HOSTNAME_HEADER = "x-zeta-stats-hostname";
22
33
 
23
34
  /** Identity-header value for dashboards enforcing an explicit bind host and same-origin access. */
24
35
  export const STATS_DASHBOARD_SECURITY_VERSION = "3";
@@ -242,14 +253,19 @@ async function reclaimStatsPort(port: number, hasDashboardIdentity = false): Pro
242
253
  .replace(/ \(deleted\)$/, "");
243
254
  const normalizedCommand = holder.commandLine.toLowerCase().replaceAll("\\", "/");
244
255
  const hasStatsIdentity =
256
+ normalizedImage === "zeta-stats" ||
245
257
  normalizedImage === "omp-stats" ||
246
- /(?:^|[/"'\s])omp-stats(?:\.exe)?(?:["'\s]|$)/.test(normalizedCommand) ||
258
+ /(?:^|[/"'\s])(?:zeta|omp)-stats(?:\.exe)?(?:["'\s]|$)/.test(normalizedCommand) ||
247
259
  /\/packages\/stats\/src\/index\.ts(?:["'\s]|$)/.test(normalizedCommand) ||
248
- (normalizedImage === "omp" && /(?:^|\s)stats(?:\s|$)/.test(normalizedCommand)) ||
249
- /(?:^|\/)omp(?:\.exe)?["'\s]+stats(?:["'\s]|$)/.test(normalizedCommand);
260
+ ((normalizedImage === "zeta-c" ||
261
+ normalizedImage === "zeta-cli" ||
262
+ normalizedImage === "zetacode" ||
263
+ normalizedImage === "omp") &&
264
+ /(?:^|\s)stats(?:\s|$)/.test(normalizedCommand)) ||
265
+ /(?:^|\/)(?:zeta-c|zeta-cli|zetacode|omp)(?:\.exe)?["'\s]+stats(?:["'\s]|$)/.test(normalizedCommand);
250
266
  if (!STATS_RUNTIME_IMAGES[normalizedImage] || (!hasStatsIdentity && !hasDashboardIdentity)) {
251
267
  throw new Error(
252
- `Port ${port} is in use by ${holder.image} (PID ${holder.pid}), which is not identifiable as an omp stats dashboard; refusing to stop it.`,
268
+ `Port ${port} is in use by ${holder.image} (PID ${holder.pid}), which is not identifiable as a zeta stats dashboard; refusing to stop it.`,
253
269
  );
254
270
  }
255
271
 
package/src/server.ts CHANGED
@@ -69,7 +69,7 @@ async function getEmbeddedClientFiles(): Promise<Map<string, Blob>> {
69
69
 
70
70
  if (!EMBEDDED_CLIENT_ARCHIVE) {
71
71
  throw new Error(
72
- "Embedded stats client bundle missing. Rebuild the omp binary or npm bundle with embedded stats assets.",
72
+ "Embedded stats client bundle missing. Rebuild the zeta binary or npm bundle with embedded stats assets.",
73
73
  );
74
74
  }
75
75
 
@@ -157,7 +157,7 @@ const ensureClientBuild = async () => {
157
157
  * preflight, which this server never approves, so a hostile page cannot
158
158
  * trigger a paid judge run through a cross-site form or `fetch`.
159
159
  */
160
- const STATS_ACTION_HEADER = "X-Omp-Stats-Action";
160
+ const STATS_ACTION_HEADER = "X-Zeta-Stats-Action";
161
161
 
162
162
  /**
163
163
  * Handle API requests.