reasonix 0.34.1 → 0.36.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.
Files changed (91) hide show
  1. package/dashboard/app.css +16 -14
  2. package/dashboard/dist/app.js +77 -18
  3. package/dashboard/dist/app.js.map +1 -1
  4. package/dist/cli/{chat-TD6GR3QK.js → chat-RGMYAOY2.js} +18 -17
  5. package/dist/cli/{chunk-SA4UGZPG.js → chunk-2MCYGFLK.js} +15 -10
  6. package/dist/cli/chunk-2MCYGFLK.js.map +1 -0
  7. package/dist/cli/{chunk-SW3CCXEV.js → chunk-4Q3GRJIU.js} +2 -2
  8. package/dist/cli/{chunk-5JXXEPDM.js → chunk-BHLHOS5Y.js} +8 -2
  9. package/dist/cli/chunk-BHLHOS5Y.js.map +1 -0
  10. package/dist/cli/{chunk-F3ILWP2L.js → chunk-BJ376EN3.js} +9 -8
  11. package/dist/cli/chunk-BJ376EN3.js.map +1 -0
  12. package/dist/cli/{chunk-2AWTGJ2C.js → chunk-CRPQUBP6.js} +26 -9
  13. package/dist/cli/{chunk-2AWTGJ2C.js.map → chunk-CRPQUBP6.js.map} +1 -1
  14. package/dist/cli/{chunk-EINEIIIW.js → chunk-EN4LAZW5.js} +563 -250
  15. package/dist/cli/chunk-EN4LAZW5.js.map +1 -0
  16. package/dist/cli/{chunk-OERAGRJX.js → chunk-IPCPEZWQ.js} +2 -2
  17. package/dist/cli/{chunk-U3V2ZQ5J.js → chunk-KJQIA4US.js} +6 -2
  18. package/dist/cli/chunk-KJQIA4US.js.map +1 -0
  19. package/dist/cli/{chunk-Q36KBLSU.js → chunk-MLXUGPJE.js} +292 -35
  20. package/dist/cli/chunk-MLXUGPJE.js.map +1 -0
  21. package/dist/cli/{chunk-SX6L4HZZ.js → chunk-QPNZWUZF.js} +53 -6
  22. package/dist/cli/chunk-QPNZWUZF.js.map +1 -0
  23. package/dist/cli/{chunk-LNTORE5K.js → chunk-QRUQ2BFT.js} +159 -40
  24. package/dist/cli/chunk-QRUQ2BFT.js.map +1 -0
  25. package/dist/cli/{chunk-KZHMKOJH.js → chunk-T52GAWPP.js} +25 -3
  26. package/dist/cli/chunk-T52GAWPP.js.map +1 -0
  27. package/dist/cli/{chunk-I6YIAK6C.js → chunk-UNMYFZPZ.js} +2 -2
  28. package/dist/cli/{update-4TJWRUIN.js → chunk-WJ3YX4PZ.js} +51 -12
  29. package/dist/cli/chunk-WJ3YX4PZ.js.map +1 -0
  30. package/dist/cli/{chunk-RXGEGA7K.js → chunk-XQIFIB3U.js} +18 -7
  31. package/dist/cli/{chunk-RXGEGA7K.js.map → chunk-XQIFIB3U.js.map} +1 -1
  32. package/dist/cli/{chunk-2EBODRRO.js → chunk-ZJR4QLXB.js} +5 -1
  33. package/dist/cli/{chunk-2EBODRRO.js.map → chunk-ZJR4QLXB.js.map} +1 -1
  34. package/dist/cli/{chunk-6TMHAK5D.js → chunk-ZU45XW3P.js} +2 -2
  35. package/dist/cli/code-KJB3WDU6.js +435 -0
  36. package/dist/cli/code-KJB3WDU6.js.map +1 -0
  37. package/dist/cli/{commands-MEZPSEHV.js → commands-FE2UDFBC.js} +3 -3
  38. package/dist/cli/{commit-CE4EFTUQ.js → commit-3IAGB22T.js} +5 -4
  39. package/dist/cli/commit-3IAGB22T.js.map +1 -0
  40. package/dist/cli/{doctor-YASM64X6.js → doctor-DKD34EFD.js} +7 -7
  41. package/dist/cli/index.js +35 -33
  42. package/dist/cli/index.js.map +1 -1
  43. package/dist/cli/{mcp-LDFK5QJI.js → mcp-2RDEQST6.js} +2 -2
  44. package/dist/cli/{mcp-browse-FYHEITCM.js → mcp-browse-VM5GLRBQ.js} +2 -2
  45. package/dist/cli/{mcp-inspect-T2HBR22P.js → mcp-inspect-CWSVCZUQ.js} +3 -3
  46. package/dist/cli/{prompt-V47QKSAR.js → prompt-YEKXMNNV.js} +3 -3
  47. package/dist/cli/{replay-JEDLU7F2.js → replay-D7RT2DR7.js} +3 -3
  48. package/dist/cli/replay-D7RT2DR7.js.map +1 -0
  49. package/dist/cli/{run-NHD2RSTD.js → run-FK5UBIIM.js} +13 -12
  50. package/dist/cli/run-FK5UBIIM.js.map +1 -0
  51. package/dist/cli/{server-MC4A4WAJ.js → server-W4XJK4GX.js} +17 -17
  52. package/dist/cli/{server-MC4A4WAJ.js.map → server-W4XJK4GX.js.map} +1 -1
  53. package/dist/cli/{sessions-ZHWJEW4L.js → sessions-YZXWMIWW.js} +10 -10
  54. package/dist/cli/{setup-DK43MT47.js → setup-IIAJXHP4.js} +196 -130
  55. package/dist/cli/setup-IIAJXHP4.js.map +1 -0
  56. package/dist/cli/update-GUCWB4UN.js +13 -0
  57. package/dist/cli/update-GUCWB4UN.js.map +1 -0
  58. package/dist/cli/{version-O362UKPM.js → version-DWD6RLIU.js} +12 -12
  59. package/dist/index.d.ts +19 -2
  60. package/dist/index.js +543 -78
  61. package/dist/index.js.map +1 -1
  62. package/package.json +1 -1
  63. package/dist/cli/chunk-5JXXEPDM.js.map +0 -1
  64. package/dist/cli/chunk-EINEIIIW.js.map +0 -1
  65. package/dist/cli/chunk-F3ILWP2L.js.map +0 -1
  66. package/dist/cli/chunk-KZHMKOJH.js.map +0 -1
  67. package/dist/cli/chunk-LNTORE5K.js.map +0 -1
  68. package/dist/cli/chunk-Q36KBLSU.js.map +0 -1
  69. package/dist/cli/chunk-SA4UGZPG.js.map +0 -1
  70. package/dist/cli/chunk-SX6L4HZZ.js.map +0 -1
  71. package/dist/cli/chunk-U3V2ZQ5J.js.map +0 -1
  72. package/dist/cli/code-TGUOQBRJ.js +0 -153
  73. package/dist/cli/code-TGUOQBRJ.js.map +0 -1
  74. package/dist/cli/commit-CE4EFTUQ.js.map +0 -1
  75. package/dist/cli/replay-JEDLU7F2.js.map +0 -1
  76. package/dist/cli/run-NHD2RSTD.js.map +0 -1
  77. package/dist/cli/setup-DK43MT47.js.map +0 -1
  78. package/dist/cli/update-4TJWRUIN.js.map +0 -1
  79. /package/dist/cli/{chat-TD6GR3QK.js.map → chat-RGMYAOY2.js.map} +0 -0
  80. /package/dist/cli/{chunk-SW3CCXEV.js.map → chunk-4Q3GRJIU.js.map} +0 -0
  81. /package/dist/cli/{chunk-OERAGRJX.js.map → chunk-IPCPEZWQ.js.map} +0 -0
  82. /package/dist/cli/{chunk-I6YIAK6C.js.map → chunk-UNMYFZPZ.js.map} +0 -0
  83. /package/dist/cli/{chunk-6TMHAK5D.js.map → chunk-ZU45XW3P.js.map} +0 -0
  84. /package/dist/cli/{commands-MEZPSEHV.js.map → commands-FE2UDFBC.js.map} +0 -0
  85. /package/dist/cli/{doctor-YASM64X6.js.map → doctor-DKD34EFD.js.map} +0 -0
  86. /package/dist/cli/{mcp-LDFK5QJI.js.map → mcp-2RDEQST6.js.map} +0 -0
  87. /package/dist/cli/{mcp-browse-FYHEITCM.js.map → mcp-browse-VM5GLRBQ.js.map} +0 -0
  88. /package/dist/cli/{mcp-inspect-T2HBR22P.js.map → mcp-inspect-CWSVCZUQ.js.map} +0 -0
  89. /package/dist/cli/{prompt-V47QKSAR.js.map → prompt-YEKXMNNV.js.map} +0 -0
  90. /package/dist/cli/{sessions-ZHWJEW4L.js.map → sessions-YZXWMIWW.js.map} +0 -0
  91. /package/dist/cli/{version-O362UKPM.js.map → version-DWD6RLIU.js.map} +0 -0
