@linxiraos/pi-stats 1.1.0 → 1.1.2

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.
Files changed (67) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +3 -3
  3. package/THIRD-PARTY-NOTICES.txt +22909 -0
  4. package/dist/client/index.css +1 -0
  5. package/dist/client/index.html +24 -0
  6. package/dist/client/index.js +257 -0
  7. package/dist/client/styles.css +1692 -0
  8. package/dist/types/aggregator.d.ts +103 -0
  9. package/dist/types/client/App.d.ts +1 -0
  10. package/dist/types/client/api.d.ts +22 -0
  11. package/dist/types/client/app/AppLayout.d.ts +16 -0
  12. package/dist/types/client/app/NavRail.d.ts +7 -0
  13. package/dist/types/client/app/RangeControl.d.ts +7 -0
  14. package/dist/types/client/app/SyncButton.d.ts +14 -0
  15. package/dist/types/client/app/ThemeToggle.d.ts +1 -0
  16. package/dist/types/client/app/TopBar.d.ts +15 -0
  17. package/dist/types/client/app/routes.d.ts +12 -0
  18. package/dist/types/client/components/AgentTokenShare.d.ts +5 -0
  19. package/dist/types/client/components/chart-shared.d.ts +173 -0
  20. package/dist/types/client/components/models-table-shared.d.ts +175 -0
  21. package/dist/types/client/components/range-meta.d.ts +21 -0
  22. package/dist/types/client/data/charts.d.ts +1 -0
  23. package/dist/types/client/data/formatters.d.ts +13 -0
  24. package/dist/types/client/data/useHashRoute.d.ts +8 -0
  25. package/dist/types/client/data/useResource.d.ts +13 -0
  26. package/dist/types/client/data/view-models.d.ts +75 -0
  27. package/dist/types/client/index.d.ts +2 -0
  28. package/dist/types/client/routes/BehaviorRoute.d.ts +7 -0
  29. package/dist/types/client/routes/CostsRoute.d.ts +7 -0
  30. package/dist/types/client/routes/ErrorsRoute.d.ts +8 -0
  31. package/dist/types/client/routes/GainRoute.d.ts +7 -0
  32. package/dist/types/client/routes/ModelsRoute.d.ts +7 -0
  33. package/dist/types/client/routes/OverviewRoute.d.ts +8 -0
  34. package/dist/types/client/routes/ProjectsRoute.d.ts +7 -0
  35. package/dist/types/client/routes/ProvidersRoute.d.ts +7 -0
  36. package/dist/types/client/routes/RequestsRoute.d.ts +8 -0
  37. package/dist/types/client/routes/ToolsRoute.d.ts +7 -0
  38. package/dist/types/client/routes/index.d.ts +10 -0
  39. package/dist/types/client/types.d.ts +63 -0
  40. package/dist/types/client/ui/AsyncBoundary.d.ts +12 -0
  41. package/dist/types/client/ui/DataTable.d.ts +17 -0
  42. package/dist/types/client/ui/EmptyState.d.ts +7 -0
  43. package/dist/types/client/ui/ErrorState.d.ts +6 -0
  44. package/dist/types/client/ui/JsonBlock.d.ts +7 -0
  45. package/dist/types/client/ui/MetricCluster.d.ts +5 -0
  46. package/dist/types/client/ui/Panel.d.ts +7 -0
  47. package/dist/types/client/ui/RequestDrawer.d.ts +5 -0
  48. package/dist/types/client/ui/SegmentedControl.d.ts +12 -0
  49. package/dist/types/client/ui/Skeleton.d.ts +8 -0
  50. package/dist/types/client/ui/StatusPill.d.ts +7 -0
  51. package/dist/types/client/ui/index.d.ts +11 -0
  52. package/dist/types/client/useSystemTheme.d.ts +11 -0
  53. package/dist/types/db.d.ts +160 -0
  54. package/dist/types/embedded-client.d.ts +18 -0
  55. package/dist/types/gain-aggregator.d.ts +26 -0
  56. package/dist/types/index.d.ts +17 -0
  57. package/dist/types/parser.d.ts +53 -0
  58. package/dist/types/port-conflict.d.ts +16 -0
  59. package/dist/types/server.d.ts +14 -0
  60. package/dist/types/shared-types.d.ts +421 -0
  61. package/dist/types/sync-worker.d.ts +31 -0
  62. package/dist/types/types.d.ts +164 -0
  63. package/dist/types/usage-windows.d.ts +72 -0
  64. package/dist/types/user-metrics.d.ts +81 -0
  65. package/package.json +95 -91
  66. package/src/aggregator.ts +1 -1
  67. package/src/index.ts +0 -0
