reasonix 0.32.0 → 0.33.1

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 (118) hide show
  1. package/dist/cli/chat-Q5ZCVIOO.js +39 -0
  2. package/dist/cli/chunk-2AWTGJ2C.js +110 -0
  3. package/dist/cli/chunk-2AWTGJ2C.js.map +1 -0
  4. package/dist/cli/chunk-3Q3C4W66.js +30 -0
  5. package/dist/cli/chunk-3Q3C4W66.js.map +1 -0
  6. package/dist/cli/chunk-4DCHFFEY.js +149 -0
  7. package/dist/cli/chunk-4DCHFFEY.js.map +1 -0
  8. package/dist/cli/chunk-5X7LZJDE.js +36 -0
  9. package/dist/cli/chunk-5X7LZJDE.js.map +1 -0
  10. package/dist/cli/chunk-63KAV5DX.js +106 -0
  11. package/dist/cli/chunk-63KAV5DX.js.map +1 -0
  12. package/dist/cli/chunk-6TMHAK5D.js +576 -0
  13. package/dist/cli/chunk-6TMHAK5D.js.map +1 -0
  14. package/dist/cli/chunk-APPB3ZPQ.js +43 -0
  15. package/dist/cli/chunk-APPB3ZPQ.js.map +1 -0
  16. package/dist/cli/chunk-BQNUJJN7.js +42 -0
  17. package/dist/cli/chunk-BQNUJJN7.js.map +1 -0
  18. package/dist/cli/chunk-CPOV2O73.js +39 -0
  19. package/dist/cli/chunk-CPOV2O73.js.map +1 -0
  20. package/dist/cli/chunk-D5DKXIP5.js +368 -0
  21. package/dist/cli/chunk-D5DKXIP5.js.map +1 -0
  22. package/dist/cli/chunk-DFP4YSVM.js +247 -0
  23. package/dist/cli/chunk-DFP4YSVM.js.map +1 -0
  24. package/dist/cli/chunk-DULSP7JH.js +410 -0
  25. package/dist/cli/chunk-DULSP7JH.js.map +1 -0
  26. package/dist/cli/chunk-FM57FNPJ.js +46 -0
  27. package/dist/cli/chunk-FM57FNPJ.js.map +1 -0
  28. package/dist/cli/chunk-FWGEHRB7.js +54 -0
  29. package/dist/cli/chunk-FWGEHRB7.js.map +1 -0
  30. package/dist/cli/chunk-FXGQ5NHE.js +513 -0
  31. package/dist/cli/chunk-FXGQ5NHE.js.map +1 -0
  32. package/dist/cli/chunk-G3XNWSFN.js +53 -0
  33. package/dist/cli/chunk-G3XNWSFN.js.map +1 -0
  34. package/dist/cli/chunk-I6YIAK6C.js +757 -0
  35. package/dist/cli/chunk-I6YIAK6C.js.map +1 -0
  36. package/dist/cli/chunk-J5VLP23S.js +94 -0
  37. package/dist/cli/chunk-J5VLP23S.js.map +1 -0
  38. package/dist/cli/chunk-KMWKGPFZ.js +303 -0
  39. package/dist/cli/chunk-KMWKGPFZ.js.map +1 -0
  40. package/dist/cli/chunk-MDHVWCJ4.js +14965 -0
  41. package/dist/cli/chunk-MDHVWCJ4.js.map +1 -0
  42. package/dist/cli/chunk-MHDNZXJJ.js +48 -0
  43. package/dist/cli/chunk-MHDNZXJJ.js.map +1 -0
  44. package/dist/cli/chunk-ORM6PK57.js +140 -0
  45. package/dist/cli/chunk-ORM6PK57.js.map +1 -0
  46. package/dist/cli/chunk-Q6YFXW7H.js +4986 -0
  47. package/dist/cli/chunk-Q6YFXW7H.js.map +1 -0
  48. package/dist/cli/chunk-QGE6AF76.js +1467 -0
  49. package/dist/cli/chunk-QGE6AF76.js.map +1 -0
  50. package/dist/cli/chunk-RFX7TYVV.js +28 -0
  51. package/dist/cli/chunk-RFX7TYVV.js.map +1 -0
  52. package/dist/cli/chunk-RZILUXUC.js +940 -0
  53. package/dist/cli/chunk-RZILUXUC.js.map +1 -0
  54. package/dist/cli/chunk-SDE5U32Z.js +535 -0
  55. package/dist/cli/chunk-SDE5U32Z.js.map +1 -0
  56. package/dist/cli/chunk-SOZE7V7V.js +340 -0
  57. package/dist/cli/chunk-SOZE7V7V.js.map +1 -0
  58. package/dist/cli/chunk-U3V2ZQ5J.js +479 -0
  59. package/dist/cli/chunk-U3V2ZQ5J.js.map +1 -0
  60. package/dist/cli/chunk-W4LDFAZ6.js +1544 -0
  61. package/dist/cli/chunk-W4LDFAZ6.js.map +1 -0
  62. package/dist/cli/chunk-WBDE4IRI.js +208 -0
  63. package/dist/cli/chunk-WBDE4IRI.js.map +1 -0
  64. package/dist/cli/chunk-XHQIK7B6.js +189 -0
  65. package/dist/cli/chunk-XHQIK7B6.js.map +1 -0
  66. package/dist/cli/chunk-XJLZ4HKU.js +307 -0
  67. package/dist/cli/chunk-XJLZ4HKU.js.map +1 -0
  68. package/dist/cli/chunk-ZPTSJGX5.js +88 -0
  69. package/dist/cli/chunk-ZPTSJGX5.js.map +1 -0
  70. package/dist/cli/chunk-ZTLZO42A.js +231 -0
  71. package/dist/cli/chunk-ZTLZO42A.js.map +1 -0
  72. package/dist/cli/code-DLR77NPZ.js +151 -0
  73. package/dist/cli/code-DLR77NPZ.js.map +1 -0
  74. package/dist/cli/commands-JWT2MWVH.js +352 -0
  75. package/dist/cli/commands-JWT2MWVH.js.map +1 -0
  76. package/dist/cli/commit-RPZBOZS2.js +288 -0
  77. package/dist/cli/commit-RPZBOZS2.js.map +1 -0
  78. package/dist/cli/diff-NTEHCSDW.js +145 -0
  79. package/dist/cli/diff-NTEHCSDW.js.map +1 -0
  80. package/dist/cli/doctor-3TGB2NZN.js +19 -0
  81. package/dist/cli/doctor-3TGB2NZN.js.map +1 -0
  82. package/dist/cli/events-P27CX7LN.js +338 -0
  83. package/dist/cli/events-P27CX7LN.js.map +1 -0
  84. package/dist/cli/index.js +80 -33693
  85. package/dist/cli/index.js.map +1 -1
  86. package/dist/cli/mcp-ARTNQ24O.js +266 -0
  87. package/dist/cli/mcp-ARTNQ24O.js.map +1 -0
  88. package/dist/cli/mcp-browse-HLO2ENDL.js +163 -0
  89. package/dist/cli/mcp-browse-HLO2ENDL.js.map +1 -0
  90. package/dist/cli/mcp-inspect-T2HBR22P.js +103 -0
  91. package/dist/cli/mcp-inspect-T2HBR22P.js.map +1 -0
  92. package/dist/cli/{prompt-XHICFAYN.js → prompt-V47QKSAR.js} +3 -2
  93. package/dist/cli/prompt-V47QKSAR.js.map +1 -0
  94. package/dist/cli/prune-sessions-ERL6B4G5.js +42 -0
  95. package/dist/cli/prune-sessions-ERL6B4G5.js.map +1 -0
  96. package/dist/cli/replay-Q43DSMG6.js +273 -0
  97. package/dist/cli/replay-Q43DSMG6.js.map +1 -0
  98. package/dist/cli/run-JMEOTQCG.js +215 -0
  99. package/dist/cli/run-JMEOTQCG.js.map +1 -0
  100. package/dist/cli/server-SYC3OVOP.js +2967 -0
  101. package/dist/cli/server-SYC3OVOP.js.map +1 -0
  102. package/dist/cli/sessions-MOJAALJI.js +102 -0
  103. package/dist/cli/sessions-MOJAALJI.js.map +1 -0
  104. package/dist/cli/setup-CCJZAWTY.js +404 -0
  105. package/dist/cli/setup-CCJZAWTY.js.map +1 -0
  106. package/dist/cli/stats-5RJCATCE.js +12 -0
  107. package/dist/cli/stats-5RJCATCE.js.map +1 -0
  108. package/dist/cli/update-4TJWRUIN.js +90 -0
  109. package/dist/cli/update-4TJWRUIN.js.map +1 -0
  110. package/dist/cli/version-3MYFE4G6.js +29 -0
  111. package/dist/cli/version-3MYFE4G6.js.map +1 -0
  112. package/dist/index.d.ts +13 -2
  113. package/dist/index.js +493 -89
  114. package/dist/index.js.map +1 -1
  115. package/package.json +1 -1
  116. package/dist/cli/chunk-VWFJNLIK.js +0 -1031
  117. package/dist/cli/chunk-VWFJNLIK.js.map +0 -1
  118. /package/dist/cli/{prompt-XHICFAYN.js.map → chat-Q5ZCVIOO.js.map} +0 -0
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli/ui/presets.ts
4
+ var PRESETS = {
5
+ auto: {
6
+ model: "deepseek-v4-flash",
7
+ reasoningEffort: "max",
8
+ autoEscalate: true
9
+ },
10
+ flash: {
11
+ model: "deepseek-v4-flash",
12
+ reasoningEffort: "max",
13
+ autoEscalate: false
14
+ },
15
+ pro: {
16
+ model: "deepseek-v4-pro",
17
+ reasoningEffort: "max",
18
+ autoEscalate: false
19
+ }
20
+ };
21
+ var PRESET_DESCRIPTIONS = {
22
+ auto: {
23
+ headline: "flash \u2192 pro on hard turns",
24
+ cost: "default \xB7 ~96% turns stay on flash \xB7 pro kicks in only when needed"
25
+ },
26
+ flash: {
27
+ headline: "v4-flash always",
28
+ cost: "cheapest \xB7 predictable \xB7 /pro still works for a one-turn bump"
29
+ },
30
+ pro: {
31
+ headline: "v4-pro always",
32
+ cost: "~3\xD7 flash (5/31 discount) / ~12\xD7 full price \xB7 for hard multi-turn work"
33
+ }
34
+ };
35
+ function resolvePreset(name) {
36
+ if (name === "auto" || name === "flash" || name === "pro") return PRESETS[name];
37
+ if (name === "fast") return { ...PRESETS.flash, reasoningEffort: "high" };
38
+ if (name === "smart") return PRESETS.auto;
39
+ if (name === "max") return PRESETS.pro;
40
+ return PRESETS.auto;
41
+ }
42
+
43
+ export {
44
+ PRESETS,
45
+ PRESET_DESCRIPTIONS,
46
+ resolvePreset
47
+ };
48
+ //# sourceMappingURL=chunk-MHDNZXJJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/ui/presets.ts"],"sourcesContent":["import type { PresetName } from \"../../config.js\";\n\nexport interface PresetSettings {\n model: string;\n reasoningEffort: \"high\" | \"max\";\n autoEscalate: boolean;\n}\n\n/** Old names `fast`/`smart`/`max` aliased via `resolvePreset` so legacy configs still load. */\nexport const PRESETS: Record<\"auto\" | \"flash\" | \"pro\", PresetSettings> = {\n auto: {\n model: \"deepseek-v4-flash\",\n reasoningEffort: \"max\",\n autoEscalate: true,\n },\n flash: {\n model: \"deepseek-v4-flash\",\n reasoningEffort: \"max\",\n autoEscalate: false,\n },\n pro: {\n model: \"deepseek-v4-pro\",\n reasoningEffort: \"max\",\n autoEscalate: false,\n },\n};\n\nexport const PRESET_DESCRIPTIONS: Record<\n \"auto\" | \"flash\" | \"pro\",\n { headline: string; cost: string }\n> = {\n auto: {\n headline: \"flash → pro on hard turns\",\n cost: \"default · ~96% turns stay on flash · pro kicks in only when needed\",\n },\n flash: {\n headline: \"v4-flash always\",\n cost: \"cheapest · predictable · /pro still works for a one-turn bump\",\n },\n pro: {\n headline: \"v4-pro always\",\n cost: \"~3× flash (5/31 discount) / ~12× full price · for hard multi-turn work\",\n },\n};\n\n/** Legacy aliases: fast→flash+high, smart→auto, max→pro. Unknown names fall through to auto. */\nexport function resolvePreset(name: PresetName | undefined): PresetSettings {\n if (name === \"auto\" || name === \"flash\" || name === \"pro\") return PRESETS[name];\n if (name === \"fast\") return { ...PRESETS.flash, reasoningEffort: \"high\" };\n if (name === \"smart\") return PRESETS.auto;\n if (name === \"max\") return PRESETS.pro;\n return PRESETS.auto;\n}\n\n/** Canonical name for storage / display — unknown values become auto. */\nexport function canonicalPresetName(name: PresetName | undefined): \"auto\" | \"flash\" | \"pro\" {\n if (name === \"auto\" || name === \"flash\" || name === \"pro\") return name;\n return \"auto\";\n}\n"],"mappings":";;;AASO,IAAM,UAA4D;AAAA,EACvE,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB;AAAA,EACA,KAAK;AAAA,IACH,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB;AACF;AAEO,IAAM,sBAGT;AAAA,EACF,MAAM;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AAAA,EACA,OAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AAAA,EACA,KAAK;AAAA,IACH,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AACF;AAGO,SAAS,cAAc,MAA8C;AAC1E,MAAI,SAAS,UAAU,SAAS,WAAW,SAAS,MAAO,QAAO,QAAQ,IAAI;AAC9E,MAAI,SAAS,OAAQ,QAAO,EAAE,GAAG,QAAQ,OAAO,iBAAiB,OAAO;AACxE,MAAI,SAAS,QAAS,QAAO,QAAQ;AACrC,MAAI,SAAS,MAAO,QAAO,QAAQ;AACnC,SAAO,QAAQ;AACjB;","names":[]}
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/telemetry/stats.ts
4
+ var DEEPSEEK_PRICING = {
5
+ "deepseek-v4-flash": { inputCacheHit: 0.028, inputCacheMiss: 0.139, output: 0.278 },
6
+ "deepseek-v4-pro": { inputCacheHit: 0.139, inputCacheMiss: 1.667, output: 3.333 },
7
+ // Compat aliases — priced as v4-flash per the deprecation notice.
8
+ "deepseek-chat": { inputCacheHit: 0.028, inputCacheMiss: 0.139, output: 0.278 },
9
+ "deepseek-reasoner": { inputCacheHit: 0.028, inputCacheMiss: 0.139, output: 0.278 }
10
+ };
11
+ var CLAUDE_SONNET_PRICING = { input: 3, output: 15 };
12
+ var DEEPSEEK_CONTEXT_TOKENS = {
13
+ "deepseek-v4-flash": 1e6,
14
+ "deepseek-v4-pro": 1e6,
15
+ "deepseek-chat": 1e6,
16
+ "deepseek-reasoner": 1e6
17
+ };
18
+ var DEFAULT_CONTEXT_TOKENS = 131072;
19
+ function costUsd(model, usage) {
20
+ const p = DEEPSEEK_PRICING[model];
21
+ if (!p) return 0;
22
+ return (usage.promptCacheHitTokens * p.inputCacheHit + usage.promptCacheMissTokens * p.inputCacheMiss + usage.completionTokens * p.output) / 1e6;
23
+ }
24
+ function inputCostUsd(model, usage) {
25
+ const p = DEEPSEEK_PRICING[model];
26
+ if (!p) return 0;
27
+ return (usage.promptCacheHitTokens * p.inputCacheHit + usage.promptCacheMissTokens * p.inputCacheMiss) / 1e6;
28
+ }
29
+ function outputCostUsd(model, usage) {
30
+ const p = DEEPSEEK_PRICING[model];
31
+ if (!p) return 0;
32
+ return usage.completionTokens * p.output / 1e6;
33
+ }
34
+ function cacheSavingsUsd(model, hitTokens) {
35
+ if (hitTokens <= 0) return 0;
36
+ const p = DEEPSEEK_PRICING[model];
37
+ if (!p) return 0;
38
+ return hitTokens * (p.inputCacheMiss - p.inputCacheHit) / 1e6;
39
+ }
40
+ function claudeEquivalentCost(usage) {
41
+ return (usage.promptTokens * CLAUDE_SONNET_PRICING.input + usage.completionTokens * CLAUDE_SONNET_PRICING.output) / 1e6;
42
+ }
43
+ var SessionStats = class {
44
+ turns = [];
45
+ /** Cost from prior runs of a resumed session, restored from session meta. */
46
+ _carryoverCost = 0;
47
+ /** Turn count from prior runs of a resumed session. */
48
+ _carryoverTurns = 0;
49
+ _carryoverCacheHit = 0;
50
+ _carryoverCacheMiss = 0;
51
+ /** Last turn's promptTokens before exit — surfaced via summary() until the next live turn lands. */
52
+ _carryoverLastPromptTokens = 0;
53
+ /** Seed totals from a resumed session's persisted meta — only call once at construction. */
54
+ seedCarryover(opts) {
55
+ if (typeof opts.totalCostUsd === "number" && opts.totalCostUsd > 0) {
56
+ this._carryoverCost = opts.totalCostUsd;
57
+ }
58
+ if (typeof opts.turnCount === "number" && opts.turnCount > 0) {
59
+ this._carryoverTurns = opts.turnCount;
60
+ }
61
+ if (typeof opts.cacheHitTokens === "number" && opts.cacheHitTokens > 0) {
62
+ this._carryoverCacheHit = opts.cacheHitTokens;
63
+ }
64
+ if (typeof opts.cacheMissTokens === "number" && opts.cacheMissTokens > 0) {
65
+ this._carryoverCacheMiss = opts.cacheMissTokens;
66
+ }
67
+ if (typeof opts.lastPromptTokens === "number" && opts.lastPromptTokens > 0) {
68
+ this._carryoverLastPromptTokens = opts.lastPromptTokens;
69
+ }
70
+ }
71
+ record(turn, model, usage) {
72
+ const cost = costUsd(model, usage);
73
+ const stats = {
74
+ turn,
75
+ model,
76
+ usage,
77
+ cost,
78
+ cacheHitRatio: usage.cacheHitRatio
79
+ };
80
+ this.turns.push(stats);
81
+ return stats;
82
+ }
83
+ get totalCost() {
84
+ return this._carryoverCost + this.turns.reduce((sum, t) => sum + t.cost, 0);
85
+ }
86
+ get totalClaudeEquivalent() {
87
+ return this.turns.reduce((sum, t) => sum + claudeEquivalentCost(t.usage), 0);
88
+ }
89
+ get savingsVsClaude() {
90
+ const c = this.totalClaudeEquivalent;
91
+ return c > 0 ? 1 - this.totalCost / c : 0;
92
+ }
93
+ get totalInputCost() {
94
+ return this.turns.reduce((sum, t) => sum + inputCostUsd(t.model, t.usage), 0);
95
+ }
96
+ get totalOutputCost() {
97
+ return this.turns.reduce((sum, t) => sum + outputCostUsd(t.model, t.usage), 0);
98
+ }
99
+ get aggregateCacheHitRatio() {
100
+ let hit = this._carryoverCacheHit;
101
+ let miss = this._carryoverCacheMiss;
102
+ for (const t of this.turns) {
103
+ hit += t.usage.promptCacheHitTokens;
104
+ miss += t.usage.promptCacheMissTokens;
105
+ }
106
+ const denom = hit + miss;
107
+ return denom > 0 ? hit / denom : 0;
108
+ }
109
+ summary() {
110
+ const last = this.turns[this.turns.length - 1];
111
+ return {
112
+ turns: this.turns.length + this._carryoverTurns,
113
+ totalCostUsd: round(this.totalCost, 6),
114
+ totalInputCostUsd: round(this.totalInputCost, 6),
115
+ totalOutputCostUsd: round(this.totalOutputCost, 6),
116
+ claudeEquivalentUsd: round(this.totalClaudeEquivalent, 6),
117
+ savingsVsClaudePct: round(this.savingsVsClaude * 100, 2),
118
+ cacheHitRatio: round(this.aggregateCacheHitRatio, 4),
119
+ lastPromptTokens: last?.usage.promptTokens ?? this._carryoverLastPromptTokens,
120
+ lastTurnCostUsd: round(last?.cost ?? 0, 6)
121
+ };
122
+ }
123
+ };
124
+ function round(n, digits) {
125
+ const f = 10 ** digits;
126
+ return Math.round(n * f) / f;
127
+ }
128
+
129
+ export {
130
+ DEEPSEEK_PRICING,
131
+ DEEPSEEK_CONTEXT_TOKENS,
132
+ DEFAULT_CONTEXT_TOKENS,
133
+ costUsd,
134
+ inputCostUsd,
135
+ outputCostUsd,
136
+ cacheSavingsUsd,
137
+ claudeEquivalentCost,
138
+ SessionStats
139
+ };
140
+ //# sourceMappingURL=chunk-ORM6PK57.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/telemetry/stats.ts"],"sourcesContent":["import type { Usage } from \"../client.js\";\n\n/** USD per 1M tokens; CNY sheet converted at fixed 7.2 — revisit if FX moves >±5%. */\nexport const DEEPSEEK_PRICING: Record<\n string,\n { inputCacheHit: number; inputCacheMiss: number; output: number }\n> = {\n \"deepseek-v4-flash\": { inputCacheHit: 0.028, inputCacheMiss: 0.139, output: 0.278 },\n \"deepseek-v4-pro\": { inputCacheHit: 0.139, inputCacheMiss: 1.667, output: 3.333 },\n // Compat aliases — priced as v4-flash per the deprecation notice.\n \"deepseek-chat\": { inputCacheHit: 0.028, inputCacheMiss: 0.139, output: 0.278 },\n \"deepseek-reasoner\": { inputCacheHit: 0.028, inputCacheMiss: 0.139, output: 0.278 },\n};\n\n/** Reference Claude Sonnet 4.6 pricing (USD per 1M tokens). */\nexport const CLAUDE_SONNET_PRICING = { input: 3.0, output: 15.0 };\n\n/** Prompt-side window only; completion caps live server-side and don't affect this gauge. */\nexport const DEEPSEEK_CONTEXT_TOKENS: Record<string, number> = {\n \"deepseek-v4-flash\": 1_000_000,\n \"deepseek-v4-pro\": 1_000_000,\n \"deepseek-chat\": 1_000_000,\n \"deepseek-reasoner\": 1_000_000,\n};\n\n/** Fallback when the caller's model id isn't in the table — safe lower bound. */\nexport const DEFAULT_CONTEXT_TOKENS = 131_072;\n\nexport function costUsd(model: string, usage: Usage): number {\n const p = DEEPSEEK_PRICING[model];\n if (!p) return 0;\n return (\n (usage.promptCacheHitTokens * p.inputCacheHit +\n usage.promptCacheMissTokens * p.inputCacheMiss +\n usage.completionTokens * p.output) /\n 1_000_000\n );\n}\n\n/** Input-side cost only (prompt, cache hit + miss). Used for the panel breakdown. */\nexport function inputCostUsd(model: string, usage: Usage): number {\n const p = DEEPSEEK_PRICING[model];\n if (!p) return 0;\n return (\n (usage.promptCacheHitTokens * p.inputCacheHit +\n usage.promptCacheMissTokens * p.inputCacheMiss) /\n 1_000_000\n );\n}\n\n/** Output-side cost only (completion tokens). Used for the panel breakdown. */\nexport function outputCostUsd(model: string, usage: Usage): number {\n const p = DEEPSEEK_PRICING[model];\n if (!p) return 0;\n return (usage.completionTokens * p.output) / 1_000_000;\n}\n\nexport function cacheSavingsUsd(model: string, hitTokens: number): number {\n if (hitTokens <= 0) return 0;\n const p = DEEPSEEK_PRICING[model];\n if (!p) return 0;\n return (hitTokens * (p.inputCacheMiss - p.inputCacheHit)) / 1_000_000;\n}\n\nexport function claudeEquivalentCost(usage: Usage): number {\n return (\n (usage.promptTokens * CLAUDE_SONNET_PRICING.input +\n usage.completionTokens * CLAUDE_SONNET_PRICING.output) /\n 1_000_000\n );\n}\n\nexport interface TurnStats {\n turn: number;\n model: string;\n usage: Usage;\n cost: number;\n cacheHitRatio: number;\n}\n\nexport interface SessionSummary {\n turns: number;\n totalCostUsd: number;\n totalInputCostUsd: number;\n /** Output-side (completion) cost aggregated across the session. */\n totalOutputCostUsd: number;\n /** @deprecated Claude reference; kept for benchmarks + replay compat, no longer surfaced in the TUI. */\n claudeEquivalentUsd: number;\n /** @deprecated. Same as claudeEquivalentUsd — synthetic ratio, not a real measurement. */\n savingsVsClaudePct: number;\n cacheHitRatio: number;\n /** Floor estimate for next call — actual cost = this + user delta + new tool outputs. */\n lastPromptTokens: number;\n lastTurnCostUsd: number;\n}\n\nexport class SessionStats {\n readonly turns: TurnStats[] = [];\n /** Cost from prior runs of a resumed session, restored from session meta. */\n private _carryoverCost = 0;\n /** Turn count from prior runs of a resumed session. */\n private _carryoverTurns = 0;\n private _carryoverCacheHit = 0;\n private _carryoverCacheMiss = 0;\n /** Last turn's promptTokens before exit — surfaced via summary() until the next live turn lands. */\n private _carryoverLastPromptTokens = 0;\n\n /** Seed totals from a resumed session's persisted meta — only call once at construction. */\n seedCarryover(opts: {\n totalCostUsd?: number;\n turnCount?: number;\n cacheHitTokens?: number;\n cacheMissTokens?: number;\n lastPromptTokens?: number;\n }): void {\n if (typeof opts.totalCostUsd === \"number\" && opts.totalCostUsd > 0) {\n this._carryoverCost = opts.totalCostUsd;\n }\n if (typeof opts.turnCount === \"number\" && opts.turnCount > 0) {\n this._carryoverTurns = opts.turnCount;\n }\n if (typeof opts.cacheHitTokens === \"number\" && opts.cacheHitTokens > 0) {\n this._carryoverCacheHit = opts.cacheHitTokens;\n }\n if (typeof opts.cacheMissTokens === \"number\" && opts.cacheMissTokens > 0) {\n this._carryoverCacheMiss = opts.cacheMissTokens;\n }\n if (typeof opts.lastPromptTokens === \"number\" && opts.lastPromptTokens > 0) {\n this._carryoverLastPromptTokens = opts.lastPromptTokens;\n }\n }\n\n record(turn: number, model: string, usage: Usage): TurnStats {\n const cost = costUsd(model, usage);\n const stats: TurnStats = {\n turn,\n model,\n usage,\n cost,\n cacheHitRatio: usage.cacheHitRatio,\n };\n this.turns.push(stats);\n return stats;\n }\n\n get totalCost(): number {\n return this._carryoverCost + this.turns.reduce((sum, t) => sum + t.cost, 0);\n }\n\n get totalClaudeEquivalent(): number {\n return this.turns.reduce((sum, t) => sum + claudeEquivalentCost(t.usage), 0);\n }\n\n get savingsVsClaude(): number {\n const c = this.totalClaudeEquivalent;\n return c > 0 ? 1 - this.totalCost / c : 0;\n }\n\n get totalInputCost(): number {\n return this.turns.reduce((sum, t) => sum + inputCostUsd(t.model, t.usage), 0);\n }\n\n get totalOutputCost(): number {\n return this.turns.reduce((sum, t) => sum + outputCostUsd(t.model, t.usage), 0);\n }\n\n get aggregateCacheHitRatio(): number {\n let hit = this._carryoverCacheHit;\n let miss = this._carryoverCacheMiss;\n for (const t of this.turns) {\n hit += t.usage.promptCacheHitTokens;\n miss += t.usage.promptCacheMissTokens;\n }\n const denom = hit + miss;\n return denom > 0 ? hit / denom : 0;\n }\n\n summary(): SessionSummary {\n const last = this.turns[this.turns.length - 1];\n return {\n turns: this.turns.length + this._carryoverTurns,\n totalCostUsd: round(this.totalCost, 6),\n totalInputCostUsd: round(this.totalInputCost, 6),\n totalOutputCostUsd: round(this.totalOutputCost, 6),\n claudeEquivalentUsd: round(this.totalClaudeEquivalent, 6),\n savingsVsClaudePct: round(this.savingsVsClaude * 100, 2),\n cacheHitRatio: round(this.aggregateCacheHitRatio, 4),\n lastPromptTokens: last?.usage.promptTokens ?? this._carryoverLastPromptTokens,\n lastTurnCostUsd: round(last?.cost ?? 0, 6),\n };\n }\n}\n\nfunction round(n: number, digits: number): number {\n const f = 10 ** digits;\n return Math.round(n * f) / f;\n}\n"],"mappings":"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","names":[]}