package/dashboard/app.css CHANGED
@@ -85,7 +85,7 @@ a:hover { text-decoration: underline; }
85
85
  /* ── Doc chrome ─────────────────────────────────────────────────────────── */
86
86
  .page {
87
87
  display: grid;
88
- grid-template-columns: 240px minmax(0, 1fr);
88
+ grid-template-columns: 260px minmax(0, 1fr);
89
89
  max-width: 1320px;
90
90
  margin: 0 auto;
91
91
  min-height: 100vh;
@@ -94,18 +94,19 @@ a:hover { text-decoration: underline; }
94
94
  position: sticky; top: 0; align-self: start;
95
95
  height: 100vh; overflow-y: auto;
96
96
  border-right: 1px solid var(--bd);
97
- padding: 28px 18px;
97
+ padding: 28px 16px;
98
98
  background: var(--bg);
99
99
  }
100
- .toc h1 { font-size: 14px; font-weight: 700; margin: 0 0 4px; color: var(--fg-0); letter-spacing: .03em; font-family: var(--font-mono); }
100
+ .toc h1 { font-size: 15px; font-weight: 700; margin: 0 0 4px; color: var(--fg-0); letter-spacing: .03em; font-family: var(--font-mono); }
101
101
  .toc h1 .dot { color: var(--c-brand); margin-right: 8px; }
