@guenbankhai/tools 0.0.0-stage → 0.1.0
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/README.md +53 -2
- package/README.vi.md +54 -0
- package/agentmoni/lib/agents/claude/billing.js +13 -0
- package/agentmoni/lib/agents/claude/home.js +4 -0
- package/agentmoni/lib/agents/claude/index.js +181 -0
- package/agentmoni/lib/agents/claude/sources/oauth-usage.js +74 -0
- package/agentmoni/lib/agents/claude/timeline.js +26 -0
- package/agentmoni/lib/agents/codex/billing.js +9 -0
- package/agentmoni/lib/agents/codex/index.js +280 -0
- package/agentmoni/lib/agents/codex/sources/rollout.js +26 -0
- package/agentmoni/lib/agents/codex/timeline.js +22 -0
- package/agentmoni/lib/agents/index.js +13 -0
- package/agentmoni/lib/catalog.js +96 -0
- package/agentmoni/lib/catalog.json +493 -0
- package/agentmoni/lib/collect.js +11 -0
- package/agentmoni/lib/colors.js +35 -0
- package/agentmoni/lib/cost.js +87 -0
- package/agentmoni/lib/format.js +18 -0
- package/agentmoni/lib/graph.js +106 -0
- package/agentmoni/lib/history.js +50 -0
- package/agentmoni/lib/json-fields.js +58 -0
- package/agentmoni/lib/jsonl.js +43 -0
- package/agentmoni/lib/launch.js +118 -0
- package/agentmoni/lib/limits.js +11 -0
- package/agentmoni/lib/links.js +139 -0
- package/agentmoni/lib/list.js +71 -0
- package/agentmoni/lib/log.js +226 -0
- package/agentmoni/lib/monitor.js +58 -0
- package/agentmoni/lib/page.html +591 -0
- package/agentmoni/lib/present.js +184 -0
- package/agentmoni/lib/procs.js +22 -0
- package/agentmoni/lib/quota.js +34 -0
- package/agentmoni/lib/repokey.js +44 -0
- package/agentmoni/lib/share.js +106 -0
- package/agentmoni/lib/state.js +62 -0
- package/agentmoni/lib/terminal.js +143 -0
- package/agentmoni/lib/timeline.js +40 -0
- package/agentmoni/lib/web.js +75 -0
- package/agentmoni/monitor.js +98 -0
- package/package.json +22 -4
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"contextWarn": 0.8,
|
|
4
|
+
"models": {
|
|
5
|
+
"claude-haiku-5-5": {
|
|
6
|
+
"context": 200000,
|
|
7
|
+
"weights": [
|
|
8
|
+
{
|
|
9
|
+
"value": 1,
|
|
10
|
+
"source": "community",
|
|
11
|
+
"at": "2026-10-01",
|
|
12
|
+
"validFrom": "2026-10-01"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"agent": "claude",
|
|
16
|
+
"tier": 1,
|
|
17
|
+
"color": 145,
|
|
18
|
+
"prices": [
|
|
19
|
+
{
|
|
20
|
+
"input": 0.1,
|
|
21
|
+
"cacheWrite5m": 0.125,
|
|
22
|
+
"cacheWrite1h": 0.2,
|
|
23
|
+
"cacheRead": 0.01,
|
|
24
|
+
"output": 0.5,
|
|
25
|
+
"source": "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
26
|
+
"at": "2026-11-10",
|
|
27
|
+
"validFrom": "2026-11-10",
|
|
28
|
+
"geoMultipliers": {
|
|
29
|
+
"us": 1.1,
|
|
30
|
+
"global": 1
|
|
31
|
+
},
|
|
32
|
+
"long": {
|
|
33
|
+
"above": 100000,
|
|
34
|
+
"input": 0.5,
|
|
35
|
+
"cacheWrite5m": 0.625,
|
|
36
|
+
"cacheWrite1h": 1,
|
|
37
|
+
"cacheRead": 0.05,
|
|
38
|
+
"output": 2.5
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"claude-sonnet-5-5": {
|
|
44
|
+
"context": 200000,
|
|
45
|
+
"weights": [
|
|
46
|
+
{
|
|
47
|
+
"value": 1.5,
|
|
48
|
+
"source": "community",
|
|
49
|
+
"at": "2026-10-01",
|
|
50
|
+
"validFrom": "2026-10-01"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"agent": "claude",
|
|
54
|
+
"tier": 2,
|
|
55
|
+
"color": 75,
|
|
56
|
+
"prices": [
|
|
57
|
+
{
|
|
58
|
+
"input": 2,
|
|
59
|
+
"cacheWrite5m": 2.5,
|
|
60
|
+
"cacheWrite1h": 4,
|
|
61
|
+
"cacheRead": 0.1,
|
|
62
|
+
"output": 10,
|
|
63
|
+
"source": "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
64
|
+
"at": "2026-11-10",
|
|
65
|
+
"validFrom": "2026-11-10",
|
|
66
|
+
"geoMultipliers": {
|
|
67
|
+
"us": 1.1,
|
|
68
|
+
"global": 1
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"claude-opus-5-5": {
|
|
74
|
+
"context": 200000,
|
|
75
|
+
"weights": [
|
|
76
|
+
{
|
|
77
|
+
"value": 2.2,
|
|
78
|
+
"source": "community",
|
|
79
|
+
"at": "2026-10-01",
|
|
80
|
+
"validFrom": "2026-10-01"
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"agent": "claude",
|
|
84
|
+
"tier": 3,
|
|
85
|
+
"color": 280,
|
|
86
|
+
"prices": [
|
|
87
|
+
{
|
|
88
|
+
"input": 4,
|
|
89
|
+
"cacheWrite5m": 5,
|
|
90
|
+
"cacheWrite1h": 8,
|
|
91
|
+
"cacheRead": 0.2,
|
|
92
|
+
"output": 20,
|
|
93
|
+
"source": "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
94
|
+
"at": "2026-11-10",
|
|
95
|
+
"validFrom": "2026-11-10",
|
|
96
|
+
"geoMultipliers": {
|
|
97
|
+
"us": 1.1,
|
|
98
|
+
"global": 1
|
|
99
|
+
},
|
|
100
|
+
"fastMultiplier": 2
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
"claude-fable-5-1": {
|
|
105
|
+
"context": 200000,
|
|
106
|
+
"weights": [
|
|
107
|
+
{
|
|
108
|
+
"value": 10,
|
|
109
|
+
"source": "community",
|
|
110
|
+
"at": "2026-10-01",
|
|
111
|
+
"validFrom": "2026-10-01",
|
|
112
|
+
"note": "also has its own weekly limit"
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"agent": "claude",
|
|
116
|
+
"tier": 4,
|
|
117
|
+
"color": 335,
|
|
118
|
+
"prices": [
|
|
119
|
+
{
|
|
120
|
+
"input": 10,
|
|
121
|
+
"cacheWrite5m": 12.5,
|
|
122
|
+
"cacheWrite1h": 20,
|
|
123
|
+
"cacheRead": 0.25,
|
|
124
|
+
"output": 50,
|
|
125
|
+
"source": "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
126
|
+
"at": "2026-11-10",
|
|
127
|
+
"validFrom": "2026-11-10",
|
|
128
|
+
"geoMultipliers": {
|
|
129
|
+
"us": 1.1,
|
|
130
|
+
"global": 1
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
"gpt-6-luna": {
|
|
136
|
+
"context": 400000,
|
|
137
|
+
"weights": [
|
|
138
|
+
{
|
|
139
|
+
"value": 0.05,
|
|
140
|
+
"source": "doc",
|
|
141
|
+
"at": "2026-11-07",
|
|
142
|
+
"validFrom": "2026-11-06",
|
|
143
|
+
"note": "API price ratio to Sol ($0.10 vs $2 input); subscription weight unmeasured"
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
"agent": "codex",
|
|
147
|
+
"tier": 1,
|
|
148
|
+
"color": 145,
|
|
149
|
+
"prices": [
|
|
150
|
+
{
|
|
151
|
+
"input": 0.1,
|
|
152
|
+
"cacheWrite5m": null,
|
|
153
|
+
"cacheWrite1h": null,
|
|
154
|
+
"cacheRead": 0.01,
|
|
155
|
+
"output": 0.5,
|
|
156
|
+
"source": "https://developers.openai.com/api/docs/pricing",
|
|
157
|
+
"at": "2026-11-10",
|
|
158
|
+
"validFrom": "2026-11-10",
|
|
159
|
+
"long": {
|
|
160
|
+
"above": 272000,
|
|
161
|
+
"input": 0.2,
|
|
162
|
+
"cacheWrite5m": null,
|
|
163
|
+
"cacheWrite1h": null,
|
|
164
|
+
"cacheRead": 0.02,
|
|
165
|
+
"output": 0.75
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
"gpt-6.1-sol": {
|
|
171
|
+
"context": 400000,
|
|
172
|
+
"weights": [
|
|
173
|
+
{
|
|
174
|
+
"value": 1,
|
|
175
|
+
"source": "measured",
|
|
176
|
+
"at": "2026-11-06",
|
|
177
|
+
"n": 2,
|
|
178
|
+
"validFrom": "2026-11-06",
|
|
179
|
+
"note": "reference model of the Codex weights"
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
"agent": "codex",
|
|
183
|
+
"tier": 2,
|
|
184
|
+
"color": 75,
|
|
185
|
+
"prices": [
|
|
186
|
+
{
|
|
187
|
+
"input": 2,
|
|
188
|
+
"cacheWrite5m": null,
|
|
189
|
+
"cacheWrite1h": null,
|
|
190
|
+
"cacheRead": 0.1,
|
|
191
|
+
"output": 10,
|
|
192
|
+
"source": "https://developers.openai.com/api/docs/pricing",
|
|
193
|
+
"at": "2026-11-10",
|
|
194
|
+
"validFrom": "2026-11-10",
|
|
195
|
+
"long": {
|
|
196
|
+
"above": 272000,
|
|
197
|
+
"input": 4,
|
|
198
|
+
"cacheWrite5m": null,
|
|
199
|
+
"cacheWrite1h": null,
|
|
200
|
+
"cacheRead": 0.2,
|
|
201
|
+
"output": 15
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
},
|
|
206
|
+
"gpt-6-astra": {
|
|
207
|
+
"context": 400000,
|
|
208
|
+
"weights": [
|
|
209
|
+
{
|
|
210
|
+
"value": 5,
|
|
211
|
+
"source": "doc",
|
|
212
|
+
"at": "2026-11-07",
|
|
213
|
+
"validFrom": "2026-11-06",
|
|
214
|
+
"note": "API price ratio to Sol ($10 vs $2 input); subscription weight unmeasured"
|
|
215
|
+
}
|
|
216
|
+
],
|
|
217
|
+
"agent": "codex",
|
|
218
|
+
"tier": 3,
|
|
219
|
+
"color": 280,
|
|
220
|
+
"prices": [
|
|
221
|
+
{
|
|
222
|
+
"input": 10,
|
|
223
|
+
"cacheWrite5m": null,
|
|
224
|
+
"cacheWrite1h": null,
|
|
225
|
+
"cacheRead": 1,
|
|
226
|
+
"output": 50,
|
|
227
|
+
"source": "https://developers.openai.com/api/docs/pricing",
|
|
228
|
+
"at": "2026-11-10",
|
|
229
|
+
"validFrom": "2026-11-10",
|
|
230
|
+
"long": {
|
|
231
|
+
"above": 272000,
|
|
232
|
+
"input": 20,
|
|
233
|
+
"cacheWrite5m": null,
|
|
234
|
+
"cacheWrite1h": null,
|
|
235
|
+
"cacheRead": 2,
|
|
236
|
+
"output": 75
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"tokenTypes": [
|
|
243
|
+
"input",
|
|
244
|
+
"cacheWrite",
|
|
245
|
+
"cacheRead",
|
|
246
|
+
"output"
|
|
247
|
+
],
|
|
248
|
+
"agents": {
|
|
249
|
+
"claude": {
|
|
250
|
+
"plan": "pro",
|
|
251
|
+
"plans": {
|
|
252
|
+
"pro": {
|
|
253
|
+
"windows": {
|
|
254
|
+
"5h": [
|
|
255
|
+
{
|
|
256
|
+
"capacity": 15000000,
|
|
257
|
+
"source": "measured",
|
|
258
|
+
"at": "2026-11-06",
|
|
259
|
+
"n": 3,
|
|
260
|
+
"validFrom": "2026-10-01",
|
|
261
|
+
"note": "Max 20x 300M / 20; matched 3 measured points"
|
|
262
|
+
}
|
|
263
|
+
],
|
|
264
|
+
"7d": [
|
|
265
|
+
{
|
|
266
|
+
"capacity": 85000000,
|
|
267
|
+
"source": "estimated",
|
|
268
|
+
"at": "2026-11-06",
|
|
269
|
+
"n": 1,
|
|
270
|
+
"validFrom": "2026-10-01",
|
|
271
|
+
"note": "7d +3% while 5h used ~17%; range 64M-128M"
|
|
272
|
+
}
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
"tokenWeights": [
|
|
278
|
+
{
|
|
279
|
+
"input": 1,
|
|
280
|
+
"cacheWrite": 1.25,
|
|
281
|
+
"cacheRead": 0.025,
|
|
282
|
+
"output": 5,
|
|
283
|
+
"source": "community",
|
|
284
|
+
"at": "2026-10-01",
|
|
285
|
+
"validFrom": "2026-10-01",
|
|
286
|
+
"note": "zenn.dev/tksfjt1024; output includes thinking"
|
|
287
|
+
}
|
|
288
|
+
],
|
|
289
|
+
"quotaSources": [
|
|
290
|
+
"oauth-usage"
|
|
291
|
+
],
|
|
292
|
+
"id": "claude",
|
|
293
|
+
"name": "Claude",
|
|
294
|
+
"color": 25,
|
|
295
|
+
"cacheWrite": true,
|
|
296
|
+
"modelPrefix": "claude-",
|
|
297
|
+
"windows": [
|
|
298
|
+
{
|
|
299
|
+
"id": "5h",
|
|
300
|
+
"label": "5h",
|
|
301
|
+
"durationMs": 18000000,
|
|
302
|
+
"field": "five_hour"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"id": "7d",
|
|
306
|
+
"label": "7d",
|
|
307
|
+
"durationMs": 604800000,
|
|
308
|
+
"field": "seven_day"
|
|
309
|
+
}
|
|
310
|
+
],
|
|
311
|
+
"originators": [
|
|
312
|
+
"Claude Code"
|
|
313
|
+
],
|
|
314
|
+
"pluginData": {
|
|
315
|
+
"homeEnv": "CLAUDE_CONFIG_DIR",
|
|
316
|
+
"home": ".claude",
|
|
317
|
+
"relative": "plugins/data"
|
|
318
|
+
},
|
|
319
|
+
"efforts": [
|
|
320
|
+
{
|
|
321
|
+
"id": "low",
|
|
322
|
+
"color": 215
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"id": "medium",
|
|
326
|
+
"color": 170
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
"id": "high",
|
|
330
|
+
"color": 55
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
"id": "xhigh",
|
|
334
|
+
"color": 30
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"id": "max",
|
|
338
|
+
"color": 0
|
|
339
|
+
}
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
"codex": {
|
|
343
|
+
"plan": "plus",
|
|
344
|
+
"plans": {
|
|
345
|
+
"plus": {
|
|
346
|
+
"windows": {
|
|
347
|
+
"5h": [
|
|
348
|
+
{
|
|
349
|
+
"capacity": 12800000,
|
|
350
|
+
"source": "measured",
|
|
351
|
+
"at": "2026-11-06",
|
|
352
|
+
"n": 2,
|
|
353
|
+
"validFrom": "2026-11-06",
|
|
354
|
+
"note": "1% ~ 8k Sol output; rollout regression suggests ~8.1M, unresolved"
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
"capacity": 3700000,
|
|
358
|
+
"source": "measured",
|
|
359
|
+
"at": "2026-11-07",
|
|
360
|
+
"n": 735,
|
|
361
|
+
"validFrom": "2026-11-06T18:00:00Z",
|
|
362
|
+
"note": "calibrate codex 2026-11-07: 735 points, 9 windows, R2 0.989; mixed models/efforts, possible off-machine use"
|
|
363
|
+
}
|
|
364
|
+
],
|
|
365
|
+
"7d": [
|
|
366
|
+
{
|
|
367
|
+
"capacity": 100000000,
|
|
368
|
+
"source": "estimated",
|
|
369
|
+
"at": "2026-11-06",
|
|
370
|
+
"n": 1,
|
|
371
|
+
"validFrom": "2026-11-06",
|
|
372
|
+
"note": "7d +1% while 5h +8%; weak"
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"capacity": 28900000,
|
|
376
|
+
"source": "estimated",
|
|
377
|
+
"at": "2026-11-07",
|
|
378
|
+
"validFrom": "2026-11-06T18:00:00Z",
|
|
379
|
+
"note": "same 7d/5h ratio as before (~7.8) on the new 5h capacity"
|
|
380
|
+
}
|
|
381
|
+
]
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
"tokenWeights": [
|
|
386
|
+
{
|
|
387
|
+
"input": 1,
|
|
388
|
+
"cacheWrite": 0,
|
|
389
|
+
"cacheRead": 0.11,
|
|
390
|
+
"output": 16,
|
|
391
|
+
"source": "measured",
|
|
392
|
+
"at": "2026-11-06",
|
|
393
|
+
"n": 163,
|
|
394
|
+
"validFrom": "2026-11-06",
|
|
395
|
+
"note": "regression on one 5h window; output includes reasoning"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"input": 1,
|
|
399
|
+
"cacheWrite": 0,
|
|
400
|
+
"cacheRead": 0.047,
|
|
401
|
+
"output": 4.67,
|
|
402
|
+
"source": "measured",
|
|
403
|
+
"at": "2026-11-07",
|
|
404
|
+
"n": 735,
|
|
405
|
+
"validFrom": "2026-11-06T18:00:00Z",
|
|
406
|
+
"note": "calibrate codex 2026-11-07: 735 points, 9 windows, R2 0.989; mixed models/efforts, possible off-machine use"
|
|
407
|
+
}
|
|
408
|
+
],
|
|
409
|
+
"quotaSources": [
|
|
410
|
+
"rollout"
|
|
411
|
+
],
|
|
412
|
+
"id": "codex",
|
|
413
|
+
"name": "Codex",
|
|
414
|
+
"color": 200,
|
|
415
|
+
"cacheWrite": false,
|
|
416
|
+
"modelPrefix": "",
|
|
417
|
+
"windows": [
|
|
418
|
+
{
|
|
419
|
+
"id": "5h",
|
|
420
|
+
"label": "5h",
|
|
421
|
+
"durationMs": 18000000,
|
|
422
|
+
"minutes": 300
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
"id": "7d",
|
|
426
|
+
"label": "7d",
|
|
427
|
+
"durationMs": 604800000,
|
|
428
|
+
"minutes": 10080
|
|
429
|
+
}
|
|
430
|
+
],
|
|
431
|
+
"pluginOrigins": [
|
|
432
|
+
"Claude Code"
|
|
433
|
+
],
|
|
434
|
+
"efforts": [
|
|
435
|
+
{
|
|
436
|
+
"id": "low",
|
|
437
|
+
"color": 215
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
"id": "medium",
|
|
441
|
+
"color": 170
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
"id": "high",
|
|
445
|
+
"color": 55
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"id": "xhigh",
|
|
449
|
+
"color": 30
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"id": "max",
|
|
453
|
+
"color": 0
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
"id": "ultra",
|
|
457
|
+
"color": 0
|
|
458
|
+
}
|
|
459
|
+
]
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
"priceSchema": {
|
|
463
|
+
"fields": [
|
|
464
|
+
"input",
|
|
465
|
+
"cacheWrite5m",
|
|
466
|
+
"cacheWrite1h",
|
|
467
|
+
"cacheRead",
|
|
468
|
+
"output"
|
|
469
|
+
],
|
|
470
|
+
"long": {
|
|
471
|
+
"above": "token count",
|
|
472
|
+
"fields": [
|
|
473
|
+
"input",
|
|
474
|
+
"cacheWrite5m",
|
|
475
|
+
"cacheWrite1h",
|
|
476
|
+
"cacheRead",
|
|
477
|
+
"output"
|
|
478
|
+
]
|
|
479
|
+
},
|
|
480
|
+
"metadata": [
|
|
481
|
+
"source",
|
|
482
|
+
"at",
|
|
483
|
+
"validFrom"
|
|
484
|
+
],
|
|
485
|
+
"nullable": [
|
|
486
|
+
"cacheWrite5m",
|
|
487
|
+
"cacheWrite1h"
|
|
488
|
+
],
|
|
489
|
+
"fastMultiplier": "positive number; multiplies all token prices",
|
|
490
|
+
"geoMultipliers": "inference_geo -> positive multiplier; unknown values use 1",
|
|
491
|
+
"longPrompt": "input + cacheRead + cacheWrite per request"
|
|
492
|
+
}
|
|
493
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// One refresh: registered agents -> state -> links. External evidence is injectable.
|
|
2
|
+
const agents = require('./agents/index.js');
|
|
3
|
+
const { listProcesses } = require('./procs.js');
|
|
4
|
+
const { resolveStates, createTracker } = require('./state.js');
|
|
5
|
+
const { link } = require('./links.js');
|
|
6
|
+
function collect({ registry = agents, since = 0, now = Date.now(), tracker = createTracker(), procs = listProcesses(registry),
|
|
7
|
+
pidFiles = registry.flatMap(a => a.readPidFiles?.() ?? []),
|
|
8
|
+
sessions = registry.flatMap(a => a.readSessions({ since })), pluginJobs = registry.flatMap(a => a.readJobs?.() ?? []) } = {}) {
|
|
9
|
+
return link(resolveStates({ sessions, procs, pidFiles, now, tracker, registry }), { procs, pluginJobs, registry });
|
|
10
|
+
}
|
|
11
|
+
module.exports = { collect };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// One colour source for the terminal (truecolor) and the web (rgb). Colours are hues put through a per-theme
|
|
2
|
+
// saturation/lightness, so text stays readable on light, dark and terminal backgrounds. Unknown value = grey.
|
|
3
|
+
(function (root) {
|
|
4
|
+
const agents = typeof module === 'object' && module.exports ? require('./agents/index.js') : root.AgentRegistry;
|
|
5
|
+
const NAMES = Object.fromEntries(agents.map(a => [a.id, a.name]));
|
|
6
|
+
const short = m => { const text = String(m ?? ''); return agents.reduce((v, a) => a.modelPrefix && v.startsWith(a.modelPrefix) ? v.slice(a.modelPrefix.length) : v, text).replace(/-\d{8}$/, ''); };
|
|
7
|
+
const LOOK = { light: [0.72, 0.36], dark: [0.8, 0.68] }; // [saturation, lightness]
|
|
8
|
+
// I / CR / CW / O legend: [light, dark] as rgb; page.html sets its CSS variables from here.
|
|
9
|
+
const PART = { i: [[59, 120, 196], [91, 155, 234]], cr: [[63, 155, 91], [85, 194, 123]], cw: [[217, 163, 26], [242, 199, 68]], o: [[212, 80, 78], [240, 113, 111]] };
|
|
10
|
+
const GREY = { light: [102, 112, 133], dark: [152, 162, 179] };
|
|
11
|
+
|
|
12
|
+
const idOf = m => String(m ?? '').replace(/-\d{8}$/, '').replace(/\[.*\]$/, '');
|
|
13
|
+
const modelOf = model => agents.flatMap(a => a.models ?? []).find(m => m.id === idOf(model));
|
|
14
|
+
const tierOf = model => modelOf(model)?.tier ?? null;
|
|
15
|
+
const hueOf = (kind, key, provider) => kind === 'provider' ? agents.find(a => a.id === key)?.hue
|
|
16
|
+
: kind === 'effort' ? agents.find(a => a.id === provider)?.efforts?.find(e => e.id === String(key ?? '').toLowerCase())?.color
|
|
17
|
+
: modelOf(key)?.color;
|
|
18
|
+
|
|
19
|
+
// kind: 'provider' | 'model' | 'effort' -> [r, g, b] 0..255
|
|
20
|
+
function rgb(kind, key, theme = 'dark', provider) {
|
|
21
|
+
const hue = hueOf(kind, key, provider);
|
|
22
|
+
if (hue == null) return GREY[theme];
|
|
23
|
+
const [s, l] = LOOK[theme], a = s * Math.min(l, 1 - l);
|
|
24
|
+
const f = n => { const k = (n + hue / 30) % 12; return Math.round(255 * (l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1)))); };
|
|
25
|
+
return [f(0), f(8), f(4)];
|
|
26
|
+
}
|
|
27
|
+
const css = (kind, key, theme = 'dark', provider) => `rgb(${rgb(kind, key, theme, provider).join(',')})`;
|
|
28
|
+
const ansi = (kind, key, provider) => `38;2;${rgb(kind, key, 'dark', provider).join(';')}`;
|
|
29
|
+
const cssPart = (p, theme = 'dark') => `rgb(${PART[p][theme === 'dark' ? 1 : 0].join(',')})`;
|
|
30
|
+
const partAnsi = p => `38;2;${PART[p][1].join(';')}`;
|
|
31
|
+
|
|
32
|
+
const api = { NAMES, short, rgb, css, ansi, tierOf, partAnsi, cssPart, PART };
|
|
33
|
+
if (typeof module === 'object' && module.exports) module.exports = api;
|
|
34
|
+
else root.Colors = api;
|
|
35
|
+
})(typeof globalThis === 'object' ? globalThis : this);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// One quota formula for every provider: only the numbers in catalog.json differ.
|
|
2
|
+
// % of a window = model weight x sum(token weight x tokens) / window capacity of the plan.
|
|
3
|
+
const { pick, modelWeight, windowIds } = require('./catalog.js');
|
|
4
|
+
|
|
5
|
+
const unknown = (windows, assumedWeight, weightSource) => ({ units: null, percent: Object.fromEntries(windows.map(w => [w, null])), parts: null, assumedWeight, weightSource });
|
|
6
|
+
|
|
7
|
+
// percent[w] is the total; parts[w][type] is each token type's share of it (null where the count is unknown).
|
|
8
|
+
function cost(catalog, modelId, tokens, at = Date.now()) {
|
|
9
|
+
const model = own(catalog.models, modelId);
|
|
10
|
+
if (!model) throw new Error(`Unknown model: ${modelId}`);
|
|
11
|
+
const provider = catalog.agents[model.agent];
|
|
12
|
+
const WINDOWS = windowIds(catalog, model.agent), TOKEN_TYPES = catalog.tokenTypes;
|
|
13
|
+
const weight = modelWeight(catalog, modelId, at);
|
|
14
|
+
if (weight.value == null || !provider.tokenWeights) return unknown(WINDOWS, true, weight.source);
|
|
15
|
+
const weights = pick(provider.tokenWeights, at);
|
|
16
|
+
// A missing count (null) only blocks the result when that token type costs something.
|
|
17
|
+
if (TOKEN_TYPES.some(t => tokens[t] == null && weights[t] !== 0)) return unknown(WINDOWS, weight.assumed, weight.source);
|
|
18
|
+
const units = Object.fromEntries(TOKEN_TYPES.map(t => [t, tokens[t] == null ? null : weight.value * tokens[t] * weights[t]]));
|
|
19
|
+
const u = TOKEN_TYPES.reduce((sum, t) => sum + (units[t] ?? 0), 0);
|
|
20
|
+
const percent = {}, parts = {};
|
|
21
|
+
for (const w of WINDOWS) {
|
|
22
|
+
const capacity = pick(provider.plans[provider.plan].windows[w], at).capacity;
|
|
23
|
+
percent[w] = u / capacity * 100;
|
|
24
|
+
parts[w] = Object.fromEntries(TOKEN_TYPES.map(t => [t, units[t] == null ? null : units[t] / capacity * 100]));
|
|
25
|
+
}
|
|
26
|
+
return { units: u, percent, parts, assumedWeight: weight.assumed, weightSource: weight.source };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = { cost };
|
|
30
|
+
// Pure, provider-independent pricing. All amounts are USD; rates are per million tokens.
|
|
31
|
+
const valid = n => typeof n === 'number' && Number.isFinite(n) && n >= 0;
|
|
32
|
+
const own = (object, key) => object != null && typeof key === 'string' && Object.hasOwn(object, key) ? object[key] : undefined;
|
|
33
|
+
function price(record, catalog) {
|
|
34
|
+
const unknown = { costUSD: null, source: 'unknown', uncertain: false };
|
|
35
|
+
if (record?.costUSD != null) return valid(record.costUSD) ? { costUSD: record.costUSD, source: 'log', uncertain: false } : unknown;
|
|
36
|
+
const at = typeof record?.at === 'number' ? record.at : Date.parse(record?.at);
|
|
37
|
+
if (!Number.isFinite(at)) return unknown;
|
|
38
|
+
// shortcut: oldest price applies backwards, add older entries when a price change is known
|
|
39
|
+
const p = pick(own(catalog?.models, record?.model)?.prices ?? [], at);
|
|
40
|
+
if (!p || !record.tokens) return unknown;
|
|
41
|
+
const t = record.tokens;
|
|
42
|
+
const oneHour = t.cacheWrite1h ?? 0;
|
|
43
|
+
const write = t.cacheWrite ?? ((t.cacheWrite5m ?? 0) + oneHour);
|
|
44
|
+
const counts = { input: t.input ?? 0, cacheRead: t.cacheRead ?? 0,
|
|
45
|
+
cacheWrite5m: t.cacheWrite5m ?? write - oneHour, cacheWrite1h: oneHour, output: t.output ?? 0 };
|
|
46
|
+
if (Object.values(counts).some(n => !valid(n))) return unknown;
|
|
47
|
+
const long = !!p.long && counts.input + counts.cacheRead + write > p.long.above;
|
|
48
|
+
const rates = long ? p.long : p;
|
|
49
|
+
let amount = 0;
|
|
50
|
+
for (const [k, n] of Object.entries(counts)) {
|
|
51
|
+
if (n && !valid(rates[k])) return unknown;
|
|
52
|
+
amount += n * (rates[k] ?? 0) / 1e6;
|
|
53
|
+
}
|
|
54
|
+
const fast = record.speed === 'fast';
|
|
55
|
+
const geo = own(p.geoMultipliers, record.inference_geo);
|
|
56
|
+
amount *= (fast && valid(p.fastMultiplier) ? p.fastMultiplier : 1) * (valid(geo) ? geo : 1);
|
|
57
|
+
if (!valid(amount)) return unknown;
|
|
58
|
+
return { costUSD: amount, source: 'estimate', uncertain: fast && !p.fastMultiplier,
|
|
59
|
+
priceSource: p.source, validFrom: p.validFrom, long };
|
|
60
|
+
}
|
|
61
|
+
function summarize(records, catalog) {
|
|
62
|
+
let knownUSD = 0, knownRecords = 0, unknownRecords = 0, uncertainRecords = 0;
|
|
63
|
+
const unknownModels = new Set(), sources = new Set();
|
|
64
|
+
for (const r of records) {
|
|
65
|
+
const p = price(r, catalog);
|
|
66
|
+
sources.add(p.source);
|
|
67
|
+
if (!valid(p.costUSD) || !valid(knownUSD + p.costUSD)) { unknownRecords++; unknownModels.add(r?.model ?? 'unknown'); }
|
|
68
|
+
else { knownUSD += p.costUSD; knownRecords++; }
|
|
69
|
+
if (p.uncertain) uncertainRecords++;
|
|
70
|
+
}
|
|
71
|
+
return { costUSD: unknownRecords && !knownRecords ? null : knownUSD, knownUSD, knownRecords,
|
|
72
|
+
unknownRecords, unknownModels: [...unknownModels].sort(), uncertainRecords, sources: [...sources].sort() };
|
|
73
|
+
}
|
|
74
|
+
function byDay(records, catalog) {
|
|
75
|
+
const groups = new Map();
|
|
76
|
+
for (const r of records) {
|
|
77
|
+
const d = new Date(r.at);
|
|
78
|
+
const day = Number.isFinite(d.getTime()) ? `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}` : 'unknown';
|
|
79
|
+
if (!groups.has(day)) groups.set(day, []);
|
|
80
|
+
groups.get(day).push(r);
|
|
81
|
+
}
|
|
82
|
+
return Object.fromEntries([...groups].sort(([a], [b]) => a.localeCompare(b)).map(([day, rs]) => [day, summarize(rs, catalog)]));
|
|
83
|
+
}
|
|
84
|
+
// Older stores without per-request usage cannot safely use aggregate tokens for long pricing.
|
|
85
|
+
const recordsOf = s => Array.isArray(s.usage) && s.usage.length ? s.usage : [{ at: s.startedAt, model: s.model }];
|
|
86
|
+
const billingView = billing => ({ billing: billing ?? 'unknown', showQuota: billing !== 'api', costKind: billing === 'api' ? 'api' : 'api-equivalent' });
|
|
87
|
+
module.exports = { cost, price, summarize, byDay, recordsOf, billingView };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Number and time formats shared by the terminal and the web (step 7).
|
|
2
|
+
// Percent: always a leading zero and one decimal; >0 but <0.1 is "<0.1"; unknown is "—".
|
|
3
|
+
const pct = n => n == null || !Number.isFinite(n) ? '—' : n > 0 && n < 0.1 ? '<0.1' : n.toFixed(1);
|
|
4
|
+
// Tokens: 1.24M, 38.2k, 512; unknown is "—".
|
|
5
|
+
// The unit switches after rounding: 999960 is 1.00M, not 1000.0k.
|
|
6
|
+
const tok = n => n == null || !Number.isFinite(n) ? '—' : n >= 1e6 || (n >= 1e3 && (n / 1e3).toFixed(1) === '1000.0') ? (n / 1e6).toFixed(2) + 'M' : n >= 1e3 ? (n / 1e3).toFixed(1) + 'k' : String(Math.round(n));
|
|
7
|
+
// Context size: whole thousands (96k/200k).
|
|
8
|
+
const ctx = n => n == null ? '—' : n >= 1e6 || Math.round(n / 1e3) >= 1000 ? (n / 1e6).toFixed(1).replace(/\.0$/, '') + 'M' : n >= 1e3 ? Math.round(n / 1e3) + 'k' : String(n);
|
|
9
|
+
// Duration: 48m, 2h14m, 3d.
|
|
10
|
+
function dur(ms) {
|
|
11
|
+
const m = Math.max(0, Math.round(ms / 60000));
|
|
12
|
+
return m >= 1440 ? `${Math.floor(m / 1440)}d` : m >= 60 ? `${Math.floor(m / 60)}h${String(m % 60).padStart(2, '0')}m` : `${m}m`;
|
|
13
|
+
}
|
|
14
|
+
const hhmm = ms => { const d = new Date(ms); return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`; };
|
|
15
|
+
// "outside monitor" value: +1.2, <0.1, —
|
|
16
|
+
const rise = n => n == null ? '—' : n > 0 && n < 0.1 ? '<0.1' : (n > 0 ? '+' : '') + n.toFixed(1);
|
|
17
|
+
|
|
18
|
+
module.exports = { pct, tok, ctx, dur, hhmm, rise };
|