opencode-visual-cache 1.5.0 → 1.6.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 +10 -4
- package/README_EN.md +10 -4
- package/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/i18n.d.ts +102 -0
- package/dist/i18n.js +368 -0
- package/dist/index.js +420 -254
- package/dist/tui.js +1086 -411
- package/package.json +1 -1
- package/src/_version.ts +1 -1
- package/src/i18n.ts +380 -0
- package/src/index.tsx +499 -304
package/dist/tui.js
CHANGED
|
@@ -13,7 +13,7 @@ import { createElement as _$createElement } from "@opentui/solid";
|
|
|
13
13
|
import { createMemo, createSignal, createEffect, onMount, onCleanup, Show, untrack } from "solid-js";
|
|
14
14
|
|
|
15
15
|
// src/_version.ts
|
|
16
|
-
var PLUGIN_VERSION = "1.
|
|
16
|
+
var PLUGIN_VERSION = "1.6.0";
|
|
17
17
|
|
|
18
18
|
// src/balance-providers.ts
|
|
19
19
|
var BalanceError = class extends Error {
|
|
@@ -117,51 +117,7 @@ function maskKey(k) {
|
|
|
117
117
|
return k.slice(0, 5) + "*".repeat(Math.max(3, k.length - 10)) + k.slice(-5);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
// src/
|
|
121
|
-
function charColumns(c) {
|
|
122
|
-
const code = c.codePointAt(0) ?? 0;
|
|
123
|
-
if (code < 32) return 0;
|
|
124
|
-
if (code < 127) return 1;
|
|
125
|
-
if (code < 160) return 0;
|
|
126
|
-
if (code >= 4352 && code <= 4447 || // Hangul Jamo
|
|
127
|
-
code >= 11904 && code <= 42191 || // CJK Radicals … Yi
|
|
128
|
-
code >= 44032 && code <= 55203 || // Hangul
|
|
129
|
-
code >= 63744 && code <= 64255 || // CJK Compat
|
|
130
|
-
code >= 65040 && code <= 65135 || // Vertical / Compat
|
|
131
|
-
code >= 65281 && code <= 65376 || // Fullwidth
|
|
132
|
-
code >= 65504 && code <= 65510 || // Fullwidth signs
|
|
133
|
-
code >= 127744 && code <= 128591 || // Misc Symbols (emoji)
|
|
134
|
-
code >= 131072 && code <= 262141)
|
|
135
|
-
return 2;
|
|
136
|
-
return 1;
|
|
137
|
-
}
|
|
138
|
-
function visualWidth(s) {
|
|
139
|
-
let w = 0;
|
|
140
|
-
for (const c of s) w += charColumns(c);
|
|
141
|
-
return w;
|
|
142
|
-
}
|
|
143
|
-
function truncateVisual(s, maxCols) {
|
|
144
|
-
if (visualWidth(s) <= maxCols) return s;
|
|
145
|
-
let result = "", w = 0;
|
|
146
|
-
for (const c of s) {
|
|
147
|
-
const cw = charColumns(c);
|
|
148
|
-
if (w + cw > maxCols - 1) {
|
|
149
|
-
result += "\u2026";
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
result += c;
|
|
153
|
-
w += cw;
|
|
154
|
-
}
|
|
155
|
-
return result;
|
|
156
|
-
}
|
|
157
|
-
var DEBUG_LANG = typeof process !== "undefined" ? process.env?.CACHE_TUI_LANG : void 0;
|
|
158
|
-
var LANG_ZH = DEBUG_LANG ? DEBUG_LANG === "zh" : (() => {
|
|
159
|
-
try {
|
|
160
|
-
return Intl.DateTimeFormat().resolvedOptions().locale.startsWith("zh");
|
|
161
|
-
} catch {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
})();
|
|
120
|
+
// src/i18n.ts
|
|
165
121
|
var ZH_T = {
|
|
166
122
|
title: "\u7F13\u5B58\u7EDF\u8BA1",
|
|
167
123
|
hit: "\u547D\u4E2D\u7387",
|
|
@@ -199,7 +155,49 @@ var ZH_T = {
|
|
|
199
155
|
balErr401: "API Key \u65E0\u6548",
|
|
200
156
|
balErr403: "\u4F59\u989D\u67E5\u8BE2\u88AB\u62D2\u7EDD",
|
|
201
157
|
balErrEmpty: "\u672A\u83B7\u53D6\u5230\u4F59\u989D\u6570\u636E",
|
|
202
|
-
balErrTimeout: "\u67E5\u8BE2\u8D85\u65F6"
|
|
158
|
+
balErrTimeout: "\u67E5\u8BE2\u8D85\u65F6",
|
|
159
|
+
balUnsupported: "\u5F53\u524D\u63D0\u4F9B\u5546\u4E0D\u652F\u6301\u4F59\u989D\u67E5\u8BE2",
|
|
160
|
+
barHit: "\u547D\u4E2D\u7387",
|
|
161
|
+
barBal: "\u4F59\u989D",
|
|
162
|
+
barTok: "Tokens",
|
|
163
|
+
// ── /cache-section 面板 ──
|
|
164
|
+
secToggle: "\u5207\u6362\u533A\u5757",
|
|
165
|
+
secBalance: "\u4F59\u989D",
|
|
166
|
+
secBottom: "\u5E95\u90E8\u72B6\u6001\u680F",
|
|
167
|
+
secBorder: "\u9762\u677F\u8FB9\u6846",
|
|
168
|
+
// ── toast ──
|
|
169
|
+
keySaved: "API Key \u5DF2\u4FDD\u5B58\uFF0C\u6B63\u5728\u67E5\u8BE2\u4F59\u989D...",
|
|
170
|
+
keyCleared: "API Key \u5DF2\u6E05\u9664",
|
|
171
|
+
currencySet: "\u5E01\u79CD: {v} ({s}), \u6C47\u7387: {r}",
|
|
172
|
+
rateSet: "\u6C47\u7387\u5DF2\u8BBE\u4E3A {r}",
|
|
173
|
+
panelConfigTitle: "\u7F13\u5B58\u9762\u677F\u914D\u7F6E",
|
|
174
|
+
panelConfigMsg: "\u5E01\u79CD: {c} | \u6C47\u7387: {r} | \u660E\u7EC6: {d} | \u6A21\u578B: {m} | \u5206\u5E03: {t} | \u6280\u80FD: {k} | \u4F59\u989D: {b} | \u5E95\u90E8: {f}",
|
|
175
|
+
borderShown: "\u9762\u677F\u8FB9\u6846 \u5DF2\u663E\u793A",
|
|
176
|
+
borderHidden: "\u9762\u677F\u8FB9\u6846 \u5DF2\u9690\u85CF",
|
|
177
|
+
sectionShown: "{s} \u5DF2\u663E\u793A",
|
|
178
|
+
sectionHidden: "{s} \u5DF2\u9690\u85CF",
|
|
179
|
+
langSwitched: "\u8BED\u8A00\u5DF2\u5207\u6362\u4E3A\u4E2D\u6587",
|
|
180
|
+
autoSwitchOn: "\u81EA\u52A8\u5207\u6362\u4F59\u989D\u63D0\u4F9B\u5546: \u5F00",
|
|
181
|
+
autoSwitchOff: "\u81EA\u52A8\u5207\u6362\u4F59\u989D\u63D0\u4F9B\u5546: \u5173",
|
|
182
|
+
providerManual: "\u4F59\u989D\u63D0\u4F9B\u5546: {p}\uFF08\u81EA\u52A8\u5207\u6362\u5DF2\u5173\u95ED\uFF09",
|
|
183
|
+
runInSession: "\u8BF7\u5728\u4F1A\u8BDD\u5185\u8FD0\u884C\u6B64\u547D\u4EE4",
|
|
184
|
+
backToMain: "\u5DF2\u5207\u56DE\u4E3B\u4F1A\u8BDD",
|
|
185
|
+
subAgentSwitched: "\u5DF2\u5207\u6362\u81F3\u5B50\u4EE3\u7406: {s}",
|
|
186
|
+
// ── 对话框 / 菜单 ──
|
|
187
|
+
langTitle: "\u663E\u793A\u8BED\u8A00",
|
|
188
|
+
subPrefix: "\u5B50\u4EE3\u7406: ",
|
|
189
|
+
keyUser: "\uFF08\u7528\u6237 key\uFF09",
|
|
190
|
+
keyOpenCode: "\uFF08OpenCode\uFF09",
|
|
191
|
+
keyNotSet: "\uFF08\u672A\u914D\u7F6E\uFF09",
|
|
192
|
+
balKeyPrompt: "\u8F93\u5165 {p} API Key \u4EE5\u663E\u793A\u8D26\u6237\u4F59\u989D\uFF08\u7559\u7A7A\u6E05\u9664\uFF09",
|
|
193
|
+
balProvTitle: "\u4F59\u989D\u63D0\u4F9B\u5546 / \u81EA\u52A8\u5207\u6362",
|
|
194
|
+
autoSwitchOpt: "\u81EA\u52A8\u5207\u6362\u63D0\u4F9B\u5546",
|
|
195
|
+
balSelectTitle: "\u9009\u62E9\u4F59\u989D\u63D0\u4F9B\u5546",
|
|
196
|
+
backToMainTitle: "\u56DE\u5230\u4E3B\u4F1A\u8BDD",
|
|
197
|
+
subSelectTitle: "\u9009\u62E9\u5B50\u4EE3\u7406",
|
|
198
|
+
subSwitchTitle: "\u5207\u6362\u5B50\u4EE3\u7406",
|
|
199
|
+
subViewTitle: "\u67E5\u770B\u5B50\u4EE3\u7406\u7F13\u5B58",
|
|
200
|
+
subNoFound: "\u672A\u627E\u5230\u5B50\u4EE3\u7406\uFF0C\u8BF7\u624B\u52A8\u7C98\u8D34 Session ID"
|
|
203
201
|
};
|
|
204
202
|
var EN_T = {
|
|
205
203
|
title: "Token Cache",
|
|
@@ -238,8 +236,284 @@ var EN_T = {
|
|
|
238
236
|
balErr401: "Invalid API Key",
|
|
239
237
|
balErr403: "Balance request rejected",
|
|
240
238
|
balErrEmpty: "No balance data",
|
|
241
|
-
balErrTimeout: "Request timed out"
|
|
239
|
+
balErrTimeout: "Request timed out",
|
|
240
|
+
balUnsupported: "Balance query unsupported",
|
|
241
|
+
barHit: "Hit",
|
|
242
|
+
barBal: "Balance",
|
|
243
|
+
barTok: "Tokens",
|
|
244
|
+
// ── /cache-section panel ──
|
|
245
|
+
secToggle: "Toggle Section",
|
|
246
|
+
secBalance: "Balance",
|
|
247
|
+
secBottom: "Bottom Bar",
|
|
248
|
+
secBorder: "Panel Border",
|
|
249
|
+
// ── toasts ──
|
|
250
|
+
keySaved: "API Key saved, fetching balance...",
|
|
251
|
+
keyCleared: "API Key cleared",
|
|
252
|
+
currencySet: "Currency: {v} ({s}), rate: {r}",
|
|
253
|
+
rateSet: "Exchange rate set to {r}",
|
|
254
|
+
panelConfigTitle: "Cache Panel Config",
|
|
255
|
+
panelConfigMsg: "Currency: {c} | Rate: {r} | Detail: {d} | Model: {m} | Dist: {t} | Skills: {k} | Balance: {b} | Bottom: {f}",
|
|
256
|
+
borderShown: "Panel border shown",
|
|
257
|
+
borderHidden: "Panel border hidden",
|
|
258
|
+
sectionShown: "{s} section shown",
|
|
259
|
+
sectionHidden: "{s} section hidden",
|
|
260
|
+
langSwitched: "Switched to English",
|
|
261
|
+
autoSwitchOn: "Auto-switch balance provider: ON",
|
|
262
|
+
autoSwitchOff: "Auto-switch balance provider: OFF",
|
|
263
|
+
providerManual: "Balance provider: {p} (auto-switch off)",
|
|
264
|
+
runInSession: "Please run this command inside a session",
|
|
265
|
+
backToMain: "Switched to main session",
|
|
266
|
+
subAgentSwitched: "Showing sub-agent: {s}",
|
|
267
|
+
// ── dialogs / menus ──
|
|
268
|
+
langTitle: "Display Language",
|
|
269
|
+
subPrefix: "Sub: ",
|
|
270
|
+
keyUser: " (user key)",
|
|
271
|
+
keyOpenCode: " (OpenCode)",
|
|
272
|
+
keyNotSet: " (not set)",
|
|
273
|
+
balKeyPrompt: "Enter your {p} API key to show account balance (leave empty to clear)",
|
|
274
|
+
balProvTitle: "Balance Provider / Auto-switch",
|
|
275
|
+
autoSwitchOpt: "Auto-switch provider",
|
|
276
|
+
balSelectTitle: "Select Balance Provider",
|
|
277
|
+
backToMainTitle: "Back to Main",
|
|
278
|
+
subSelectTitle: "Select Sub-Agent",
|
|
279
|
+
subSwitchTitle: "Switch Sub",
|
|
280
|
+
subViewTitle: "View Sub Cache",
|
|
281
|
+
subNoFound: "No sub-agents found. Paste a Session ID manually"
|
|
242
282
|
};
|
|
283
|
+
var JA_T = {
|
|
284
|
+
title: "\u30AD\u30E3\u30C3\u30B7\u30E5\u7D71\u8A08",
|
|
285
|
+
hit: "\u30D2\u30C3\u30C8\u7387",
|
|
286
|
+
totalHit: "\u7DCF\u30D2\u30C3\u30C8:",
|
|
287
|
+
read: "\u30AD\u30E3\u30C3\u30B7\u30E5\u8AAD\u8FBC:",
|
|
288
|
+
write: "\u30AD\u30E3\u30C3\u30B7\u30E5\u66F8\u8FBC:",
|
|
289
|
+
miss: "\u672A\u30D2\u30C3\u30C8:",
|
|
290
|
+
out: "\u51FA\u529B:",
|
|
291
|
+
cost: "\u8CBB\u7528:",
|
|
292
|
+
saved: "\u7D2F\u8A08\u7BC0\u7D04:",
|
|
293
|
+
model: "\u30E2\u30C7\u30EB:",
|
|
294
|
+
provider: "\u30D7\u30ED\u30D0\u30A4\u30C0:",
|
|
295
|
+
rate: "\u5358\u4FA1:",
|
|
296
|
+
hitFolded: "\u30D2\u30C3\u30C8",
|
|
297
|
+
inputRate: "\u5165\u529B",
|
|
298
|
+
cacheRate: "\u30AD\u30E3\u30C3\u30B7\u30E5",
|
|
299
|
+
writeRate: "\u66F8\u8FBC",
|
|
300
|
+
noData: "\u30AD\u30E3\u30C3\u30B7\u30E5\u30C7\u30FC\u30BF\u5F85\u6A5F\u4E2D...",
|
|
301
|
+
tok: "tok",
|
|
302
|
+
distTitle: "Token \u5206\u5E03\uFF08\u63A8\u5B9A\uFF09",
|
|
303
|
+
distSys: "\u30B7\u30B9\u30C6\u30E0:",
|
|
304
|
+
distUser: "\u30E6\u30FC\u30B6\u30FC:",
|
|
305
|
+
distAgent: "Agent \u6307\u793A:",
|
|
306
|
+
distTool: "Tool \u547C\u3073\u51FA\u3057:",
|
|
307
|
+
distRes: "Tool \u7D50\u679C:",
|
|
308
|
+
distTotal: "\u5408\u8A08:",
|
|
309
|
+
distOut: "\u51FA\u529B:",
|
|
310
|
+
secDetail: "\u660E\u7D30",
|
|
311
|
+
secModel: "\u30E2\u30C7\u30EB",
|
|
312
|
+
secSkills: "\u8AAD\u307F\u8FBC\u307F\u6E08\u307F\u30B9\u30AD\u30EB",
|
|
313
|
+
balTotal: "\u7DCF\u6B8B\u9AD8:",
|
|
314
|
+
balNoKey: "{p} \u306E API Key \u672A\u8A2D\u5B9A",
|
|
315
|
+
balLoading: "\u53D6\u5F97\u4E2D...",
|
|
316
|
+
balError: "\u53D6\u5F97\u5931\u6557",
|
|
317
|
+
balErr401: "API Key \u7121\u52B9",
|
|
318
|
+
balErr403: "\u6B8B\u9AD8\u7167\u4F1A\u304C\u62D2\u5426\u3055\u308C\u307E\u3057\u305F",
|
|
319
|
+
balErrEmpty: "\u6B8B\u9AD8\u30C7\u30FC\u30BF\u306A\u3057",
|
|
320
|
+
balErrTimeout: "\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8",
|
|
321
|
+
balUnsupported: "\u3053\u306E\u30D7\u30ED\u30D0\u30A4\u30C0\u306F\u6B8B\u9AD8\u7167\u4F1A\u975E\u5BFE\u5FDC",
|
|
322
|
+
barHit: "\u30D2\u30C3\u30C8\u7387",
|
|
323
|
+
barBal: "\u6B8B\u9AD8",
|
|
324
|
+
barTok: "Tokens",
|
|
325
|
+
// ── /cache-section パネル ──
|
|
326
|
+
secToggle: "\u30BB\u30AF\u30B7\u30E7\u30F3\u5207\u66FF",
|
|
327
|
+
secBalance: "\u6B8B\u9AD8",
|
|
328
|
+
secBottom: "\u4E0B\u90E8\u30B9\u30C6\u30FC\u30BF\u30B9\u30D0\u30FC",
|
|
329
|
+
secBorder: "\u30D1\u30CD\u30EB\u67A0\u7DDA",
|
|
330
|
+
// ── toast ──
|
|
331
|
+
keySaved: "API Key \u4FDD\u5B58\u6E08\u307F\u3001\u6B8B\u9AD8\u3092\u53D6\u5F97\u4E2D...",
|
|
332
|
+
keyCleared: "API Key \u3092\u30AF\u30EA\u30A2\u3057\u307E\u3057\u305F",
|
|
333
|
+
currencySet: "\u901A\u8CA8: {v} ({s}), \u30EC\u30FC\u30C8: {r}",
|
|
334
|
+
rateSet: "\u30EC\u30FC\u30C8\u3092 {r} \u306B\u8A2D\u5B9A\u3057\u307E\u3057\u305F",
|
|
335
|
+
panelConfigTitle: "\u30D1\u30CD\u30EB\u8A2D\u5B9A",
|
|
336
|
+
panelConfigMsg: "\u901A\u8CA8: {c} | \u30EC\u30FC\u30C8: {r} | \u660E\u7D30: {d} | \u30E2\u30C7\u30EB: {m} | \u5206\u5E03: {t} | \u30B9\u30AD\u30EB: {k} | \u6B8B\u9AD8: {b} | \u4E0B\u90E8: {f}",
|
|
337
|
+
borderShown: "\u30D1\u30CD\u30EB\u67A0\u7DDA \u8868\u793A",
|
|
338
|
+
borderHidden: "\u30D1\u30CD\u30EB\u67A0\u7DDA \u975E\u8868\u793A",
|
|
339
|
+
sectionShown: "{s} \u8868\u793A",
|
|
340
|
+
sectionHidden: "{s} \u975E\u8868\u793A",
|
|
341
|
+
langSwitched: "\u65E5\u672C\u8A9E\u306B\u5207\u308A\u66FF\u3048\u307E\u3057\u305F",
|
|
342
|
+
autoSwitchOn: "\u6B8B\u9AD8\u30D7\u30ED\u30D0\u30A4\u30C0\u81EA\u52D5\u5207\u66FF: \u30AA\u30F3",
|
|
343
|
+
autoSwitchOff: "\u6B8B\u9AD8\u30D7\u30ED\u30D0\u30A4\u30C0\u81EA\u52D5\u5207\u66FF: \u30AA\u30D5",
|
|
344
|
+
providerManual: "\u6B8B\u9AD8\u30D7\u30ED\u30D0\u30A4\u30C0: {p}\uFF08\u81EA\u52D5\u5207\u66FF\u30AA\u30D5\uFF09",
|
|
345
|
+
runInSession: "\u30BB\u30C3\u30B7\u30E7\u30F3\u5185\u3067\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
346
|
+
backToMain: "\u30E1\u30A4\u30F3\u30BB\u30C3\u30B7\u30E7\u30F3\u306B\u623B\u308A\u307E\u3057\u305F",
|
|
347
|
+
subAgentSwitched: "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u3078\u5207\u66FF: {s}",
|
|
348
|
+
// ── ダイアログ / メニュー ──
|
|
349
|
+
langTitle: "\u8868\u793A\u8A00\u8A9E",
|
|
350
|
+
subPrefix: "\u30B5\u30D6: ",
|
|
351
|
+
keyUser: "\uFF08\u30E6\u30FC\u30B6\u30FC key\uFF09",
|
|
352
|
+
keyOpenCode: "\uFF08OpenCode\uFF09",
|
|
353
|
+
keyNotSet: "\uFF08\u672A\u8A2D\u5B9A\uFF09",
|
|
354
|
+
balKeyPrompt: "{p} \u306E API Key \u3092\u5165\u529B\u3057\u3066\u6B8B\u9AD8\u3092\u8868\u793A\uFF08\u7A7A\u6B04\u3067\u30AF\u30EA\u30A2\uFF09",
|
|
355
|
+
balProvTitle: "\u6B8B\u9AD8\u30D7\u30ED\u30D0\u30A4\u30C0 / \u81EA\u52D5\u5207\u66FF",
|
|
356
|
+
autoSwitchOpt: "\u81EA\u52D5\u5207\u66FF\u30D7\u30ED\u30D0\u30A4\u30C0",
|
|
357
|
+
balSelectTitle: "\u6B8B\u9AD8\u30D7\u30ED\u30D0\u30A4\u30C0\u9078\u629E",
|
|
358
|
+
backToMainTitle: "\u30E1\u30A4\u30F3\u306B\u623B\u308B",
|
|
359
|
+
subSelectTitle: "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u9078\u629E",
|
|
360
|
+
subSwitchTitle: "\u30B5\u30D6\u5207\u66FF",
|
|
361
|
+
subViewTitle: "\u30B5\u30D6\u30AD\u30E3\u30C3\u30B7\u30E5\u8868\u793A",
|
|
362
|
+
subNoFound: "\u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002Session ID \u3092\u624B\u52D5\u3067\u8CBC\u308A\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044"
|
|
363
|
+
};
|
|
364
|
+
var KO_T = {
|
|
365
|
+
title: "\uCE90\uC2DC \uD1B5\uACC4",
|
|
366
|
+
hit: "\uD788\uD2B8\uC728",
|
|
367
|
+
totalHit: "\uCD1D \uD788\uD2B8:",
|
|
368
|
+
read: "\uCE90\uC2DC \uC77D\uAE30:",
|
|
369
|
+
write: "\uCE90\uC2DC \uC4F0\uAE30:",
|
|
370
|
+
miss: "\uBBF8\uD788\uD2B8:",
|
|
371
|
+
out: "\uCD9C\uB825:",
|
|
372
|
+
cost: "\uBE44\uC6A9:",
|
|
373
|
+
saved: "\uB204\uC801 \uC808\uC57D:",
|
|
374
|
+
model: "\uBAA8\uB378:",
|
|
375
|
+
provider: "\uD504\uB85C\uBC14\uC774\uB354:",
|
|
376
|
+
rate: "\uB2E8\uAC00:",
|
|
377
|
+
hitFolded: "\uD788\uD2B8",
|
|
378
|
+
inputRate: "\uC785\uB825",
|
|
379
|
+
cacheRate: "\uCE90\uC2DC",
|
|
380
|
+
writeRate: "\uC4F0\uAE30",
|
|
381
|
+
noData: "\uCE90\uC2DC \uB370\uC774\uD130 \uB300\uAE30 \uC911...",
|
|
382
|
+
tok: "tok",
|
|
383
|
+
distTitle: "Token \uBD84\uD3EC(\uCD94\uC815)",
|
|
384
|
+
distSys: "\uC2DC\uC2A4\uD15C:",
|
|
385
|
+
distUser: "\uC0AC\uC6A9\uC790:",
|
|
386
|
+
distAgent: "Agent \uC9C0\uC2DC:",
|
|
387
|
+
distTool: "Tool \uD638\uCD9C:",
|
|
388
|
+
distRes: "Tool \uACB0\uACFC:",
|
|
389
|
+
distTotal: "\uD569\uACC4:",
|
|
390
|
+
distOut: "\uCD9C\uB825:",
|
|
391
|
+
secDetail: "\uC0C1\uC138",
|
|
392
|
+
secModel: "\uBAA8\uB378",
|
|
393
|
+
secSkills: "\uB85C\uB4DC\uB41C \uC2A4\uD0AC",
|
|
394
|
+
balTotal: "\uCD1D \uC794\uC561:",
|
|
395
|
+
balNoKey: "{p} API Key \uBBF8\uC124\uC815",
|
|
396
|
+
balLoading: "\uC870\uD68C \uC911...",
|
|
397
|
+
balError: "\uC870\uD68C \uC2E4\uD328",
|
|
398
|
+
balErr401: "API Key \uBB34\uD6A8",
|
|
399
|
+
balErr403: "\uC794\uC561 \uC870\uD68C\uAC00 \uAC70\uBD80\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
|
|
400
|
+
balErrEmpty: "\uC794\uC561 \uB370\uC774\uD130 \uC5C6\uC74C",
|
|
401
|
+
balErrTimeout: "\uC2DC\uAC04 \uCD08\uACFC",
|
|
402
|
+
balUnsupported: "\uC774 \uD504\uB85C\uBC14\uC774\uB354\uB294 \uC794\uC561 \uC870\uD68C \uBBF8\uC9C0\uC6D0",
|
|
403
|
+
barHit: "\uD788\uD2B8\uC728",
|
|
404
|
+
barBal: "\uC794\uC561",
|
|
405
|
+
barTok: "Tokens",
|
|
406
|
+
// ── /cache-section 패널 ──
|
|
407
|
+
secToggle: "\uC139\uC158 \uC804\uD658",
|
|
408
|
+
secBalance: "\uC794\uC561",
|
|
409
|
+
secBottom: "\uD558\uB2E8 \uC0C1\uD0DC\uBC14",
|
|
410
|
+
secBorder: "\uD328\uB110 \uD14C\uB450\uB9AC",
|
|
411
|
+
// ── toast ──
|
|
412
|
+
keySaved: "API Key \uC800\uC7A5\uB428, \uC794\uC561 \uC870\uD68C \uC911...",
|
|
413
|
+
keyCleared: "API Key \uC0AD\uC81C\uB428",
|
|
414
|
+
currencySet: "\uD1B5\uD654: {v} ({s}), \uD658\uC728: {r}",
|
|
415
|
+
rateSet: "\uD658\uC728\uC744 {r}(\uC73C)\uB85C \uC124\uC815\uD588\uC2B5\uB2C8\uB2E4",
|
|
416
|
+
panelConfigTitle: "\uD328\uB110 \uC124\uC815",
|
|
417
|
+
panelConfigMsg: "\uD1B5\uD654: {c} | \uD658\uC728: {r} | \uC0C1\uC138: {d} | \uBAA8\uB378: {m} | \uBD84\uD3EC: {t} | \uC2A4\uD0AC: {k} | \uC794\uC561: {b} | \uD558\uB2E8: {f}",
|
|
418
|
+
borderShown: "\uD328\uB110 \uD14C\uB450\uB9AC \uD45C\uC2DC",
|
|
419
|
+
borderHidden: "\uD328\uB110 \uD14C\uB450\uB9AC \uC228\uAE40",
|
|
420
|
+
sectionShown: "{s} \uD45C\uC2DC",
|
|
421
|
+
sectionHidden: "{s} \uC228\uAE40",
|
|
422
|
+
langSwitched: "\uD55C\uAD6D\uC5B4\uB85C \uC804\uD658\uD588\uC2B5\uB2C8\uB2E4",
|
|
423
|
+
autoSwitchOn: "\uC794\uC561 \uD504\uB85C\uBC14\uC774\uB354 \uC790\uB3D9 \uC804\uD658: \uCF1C\uC9D0",
|
|
424
|
+
autoSwitchOff: "\uC794\uC561 \uD504\uB85C\uBC14\uC774\uB354 \uC790\uB3D9 \uC804\uD658: \uAEBC\uC9D0",
|
|
425
|
+
providerManual: "\uC794\uC561 \uD504\uB85C\uBC14\uC774\uB354: {p}(\uC790\uB3D9 \uC804\uD658 \uAEBC\uC9D0)",
|
|
426
|
+
runInSession: "\uC138\uC158 \uB0B4\uC5D0\uC11C \uC2E4\uD589\uD574 \uC8FC\uC138\uC694",
|
|
427
|
+
backToMain: "\uBA54\uC778 \uC138\uC158\uC73C\uB85C \uB3CC\uC544\uAC14\uC2B5\uB2C8\uB2E4",
|
|
428
|
+
subAgentSwitched: "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8\uB85C \uC804\uD658: {s}",
|
|
429
|
+
// ── 다이얼로그 / 메뉴 ──
|
|
430
|
+
langTitle: "\uD45C\uC2DC \uC5B8\uC5B4",
|
|
431
|
+
subPrefix: "\uC11C\uBE0C: ",
|
|
432
|
+
keyUser: "(\uC0AC\uC6A9\uC790 key)",
|
|
433
|
+
keyOpenCode: "(OpenCode)",
|
|
434
|
+
keyNotSet: "(\uBBF8\uC124\uC815)",
|
|
435
|
+
balKeyPrompt: "{p} API Key\uB97C \uC785\uB825\uD558\uC5EC \uC794\uC561 \uD45C\uC2DC(\uBE44\uC6B0\uBA74 \uC0AD\uC81C)",
|
|
436
|
+
balProvTitle: "\uC794\uC561 \uD504\uB85C\uBC14\uC774\uB354 / \uC790\uB3D9 \uC804\uD658",
|
|
437
|
+
autoSwitchOpt: "\uC790\uB3D9 \uC804\uD658 \uD504\uB85C\uBC14\uC774\uB354",
|
|
438
|
+
balSelectTitle: "\uC794\uC561 \uD504\uB85C\uBC14\uC774\uB354 \uC120\uD0DD",
|
|
439
|
+
backToMainTitle: "\uBA54\uC778\uC73C\uB85C \uB3CC\uC544\uAC00\uAE30",
|
|
440
|
+
subSelectTitle: "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8 \uC120\uD0DD",
|
|
441
|
+
subSwitchTitle: "\uC11C\uBE0C \uC804\uD658",
|
|
442
|
+
subViewTitle: "\uC11C\uBE0C \uCE90\uC2DC \uBCF4\uAE30",
|
|
443
|
+
subNoFound: "\uC11C\uBE0C \uC5D0\uC774\uC804\uD2B8\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. Session ID\uB97C \uC9C1\uC811 \uBD99\uC5EC\uB123\uC73C\uC138\uC694"
|
|
444
|
+
};
|
|
445
|
+
var LANGS = { zh: ZH_T, en: EN_T, ja: JA_T, ko: KO_T };
|
|
446
|
+
var LANG_META = [
|
|
447
|
+
{ code: "zh", label: "\u4E2D\u6587" },
|
|
448
|
+
{ code: "en", label: "English" },
|
|
449
|
+
{ code: "ja", label: "\u65E5\u672C\u8A9E" },
|
|
450
|
+
{ code: "ko", label: "\uD55C\uAD6D\uC5B4" }
|
|
451
|
+
];
|
|
452
|
+
function applyParams(tpl, params) {
|
|
453
|
+
if (!params) return tpl;
|
|
454
|
+
return tpl.replace(
|
|
455
|
+
/\{(\w+)\}/g,
|
|
456
|
+
(m, k) => k in params ? String(params[k]) : m
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
function createT(getCode) {
|
|
460
|
+
return (key, params) => applyParams(LANGS[getCode()][key], params);
|
|
461
|
+
}
|
|
462
|
+
function detectLang() {
|
|
463
|
+
try {
|
|
464
|
+
const loc = Intl.DateTimeFormat().resolvedOptions().locale.toLowerCase();
|
|
465
|
+
if (loc.startsWith("zh")) return "zh";
|
|
466
|
+
if (loc.startsWith("ja")) return "ja";
|
|
467
|
+
if (loc.startsWith("ko")) return "ko";
|
|
468
|
+
return "en";
|
|
469
|
+
} catch {
|
|
470
|
+
return "en";
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// src/index.tsx
|
|
475
|
+
function charColumns(c) {
|
|
476
|
+
const code = c.codePointAt(0) ?? 0;
|
|
477
|
+
if (code < 32) return 0;
|
|
478
|
+
if (code < 127) return 1;
|
|
479
|
+
if (code < 160) return 0;
|
|
480
|
+
if (code >= 4352 && code <= 4447 || // Hangul Jamo
|
|
481
|
+
code >= 11904 && code <= 42191 || // CJK Radicals … Yi
|
|
482
|
+
code >= 44032 && code <= 55203 || // Hangul
|
|
483
|
+
code >= 63744 && code <= 64255 || // CJK Compat
|
|
484
|
+
code >= 65040 && code <= 65135 || // Vertical / Compat
|
|
485
|
+
code >= 65281 && code <= 65376 || // Fullwidth
|
|
486
|
+
code >= 65504 && code <= 65510 || // Fullwidth signs
|
|
487
|
+
code >= 127744 && code <= 128591 || // Misc Symbols (emoji)
|
|
488
|
+
code >= 131072 && code <= 262141)
|
|
489
|
+
return 2;
|
|
490
|
+
return 1;
|
|
491
|
+
}
|
|
492
|
+
function visualWidth(s) {
|
|
493
|
+
let w = 0;
|
|
494
|
+
for (const c of s) w += charColumns(c);
|
|
495
|
+
return w;
|
|
496
|
+
}
|
|
497
|
+
function visualPadEnd(s, cols) {
|
|
498
|
+
const pad = cols - visualWidth(s);
|
|
499
|
+
return pad > 0 ? s + " ".repeat(pad) : s;
|
|
500
|
+
}
|
|
501
|
+
function truncateVisual(s, maxCols) {
|
|
502
|
+
if (visualWidth(s) <= maxCols) return s;
|
|
503
|
+
let result = "", w = 0;
|
|
504
|
+
for (const c of s) {
|
|
505
|
+
const cw = charColumns(c);
|
|
506
|
+
if (w + cw > maxCols - 1) {
|
|
507
|
+
result += "\u2026";
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
result += c;
|
|
511
|
+
w += cw;
|
|
512
|
+
}
|
|
513
|
+
return result;
|
|
514
|
+
}
|
|
515
|
+
var DEBUG_LANG = typeof process !== "undefined" ? process.env?.CACHE_TUI_LANG : void 0;
|
|
516
|
+
var INIT_LANG = DEBUG_LANG !== void 0 && LANG_META.some((m) => m.code === DEBUG_LANG) ? DEBUG_LANG : detectLang();
|
|
243
517
|
function rgb(raw) {
|
|
244
518
|
if (typeof raw === "string" && raw.startsWith("#")) {
|
|
245
519
|
const h = raw.slice(1);
|
|
@@ -374,6 +648,33 @@ function balanceSymbol(currency) {
|
|
|
374
648
|
const sym = CURRENCIES[currency];
|
|
375
649
|
return sym ?? currency + " ";
|
|
376
650
|
}
|
|
651
|
+
function fmtCompact(n) {
|
|
652
|
+
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
|
|
653
|
+
if (n >= 1e3) return (n / 1e3).toFixed(1) + "K";
|
|
654
|
+
return String(Math.round(n));
|
|
655
|
+
}
|
|
656
|
+
function formatBalanceAmount(total) {
|
|
657
|
+
const n = parseFloat(total);
|
|
658
|
+
if (!Number.isFinite(n)) return total;
|
|
659
|
+
if (n === 0 || n >= 1) return n.toLocaleString("en-US", {
|
|
660
|
+
minimumFractionDigits: 2,
|
|
661
|
+
maximumFractionDigits: 2
|
|
662
|
+
});
|
|
663
|
+
return n.toLocaleString("en-US", {
|
|
664
|
+
maximumFractionDigits: 6
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
function formatBalanceText(list, pref, rate) {
|
|
668
|
+
const native = pref ? list.find((x) => x.currency === pref) : void 0;
|
|
669
|
+
if (native) return balanceSymbol(native.currency) + formatBalanceAmount(native.total);
|
|
670
|
+
const base = list[0];
|
|
671
|
+
const baseAmt = parseFloat(base.total);
|
|
672
|
+
const converted = Number.isFinite(baseAmt) ? convertBalance(pref || base.currency, rate, baseAmt, base.currency) : baseAmt;
|
|
673
|
+
const shown = pref && base.currency !== pref ? converted.toLocaleString("en-US", {
|
|
674
|
+
maximumFractionDigits: 2
|
|
675
|
+
}) : formatBalanceAmount(base.total);
|
|
676
|
+
return balanceSymbol(pref || base.currency) + shown;
|
|
677
|
+
}
|
|
377
678
|
var CURRENCIES = {
|
|
378
679
|
USD: "$",
|
|
379
680
|
CNY: "\xA5",
|
|
@@ -411,8 +712,7 @@ function TokenCachePanel(props) {
|
|
|
411
712
|
setCurrencySymbol,
|
|
412
713
|
exchangeRate,
|
|
413
714
|
setExchangeRate,
|
|
414
|
-
|
|
415
|
-
setLangZH,
|
|
715
|
+
langCode,
|
|
416
716
|
sectionDetail,
|
|
417
717
|
setSectionDetail,
|
|
418
718
|
sectionModel,
|
|
@@ -428,12 +728,15 @@ function TokenCachePanel(props) {
|
|
|
428
728
|
setBalanceProviderId,
|
|
429
729
|
autoBalance,
|
|
430
730
|
setAutoBalance,
|
|
731
|
+
balanceUnsupported,
|
|
732
|
+
setBalanceUnsupported,
|
|
733
|
+
balanceState,
|
|
431
734
|
balanceCurrency,
|
|
432
735
|
setBalanceCurrency,
|
|
433
736
|
borderVisible,
|
|
434
737
|
setBorderVisible
|
|
435
738
|
} = props.signals;
|
|
436
|
-
const t =
|
|
739
|
+
const t = createT(() => langCode());
|
|
437
740
|
const [lastDist, setLastDist] = createSignal({
|
|
438
741
|
system: 0,
|
|
439
742
|
user: 0,
|
|
@@ -480,72 +783,7 @@ function TokenCachePanel(props) {
|
|
|
480
783
|
hasSkills: false
|
|
481
784
|
});
|
|
482
785
|
const [refreshTick, setRefreshTick] = createSignal(0);
|
|
483
|
-
const [balanceState, setBalanceState] = createSignal({
|
|
484
|
-
status: "idle",
|
|
485
|
-
data: null,
|
|
486
|
-
lastFetch: 0
|
|
487
|
-
});
|
|
488
|
-
let balanceSeq = 0;
|
|
489
786
|
const providerName = createMemo(() => getBalanceProvider(balanceProviderId()).name);
|
|
490
|
-
const pollBalance = async () => {
|
|
491
|
-
const provider = getBalanceProvider(balanceProviderId());
|
|
492
|
-
const key = props.api.kv.get(`${KV_PREFIX}.balance.${provider.id}.key`, "") || findOpencodeKey(props.api, provider);
|
|
493
|
-
if (!key) {
|
|
494
|
-
setBalanceState({
|
|
495
|
-
status: "idle",
|
|
496
|
-
data: null,
|
|
497
|
-
lastFetch: 0,
|
|
498
|
-
error: void 0,
|
|
499
|
-
key: void 0
|
|
500
|
-
});
|
|
501
|
-
return;
|
|
502
|
-
}
|
|
503
|
-
const now = Date.now();
|
|
504
|
-
const prev = balanceState();
|
|
505
|
-
if (prev.status === "ok" && prev.key === key && now - prev.lastFetch < BALANCE_POLL_MS) return;
|
|
506
|
-
const seq = ++balanceSeq;
|
|
507
|
-
setBalanceState({
|
|
508
|
-
...prev,
|
|
509
|
-
status: "loading",
|
|
510
|
-
error: void 0,
|
|
511
|
-
key
|
|
512
|
-
});
|
|
513
|
-
const controller = new AbortController();
|
|
514
|
-
let timedOut = false;
|
|
515
|
-
const timer = setTimeout(() => {
|
|
516
|
-
timedOut = true;
|
|
517
|
-
controller.abort();
|
|
518
|
-
}, 1e4);
|
|
519
|
-
try {
|
|
520
|
-
const data2 = await provider.fetchBalance(key, controller.signal);
|
|
521
|
-
clearTimeout(timer);
|
|
522
|
-
if (seq !== balanceSeq) return;
|
|
523
|
-
setBalanceState({
|
|
524
|
-
status: "ok",
|
|
525
|
-
data: data2,
|
|
526
|
-
lastFetch: Date.now(),
|
|
527
|
-
error: void 0,
|
|
528
|
-
key
|
|
529
|
-
});
|
|
530
|
-
} catch (err) {
|
|
531
|
-
clearTimeout(timer);
|
|
532
|
-
if (seq !== balanceSeq) return;
|
|
533
|
-
const code = timedOut ? "TIMEOUT" : err instanceof Error ? err.message : "";
|
|
534
|
-
setBalanceState({
|
|
535
|
-
status: "error",
|
|
536
|
-
data: null,
|
|
537
|
-
lastFetch: 0,
|
|
538
|
-
error: code,
|
|
539
|
-
key
|
|
540
|
-
});
|
|
541
|
-
}
|
|
542
|
-
};
|
|
543
|
-
createEffect(() => {
|
|
544
|
-
void balanceRefresh();
|
|
545
|
-
untrack(() => {
|
|
546
|
-
void pollBalance();
|
|
547
|
-
});
|
|
548
|
-
});
|
|
549
787
|
createEffect(() => {
|
|
550
788
|
if (!autoBalance()) return;
|
|
551
789
|
const sid = props.signals.overrideSessionId() ?? props.sessionId;
|
|
@@ -567,9 +805,14 @@ function TokenCachePanel(props) {
|
|
|
567
805
|
}
|
|
568
806
|
if (!pid) return;
|
|
569
807
|
const hit = matchBalanceProvider(pid);
|
|
570
|
-
if (hit
|
|
571
|
-
|
|
572
|
-
|
|
808
|
+
if (hit) {
|
|
809
|
+
setBalanceUnsupported(false);
|
|
810
|
+
if (hit.id !== balanceProviderId()) {
|
|
811
|
+
setBalanceProviderId(hit.id);
|
|
812
|
+
props.signals.setBalanceRefresh(props.signals.balanceRefresh() + 1);
|
|
813
|
+
}
|
|
814
|
+
} else {
|
|
815
|
+
setBalanceUnsupported(true);
|
|
573
816
|
}
|
|
574
817
|
});
|
|
575
818
|
let lastMainSid = props.sessionId;
|
|
@@ -602,18 +845,18 @@ function TokenCachePanel(props) {
|
|
|
602
845
|
let prevMsgHitRate = -1, lastMsgHitRate = -1;
|
|
603
846
|
for (const msg of msgs) {
|
|
604
847
|
if (msg.role !== "assistant") continue;
|
|
605
|
-
const
|
|
606
|
-
if (!
|
|
607
|
-
const mit = num(
|
|
848
|
+
const tok = msg.tokens;
|
|
849
|
+
if (!tok) continue;
|
|
850
|
+
const mit = num(tok.input) + num(tok.cache?.read) + num(tok.cache?.write), mrt = num(tok.cache?.read);
|
|
608
851
|
if (mit > 0) {
|
|
609
852
|
prevMsgHitRate = lastMsgHitRate;
|
|
610
853
|
lastMsgHitRate = mrt / mit * 100;
|
|
611
854
|
}
|
|
612
855
|
if (fallbackTokens) {
|
|
613
|
-
input += num(
|
|
614
|
-
read += num(
|
|
615
|
-
write += num(
|
|
616
|
-
output += num(
|
|
856
|
+
input += num(tok.input);
|
|
857
|
+
read += num(tok.cache?.read);
|
|
858
|
+
write += num(tok.cache?.write);
|
|
859
|
+
output += num(tok.output);
|
|
617
860
|
}
|
|
618
861
|
if (fallbackCost) {
|
|
619
862
|
cost += num(msg.cost);
|
|
@@ -635,7 +878,7 @@ function TokenCachePanel(props) {
|
|
|
635
878
|
break;
|
|
636
879
|
}
|
|
637
880
|
const hitRate = lastMsgHitRate >= 0 ? lastMsgHitRate : 0;
|
|
638
|
-
const freshTotal = input + read, sessionHitRate = freshTotal > 0 ? read / freshTotal * 100 : 0;
|
|
881
|
+
const freshTotal = input + read + write, sessionHitRate = freshTotal > 0 ? read / freshTotal * 100 : 0;
|
|
639
882
|
const model = mid.split("/").pop() ?? mid, hasPricing = inputRate > 0 || cacheReadRate > 0 || cacheWriteRate > 0;
|
|
640
883
|
const hasTrendData = prevMsgHitRate >= 0 && lastMsgHitRate >= 0;
|
|
641
884
|
const trend = hasTrendData ? lastMsgHitRate - prevMsgHitRate : 0, providerName2 = pid || "";
|
|
@@ -728,13 +971,13 @@ function TokenCachePanel(props) {
|
|
|
728
971
|
}
|
|
729
972
|
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
730
973
|
if (msgs[i].role !== "assistant") continue;
|
|
731
|
-
const
|
|
732
|
-
if (
|
|
974
|
+
const tok = msgs[i].tokens;
|
|
975
|
+
if (tok && ((tok.input ?? 0) > 0 || (tok.cache?.read ?? 0) > 0 || (tok.cache?.write ?? 0) > 0)) {
|
|
733
976
|
lastAssMsg = msgs[i];
|
|
734
977
|
break;
|
|
735
978
|
}
|
|
736
979
|
}
|
|
737
|
-
dist.apiInput = num(lastAssMsg?.tokens?.input) + num(lastAssMsg?.tokens?.cache?.read);
|
|
980
|
+
dist.apiInput = num(lastAssMsg?.tokens?.input) + num(lastAssMsg?.tokens?.cache?.read) + num(lastAssMsg?.tokens?.cache?.write);
|
|
738
981
|
dist.apiOutput = num(lastAssMsg?.tokens?.output);
|
|
739
982
|
hasDistData = dist.system + dist.user + dist.agent + dist.toolCall + dist.toolResult > 0 || dist.apiOutput > 0 || dist.apiInput > 0;
|
|
740
983
|
} catch {
|
|
@@ -818,6 +1061,7 @@ function TokenCachePanel(props) {
|
|
|
818
1061
|
const savedProvider = props.api.kv.get(`${KV_PREFIX}.balance.provider`);
|
|
819
1062
|
if (typeof savedProvider === "string" && balanceProviders.some((p) => p.id === savedProvider)) {
|
|
820
1063
|
setBalanceProviderId(savedProvider);
|
|
1064
|
+
setBalanceUnsupported(false);
|
|
821
1065
|
}
|
|
822
1066
|
const savedAuto = props.api.kv.get(`${KV_PREFIX}.balance.auto`);
|
|
823
1067
|
if (typeof savedAuto === "boolean") setAutoBalance(savedAuto);
|
|
@@ -835,10 +1079,6 @@ function TokenCachePanel(props) {
|
|
|
835
1079
|
setSectionBalance(Boolean(props.api.kv.get(`${KV_PREFIX}.section.balance`, true)));
|
|
836
1080
|
const bv = props.api.kv.get(`${KV_PREFIX}.border`, true);
|
|
837
1081
|
setBorderVisible(bv !== false);
|
|
838
|
-
const savedLang = props.api.kv.get(`${KV_PREFIX}.lang`);
|
|
839
|
-
if (savedLang === "zh" || savedLang === "en") {
|
|
840
|
-
setLangZH(savedLang === "zh");
|
|
841
|
-
}
|
|
842
1082
|
const cachedDist = props.api.kv.get(`${KV_PREFIX}.dist_snapshot`);
|
|
843
1083
|
if (cachedDist) {
|
|
844
1084
|
setLastDist(cachedDist);
|
|
@@ -885,10 +1125,8 @@ function TokenCachePanel(props) {
|
|
|
885
1125
|
setRefreshTick((v) => v + 1);
|
|
886
1126
|
});
|
|
887
1127
|
setRefreshTick((v) => v + 1);
|
|
888
|
-
const balanceTimer = setInterval(pollBalance, BALANCE_POLL_MS);
|
|
889
1128
|
onCleanup(() => {
|
|
890
1129
|
clearTimeout(partTimer);
|
|
891
|
-
clearInterval(balanceTimer);
|
|
892
1130
|
unsubPart();
|
|
893
1131
|
unsubMsg();
|
|
894
1132
|
unsubSession();
|
|
@@ -916,11 +1154,12 @@ function TokenCachePanel(props) {
|
|
|
916
1154
|
const gutter = createMemo(() => borderVisible() ? 6 : 0);
|
|
917
1155
|
const sep = createMemo(() => "\u2500".repeat(Math.max(1, panelWidth() - gutter())));
|
|
918
1156
|
function trendLabel(t2) {
|
|
919
|
-
|
|
1157
|
+
if (Math.abs(t2) < 0.05) return "-";
|
|
1158
|
+
return (t2 > 0 ? "\u2191" : "\u2193") + Math.abs(t2).toFixed(1) + "%";
|
|
920
1159
|
}
|
|
921
1160
|
const barW = createMemo(() => {
|
|
922
1161
|
const trendSpace = data().hasTrendData ? LABEL_GAP + visualWidth(trendLabel(data().trend)) : 0;
|
|
923
|
-
const overhead = visualWidth(t(
|
|
1162
|
+
const overhead = visualWidth(t("hit")) + LABEL_GAP + BAR_BRACKETS + BAR_GAP + PCT_FIXED_WIDTH + trendSpace + gutter();
|
|
924
1163
|
return Math.max(3, panelWidth() - overhead);
|
|
925
1164
|
});
|
|
926
1165
|
const bar = createMemo(() => progressBar(data().hitRate, barW()));
|
|
@@ -974,7 +1213,7 @@ function TokenCachePanel(props) {
|
|
|
974
1213
|
}));
|
|
975
1214
|
_$insert(_el$3, () => open() ? "\u25BC " : "\u25B6 ");
|
|
976
1215
|
_$insertNode(_el$4, _el$5);
|
|
977
|
-
_$insert(_el$5, () => t(
|
|
1216
|
+
_$insert(_el$5, () => t("title"));
|
|
978
1217
|
_$insert(_el$4, _$createComponent(Show, {
|
|
979
1218
|
get when() {
|
|
980
1219
|
return open();
|
|
@@ -1001,13 +1240,13 @@ function TokenCachePanel(props) {
|
|
|
1001
1240
|
get children() {
|
|
1002
1241
|
return [(() => {
|
|
1003
1242
|
var _el$8 = _$createElement("span");
|
|
1004
|
-
_$insert(_el$8, () => " ".repeat(Math.max(1, panelWidth() - gutter() - HEADER_PREFIX - visualWidth(t(
|
|
1243
|
+
_$insert(_el$8, () => " ".repeat(Math.max(1, panelWidth() - gutter() - HEADER_PREFIX - visualWidth(t("title")) - visualWidth(pct() + " " + t("hitFolded") + " " + trendLabel(data().trend)))));
|
|
1005
1244
|
return _el$8;
|
|
1006
1245
|
})(), (() => {
|
|
1007
1246
|
var _el$9 = _$createElement("span"), _el$0 = _$createTextNode(` `);
|
|
1008
1247
|
_$insertNode(_el$9, _el$0);
|
|
1009
1248
|
_$insert(_el$9, pct, _el$0);
|
|
1010
|
-
_$insert(_el$9, () => t()
|
|
1249
|
+
_$insert(_el$9, () => t("hitFolded"), null);
|
|
1011
1250
|
_$effect((_$p) => _$setProp(_el$9, "style", {
|
|
1012
1251
|
fg: hitColor()
|
|
1013
1252
|
}, _$p));
|
|
@@ -1017,7 +1256,7 @@ function TokenCachePanel(props) {
|
|
|
1017
1256
|
_$insertNode(_el$1, _el$10);
|
|
1018
1257
|
_$insert(_el$1, () => trendLabel(data().trend), null);
|
|
1019
1258
|
_$effect((_$p) => _$setProp(_el$1, "style", {
|
|
1020
|
-
fg: data().trend
|
|
1259
|
+
fg: Math.abs(data().trend) >= 0.05 ? data().trend > 0 ? pal().success : pal().error : pal().text
|
|
1021
1260
|
}, _$p));
|
|
1022
1261
|
return _el$1;
|
|
1023
1262
|
})()];
|
|
@@ -1029,13 +1268,13 @@ function TokenCachePanel(props) {
|
|
|
1029
1268
|
get children() {
|
|
1030
1269
|
return [(() => {
|
|
1031
1270
|
var _el$11 = _$createElement("span");
|
|
1032
|
-
_$insert(_el$11, () => " ".repeat(Math.max(1, panelWidth() - gutter() - HEADER_PREFIX - visualWidth(t(
|
|
1271
|
+
_$insert(_el$11, () => " ".repeat(Math.max(1, panelWidth() - gutter() - HEADER_PREFIX - visualWidth(t("title")) - visualWidth(pct() + " " + t("hitFolded")))));
|
|
1033
1272
|
return _el$11;
|
|
1034
1273
|
})(), (() => {
|
|
1035
1274
|
var _el$12 = _$createElement("span"), _el$13 = _$createTextNode(` `);
|
|
1036
1275
|
_$insertNode(_el$12, _el$13);
|
|
1037
1276
|
_$insert(_el$12, pct, _el$13);
|
|
1038
|
-
_$insert(_el$12, () => t()
|
|
1277
|
+
_$insert(_el$12, () => t("hitFolded"), null);
|
|
1039
1278
|
_$effect((_$p) => _$setProp(_el$12, "style", {
|
|
1040
1279
|
fg: hitColor()
|
|
1041
1280
|
}, _$p));
|
|
@@ -1056,28 +1295,28 @@ function TokenCachePanel(props) {
|
|
|
1056
1295
|
},
|
|
1057
1296
|
get children() {
|
|
1058
1297
|
return (() => {
|
|
1059
|
-
const prefix = " \u21B3 " + (
|
|
1298
|
+
const prefix = " \u21B3 " + t("subPrefix");
|
|
1060
1299
|
const maxSidW = Math.max(6, panelWidth() - visualWidth(prefix));
|
|
1061
1300
|
return (() => {
|
|
1062
|
-
var _el$
|
|
1063
|
-
_$insertNode(_el$
|
|
1064
|
-
_$insertNode(_el$
|
|
1065
|
-
_$insert(_el$
|
|
1066
|
-
_$insert(_el$
|
|
1301
|
+
var _el$69 = _$createElement("text"), _el$70 = _$createElement("span"), _el$71 = _$createElement("span");
|
|
1302
|
+
_$insertNode(_el$69, _el$70);
|
|
1303
|
+
_$insertNode(_el$69, _el$71);
|
|
1304
|
+
_$insert(_el$70, prefix);
|
|
1305
|
+
_$insert(_el$71, () => truncateVisual(props.signals.overrideSessionId(), maxSidW));
|
|
1067
1306
|
_$effect((_p$) => {
|
|
1068
|
-
var _v$
|
|
1307
|
+
var _v$17 = {
|
|
1069
1308
|
fg: pal().muted
|
|
1070
|
-
}, _v$
|
|
1309
|
+
}, _v$18 = {
|
|
1071
1310
|
fg: pal().text
|
|
1072
1311
|
};
|
|
1073
|
-
_v$
|
|
1074
|
-
_v$
|
|
1312
|
+
_v$17 !== _p$.e && (_p$.e = _$setProp(_el$70, "style", _v$17, _p$.e));
|
|
1313
|
+
_v$18 !== _p$.t && (_p$.t = _$setProp(_el$71, "style", _v$18, _p$.t));
|
|
1075
1314
|
return _p$;
|
|
1076
1315
|
}, {
|
|
1077
1316
|
e: void 0,
|
|
1078
1317
|
t: void 0
|
|
1079
1318
|
});
|
|
1080
|
-
return _el$
|
|
1319
|
+
return _el$69;
|
|
1081
1320
|
})();
|
|
1082
1321
|
})();
|
|
1083
1322
|
}
|
|
@@ -1087,30 +1326,30 @@ function TokenCachePanel(props) {
|
|
|
1087
1326
|
},
|
|
1088
1327
|
get fallback() {
|
|
1089
1328
|
return [(() => {
|
|
1090
|
-
var _el$
|
|
1091
|
-
_$insert(_el$
|
|
1092
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1093
|
-
return _el$
|
|
1329
|
+
var _el$72 = _$createElement("text");
|
|
1330
|
+
_$insert(_el$72, sep);
|
|
1331
|
+
_$effect((_$p) => _$setProp(_el$72, "fg", pal().muted, _$p));
|
|
1332
|
+
return _el$72;
|
|
1094
1333
|
})(), (() => {
|
|
1095
|
-
var _el$
|
|
1096
|
-
_$insertNode(_el$
|
|
1097
|
-
_$insertNode(_el$
|
|
1098
|
-
_$insertNode(_el$
|
|
1099
|
-
_$insert(_el$
|
|
1334
|
+
var _el$73 = _$createElement("text"), _el$74 = _$createElement("span"), _el$76 = _$createElement("span");
|
|
1335
|
+
_$insertNode(_el$73, _el$74);
|
|
1336
|
+
_$insertNode(_el$73, _el$76);
|
|
1337
|
+
_$insertNode(_el$74, _$createTextNode(`> `));
|
|
1338
|
+
_$insert(_el$76, () => t("noData"));
|
|
1100
1339
|
_$effect((_p$) => {
|
|
1101
|
-
var _v$
|
|
1340
|
+
var _v$19 = {
|
|
1102
1341
|
fg: pal().muted
|
|
1103
|
-
}, _v$
|
|
1342
|
+
}, _v$20 = {
|
|
1104
1343
|
fg: pal().muted
|
|
1105
1344
|
};
|
|
1106
|
-
_v$
|
|
1107
|
-
_v$
|
|
1345
|
+
_v$19 !== _p$.e && (_p$.e = _$setProp(_el$74, "style", _v$19, _p$.e));
|
|
1346
|
+
_v$20 !== _p$.t && (_p$.t = _$setProp(_el$76, "style", _v$20, _p$.t));
|
|
1108
1347
|
return _p$;
|
|
1109
1348
|
}, {
|
|
1110
1349
|
e: void 0,
|
|
1111
1350
|
t: void 0
|
|
1112
1351
|
});
|
|
1113
|
-
return _el$
|
|
1352
|
+
return _el$73;
|
|
1114
1353
|
})()];
|
|
1115
1354
|
},
|
|
1116
1355
|
get children() {
|
|
@@ -1125,7 +1364,7 @@ function TokenCachePanel(props) {
|
|
|
1125
1364
|
_$insertNode(_el$15, _el$18);
|
|
1126
1365
|
_$insertNode(_el$15, _el$21);
|
|
1127
1366
|
_$insertNode(_el$16, _el$17);
|
|
1128
|
-
_$insert(_el$16, () => t()
|
|
1367
|
+
_$insert(_el$16, () => t("hit"), _el$17);
|
|
1129
1368
|
_$insertNode(_el$18, _el$19);
|
|
1130
1369
|
_$insertNode(_el$18, _el$20);
|
|
1131
1370
|
_$insert(_el$18, bar, _el$20);
|
|
@@ -1139,7 +1378,7 @@ function TokenCachePanel(props) {
|
|
|
1139
1378
|
_$insertNode(_el$22, _el$23);
|
|
1140
1379
|
_$insert(_el$22, () => trendLabel(data().trend), null);
|
|
1141
1380
|
_$effect((_$p) => _$setProp(_el$22, "style", {
|
|
1142
|
-
fg: data().trend
|
|
1381
|
+
fg: Math.abs(data().trend) >= 0.05 ? data().trend > 0 ? pal().success : pal().error : pal().text
|
|
1143
1382
|
}, _$p));
|
|
1144
1383
|
return _el$22;
|
|
1145
1384
|
}
|
|
@@ -1164,7 +1403,7 @@ function TokenCachePanel(props) {
|
|
|
1164
1403
|
return _el$15;
|
|
1165
1404
|
})(), (() => {
|
|
1166
1405
|
var _el$24 = _$createElement("text");
|
|
1167
|
-
_$insert(_el$24, () => justify(t()
|
|
1406
|
+
_$insert(_el$24, () => justify(t("totalHit"), (Math.floor(data().sessionHitRate * 10) / 10).toFixed(1) + "%"));
|
|
1168
1407
|
_$effect((_$p) => _$setProp(_el$24, "fg", pal().muted, _$p));
|
|
1169
1408
|
return _el$24;
|
|
1170
1409
|
})(), _$createComponent(Show, {
|
|
@@ -1184,8 +1423,8 @@ function TokenCachePanel(props) {
|
|
|
1184
1423
|
}));
|
|
1185
1424
|
_$insert(_el$26, () => detailOpen() ? "\u25BC " : "\u25B6 ");
|
|
1186
1425
|
_$insertNode(_el$27, _el$28);
|
|
1187
|
-
_$insert(_el$28, () => t(
|
|
1188
|
-
_$insert(_el$29, () => sep().slice(visualWidth((detailOpen() ? "\u25BC " : "\u25B6 ") + t(
|
|
1426
|
+
_$insert(_el$28, () => t("secDetail"));
|
|
1427
|
+
_$insert(_el$29, () => sep().slice(visualWidth((detailOpen() ? "\u25BC " : "\u25B6 ") + t("secDetail"))));
|
|
1189
1428
|
_$effect((_p$) => {
|
|
1190
1429
|
var _v$4 = {
|
|
1191
1430
|
fg: pal().muted
|
|
@@ -1215,7 +1454,7 @@ function TokenCachePanel(props) {
|
|
|
1215
1454
|
},
|
|
1216
1455
|
get children() {
|
|
1217
1456
|
var _el$30 = _$createElement("text");
|
|
1218
|
-
_$insert(_el$30, () => justify(t()
|
|
1457
|
+
_$insert(_el$30, () => justify(t("read"), fmt(data().read), t("tok")));
|
|
1219
1458
|
_$effect((_$p) => _$setProp(_el$30, "fg", pal().muted, _$p));
|
|
1220
1459
|
return _el$30;
|
|
1221
1460
|
}
|
|
@@ -1225,18 +1464,18 @@ function TokenCachePanel(props) {
|
|
|
1225
1464
|
},
|
|
1226
1465
|
get children() {
|
|
1227
1466
|
var _el$31 = _$createElement("text");
|
|
1228
|
-
_$insert(_el$31, () => justify(t()
|
|
1467
|
+
_$insert(_el$31, () => justify(t("write"), fmt(data().write), t("tok")));
|
|
1229
1468
|
_$effect((_$p) => _$setProp(_el$31, "fg", pal().muted, _$p));
|
|
1230
1469
|
return _el$31;
|
|
1231
1470
|
}
|
|
1232
1471
|
}), (() => {
|
|
1233
1472
|
var _el$32 = _$createElement("text");
|
|
1234
|
-
_$insert(_el$32, () => justify(t()
|
|
1473
|
+
_$insert(_el$32, () => justify(t("miss"), fmt(data().freshInput + data().write), t("tok")));
|
|
1235
1474
|
_$effect((_$p) => _$setProp(_el$32, "fg", pal().muted, _$p));
|
|
1236
1475
|
return _el$32;
|
|
1237
1476
|
})(), (() => {
|
|
1238
1477
|
var _el$33 = _$createElement("text");
|
|
1239
|
-
_$insert(_el$33, () => justify(t()
|
|
1478
|
+
_$insert(_el$33, () => justify(t("out"), fmt(data().output), t("tok")));
|
|
1240
1479
|
_$effect((_$p) => _$setProp(_el$33, "fg", pal().muted, _$p));
|
|
1241
1480
|
return _el$33;
|
|
1242
1481
|
})(), _$createComponent(Show, {
|
|
@@ -1248,8 +1487,8 @@ function TokenCachePanel(props) {
|
|
|
1248
1487
|
_$insertNode(_el$34, _el$35);
|
|
1249
1488
|
_$insertNode(_el$34, _el$36);
|
|
1250
1489
|
_$insertNode(_el$34, _el$37);
|
|
1251
|
-
_$insert(_el$35, () => t(
|
|
1252
|
-
_$insert(_el$36, () => " ".repeat(Math.max(1, panelWidth() - gutter() - visualWidth(t(
|
|
1490
|
+
_$insert(_el$35, () => t("saved"));
|
|
1491
|
+
_$insert(_el$36, () => " ".repeat(Math.max(1, panelWidth() - gutter() - visualWidth(t("saved")) - visualWidth("~" + fmtCost(data().saved, currencySymbol(), exchangeRate())))));
|
|
1253
1492
|
_$insertNode(_el$37, _el$38);
|
|
1254
1493
|
_$insert(_el$37, () => fmtCost(data().saved, currencySymbol(), exchangeRate()), null);
|
|
1255
1494
|
_$effect((_p$) => {
|
|
@@ -1277,37 +1516,37 @@ function TokenCachePanel(props) {
|
|
|
1277
1516
|
},
|
|
1278
1517
|
get children() {
|
|
1279
1518
|
return [_$memo(() => (() => {
|
|
1280
|
-
var _el$
|
|
1281
|
-
_$insertNode(_el$
|
|
1282
|
-
_$insertNode(_el$
|
|
1283
|
-
_$insertNode(_el$
|
|
1284
|
-
_$setProp(_el$
|
|
1519
|
+
var _el$77 = _$createElement("text"), _el$78 = _$createElement("span"), _el$79 = _$createElement("span"), _el$80 = _$createElement("b"), _el$81 = _$createElement("span");
|
|
1520
|
+
_$insertNode(_el$77, _el$78);
|
|
1521
|
+
_$insertNode(_el$77, _el$79);
|
|
1522
|
+
_$insertNode(_el$77, _el$81);
|
|
1523
|
+
_$setProp(_el$77, "onMouseUp", () => setModelOpen((o) => {
|
|
1285
1524
|
const n = !o;
|
|
1286
1525
|
persistFold("model", n);
|
|
1287
1526
|
return n;
|
|
1288
1527
|
}));
|
|
1289
|
-
_$insert(_el$
|
|
1290
|
-
_$insertNode(_el$
|
|
1291
|
-
_$insert(_el$
|
|
1292
|
-
_$insert(_el$
|
|
1528
|
+
_$insert(_el$78, () => modelOpen() ? "\u25BC " : "\u25B6 ");
|
|
1529
|
+
_$insertNode(_el$79, _el$80);
|
|
1530
|
+
_$insert(_el$80, () => t("secModel"));
|
|
1531
|
+
_$insert(_el$81, () => sep().slice(visualWidth((modelOpen() ? "\u25BC " : "\u25B6 ") + t("secModel"))));
|
|
1293
1532
|
_$effect((_p$) => {
|
|
1294
|
-
var _v$
|
|
1533
|
+
var _v$21 = {
|
|
1295
1534
|
fg: pal().muted
|
|
1296
|
-
}, _v$
|
|
1535
|
+
}, _v$22 = {
|
|
1297
1536
|
fg: pal().primary
|
|
1298
|
-
}, _v$
|
|
1537
|
+
}, _v$23 = {
|
|
1299
1538
|
fg: pal().muted
|
|
1300
1539
|
};
|
|
1301
|
-
_v$
|
|
1302
|
-
_v$
|
|
1303
|
-
_v$
|
|
1540
|
+
_v$21 !== _p$.e && (_p$.e = _$setProp(_el$78, "style", _v$21, _p$.e));
|
|
1541
|
+
_v$22 !== _p$.t && (_p$.t = _$setProp(_el$79, "style", _v$22, _p$.t));
|
|
1542
|
+
_v$23 !== _p$.a && (_p$.a = _$setProp(_el$81, "style", _v$23, _p$.a));
|
|
1304
1543
|
return _p$;
|
|
1305
1544
|
}, {
|
|
1306
1545
|
e: void 0,
|
|
1307
1546
|
t: void 0,
|
|
1308
1547
|
a: void 0
|
|
1309
1548
|
});
|
|
1310
|
-
return _el$
|
|
1549
|
+
return _el$77;
|
|
1311
1550
|
})()), _$createComponent(Show, {
|
|
1312
1551
|
get when() {
|
|
1313
1552
|
return modelOpen();
|
|
@@ -1315,7 +1554,7 @@ function TokenCachePanel(props) {
|
|
|
1315
1554
|
get children() {
|
|
1316
1555
|
return [(() => {
|
|
1317
1556
|
var _el$39 = _$createElement("text");
|
|
1318
|
-
_$insert(_el$39, () => justify(t()
|
|
1557
|
+
_$insert(_el$39, () => justify(t("cost"), fmtCost(data().cost, currencySymbol(), exchangeRate())));
|
|
1319
1558
|
_$effect((_$p) => _$setProp(_el$39, "fg", pal().text, _$p));
|
|
1320
1559
|
return _el$39;
|
|
1321
1560
|
})(), _$createComponent(Show, {
|
|
@@ -1324,13 +1563,13 @@ function TokenCachePanel(props) {
|
|
|
1324
1563
|
},
|
|
1325
1564
|
get children() {
|
|
1326
1565
|
var _el$40 = _$createElement("text");
|
|
1327
|
-
_$insert(_el$40, () => justify(t()
|
|
1566
|
+
_$insert(_el$40, () => justify(t("provider"), data().providerName));
|
|
1328
1567
|
_$effect((_$p) => _$setProp(_el$40, "fg", pal().muted, _$p));
|
|
1329
1568
|
return _el$40;
|
|
1330
1569
|
}
|
|
1331
1570
|
}), (() => {
|
|
1332
1571
|
var _el$41 = _$createElement("text");
|
|
1333
|
-
_$insert(_el$41, () => justify(t()
|
|
1572
|
+
_$insert(_el$41, () => justify(t("model"), data().model));
|
|
1334
1573
|
_$effect((_$p) => _$setProp(_el$41, "fg", pal().muted, _$p));
|
|
1335
1574
|
return _el$41;
|
|
1336
1575
|
})(), _$createComponent(Show, {
|
|
@@ -1340,7 +1579,7 @@ function TokenCachePanel(props) {
|
|
|
1340
1579
|
get children() {
|
|
1341
1580
|
return [(() => {
|
|
1342
1581
|
var _el$42 = _$createElement("text");
|
|
1343
|
-
_$insert(_el$42, () => justify(t()
|
|
1582
|
+
_$insert(_el$42, () => justify(t("rate"), currencySymbol() + (data().inputRate * exchangeRate()).toFixed(2) + "/M " + t("inputRate")));
|
|
1344
1583
|
_$effect((_$p) => _$setProp(_el$42, "fg", pal().muted, _$p));
|
|
1345
1584
|
return _el$42;
|
|
1346
1585
|
})(), _$createComponent(Show, {
|
|
@@ -1349,7 +1588,7 @@ function TokenCachePanel(props) {
|
|
|
1349
1588
|
},
|
|
1350
1589
|
get children() {
|
|
1351
1590
|
var _el$43 = _$createElement("text");
|
|
1352
|
-
_$insert(_el$43, () => justify("", currencySymbol() + (data().cacheReadRate * exchangeRate()).toFixed(2) + "/M " + t(
|
|
1591
|
+
_$insert(_el$43, () => justify("", currencySymbol() + (data().cacheReadRate * exchangeRate()).toFixed(2) + "/M " + t("cacheRate")));
|
|
1353
1592
|
_$effect((_$p) => _$setProp(_el$43, "fg", pal().muted, _$p));
|
|
1354
1593
|
return _el$43;
|
|
1355
1594
|
}
|
|
@@ -1359,7 +1598,7 @@ function TokenCachePanel(props) {
|
|
|
1359
1598
|
},
|
|
1360
1599
|
get children() {
|
|
1361
1600
|
var _el$44 = _$createElement("text");
|
|
1362
|
-
_$insert(_el$44, () => justify("", currencySymbol() + (data().cacheWriteRate * exchangeRate()).toFixed(2) + "/M " + t(
|
|
1601
|
+
_$insert(_el$44, () => justify("", currencySymbol() + (data().cacheWriteRate * exchangeRate()).toFixed(2) + "/M " + t("writeRate")));
|
|
1363
1602
|
_$effect((_$p) => _$setProp(_el$44, "fg", pal().muted, _$p));
|
|
1364
1603
|
return _el$44;
|
|
1365
1604
|
}
|
|
@@ -1380,37 +1619,37 @@ function TokenCachePanel(props) {
|
|
|
1380
1619
|
},
|
|
1381
1620
|
get children() {
|
|
1382
1621
|
return [_$memo(() => (() => {
|
|
1383
|
-
var _el$
|
|
1384
|
-
_$insertNode(_el$
|
|
1385
|
-
_$insertNode(_el$
|
|
1386
|
-
_$insertNode(_el$
|
|
1387
|
-
_$setProp(_el$
|
|
1622
|
+
var _el$82 = _$createElement("text"), _el$83 = _$createElement("span"), _el$84 = _$createElement("span"), _el$85 = _$createElement("b"), _el$86 = _$createElement("span");
|
|
1623
|
+
_$insertNode(_el$82, _el$83);
|
|
1624
|
+
_$insertNode(_el$82, _el$84);
|
|
1625
|
+
_$insertNode(_el$82, _el$86);
|
|
1626
|
+
_$setProp(_el$82, "onMouseUp", () => setDistOpen((o) => {
|
|
1388
1627
|
const n = !o;
|
|
1389
1628
|
persistFold("dist", n);
|
|
1390
1629
|
return n;
|
|
1391
1630
|
}));
|
|
1392
|
-
_$insert(_el$
|
|
1393
|
-
_$insertNode(_el$
|
|
1394
|
-
_$insert(_el$
|
|
1395
|
-
_$insert(_el$
|
|
1631
|
+
_$insert(_el$83, () => distOpen() ? "\u25BC " : "\u25B6 ");
|
|
1632
|
+
_$insertNode(_el$84, _el$85);
|
|
1633
|
+
_$insert(_el$85, () => t("distTitle"));
|
|
1634
|
+
_$insert(_el$86, () => sep().slice(visualWidth((distOpen() ? "\u25BC " : "\u25B6 ") + t("distTitle"))));
|
|
1396
1635
|
_$effect((_p$) => {
|
|
1397
|
-
var _v$
|
|
1636
|
+
var _v$24 = {
|
|
1398
1637
|
fg: pal().muted
|
|
1399
|
-
}, _v$
|
|
1638
|
+
}, _v$25 = {
|
|
1400
1639
|
fg: pal().primary
|
|
1401
|
-
}, _v$
|
|
1640
|
+
}, _v$26 = {
|
|
1402
1641
|
fg: pal().muted
|
|
1403
1642
|
};
|
|
1404
|
-
_v$
|
|
1405
|
-
_v$
|
|
1406
|
-
_v$
|
|
1643
|
+
_v$24 !== _p$.e && (_p$.e = _$setProp(_el$83, "style", _v$24, _p$.e));
|
|
1644
|
+
_v$25 !== _p$.t && (_p$.t = _$setProp(_el$84, "style", _v$25, _p$.t));
|
|
1645
|
+
_v$26 !== _p$.a && (_p$.a = _$setProp(_el$86, "style", _v$26, _p$.a));
|
|
1407
1646
|
return _p$;
|
|
1408
1647
|
}, {
|
|
1409
1648
|
e: void 0,
|
|
1410
1649
|
t: void 0,
|
|
1411
1650
|
a: void 0
|
|
1412
1651
|
});
|
|
1413
|
-
return _el$
|
|
1652
|
+
return _el$82;
|
|
1414
1653
|
})()), _$createComponent(Show, {
|
|
1415
1654
|
get when() {
|
|
1416
1655
|
return distOpen();
|
|
@@ -1422,7 +1661,7 @@ function TokenCachePanel(props) {
|
|
|
1422
1661
|
},
|
|
1423
1662
|
get children() {
|
|
1424
1663
|
var _el$45 = _$createElement("text");
|
|
1425
|
-
_$insert(_el$45, () => justify(t()
|
|
1664
|
+
_$insert(_el$45, () => justify(t("distSys"), fmt(data().dist.system), t("tok")));
|
|
1426
1665
|
_$effect((_$p) => _$setProp(_el$45, "fg", pal().muted, _$p));
|
|
1427
1666
|
return _el$45;
|
|
1428
1667
|
}
|
|
@@ -1432,7 +1671,7 @@ function TokenCachePanel(props) {
|
|
|
1432
1671
|
},
|
|
1433
1672
|
get children() {
|
|
1434
1673
|
var _el$46 = _$createElement("text");
|
|
1435
|
-
_$insert(_el$46, () => justify(t()
|
|
1674
|
+
_$insert(_el$46, () => justify(t("distUser"), fmt(data().dist.user), t("tok")));
|
|
1436
1675
|
_$effect((_$p) => _$setProp(_el$46, "fg", pal().muted, _$p));
|
|
1437
1676
|
return _el$46;
|
|
1438
1677
|
}
|
|
@@ -1442,7 +1681,7 @@ function TokenCachePanel(props) {
|
|
|
1442
1681
|
},
|
|
1443
1682
|
get children() {
|
|
1444
1683
|
var _el$47 = _$createElement("text");
|
|
1445
|
-
_$insert(_el$47, () => justify(t()
|
|
1684
|
+
_$insert(_el$47, () => justify(t("distAgent"), fmt(data().dist.agent), t("tok")));
|
|
1446
1685
|
_$effect((_$p) => _$setProp(_el$47, "fg", pal().muted, _$p));
|
|
1447
1686
|
return _el$47;
|
|
1448
1687
|
}
|
|
@@ -1452,7 +1691,7 @@ function TokenCachePanel(props) {
|
|
|
1452
1691
|
},
|
|
1453
1692
|
get children() {
|
|
1454
1693
|
var _el$48 = _$createElement("text");
|
|
1455
|
-
_$insert(_el$48, () => justify(t()
|
|
1694
|
+
_$insert(_el$48, () => justify(t("distTool"), fmt(data().dist.toolCall), t("tok")));
|
|
1456
1695
|
_$effect((_$p) => _$setProp(_el$48, "fg", pal().muted, _$p));
|
|
1457
1696
|
return _el$48;
|
|
1458
1697
|
}
|
|
@@ -1462,13 +1701,13 @@ function TokenCachePanel(props) {
|
|
|
1462
1701
|
},
|
|
1463
1702
|
get children() {
|
|
1464
1703
|
var _el$49 = _$createElement("text");
|
|
1465
|
-
_$insert(_el$49, () => justify(t()
|
|
1704
|
+
_$insert(_el$49, () => justify(t("distRes"), fmt(data().dist.toolResult), t("tok")));
|
|
1466
1705
|
_$effect((_$p) => _$setProp(_el$49, "fg", pal().muted, _$p));
|
|
1467
1706
|
return _el$49;
|
|
1468
1707
|
}
|
|
1469
1708
|
}), (() => {
|
|
1470
1709
|
var _el$50 = _$createElement("text");
|
|
1471
|
-
_$insert(_el$50, () => justify(t()
|
|
1710
|
+
_$insert(_el$50, () => justify(t("distTotal"), fmt(data().dist.apiInput), t("tok")));
|
|
1472
1711
|
_$effect((_$p) => _$setProp(_el$50, "fg", pal().text, _$p));
|
|
1473
1712
|
return _el$50;
|
|
1474
1713
|
})()];
|
|
@@ -1488,37 +1727,37 @@ function TokenCachePanel(props) {
|
|
|
1488
1727
|
},
|
|
1489
1728
|
get children() {
|
|
1490
1729
|
return [_$memo(() => (() => {
|
|
1491
|
-
var _el$
|
|
1492
|
-
_$insertNode(_el$
|
|
1493
|
-
_$insertNode(_el$
|
|
1494
|
-
_$insertNode(_el$
|
|
1495
|
-
_$insertNode(_el$
|
|
1496
|
-
_$setProp(_el$
|
|
1730
|
+
var _el$87 = _$createElement("text"), _el$88 = _$createElement("span"), _el$89 = _$createElement("span"), _el$90 = _$createElement("b"), _el$91 = _$createElement("span"), _el$92 = _$createTextNode(` (`), _el$93 = _$createTextNode(`)`), _el$94 = _$createElement("span");
|
|
1731
|
+
_$insertNode(_el$87, _el$88);
|
|
1732
|
+
_$insertNode(_el$87, _el$89);
|
|
1733
|
+
_$insertNode(_el$87, _el$91);
|
|
1734
|
+
_$insertNode(_el$87, _el$94);
|
|
1735
|
+
_$setProp(_el$87, "onMouseUp", () => setSkillsOpen((o) => {
|
|
1497
1736
|
const n = !o;
|
|
1498
1737
|
persistFold("skills", n);
|
|
1499
1738
|
return n;
|
|
1500
1739
|
}));
|
|
1501
|
-
_$insert(_el$
|
|
1502
|
-
_$insertNode(_el$
|
|
1503
|
-
_$insert(_el$
|
|
1504
|
-
_$insertNode(_el$
|
|
1505
|
-
_$insertNode(_el$
|
|
1506
|
-
_$insert(_el$
|
|
1507
|
-
_$insert(_el$
|
|
1740
|
+
_$insert(_el$88, () => skillsOpen() ? "\u25BC " : "\u25B6 ");
|
|
1741
|
+
_$insertNode(_el$89, _el$90);
|
|
1742
|
+
_$insert(_el$90, () => t("secSkills"));
|
|
1743
|
+
_$insertNode(_el$91, _el$92);
|
|
1744
|
+
_$insertNode(_el$91, _el$93);
|
|
1745
|
+
_$insert(_el$91, () => data().skills.length, _el$93);
|
|
1746
|
+
_$insert(_el$94, () => sep().slice(visualWidth((skillsOpen() ? "\u25BC " : "\u25B6 ") + t("secSkills") + ` (${data().skills.length})`)));
|
|
1508
1747
|
_$effect((_p$) => {
|
|
1509
|
-
var _v$
|
|
1748
|
+
var _v$27 = {
|
|
1510
1749
|
fg: pal().muted
|
|
1511
|
-
}, _v$
|
|
1750
|
+
}, _v$28 = {
|
|
1512
1751
|
fg: pal().primary
|
|
1513
|
-
}, _v$
|
|
1752
|
+
}, _v$29 = {
|
|
1514
1753
|
fg: pal().muted
|
|
1515
|
-
}, _v$
|
|
1754
|
+
}, _v$30 = {
|
|
1516
1755
|
fg: pal().muted
|
|
1517
1756
|
};
|
|
1518
|
-
_v$
|
|
1519
|
-
_v$
|
|
1520
|
-
_v$
|
|
1521
|
-
_v$
|
|
1757
|
+
_v$27 !== _p$.e && (_p$.e = _$setProp(_el$88, "style", _v$27, _p$.e));
|
|
1758
|
+
_v$28 !== _p$.t && (_p$.t = _$setProp(_el$89, "style", _v$28, _p$.t));
|
|
1759
|
+
_v$29 !== _p$.a && (_p$.a = _$setProp(_el$91, "style", _v$29, _p$.a));
|
|
1760
|
+
_v$30 !== _p$.o && (_p$.o = _$setProp(_el$94, "style", _v$30, _p$.o));
|
|
1522
1761
|
return _p$;
|
|
1523
1762
|
}, {
|
|
1524
1763
|
e: void 0,
|
|
@@ -1526,21 +1765,21 @@ function TokenCachePanel(props) {
|
|
|
1526
1765
|
a: void 0,
|
|
1527
1766
|
o: void 0
|
|
1528
1767
|
});
|
|
1529
|
-
return _el$
|
|
1768
|
+
return _el$87;
|
|
1530
1769
|
})()), _$createComponent(Show, {
|
|
1531
1770
|
get when() {
|
|
1532
1771
|
return skillsOpen();
|
|
1533
1772
|
},
|
|
1534
1773
|
get children() {
|
|
1535
1774
|
return data().skills.map((sk) => {
|
|
1536
|
-
const rightW = visualWidth(fmt(sk.tokens)) + UNIT_GAP + visualWidth(t(
|
|
1775
|
+
const rightW = visualWidth(fmt(sk.tokens)) + UNIT_GAP + visualWidth(t("tok"));
|
|
1537
1776
|
const maxLabel = Math.max(4, panelWidth() - gutter() - rightW - 1);
|
|
1538
1777
|
const label = truncateVisual(sk.name, maxLabel);
|
|
1539
1778
|
return (() => {
|
|
1540
|
-
var _el$
|
|
1541
|
-
_$insert(_el$
|
|
1542
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1543
|
-
return _el$
|
|
1779
|
+
var _el$95 = _$createElement("text");
|
|
1780
|
+
_$insert(_el$95, () => justify(label, fmt(sk.tokens), t("tok")));
|
|
1781
|
+
_$effect((_$p) => _$setProp(_el$95, "fg", pal().muted, _$p));
|
|
1782
|
+
return _el$95;
|
|
1544
1783
|
})();
|
|
1545
1784
|
});
|
|
1546
1785
|
}
|
|
@@ -1560,14 +1799,14 @@ function TokenCachePanel(props) {
|
|
|
1560
1799
|
return _el$51;
|
|
1561
1800
|
})(), _$createComponent(Show, {
|
|
1562
1801
|
get when() {
|
|
1563
|
-
return
|
|
1802
|
+
return balanceUnsupported();
|
|
1564
1803
|
},
|
|
1565
1804
|
get children() {
|
|
1566
1805
|
var _el$52 = _$createElement("text"), _el$53 = _$createElement("span"), _el$55 = _$createElement("span");
|
|
1567
1806
|
_$insertNode(_el$52, _el$53);
|
|
1568
1807
|
_$insertNode(_el$52, _el$55);
|
|
1569
1808
|
_$insertNode(_el$53, _$createTextNode(`> `));
|
|
1570
|
-
_$insert(_el$55, () => t(
|
|
1809
|
+
_$insert(_el$55, () => t("balUnsupported"));
|
|
1571
1810
|
_$effect((_p$) => {
|
|
1572
1811
|
var _v$9 = pal().muted, _v$0 = {
|
|
1573
1812
|
fg: pal().muted
|
|
@@ -1583,87 +1822,98 @@ function TokenCachePanel(props) {
|
|
|
1583
1822
|
}
|
|
1584
1823
|
}), _$createComponent(Show, {
|
|
1585
1824
|
get when() {
|
|
1586
|
-
return
|
|
1825
|
+
return !balanceUnsupported();
|
|
1587
1826
|
},
|
|
1588
1827
|
get children() {
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
_$
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
return
|
|
1652
|
-
|
|
1828
|
+
return [_$createComponent(Show, {
|
|
1829
|
+
get when() {
|
|
1830
|
+
return balanceState().status === "idle";
|
|
1831
|
+
},
|
|
1832
|
+
get children() {
|
|
1833
|
+
var _el$56 = _$createElement("text"), _el$57 = _$createElement("span"), _el$59 = _$createElement("span");
|
|
1834
|
+
_$insertNode(_el$56, _el$57);
|
|
1835
|
+
_$insertNode(_el$56, _el$59);
|
|
1836
|
+
_$insertNode(_el$57, _$createTextNode(`> `));
|
|
1837
|
+
_$insert(_el$59, () => t("balNoKey", {
|
|
1838
|
+
p: providerName()
|
|
1839
|
+
}));
|
|
1840
|
+
_$effect((_p$) => {
|
|
1841
|
+
var _v$1 = pal().muted, _v$10 = {
|
|
1842
|
+
fg: pal().muted
|
|
1843
|
+
};
|
|
1844
|
+
_v$1 !== _p$.e && (_p$.e = _$setProp(_el$56, "fg", _v$1, _p$.e));
|
|
1845
|
+
_v$10 !== _p$.t && (_p$.t = _$setProp(_el$57, "style", _v$10, _p$.t));
|
|
1846
|
+
return _p$;
|
|
1847
|
+
}, {
|
|
1848
|
+
e: void 0,
|
|
1849
|
+
t: void 0
|
|
1850
|
+
});
|
|
1851
|
+
return _el$56;
|
|
1852
|
+
}
|
|
1853
|
+
}), _$createComponent(Show, {
|
|
1854
|
+
get when() {
|
|
1855
|
+
return balanceState().status === "loading";
|
|
1856
|
+
},
|
|
1857
|
+
get children() {
|
|
1858
|
+
var _el$60 = _$createElement("text"), _el$61 = _$createElement("span"), _el$63 = _$createElement("span");
|
|
1859
|
+
_$insertNode(_el$60, _el$61);
|
|
1860
|
+
_$insertNode(_el$60, _el$63);
|
|
1861
|
+
_$insertNode(_el$61, _$createTextNode(`> `));
|
|
1862
|
+
_$insert(_el$63, () => t("balLoading"));
|
|
1863
|
+
_$effect((_p$) => {
|
|
1864
|
+
var _v$11 = pal().muted, _v$12 = {
|
|
1865
|
+
fg: pal().muted
|
|
1866
|
+
};
|
|
1867
|
+
_v$11 !== _p$.e && (_p$.e = _$setProp(_el$60, "fg", _v$11, _p$.e));
|
|
1868
|
+
_v$12 !== _p$.t && (_p$.t = _$setProp(_el$61, "style", _v$12, _p$.t));
|
|
1869
|
+
return _p$;
|
|
1870
|
+
}, {
|
|
1871
|
+
e: void 0,
|
|
1872
|
+
t: void 0
|
|
1873
|
+
});
|
|
1874
|
+
return _el$60;
|
|
1875
|
+
}
|
|
1876
|
+
}), _$createComponent(Show, {
|
|
1877
|
+
get when() {
|
|
1878
|
+
return balanceState().status === "error";
|
|
1879
|
+
},
|
|
1880
|
+
get children() {
|
|
1881
|
+
var _el$64 = _$createElement("text"), _el$65 = _$createElement("span"), _el$67 = _$createElement("span");
|
|
1882
|
+
_$insertNode(_el$64, _el$65);
|
|
1883
|
+
_$insertNode(_el$64, _el$67);
|
|
1884
|
+
_$insertNode(_el$65, _$createTextNode(`> `));
|
|
1885
|
+
_$insert(_el$67, () => {
|
|
1886
|
+
const code = balanceState().error;
|
|
1887
|
+
if (code === "401") return t("balErr401");
|
|
1888
|
+
if (code === "403") return t("balErr403");
|
|
1889
|
+
if (code === "EMPTY") return t("balErrEmpty");
|
|
1890
|
+
if (code === "TIMEOUT") return t("balErrTimeout");
|
|
1891
|
+
return t("balError") + (code ? ` (${code})` : "");
|
|
1892
|
+
});
|
|
1893
|
+
_$effect((_p$) => {
|
|
1894
|
+
var _v$13 = pal().error, _v$14 = {
|
|
1895
|
+
fg: pal().muted
|
|
1896
|
+
};
|
|
1897
|
+
_v$13 !== _p$.e && (_p$.e = _$setProp(_el$64, "fg", _v$13, _p$.e));
|
|
1898
|
+
_v$14 !== _p$.t && (_p$.t = _$setProp(_el$65, "style", _v$14, _p$.t));
|
|
1899
|
+
return _p$;
|
|
1900
|
+
}, {
|
|
1901
|
+
e: void 0,
|
|
1902
|
+
t: void 0
|
|
1903
|
+
});
|
|
1904
|
+
return _el$64;
|
|
1905
|
+
}
|
|
1906
|
+
}), _$createComponent(Show, {
|
|
1907
|
+
get when() {
|
|
1908
|
+
return _$memo(() => balanceState().status === "ok")() && balanceState().data;
|
|
1909
|
+
},
|
|
1910
|
+
get children() {
|
|
1911
|
+
var _el$68 = _$createElement("text");
|
|
1912
|
+
_$insert(_el$68, () => justify(t("balTotal"), formatBalanceText(balanceState().data, balanceCurrency(), exchangeRate())));
|
|
1913
|
+
_$effect((_$p) => _$setProp(_el$68, "fg", pal().text, _$p));
|
|
1914
|
+
return _el$68;
|
|
1653
1915
|
}
|
|
1654
|
-
|
|
1655
|
-
const baseAmt = parseFloat(base.total);
|
|
1656
|
-
const converted = Number.isFinite(baseAmt) ? convertBalance(pref || base.currency, exchangeRate(), baseAmt, base.currency) : baseAmt;
|
|
1657
|
-
const shown = pref && base.currency !== pref ? converted.toLocaleString("en-US", {
|
|
1658
|
-
maximumFractionDigits: 2
|
|
1659
|
-
}) : base.total;
|
|
1660
|
-
return (() => {
|
|
1661
|
-
var _el$92 = _$createElement("text");
|
|
1662
|
-
_$insert(_el$92, () => justify(t().balTotal, balanceSymbol(pref || base.currency) + shown));
|
|
1663
|
-
_$effect((_$p) => _$setProp(_el$92, "fg", pal().text, _$p));
|
|
1664
|
-
return _el$92;
|
|
1665
|
-
})();
|
|
1666
|
-
})();
|
|
1916
|
+
})];
|
|
1667
1917
|
}
|
|
1668
1918
|
})];
|
|
1669
1919
|
}
|
|
@@ -1673,13 +1923,13 @@ function TokenCachePanel(props) {
|
|
|
1673
1923
|
}
|
|
1674
1924
|
}), null);
|
|
1675
1925
|
_$effect((_p$) => {
|
|
1676
|
-
var _v$
|
|
1926
|
+
var _v$15 = {
|
|
1677
1927
|
fg: pal().muted
|
|
1678
|
-
}, _v$
|
|
1928
|
+
}, _v$16 = {
|
|
1679
1929
|
fg: pal().primary
|
|
1680
1930
|
};
|
|
1681
|
-
_v$
|
|
1682
|
-
_v$
|
|
1931
|
+
_v$15 !== _p$.e && (_p$.e = _$setProp(_el$3, "style", _v$15, _p$.e));
|
|
1932
|
+
_v$16 !== _p$.t && (_p$.t = _$setProp(_el$4, "style", _v$16, _p$.t));
|
|
1683
1933
|
return _p$;
|
|
1684
1934
|
}, {
|
|
1685
1935
|
e: void 0,
|
|
@@ -1688,6 +1938,233 @@ function TokenCachePanel(props) {
|
|
|
1688
1938
|
return _el$;
|
|
1689
1939
|
})();
|
|
1690
1940
|
}
|
|
1941
|
+
function BottomStatusBar(props) {
|
|
1942
|
+
const KV_PREFIX = "cache_panel";
|
|
1943
|
+
const t = createT(() => props.signals.langCode());
|
|
1944
|
+
const sid = props.sessionId;
|
|
1945
|
+
const stats = createMemo(() => {
|
|
1946
|
+
const id = sid;
|
|
1947
|
+
if (!id) return null;
|
|
1948
|
+
const msgs = props.api.state.session.messages(id);
|
|
1949
|
+
const session = typeof props.api.state.session.get === "function" ? props.api.state.session.get(id) : void 0;
|
|
1950
|
+
let input = session?.tokens?.input ?? 0;
|
|
1951
|
+
let read = session?.tokens?.cache?.read ?? 0;
|
|
1952
|
+
let write = session?.tokens?.cache?.write ?? 0;
|
|
1953
|
+
if (session?.tokens == null) {
|
|
1954
|
+
for (const m of msgs) {
|
|
1955
|
+
if (m.role !== "assistant") continue;
|
|
1956
|
+
const tk = m.tokens;
|
|
1957
|
+
if (!tk) continue;
|
|
1958
|
+
input += num(tk.input);
|
|
1959
|
+
read += num(tk.cache?.read);
|
|
1960
|
+
write += num(tk.cache?.write);
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
let hitRate = -1, prevHitRate = -1;
|
|
1964
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
1965
|
+
const m = msgs[i];
|
|
1966
|
+
if (m.role !== "assistant") continue;
|
|
1967
|
+
const tk = m.tokens;
|
|
1968
|
+
if (!tk) continue;
|
|
1969
|
+
const mit = num(tk.input) + num(tk.cache?.read) + num(tk.cache?.write);
|
|
1970
|
+
const mrt = num(tk.cache?.read);
|
|
1971
|
+
if (mit <= 0) continue;
|
|
1972
|
+
const rate = mrt / mit * 100;
|
|
1973
|
+
if (hitRate < 0) {
|
|
1974
|
+
hitRate = rate;
|
|
1975
|
+
continue;
|
|
1976
|
+
}
|
|
1977
|
+
prevHitRate = rate;
|
|
1978
|
+
break;
|
|
1979
|
+
}
|
|
1980
|
+
return {
|
|
1981
|
+
hitRate,
|
|
1982
|
+
prevHitRate,
|
|
1983
|
+
input,
|
|
1984
|
+
read,
|
|
1985
|
+
write
|
|
1986
|
+
};
|
|
1987
|
+
});
|
|
1988
|
+
createEffect(() => {
|
|
1989
|
+
if (!props.signals.autoBalance()) return;
|
|
1990
|
+
const id = sid;
|
|
1991
|
+
if (!id) return;
|
|
1992
|
+
const msgs = props.api.state.session.messages(id);
|
|
1993
|
+
let pid = "";
|
|
1994
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
1995
|
+
const m = msgs[i];
|
|
1996
|
+
if (m.role === "assistant" && m.providerID) {
|
|
1997
|
+
pid = m.providerID;
|
|
1998
|
+
break;
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
if (!pid) {
|
|
2002
|
+
try {
|
|
2003
|
+
pid = props.api.state.session.get(id)?.model?.providerID ?? "";
|
|
2004
|
+
} catch {
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
if (!pid) return;
|
|
2008
|
+
const hit = matchBalanceProvider(pid);
|
|
2009
|
+
if (hit) {
|
|
2010
|
+
props.signals.setBalanceUnsupported(false);
|
|
2011
|
+
if (hit.id !== props.signals.balanceProviderId()) {
|
|
2012
|
+
props.signals.setBalanceProviderId(hit.id);
|
|
2013
|
+
props.signals.setBalanceRefresh(props.signals.balanceRefresh() + 1);
|
|
2014
|
+
}
|
|
2015
|
+
} else {
|
|
2016
|
+
props.signals.setBalanceUnsupported(true);
|
|
2017
|
+
}
|
|
2018
|
+
});
|
|
2019
|
+
const pal = createMemo(() => {
|
|
2020
|
+
const th = props.api.theme.current;
|
|
2021
|
+
const sat = (k, fb) => desaturateTo(th[k], MAX_SAT, fb);
|
|
2022
|
+
return {
|
|
2023
|
+
text: sat("text", FALLBACK.text),
|
|
2024
|
+
muted: sat("textMuted", FALLBACK.muted),
|
|
2025
|
+
success: sat("success", FALLBACK.success),
|
|
2026
|
+
warning: sat("warning", FALLBACK.warning),
|
|
2027
|
+
error: sat("error", FALLBACK.error)
|
|
2028
|
+
};
|
|
2029
|
+
});
|
|
2030
|
+
const hitColor = createMemo(() => {
|
|
2031
|
+
const r = stats()?.hitRate ?? -1;
|
|
2032
|
+
if (r >= 85) return pal().success;
|
|
2033
|
+
if (r >= 70) return pal().warning;
|
|
2034
|
+
return pal().error;
|
|
2035
|
+
});
|
|
2036
|
+
const trend = createMemo(() => {
|
|
2037
|
+
const s = stats();
|
|
2038
|
+
if (!s || s.prevHitRate < 0 || s.hitRate < 0) return null;
|
|
2039
|
+
const d = s.hitRate - s.prevHitRate;
|
|
2040
|
+
return Math.abs(d) < 0.05 ? null : d;
|
|
2041
|
+
});
|
|
2042
|
+
const balanceText = createMemo(() => {
|
|
2043
|
+
const s = props.signals.balanceState();
|
|
2044
|
+
if (s.status === "ok" && s.data) return formatBalanceText(s.data, props.signals.balanceCurrency(), props.signals.exchangeRate());
|
|
2045
|
+
if (s.status === "loading") return "\u2026";
|
|
2046
|
+
if (s.status === "error") return "\u26A0";
|
|
2047
|
+
return "-";
|
|
2048
|
+
});
|
|
2049
|
+
const directory = createMemo(() => {
|
|
2050
|
+
try {
|
|
2051
|
+
return props.api.state.path.directory;
|
|
2052
|
+
} catch {
|
|
2053
|
+
return "";
|
|
2054
|
+
}
|
|
2055
|
+
});
|
|
2056
|
+
onMount(() => {
|
|
2057
|
+
try {
|
|
2058
|
+
const v = props.api.kv.get(`${KV_PREFIX}.section.bottom`, true);
|
|
2059
|
+
props.signals.setSectionBottom(v !== false);
|
|
2060
|
+
} catch {
|
|
2061
|
+
}
|
|
2062
|
+
});
|
|
2063
|
+
return _$createComponent(Show, {
|
|
2064
|
+
get when() {
|
|
2065
|
+
return props.signals.sectionBottom();
|
|
2066
|
+
},
|
|
2067
|
+
get fallback() {
|
|
2068
|
+
return (() => {
|
|
2069
|
+
var _el$110 = _$createElement("text");
|
|
2070
|
+
_$insert(_el$110, directory);
|
|
2071
|
+
_$effect((_$p) => _$setProp(_el$110, "fg", pal().muted, _$p));
|
|
2072
|
+
return _el$110;
|
|
2073
|
+
})();
|
|
2074
|
+
},
|
|
2075
|
+
get children() {
|
|
2076
|
+
var _el$96 = _$createElement("box"), _el$97 = _$createElement("text"), _el$98 = _$createElement("box"), _el$99 = _$createElement("text"), _el$100 = _$createElement("span"), _el$101 = _$createTextNode(` `), _el$102 = _$createElement("span"), _el$104 = _$createElement("span"), _el$105 = _$createElement("span"), _el$108 = _$createElement("text");
|
|
2077
|
+
_$insertNode(_el$96, _el$97);
|
|
2078
|
+
_$insertNode(_el$96, _el$98);
|
|
2079
|
+
_$setProp(_el$96, "marginLeft", 1);
|
|
2080
|
+
_$setProp(_el$96, "flexGrow", 1);
|
|
2081
|
+
_$setProp(_el$96, "flexShrink", 0);
|
|
2082
|
+
_$setProp(_el$96, "flexDirection", "row");
|
|
2083
|
+
_$setProp(_el$96, "justifyContent", "space-between");
|
|
2084
|
+
_$insert(_el$97, directory);
|
|
2085
|
+
_$insertNode(_el$98, _el$99);
|
|
2086
|
+
_$insertNode(_el$98, _el$108);
|
|
2087
|
+
_$setProp(_el$98, "flexDirection", "row");
|
|
2088
|
+
_$insertNode(_el$99, _el$100);
|
|
2089
|
+
_$insertNode(_el$99, _el$102);
|
|
2090
|
+
_$insertNode(_el$99, _el$104);
|
|
2091
|
+
_$insertNode(_el$99, _el$105);
|
|
2092
|
+
_$insertNode(_el$100, _el$101);
|
|
2093
|
+
_$insert(_el$100, () => t("barHit"), _el$101);
|
|
2094
|
+
_$insert(_el$102, (() => {
|
|
2095
|
+
var _c$ = _$memo(() => (stats()?.hitRate ?? -1) >= 0);
|
|
2096
|
+
return () => _c$() ? (Math.floor(stats().hitRate * 10) / 10).toFixed(1) + "%" : "--";
|
|
2097
|
+
})());
|
|
2098
|
+
_$insert(_el$99, _$createComponent(Show, {
|
|
2099
|
+
get when() {
|
|
2100
|
+
return trend() !== null;
|
|
2101
|
+
},
|
|
2102
|
+
get children() {
|
|
2103
|
+
var _el$103 = _$createElement("span");
|
|
2104
|
+
_$insert(_el$103, () => " " + (trend() > 0 ? "\u2191" : "\u2193") + Math.abs(trend()).toFixed(1) + "%");
|
|
2105
|
+
_$effect((_$p) => _$setProp(_el$103, "style", {
|
|
2106
|
+
fg: trend() > 0 ? pal().success : pal().error
|
|
2107
|
+
}, _$p));
|
|
2108
|
+
return _el$103;
|
|
2109
|
+
}
|
|
2110
|
+
}), _el$104);
|
|
2111
|
+
_$insert(_el$104, () => " \xB7 " + t("barTok") + " ");
|
|
2112
|
+
_$insert(_el$105, (() => {
|
|
2113
|
+
var _c$2 = _$memo(() => !!stats());
|
|
2114
|
+
return () => _c$2() ? fmtCompact(stats().input + stats().read + stats().write) : "--";
|
|
2115
|
+
})());
|
|
2116
|
+
_$insert(_el$99, _$createComponent(Show, {
|
|
2117
|
+
get when() {
|
|
2118
|
+
return !props.signals.balanceUnsupported();
|
|
2119
|
+
},
|
|
2120
|
+
get children() {
|
|
2121
|
+
return [(() => {
|
|
2122
|
+
var _el$106 = _$createElement("span");
|
|
2123
|
+
_$insert(_el$106, () => " \xB7 " + t("barBal") + " ");
|
|
2124
|
+
_$effect((_$p) => _$setProp(_el$106, "style", {
|
|
2125
|
+
fg: pal().muted
|
|
2126
|
+
}, _$p));
|
|
2127
|
+
return _el$106;
|
|
2128
|
+
})(), (() => {
|
|
2129
|
+
var _el$107 = _$createElement("span");
|
|
2130
|
+
_$insert(_el$107, balanceText);
|
|
2131
|
+
_$effect((_$p) => _$setProp(_el$107, "style", {
|
|
2132
|
+
fg: pal().text
|
|
2133
|
+
}, _$p));
|
|
2134
|
+
return _el$107;
|
|
2135
|
+
})()];
|
|
2136
|
+
}
|
|
2137
|
+
}), null);
|
|
2138
|
+
_$insertNode(_el$108, _$createTextNode(` \xB7 `));
|
|
2139
|
+
_$effect((_p$) => {
|
|
2140
|
+
var _v$31 = pal().muted, _v$32 = {
|
|
2141
|
+
fg: pal().muted
|
|
2142
|
+
}, _v$33 = {
|
|
2143
|
+
fg: hitColor()
|
|
2144
|
+
}, _v$34 = {
|
|
2145
|
+
fg: pal().muted
|
|
2146
|
+
}, _v$35 = {
|
|
2147
|
+
fg: pal().text
|
|
2148
|
+
}, _v$36 = pal().muted;
|
|
2149
|
+
_v$31 !== _p$.e && (_p$.e = _$setProp(_el$97, "fg", _v$31, _p$.e));
|
|
2150
|
+
_v$32 !== _p$.t && (_p$.t = _$setProp(_el$100, "style", _v$32, _p$.t));
|
|
2151
|
+
_v$33 !== _p$.a && (_p$.a = _$setProp(_el$102, "style", _v$33, _p$.a));
|
|
2152
|
+
_v$34 !== _p$.o && (_p$.o = _$setProp(_el$104, "style", _v$34, _p$.o));
|
|
2153
|
+
_v$35 !== _p$.i && (_p$.i = _$setProp(_el$105, "style", _v$35, _p$.i));
|
|
2154
|
+
_v$36 !== _p$.n && (_p$.n = _$setProp(_el$108, "fg", _v$36, _p$.n));
|
|
2155
|
+
return _p$;
|
|
2156
|
+
}, {
|
|
2157
|
+
e: void 0,
|
|
2158
|
+
t: void 0,
|
|
2159
|
+
a: void 0,
|
|
2160
|
+
o: void 0,
|
|
2161
|
+
i: void 0,
|
|
2162
|
+
n: void 0
|
|
2163
|
+
});
|
|
2164
|
+
return _el$96;
|
|
2165
|
+
}
|
|
2166
|
+
});
|
|
2167
|
+
}
|
|
1691
2168
|
function createSidebarSlot(api, signals) {
|
|
1692
2169
|
let lastSlotSid = "";
|
|
1693
2170
|
return {
|
|
@@ -1723,20 +2200,28 @@ var tui = async (api) => {
|
|
|
1723
2200
|
const [sectionDist, setSectionDist] = createSignal(true);
|
|
1724
2201
|
const [sectionSkills, setSectionSkills] = createSignal(true);
|
|
1725
2202
|
const [sectionBalance, setSectionBalance] = createSignal(true);
|
|
2203
|
+
const [sectionBottom, setSectionBottom] = createSignal(true);
|
|
1726
2204
|
const [balanceRefresh, setBalanceRefresh] = createSignal(0);
|
|
1727
2205
|
const [balanceProviderId, setBalanceProviderId] = createSignal("deepseek");
|
|
1728
2206
|
const [autoBalance, setAutoBalance] = createSignal(true);
|
|
2207
|
+
const [balanceUnsupported, setBalanceUnsupported] = createSignal(false);
|
|
1729
2208
|
const [balanceCurrency, setBalanceCurrency] = createSignal("");
|
|
1730
2209
|
const [borderVisible, setBorderVisible] = createSignal(true);
|
|
1731
|
-
const [
|
|
2210
|
+
const [langCode, setLangCode] = createSignal(INIT_LANG);
|
|
1732
2211
|
const [overrideSessionId, setOverrideSessionId] = createSignal(void 0);
|
|
2212
|
+
const [balanceState, setBalanceState] = createSignal({
|
|
2213
|
+
status: "idle",
|
|
2214
|
+
data: null,
|
|
2215
|
+
lastFetch: 0
|
|
2216
|
+
});
|
|
2217
|
+
let balanceSeq = 0;
|
|
1733
2218
|
const signals = {
|
|
1734
2219
|
currencySymbol,
|
|
1735
2220
|
setCurrencySymbol,
|
|
1736
2221
|
exchangeRate,
|
|
1737
2222
|
setExchangeRate,
|
|
1738
|
-
|
|
1739
|
-
|
|
2223
|
+
langCode,
|
|
2224
|
+
setLangCode,
|
|
1740
2225
|
sectionDetail,
|
|
1741
2226
|
setSectionDetail,
|
|
1742
2227
|
sectionModel,
|
|
@@ -1747,12 +2232,17 @@ var tui = async (api) => {
|
|
|
1747
2232
|
setSectionSkills,
|
|
1748
2233
|
sectionBalance,
|
|
1749
2234
|
setSectionBalance,
|
|
2235
|
+
sectionBottom,
|
|
2236
|
+
setSectionBottom,
|
|
1750
2237
|
balanceRefresh,
|
|
1751
2238
|
setBalanceRefresh,
|
|
1752
2239
|
balanceProviderId,
|
|
1753
2240
|
setBalanceProviderId,
|
|
1754
2241
|
autoBalance,
|
|
1755
2242
|
setAutoBalance,
|
|
2243
|
+
balanceUnsupported,
|
|
2244
|
+
setBalanceUnsupported,
|
|
2245
|
+
balanceState,
|
|
1756
2246
|
balanceCurrency,
|
|
1757
2247
|
setBalanceCurrency,
|
|
1758
2248
|
borderVisible,
|
|
@@ -1761,16 +2251,139 @@ var tui = async (api) => {
|
|
|
1761
2251
|
setOverrideSessionId
|
|
1762
2252
|
};
|
|
1763
2253
|
api.slots.register(createSidebarSlot(api, signals));
|
|
2254
|
+
api.slots.register({
|
|
2255
|
+
order: 55,
|
|
2256
|
+
slots: {
|
|
2257
|
+
session_prompt(_ctx, input) {
|
|
2258
|
+
return _$createComponent(api.ui.Prompt, {
|
|
2259
|
+
get sessionID() {
|
|
2260
|
+
return input.session_id;
|
|
2261
|
+
},
|
|
2262
|
+
get visible() {
|
|
2263
|
+
return input.visible;
|
|
2264
|
+
},
|
|
2265
|
+
get disabled() {
|
|
2266
|
+
return input.disabled;
|
|
2267
|
+
},
|
|
2268
|
+
get onSubmit() {
|
|
2269
|
+
return input.on_submit;
|
|
2270
|
+
},
|
|
2271
|
+
ref(r$) {
|
|
2272
|
+
var _ref$2 = input.ref;
|
|
2273
|
+
typeof _ref$2 === "function" ? _ref$2(r$) : input.ref = r$;
|
|
2274
|
+
},
|
|
2275
|
+
get hint() {
|
|
2276
|
+
return _$createComponent(BottomStatusBar, {
|
|
2277
|
+
api,
|
|
2278
|
+
signals,
|
|
2279
|
+
get sessionId() {
|
|
2280
|
+
return input.session_id;
|
|
2281
|
+
}
|
|
2282
|
+
});
|
|
2283
|
+
}
|
|
2284
|
+
});
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
});
|
|
1764
2288
|
const KV_PREFIX = "cache_panel";
|
|
2289
|
+
const restoreLang = () => {
|
|
2290
|
+
try {
|
|
2291
|
+
const saved = api.kv.get(`${KV_PREFIX}.lang`);
|
|
2292
|
+
if (saved && LANG_META.some((m) => m.code === saved)) setLangCode(saved);
|
|
2293
|
+
} catch {
|
|
2294
|
+
}
|
|
2295
|
+
};
|
|
2296
|
+
if (api.kv.ready) {
|
|
2297
|
+
restoreLang();
|
|
2298
|
+
} else {
|
|
2299
|
+
const langTimer = setInterval(() => {
|
|
2300
|
+
if (api.kv.ready) {
|
|
2301
|
+
clearInterval(langTimer);
|
|
2302
|
+
restoreLang();
|
|
2303
|
+
}
|
|
2304
|
+
}, 10);
|
|
2305
|
+
api.lifecycle.onDispose(() => clearInterval(langTimer));
|
|
2306
|
+
}
|
|
2307
|
+
const pollBalance = async () => {
|
|
2308
|
+
const provider = getBalanceProvider(balanceProviderId());
|
|
2309
|
+
const key = api.kv.get(`${KV_PREFIX}.balance.${provider.id}.key`, "") || findOpencodeKey(api, provider);
|
|
2310
|
+
if (balanceUnsupported()) {
|
|
2311
|
+
setBalanceState({
|
|
2312
|
+
status: "idle",
|
|
2313
|
+
data: null,
|
|
2314
|
+
lastFetch: 0,
|
|
2315
|
+
error: void 0,
|
|
2316
|
+
key: void 0
|
|
2317
|
+
});
|
|
2318
|
+
return;
|
|
2319
|
+
}
|
|
2320
|
+
if (!key) {
|
|
2321
|
+
setBalanceState({
|
|
2322
|
+
status: "idle",
|
|
2323
|
+
data: null,
|
|
2324
|
+
lastFetch: 0,
|
|
2325
|
+
error: void 0,
|
|
2326
|
+
key: void 0
|
|
2327
|
+
});
|
|
2328
|
+
return;
|
|
2329
|
+
}
|
|
2330
|
+
const now = Date.now();
|
|
2331
|
+
const prev = balanceState();
|
|
2332
|
+
if (prev.status === "ok" && prev.key === key && now - prev.lastFetch < BALANCE_POLL_MS) return;
|
|
2333
|
+
const seq = ++balanceSeq;
|
|
2334
|
+
setBalanceState({
|
|
2335
|
+
...prev,
|
|
2336
|
+
status: "loading",
|
|
2337
|
+
error: void 0,
|
|
2338
|
+
key
|
|
2339
|
+
});
|
|
2340
|
+
const controller = new AbortController();
|
|
2341
|
+
let timedOut = false;
|
|
2342
|
+
const timer = setTimeout(() => {
|
|
2343
|
+
timedOut = true;
|
|
2344
|
+
controller.abort();
|
|
2345
|
+
}, 1e4);
|
|
2346
|
+
try {
|
|
2347
|
+
const data = await provider.fetchBalance(key, controller.signal);
|
|
2348
|
+
clearTimeout(timer);
|
|
2349
|
+
if (seq !== balanceSeq) return;
|
|
2350
|
+
setBalanceState({
|
|
2351
|
+
status: "ok",
|
|
2352
|
+
data,
|
|
2353
|
+
lastFetch: Date.now(),
|
|
2354
|
+
error: void 0,
|
|
2355
|
+
key
|
|
2356
|
+
});
|
|
2357
|
+
} catch (err) {
|
|
2358
|
+
clearTimeout(timer);
|
|
2359
|
+
if (seq !== balanceSeq) return;
|
|
2360
|
+
const code = timedOut ? "TIMEOUT" : err instanceof Error ? err.message : "";
|
|
2361
|
+
setBalanceState({
|
|
2362
|
+
status: "error",
|
|
2363
|
+
data: null,
|
|
2364
|
+
lastFetch: 0,
|
|
2365
|
+
error: code,
|
|
2366
|
+
key
|
|
2367
|
+
});
|
|
2368
|
+
}
|
|
2369
|
+
};
|
|
2370
|
+
createEffect(() => {
|
|
2371
|
+
void balanceRefresh();
|
|
2372
|
+
untrack(() => {
|
|
2373
|
+
void pollBalance();
|
|
2374
|
+
});
|
|
2375
|
+
});
|
|
2376
|
+
const balanceTimer = setInterval(pollBalance, BALANCE_POLL_MS);
|
|
2377
|
+
api.lifecycle.onDispose(() => clearInterval(balanceTimer));
|
|
1765
2378
|
const providerOptionTitle = (p, current) => {
|
|
1766
|
-
const
|
|
2379
|
+
const t = createT(() => langCode());
|
|
1767
2380
|
const hasManual = !!api.kv.get(`${KV_PREFIX}.balance.${p.id}.key`, "");
|
|
1768
2381
|
const hasAuto = !hasManual && !!findOpencodeKey(api, p);
|
|
1769
|
-
const mark = hasManual ?
|
|
2382
|
+
const mark = hasManual ? t("keyUser") : hasAuto ? t("keyOpenCode") : t("keyNotSet");
|
|
1770
2383
|
return p.name + mark + (current && p.id === current ? " *" : "");
|
|
1771
2384
|
};
|
|
1772
2385
|
const promptBalanceKey = (dialog, provider) => {
|
|
1773
|
-
const
|
|
2386
|
+
const t = createT(() => langCode());
|
|
1774
2387
|
const current = api.kv.get(`${KV_PREFIX}.balance.${provider.id}.key`, "");
|
|
1775
2388
|
const masked = maskKey(current);
|
|
1776
2389
|
dialog?.replace(() => _$createComponent(api.ui.DialogPrompt, {
|
|
@@ -1778,9 +2391,11 @@ var tui = async (api) => {
|
|
|
1778
2391
|
return provider.name;
|
|
1779
2392
|
},
|
|
1780
2393
|
description: () => (() => {
|
|
1781
|
-
var _el$
|
|
1782
|
-
_$insert(_el$
|
|
1783
|
-
|
|
2394
|
+
var _el$111 = _$createElement("text");
|
|
2395
|
+
_$insert(_el$111, () => t("balKeyPrompt", {
|
|
2396
|
+
p: provider.name
|
|
2397
|
+
}));
|
|
2398
|
+
return _el$111;
|
|
1784
2399
|
})(),
|
|
1785
2400
|
get placeholder() {
|
|
1786
2401
|
return provider.keyPlaceholder ?? "sk-...";
|
|
@@ -1800,11 +2415,11 @@ var tui = async (api) => {
|
|
|
1800
2415
|
setBalanceRefresh((v) => v + 1);
|
|
1801
2416
|
if (key) {
|
|
1802
2417
|
api.ui.toast({
|
|
1803
|
-
message:
|
|
2418
|
+
message: t("keySaved")
|
|
1804
2419
|
});
|
|
1805
2420
|
} else {
|
|
1806
2421
|
api.ui.toast({
|
|
1807
|
-
message:
|
|
2422
|
+
message: t("keyCleared")
|
|
1808
2423
|
});
|
|
1809
2424
|
}
|
|
1810
2425
|
dialog?.clear();
|
|
@@ -1829,6 +2444,7 @@ var tui = async (api) => {
|
|
|
1829
2444
|
}));
|
|
1830
2445
|
},
|
|
1831
2446
|
onSelect: (opt) => {
|
|
2447
|
+
const t = createT(() => langCode());
|
|
1832
2448
|
const sym = CURRENCIES[opt.value] ?? "$";
|
|
1833
2449
|
const defRate = DEFAULT_RATES[opt.value] ?? 1;
|
|
1834
2450
|
api.kv.set(`${KV_PREFIX}.currency`, sym);
|
|
@@ -1838,7 +2454,11 @@ var tui = async (api) => {
|
|
|
1838
2454
|
signals.setCurrencySymbol(sym);
|
|
1839
2455
|
signals.setExchangeRate(defRate);
|
|
1840
2456
|
api.ui.toast({
|
|
1841
|
-
message:
|
|
2457
|
+
message: t("currencySet", {
|
|
2458
|
+
v: opt.value,
|
|
2459
|
+
s: sym,
|
|
2460
|
+
r: defRate
|
|
2461
|
+
})
|
|
1842
2462
|
});
|
|
1843
2463
|
dialog?.clear();
|
|
1844
2464
|
}
|
|
@@ -1855,21 +2475,24 @@ var tui = async (api) => {
|
|
|
1855
2475
|
dialog?.replace(() => _$createComponent(api.ui.DialogPrompt, {
|
|
1856
2476
|
title: "Exchange Rate",
|
|
1857
2477
|
description: () => (() => {
|
|
1858
|
-
var _el$
|
|
1859
|
-
_$insertNode(_el$
|
|
1860
|
-
return _el$
|
|
2478
|
+
var _el$112 = _$createElement("text");
|
|
2479
|
+
_$insertNode(_el$112, _$createTextNode(`Enter the exchange rate from USD to your currency (e.g. 7.2 for CNY)`));
|
|
2480
|
+
return _el$112;
|
|
1861
2481
|
})(),
|
|
1862
2482
|
placeholder: "1.0",
|
|
1863
2483
|
get value() {
|
|
1864
2484
|
return String(api.kv.get(`${KV_PREFIX}.rate`, 1));
|
|
1865
2485
|
},
|
|
1866
2486
|
onConfirm: (val) => {
|
|
2487
|
+
const t = createT(() => langCode());
|
|
1867
2488
|
const n = parseFloat(val);
|
|
1868
2489
|
if (n > 0) {
|
|
1869
2490
|
api.kv.set(`${KV_PREFIX}.rate`, n);
|
|
1870
2491
|
signals.setExchangeRate(n);
|
|
1871
2492
|
api.ui.toast({
|
|
1872
|
-
message:
|
|
2493
|
+
message: t("rateSet", {
|
|
2494
|
+
r: n
|
|
2495
|
+
})
|
|
1873
2496
|
});
|
|
1874
2497
|
}
|
|
1875
2498
|
dialog?.clear();
|
|
@@ -1884,40 +2507,59 @@ var tui = async (api) => {
|
|
|
1884
2507
|
name: "cache-section"
|
|
1885
2508
|
},
|
|
1886
2509
|
onSelect: (dialog) => {
|
|
2510
|
+
const t = createT(() => langCode());
|
|
1887
2511
|
const detailOn = Boolean(api.kv.get(`${KV_PREFIX}.section.detail`, true));
|
|
1888
2512
|
const modelOn = Boolean(api.kv.get(`${KV_PREFIX}.section.model`, true));
|
|
1889
2513
|
const distOn = Boolean(api.kv.get(`${KV_PREFIX}.section.dist`, true));
|
|
1890
2514
|
const skillsOn = Boolean(api.kv.get(`${KV_PREFIX}.section.skills`, true));
|
|
1891
2515
|
const balanceOn = Boolean(api.kv.get(`${KV_PREFIX}.section.balance`, true));
|
|
2516
|
+
const bottomOn = Boolean(api.kv.get(`${KV_PREFIX}.section.bottom`, true));
|
|
1892
2517
|
const borderOn = Boolean(api.kv.get(`${KV_PREFIX}.border`, true));
|
|
2518
|
+
const labels = {
|
|
2519
|
+
detail: t("secDetail"),
|
|
2520
|
+
model: t("secModel"),
|
|
2521
|
+
dist: t("distTitle"),
|
|
2522
|
+
skills: t("secSkills"),
|
|
2523
|
+
balance: t("secBalance"),
|
|
2524
|
+
bottom: t("secBottom"),
|
|
2525
|
+
border: t("secBorder")
|
|
2526
|
+
};
|
|
2527
|
+
const optTitle = (label, on) => `${visualPadEnd(label, 15)}[${on ? "ON" : "OFF"}]`;
|
|
1893
2528
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
1894
|
-
title
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
2529
|
+
get title() {
|
|
2530
|
+
return t("secToggle");
|
|
2531
|
+
},
|
|
2532
|
+
get options() {
|
|
2533
|
+
return [{
|
|
2534
|
+
title: optTitle(labels.detail, detailOn),
|
|
2535
|
+
value: "detail"
|
|
2536
|
+
}, {
|
|
2537
|
+
title: optTitle(labels.model, modelOn),
|
|
2538
|
+
value: "model"
|
|
2539
|
+
}, {
|
|
2540
|
+
title: optTitle(labels.dist, distOn),
|
|
2541
|
+
value: "dist"
|
|
2542
|
+
}, {
|
|
2543
|
+
title: optTitle(labels.skills, skillsOn),
|
|
2544
|
+
value: "skills"
|
|
2545
|
+
}, {
|
|
2546
|
+
title: optTitle(labels.balance, balanceOn),
|
|
2547
|
+
value: "balance"
|
|
2548
|
+
}, {
|
|
2549
|
+
title: optTitle(labels.bottom, bottomOn),
|
|
2550
|
+
value: "bottom"
|
|
2551
|
+
}, {
|
|
2552
|
+
title: optTitle(labels.border, borderOn),
|
|
2553
|
+
value: "border"
|
|
2554
|
+
}];
|
|
2555
|
+
},
|
|
1914
2556
|
onSelect: (opt) => {
|
|
1915
2557
|
if (opt.value === "border") {
|
|
1916
2558
|
const cur = Boolean(api.kv.get(`${KV_PREFIX}.border`, true));
|
|
1917
2559
|
api.kv.set(`${KV_PREFIX}.border`, !cur);
|
|
1918
2560
|
signals.setBorderVisible(!cur);
|
|
1919
2561
|
api.ui.toast({
|
|
1920
|
-
message:
|
|
2562
|
+
message: !cur ? t("borderShown") : t("borderHidden")
|
|
1921
2563
|
});
|
|
1922
2564
|
} else {
|
|
1923
2565
|
const key = `${KV_PREFIX}.section.${opt.value}`;
|
|
@@ -1928,8 +2570,12 @@ var tui = async (api) => {
|
|
|
1928
2570
|
if (opt.value === "dist") signals.setSectionDist(!cur);
|
|
1929
2571
|
if (opt.value === "skills") signals.setSectionSkills(!cur);
|
|
1930
2572
|
if (opt.value === "balance") signals.setSectionBalance(!cur);
|
|
2573
|
+
if (opt.value === "bottom") signals.setSectionBottom(!cur);
|
|
2574
|
+
const name = labels[opt.value] ?? opt.value;
|
|
1931
2575
|
api.ui.toast({
|
|
1932
|
-
message:
|
|
2576
|
+
message: t(!cur ? "sectionShown" : "sectionHidden", {
|
|
2577
|
+
s: name
|
|
2578
|
+
})
|
|
1933
2579
|
});
|
|
1934
2580
|
}
|
|
1935
2581
|
dialog?.clear();
|
|
@@ -1944,6 +2590,7 @@ var tui = async (api) => {
|
|
|
1944
2590
|
name: "cache-config"
|
|
1945
2591
|
},
|
|
1946
2592
|
onSelect: (dialog) => {
|
|
2593
|
+
const t = createT(() => langCode());
|
|
1947
2594
|
const sym = api.kv.get(`${KV_PREFIX}.currency`) ?? "$";
|
|
1948
2595
|
const rate = api.kv.get(`${KV_PREFIX}.rate`) ?? 1;
|
|
1949
2596
|
const detail = Boolean(api.kv.get(`${KV_PREFIX}.section.detail`, true));
|
|
@@ -1951,9 +2598,20 @@ var tui = async (api) => {
|
|
|
1951
2598
|
const dist = Boolean(api.kv.get(`${KV_PREFIX}.section.dist`, true));
|
|
1952
2599
|
const skills = Boolean(api.kv.get(`${KV_PREFIX}.section.skills`, true));
|
|
1953
2600
|
const balance = Boolean(api.kv.get(`${KV_PREFIX}.section.balance`, true));
|
|
2601
|
+
const bottom = Boolean(api.kv.get(`${KV_PREFIX}.section.bottom`, true));
|
|
2602
|
+
const on = (v) => v ? "ON" : "OFF";
|
|
1954
2603
|
api.ui.toast({
|
|
1955
|
-
title: "
|
|
1956
|
-
message:
|
|
2604
|
+
title: t("panelConfigTitle"),
|
|
2605
|
+
message: t("panelConfigMsg", {
|
|
2606
|
+
c: sym,
|
|
2607
|
+
r: rate,
|
|
2608
|
+
d: on(detail),
|
|
2609
|
+
m: on(model),
|
|
2610
|
+
t: on(dist),
|
|
2611
|
+
k: on(skills),
|
|
2612
|
+
b: on(balance),
|
|
2613
|
+
f: on(bottom)
|
|
2614
|
+
}),
|
|
1957
2615
|
duration: 8e3
|
|
1958
2616
|
});
|
|
1959
2617
|
dialog?.clear();
|
|
@@ -1966,22 +2624,24 @@ var tui = async (api) => {
|
|
|
1966
2624
|
name: "cache-lang"
|
|
1967
2625
|
},
|
|
1968
2626
|
onSelect: (dialog) => {
|
|
1969
|
-
const
|
|
2627
|
+
const t = createT(() => langCode());
|
|
2628
|
+
const cur = langCode();
|
|
1970
2629
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
1971
|
-
title
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
2630
|
+
get title() {
|
|
2631
|
+
return t("langTitle");
|
|
2632
|
+
},
|
|
2633
|
+
get options() {
|
|
2634
|
+
return LANG_META.map((m) => ({
|
|
2635
|
+
title: `${visualPadEnd(m.label, 9)}${cur === m.code ? "\u2713" : ""}`,
|
|
2636
|
+
value: m.code
|
|
2637
|
+
}));
|
|
2638
|
+
},
|
|
1979
2639
|
onSelect: (opt) => {
|
|
1980
|
-
const
|
|
1981
|
-
api.kv.set(`${KV_PREFIX}.lang`,
|
|
1982
|
-
|
|
2640
|
+
const code = opt.value;
|
|
2641
|
+
api.kv.set(`${KV_PREFIX}.lang`, code);
|
|
2642
|
+
setLangCode(code);
|
|
1983
2643
|
api.ui.toast({
|
|
1984
|
-
message:
|
|
2644
|
+
message: t("langSwitched")
|
|
1985
2645
|
});
|
|
1986
2646
|
dialog?.clear();
|
|
1987
2647
|
}
|
|
@@ -1995,12 +2655,14 @@ var tui = async (api) => {
|
|
|
1995
2655
|
name: "cache-balance"
|
|
1996
2656
|
},
|
|
1997
2657
|
onSelect: (dialog) => {
|
|
1998
|
-
const
|
|
2658
|
+
const t = createT(() => langCode());
|
|
1999
2659
|
const current = signals.balanceProviderId();
|
|
2000
2660
|
const auto = signals.autoBalance();
|
|
2001
|
-
const autoLabel =
|
|
2661
|
+
const autoLabel = `${t("autoSwitchOpt")} [${auto ? "ON" : "OFF"}]`;
|
|
2002
2662
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
2003
|
-
title
|
|
2663
|
+
get title() {
|
|
2664
|
+
return t("balProvTitle");
|
|
2665
|
+
},
|
|
2004
2666
|
get options() {
|
|
2005
2667
|
return [{
|
|
2006
2668
|
title: autoLabel,
|
|
@@ -2016,7 +2678,7 @@ var tui = async (api) => {
|
|
|
2016
2678
|
api.kv.set(`${KV_PREFIX}.balance.auto`, next);
|
|
2017
2679
|
signals.setAutoBalance(next);
|
|
2018
2680
|
api.ui.toast({
|
|
2019
|
-
message:
|
|
2681
|
+
message: next ? t("autoSwitchOn") : t("autoSwitchOff")
|
|
2020
2682
|
});
|
|
2021
2683
|
dialog?.clear();
|
|
2022
2684
|
} else {
|
|
@@ -2025,13 +2687,16 @@ var tui = async (api) => {
|
|
|
2025
2687
|
api.kv.set(`${KV_PREFIX}.balance.auto`, false);
|
|
2026
2688
|
signals.setBalanceProviderId(provider.id);
|
|
2027
2689
|
signals.setAutoBalance(false);
|
|
2690
|
+
signals.setBalanceUnsupported(false);
|
|
2028
2691
|
signals.setBalanceRefresh(signals.balanceRefresh() + 1);
|
|
2029
2692
|
const hasKey = !!api.kv.get(`${KV_PREFIX}.balance.${provider.id}.key`, "");
|
|
2030
2693
|
if (!hasKey) {
|
|
2031
2694
|
promptBalanceKey(dialog, provider);
|
|
2032
2695
|
} else {
|
|
2033
2696
|
api.ui.toast({
|
|
2034
|
-
message:
|
|
2697
|
+
message: t("providerManual", {
|
|
2698
|
+
p: provider.name
|
|
2699
|
+
})
|
|
2035
2700
|
});
|
|
2036
2701
|
dialog?.clear();
|
|
2037
2702
|
}
|
|
@@ -2047,9 +2712,11 @@ var tui = async (api) => {
|
|
|
2047
2712
|
name: "cache-balance-key"
|
|
2048
2713
|
},
|
|
2049
2714
|
onSelect: (dialog) => {
|
|
2050
|
-
const
|
|
2715
|
+
const t = createT(() => langCode());
|
|
2051
2716
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
2052
|
-
title
|
|
2717
|
+
get title() {
|
|
2718
|
+
return t("balSelectTitle");
|
|
2719
|
+
},
|
|
2053
2720
|
get options() {
|
|
2054
2721
|
return balanceProviders.map((p) => ({
|
|
2055
2722
|
title: providerOptionTitle(p),
|
|
@@ -2075,10 +2742,11 @@ var tui = async (api) => {
|
|
|
2075
2742
|
name: "cache-debug-skills"
|
|
2076
2743
|
},
|
|
2077
2744
|
onSelect: () => {
|
|
2745
|
+
const t = createT(() => langCode());
|
|
2078
2746
|
const rt = api.route.current;
|
|
2079
2747
|
if (rt.name !== "session" || !rt.params) {
|
|
2080
2748
|
api.ui.toast({
|
|
2081
|
-
message: "
|
|
2749
|
+
message: t("runInSession"),
|
|
2082
2750
|
variant: "warning"
|
|
2083
2751
|
});
|
|
2084
2752
|
return;
|
|
@@ -2096,9 +2764,9 @@ var tui = async (api) => {
|
|
|
2096
2764
|
}
|
|
2097
2765
|
for (const p of parts) {
|
|
2098
2766
|
if (p.type === "tool") {
|
|
2099
|
-
const
|
|
2100
|
-
byTool[
|
|
2101
|
-
if (
|
|
2767
|
+
const t2 = String(p.tool ?? "?");
|
|
2768
|
+
byTool[t2] = (byTool[t2] ?? 0) + 1;
|
|
2769
|
+
if (t2 === "skill") {
|
|
2102
2770
|
const meta = p.state?.metadata;
|
|
2103
2771
|
const rootMeta = p.metadata;
|
|
2104
2772
|
skillParts.push(`state.metadata=${JSON.stringify(meta)} | root.metadata=${JSON.stringify(rootMeta)} | state.title="${p.state?.title}" | state.output[:80]="${String(p.state?.output ?? "").slice(0, 80)}"`);
|
|
@@ -2167,7 +2835,7 @@ var tui = async (api) => {
|
|
|
2167
2835
|
return true;
|
|
2168
2836
|
});
|
|
2169
2837
|
if (unique.length > 0) {
|
|
2170
|
-
const
|
|
2838
|
+
const t = createT(() => langCode());
|
|
2171
2839
|
const currentSid = signals.overrideSessionId() ?? api.kv.get(`${KV_PREFIX}.session`, "");
|
|
2172
2840
|
const options = unique.map((c, i) => ({
|
|
2173
2841
|
title: `${i + 1}. ${c.title}`,
|
|
@@ -2175,7 +2843,7 @@ var tui = async (api) => {
|
|
|
2175
2843
|
description: c.description
|
|
2176
2844
|
}));
|
|
2177
2845
|
const backValue = "__main__";
|
|
2178
|
-
const backTitle = `\u2500 ${
|
|
2846
|
+
const backTitle = `\u2500 ${t("backToMainTitle")}`;
|
|
2179
2847
|
options.unshift({
|
|
2180
2848
|
title: backTitle,
|
|
2181
2849
|
value: backValue,
|
|
@@ -2188,7 +2856,9 @@ var tui = async (api) => {
|
|
|
2188
2856
|
});
|
|
2189
2857
|
const currentIdx = currentSid ? options.findIndex((o) => o.value === currentSid) : -1;
|
|
2190
2858
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
2191
|
-
title
|
|
2859
|
+
get title() {
|
|
2860
|
+
return t("subSelectTitle");
|
|
2861
|
+
},
|
|
2192
2862
|
options,
|
|
2193
2863
|
get current() {
|
|
2194
2864
|
return currentIdx >= 0 ? options[currentIdx].value : void 0;
|
|
@@ -2198,28 +2868,30 @@ var tui = async (api) => {
|
|
|
2198
2868
|
signals.setOverrideSessionId(void 0);
|
|
2199
2869
|
api.kv.set(`${KV_PREFIX}.session`, "");
|
|
2200
2870
|
api.ui.toast({
|
|
2201
|
-
message:
|
|
2871
|
+
message: t("backToMain")
|
|
2202
2872
|
});
|
|
2203
2873
|
} else {
|
|
2204
2874
|
signals.setOverrideSessionId(opt.value);
|
|
2205
2875
|
api.kv.set(`${KV_PREFIX}.session`, opt.value);
|
|
2206
2876
|
api.ui.toast({
|
|
2207
|
-
message: (
|
|
2877
|
+
message: t("subAgentSwitched", {
|
|
2878
|
+
s: opt.value.slice(0, 24) + "\u2026"
|
|
2879
|
+
})
|
|
2208
2880
|
});
|
|
2209
2881
|
}
|
|
2210
2882
|
dialog?.clear();
|
|
2211
2883
|
}
|
|
2212
2884
|
}));
|
|
2213
2885
|
} else {
|
|
2214
|
-
const
|
|
2886
|
+
const t = createT(() => langCode());
|
|
2215
2887
|
dialog?.replace(() => _$createComponent(api.ui.DialogPrompt, {
|
|
2216
2888
|
get title() {
|
|
2217
|
-
return signals.overrideSessionId() ?
|
|
2889
|
+
return _$memo(() => !!signals.overrideSessionId())() ? t("subSwitchTitle") : t("subViewTitle");
|
|
2218
2890
|
},
|
|
2219
2891
|
description: () => (() => {
|
|
2220
|
-
var _el$
|
|
2221
|
-
_$insert(_el$
|
|
2222
|
-
return _el$
|
|
2892
|
+
var _el$114 = _$createElement("text");
|
|
2893
|
+
_$insert(_el$114, () => t("subNoFound"));
|
|
2894
|
+
return _el$114;
|
|
2223
2895
|
})(),
|
|
2224
2896
|
placeholder: "ses_...",
|
|
2225
2897
|
get value() {
|
|
@@ -2231,7 +2903,9 @@ var tui = async (api) => {
|
|
|
2231
2903
|
signals.setOverrideSessionId(sid);
|
|
2232
2904
|
api.kv.set(`${KV_PREFIX}.session`, sid);
|
|
2233
2905
|
api.ui.toast({
|
|
2234
|
-
message: (
|
|
2906
|
+
message: t("subAgentSwitched", {
|
|
2907
|
+
s: sid.slice(0, 24) + "\u2026"
|
|
2908
|
+
})
|
|
2235
2909
|
});
|
|
2236
2910
|
}
|
|
2237
2911
|
dialog?.clear();
|
|
@@ -2248,10 +2922,11 @@ var tui = async (api) => {
|
|
|
2248
2922
|
name: "cache-session-back"
|
|
2249
2923
|
},
|
|
2250
2924
|
onSelect: (dialog) => {
|
|
2925
|
+
const t = createT(() => langCode());
|
|
2251
2926
|
signals.setOverrideSessionId(void 0);
|
|
2252
2927
|
api.kv.set(`${KV_PREFIX}.session`, "");
|
|
2253
2928
|
api.ui.toast({
|
|
2254
|
-
message:
|
|
2929
|
+
message: t("backToMain")
|
|
2255
2930
|
});
|
|
2256
2931
|
dialog?.clear();
|
|
2257
2932
|
}
|