102
- .toc .sub { font-size: 11px; color: var(--fg-3); margin: 0 0 18px; letter-spacing: .04em; }
103
- .toc-section { font-size: 10px; text-transform: uppercase; letter-spacing: .14em; color: var(--fg-4); margin: 22px 0 6px; font-weight: 700; }
102
+ .toc .sub { font-size: 12px; color: var(--fg-3); margin: 0 0 18px; letter-spacing: .04em; }
103
+ .toc-section { font-size: 12px; text-transform: uppercase; letter-spacing: .08em; color: var(--fg-4); margin: 22px 0 6px; font-weight: 700; }
104
104
  .toc-section:first-of-type { margin-top: 0; }
105
105
  .toc ul { list-style: none; padding: 0; margin: 0; }
106
106
  .toc li a {
107
- display: block; padding: 3px 8px; margin: 1px 0;
108
- color: var(--fg-2); font-size: 12.5px; border-radius: var(--r);
107
+ display: block; padding: 4px 10px; margin: 1px 0;
108
+ color: var(--fg-2); font-size: 14px; line-height: 1.4;
109
+ border-radius: var(--r); overflow-wrap: anywhere;
109
110
  }
110
111
  .toc li a:hover { color: var(--fg-0); background: var(--bg-elev); text-decoration: none; }
111
112
 
@@ -118,7 +119,7 @@ main { padding: 32px 40px 60px 32px; min-width: 0; }
118
119
  }
