opencode-visual-cache 1.4.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 +37 -4
- package/README_EN.md +37 -4
- package/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/balance-providers.d.ts +27 -0
- package/dist/balance-providers.js +131 -0
- package/dist/i18n.d.ts +102 -0
- package/dist/i18n.js +368 -0
- package/dist/index.js +585 -283
- package/dist/tui.js +1350 -453
- package/package.json +1 -1
- package/src/_version.ts +1 -1
- package/src/balance-providers.ts +153 -0
- package/src/i18n.ts +380 -0
- package/src/index.tsx +687 -343
package/dist/tui.js
CHANGED
|
@@ -13,53 +13,111 @@ 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
|
-
// src/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return 1;
|
|
35
|
-
}
|
|
36
|
-
function visualWidth(s) {
|
|
37
|
-
let w = 0;
|
|
38
|
-
for (const c of s) w += charColumns(c);
|
|
39
|
-
return w;
|
|
40
|
-
}
|
|
41
|
-
function truncateVisual(s, maxCols) {
|
|
42
|
-
if (visualWidth(s) <= maxCols) return s;
|
|
43
|
-
let result = "", w = 0;
|
|
44
|
-
for (const c of s) {
|
|
45
|
-
const cw = charColumns(c);
|
|
46
|
-
if (w + cw > maxCols - 1) {
|
|
47
|
-
result += "\u2026";
|
|
48
|
-
break;
|
|
18
|
+
// src/balance-providers.ts
|
|
19
|
+
var BalanceError = class extends Error {
|
|
20
|
+
};
|
|
21
|
+
var siliconflowProvider = {
|
|
22
|
+
id: "siliconflow",
|
|
23
|
+
name: "SiliconFlow",
|
|
24
|
+
keyPlaceholder: "sk-...",
|
|
25
|
+
async fetchBalance(apiKey, signal) {
|
|
26
|
+
const res = await fetch("https://api.siliconflow.cn/v1/user/info", {
|
|
27
|
+
headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
|
|
28
|
+
signal
|
|
29
|
+
});
|
|
30
|
+
if (!res.ok) {
|
|
31
|
+
if (res.status === 401) throw new BalanceError("401");
|
|
32
|
+
if (res.status === 403) throw new BalanceError("403");
|
|
33
|
+
throw new BalanceError(String(res.status));
|
|
49
34
|
}
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
const json = await res.json();
|
|
36
|
+
const total = json.data?.totalBalance ?? json.data?.balance;
|
|
37
|
+
if (typeof total === "undefined" || total === null) throw new BalanceError("EMPTY");
|
|
38
|
+
return [{ currency: "CNY", total: String(total) }];
|
|
52
39
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
40
|
+
};
|
|
41
|
+
var deepseekProvider = {
|
|
42
|
+
id: "deepseek",
|
|
43
|
+
name: "DeepSeek",
|
|
44
|
+
keyPlaceholder: "sk-...",
|
|
45
|
+
async fetchBalance(apiKey, signal) {
|
|
46
|
+
const res = await fetch("https://api.deepseek.com/user/balance", {
|
|
47
|
+
headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
|
|
48
|
+
signal
|
|
49
|
+
});
|
|
50
|
+
if (!res.ok) {
|
|
51
|
+
if (res.status === 401) throw new BalanceError("401");
|
|
52
|
+
if (res.status === 402 || res.status === 403) throw new BalanceError("403");
|
|
53
|
+
throw new BalanceError(String(res.status));
|
|
54
|
+
}
|
|
55
|
+
const json = await res.json();
|
|
56
|
+
const infos = json.balance_infos ?? [];
|
|
57
|
+
if (infos.length === 0) throw new BalanceError("EMPTY");
|
|
58
|
+
return infos.map((info) => ({
|
|
59
|
+
currency: info.currency ?? "CNY",
|
|
60
|
+
total: info.total_balance ?? "0"
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
var openrouterProvider = {
|
|
65
|
+
id: "openrouter",
|
|
66
|
+
name: "OpenRouter",
|
|
67
|
+
keyPlaceholder: "sk-or-...",
|
|
68
|
+
async fetchBalance(apiKey, signal) {
|
|
69
|
+
const res = await fetch("https://openrouter.ai/api/v1/credits", {
|
|
70
|
+
headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
|
|
71
|
+
signal
|
|
72
|
+
});
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
if (res.status === 401 || res.status === 403) throw new BalanceError("403");
|
|
75
|
+
throw new BalanceError(String(res.status));
|
|
76
|
+
}
|
|
77
|
+
const json = await res.json();
|
|
78
|
+
const credits = json.data?.total_credits;
|
|
79
|
+
const usage = json.data?.total_usage;
|
|
80
|
+
if (typeof credits !== "number" || typeof usage !== "number") throw new BalanceError("EMPTY");
|
|
81
|
+
return [{ currency: "USD", total: (credits - usage).toFixed(2) }];
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var moonshotProvider = {
|
|
85
|
+
id: "moonshot",
|
|
86
|
+
name: "Moonshot",
|
|
87
|
+
keyPlaceholder: "sk-...",
|
|
88
|
+
async fetchBalance(apiKey, signal) {
|
|
89
|
+
const res = await fetch("https://api.moonshot.cn/v1/users/me/balance", {
|
|
90
|
+
headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
|
|
91
|
+
signal
|
|
92
|
+
});
|
|
93
|
+
if (!res.ok) {
|
|
94
|
+
if (res.status === 401) throw new BalanceError("401");
|
|
95
|
+
if (res.status === 403) throw new BalanceError("403");
|
|
96
|
+
throw new BalanceError(String(res.status));
|
|
97
|
+
}
|
|
98
|
+
const json = await res.json();
|
|
99
|
+
const balance = json.data?.available_balance;
|
|
100
|
+
if (typeof balance === "undefined" || balance === null) throw new BalanceError("EMPTY");
|
|
101
|
+
return [{ currency: "CNY", total: String(balance) }];
|
|
61
102
|
}
|
|
62
|
-
}
|
|
103
|
+
};
|
|
104
|
+
var balanceProviders = [deepseekProvider, siliconflowProvider, openrouterProvider, moonshotProvider];
|
|
105
|
+
function getBalanceProvider(id) {
|
|
106
|
+
return balanceProviders.find((p) => p.id === id) ?? balanceProviders[0] ?? deepseekProvider;
|
|
107
|
+
}
|
|
108
|
+
function matchBalanceProvider(providerId) {
|
|
109
|
+
const id = providerId.toLowerCase();
|
|
110
|
+
const exact = balanceProviders.find((p) => p.id.toLowerCase() === id);
|
|
111
|
+
if (exact) return exact;
|
|
112
|
+
return balanceProviders.find((p) => id.startsWith(p.id.toLowerCase()));
|
|
113
|
+
}
|
|
114
|
+
function maskKey(k) {
|
|
115
|
+
if (!k) return "";
|
|
116
|
+
if (k.length <= 10) return k.slice(0, 5) + "*".repeat(Math.max(3, k.length - 5));
|
|
117
|
+
return k.slice(0, 5) + "*".repeat(Math.max(3, k.length - 10)) + k.slice(-5);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/i18n.ts
|
|
63
121
|
var ZH_T = {
|
|
64
122
|
title: "\u7F13\u5B58\u7EDF\u8BA1",
|
|
65
123
|
hit: "\u547D\u4E2D\u7387",
|
|
@@ -91,13 +149,55 @@ var ZH_T = {
|
|
|
91
149
|
secModel: "\u6A21\u578B",
|
|
92
150
|
secSkills: "\u5DF2\u52A0\u8F7D\u6280\u80FD",
|
|
93
151
|
balTotal: "\u603B\u4F59\u989D:",
|
|
94
|
-
balNoKey: "\u672A\u914D\u7F6E API Key",
|
|
152
|
+
balNoKey: "\u672A\u914D\u7F6E {p} API Key",
|
|
95
153
|
balLoading: "\u67E5\u8BE2\u4E2D...",
|
|
96
154
|
balError: "\u67E5\u8BE2\u5931\u8D25",
|
|
97
155
|
balErr401: "API Key \u65E0\u6548",
|
|
98
156
|
balErr403: "\u4F59\u989D\u67E5\u8BE2\u88AB\u62D2\u7EDD",
|
|
99
157
|
balErrEmpty: "\u672A\u83B7\u53D6\u5230\u4F59\u989D\u6570\u636E",
|
|
100
|
-
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"
|
|
101
201
|
};
|
|
102
202
|
var EN_T = {
|
|
103
203
|
title: "Token Cache",
|
|
@@ -130,14 +230,290 @@ var EN_T = {
|
|
|
130
230
|
secModel: "Model",
|
|
131
231
|
secSkills: "Loaded Skills",
|
|
132
232
|
balTotal: "Total:",
|
|
133
|
-
balNoKey: "
|
|
233
|
+
balNoKey: "{p} API Key not set",
|
|
134
234
|
balLoading: "Fetching...",
|
|
135
235
|
balError: "Fetch failed",
|
|
136
236
|
balErr401: "Invalid API Key",
|
|
137
237
|
balErr403: "Balance request rejected",
|
|
138
238
|
balErrEmpty: "No balance data",
|
|
139
|
-
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"
|
|
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"
|
|
140
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();
|
|
141
517
|
function rgb(raw) {
|
|
142
518
|
if (typeof raw === "string" && raw.startsWith("#")) {
|
|
143
519
|
const h = raw.slice(1);
|
|
@@ -249,37 +625,56 @@ function estimateTokens(text) {
|
|
|
249
625
|
return Math.max(1, Math.ceil(ascii / asciiPerToken + cjk / 1));
|
|
250
626
|
}
|
|
251
627
|
var BALANCE_POLL_MS = 5 * 60 * 1e3;
|
|
252
|
-
async function fetchDeepSeekBalance(apiKey, signal) {
|
|
253
|
-
const res = await fetch("https://api.deepseek.com/user/balance", {
|
|
254
|
-
headers: {
|
|
255
|
-
Authorization: `Bearer ${apiKey}`,
|
|
256
|
-
Accept: "application/json"
|
|
257
|
-
},
|
|
258
|
-
signal
|
|
259
|
-
});
|
|
260
|
-
if (!res.ok) {
|
|
261
|
-
if (res.status === 401) throw new Error("401");
|
|
262
|
-
if (res.status === 402 || res.status === 403) throw new Error("403");
|
|
263
|
-
throw new Error(String(res.status));
|
|
264
|
-
}
|
|
265
|
-
const json = await res.json();
|
|
266
|
-
const infos = json.balance_infos ?? [];
|
|
267
|
-
if (infos.length === 0) throw new Error("EMPTY");
|
|
268
|
-
return infos.map((info) => ({
|
|
269
|
-
currency: info.currency ?? "CNY",
|
|
270
|
-
total: info.total_balance ?? "0"
|
|
271
|
-
}));
|
|
272
|
-
}
|
|
273
628
|
function convertBalance(target, targetRate, amount, from) {
|
|
274
629
|
if (from === target) return amount;
|
|
275
630
|
const fromRate = DEFAULT_RATES[from] ?? 1;
|
|
276
631
|
const usd = from === "USD" ? amount : amount / fromRate;
|
|
277
632
|
return target === "USD" ? usd : usd * targetRate;
|
|
278
633
|
}
|
|
634
|
+
function findOpencodeKey(api, provider) {
|
|
635
|
+
try {
|
|
636
|
+
const provs = api.state.provider;
|
|
637
|
+
const id = provider.id.toLowerCase();
|
|
638
|
+
const hit = provs.find((p) => p.id.toLowerCase() === id) ?? provs.find((p) => p.id.toLowerCase().startsWith(id));
|
|
639
|
+
if (!hit) return "";
|
|
640
|
+
const k = typeof hit.key === "string" ? hit.key : "";
|
|
641
|
+
if (k) return k;
|
|
642
|
+
return typeof hit.options?.apiKey === "string" ? hit.options.apiKey : "";
|
|
643
|
+
} catch {
|
|
644
|
+
return "";
|
|
645
|
+
}
|
|
646
|
+
}
|
|
279
647
|
function balanceSymbol(currency) {
|
|
280
648
|
const sym = CURRENCIES[currency];
|
|
281
649
|
return sym ?? currency + " ";
|
|
282
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
|
+
}
|
|
283
678
|
var CURRENCIES = {
|
|
284
679
|
USD: "$",
|
|
285
680
|
CNY: "\xA5",
|
|
@@ -317,8 +712,7 @@ function TokenCachePanel(props) {
|
|
|
317
712
|
setCurrencySymbol,
|
|
318
713
|
exchangeRate,
|
|
319
714
|
setExchangeRate,
|
|
320
|
-
|
|
321
|
-
setLangZH,
|
|
715
|
+
langCode,
|
|
322
716
|
sectionDetail,
|
|
323
717
|
setSectionDetail,
|
|
324
718
|
sectionModel,
|
|
@@ -330,12 +724,19 @@ function TokenCachePanel(props) {
|
|
|
330
724
|
sectionBalance,
|
|
331
725
|
setSectionBalance,
|
|
332
726
|
balanceRefresh,
|
|
727
|
+
balanceProviderId,
|
|
728
|
+
setBalanceProviderId,
|
|
729
|
+
autoBalance,
|
|
730
|
+
setAutoBalance,
|
|
731
|
+
balanceUnsupported,
|
|
732
|
+
setBalanceUnsupported,
|
|
733
|
+
balanceState,
|
|
333
734
|
balanceCurrency,
|
|
334
735
|
setBalanceCurrency,
|
|
335
736
|
borderVisible,
|
|
336
737
|
setBorderVisible
|
|
337
738
|
} = props.signals;
|
|
338
|
-
const t =
|
|
739
|
+
const t = createT(() => langCode());
|
|
339
740
|
const [lastDist, setLastDist] = createSignal({
|
|
340
741
|
system: 0,
|
|
341
742
|
user: 0,
|
|
@@ -382,69 +783,37 @@ function TokenCachePanel(props) {
|
|
|
382
783
|
hasSkills: false
|
|
383
784
|
});
|
|
384
785
|
const [refreshTick, setRefreshTick] = createSignal(0);
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
lastFetch: 0,
|
|
398
|
-
error: void 0,
|
|
399
|
-
key: void 0
|
|
400
|
-
});
|
|
401
|
-
return;
|
|
786
|
+
const providerName = createMemo(() => getBalanceProvider(balanceProviderId()).name);
|
|
787
|
+
createEffect(() => {
|
|
788
|
+
if (!autoBalance()) return;
|
|
789
|
+
const sid = props.signals.overrideSessionId() ?? props.sessionId;
|
|
790
|
+
const msgs = props.api.state.session.messages(sid);
|
|
791
|
+
let pid = "";
|
|
792
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
793
|
+
const m = msgs[i];
|
|
794
|
+
if (m.role === "assistant" && m.providerID) {
|
|
795
|
+
pid = m.providerID;
|
|
796
|
+
break;
|
|
797
|
+
}
|
|
402
798
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
const data2 = await fetchDeepSeekBalance(key, controller.signal);
|
|
421
|
-
clearTimeout(timer);
|
|
422
|
-
if (seq !== balanceSeq) return;
|
|
423
|
-
setBalanceState({
|
|
424
|
-
status: "ok",
|
|
425
|
-
data: data2,
|
|
426
|
-
lastFetch: Date.now(),
|
|
427
|
-
error: void 0,
|
|
428
|
-
key
|
|
429
|
-
});
|
|
430
|
-
} catch (err) {
|
|
431
|
-
clearTimeout(timer);
|
|
432
|
-
if (seq !== balanceSeq) return;
|
|
433
|
-
const code = timedOut ? "TIMEOUT" : err instanceof Error ? err.message : "";
|
|
434
|
-
setBalanceState({
|
|
435
|
-
status: "error",
|
|
436
|
-
data: null,
|
|
437
|
-
lastFetch: 0,
|
|
438
|
-
error: code,
|
|
439
|
-
key
|
|
440
|
-
});
|
|
799
|
+
if (!pid) {
|
|
800
|
+
try {
|
|
801
|
+
const session = props.api.state.session.get(sid);
|
|
802
|
+
pid = session?.model?.providerID ?? "";
|
|
803
|
+
} catch {
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
if (!pid) return;
|
|
807
|
+
const hit = matchBalanceProvider(pid);
|
|
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);
|
|
441
816
|
}
|
|
442
|
-
};
|
|
443
|
-
createEffect(() => {
|
|
444
|
-
void balanceRefresh();
|
|
445
|
-
untrack(() => {
|
|
446
|
-
void pollBalance();
|
|
447
|
-
});
|
|
448
817
|
});
|
|
449
818
|
let lastMainSid = props.sessionId;
|
|
450
819
|
createEffect(() => {
|
|
@@ -476,18 +845,18 @@ function TokenCachePanel(props) {
|
|
|
476
845
|
let prevMsgHitRate = -1, lastMsgHitRate = -1;
|
|
477
846
|
for (const msg of msgs) {
|
|
478
847
|
if (msg.role !== "assistant") continue;
|
|
479
|
-
const
|
|
480
|
-
if (!
|
|
481
|
-
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);
|
|
482
851
|
if (mit > 0) {
|
|
483
852
|
prevMsgHitRate = lastMsgHitRate;
|
|
484
853
|
lastMsgHitRate = mrt / mit * 100;
|
|
485
854
|
}
|
|
486
855
|
if (fallbackTokens) {
|
|
487
|
-
input += num(
|
|
488
|
-
read += num(
|
|
489
|
-
write += num(
|
|
490
|
-
output += num(
|
|
856
|
+
input += num(tok.input);
|
|
857
|
+
read += num(tok.cache?.read);
|
|
858
|
+
write += num(tok.cache?.write);
|
|
859
|
+
output += num(tok.output);
|
|
491
860
|
}
|
|
492
861
|
if (fallbackCost) {
|
|
493
862
|
cost += num(msg.cost);
|
|
@@ -509,10 +878,10 @@ function TokenCachePanel(props) {
|
|
|
509
878
|
break;
|
|
510
879
|
}
|
|
511
880
|
const hitRate = lastMsgHitRate >= 0 ? lastMsgHitRate : 0;
|
|
512
|
-
const freshTotal = input + read, sessionHitRate = freshTotal > 0 ? read / freshTotal * 100 : 0;
|
|
881
|
+
const freshTotal = input + read + write, sessionHitRate = freshTotal > 0 ? read / freshTotal * 100 : 0;
|
|
513
882
|
const model = mid.split("/").pop() ?? mid, hasPricing = inputRate > 0 || cacheReadRate > 0 || cacheWriteRate > 0;
|
|
514
883
|
const hasTrendData = prevMsgHitRate >= 0 && lastMsgHitRate >= 0;
|
|
515
|
-
const trend = hasTrendData ? lastMsgHitRate - prevMsgHitRate : 0,
|
|
884
|
+
const trend = hasTrendData ? lastMsgHitRate - prevMsgHitRate : 0, providerName2 = pid || "";
|
|
516
885
|
const distData = untrack(() => {
|
|
517
886
|
let dist = {
|
|
518
887
|
system: 0,
|
|
@@ -602,13 +971,13 @@ function TokenCachePanel(props) {
|
|
|
602
971
|
}
|
|
603
972
|
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
604
973
|
if (msgs[i].role !== "assistant") continue;
|
|
605
|
-
const
|
|
606
|
-
if (
|
|
974
|
+
const tok = msgs[i].tokens;
|
|
975
|
+
if (tok && ((tok.input ?? 0) > 0 || (tok.cache?.read ?? 0) > 0 || (tok.cache?.write ?? 0) > 0)) {
|
|
607
976
|
lastAssMsg = msgs[i];
|
|
608
977
|
break;
|
|
609
978
|
}
|
|
610
979
|
}
|
|
611
|
-
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);
|
|
612
981
|
dist.apiOutput = num(lastAssMsg?.tokens?.output);
|
|
613
982
|
hasDistData = dist.system + dist.user + dist.agent + dist.toolCall + dist.toolResult > 0 || dist.apiOutput > 0 || dist.apiInput > 0;
|
|
614
983
|
} catch {
|
|
@@ -637,7 +1006,7 @@ function TokenCachePanel(props) {
|
|
|
637
1006
|
hasData: read > 0 || write > 0 || input > 0 || output > 0 || cost > 0,
|
|
638
1007
|
trend,
|
|
639
1008
|
hasTrendData,
|
|
640
|
-
providerName,
|
|
1009
|
+
providerName: providerName2,
|
|
641
1010
|
sessionHitRate,
|
|
642
1011
|
dist: distData.finalDist,
|
|
643
1012
|
hasDistData: distData.finalHasDist,
|
|
@@ -689,6 +1058,20 @@ function TokenCachePanel(props) {
|
|
|
689
1058
|
if (typeof rate === "number" && rate > 0) setExchangeRate(rate);
|
|
690
1059
|
const balCur = props.api.kv.get(`${KV_PREFIX}.balance_currency`);
|
|
691
1060
|
if (typeof balCur === "string") setBalanceCurrency(balCur);
|
|
1061
|
+
const savedProvider = props.api.kv.get(`${KV_PREFIX}.balance.provider`);
|
|
1062
|
+
if (typeof savedProvider === "string" && balanceProviders.some((p) => p.id === savedProvider)) {
|
|
1063
|
+
setBalanceProviderId(savedProvider);
|
|
1064
|
+
setBalanceUnsupported(false);
|
|
1065
|
+
}
|
|
1066
|
+
const savedAuto = props.api.kv.get(`${KV_PREFIX}.balance.auto`);
|
|
1067
|
+
if (typeof savedAuto === "boolean") setAutoBalance(savedAuto);
|
|
1068
|
+
const legacyKey = props.api.kv.get(`${KV_PREFIX}.ds_key`, "");
|
|
1069
|
+
if (legacyKey) {
|
|
1070
|
+
const dsKey = props.api.kv.get(`${KV_PREFIX}.balance.deepseek.key`, "");
|
|
1071
|
+
if (!dsKey) props.api.kv.set(`${KV_PREFIX}.balance.deepseek.key`, legacyKey);
|
|
1072
|
+
props.api.kv.set(`${KV_PREFIX}.ds_key`, "");
|
|
1073
|
+
}
|
|
1074
|
+
props.signals.setBalanceRefresh(props.signals.balanceRefresh() + 1);
|
|
692
1075
|
setSectionDetail(Boolean(props.api.kv.get(`${KV_PREFIX}.section.detail`, true)));
|
|
693
1076
|
setSectionModel(Boolean(props.api.kv.get(`${KV_PREFIX}.section.model`, true)));
|
|
694
1077
|
setSectionDist(Boolean(props.api.kv.get(`${KV_PREFIX}.section.dist`, true)));
|
|
@@ -696,10 +1079,6 @@ function TokenCachePanel(props) {
|
|
|
696
1079
|
setSectionBalance(Boolean(props.api.kv.get(`${KV_PREFIX}.section.balance`, true)));
|
|
697
1080
|
const bv = props.api.kv.get(`${KV_PREFIX}.border`, true);
|
|
698
1081
|
setBorderVisible(bv !== false);
|
|
699
|
-
const savedLang = props.api.kv.get(`${KV_PREFIX}.lang`);
|
|
700
|
-
if (savedLang === "zh" || savedLang === "en") {
|
|
701
|
-
setLangZH(savedLang === "zh");
|
|
702
|
-
}
|
|
703
1082
|
const cachedDist = props.api.kv.get(`${KV_PREFIX}.dist_snapshot`);
|
|
704
1083
|
if (cachedDist) {
|
|
705
1084
|
setLastDist(cachedDist);
|
|
@@ -746,10 +1125,8 @@ function TokenCachePanel(props) {
|
|
|
746
1125
|
setRefreshTick((v) => v + 1);
|
|
747
1126
|
});
|
|
748
1127
|
setRefreshTick((v) => v + 1);
|
|
749
|
-
const balanceTimer = setInterval(pollBalance, BALANCE_POLL_MS);
|
|
750
1128
|
onCleanup(() => {
|
|
751
1129
|
clearTimeout(partTimer);
|
|
752
|
-
clearInterval(balanceTimer);
|
|
753
1130
|
unsubPart();
|
|
754
1131
|
unsubMsg();
|
|
755
1132
|
unsubSession();
|
|
@@ -777,11 +1154,12 @@ function TokenCachePanel(props) {
|
|
|
777
1154
|
const gutter = createMemo(() => borderVisible() ? 6 : 0);
|
|
778
1155
|
const sep = createMemo(() => "\u2500".repeat(Math.max(1, panelWidth() - gutter())));
|
|
779
1156
|
function trendLabel(t2) {
|
|
780
|
-
|
|
1157
|
+
if (Math.abs(t2) < 0.05) return "-";
|
|
1158
|
+
return (t2 > 0 ? "\u2191" : "\u2193") + Math.abs(t2).toFixed(1) + "%";
|
|
781
1159
|
}
|
|
782
1160
|
const barW = createMemo(() => {
|
|
783
1161
|
const trendSpace = data().hasTrendData ? LABEL_GAP + visualWidth(trendLabel(data().trend)) : 0;
|
|
784
|
-
const overhead = visualWidth(t(
|
|
1162
|
+
const overhead = visualWidth(t("hit")) + LABEL_GAP + BAR_BRACKETS + BAR_GAP + PCT_FIXED_WIDTH + trendSpace + gutter();
|
|
785
1163
|
return Math.max(3, panelWidth() - overhead);
|
|
786
1164
|
});
|
|
787
1165
|
const bar = createMemo(() => progressBar(data().hitRate, barW()));
|
|
@@ -835,7 +1213,7 @@ function TokenCachePanel(props) {
|
|
|
835
1213
|
}));
|
|
836
1214
|
_$insert(_el$3, () => open() ? "\u25BC " : "\u25B6 ");
|
|
837
1215
|
_$insertNode(_el$4, _el$5);
|
|
838
|
-
_$insert(_el$5, () => t(
|
|
1216
|
+
_$insert(_el$5, () => t("title"));
|
|
839
1217
|
_$insert(_el$4, _$createComponent(Show, {
|
|
840
1218
|
get when() {
|
|
841
1219
|
return open();
|
|
@@ -862,13 +1240,13 @@ function TokenCachePanel(props) {
|
|
|
862
1240
|
get children() {
|
|
863
1241
|
return [(() => {
|
|
864
1242
|
var _el$8 = _$createElement("span");
|
|
865
|
-
_$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)))));
|
|
866
1244
|
return _el$8;
|
|
867
1245
|
})(), (() => {
|
|
868
1246
|
var _el$9 = _$createElement("span"), _el$0 = _$createTextNode(` `);
|
|
869
1247
|
_$insertNode(_el$9, _el$0);
|
|
870
1248
|
_$insert(_el$9, pct, _el$0);
|
|
871
|
-
_$insert(_el$9, () => t()
|
|
1249
|
+
_$insert(_el$9, () => t("hitFolded"), null);
|
|
872
1250
|
_$effect((_$p) => _$setProp(_el$9, "style", {
|
|
873
1251
|
fg: hitColor()
|
|
874
1252
|
}, _$p));
|
|
@@ -878,7 +1256,7 @@ function TokenCachePanel(props) {
|
|
|
878
1256
|
_$insertNode(_el$1, _el$10);
|
|
879
1257
|
_$insert(_el$1, () => trendLabel(data().trend), null);
|
|
880
1258
|
_$effect((_$p) => _$setProp(_el$1, "style", {
|
|
881
|
-
fg: data().trend
|
|
1259
|
+
fg: Math.abs(data().trend) >= 0.05 ? data().trend > 0 ? pal().success : pal().error : pal().text
|
|
882
1260
|
}, _$p));
|
|
883
1261
|
return _el$1;
|
|
884
1262
|
})()];
|
|
@@ -890,13 +1268,13 @@ function TokenCachePanel(props) {
|
|
|
890
1268
|
get children() {
|
|
891
1269
|
return [(() => {
|
|
892
1270
|
var _el$11 = _$createElement("span");
|
|
893
|
-
_$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")))));
|
|
894
1272
|
return _el$11;
|
|
895
1273
|
})(), (() => {
|
|
896
1274
|
var _el$12 = _$createElement("span"), _el$13 = _$createTextNode(` `);
|
|
897
1275
|
_$insertNode(_el$12, _el$13);
|
|
898
1276
|
_$insert(_el$12, pct, _el$13);
|
|
899
|
-
_$insert(_el$12, () => t()
|
|
1277
|
+
_$insert(_el$12, () => t("hitFolded"), null);
|
|
900
1278
|
_$effect((_$p) => _$setProp(_el$12, "style", {
|
|
901
1279
|
fg: hitColor()
|
|
902
1280
|
}, _$p));
|
|
@@ -917,28 +1295,28 @@ function TokenCachePanel(props) {
|
|
|
917
1295
|
},
|
|
918
1296
|
get children() {
|
|
919
1297
|
return (() => {
|
|
920
|
-
const prefix = " \u21B3 " + (
|
|
1298
|
+
const prefix = " \u21B3 " + t("subPrefix");
|
|
921
1299
|
const maxSidW = Math.max(6, panelWidth() - visualWidth(prefix));
|
|
922
1300
|
return (() => {
|
|
923
|
-
var _el$
|
|
924
|
-
_$insertNode(_el$
|
|
925
|
-
_$insertNode(_el$
|
|
926
|
-
_$insert(_el$
|
|
927
|
-
_$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));
|
|
928
1306
|
_$effect((_p$) => {
|
|
929
|
-
var _v$
|
|
1307
|
+
var _v$17 = {
|
|
930
1308
|
fg: pal().muted
|
|
931
|
-
}, _v$
|
|
1309
|
+
}, _v$18 = {
|
|
932
1310
|
fg: pal().text
|
|
933
1311
|
};
|
|
934
|
-
_v$
|
|
935
|
-
_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));
|
|
936
1314
|
return _p$;
|
|
937
1315
|
}, {
|
|
938
1316
|
e: void 0,
|
|
939
1317
|
t: void 0
|
|
940
1318
|
});
|
|
941
|
-
return _el$
|
|
1319
|
+
return _el$69;
|
|
942
1320
|
})();
|
|
943
1321
|
})();
|
|
944
1322
|
}
|
|
@@ -948,30 +1326,30 @@ function TokenCachePanel(props) {
|
|
|
948
1326
|
},
|
|
949
1327
|
get fallback() {
|
|
950
1328
|
return [(() => {
|
|
951
|
-
var _el$
|
|
952
|
-
_$insert(_el$
|
|
953
|
-
_$effect((_$p) => _$setProp(_el$
|
|
954
|
-
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;
|
|
955
1333
|
})(), (() => {
|
|
956
|
-
var _el$
|
|
957
|
-
_$insertNode(_el$
|
|
958
|
-
_$insertNode(_el$
|
|
959
|
-
_$insertNode(_el$
|
|
960
|
-
_$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"));
|
|
961
1339
|
_$effect((_p$) => {
|
|
962
|
-
var _v$
|
|
1340
|
+
var _v$19 = {
|
|
963
1341
|
fg: pal().muted
|
|
964
|
-
}, _v$
|
|
1342
|
+
}, _v$20 = {
|
|
965
1343
|
fg: pal().muted
|
|
966
1344
|
};
|
|
967
|
-
_v$
|
|
968
|
-
_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));
|
|
969
1347
|
return _p$;
|
|
970
1348
|
}, {
|
|
971
1349
|
e: void 0,
|
|
972
1350
|
t: void 0
|
|
973
1351
|
});
|
|
974
|
-
return _el$
|
|
1352
|
+
return _el$73;
|
|
975
1353
|
})()];
|
|
976
1354
|
},
|
|
977
1355
|
get children() {
|
|
@@ -986,7 +1364,7 @@ function TokenCachePanel(props) {
|
|
|
986
1364
|
_$insertNode(_el$15, _el$18);
|
|
987
1365
|
_$insertNode(_el$15, _el$21);
|
|
988
1366
|
_$insertNode(_el$16, _el$17);
|
|
989
|
-
_$insert(_el$16, () => t()
|
|
1367
|
+
_$insert(_el$16, () => t("hit"), _el$17);
|
|
990
1368
|
_$insertNode(_el$18, _el$19);
|
|
991
1369
|
_$insertNode(_el$18, _el$20);
|
|
992
1370
|
_$insert(_el$18, bar, _el$20);
|
|
@@ -1000,7 +1378,7 @@ function TokenCachePanel(props) {
|
|
|
1000
1378
|
_$insertNode(_el$22, _el$23);
|
|
1001
1379
|
_$insert(_el$22, () => trendLabel(data().trend), null);
|
|
1002
1380
|
_$effect((_$p) => _$setProp(_el$22, "style", {
|
|
1003
|
-
fg: data().trend
|
|
1381
|
+
fg: Math.abs(data().trend) >= 0.05 ? data().trend > 0 ? pal().success : pal().error : pal().text
|
|
1004
1382
|
}, _$p));
|
|
1005
1383
|
return _el$22;
|
|
1006
1384
|
}
|
|
@@ -1025,7 +1403,7 @@ function TokenCachePanel(props) {
|
|
|
1025
1403
|
return _el$15;
|
|
1026
1404
|
})(), (() => {
|
|
1027
1405
|
var _el$24 = _$createElement("text");
|
|
1028
|
-
_$insert(_el$24, () => justify(t()
|
|
1406
|
+
_$insert(_el$24, () => justify(t("totalHit"), (Math.floor(data().sessionHitRate * 10) / 10).toFixed(1) + "%"));
|
|
1029
1407
|
_$effect((_$p) => _$setProp(_el$24, "fg", pal().muted, _$p));
|
|
1030
1408
|
return _el$24;
|
|
1031
1409
|
})(), _$createComponent(Show, {
|
|
@@ -1045,8 +1423,8 @@ function TokenCachePanel(props) {
|
|
|
1045
1423
|
}));
|
|
1046
1424
|
_$insert(_el$26, () => detailOpen() ? "\u25BC " : "\u25B6 ");
|
|
1047
1425
|
_$insertNode(_el$27, _el$28);
|
|
1048
|
-
_$insert(_el$28, () => t(
|
|
1049
|
-
_$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"))));
|
|
1050
1428
|
_$effect((_p$) => {
|
|
1051
1429
|
var _v$4 = {
|
|
1052
1430
|
fg: pal().muted
|
|
@@ -1076,7 +1454,7 @@ function TokenCachePanel(props) {
|
|
|
1076
1454
|
},
|
|
1077
1455
|
get children() {
|
|
1078
1456
|
var _el$30 = _$createElement("text");
|
|
1079
|
-
_$insert(_el$30, () => justify(t()
|
|
1457
|
+
_$insert(_el$30, () => justify(t("read"), fmt(data().read), t("tok")));
|
|
1080
1458
|
_$effect((_$p) => _$setProp(_el$30, "fg", pal().muted, _$p));
|
|
1081
1459
|
return _el$30;
|
|
1082
1460
|
}
|
|
@@ -1086,18 +1464,18 @@ function TokenCachePanel(props) {
|
|
|
1086
1464
|
},
|
|
1087
1465
|
get children() {
|
|
1088
1466
|
var _el$31 = _$createElement("text");
|
|
1089
|
-
_$insert(_el$31, () => justify(t()
|
|
1467
|
+
_$insert(_el$31, () => justify(t("write"), fmt(data().write), t("tok")));
|
|
1090
1468
|
_$effect((_$p) => _$setProp(_el$31, "fg", pal().muted, _$p));
|
|
1091
1469
|
return _el$31;
|
|
1092
1470
|
}
|
|
1093
1471
|
}), (() => {
|
|
1094
1472
|
var _el$32 = _$createElement("text");
|
|
1095
|
-
_$insert(_el$32, () => justify(t()
|
|
1473
|
+
_$insert(_el$32, () => justify(t("miss"), fmt(data().freshInput + data().write), t("tok")));
|
|
1096
1474
|
_$effect((_$p) => _$setProp(_el$32, "fg", pal().muted, _$p));
|
|
1097
1475
|
return _el$32;
|
|
1098
1476
|
})(), (() => {
|
|
1099
1477
|
var _el$33 = _$createElement("text");
|
|
1100
|
-
_$insert(_el$33, () => justify(t()
|
|
1478
|
+
_$insert(_el$33, () => justify(t("out"), fmt(data().output), t("tok")));
|
|
1101
1479
|
_$effect((_$p) => _$setProp(_el$33, "fg", pal().muted, _$p));
|
|
1102
1480
|
return _el$33;
|
|
1103
1481
|
})(), _$createComponent(Show, {
|
|
@@ -1109,8 +1487,8 @@ function TokenCachePanel(props) {
|
|
|
1109
1487
|
_$insertNode(_el$34, _el$35);
|
|
1110
1488
|
_$insertNode(_el$34, _el$36);
|
|
1111
1489
|
_$insertNode(_el$34, _el$37);
|
|
1112
|
-
_$insert(_el$35, () => t(
|
|
1113
|
-
_$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())))));
|
|
1114
1492
|
_$insertNode(_el$37, _el$38);
|
|
1115
1493
|
_$insert(_el$37, () => fmtCost(data().saved, currencySymbol(), exchangeRate()), null);
|
|
1116
1494
|
_$effect((_p$) => {
|
|
@@ -1138,37 +1516,37 @@ function TokenCachePanel(props) {
|
|
|
1138
1516
|
},
|
|
1139
1517
|
get children() {
|
|
1140
1518
|
return [_$memo(() => (() => {
|
|
1141
|
-
var _el$
|
|
1142
|
-
_$insertNode(_el$
|
|
1143
|
-
_$insertNode(_el$
|
|
1144
|
-
_$insertNode(_el$
|
|
1145
|
-
_$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) => {
|
|
1146
1524
|
const n = !o;
|
|
1147
1525
|
persistFold("model", n);
|
|
1148
1526
|
return n;
|
|
1149
1527
|
}));
|
|
1150
|
-
_$insert(_el$
|
|
1151
|
-
_$insertNode(_el$
|
|
1152
|
-
_$insert(_el$
|
|
1153
|
-
_$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"))));
|
|
1154
1532
|
_$effect((_p$) => {
|
|
1155
|
-
var _v$
|
|
1533
|
+
var _v$21 = {
|
|
1156
1534
|
fg: pal().muted
|
|
1157
|
-
}, _v$
|
|
1535
|
+
}, _v$22 = {
|
|
1158
1536
|
fg: pal().primary
|
|
1159
|
-
}, _v$
|
|
1537
|
+
}, _v$23 = {
|
|
1160
1538
|
fg: pal().muted
|
|
1161
1539
|
};
|
|
1162
|
-
_v$
|
|
1163
|
-
_v$
|
|
1164
|
-
_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));
|
|
1165
1543
|
return _p$;
|
|
1166
1544
|
}, {
|
|
1167
1545
|
e: void 0,
|
|
1168
1546
|
t: void 0,
|
|
1169
1547
|
a: void 0
|
|
1170
1548
|
});
|
|
1171
|
-
return _el$
|
|
1549
|
+
return _el$77;
|
|
1172
1550
|
})()), _$createComponent(Show, {
|
|
1173
1551
|
get when() {
|
|
1174
1552
|
return modelOpen();
|
|
@@ -1176,7 +1554,7 @@ function TokenCachePanel(props) {
|
|
|
1176
1554
|
get children() {
|
|
1177
1555
|
return [(() => {
|
|
1178
1556
|
var _el$39 = _$createElement("text");
|
|
1179
|
-
_$insert(_el$39, () => justify(t()
|
|
1557
|
+
_$insert(_el$39, () => justify(t("cost"), fmtCost(data().cost, currencySymbol(), exchangeRate())));
|
|
1180
1558
|
_$effect((_$p) => _$setProp(_el$39, "fg", pal().text, _$p));
|
|
1181
1559
|
return _el$39;
|
|
1182
1560
|
})(), _$createComponent(Show, {
|
|
@@ -1185,13 +1563,13 @@ function TokenCachePanel(props) {
|
|
|
1185
1563
|
},
|
|
1186
1564
|
get children() {
|
|
1187
1565
|
var _el$40 = _$createElement("text");
|
|
1188
|
-
_$insert(_el$40, () => justify(t()
|
|
1566
|
+
_$insert(_el$40, () => justify(t("provider"), data().providerName));
|
|
1189
1567
|
_$effect((_$p) => _$setProp(_el$40, "fg", pal().muted, _$p));
|
|
1190
1568
|
return _el$40;
|
|
1191
1569
|
}
|
|
1192
1570
|
}), (() => {
|
|
1193
1571
|
var _el$41 = _$createElement("text");
|
|
1194
|
-
_$insert(_el$41, () => justify(t()
|
|
1572
|
+
_$insert(_el$41, () => justify(t("model"), data().model));
|
|
1195
1573
|
_$effect((_$p) => _$setProp(_el$41, "fg", pal().muted, _$p));
|
|
1196
1574
|
return _el$41;
|
|
1197
1575
|
})(), _$createComponent(Show, {
|
|
@@ -1201,7 +1579,7 @@ function TokenCachePanel(props) {
|
|
|
1201
1579
|
get children() {
|
|
1202
1580
|
return [(() => {
|
|
1203
1581
|
var _el$42 = _$createElement("text");
|
|
1204
|
-
_$insert(_el$42, () => justify(t()
|
|
1582
|
+
_$insert(_el$42, () => justify(t("rate"), currencySymbol() + (data().inputRate * exchangeRate()).toFixed(2) + "/M " + t("inputRate")));
|
|
1205
1583
|
_$effect((_$p) => _$setProp(_el$42, "fg", pal().muted, _$p));
|
|
1206
1584
|
return _el$42;
|
|
1207
1585
|
})(), _$createComponent(Show, {
|
|
@@ -1210,7 +1588,7 @@ function TokenCachePanel(props) {
|
|
|
1210
1588
|
},
|
|
1211
1589
|
get children() {
|
|
1212
1590
|
var _el$43 = _$createElement("text");
|
|
1213
|
-
_$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")));
|
|
1214
1592
|
_$effect((_$p) => _$setProp(_el$43, "fg", pal().muted, _$p));
|
|
1215
1593
|
return _el$43;
|
|
1216
1594
|
}
|
|
@@ -1220,7 +1598,7 @@ function TokenCachePanel(props) {
|
|
|
1220
1598
|
},
|
|
1221
1599
|
get children() {
|
|
1222
1600
|
var _el$44 = _$createElement("text");
|
|
1223
|
-
_$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")));
|
|
1224
1602
|
_$effect((_$p) => _$setProp(_el$44, "fg", pal().muted, _$p));
|
|
1225
1603
|
return _el$44;
|
|
1226
1604
|
}
|
|
@@ -1241,37 +1619,37 @@ function TokenCachePanel(props) {
|
|
|
1241
1619
|
},
|
|
1242
1620
|
get children() {
|
|
1243
1621
|
return [_$memo(() => (() => {
|
|
1244
|
-
var _el$
|
|
1245
|
-
_$insertNode(_el$
|
|
1246
|
-
_$insertNode(_el$
|
|
1247
|
-
_$insertNode(_el$
|
|
1248
|
-
_$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) => {
|
|
1249
1627
|
const n = !o;
|
|
1250
1628
|
persistFold("dist", n);
|
|
1251
1629
|
return n;
|
|
1252
1630
|
}));
|
|
1253
|
-
_$insert(_el$
|
|
1254
|
-
_$insertNode(_el$
|
|
1255
|
-
_$insert(_el$
|
|
1256
|
-
_$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"))));
|
|
1257
1635
|
_$effect((_p$) => {
|
|
1258
|
-
var _v$
|
|
1636
|
+
var _v$24 = {
|
|
1259
1637
|
fg: pal().muted
|
|
1260
|
-
}, _v$
|
|
1638
|
+
}, _v$25 = {
|
|
1261
1639
|
fg: pal().primary
|
|
1262
|
-
}, _v$
|
|
1640
|
+
}, _v$26 = {
|
|
1263
1641
|
fg: pal().muted
|
|
1264
1642
|
};
|
|
1265
|
-
_v$
|
|
1266
|
-
_v$
|
|
1267
|
-
_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));
|
|
1268
1646
|
return _p$;
|
|
1269
1647
|
}, {
|
|
1270
1648
|
e: void 0,
|
|
1271
1649
|
t: void 0,
|
|
1272
1650
|
a: void 0
|
|
1273
1651
|
});
|
|
1274
|
-
return _el$
|
|
1652
|
+
return _el$82;
|
|
1275
1653
|
})()), _$createComponent(Show, {
|
|
1276
1654
|
get when() {
|
|
1277
1655
|
return distOpen();
|
|
@@ -1283,7 +1661,7 @@ function TokenCachePanel(props) {
|
|
|
1283
1661
|
},
|
|
1284
1662
|
get children() {
|
|
1285
1663
|
var _el$45 = _$createElement("text");
|
|
1286
|
-
_$insert(_el$45, () => justify(t()
|
|
1664
|
+
_$insert(_el$45, () => justify(t("distSys"), fmt(data().dist.system), t("tok")));
|
|
1287
1665
|
_$effect((_$p) => _$setProp(_el$45, "fg", pal().muted, _$p));
|
|
1288
1666
|
return _el$45;
|
|
1289
1667
|
}
|
|
@@ -1293,7 +1671,7 @@ function TokenCachePanel(props) {
|
|
|
1293
1671
|
},
|
|
1294
1672
|
get children() {
|
|
1295
1673
|
var _el$46 = _$createElement("text");
|
|
1296
|
-
_$insert(_el$46, () => justify(t()
|
|
1674
|
+
_$insert(_el$46, () => justify(t("distUser"), fmt(data().dist.user), t("tok")));
|
|
1297
1675
|
_$effect((_$p) => _$setProp(_el$46, "fg", pal().muted, _$p));
|
|
1298
1676
|
return _el$46;
|
|
1299
1677
|
}
|
|
@@ -1303,7 +1681,7 @@ function TokenCachePanel(props) {
|
|
|
1303
1681
|
},
|
|
1304
1682
|
get children() {
|
|
1305
1683
|
var _el$47 = _$createElement("text");
|
|
1306
|
-
_$insert(_el$47, () => justify(t()
|
|
1684
|
+
_$insert(_el$47, () => justify(t("distAgent"), fmt(data().dist.agent), t("tok")));
|
|
1307
1685
|
_$effect((_$p) => _$setProp(_el$47, "fg", pal().muted, _$p));
|
|
1308
1686
|
return _el$47;
|
|
1309
1687
|
}
|
|
@@ -1313,7 +1691,7 @@ function TokenCachePanel(props) {
|
|
|
1313
1691
|
},
|
|
1314
1692
|
get children() {
|
|
1315
1693
|
var _el$48 = _$createElement("text");
|
|
1316
|
-
_$insert(_el$48, () => justify(t()
|
|
1694
|
+
_$insert(_el$48, () => justify(t("distTool"), fmt(data().dist.toolCall), t("tok")));
|
|
1317
1695
|
_$effect((_$p) => _$setProp(_el$48, "fg", pal().muted, _$p));
|
|
1318
1696
|
return _el$48;
|
|
1319
1697
|
}
|
|
@@ -1323,13 +1701,13 @@ function TokenCachePanel(props) {
|
|
|
1323
1701
|
},
|
|
1324
1702
|
get children() {
|
|
1325
1703
|
var _el$49 = _$createElement("text");
|
|
1326
|
-
_$insert(_el$49, () => justify(t()
|
|
1704
|
+
_$insert(_el$49, () => justify(t("distRes"), fmt(data().dist.toolResult), t("tok")));
|
|
1327
1705
|
_$effect((_$p) => _$setProp(_el$49, "fg", pal().muted, _$p));
|
|
1328
1706
|
return _el$49;
|
|
1329
1707
|
}
|
|
1330
1708
|
}), (() => {
|
|
1331
1709
|
var _el$50 = _$createElement("text");
|
|
1332
|
-
_$insert(_el$50, () => justify(t()
|
|
1710
|
+
_$insert(_el$50, () => justify(t("distTotal"), fmt(data().dist.apiInput), t("tok")));
|
|
1333
1711
|
_$effect((_$p) => _$setProp(_el$50, "fg", pal().text, _$p));
|
|
1334
1712
|
return _el$50;
|
|
1335
1713
|
})()];
|
|
@@ -1349,37 +1727,37 @@ function TokenCachePanel(props) {
|
|
|
1349
1727
|
},
|
|
1350
1728
|
get children() {
|
|
1351
1729
|
return [_$memo(() => (() => {
|
|
1352
|
-
var _el$
|
|
1353
|
-
_$insertNode(_el$
|
|
1354
|
-
_$insertNode(_el$
|
|
1355
|
-
_$insertNode(_el$
|
|
1356
|
-
_$insertNode(_el$
|
|
1357
|
-
_$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) => {
|
|
1358
1736
|
const n = !o;
|
|
1359
1737
|
persistFold("skills", n);
|
|
1360
1738
|
return n;
|
|
1361
1739
|
}));
|
|
1362
|
-
_$insert(_el$
|
|
1363
|
-
_$insertNode(_el$
|
|
1364
|
-
_$insert(_el$
|
|
1365
|
-
_$insertNode(_el$
|
|
1366
|
-
_$insertNode(_el$
|
|
1367
|
-
_$insert(_el$
|
|
1368
|
-
_$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})`)));
|
|
1369
1747
|
_$effect((_p$) => {
|
|
1370
|
-
var _v$
|
|
1748
|
+
var _v$27 = {
|
|
1371
1749
|
fg: pal().muted
|
|
1372
|
-
}, _v$
|
|
1750
|
+
}, _v$28 = {
|
|
1373
1751
|
fg: pal().primary
|
|
1374
|
-
}, _v$
|
|
1752
|
+
}, _v$29 = {
|
|
1375
1753
|
fg: pal().muted
|
|
1376
|
-
}, _v$
|
|
1754
|
+
}, _v$30 = {
|
|
1377
1755
|
fg: pal().muted
|
|
1378
1756
|
};
|
|
1379
|
-
_v$
|
|
1380
|
-
_v$
|
|
1381
|
-
_v$
|
|
1382
|
-
_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));
|
|
1383
1761
|
return _p$;
|
|
1384
1762
|
}, {
|
|
1385
1763
|
e: void 0,
|
|
@@ -1387,21 +1765,21 @@ function TokenCachePanel(props) {
|
|
|
1387
1765
|
a: void 0,
|
|
1388
1766
|
o: void 0
|
|
1389
1767
|
});
|
|
1390
|
-
return _el$
|
|
1768
|
+
return _el$87;
|
|
1391
1769
|
})()), _$createComponent(Show, {
|
|
1392
1770
|
get when() {
|
|
1393
1771
|
return skillsOpen();
|
|
1394
1772
|
},
|
|
1395
1773
|
get children() {
|
|
1396
1774
|
return data().skills.map((sk) => {
|
|
1397
|
-
const rightW = visualWidth(fmt(sk.tokens)) + UNIT_GAP + visualWidth(t(
|
|
1775
|
+
const rightW = visualWidth(fmt(sk.tokens)) + UNIT_GAP + visualWidth(t("tok"));
|
|
1398
1776
|
const maxLabel = Math.max(4, panelWidth() - gutter() - rightW - 1);
|
|
1399
1777
|
const label = truncateVisual(sk.name, maxLabel);
|
|
1400
1778
|
return (() => {
|
|
1401
|
-
var _el$
|
|
1402
|
-
_$insert(_el$
|
|
1403
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1404
|
-
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;
|
|
1405
1783
|
})();
|
|
1406
1784
|
});
|
|
1407
1785
|
}
|
|
@@ -1421,14 +1799,14 @@ function TokenCachePanel(props) {
|
|
|
1421
1799
|
return _el$51;
|
|
1422
1800
|
})(), _$createComponent(Show, {
|
|
1423
1801
|
get when() {
|
|
1424
|
-
return
|
|
1802
|
+
return balanceUnsupported();
|
|
1425
1803
|
},
|
|
1426
1804
|
get children() {
|
|
1427
1805
|
var _el$52 = _$createElement("text"), _el$53 = _$createElement("span"), _el$55 = _$createElement("span");
|
|
1428
1806
|
_$insertNode(_el$52, _el$53);
|
|
1429
1807
|
_$insertNode(_el$52, _el$55);
|
|
1430
1808
|
_$insertNode(_el$53, _$createTextNode(`> `));
|
|
1431
|
-
_$insert(_el$55, () => t()
|
|
1809
|
+
_$insert(_el$55, () => t("balUnsupported"));
|
|
1432
1810
|
_$effect((_p$) => {
|
|
1433
1811
|
var _v$9 = pal().muted, _v$0 = {
|
|
1434
1812
|
fg: pal().muted
|
|
@@ -1444,87 +1822,98 @@ function TokenCachePanel(props) {
|
|
|
1444
1822
|
}
|
|
1445
1823
|
}), _$createComponent(Show, {
|
|
1446
1824
|
get when() {
|
|
1447
|
-
return
|
|
1825
|
+
return !balanceUnsupported();
|
|
1448
1826
|
},
|
|
1449
1827
|
get children() {
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
_$
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
}
|
|
1498
|
-
}), _$createComponent(Show, {
|
|
1499
|
-
get when() {
|
|
1500
|
-
return _$memo(() => balanceState().status === "ok")() && balanceState().data;
|
|
1501
|
-
},
|
|
1502
|
-
get children() {
|
|
1503
|
-
return (() => {
|
|
1504
|
-
const list = balanceState().data;
|
|
1505
|
-
const pref = balanceCurrency();
|
|
1506
|
-
const native = pref ? list.find((x) => x.currency === pref) : void 0;
|
|
1507
|
-
if (native) {
|
|
1508
|
-
return (() => {
|
|
1509
|
-
var _el$91 = _$createElement("text");
|
|
1510
|
-
_$insert(_el$91, () => justify(t().balTotal, balanceSymbol(native.currency) + native.total));
|
|
1511
|
-
_$effect((_$p) => _$setProp(_el$91, "fg", pal().text, _$p));
|
|
1512
|
-
return _el$91;
|
|
1513
|
-
})();
|
|
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;
|
|
1514
1875
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
_$
|
|
1524
|
-
_$
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
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;
|
|
1915
|
+
}
|
|
1916
|
+
})];
|
|
1528
1917
|
}
|
|
1529
1918
|
})];
|
|
1530
1919
|
}
|
|
@@ -1534,13 +1923,13 @@ function TokenCachePanel(props) {
|
|
|
1534
1923
|
}
|
|
1535
1924
|
}), null);
|
|
1536
1925
|
_$effect((_p$) => {
|
|
1537
|
-
var _v$
|
|
1926
|
+
var _v$15 = {
|
|
1538
1927
|
fg: pal().muted
|
|
1539
|
-
}, _v$
|
|
1928
|
+
}, _v$16 = {
|
|
1540
1929
|
fg: pal().primary
|
|
1541
1930
|
};
|
|
1542
|
-
_v$
|
|
1543
|
-
_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));
|
|
1544
1933
|
return _p$;
|
|
1545
1934
|
}, {
|
|
1546
1935
|
e: void 0,
|
|
@@ -1549,6 +1938,233 @@ function TokenCachePanel(props) {
|
|
|
1549
1938
|
return _el$;
|
|
1550
1939
|
})();
|
|
1551
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
|
+
}
|
|
1552
2168
|
function createSidebarSlot(api, signals) {
|
|
1553
2169
|
let lastSlotSid = "";
|
|
1554
2170
|
return {
|
|
@@ -1584,18 +2200,28 @@ var tui = async (api) => {
|
|
|
1584
2200
|
const [sectionDist, setSectionDist] = createSignal(true);
|
|
1585
2201
|
const [sectionSkills, setSectionSkills] = createSignal(true);
|
|
1586
2202
|
const [sectionBalance, setSectionBalance] = createSignal(true);
|
|
2203
|
+
const [sectionBottom, setSectionBottom] = createSignal(true);
|
|
1587
2204
|
const [balanceRefresh, setBalanceRefresh] = createSignal(0);
|
|
2205
|
+
const [balanceProviderId, setBalanceProviderId] = createSignal("deepseek");
|
|
2206
|
+
const [autoBalance, setAutoBalance] = createSignal(true);
|
|
2207
|
+
const [balanceUnsupported, setBalanceUnsupported] = createSignal(false);
|
|
1588
2208
|
const [balanceCurrency, setBalanceCurrency] = createSignal("");
|
|
1589
2209
|
const [borderVisible, setBorderVisible] = createSignal(true);
|
|
1590
|
-
const [
|
|
2210
|
+
const [langCode, setLangCode] = createSignal(INIT_LANG);
|
|
1591
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;
|
|
1592
2218
|
const signals = {
|
|
1593
2219
|
currencySymbol,
|
|
1594
2220
|
setCurrencySymbol,
|
|
1595
2221
|
exchangeRate,
|
|
1596
2222
|
setExchangeRate,
|
|
1597
|
-
|
|
1598
|
-
|
|
2223
|
+
langCode,
|
|
2224
|
+
setLangCode,
|
|
1599
2225
|
sectionDetail,
|
|
1600
2226
|
setSectionDetail,
|
|
1601
2227
|
sectionModel,
|
|
@@ -1606,8 +2232,17 @@ var tui = async (api) => {
|
|
|
1606
2232
|
setSectionSkills,
|
|
1607
2233
|
sectionBalance,
|
|
1608
2234
|
setSectionBalance,
|
|
2235
|
+
sectionBottom,
|
|
2236
|
+
setSectionBottom,
|
|
1609
2237
|
balanceRefresh,
|
|
1610
2238
|
setBalanceRefresh,
|
|
2239
|
+
balanceProviderId,
|
|
2240
|
+
setBalanceProviderId,
|
|
2241
|
+
autoBalance,
|
|
2242
|
+
setAutoBalance,
|
|
2243
|
+
balanceUnsupported,
|
|
2244
|
+
setBalanceUnsupported,
|
|
2245
|
+
balanceState,
|
|
1611
2246
|
balanceCurrency,
|
|
1612
2247
|
setBalanceCurrency,
|
|
1613
2248
|
borderVisible,
|
|
@@ -1616,7 +2251,182 @@ var tui = async (api) => {
|
|
|
1616
2251
|
setOverrideSessionId
|
|
1617
2252
|
};
|
|
1618
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
|
+
});
|
|
1619
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));
|
|
2378
|
+
const providerOptionTitle = (p, current) => {
|
|
2379
|
+
const t = createT(() => langCode());
|
|
2380
|
+
const hasManual = !!api.kv.get(`${KV_PREFIX}.balance.${p.id}.key`, "");
|
|
2381
|
+
const hasAuto = !hasManual && !!findOpencodeKey(api, p);
|
|
2382
|
+
const mark = hasManual ? t("keyUser") : hasAuto ? t("keyOpenCode") : t("keyNotSet");
|
|
2383
|
+
return p.name + mark + (current && p.id === current ? " *" : "");
|
|
2384
|
+
};
|
|
2385
|
+
const promptBalanceKey = (dialog, provider) => {
|
|
2386
|
+
const t = createT(() => langCode());
|
|
2387
|
+
const current = api.kv.get(`${KV_PREFIX}.balance.${provider.id}.key`, "");
|
|
2388
|
+
const masked = maskKey(current);
|
|
2389
|
+
dialog?.replace(() => _$createComponent(api.ui.DialogPrompt, {
|
|
2390
|
+
get title() {
|
|
2391
|
+
return provider.name;
|
|
2392
|
+
},
|
|
2393
|
+
description: () => (() => {
|
|
2394
|
+
var _el$111 = _$createElement("text");
|
|
2395
|
+
_$insert(_el$111, () => t("balKeyPrompt", {
|
|
2396
|
+
p: provider.name
|
|
2397
|
+
}));
|
|
2398
|
+
return _el$111;
|
|
2399
|
+
})(),
|
|
2400
|
+
get placeholder() {
|
|
2401
|
+
return provider.keyPlaceholder ?? "sk-...";
|
|
2402
|
+
},
|
|
2403
|
+
value: masked,
|
|
2404
|
+
onConfirm: (val) => {
|
|
2405
|
+
const input = val.trim();
|
|
2406
|
+
let key;
|
|
2407
|
+
if (input === "") {
|
|
2408
|
+
key = "";
|
|
2409
|
+
} else if (input.includes("*")) {
|
|
2410
|
+
key = current;
|
|
2411
|
+
} else {
|
|
2412
|
+
key = input;
|
|
2413
|
+
}
|
|
2414
|
+
api.kv.set(`${KV_PREFIX}.balance.${provider.id}.key`, key);
|
|
2415
|
+
setBalanceRefresh((v) => v + 1);
|
|
2416
|
+
if (key) {
|
|
2417
|
+
api.ui.toast({
|
|
2418
|
+
message: t("keySaved")
|
|
2419
|
+
});
|
|
2420
|
+
} else {
|
|
2421
|
+
api.ui.toast({
|
|
2422
|
+
message: t("keyCleared")
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
dialog?.clear();
|
|
2426
|
+
},
|
|
2427
|
+
onCancel: () => dialog?.clear()
|
|
2428
|
+
}));
|
|
2429
|
+
};
|
|
1620
2430
|
api.command?.register(() => [{
|
|
1621
2431
|
title: "Cache: Set Currency",
|
|
1622
2432
|
value: "cache.currency",
|
|
@@ -1634,6 +2444,7 @@ var tui = async (api) => {
|
|
|
1634
2444
|
}));
|
|
1635
2445
|
},
|
|
1636
2446
|
onSelect: (opt) => {
|
|
2447
|
+
const t = createT(() => langCode());
|
|
1637
2448
|
const sym = CURRENCIES[opt.value] ?? "$";
|
|
1638
2449
|
const defRate = DEFAULT_RATES[opt.value] ?? 1;
|
|
1639
2450
|
api.kv.set(`${KV_PREFIX}.currency`, sym);
|
|
@@ -1643,7 +2454,11 @@ var tui = async (api) => {
|
|
|
1643
2454
|
signals.setCurrencySymbol(sym);
|
|
1644
2455
|
signals.setExchangeRate(defRate);
|
|
1645
2456
|
api.ui.toast({
|
|
1646
|
-
message:
|
|
2457
|
+
message: t("currencySet", {
|
|
2458
|
+
v: opt.value,
|
|
2459
|
+
s: sym,
|
|
2460
|
+
r: defRate
|
|
2461
|
+
})
|
|
1647
2462
|
});
|
|
1648
2463
|
dialog?.clear();
|
|
1649
2464
|
}
|
|
@@ -1660,21 +2475,24 @@ var tui = async (api) => {
|
|
|
1660
2475
|
dialog?.replace(() => _$createComponent(api.ui.DialogPrompt, {
|
|
1661
2476
|
title: "Exchange Rate",
|
|
1662
2477
|
description: () => (() => {
|
|
1663
|
-
var _el$
|
|
1664
|
-
_$insertNode(_el$
|
|
1665
|
-
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;
|
|
1666
2481
|
})(),
|
|
1667
2482
|
placeholder: "1.0",
|
|
1668
2483
|
get value() {
|
|
1669
2484
|
return String(api.kv.get(`${KV_PREFIX}.rate`, 1));
|
|
1670
2485
|
},
|
|
1671
2486
|
onConfirm: (val) => {
|
|
2487
|
+
const t = createT(() => langCode());
|
|
1672
2488
|
const n = parseFloat(val);
|
|
1673
2489
|
if (n > 0) {
|
|
1674
2490
|
api.kv.set(`${KV_PREFIX}.rate`, n);
|
|
1675
2491
|
signals.setExchangeRate(n);
|
|
1676
2492
|
api.ui.toast({
|
|
1677
|
-
message:
|
|
2493
|
+
message: t("rateSet", {
|
|
2494
|
+
r: n
|
|
2495
|
+
})
|
|
1678
2496
|
});
|
|
1679
2497
|
}
|
|
1680
2498
|
dialog?.clear();
|
|
@@ -1689,40 +2507,59 @@ var tui = async (api) => {
|
|
|
1689
2507
|
name: "cache-section"
|
|
1690
2508
|
},
|
|
1691
2509
|
onSelect: (dialog) => {
|
|
2510
|
+
const t = createT(() => langCode());
|
|
1692
2511
|
const detailOn = Boolean(api.kv.get(`${KV_PREFIX}.section.detail`, true));
|
|
1693
2512
|
const modelOn = Boolean(api.kv.get(`${KV_PREFIX}.section.model`, true));
|
|
1694
2513
|
const distOn = Boolean(api.kv.get(`${KV_PREFIX}.section.dist`, true));
|
|
1695
2514
|
const skillsOn = Boolean(api.kv.get(`${KV_PREFIX}.section.skills`, true));
|
|
1696
2515
|
const balanceOn = Boolean(api.kv.get(`${KV_PREFIX}.section.balance`, true));
|
|
2516
|
+
const bottomOn = Boolean(api.kv.get(`${KV_PREFIX}.section.bottom`, true));
|
|
1697
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"}]`;
|
|
1698
2528
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
1699
|
-
title
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
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
|
+
},
|
|
1719
2556
|
onSelect: (opt) => {
|
|
1720
2557
|
if (opt.value === "border") {
|
|
1721
2558
|
const cur = Boolean(api.kv.get(`${KV_PREFIX}.border`, true));
|
|
1722
2559
|
api.kv.set(`${KV_PREFIX}.border`, !cur);
|
|
1723
2560
|
signals.setBorderVisible(!cur);
|
|
1724
2561
|
api.ui.toast({
|
|
1725
|
-
message:
|
|
2562
|
+
message: !cur ? t("borderShown") : t("borderHidden")
|
|
1726
2563
|
});
|
|
1727
2564
|
} else {
|
|
1728
2565
|
const key = `${KV_PREFIX}.section.${opt.value}`;
|
|
@@ -1733,8 +2570,12 @@ var tui = async (api) => {
|
|
|
1733
2570
|
if (opt.value === "dist") signals.setSectionDist(!cur);
|
|
1734
2571
|
if (opt.value === "skills") signals.setSectionSkills(!cur);
|
|
1735
2572
|
if (opt.value === "balance") signals.setSectionBalance(!cur);
|
|
2573
|
+
if (opt.value === "bottom") signals.setSectionBottom(!cur);
|
|
2574
|
+
const name = labels[opt.value] ?? opt.value;
|
|
1736
2575
|
api.ui.toast({
|
|
1737
|
-
message:
|
|
2576
|
+
message: t(!cur ? "sectionShown" : "sectionHidden", {
|
|
2577
|
+
s: name
|
|
2578
|
+
})
|
|
1738
2579
|
});
|
|
1739
2580
|
}
|
|
1740
2581
|
dialog?.clear();
|
|
@@ -1749,6 +2590,7 @@ var tui = async (api) => {
|
|
|
1749
2590
|
name: "cache-config"
|
|
1750
2591
|
},
|
|
1751
2592
|
onSelect: (dialog) => {
|
|
2593
|
+
const t = createT(() => langCode());
|
|
1752
2594
|
const sym = api.kv.get(`${KV_PREFIX}.currency`) ?? "$";
|
|
1753
2595
|
const rate = api.kv.get(`${KV_PREFIX}.rate`) ?? 1;
|
|
1754
2596
|
const detail = Boolean(api.kv.get(`${KV_PREFIX}.section.detail`, true));
|
|
@@ -1756,9 +2598,20 @@ var tui = async (api) => {
|
|
|
1756
2598
|
const dist = Boolean(api.kv.get(`${KV_PREFIX}.section.dist`, true));
|
|
1757
2599
|
const skills = Boolean(api.kv.get(`${KV_PREFIX}.section.skills`, true));
|
|
1758
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";
|
|
1759
2603
|
api.ui.toast({
|
|
1760
|
-
title: "
|
|
1761
|
-
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
|
+
}),
|
|
1762
2615
|
duration: 8e3
|
|
1763
2616
|
});
|
|
1764
2617
|
dialog?.clear();
|
|
@@ -1771,78 +2624,114 @@ var tui = async (api) => {
|
|
|
1771
2624
|
name: "cache-lang"
|
|
1772
2625
|
},
|
|
1773
2626
|
onSelect: (dialog) => {
|
|
1774
|
-
const
|
|
2627
|
+
const t = createT(() => langCode());
|
|
2628
|
+
const cur = langCode();
|
|
1775
2629
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
1776
|
-
title
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
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
|
+
},
|
|
1784
2639
|
onSelect: (opt) => {
|
|
1785
|
-
const
|
|
1786
|
-
api.kv.set(`${KV_PREFIX}.lang`,
|
|
1787
|
-
|
|
2640
|
+
const code = opt.value;
|
|
2641
|
+
api.kv.set(`${KV_PREFIX}.lang`, code);
|
|
2642
|
+
setLangCode(code);
|
|
1788
2643
|
api.ui.toast({
|
|
1789
|
-
message:
|
|
2644
|
+
message: t("langSwitched")
|
|
1790
2645
|
});
|
|
1791
2646
|
dialog?.clear();
|
|
1792
2647
|
}
|
|
1793
2648
|
}));
|
|
1794
2649
|
}
|
|
1795
2650
|
}, {
|
|
1796
|
-
title: "Cache:
|
|
1797
|
-
value: "cache.balance
|
|
1798
|
-
description: "
|
|
2651
|
+
title: "Cache: Switch Balance Provider",
|
|
2652
|
+
value: "cache.balance",
|
|
2653
|
+
description: "\u5207\u6362\u4F59\u989D\u63D0\u4F9B\u5546 / \u81EA\u52A8\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u63D0\u4F9B\u5546 | Switch balance provider / auto-switch session provider",
|
|
1799
2654
|
slash: {
|
|
1800
|
-
name: "cache-balance
|
|
2655
|
+
name: "cache-balance"
|
|
1801
2656
|
},
|
|
1802
2657
|
onSelect: (dialog) => {
|
|
1803
|
-
const
|
|
1804
|
-
const current =
|
|
1805
|
-
const
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
}
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
if (input === "") {
|
|
1826
|
-
key = "";
|
|
1827
|
-
} else if (input.includes("*")) {
|
|
1828
|
-
key = current;
|
|
1829
|
-
} else {
|
|
1830
|
-
key = input;
|
|
1831
|
-
}
|
|
1832
|
-
api.kv.set(`${KV_PREFIX}.ds_key`, key);
|
|
1833
|
-
setBalanceRefresh((v) => v + 1);
|
|
1834
|
-
if (key) {
|
|
2658
|
+
const t = createT(() => langCode());
|
|
2659
|
+
const current = signals.balanceProviderId();
|
|
2660
|
+
const auto = signals.autoBalance();
|
|
2661
|
+
const autoLabel = `${t("autoSwitchOpt")} [${auto ? "ON" : "OFF"}]`;
|
|
2662
|
+
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
2663
|
+
get title() {
|
|
2664
|
+
return t("balProvTitle");
|
|
2665
|
+
},
|
|
2666
|
+
get options() {
|
|
2667
|
+
return [{
|
|
2668
|
+
title: autoLabel,
|
|
2669
|
+
value: "__auto__"
|
|
2670
|
+
}, ...balanceProviders.map((p) => ({
|
|
2671
|
+
title: providerOptionTitle(p, current),
|
|
2672
|
+
value: p.id
|
|
2673
|
+
}))];
|
|
2674
|
+
},
|
|
2675
|
+
onSelect: (opt) => {
|
|
2676
|
+
if (opt.value === "__auto__") {
|
|
2677
|
+
const next = !auto;
|
|
2678
|
+
api.kv.set(`${KV_PREFIX}.balance.auto`, next);
|
|
2679
|
+
signals.setAutoBalance(next);
|
|
1835
2680
|
api.ui.toast({
|
|
1836
|
-
message:
|
|
2681
|
+
message: next ? t("autoSwitchOn") : t("autoSwitchOff")
|
|
1837
2682
|
});
|
|
2683
|
+
dialog?.clear();
|
|
1838
2684
|
} else {
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
});
|
|
2685
|
+
const provider = getBalanceProvider(opt.value);
|
|
2686
|
+
api.kv.set(`${KV_PREFIX}.balance.provider`, provider.id);
|
|
2687
|
+
api.kv.set(`${KV_PREFIX}.balance.auto`, false);
|
|
2688
|
+
signals.setBalanceProviderId(provider.id);
|
|
2689
|
+
signals.setAutoBalance(false);
|
|
2690
|
+
signals.setBalanceUnsupported(false);
|
|
2691
|
+
signals.setBalanceRefresh(signals.balanceRefresh() + 1);
|
|
2692
|
+
const hasKey = !!api.kv.get(`${KV_PREFIX}.balance.${provider.id}.key`, "");
|
|
2693
|
+
if (!hasKey) {
|
|
2694
|
+
promptBalanceKey(dialog, provider);
|
|
2695
|
+
} else {
|
|
2696
|
+
api.ui.toast({
|
|
2697
|
+
message: t("providerManual", {
|
|
2698
|
+
p: provider.name
|
|
2699
|
+
})
|
|
2700
|
+
});
|
|
2701
|
+
dialog?.clear();
|
|
2702
|
+
}
|
|
1842
2703
|
}
|
|
1843
|
-
|
|
2704
|
+
}
|
|
2705
|
+
}));
|
|
2706
|
+
}
|
|
2707
|
+
}, {
|
|
2708
|
+
title: "Cache: Set Balance API Key",
|
|
2709
|
+
value: "cache.balance.key",
|
|
2710
|
+
description: "Select a provider and set its API key for balance display",
|
|
2711
|
+
slash: {
|
|
2712
|
+
name: "cache-balance-key"
|
|
2713
|
+
},
|
|
2714
|
+
onSelect: (dialog) => {
|
|
2715
|
+
const t = createT(() => langCode());
|
|
2716
|
+
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
2717
|
+
get title() {
|
|
2718
|
+
return t("balSelectTitle");
|
|
1844
2719
|
},
|
|
1845
|
-
|
|
2720
|
+
get options() {
|
|
2721
|
+
return balanceProviders.map((p) => ({
|
|
2722
|
+
title: providerOptionTitle(p),
|
|
2723
|
+
value: p.id
|
|
2724
|
+
}));
|
|
2725
|
+
},
|
|
2726
|
+
onSelect: (opt) => {
|
|
2727
|
+
const provider = getBalanceProvider(opt.value);
|
|
2728
|
+
api.kv.set(`${KV_PREFIX}.balance.provider`, provider.id);
|
|
2729
|
+
api.kv.set(`${KV_PREFIX}.balance.auto`, false);
|
|
2730
|
+
signals.setBalanceProviderId(provider.id);
|
|
2731
|
+
signals.setAutoBalance(false);
|
|
2732
|
+
signals.setBalanceRefresh(signals.balanceRefresh() + 1);
|
|
2733
|
+
promptBalanceKey(dialog, provider);
|
|
2734
|
+
}
|
|
1846
2735
|
}));
|
|
1847
2736
|
}
|
|
1848
2737
|
}, {
|
|
@@ -1853,10 +2742,11 @@ var tui = async (api) => {
|
|
|
1853
2742
|
name: "cache-debug-skills"
|
|
1854
2743
|
},
|
|
1855
2744
|
onSelect: () => {
|
|
2745
|
+
const t = createT(() => langCode());
|
|
1856
2746
|
const rt = api.route.current;
|
|
1857
2747
|
if (rt.name !== "session" || !rt.params) {
|
|
1858
2748
|
api.ui.toast({
|
|
1859
|
-
message: "
|
|
2749
|
+
message: t("runInSession"),
|
|
1860
2750
|
variant: "warning"
|
|
1861
2751
|
});
|
|
1862
2752
|
return;
|
|
@@ -1874,9 +2764,9 @@ var tui = async (api) => {
|
|
|
1874
2764
|
}
|
|
1875
2765
|
for (const p of parts) {
|
|
1876
2766
|
if (p.type === "tool") {
|
|
1877
|
-
const
|
|
1878
|
-
byTool[
|
|
1879
|
-
if (
|
|
2767
|
+
const t2 = String(p.tool ?? "?");
|
|
2768
|
+
byTool[t2] = (byTool[t2] ?? 0) + 1;
|
|
2769
|
+
if (t2 === "skill") {
|
|
1880
2770
|
const meta = p.state?.metadata;
|
|
1881
2771
|
const rootMeta = p.metadata;
|
|
1882
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)}"`);
|
|
@@ -1945,7 +2835,7 @@ var tui = async (api) => {
|
|
|
1945
2835
|
return true;
|
|
1946
2836
|
});
|
|
1947
2837
|
if (unique.length > 0) {
|
|
1948
|
-
const
|
|
2838
|
+
const t = createT(() => langCode());
|
|
1949
2839
|
const currentSid = signals.overrideSessionId() ?? api.kv.get(`${KV_PREFIX}.session`, "");
|
|
1950
2840
|
const options = unique.map((c, i) => ({
|
|
1951
2841
|
title: `${i + 1}. ${c.title}`,
|
|
@@ -1953,7 +2843,7 @@ var tui = async (api) => {
|
|
|
1953
2843
|
description: c.description
|
|
1954
2844
|
}));
|
|
1955
2845
|
const backValue = "__main__";
|
|
1956
|
-
const backTitle = `\u2500 ${
|
|
2846
|
+
const backTitle = `\u2500 ${t("backToMainTitle")}`;
|
|
1957
2847
|
options.unshift({
|
|
1958
2848
|
title: backTitle,
|
|
1959
2849
|
value: backValue,
|
|
@@ -1966,7 +2856,9 @@ var tui = async (api) => {
|
|
|
1966
2856
|
});
|
|
1967
2857
|
const currentIdx = currentSid ? options.findIndex((o) => o.value === currentSid) : -1;
|
|
1968
2858
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
1969
|
-
title
|
|
2859
|
+
get title() {
|
|
2860
|
+
return t("subSelectTitle");
|
|
2861
|
+
},
|
|
1970
2862
|
options,
|
|
1971
2863
|
get current() {
|
|
1972
2864
|
return currentIdx >= 0 ? options[currentIdx].value : void 0;
|
|
@@ -1976,28 +2868,30 @@ var tui = async (api) => {
|
|
|
1976
2868
|
signals.setOverrideSessionId(void 0);
|
|
1977
2869
|
api.kv.set(`${KV_PREFIX}.session`, "");
|
|
1978
2870
|
api.ui.toast({
|
|
1979
|
-
message:
|
|
2871
|
+
message: t("backToMain")
|
|
1980
2872
|
});
|
|
1981
2873
|
} else {
|
|
1982
2874
|
signals.setOverrideSessionId(opt.value);
|
|
1983
2875
|
api.kv.set(`${KV_PREFIX}.session`, opt.value);
|
|
1984
2876
|
api.ui.toast({
|
|
1985
|
-
message: (
|
|
2877
|
+
message: t("subAgentSwitched", {
|
|
2878
|
+
s: opt.value.slice(0, 24) + "\u2026"
|
|
2879
|
+
})
|
|
1986
2880
|
});
|
|
1987
2881
|
}
|
|
1988
2882
|
dialog?.clear();
|
|
1989
2883
|
}
|
|
1990
2884
|
}));
|
|
1991
2885
|
} else {
|
|
1992
|
-
const
|
|
2886
|
+
const t = createT(() => langCode());
|
|
1993
2887
|
dialog?.replace(() => _$createComponent(api.ui.DialogPrompt, {
|
|
1994
2888
|
get title() {
|
|
1995
|
-
return signals.overrideSessionId() ?
|
|
2889
|
+
return _$memo(() => !!signals.overrideSessionId())() ? t("subSwitchTitle") : t("subViewTitle");
|
|
1996
2890
|
},
|
|
1997
2891
|
description: () => (() => {
|
|
1998
|
-
var _el$
|
|
1999
|
-
_$insert(_el$
|
|
2000
|
-
return _el$
|
|
2892
|
+
var _el$114 = _$createElement("text");
|
|
2893
|
+
_$insert(_el$114, () => t("subNoFound"));
|
|
2894
|
+
return _el$114;
|
|
2001
2895
|
})(),
|
|
2002
2896
|
placeholder: "ses_...",
|
|
2003
2897
|
get value() {
|
|
@@ -2009,7 +2903,9 @@ var tui = async (api) => {
|
|
|
2009
2903
|
signals.setOverrideSessionId(sid);
|
|
2010
2904
|
api.kv.set(`${KV_PREFIX}.session`, sid);
|
|
2011
2905
|
api.ui.toast({
|
|
2012
|
-
message: (
|
|
2906
|
+
message: t("subAgentSwitched", {
|
|
2907
|
+
s: sid.slice(0, 24) + "\u2026"
|
|
2908
|
+
})
|
|
2013
2909
|
});
|
|
2014
2910
|
}
|
|
2015
2911
|
dialog?.clear();
|
|
@@ -2026,10 +2922,11 @@ var tui = async (api) => {
|
|
|
2026
2922
|
name: "cache-session-back"
|
|
2027
2923
|
},
|
|
2028
2924
|
onSelect: (dialog) => {
|
|
2925
|
+
const t = createT(() => langCode());
|
|
2029
2926
|
signals.setOverrideSessionId(void 0);
|
|
2030
2927
|
api.kv.set(`${KV_PREFIX}.session`, "");
|
|
2031
2928
|
api.ui.toast({
|
|
2032
|
-
message:
|
|
2929
|
+
message: t("backToMain")
|
|
2033
2930
|
});
|
|
2034
2931
|
dialog?.clear();
|
|
2035
2932
|
}
|