behavior-wrapped 0.8.0 → 0.8.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.
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
{"timestamp":"2026-06-07T10:00:05.000Z","type":"response_item","payload":{"type":"message","role":"assistant","content":[{"type":"output_text","text":"Let me check that carefully."}]}}
|
|
5
5
|
{"timestamp":"2026-06-07T10:00:07.000Z","type":"response_item","payload":{"type":"function_call","name":"exec_command","call_id":"synthetic-call-1","arguments":"{}"}}
|
|
6
6
|
{"timestamp":"2026-06-07T10:00:09.000Z","type":"response_item","payload":{"type":"function_call_output","call_id":"synthetic-call-1","output":"synthetic build passed"}}
|
|
7
|
-
{"timestamp":"2026-06-07T10:00:10.000Z","type":"event_msg","payload":{"type":"token_count","info":{"total_token_usage":{"input_tokens":
|
|
7
|
+
{"timestamp":"2026-06-07T10:00:10.000Z","type":"event_msg","payload":{"type":"token_count","info":{"total_token_usage":{"input_tokens":1800,"output_tokens":250,"cache_write_input_tokens":0,"cached_input_tokens":1000,"reasoning_output_tokens":50,"total_tokens":2050}}}}
|
|
8
8
|
{"timestamp":"2026-06-07T10:00:12.000Z","type":"event_msg","payload":{"type":"task_complete","started_at":"2026-06-07T10:00:01.000Z","completed_at":"2026-06-07T10:00:12.000Z","duration_ms":11000,"turn_id":"synthetic-turn-1"}}
|
package/package.json
CHANGED
package/server/analysis.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import { safeEvidenceText, redactText } from "./privacy.mjs";
|
|
3
3
|
import { isFrustratedMessage, isGratefulMessage } from "./frustration-card.mjs";
|
|
4
|
+
import { estimateModelUsageCost } from "./model-pricing.mjs";
|
|
4
5
|
import { displayModelName } from "./model-names.mjs";
|
|
5
6
|
|
|
6
7
|
export { displayModelName } from "./model-names.mjs";
|
|
@@ -251,15 +252,6 @@ function finding(kind, title, summary, method, score, evidence) {
|
|
|
251
252
|
return { id: crypto.randomUUID(), kind, title, summary, method, confidence: confidence(score), evidence };
|
|
252
253
|
}
|
|
253
254
|
|
|
254
|
-
function ratesFor(model, agent) {
|
|
255
|
-
const value = String(model || "").toLowerCase();
|
|
256
|
-
if (value.includes("opus")) return { input: 5, output: 25, cacheWrite: 6.25, cacheRead: 0.5 };
|
|
257
|
-
if (value.includes("sonnet")) return { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 };
|
|
258
|
-
if (value.includes("haiku")) return { input: 1, output: 5, cacheWrite: 1.25, cacheRead: 0.1 };
|
|
259
|
-
if (agent === "codex" || value.startsWith("gpt")) return { input: 1.25, output: 10, cacheWrite: 1.25, cacheRead: 0.125 };
|
|
260
|
-
return { input: 3, output: 15, cacheWrite: 3.75, cacheRead: 0.3 };
|
|
261
|
-
}
|
|
262
|
-
|
|
263
255
|
function analyzeBehavior(sessionRecords) {
|
|
264
256
|
const findings = [];
|
|
265
257
|
for (const { sessionId, records } of sessionRecords) {
|
|
@@ -403,8 +395,7 @@ export function analyzeSessions(sessionRecords) {
|
|
|
403
395
|
tokenBreakdown.reasoning += reasoning;
|
|
404
396
|
const model = record?.message?.model || `${agent === "codex" ? "Codex" : "Claude"} model`;
|
|
405
397
|
modelTokens.set(model, (modelTokens.get(model) || 0) + recordTokens);
|
|
406
|
-
|
|
407
|
-
estimatedCostUsd += (input * rates.input + (output + reasoning) * rates.output + cacheWrite * rates.cacheWrite + cacheRead * rates.cacheRead) / 1_000_000;
|
|
398
|
+
estimatedCostUsd += estimateModelUsageCost(usage, model, agent);
|
|
408
399
|
}
|
|
409
400
|
for (const tool of toolUses(record)) {
|
|
410
401
|
toolCalls++;
|
|
@@ -460,7 +451,7 @@ export function analyzeSessions(sessionRecords) {
|
|
|
460
451
|
agents,
|
|
461
452
|
models,
|
|
462
453
|
estimatedCostUsd: Number(estimatedCostUsd.toFixed(2)),
|
|
463
|
-
costEstimateMethod: "API-equivalent estimate using
|
|
454
|
+
costEstimateMethod: "API-equivalent estimate using current standard list prices by exact model, including distinct cache-read, 5-minute cache-write, and 1-hour cache-write rates.",
|
|
464
455
|
};
|
|
465
456
|
return { stats, findings: analyzeBehavior(sessionRecords) };
|
|
466
457
|
}
|
package/server/discovery.mjs
CHANGED
|
@@ -458,8 +458,8 @@ function normalizeCodexRecords(records, { includePrivateToolDetails = false } =
|
|
|
458
458
|
type: "system",
|
|
459
459
|
timestamp: record.timestamp,
|
|
460
460
|
message: { model: currentModel, usage: {
|
|
461
|
-
input_tokens: usage.input_tokens,
|
|
462
|
-
output_tokens: usage.output_tokens,
|
|
461
|
+
input_tokens: Math.max(0, usage.input_tokens - usage.cached_input_tokens - usage.cache_write_input_tokens),
|
|
462
|
+
output_tokens: Math.max(0, usage.output_tokens - usage.reasoning_output_tokens),
|
|
463
463
|
cache_creation_input_tokens: usage.cache_write_input_tokens,
|
|
464
464
|
cache_read_input_tokens: usage.cached_input_tokens,
|
|
465
465
|
reasoning_output_tokens: usage.reasoning_output_tokens,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Standard API list prices in USD per million tokens, verified 2026-08-26.
|
|
2
|
+
// OpenAI: https://developers.openai.com/api/docs/models/compare
|
|
3
|
+
// Anthropic: https://platform.claude.com/docs/en/about-claude/pricing
|
|
4
|
+
const scaled = (value, multiplier) => Number((value * multiplier).toFixed(12));
|
|
5
|
+
|
|
6
|
+
const price = (input, output, cacheRead, cacheWrite5m, cacheWrite1h) => ({
|
|
7
|
+
input,
|
|
8
|
+
output,
|
|
9
|
+
cacheRead: cacheRead ?? scaled(input, 0.1),
|
|
10
|
+
cacheWrite5m: cacheWrite5m ?? scaled(input, 1.25),
|
|
11
|
+
cacheWrite1h: cacheWrite1h ?? scaled(input, 2),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const modelRates = [
|
|
15
|
+
[/gpt-5\.6-sol/, price(4, 20)],
|
|
16
|
+
[/gpt-5\.6-terra/, price(2, 12)],
|
|
17
|
+
[/gpt-5\.6-luna/, price(0.2, 1.2)],
|
|
18
|
+
[/gpt-5\.5-pro/, price(30, 180, 0, 30, 30)],
|
|
19
|
+
[/gpt-5\.5/, price(5, 30)],
|
|
20
|
+
[/gpt-5\.4-pro/, price(30, 180, 0, 30, 30)],
|
|
21
|
+
[/gpt-5\.4-mini/, price(0.75, 4.5)],
|
|
22
|
+
[/gpt-5\.4-nano/, price(0.2, 1.25)],
|
|
23
|
+
[/gpt-5\.4/, price(2.5, 15)],
|
|
24
|
+
[/gpt-5\.3-codex/, price(1.75, 14)],
|
|
25
|
+
[/gpt-5\.2/, price(1.75, 14)],
|
|
26
|
+
[/(?:claude-)?(?:fable|mythos)(?:-|\s)?5/, price(10, 50)],
|
|
27
|
+
[/(?:claude-)?opus(?:-|\s)?5/, price(5, 25)],
|
|
28
|
+
[/(?:claude-)?opus(?:-|\s)?4(?:-|\s)?(?:8|7|6|5)/, price(5, 25)],
|
|
29
|
+
[/(?:claude-)?opus(?:-|\s)?4(?:-|\s)?1/, price(15, 75)],
|
|
30
|
+
[/(?:claude-)?opus(?:-|\s)?4(?:\b|-20)/, price(15, 75)],
|
|
31
|
+
[/(?:claude-)?sonnet(?:-|\s)?5/, price(2, 10)],
|
|
32
|
+
[/(?:claude-)?sonnet(?:-|\s)?4/, price(3, 15)],
|
|
33
|
+
[/(?:claude-)?haiku(?:-|\s)?4(?:-|\s)?5/, price(1, 5)],
|
|
34
|
+
[/(?:claude-)?haiku(?:-|\s)?3(?:-|\s)?5/, price(0.8, 4)],
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
export function ratesFor(model, agent) {
|
|
38
|
+
const value = String(model || "").toLowerCase();
|
|
39
|
+
const match = modelRates.find(([pattern]) => pattern.test(value));
|
|
40
|
+
if (match) return match[1];
|
|
41
|
+
return agent === "codex" || value.startsWith("gpt") ? price(2.5, 15) : price(3, 15);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function estimateModelUsageCost(usage, model, agent) {
|
|
45
|
+
const input = Number(usage?.input_tokens) || 0;
|
|
46
|
+
const output = Number(usage?.output_tokens) || 0;
|
|
47
|
+
const reasoning = Number(usage?.reasoning_output_tokens) || 0;
|
|
48
|
+
const cacheRead = Number(usage?.cache_read_input_tokens) || 0;
|
|
49
|
+
const cacheWrite = Number(usage?.cache_creation_input_tokens) || 0;
|
|
50
|
+
const declared5m = Number(usage?.cache_creation?.ephemeral_5m_input_tokens) || 0;
|
|
51
|
+
const declared1h = Number(usage?.cache_creation?.ephemeral_1h_input_tokens) || 0;
|
|
52
|
+
const cacheWrite5m = declared5m + Math.max(0, cacheWrite - declared5m - declared1h);
|
|
53
|
+
const rates = ratesFor(model, agent);
|
|
54
|
+
return (
|
|
55
|
+
input * rates.input
|
|
56
|
+
+ (output + reasoning) * rates.output
|
|
57
|
+
+ cacheRead * rates.cacheRead
|
|
58
|
+
+ cacheWrite5m * rates.cacheWrite5m
|
|
59
|
+
+ declared1h * rates.cacheWrite1h
|
|
60
|
+
) / 1_000_000;
|
|
61
|
+
}
|