119
120
  .section > h2 .num { color: var(--fg-4); margin-right: 10px; font-weight: 500; }
120
121
  .section > .lede {
121
- color: var(--fg-2); margin: 0 0 22px; font-size: 13px; max-width: 700px; line-height: 1.6;
122
+ color: var(--fg-2); margin: 0 0 22px; font-size: 15px; max-width: 720px; line-height: 1.6;
122
123
  }
123
124
  .subsec { margin-bottom: 22px; }
124
125
  .subsec > h3 {
@@ -126,8 +127,8 @@ main { padding: 32px 40px 60px 32px; min-width: 0; }
126
127
  margin: 24px 0 4px; letter-spacing: .04em; text-transform: uppercase;
127
128
  font-family: var(--font-mono);
128
129
  }
129
- .subsec > h3 .desc { color: var(--fg-3); font-weight: 400; margin-left: 10px; font-size: 12px; text-transform: none; letter-spacing: 0; }
130
- .subsec > p { color: var(--fg-3); font-size: 12.5px; margin: 0 0 12px; max-width: 720px; line-height: 1.6; }
130
+ .subsec > h3 .desc { color: var(--fg-3); font-weight: 400; margin-left: 10px; font-size: 13px; text-transform: none; letter-spacing: 0; }
131
+ .subsec > p { color: var(--fg-3); font-size: 15px; margin: 0 0 12px; max-width: 720px; line-height: 1.6; }
131
132
 
132
133
  /* "Mock" — a faux-window frame to display dashboard pieces inside the design doc */
133
134
  .mock {
@@ -155,11 +156,11 @@ main { padding: 32px 40px 60px 32px; min-width: 0; }
155
156
  .swatch .chip { width: 22px; height: 22px; border-radius: var(--r); flex-shrink: 0; border: 1px solid rgba(255,255,255,.04); }
156
157
  .swatch .meta { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
157
158
  .swatch .name { color: var(--fg-1); font-size: 11.5px; }
158
- .swatch .hex { color: var(--fg-3); font-size: 10.5px; }
159
+ .swatch .hex { color: var(--fg-3); font-size: 11.5px; }
159
160
 
160
161
  .scale-row { display: flex; align-items: baseline; gap: 16px; padding: 6px 0; border-bottom: 1px dashed #181b22; }
161
162
  .scale-row:last-child { border-bottom: none; }
162
- .scale-row .lbl { font-family: var(--font-mono); font-size: 10.5px; color: var(--fg-3); width: 70px; flex-shrink: 0; }
163
+ .scale-row .lbl { font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-3); width: 76px; flex-shrink: 0; }
163
164
  .scale-row .ex { color: var(--fg-1); }
164
165
 
165
166
  .glyph-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 6px; }
@@ -311,12 +312,13 @@ main { padding: 32px 40px 60px 32px; min-width: 0; }
311
312
  .pill.acc { color: var(--c-accent); background: rgba(210,168,255,.10); }
312
313
 
313
314
  /* Table */
314
- .tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
315
+ .tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; table-layout: auto; }
315
316
  .tbl th, .tbl td { padding: 8px 10px; text-align: left; border-bottom: 1px solid var(--bd); }
316
317
  .tbl th { font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; color: var(--fg-3); text-transform: uppercase; letter-spacing: .08em; background: var(--bg-elev); }
318
+ .tbl th.num, .tbl td.num { font-family: var(--font-mono); text-align: right; font-variant-numeric: tabular-nums; }
317
319
  .tbl td { color: var(--fg-1); }
318
320
  .tbl tbody tr:hover { background: var(--bg-hover); }
319
- .tbl td.num { font-family: var(--font-mono); text-align: right; color: var(--fg-0); font-variant-numeric: tabular-nums; }
321
+ .tbl td.num { color: var(--fg-0); }
320
322
  .tbl td.dim { color: var(--fg-3); }
321
323
  .tbl td.path { font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-2); }
322
324
 