@@ -0,0 +1,72 @@
1
+ import type { ClientUsageClientSummary } from "@linxiraos/pi-ai/usage";
2
+ import type { ProviderWindowInsight, UsageWindowSeries } from "./shared-types.js";
3
+ /** Subset of a `usage_history` row consumed by the window analytics. */
4
+ export interface UsageSnapshotRow {
5
+ /** Epoch ms the report was fetched. */
6
+ recordedAt: number;
7
+ provider: string;
8
+ /** Stable credential identity key. */
9
+ accountKey: string;
10
+ email: string | null;
11
+ accountId: string | null;
12
+ limitId: string;
13
+ label: string;
14
+ windowLabel: string | null;
15
+ /** Used fraction (0..1, >1 = overage) when the provider reported one. */
16
+ usedFraction: number | null;
17
+ status: string | null;
18
+ }
19
+ /** Utilization series + derived insights for every provider window in range. */
20
+ export interface UsageWindowStats {
21
+ usageSeries: UsageWindowSeries[];
22
+ windowInsights: ProviderWindowInsight[];
23
+ }
24
+ /** Usage snapshots plus, in broker mode, fleet-wide token burn per provider. */
25
+ export interface UsageDataSnapshot {
26
+ rows: UsageSnapshotRow[];
27
+ /**
28
+ * Total tokens (input + output + cache read/write) per provider summed
29
+ * across every install reporting to the auth broker, or `null` when no
30
+ * broker is configured or no client reports exist for the range. Matches
31
+ * the fleet-wide window fractions in `rows`, unlike local message stats
32
+ * which only see this install's burn.
33
+ */
34
+ fleetTokensByProvider: Map<string, number> | null;
35
+ }
36
+ /**
37
+ * Read usage-limit snapshots recorded at or after `sinceMs`, oldest first.
38
+ * Opens the agent DB read-only; returns `[]` when the DB or table is absent.
39
+ */
40
+ export declare function readUsageSnapshots(sinceMs: number, dbPath?: string): UsageSnapshotRow[];
41
+ /**
42
+ * Fetch usage data from wherever it actually accumulates: the auth broker's
43
+ * durable history plus per-client observed-usage reports when a broker is
44
+ * configured (the broker performs every upstream usage fetch in that mode, so
45
+ * the local `usage_history` stays frozen), else the local agent DB. Broker
46
+ * errors fall back to the local read so the dashboard degrades to
47
+ * stale-but-present data instead of failing.
48
+ */
49
+ export declare function fetchUsageData(sinceMs: number): Promise<UsageDataSnapshot>;
50
+ /**
51
+ * Fold per-client provider aggregates into total tokens per provider
52
+ * (input + output + cache read/write, matching message-stat `totalTokens`).
53
+ * Returns `null` when no client reported anything, signalling "no data"
54
+ * rather than "zero burn".
55
+ */
56
+ export declare function sumFleetTokens(clients: ClientUsageClientSummary[]): Map<string, number> | null;
57
+ /**
58
+ * Derive utilization series and per-window insights from raw snapshots.
59
+ *
60
+ * Windows are grouped by `(provider, limitId)` — never by display label.
61
+ * Distinct limits can share a duration label (Anthropic's overall and
62
+ * model-scoped 7-day windows, Codex's base and Spark weeklies); merging them
63
+ * interleaves unrelated fractions per account and wildly inflates consumption.
64
+ *
65
+ * `tokensByProvider` supplies each provider's token burn over the same time
66
+ * range (fleet-wide broker client reports when available, else local message
67
+ * stats); it converts consumed window fraction into an estimated token
68
+ * capacity per window. Attribution note: tokens are per provider, not per
69
+ * account, so the estimate treats the account fleet as one pooled
70
+ * subscription — which is exactly how round-robin auth uses it.
71
+ */
72
+ export declare function computeUsageWindowStats(rows: UsageSnapshotRow[], tokensByProvider: ReadonlyMap<string, number>): UsageWindowStats;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Behavioral metrics extracted from a single user message.
3
+ *
4
+ * Pure, side-effect free. Designed for batch use during session ingestion
5
+ * and standalone testing.
6
+ */
7
+ export interface UserMessageMetrics {
8
+ /** Total characters of analyzed text. */
9
+ chars: number;
10
+ /** Whitespace-delimited word count. */
11
+ words: number;
12
+ /**
13
+ * Number of "yelling" sentences: sentences where more than half of the
14
+ * alphabetic characters are uppercase (and there are enough letters to
15
+ * make the ratio meaningful - short acronyms like "OK" don't count).
16
+ * A sentence also needs either two uppercase runs ("WHAT THE HELL") or
17
+ * one elongated run ("CMOOON") so a lone acronym/env var ("use JSON",
18
+ * "HOME=/tmp") doesn't register.
19
+ */
20
+ yelling: number;
21
+ /** Profanity hits (word-boundary, case-insensitive). */
22
+ profanity: number;
23
+ /**
24
+ * Catch-all "obviously upset" signal computed on a *prose-only* body
25
+ * (code fences, XML/HTML tags, URLs, file mentions, and quoted lines
26
+ * are stripped first; messages whose remaining prose is >=3 lines score
27
+ * zero because formatted prompts aren't tantrums).
28
+ *
29
+ * Sum of:
30
+ * - drama runs: 3+ `!` / `?` (with `1`-mishit fallout)
31
+ * - interjections, elongated where the short form is ambiguous:
32
+ * `noooo`, `ahhh`, `ugh(h)`, `argh`, `grr`, `stooop`, `whyyy`,
33
+ * `fuuu(ck)`, `wtfff`, `omggg`, `yesss`, `goddd`, `bruhh`
34
+ * - standalone `dude`
35
+ * - sad emoticons: `:(`, `;(`, `:-(((`
36
+ */
37
+ anguish: number;
38
+ /**
39
+ * Corrective negation: the user is telling us we got it wrong.
40
+ *
41
+ * Counted on the same prose-only body as {@link anguish}.
42
+ *
43
+ * - line-leading `nope` / `nah` / `nvm` / `wrong` / `incorrect`
44
+ * (word-bounded, so `now`, `nobody`, `north` don't match)
45
+ * - line-leading `no` when used as an interjection - followed by
46
+ * punctuation, end-of-text, or a discourse word (`no i meant`,
47
+ * `no, wait`). Determiner `no` (`no extensions to the page`,
48
+ * `no auto start`) doesn't count.
49
+ * - `that(?:'s)? not (what|right|it)` and `not what i (meant|asked|said|wanted)`
50
+ * - `makes (no|zero) sense`
51
+ */
52
+ negation: number;
53
+ /**
54
+ * The user is repeating themselves - strong signal the previous turn
55
+ * missed the ask. Counts hits for:
56
+ *
57
+ * - `i (meant|said|asked|told you|already (said|told|did|asked|wrote))`
58
+ * - `(like|as) i (said|told you|asked)`
59
+ * - `still (doesn't|isn't|not|broken|wrong|fails|failing|the same|same)`
60
+ *
61
+ * Bare `still` / `again` are too ambiguous to count alone (they show up
62
+ * in normal speech like "try again" or "still works").
63
+ */
64
+ repetition: number;
65
+ /**
66
+ * Direct second-person reproach pinned on the agent:
67
+ *
68
+ * - `you (didn't|did not|broke|missed|forgot|keep|always|never|still|ignored)`
69
+ * - `why (would|did) (you|u)`
70
+ * - sentence-leading `stop <verb>ing` imperatives
71
+ */
72
+ blame: number;
73
+ }
74
+ /**
75
+ * Compute behavioral metrics for a user message.
76
+ *
77
+ * `text` may be empty or whitespace; in that case every metric is 0.
78
+ */
79
+ export declare function computeUserMessageMetrics(text: string): UserMessageMetrics;
80
+ /** Empty metrics constant for callers that need a default. */
81
+ export declare const EMPTY_USER_METRICS: UserMessageMetrics;
package/package.json CHANGED
@@ -1,92 +1,96 @@
1
1
  {
2
- "type": "module",
3
- "name": "@linxiraos/pi-stats",
4
- "version": "1.1.0",
5
- "description": "Local observability dashboard for pi AI usage statistics",
6
- "homepage": "https://linxira-os.github.io/zeta/",
7
- "author": "Can Boluk",
8
- "license": "MIT",
9
- "repository": {
10
- "type": "git",
11
- "url": "git+https://github.com/Linxira-OS/linxira-zeta.git",
12
- "directory": "packages/stats"
13
- },
14
- "bugs": {
15
- "url": "https://github.com/Linxira-OS/linxira-zeta/issues"
16
- },
17
- "keywords": [
18
- "ai",
19
- "observability",
20
- "metrics",
21
- "dashboard",
22
- "llm",
23
- "statistics"
24
- ],
25
- "main": "./src/index.ts",
26
- "types": "./src/index.ts",
27
- "bin": {
28
- "omp-stats": "./src/index.ts"
29
- },
30
- "scripts": {
31
- "gen:stats": "bun scripts/generate-client-bundle.ts --generate",
32
- "gen:stats:reset": "bun scripts/generate-client-bundle.ts --reset",
33
- "build": "bun run build.ts",
34
- "dev": "bun run src/index.ts",
35
- "check": "biome check . && bun run check:types",
36
- "check:types": "tsgo -p tsconfig.json --noEmit && tsgo -p tsconfig.client.json --noEmit",
37
- "lint": "biome lint .",
38
- "fix": "biome check --write --unsafe .",
39
- "fmt": "biome format --write ."
40
- },
41
- "dependencies": {
42
- "@linxiraos/pi-ai": "catalog:",
43
- "@linxiraos/pi-catalog": "catalog:",
44
- "@linxiraos/pi-utils": "catalog:",
45
- "@tailwindcss/node": "catalog:",
46
- "chart.js": "catalog:",
47
- "lucide-react": "catalog:",
48
- "react": "catalog:",
49
- "react-chartjs-2": "catalog:",
50
- "react-dom": "catalog:",
51
- "tailwindcss": "catalog:"
52
- },
53
- "devDependencies": {
54
- "@types/bun": "catalog:",
55
- "@types/react": "catalog:",
56
- "@types/react-dom": "catalog:",
57
- "postcss": "catalog:"
58
- },
59
- "engines": {
60
- "bun": ">=1.3.14"
61
- },
62
- "files": [
63
- "src",
64
- "build.ts",
65
- "tailwind.config.js",
66
- "README.md",
67
- "CHANGELOG.md"
68
- ],
69
- "exports": {
70
- ".": {
71
- "types": "./src/index.ts",
72
- "import": "./src/index.ts"
73
- },
74
- "./*": {
75
- "types": "./src/*.ts",
76
- "import": "./src/*.ts"
77
- },
78
- "./client": {
79
- "types": "./src/client/index.tsx",
80
- "import": "./src/client/index.tsx"
81
- },
82
- "./client/*": {
83
- "types": "./src/client/*.ts",
84
- "import": "./src/client/*.ts"
85
- },
86
- "./client/components/*": {
87
- "types": "./src/client/components/*.ts",
88
- "import": "./src/client/components/*.ts"
89
- },
90
- "./*.js": "./src/*.ts"
91
- }
92
- }
2
+ "type": "module",
3
+ "name": "@linxiraos/pi-stats",
4
+ "version": "1.1.2",
5
+ "description": "Local observability dashboard for pi AI usage statistics",
6
+ "homepage": "https://linxira-os.github.io/zeta/",
7
+ "author": "Can Boluk",
8
+ "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/Linxira-OS/linxira-zeta.git",
12
+ "directory": "packages/stats"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/Linxira-OS/linxira-zeta/issues"
16
+ },
17
+ "keywords": [
18
+ "ai",
19
+ "observability",
20
+ "metrics",
21
+ "dashboard",
22
+ "llm",
23
+ "statistics"
24
+ ],
25
+ "main": "./src/index.ts",
26
+ "types": "./dist/types/index.d.ts",
27
+ "bin": {
28
+ "zeta-stats": "./src/index.ts"
29
+ },
30
+ "scripts": {
31
+ "gen:stats": "bun scripts/generate-client-bundle.ts --generate",
32
+ "gen:stats:reset": "bun scripts/generate-client-bundle.ts --reset",
33
+ "build": "bun run build.ts",
34
+ "dev": "bun run src/index.ts",
35
+ "check": "biome check . && bun run check:types",
36
+ "check:types": "tsgo -p tsconfig.json --noEmit && tsgo -p tsconfig.client.json --noEmit",
37
+ "lint": "biome lint .",
38
+ "fix": "biome check --write --unsafe .",
39
+ "fmt": "biome format --write ."
40
+ },
41
+ "dependencies": {
42
+ "@linxiraos/pi-ai": "1.1.2",
43
+ "@linxiraos/pi-catalog": "1.1.2",
44
+ "@linxiraos/pi-utils": "1.1.2",
45
+ "@tailwindcss/node": "^4.3.2",
46
+ "chart.js": "^4.5.1",
47
+ "lucide-react": "^1.24.0",
48
+ "react": "19.2.7",
49
+ "react-chartjs-2": "^5.3.1",
50
+ "react-dom": "19.2.7",
51
+ "tailwindcss": "^4.3.2"
52
+ },
53
+ "devDependencies": {
54
+ "@types/bun": "^1.3.14",
55
+ "@types/react": "^19.2.17",
56
+ "@types/react-dom": "^19.2.3",
57
+ "postcss": "^8.5.16"
58
+ },
59
+ "engines": {
60
+ "bun": ">=1.3.14"
61
+ },
62
+ "files": [
63
+ "src",
64
+ "build.ts",
65
+ "tailwind.config.js",
66
+ "README.md",
67
+ "CHANGELOG.md",
68
+ "LICENSE",
69
+ "THIRD-PARTY-NOTICES.txt",
70
+ "dist/types",
71
+ "dist/client"
72
+ ],
73
+ "exports": {
74
+ ".": {
75
+ "types": "./dist/types/index.d.ts",
76
+ "import": "./src/index.ts"
77
+ },
78
+ "./*": {
79
+ "types": "./dist/types/*.d.ts",
80
+ "import": "./src/*.ts"
81
+ },
82
+ "./client": {
83
+ "types": "./dist/types/client/index.d.ts",
84
+ "import": "./src/client/index.tsx"
85
+ },
86
+ "./client/*": {
87
+ "types": "./dist/types/client/*.d.ts",
88
+ "import": "./src/client/*.ts"
89
+ },
90
+ "./client/components/*": {
91
+ "types": "./dist/types/client/components/*.d.ts",
92
+ "import": "./src/client/components/*.ts"
93
+ },
94
+ "./*.js": "./src/*.ts"
95
+ }
96
+ }
package/src/aggregator.ts CHANGED
@@ -37,7 +37,7 @@ import { getSessionEntry, listAllSessionFiles, type ParseSessionResult, parseSes
37
37
  import type { SyncWorkerRequest, SyncWorkerResponse } from "./sync-worker";
38
38
  // Coding-agent binary/bundle workers route through the CLI entrypoint with a
39
39
  // hidden argv mode, so the compiled binary and npm bundle only need one
40
- // JavaScript entry. Standalone source `omp-stats` keeps using this package's
40
+ // JavaScript entry. Standalone source `zeta-stats` keeps using this package's
41
41
  // own sync-worker source file.
42
42
  import type {
43
43
  BehaviorDashboardStats,
package/src/index.ts CHANGED
File without changes