@oh-my-pi/omp-stats 16.1.13 → 16.1.15
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.
- package/CHANGELOG.md +6 -0
- package/dist/client/index.js +96 -96
- package/dist/client/styles.css +51 -0
- package/dist/types/aggregator.d.ts +1 -1
- package/dist/types/client/components/AgentTokenShare.d.ts +5 -0
- package/dist/types/client/data/view-models.d.ts +23 -1
- package/dist/types/client/types.d.ts +2 -1
- package/dist/types/db.d.ts +7 -1
- package/dist/types/parser.d.ts +11 -1
- package/dist/types/shared-types.d.ts +28 -0
- package/dist/types/types.d.ts +3 -0
- package/package.json +4 -4
- package/src/aggregator.ts +6 -1
- package/src/client/components/AgentTokenShare.tsx +68 -0
- package/src/client/data/view-models.ts +55 -0
- package/src/client/routes/OverviewRoute.tsx +10 -0
- package/src/client/types.ts +2 -0
- package/src/db.ts +101 -2
- package/src/parser.ts +24 -1
- package/src/shared-types.ts +30 -0
- package/src/types.ts +3 -0
package/src/parser.ts
CHANGED
|
@@ -3,6 +3,7 @@ import * as path from "node:path";
|
|
|
3
3
|
import { type AssistantMessage, getPriorityPremiumRequests, type ServiceTier } from "@oh-my-pi/pi-ai";
|
|
4
4
|
import { getSessionsDir, isEnoent } from "@oh-my-pi/pi-utils";
|
|
5
5
|
import type {
|
|
6
|
+
AgentType,
|
|
6
7
|
MessageStats,
|
|
7
8
|
SessionEntry,
|
|
8
9
|
SessionMessageEntry,
|
|
@@ -12,6 +13,25 @@ import type {
|
|
|
12
13
|
} from "./types";
|
|
13
14
|
import { computeUserMessageMetrics } from "./user-metrics";
|
|
14
15
|
|
|
16
|
+
/** Basename of an advisor agent's transcript inside a session artifacts dir. */
|
|
17
|
+
const ADVISOR_TRANSCRIPT_BASENAME = "__advisor.jsonl";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Classify which agent produced a transcript from its path within the sessions
|
|
21
|
+
* directory. Layout: `<sessionsDir>/<project>/<file>.jsonl` is the `main`
|
|
22
|
+
* agent; subagent and advisor transcripts live nested one level deeper inside
|
|
23
|
+
* the session's artifacts dir (`<project>/<session>/<id>.jsonl`,
|
|
24
|
+
* `<project>/<session>/__advisor.jsonl`). Any `__advisor.jsonl` — at any depth,
|
|
25
|
+
* including a subagent's own advisor — counts as `advisor`; every other nested
|
|
26
|
+
* transcript is a task `subagent`.
|
|
27
|
+
*/
|
|
28
|
+
export function classifyAgentType(sessionPath: string): AgentType {
|
|
29
|
+
if (path.basename(sessionPath) === ADVISOR_TRANSCRIPT_BASENAME) return "advisor";
|
|
30
|
+
const rel = path.relative(getSessionsDir(), sessionPath);
|
|
31
|
+
// `<project>/<file>.jsonl` -> 2 segments. Deeper nesting is a subagent.
|
|
32
|
+
return rel.split(path.sep).length <= 2 ? "main" : "subagent";
|
|
33
|
+
}
|
|
34
|
+
|
|
15
35
|
/**
|
|
16
36
|
* Extract folder name from session filename.
|
|
17
37
|
* Session files are named like: --work--pi--/timestamp_uuid.jsonl
|
|
@@ -107,6 +127,7 @@ function extractStats(
|
|
|
107
127
|
folder: string,
|
|
108
128
|
entry: SessionMessageEntry,
|
|
109
129
|
currentServiceTier: ServiceTier | undefined,
|
|
130
|
+
agentType: AgentType,
|
|
110
131
|
): MessageStats | null {
|
|
111
132
|
const msg = entry.message as AssistantMessage;
|
|
112
133
|
if (msg?.role !== "assistant") return null;
|
|
@@ -134,6 +155,7 @@ function extractStats(
|
|
|
134
155
|
stopReason: msg.stopReason,
|
|
135
156
|
errorMessage: msg.errorMessage ?? null,
|
|
136
157
|
usage,
|
|
158
|
+
agentType,
|
|
137
159
|
};
|
|
138
160
|
}
|
|
139
161
|
|
|
@@ -220,6 +242,7 @@ export async function parseSessionFile(sessionPath: string, fromOffset = 0): Pro
|
|
|
220
242
|
}
|
|
221
243
|
|
|
222
244
|
const folder = extractFolderFromPath(sessionPath);
|
|
245
|
+
const agentType = classifyAgentType(sessionPath);
|
|
223
246
|
const stats: MessageStats[] = [];
|
|
224
247
|
const userStats: UserMessageStats[] = [];
|
|
225
248
|
const userLinks: UserMessageLink[] = [];
|
|
@@ -245,7 +268,7 @@ export async function parseSessionFile(sessionPath: string, fromOffset = 0): Pro
|
|
|
245
268
|
continue;
|
|
246
269
|
}
|
|
247
270
|
if (isAssistantMessage(entry)) {
|
|
248
|
-
const msgStats = extractStats(sessionPath, folder, entry, currentServiceTier);
|
|
271
|
+
const msgStats = extractStats(sessionPath, folder, entry, currentServiceTier, agentType);
|
|
249
272
|
if (msgStats) stats.push(msgStats);
|
|
250
273
|
// Link assistant's responding model back to the user message it answered.
|
|
251
274
|
const parentId = (entry as SessionMessageEntry).parentId;
|
package/src/shared-types.ts
CHANGED
|
@@ -133,12 +133,42 @@ export interface DashboardStats {
|
|
|
133
133
|
overall: AggregatedStats;
|
|
134
134
|
byModel: ModelStats[];
|
|
135
135
|
byFolder: FolderStats[];
|
|
136
|
+
byAgentType: AgentTypeStats[];
|
|
136
137
|
timeSeries: TimeSeriesPoint[];
|
|
137
138
|
modelSeries: ModelTimeSeriesPoint[];
|
|
138
139
|
modelPerformanceSeries: ModelPerformancePoint[];
|
|
139
140
|
costSeries: CostTimeSeriesPoint[];
|
|
140
141
|
}
|
|
141
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Which agent produced a message, derived from its transcript file location
|
|
145
|
+
* inside the session directory: the top-level `<project>/<file>.jsonl` is the
|
|
146
|
+
* `main` agent, an `__advisor.jsonl` is the passive `advisor`, and any other
|
|
147
|
+
* nested transcript is a task `subagent`.
|
|
148
|
+
*/
|
|
149
|
+
export type AgentType = "main" | "subagent" | "advisor";
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Token usage aggregated by {@link AgentType} over the active range. Token
|
|
153
|
+
* columns are explicit so the dashboard's share denominator matches the
|
|
154
|
+
* counts it renders (input + output + cache read + cache write).
|
|
155
|
+
*/
|
|
156
|
+
export interface AgentTypeStats {
|
|
157
|
+
agentType: AgentType;
|
|
158
|
+
/** Total number of requests */
|
|
159
|
+
totalRequests: number;
|
|
160
|
+
/** Total input tokens */
|
|
161
|
+
totalInputTokens: number;
|
|
162
|
+
/** Total output tokens */
|
|
163
|
+
totalOutputTokens: number;
|
|
164
|
+
/** Total cache read tokens */
|
|
165
|
+
totalCacheReadTokens: number;
|
|
166
|
+
/** Total cache write tokens */
|
|
167
|
+
totalCacheWriteTokens: number;
|
|
168
|
+
/** Total cost */
|
|
169
|
+
totalCost: number;
|
|
170
|
+
}
|
|
171
|
+
|
|
142
172
|
/**
|
|
143
173
|
* Behavior time-series point (daily bucket, per responding model).
|
|
144
174
|
*/
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AssistantMessage, ServiceTier, StopReason, Usage } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { AgentType } from "./shared-types";
|
|
2
3
|
|
|
3
4
|
export * from "./shared-types";
|
|
4
5
|
|
|
@@ -32,6 +33,8 @@ export interface MessageStats {
|
|
|
32
33
|
errorMessage: string | null;
|
|
33
34
|
/** Token usage */
|
|
34
35
|
usage: Usage;
|
|
36
|
+
/** Which agent produced this message (main agent, task subagent, advisor) */
|
|
37
|
+
agentType: AgentType;
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
/**
|