@@ -19392,12 +19392,19 @@ var en = {
19392
19392
  dailyMeta: "cost \xB7 cache saved \xB7 turns",
19393
19393
  noData: "No usage data yet \u2014 run a turn in reasonix chat / code / run and refresh.",
19394
19394
  windows: "Rolling windows",
19395
+ colWindow: "window",
19395
19396
  colTurns: "turns",
19396
19397
  colCacheHit: "cache hit",
19397
19398
  colCost: "cost (USD)",
19398
19399
  colCacheSaved: "cache saved",
19399
19400
  colVsClaude: "vs Claude",
19400
19401
  colSaved: "saved",
19402
+ axisTime: "time",
19403
+ axisUsd: "USD",
19404
+ axisTurns: "turns",
19405
+ seriesCost: "cost",
19406
+ seriesCacheSaved: "cache saved",
19407
+ seriesTurns: "turns",
19401
19408
  mostUsed: "Most used models",
19402
19409
  colModel: "model"
19403
19410
  },
@@ -19966,12 +19973,19 @@ var zhCN = {
19966
19973
  dailyMeta: "\u8D39\u7528 \xB7 \u7F13\u5B58\u8282\u7701 \xB7 \u8F6E\u6B21",
19967
19974
  noData: "\u6682\u65E0\u7528\u91CF\u6570\u636E \u2014 \u5728 reasonix chat / code / run \u4E2D\u6267\u884C\u4E00\u8F6E\uFF0C\u7136\u540E\u5237\u65B0\u3002",
19968
19975
  windows: "\u6EDA\u52A8\u7A97\u53E3",
19976
+ colWindow: "\u65F6\u95F4\u8303\u56F4",
19969
19977
  colTurns: "\u8F6E\u6B21",
19970
19978
  colCacheHit: "\u7F13\u5B58\u547D\u4E2D",
19971
19979
  colCost: "\u8D39\u7528 (USD)",
19972
19980
  colCacheSaved: "\u7F13\u5B58\u8282\u7701",
19973
19981
  colVsClaude: "\u5BF9\u6BD4 Claude",
19974
19982
  colSaved: "\u8282\u7701",
19983
+ axisTime: "\u65F6\u95F4",
19984
+ axisUsd: "\u7F8E\u5143",
19985
+ axisTurns: "\u8F6E\u6B21",
19986
+ seriesCost: "\u8D39\u7528",
19987
+ seriesCacheSaved: "\u7F13\u5B58\u8282\u7701",
19988
+ seriesTurns: "\u8F6E\u6B21",
19975
19989
  mostUsed: "\u6700\u5E38\u7528\u6A21\u578B",
19976
19990
  colModel: "\u6A21\u578B"
19977
19991
  },
@@ -23347,8 +23361,31 @@ function ChatPanel() {
23347
23361
  cancelled = true;
23348
23362
  };
23349
23363
  }, []);
23364
+ const refetchCanonicalState = q2(async () => {
23365
+ try {
23366
+ const data = await api("/messages");
23367
+ setMessages(data.messages ?? []);
23368
+ setBusy(Boolean(data.busy));
23369
+ setStreaming(null);
23370
+ setActiveTool(null);
23371
+ } catch {
23372
+ }
23373
+ try {
23374
+ const m3 = await api("/modal");
23375
+ setModal(m3.modal ?? null);
23376
+ } catch {
23377
+ }
23378
+ }, []);
23350
23379
  y2(() => {
23351
23380
  const es = new EventSource(`/api/events?token=${TOKEN}`);
23381
+ let firstOpen = true;
23382
+ es.onopen = () => {
23383
+ if (firstOpen) {
23384
+ firstOpen = false;
23385
+ return;
23386
+ }
23387
+ void refetchCanonicalState();
23388
+ };
23352
23389
  es.onmessage = (ev) => {
23353
23390
  let dash;
23354
23391
  try {
@@ -23430,7 +23467,7 @@ function ChatPanel() {
23430
23467
  setTimeout(() => setError(null), 3e3);
23431
23468
  };
23432
23469
  return () => es.close();
23433
- }, []);
23470
+ }, [refetchCanonicalState]);
23434
23471
  const send = q2(async () => {
23435
23472
  const text = input.trim();
23436
23473
  if (!text || busy) return;
@@ -23846,7 +23883,7 @@ function ChatPanel() {
23846
23883
  function SideRail({ stats, budgetUsd, activePlan }) {
23847
23884
  useLang();
23848
23885
  if (!stats && !activePlan) return html4`<aside class="chat-rail"></aside>`;
23849
- const cachePct = stats ? Math.round(stats.cacheHitRatio * 100) : 0;
23886
+ const cachePct = stats ? stats.cacheHitRatio * 100 : 0;
23850
23887
  const cacheTone = cachePct >= 80 ? "ok" : cachePct >= 50 ? "" : "warn";
23851
23888
  const showBudget = stats != null && typeof budgetUsd === "number" && budgetUsd > 0;
23852
23889
  const budgetPct = showBudget ? Math.min(120, stats.totalCostUsd / budgetUsd * 100) : 0;
@@ -23864,7 +23901,7 @@ function SideRail({ stats, budgetUsd, activePlan }) {
23864
23901
  <div class="progress-row" style="margin-top:8px">
23865
23902
  <span class="lbl">${t4("chat.railCacheHit")}</span>
23866
23903
  <div class=${`progress ${cacheTone}`}><div class="progress-fill" style=${`width:${cachePct}%`}></div></div>
23867
- <span class="v">${cachePct}%</span>
23904
+ <span class="v">${cachePct.toFixed(1)}%</span>
23868
23905
  </div>
23869
23906
  </div>
23870
23907
  ` : null}
@@ -24878,6 +24915,22 @@ function usePoll(path, intervalMs = 2e3) {
24878
24915
  return { data, error, loading, refresh };
24879
24916
  }
24880
24917
 
24918
+ // dashboard/src/lib/version.ts
24919
+ function compareVersions(a3, b2) {
24920
+ const [aCore = "0", aPre = ""] = a3.split("-", 2);
24921
+ const [bCore = "0", bPre = ""] = b2.split("-", 2);
24922
+ const aParts = aCore.split(".").map((p3) => Number.parseInt(p3, 10) || 0);
24923
+ const bParts = bCore.split(".").map((p3) => Number.parseInt(p3, 10) || 0);
24924
+ for (let i3 = 0; i3 < 3; i3++) {
24925
+ const diff = (aParts[i3] ?? 0) - (bParts[i3] ?? 0);
24926
+ if (diff !== 0) return diff;
24927
+ }
24928
+ if (!aPre && !bPre) return 0;
24929
+ if (!aPre) return 1;
24930
+ if (!bPre) return -1;
24931
+ return aPre < bPre ? -1 : aPre > bPre ? 1 : 0;
24932
+ }
24933
+
24881
24934
  // dashboard/src/panels/overview.ts
24882
24935
  function kpi(label, value, delta, deltaTone) {
24883
24936
  const muted = value === "\u2014" || value === null || value === void 0;
@@ -25060,7 +25113,7 @@ function OverviewPanel() {
25060
25113
  recentPlans: null,
25061
25114
  toolActivity: null
25062
25115
  };
25063
- const upToDate = o3.latestVersion ? o3.latestVersion === o3.version : null;
25116
+ const upToDate = o3.latestVersion && o3.version ? compareVersions(o3.version, o3.latestVersion) >= 0 : null;
25064
25117
  const versionDelta = upToDate === null ? t4("overview.checking") : upToDate ? t4("overview.latest") : `latest: ${o3.latestVersion}`;
25065
25118
  const versionTone = upToDate === false ? "down" : "flat";
25066
25119
  return html4`
@@ -27176,7 +27229,7 @@ function SystemPanel() {
27176
27229
  if (error) return html4`<div class="card accent-err">${t4("common.loadingFailed", { name: "health", error: error.message })}</div>`;
27177
27230
  if (!data) return null;
27178
27231
  const h3 = data;
27179
- const upToDate = h3.latestVersion ? h3.latestVersion === h3.version : null;
27232
+ const upToDate = h3.latestVersion ? compareVersions(h3.version, h3.latestVersion) >= 0 : null;
27180
27233
  return html4`
27181
27234
  <div style="display:flex;flex-direction:column;gap:14px">
27182
27235
  <h3 style="margin:0;font-family:var(--font-mono);font-size:11px;color:var(--fg-3);text-transform:uppercase;letter-spacing:.1em">${t4("system.healthChecks")}</h3>
@@ -27311,6 +27364,7 @@ function loadUPlot() {
27311
27364
  function UsageChart({ days: days2 }) {
27312
27365
  const containerRef = A2(null);
27313
27366
  const plotRef = A2(null);
27367
+ useLang();
27314
27368
  y2(() => {
27315
27369
  let cancelled = false;
27316
27370
  loadUPlot().then((uPlot2) => {
@@ -27338,7 +27392,7 @@ function UsageChart({ days: days2 }) {
27338
27392
  { stroke: "#94a3b8", grid: { stroke: "rgba(148, 163, 184, 0.08)" } },
27339
27393
  {
27340
27394
  scale: "y",
27341
- label: "USD",
27395
+ label: t4("usage.axisUsd"),
27342
27396
  stroke: "#94a3b8",
27343
27397
  grid: { stroke: "rgba(148, 163, 184, 0.08)" },
27344
27398
  values: (_u, v3) => v3.map((n3) => `$${n3.toFixed(4)}`)
@@ -27346,17 +27400,22 @@ function UsageChart({ days: days2 }) {
27346
27400
  {
27347
27401
  scale: "turns",
27348
27402
  side: 1,
27349
- label: "turns",
27403
+ label: t4("usage.axisTurns"),
27350
27404
  stroke: "#94a3b8",
27351
27405
  grid: { show: false }
27352
27406
  }
27353
27407
  ],
27354
27408
  series: [
27355
- {},
27356
- { label: "cost", stroke: "#67e8f9", width: 2, fill: "rgba(103, 232, 249, 0.10)" },
27357
- { label: "cache saved", stroke: "#5eead4", width: 2, dash: [4, 4] },
27409
+ { label: t4("usage.axisTime") },
27410
+ {
27411
+ label: t4("usage.seriesCost"),
27412
+ stroke: "#67e8f9",
27413
+ width: 2,
27414
+ fill: "rgba(103, 232, 249, 0.10)"
27415
+ },
27416
+ { label: t4("usage.seriesCacheSaved"), stroke: "#5eead4", width: 2, dash: [4, 4] },
27358
27417
  {
27359
- label: "turns",
27418
+ label: t4("usage.seriesTurns"),
27360
27419
  stroke: "#c4b5fd",
27361
27420
  scale: "turns",
27362
27421
  width: 1.5,
@@ -27442,13 +27501,13 @@ function UsagePanel() {
27442
27501
  <table class="tbl">
27443
27502
  <thead>
27444
27503
  <tr>
27445
- <th></th>
27446
- <th>${t4("usage.colTurns")}</th>
27447
- <th>${t4("usage.colCacheHit")}</th>
27448
- <th>${t4("usage.colCost")}</th>
27449
- <th>${t4("usage.colCacheSaved")}</th>
27450
- <th>${t4("usage.colVsClaude")}</th>
27451
- <th>${t4("usage.colSaved")}</th>
27504
+ <th>${t4("usage.colWindow")}</th>
27505
+ <th class="num">${t4("usage.colTurns")}</th>
27506
+ <th class="num">${t4("usage.colCacheHit")}</th>
27507
+ <th class="num">${t4("usage.colCost")}</th>
27508
+ <th class="num">${t4("usage.colCacheSaved")}</th>
27509
+ <th class="num">${t4("usage.colVsClaude")}</th>
27510
+ <th class="num">${t4("usage.colSaved")}</th>
27452
27511
  </tr>
27453
27512
  </thead>
27454
27513
  <tbody>