opencode-visual-cache 1.3.0 → 1.5.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 +32 -2
- package/README_EN.md +32 -2
- 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/index.js +332 -4
- package/dist/tui.js +631 -98
- package/package.json +1 -1
- package/src/_version.ts +1 -1
- package/src/balance-providers.ts +153 -0
- package/src/index.tsx +402 -2
package/dist/tui.js
CHANGED
|
@@ -13,7 +13,109 @@ 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.5.0";
|
|
17
|
+
|
|
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));
|
|
34
|
+
}
|
|
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) }];
|
|
39
|
+
}
|
|
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) }];
|
|
102
|
+
}
|
|
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
|
+
}
|
|
17
119
|
|
|
18
120
|
// src/index.tsx
|
|
19
121
|
function charColumns(c) {
|
|
@@ -89,7 +191,15 @@ var ZH_T = {
|
|
|
89
191
|
distOut: "\u8F93\u51FA:",
|
|
90
192
|
secDetail: "\u660E\u7EC6",
|
|
91
193
|
secModel: "\u6A21\u578B",
|
|
92
|
-
secSkills: "\u5DF2\u52A0\u8F7D\u6280\u80FD"
|
|
194
|
+
secSkills: "\u5DF2\u52A0\u8F7D\u6280\u80FD",
|
|
195
|
+
balTotal: "\u603B\u4F59\u989D:",
|
|
196
|
+
balNoKey: "\u672A\u914D\u7F6E {p} API Key",
|
|
197
|
+
balLoading: "\u67E5\u8BE2\u4E2D...",
|
|
198
|
+
balError: "\u67E5\u8BE2\u5931\u8D25",
|
|
199
|
+
balErr401: "API Key \u65E0\u6548",
|
|
200
|
+
balErr403: "\u4F59\u989D\u67E5\u8BE2\u88AB\u62D2\u7EDD",
|
|
201
|
+
balErrEmpty: "\u672A\u83B7\u53D6\u5230\u4F59\u989D\u6570\u636E",
|
|
202
|
+
balErrTimeout: "\u67E5\u8BE2\u8D85\u65F6"
|
|
93
203
|
};
|
|
94
204
|
var EN_T = {
|
|
95
205
|
title: "Token Cache",
|
|
@@ -120,7 +230,15 @@ var EN_T = {
|
|
|
120
230
|
distOut: "Output:",
|
|
121
231
|
secDetail: "Detail",
|
|
122
232
|
secModel: "Model",
|
|
123
|
-
secSkills: "Loaded Skills"
|
|
233
|
+
secSkills: "Loaded Skills",
|
|
234
|
+
balTotal: "Total:",
|
|
235
|
+
balNoKey: "{p} API Key not set",
|
|
236
|
+
balLoading: "Fetching...",
|
|
237
|
+
balError: "Fetch failed",
|
|
238
|
+
balErr401: "Invalid API Key",
|
|
239
|
+
balErr403: "Balance request rejected",
|
|
240
|
+
balErrEmpty: "No balance data",
|
|
241
|
+
balErrTimeout: "Request timed out"
|
|
124
242
|
};
|
|
125
243
|
function rgb(raw) {
|
|
126
244
|
if (typeof raw === "string" && raw.startsWith("#")) {
|
|
@@ -232,6 +350,30 @@ function estimateTokens(text) {
|
|
|
232
350
|
const asciiPerToken = jsonLike ? 3.5 : codeLike ? 3.5 : 4;
|
|
233
351
|
return Math.max(1, Math.ceil(ascii / asciiPerToken + cjk / 1));
|
|
234
352
|
}
|
|
353
|
+
var BALANCE_POLL_MS = 5 * 60 * 1e3;
|
|
354
|
+
function convertBalance(target, targetRate, amount, from) {
|
|
355
|
+
if (from === target) return amount;
|
|
356
|
+
const fromRate = DEFAULT_RATES[from] ?? 1;
|
|
357
|
+
const usd = from === "USD" ? amount : amount / fromRate;
|
|
358
|
+
return target === "USD" ? usd : usd * targetRate;
|
|
359
|
+
}
|
|
360
|
+
function findOpencodeKey(api, provider) {
|
|
361
|
+
try {
|
|
362
|
+
const provs = api.state.provider;
|
|
363
|
+
const id = provider.id.toLowerCase();
|
|
364
|
+
const hit = provs.find((p) => p.id.toLowerCase() === id) ?? provs.find((p) => p.id.toLowerCase().startsWith(id));
|
|
365
|
+
if (!hit) return "";
|
|
366
|
+
const k = typeof hit.key === "string" ? hit.key : "";
|
|
367
|
+
if (k) return k;
|
|
368
|
+
return typeof hit.options?.apiKey === "string" ? hit.options.apiKey : "";
|
|
369
|
+
} catch {
|
|
370
|
+
return "";
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
function balanceSymbol(currency) {
|
|
374
|
+
const sym = CURRENCIES[currency];
|
|
375
|
+
return sym ?? currency + " ";
|
|
376
|
+
}
|
|
235
377
|
var CURRENCIES = {
|
|
236
378
|
USD: "$",
|
|
237
379
|
CNY: "\xA5",
|
|
@@ -279,6 +421,15 @@ function TokenCachePanel(props) {
|
|
|
279
421
|
setSectionDist,
|
|
280
422
|
sectionSkills,
|
|
281
423
|
setSectionSkills,
|
|
424
|
+
sectionBalance,
|
|
425
|
+
setSectionBalance,
|
|
426
|
+
balanceRefresh,
|
|
427
|
+
balanceProviderId,
|
|
428
|
+
setBalanceProviderId,
|
|
429
|
+
autoBalance,
|
|
430
|
+
setAutoBalance,
|
|
431
|
+
balanceCurrency,
|
|
432
|
+
setBalanceCurrency,
|
|
282
433
|
borderVisible,
|
|
283
434
|
setBorderVisible
|
|
284
435
|
} = props.signals;
|
|
@@ -329,6 +480,98 @@ function TokenCachePanel(props) {
|
|
|
329
480
|
hasSkills: false
|
|
330
481
|
});
|
|
331
482
|
const [refreshTick, setRefreshTick] = createSignal(0);
|
|
483
|
+
const [balanceState, setBalanceState] = createSignal({
|
|
484
|
+
status: "idle",
|
|
485
|
+
data: null,
|
|
486
|
+
lastFetch: 0
|
|
487
|
+
});
|
|
488
|
+
let balanceSeq = 0;
|
|
489
|
+
const providerName = createMemo(() => getBalanceProvider(balanceProviderId()).name);
|
|
490
|
+
const pollBalance = async () => {
|
|
491
|
+
const provider = getBalanceProvider(balanceProviderId());
|
|
492
|
+
const key = props.api.kv.get(`${KV_PREFIX}.balance.${provider.id}.key`, "") || findOpencodeKey(props.api, provider);
|
|
493
|
+
if (!key) {
|
|
494
|
+
setBalanceState({
|
|
495
|
+
status: "idle",
|
|
496
|
+
data: null,
|
|
497
|
+
lastFetch: 0,
|
|
498
|
+
error: void 0,
|
|
499
|
+
key: void 0
|
|
500
|
+
});
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
const now = Date.now();
|
|
504
|
+
const prev = balanceState();
|
|
505
|
+
if (prev.status === "ok" && prev.key === key && now - prev.lastFetch < BALANCE_POLL_MS) return;
|
|
506
|
+
const seq = ++balanceSeq;
|
|
507
|
+
setBalanceState({
|
|
508
|
+
...prev,
|
|
509
|
+
status: "loading",
|
|
510
|
+
error: void 0,
|
|
511
|
+
key
|
|
512
|
+
});
|
|
513
|
+
const controller = new AbortController();
|
|
514
|
+
let timedOut = false;
|
|
515
|
+
const timer = setTimeout(() => {
|
|
516
|
+
timedOut = true;
|
|
517
|
+
controller.abort();
|
|
518
|
+
}, 1e4);
|
|
519
|
+
try {
|
|
520
|
+
const data2 = await provider.fetchBalance(key, controller.signal);
|
|
521
|
+
clearTimeout(timer);
|
|
522
|
+
if (seq !== balanceSeq) return;
|
|
523
|
+
setBalanceState({
|
|
524
|
+
status: "ok",
|
|
525
|
+
data: data2,
|
|
526
|
+
lastFetch: Date.now(),
|
|
527
|
+
error: void 0,
|
|
528
|
+
key
|
|
529
|
+
});
|
|
530
|
+
} catch (err) {
|
|
531
|
+
clearTimeout(timer);
|
|
532
|
+
if (seq !== balanceSeq) return;
|
|
533
|
+
const code = timedOut ? "TIMEOUT" : err instanceof Error ? err.message : "";
|
|
534
|
+
setBalanceState({
|
|
535
|
+
status: "error",
|
|
536
|
+
data: null,
|
|
537
|
+
lastFetch: 0,
|
|
538
|
+
error: code,
|
|
539
|
+
key
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
createEffect(() => {
|
|
544
|
+
void balanceRefresh();
|
|
545
|
+
untrack(() => {
|
|
546
|
+
void pollBalance();
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
createEffect(() => {
|
|
550
|
+
if (!autoBalance()) return;
|
|
551
|
+
const sid = props.signals.overrideSessionId() ?? props.sessionId;
|
|
552
|
+
const msgs = props.api.state.session.messages(sid);
|
|
553
|
+
let pid = "";
|
|
554
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
555
|
+
const m = msgs[i];
|
|
556
|
+
if (m.role === "assistant" && m.providerID) {
|
|
557
|
+
pid = m.providerID;
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
if (!pid) {
|
|
562
|
+
try {
|
|
563
|
+
const session = props.api.state.session.get(sid);
|
|
564
|
+
pid = session?.model?.providerID ?? "";
|
|
565
|
+
} catch {
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
if (!pid) return;
|
|
569
|
+
const hit = matchBalanceProvider(pid);
|
|
570
|
+
if (hit && hit.id !== balanceProviderId()) {
|
|
571
|
+
setBalanceProviderId(hit.id);
|
|
572
|
+
props.signals.setBalanceRefresh(props.signals.balanceRefresh() + 1);
|
|
573
|
+
}
|
|
574
|
+
});
|
|
332
575
|
let lastMainSid = props.sessionId;
|
|
333
576
|
createEffect(() => {
|
|
334
577
|
const sid = props.sessionId;
|
|
@@ -395,7 +638,7 @@ function TokenCachePanel(props) {
|
|
|
395
638
|
const freshTotal = input + read, sessionHitRate = freshTotal > 0 ? read / freshTotal * 100 : 0;
|
|
396
639
|
const model = mid.split("/").pop() ?? mid, hasPricing = inputRate > 0 || cacheReadRate > 0 || cacheWriteRate > 0;
|
|
397
640
|
const hasTrendData = prevMsgHitRate >= 0 && lastMsgHitRate >= 0;
|
|
398
|
-
const trend = hasTrendData ? lastMsgHitRate - prevMsgHitRate : 0,
|
|
641
|
+
const trend = hasTrendData ? lastMsgHitRate - prevMsgHitRate : 0, providerName2 = pid || "";
|
|
399
642
|
const distData = untrack(() => {
|
|
400
643
|
let dist = {
|
|
401
644
|
system: 0,
|
|
@@ -520,7 +763,7 @@ function TokenCachePanel(props) {
|
|
|
520
763
|
hasData: read > 0 || write > 0 || input > 0 || output > 0 || cost > 0,
|
|
521
764
|
trend,
|
|
522
765
|
hasTrendData,
|
|
523
|
-
providerName,
|
|
766
|
+
providerName: providerName2,
|
|
524
767
|
sessionHitRate,
|
|
525
768
|
dist: distData.finalDist,
|
|
526
769
|
hasDistData: distData.finalHasDist,
|
|
@@ -570,10 +813,26 @@ function TokenCachePanel(props) {
|
|
|
570
813
|
const rate = props.api.kv.get(`${KV_PREFIX}.rate`);
|
|
571
814
|
if (typeof sym === "string") setCurrencySymbol(sym);
|
|
572
815
|
if (typeof rate === "number" && rate > 0) setExchangeRate(rate);
|
|
816
|
+
const balCur = props.api.kv.get(`${KV_PREFIX}.balance_currency`);
|
|
817
|
+
if (typeof balCur === "string") setBalanceCurrency(balCur);
|
|
818
|
+
const savedProvider = props.api.kv.get(`${KV_PREFIX}.balance.provider`);
|
|
819
|
+
if (typeof savedProvider === "string" && balanceProviders.some((p) => p.id === savedProvider)) {
|
|
820
|
+
setBalanceProviderId(savedProvider);
|
|
821
|
+
}
|
|
822
|
+
const savedAuto = props.api.kv.get(`${KV_PREFIX}.balance.auto`);
|
|
823
|
+
if (typeof savedAuto === "boolean") setAutoBalance(savedAuto);
|
|
824
|
+
const legacyKey = props.api.kv.get(`${KV_PREFIX}.ds_key`, "");
|
|
825
|
+
if (legacyKey) {
|
|
826
|
+
const dsKey = props.api.kv.get(`${KV_PREFIX}.balance.deepseek.key`, "");
|
|
827
|
+
if (!dsKey) props.api.kv.set(`${KV_PREFIX}.balance.deepseek.key`, legacyKey);
|
|
828
|
+
props.api.kv.set(`${KV_PREFIX}.ds_key`, "");
|
|
829
|
+
}
|
|
830
|
+
props.signals.setBalanceRefresh(props.signals.balanceRefresh() + 1);
|
|
573
831
|
setSectionDetail(Boolean(props.api.kv.get(`${KV_PREFIX}.section.detail`, true)));
|
|
574
832
|
setSectionModel(Boolean(props.api.kv.get(`${KV_PREFIX}.section.model`, true)));
|
|
575
833
|
setSectionDist(Boolean(props.api.kv.get(`${KV_PREFIX}.section.dist`, true)));
|
|
576
834
|
setSectionSkills(Boolean(props.api.kv.get(`${KV_PREFIX}.section.skills`, true)));
|
|
835
|
+
setSectionBalance(Boolean(props.api.kv.get(`${KV_PREFIX}.section.balance`, true)));
|
|
577
836
|
const bv = props.api.kv.get(`${KV_PREFIX}.border`, true);
|
|
578
837
|
setBorderVisible(bv !== false);
|
|
579
838
|
const savedLang = props.api.kv.get(`${KV_PREFIX}.lang`);
|
|
@@ -626,8 +885,10 @@ function TokenCachePanel(props) {
|
|
|
626
885
|
setRefreshTick((v) => v + 1);
|
|
627
886
|
});
|
|
628
887
|
setRefreshTick((v) => v + 1);
|
|
888
|
+
const balanceTimer = setInterval(pollBalance, BALANCE_POLL_MS);
|
|
629
889
|
onCleanup(() => {
|
|
630
890
|
clearTimeout(partTimer);
|
|
891
|
+
clearInterval(balanceTimer);
|
|
631
892
|
unsubPart();
|
|
632
893
|
unsubMsg();
|
|
633
894
|
unsubSession();
|
|
@@ -798,25 +1059,25 @@ function TokenCachePanel(props) {
|
|
|
798
1059
|
const prefix = " \u21B3 " + (langZH() ? "\u5B50\u4EE3\u7406: " : "Sub: ");
|
|
799
1060
|
const maxSidW = Math.max(6, panelWidth() - visualWidth(prefix));
|
|
800
1061
|
return (() => {
|
|
801
|
-
var _el$
|
|
802
|
-
_$insertNode(_el$
|
|
803
|
-
_$insertNode(_el$
|
|
804
|
-
_$insert(_el$
|
|
805
|
-
_$insert(_el$
|
|
1062
|
+
var _el$64 = _$createElement("text"), _el$65 = _$createElement("span"), _el$66 = _$createElement("span");
|
|
1063
|
+
_$insertNode(_el$64, _el$65);
|
|
1064
|
+
_$insertNode(_el$64, _el$66);
|
|
1065
|
+
_$insert(_el$65, prefix);
|
|
1066
|
+
_$insert(_el$66, () => truncateVisual(props.signals.overrideSessionId(), maxSidW));
|
|
806
1067
|
_$effect((_p$) => {
|
|
807
|
-
var _v$
|
|
1068
|
+
var _v$15 = {
|
|
808
1069
|
fg: pal().muted
|
|
809
|
-
}, _v$
|
|
1070
|
+
}, _v$16 = {
|
|
810
1071
|
fg: pal().text
|
|
811
1072
|
};
|
|
812
|
-
_v$
|
|
813
|
-
_v$
|
|
1073
|
+
_v$15 !== _p$.e && (_p$.e = _$setProp(_el$65, "style", _v$15, _p$.e));
|
|
1074
|
+
_v$16 !== _p$.t && (_p$.t = _$setProp(_el$66, "style", _v$16, _p$.t));
|
|
814
1075
|
return _p$;
|
|
815
1076
|
}, {
|
|
816
1077
|
e: void 0,
|
|
817
1078
|
t: void 0
|
|
818
1079
|
});
|
|
819
|
-
return _el$
|
|
1080
|
+
return _el$64;
|
|
820
1081
|
})();
|
|
821
1082
|
})();
|
|
822
1083
|
}
|
|
@@ -826,30 +1087,30 @@ function TokenCachePanel(props) {
|
|
|
826
1087
|
},
|
|
827
1088
|
get fallback() {
|
|
828
1089
|
return [(() => {
|
|
829
|
-
var _el$
|
|
830
|
-
_$insert(_el$
|
|
831
|
-
_$effect((_$p) => _$setProp(_el$
|
|
832
|
-
return _el$
|
|
1090
|
+
var _el$67 = _$createElement("text");
|
|
1091
|
+
_$insert(_el$67, sep);
|
|
1092
|
+
_$effect((_$p) => _$setProp(_el$67, "fg", pal().muted, _$p));
|
|
1093
|
+
return _el$67;
|
|
833
1094
|
})(), (() => {
|
|
834
|
-
var _el$
|
|
835
|
-
_$insertNode(_el$
|
|
836
|
-
_$insertNode(_el$
|
|
837
|
-
_$insertNode(_el$
|
|
838
|
-
_$insert(_el$
|
|
1095
|
+
var _el$68 = _$createElement("text"), _el$69 = _$createElement("span"), _el$71 = _$createElement("span");
|
|
1096
|
+
_$insertNode(_el$68, _el$69);
|
|
1097
|
+
_$insertNode(_el$68, _el$71);
|
|
1098
|
+
_$insertNode(_el$69, _$createTextNode(`> `));
|
|
1099
|
+
_$insert(_el$71, () => t().noData);
|
|
839
1100
|
_$effect((_p$) => {
|
|
840
|
-
var _v$
|
|
1101
|
+
var _v$17 = {
|
|
841
1102
|
fg: pal().muted
|
|
842
|
-
}, _v$
|
|
1103
|
+
}, _v$18 = {
|
|
843
1104
|
fg: pal().muted
|
|
844
1105
|
};
|
|
845
|
-
_v$
|
|
846
|
-
_v$
|
|
1106
|
+
_v$17 !== _p$.e && (_p$.e = _$setProp(_el$69, "style", _v$17, _p$.e));
|
|
1107
|
+
_v$18 !== _p$.t && (_p$.t = _$setProp(_el$71, "style", _v$18, _p$.t));
|
|
847
1108
|
return _p$;
|
|
848
1109
|
}, {
|
|
849
1110
|
e: void 0,
|
|
850
1111
|
t: void 0
|
|
851
1112
|
});
|
|
852
|
-
return _el$
|
|
1113
|
+
return _el$68;
|
|
853
1114
|
})()];
|
|
854
1115
|
},
|
|
855
1116
|
get children() {
|
|
@@ -1016,37 +1277,37 @@ function TokenCachePanel(props) {
|
|
|
1016
1277
|
},
|
|
1017
1278
|
get children() {
|
|
1018
1279
|
return [_$memo(() => (() => {
|
|
1019
|
-
var _el$
|
|
1020
|
-
_$insertNode(_el$
|
|
1021
|
-
_$insertNode(_el$
|
|
1022
|
-
_$insertNode(_el$
|
|
1023
|
-
_$setProp(_el$
|
|
1280
|
+
var _el$72 = _$createElement("text"), _el$73 = _$createElement("span"), _el$74 = _$createElement("span"), _el$75 = _$createElement("b"), _el$76 = _$createElement("span");
|
|
1281
|
+
_$insertNode(_el$72, _el$73);
|
|
1282
|
+
_$insertNode(_el$72, _el$74);
|
|
1283
|
+
_$insertNode(_el$72, _el$76);
|
|
1284
|
+
_$setProp(_el$72, "onMouseUp", () => setModelOpen((o) => {
|
|
1024
1285
|
const n = !o;
|
|
1025
1286
|
persistFold("model", n);
|
|
1026
1287
|
return n;
|
|
1027
1288
|
}));
|
|
1028
|
-
_$insert(_el$
|
|
1029
|
-
_$insertNode(_el$
|
|
1030
|
-
_$insert(_el$
|
|
1031
|
-
_$insert(_el$
|
|
1289
|
+
_$insert(_el$73, () => modelOpen() ? "\u25BC " : "\u25B6 ");
|
|
1290
|
+
_$insertNode(_el$74, _el$75);
|
|
1291
|
+
_$insert(_el$75, () => t().secModel);
|
|
1292
|
+
_$insert(_el$76, () => sep().slice(visualWidth((modelOpen() ? "\u25BC " : "\u25B6 ") + t().secModel)));
|
|
1032
1293
|
_$effect((_p$) => {
|
|
1033
|
-
var _v$
|
|
1294
|
+
var _v$19 = {
|
|
1034
1295
|
fg: pal().muted
|
|
1035
|
-
}, _v$
|
|
1296
|
+
}, _v$20 = {
|
|
1036
1297
|
fg: pal().primary
|
|
1037
|
-
}, _v$
|
|
1298
|
+
}, _v$21 = {
|
|
1038
1299
|
fg: pal().muted
|
|
1039
1300
|
};
|
|
1040
|
-
_v$
|
|
1041
|
-
_v$
|
|
1042
|
-
_v$
|
|
1301
|
+
_v$19 !== _p$.e && (_p$.e = _$setProp(_el$73, "style", _v$19, _p$.e));
|
|
1302
|
+
_v$20 !== _p$.t && (_p$.t = _$setProp(_el$74, "style", _v$20, _p$.t));
|
|
1303
|
+
_v$21 !== _p$.a && (_p$.a = _$setProp(_el$76, "style", _v$21, _p$.a));
|
|
1043
1304
|
return _p$;
|
|
1044
1305
|
}, {
|
|
1045
1306
|
e: void 0,
|
|
1046
1307
|
t: void 0,
|
|
1047
1308
|
a: void 0
|
|
1048
1309
|
});
|
|
1049
|
-
return _el$
|
|
1310
|
+
return _el$72;
|
|
1050
1311
|
})()), _$createComponent(Show, {
|
|
1051
1312
|
get when() {
|
|
1052
1313
|
return modelOpen();
|
|
@@ -1119,37 +1380,37 @@ function TokenCachePanel(props) {
|
|
|
1119
1380
|
},
|
|
1120
1381
|
get children() {
|
|
1121
1382
|
return [_$memo(() => (() => {
|
|
1122
|
-
var _el$
|
|
1123
|
-
_$insertNode(_el$
|
|
1124
|
-
_$insertNode(_el$
|
|
1125
|
-
_$insertNode(_el$
|
|
1126
|
-
_$setProp(_el$
|
|
1383
|
+
var _el$77 = _$createElement("text"), _el$78 = _$createElement("span"), _el$79 = _$createElement("span"), _el$80 = _$createElement("b"), _el$81 = _$createElement("span");
|
|
1384
|
+
_$insertNode(_el$77, _el$78);
|
|
1385
|
+
_$insertNode(_el$77, _el$79);
|
|
1386
|
+
_$insertNode(_el$77, _el$81);
|
|
1387
|
+
_$setProp(_el$77, "onMouseUp", () => setDistOpen((o) => {
|
|
1127
1388
|
const n = !o;
|
|
1128
1389
|
persistFold("dist", n);
|
|
1129
1390
|
return n;
|
|
1130
1391
|
}));
|
|
1131
|
-
_$insert(_el$
|
|
1132
|
-
_$insertNode(_el$
|
|
1133
|
-
_$insert(_el$
|
|
1134
|
-
_$insert(_el$
|
|
1392
|
+
_$insert(_el$78, () => distOpen() ? "\u25BC " : "\u25B6 ");
|
|
1393
|
+
_$insertNode(_el$79, _el$80);
|
|
1394
|
+
_$insert(_el$80, () => t().distTitle);
|
|
1395
|
+
_$insert(_el$81, () => sep().slice(visualWidth((distOpen() ? "\u25BC " : "\u25B6 ") + t().distTitle)));
|
|
1135
1396
|
_$effect((_p$) => {
|
|
1136
|
-
var _v$
|
|
1397
|
+
var _v$22 = {
|
|
1137
1398
|
fg: pal().muted
|
|
1138
|
-
}, _v$
|
|
1399
|
+
}, _v$23 = {
|
|
1139
1400
|
fg: pal().primary
|
|
1140
|
-
}, _v$
|
|
1401
|
+
}, _v$24 = {
|
|
1141
1402
|
fg: pal().muted
|
|
1142
1403
|
};
|
|
1143
|
-
_v$
|
|
1144
|
-
_v$
|
|
1145
|
-
_v$
|
|
1404
|
+
_v$22 !== _p$.e && (_p$.e = _$setProp(_el$78, "style", _v$22, _p$.e));
|
|
1405
|
+
_v$23 !== _p$.t && (_p$.t = _$setProp(_el$79, "style", _v$23, _p$.t));
|
|
1406
|
+
_v$24 !== _p$.a && (_p$.a = _$setProp(_el$81, "style", _v$24, _p$.a));
|
|
1146
1407
|
return _p$;
|
|
1147
1408
|
}, {
|
|
1148
1409
|
e: void 0,
|
|
1149
1410
|
t: void 0,
|
|
1150
1411
|
a: void 0
|
|
1151
1412
|
});
|
|
1152
|
-
return _el$
|
|
1413
|
+
return _el$77;
|
|
1153
1414
|
})()), _$createComponent(Show, {
|
|
1154
1415
|
get when() {
|
|
1155
1416
|
return distOpen();
|
|
@@ -1227,37 +1488,37 @@ function TokenCachePanel(props) {
|
|
|
1227
1488
|
},
|
|
1228
1489
|
get children() {
|
|
1229
1490
|
return [_$memo(() => (() => {
|
|
1230
|
-
var _el$
|
|
1231
|
-
_$insertNode(_el$
|
|
1232
|
-
_$insertNode(_el$
|
|
1233
|
-
_$insertNode(_el$
|
|
1234
|
-
_$insertNode(_el$
|
|
1235
|
-
_$setProp(_el$
|
|
1491
|
+
var _el$82 = _$createElement("text"), _el$83 = _$createElement("span"), _el$84 = _$createElement("span"), _el$85 = _$createElement("b"), _el$86 = _$createElement("span"), _el$87 = _$createTextNode(` (`), _el$88 = _$createTextNode(`)`), _el$89 = _$createElement("span");
|
|
1492
|
+
_$insertNode(_el$82, _el$83);
|
|
1493
|
+
_$insertNode(_el$82, _el$84);
|
|
1494
|
+
_$insertNode(_el$82, _el$86);
|
|
1495
|
+
_$insertNode(_el$82, _el$89);
|
|
1496
|
+
_$setProp(_el$82, "onMouseUp", () => setSkillsOpen((o) => {
|
|
1236
1497
|
const n = !o;
|
|
1237
1498
|
persistFold("skills", n);
|
|
1238
1499
|
return n;
|
|
1239
1500
|
}));
|
|
1240
|
-
_$insert(_el$
|
|
1241
|
-
_$insertNode(_el$
|
|
1242
|
-
_$insert(_el$
|
|
1243
|
-
_$insertNode(_el$
|
|
1244
|
-
_$insertNode(_el$
|
|
1245
|
-
_$insert(_el$
|
|
1246
|
-
_$insert(_el$
|
|
1501
|
+
_$insert(_el$83, () => skillsOpen() ? "\u25BC " : "\u25B6 ");
|
|
1502
|
+
_$insertNode(_el$84, _el$85);
|
|
1503
|
+
_$insert(_el$85, () => t().secSkills);
|
|
1504
|
+
_$insertNode(_el$86, _el$87);
|
|
1505
|
+
_$insertNode(_el$86, _el$88);
|
|
1506
|
+
_$insert(_el$86, () => data().skills.length, _el$88);
|
|
1507
|
+
_$insert(_el$89, () => sep().slice(visualWidth((skillsOpen() ? "\u25BC " : "\u25B6 ") + t().secSkills + ` (${data().skills.length})`)));
|
|
1247
1508
|
_$effect((_p$) => {
|
|
1248
|
-
var _v$
|
|
1509
|
+
var _v$25 = {
|
|
1249
1510
|
fg: pal().muted
|
|
1250
|
-
}, _v$
|
|
1511
|
+
}, _v$26 = {
|
|
1251
1512
|
fg: pal().primary
|
|
1252
|
-
}, _v$
|
|
1513
|
+
}, _v$27 = {
|
|
1253
1514
|
fg: pal().muted
|
|
1254
|
-
}, _v$
|
|
1515
|
+
}, _v$28 = {
|
|
1255
1516
|
fg: pal().muted
|
|
1256
1517
|
};
|
|
1257
|
-
_v$
|
|
1258
|
-
_v$
|
|
1259
|
-
_v$
|
|
1260
|
-
_v$
|
|
1518
|
+
_v$25 !== _p$.e && (_p$.e = _$setProp(_el$83, "style", _v$25, _p$.e));
|
|
1519
|
+
_v$26 !== _p$.t && (_p$.t = _$setProp(_el$84, "style", _v$26, _p$.t));
|
|
1520
|
+
_v$27 !== _p$.a && (_p$.a = _$setProp(_el$86, "style", _v$27, _p$.a));
|
|
1521
|
+
_v$28 !== _p$.o && (_p$.o = _$setProp(_el$89, "style", _v$28, _p$.o));
|
|
1261
1522
|
return _p$;
|
|
1262
1523
|
}, {
|
|
1263
1524
|
e: void 0,
|
|
@@ -1265,7 +1526,7 @@ function TokenCachePanel(props) {
|
|
|
1265
1526
|
a: void 0,
|
|
1266
1527
|
o: void 0
|
|
1267
1528
|
});
|
|
1268
|
-
return _el$
|
|
1529
|
+
return _el$82;
|
|
1269
1530
|
})()), _$createComponent(Show, {
|
|
1270
1531
|
get when() {
|
|
1271
1532
|
return skillsOpen();
|
|
@@ -1276,10 +1537,10 @@ function TokenCachePanel(props) {
|
|
|
1276
1537
|
const maxLabel = Math.max(4, panelWidth() - gutter() - rightW - 1);
|
|
1277
1538
|
const label = truncateVisual(sk.name, maxLabel);
|
|
1278
1539
|
return (() => {
|
|
1279
|
-
var _el$
|
|
1280
|
-
_$insert(_el$
|
|
1281
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1282
|
-
return _el$
|
|
1540
|
+
var _el$90 = _$createElement("text");
|
|
1541
|
+
_$insert(_el$90, () => justify(label, fmt(sk.tokens), t().tok));
|
|
1542
|
+
_$effect((_$p) => _$setProp(_el$90, "fg", pal().muted, _$p));
|
|
1543
|
+
return _el$90;
|
|
1283
1544
|
})();
|
|
1284
1545
|
});
|
|
1285
1546
|
}
|
|
@@ -1287,19 +1548,138 @@ function TokenCachePanel(props) {
|
|
|
1287
1548
|
}
|
|
1288
1549
|
});
|
|
1289
1550
|
}
|
|
1551
|
+
}), _$createComponent(Show, {
|
|
1552
|
+
get when() {
|
|
1553
|
+
return sectionBalance();
|
|
1554
|
+
},
|
|
1555
|
+
get children() {
|
|
1556
|
+
return [(() => {
|
|
1557
|
+
var _el$51 = _$createElement("text");
|
|
1558
|
+
_$insert(_el$51, sep);
|
|
1559
|
+
_$effect((_$p) => _$setProp(_el$51, "fg", pal().muted, _$p));
|
|
1560
|
+
return _el$51;
|
|
1561
|
+
})(), _$createComponent(Show, {
|
|
1562
|
+
get when() {
|
|
1563
|
+
return balanceState().status === "idle";
|
|
1564
|
+
},
|
|
1565
|
+
get children() {
|
|
1566
|
+
var _el$52 = _$createElement("text"), _el$53 = _$createElement("span"), _el$55 = _$createElement("span");
|
|
1567
|
+
_$insertNode(_el$52, _el$53);
|
|
1568
|
+
_$insertNode(_el$52, _el$55);
|
|
1569
|
+
_$insertNode(_el$53, _$createTextNode(`> `));
|
|
1570
|
+
_$insert(_el$55, () => t().balNoKey.replace("{p}", providerName()));
|
|
1571
|
+
_$effect((_p$) => {
|
|
1572
|
+
var _v$9 = pal().muted, _v$0 = {
|
|
1573
|
+
fg: pal().muted
|
|
1574
|
+
};
|
|
1575
|
+
_v$9 !== _p$.e && (_p$.e = _$setProp(_el$52, "fg", _v$9, _p$.e));
|
|
1576
|
+
_v$0 !== _p$.t && (_p$.t = _$setProp(_el$53, "style", _v$0, _p$.t));
|
|
1577
|
+
return _p$;
|
|
1578
|
+
}, {
|
|
1579
|
+
e: void 0,
|
|
1580
|
+
t: void 0
|
|
1581
|
+
});
|
|
1582
|
+
return _el$52;
|
|
1583
|
+
}
|
|
1584
|
+
}), _$createComponent(Show, {
|
|
1585
|
+
get when() {
|
|
1586
|
+
return balanceState().status === "loading";
|
|
1587
|
+
},
|
|
1588
|
+
get children() {
|
|
1589
|
+
var _el$56 = _$createElement("text"), _el$57 = _$createElement("span"), _el$59 = _$createElement("span");
|
|
1590
|
+
_$insertNode(_el$56, _el$57);
|
|
1591
|
+
_$insertNode(_el$56, _el$59);
|
|
1592
|
+
_$insertNode(_el$57, _$createTextNode(`> `));
|
|
1593
|
+
_$insert(_el$59, () => t().balLoading);
|
|
1594
|
+
_$effect((_p$) => {
|
|
1595
|
+
var _v$1 = pal().muted, _v$10 = {
|
|
1596
|
+
fg: pal().muted
|
|
1597
|
+
};
|
|
1598
|
+
_v$1 !== _p$.e && (_p$.e = _$setProp(_el$56, "fg", _v$1, _p$.e));
|
|
1599
|
+
_v$10 !== _p$.t && (_p$.t = _$setProp(_el$57, "style", _v$10, _p$.t));
|
|
1600
|
+
return _p$;
|
|
1601
|
+
}, {
|
|
1602
|
+
e: void 0,
|
|
1603
|
+
t: void 0
|
|
1604
|
+
});
|
|
1605
|
+
return _el$56;
|
|
1606
|
+
}
|
|
1607
|
+
}), _$createComponent(Show, {
|
|
1608
|
+
get when() {
|
|
1609
|
+
return balanceState().status === "error";
|
|
1610
|
+
},
|
|
1611
|
+
get children() {
|
|
1612
|
+
var _el$60 = _$createElement("text"), _el$61 = _$createElement("span"), _el$63 = _$createElement("span");
|
|
1613
|
+
_$insertNode(_el$60, _el$61);
|
|
1614
|
+
_$insertNode(_el$60, _el$63);
|
|
1615
|
+
_$insertNode(_el$61, _$createTextNode(`> `));
|
|
1616
|
+
_$insert(_el$63, () => {
|
|
1617
|
+
const code = balanceState().error;
|
|
1618
|
+
if (code === "401") return t().balErr401;
|
|
1619
|
+
if (code === "403") return t().balErr403;
|
|
1620
|
+
if (code === "EMPTY") return t().balErrEmpty;
|
|
1621
|
+
if (code === "TIMEOUT") return t().balErrTimeout;
|
|
1622
|
+
return t().balError + (code ? ` (${code})` : "");
|
|
1623
|
+
});
|
|
1624
|
+
_$effect((_p$) => {
|
|
1625
|
+
var _v$11 = pal().error, _v$12 = {
|
|
1626
|
+
fg: pal().muted
|
|
1627
|
+
};
|
|
1628
|
+
_v$11 !== _p$.e && (_p$.e = _$setProp(_el$60, "fg", _v$11, _p$.e));
|
|
1629
|
+
_v$12 !== _p$.t && (_p$.t = _$setProp(_el$61, "style", _v$12, _p$.t));
|
|
1630
|
+
return _p$;
|
|
1631
|
+
}, {
|
|
1632
|
+
e: void 0,
|
|
1633
|
+
t: void 0
|
|
1634
|
+
});
|
|
1635
|
+
return _el$60;
|
|
1636
|
+
}
|
|
1637
|
+
}), _$createComponent(Show, {
|
|
1638
|
+
get when() {
|
|
1639
|
+
return _$memo(() => balanceState().status === "ok")() && balanceState().data;
|
|
1640
|
+
},
|
|
1641
|
+
get children() {
|
|
1642
|
+
return (() => {
|
|
1643
|
+
const list = balanceState().data;
|
|
1644
|
+
const pref = balanceCurrency();
|
|
1645
|
+
const native = pref ? list.find((x) => x.currency === pref) : void 0;
|
|
1646
|
+
if (native) {
|
|
1647
|
+
return (() => {
|
|
1648
|
+
var _el$91 = _$createElement("text");
|
|
1649
|
+
_$insert(_el$91, () => justify(t().balTotal, balanceSymbol(native.currency) + native.total));
|
|
1650
|
+
_$effect((_$p) => _$setProp(_el$91, "fg", pal().text, _$p));
|
|
1651
|
+
return _el$91;
|
|
1652
|
+
})();
|
|
1653
|
+
}
|
|
1654
|
+
const base = list[0];
|
|
1655
|
+
const baseAmt = parseFloat(base.total);
|
|
1656
|
+
const converted = Number.isFinite(baseAmt) ? convertBalance(pref || base.currency, exchangeRate(), baseAmt, base.currency) : baseAmt;
|
|
1657
|
+
const shown = pref && base.currency !== pref ? converted.toLocaleString("en-US", {
|
|
1658
|
+
maximumFractionDigits: 2
|
|
1659
|
+
}) : base.total;
|
|
1660
|
+
return (() => {
|
|
1661
|
+
var _el$92 = _$createElement("text");
|
|
1662
|
+
_$insert(_el$92, () => justify(t().balTotal, balanceSymbol(pref || base.currency) + shown));
|
|
1663
|
+
_$effect((_$p) => _$setProp(_el$92, "fg", pal().text, _$p));
|
|
1664
|
+
return _el$92;
|
|
1665
|
+
})();
|
|
1666
|
+
})();
|
|
1667
|
+
}
|
|
1668
|
+
})];
|
|
1669
|
+
}
|
|
1290
1670
|
})];
|
|
1291
1671
|
}
|
|
1292
1672
|
})];
|
|
1293
1673
|
}
|
|
1294
1674
|
}), null);
|
|
1295
1675
|
_$effect((_p$) => {
|
|
1296
|
-
var _v$
|
|
1676
|
+
var _v$13 = {
|
|
1297
1677
|
fg: pal().muted
|
|
1298
|
-
}, _v$
|
|
1678
|
+
}, _v$14 = {
|
|
1299
1679
|
fg: pal().primary
|
|
1300
1680
|
};
|
|
1301
|
-
_v$
|
|
1302
|
-
_v$
|
|
1681
|
+
_v$13 !== _p$.e && (_p$.e = _$setProp(_el$3, "style", _v$13, _p$.e));
|
|
1682
|
+
_v$14 !== _p$.t && (_p$.t = _$setProp(_el$4, "style", _v$14, _p$.t));
|
|
1303
1683
|
return _p$;
|
|
1304
1684
|
}, {
|
|
1305
1685
|
e: void 0,
|
|
@@ -1342,6 +1722,11 @@ var tui = async (api) => {
|
|
|
1342
1722
|
const [sectionModel, setSectionModel] = createSignal(true);
|
|
1343
1723
|
const [sectionDist, setSectionDist] = createSignal(true);
|
|
1344
1724
|
const [sectionSkills, setSectionSkills] = createSignal(true);
|
|
1725
|
+
const [sectionBalance, setSectionBalance] = createSignal(true);
|
|
1726
|
+
const [balanceRefresh, setBalanceRefresh] = createSignal(0);
|
|
1727
|
+
const [balanceProviderId, setBalanceProviderId] = createSignal("deepseek");
|
|
1728
|
+
const [autoBalance, setAutoBalance] = createSignal(true);
|
|
1729
|
+
const [balanceCurrency, setBalanceCurrency] = createSignal("");
|
|
1345
1730
|
const [borderVisible, setBorderVisible] = createSignal(true);
|
|
1346
1731
|
const [langZH, setLangZH] = createSignal(LANG_ZH);
|
|
1347
1732
|
const [overrideSessionId, setOverrideSessionId] = createSignal(void 0);
|
|
@@ -1360,6 +1745,16 @@ var tui = async (api) => {
|
|
|
1360
1745
|
setSectionDist,
|
|
1361
1746
|
sectionSkills,
|
|
1362
1747
|
setSectionSkills,
|
|
1748
|
+
sectionBalance,
|
|
1749
|
+
setSectionBalance,
|
|
1750
|
+
balanceRefresh,
|
|
1751
|
+
setBalanceRefresh,
|
|
1752
|
+
balanceProviderId,
|
|
1753
|
+
setBalanceProviderId,
|
|
1754
|
+
autoBalance,
|
|
1755
|
+
setAutoBalance,
|
|
1756
|
+
balanceCurrency,
|
|
1757
|
+
setBalanceCurrency,
|
|
1363
1758
|
borderVisible,
|
|
1364
1759
|
setBorderVisible,
|
|
1365
1760
|
overrideSessionId,
|
|
@@ -1367,6 +1762,56 @@ var tui = async (api) => {
|
|
|
1367
1762
|
};
|
|
1368
1763
|
api.slots.register(createSidebarSlot(api, signals));
|
|
1369
1764
|
const KV_PREFIX = "cache_panel";
|
|
1765
|
+
const providerOptionTitle = (p, current) => {
|
|
1766
|
+
const zh = langZH();
|
|
1767
|
+
const hasManual = !!api.kv.get(`${KV_PREFIX}.balance.${p.id}.key`, "");
|
|
1768
|
+
const hasAuto = !hasManual && !!findOpencodeKey(api, p);
|
|
1769
|
+
const mark = hasManual ? zh ? "\uFF08\u7528\u6237 key\uFF09" : " (user key)" : hasAuto ? zh ? "\uFF08OpenCode\uFF09" : " (OpenCode)" : zh ? "\uFF08\u672A\u914D\u7F6E\uFF09" : " (not set)";
|
|
1770
|
+
return p.name + mark + (current && p.id === current ? " *" : "");
|
|
1771
|
+
};
|
|
1772
|
+
const promptBalanceKey = (dialog, provider) => {
|
|
1773
|
+
const zh = langZH();
|
|
1774
|
+
const current = api.kv.get(`${KV_PREFIX}.balance.${provider.id}.key`, "");
|
|
1775
|
+
const masked = maskKey(current);
|
|
1776
|
+
dialog?.replace(() => _$createComponent(api.ui.DialogPrompt, {
|
|
1777
|
+
get title() {
|
|
1778
|
+
return provider.name;
|
|
1779
|
+
},
|
|
1780
|
+
description: () => (() => {
|
|
1781
|
+
var _el$93 = _$createElement("text");
|
|
1782
|
+
_$insert(_el$93, () => zh ? `\u8F93\u5165 ${provider.name} API Key \u4EE5\u663E\u793A\u8D26\u6237\u4F59\u989D\uFF08\u7559\u7A7A\u6E05\u9664\uFF09` : `Enter your ${provider.name} API key to show account balance (leave empty to clear)`);
|
|
1783
|
+
return _el$93;
|
|
1784
|
+
})(),
|
|
1785
|
+
get placeholder() {
|
|
1786
|
+
return provider.keyPlaceholder ?? "sk-...";
|
|
1787
|
+
},
|
|
1788
|
+
value: masked,
|
|
1789
|
+
onConfirm: (val) => {
|
|
1790
|
+
const input = val.trim();
|
|
1791
|
+
let key;
|
|
1792
|
+
if (input === "") {
|
|
1793
|
+
key = "";
|
|
1794
|
+
} else if (input.includes("*")) {
|
|
1795
|
+
key = current;
|
|
1796
|
+
} else {
|
|
1797
|
+
key = input;
|
|
1798
|
+
}
|
|
1799
|
+
api.kv.set(`${KV_PREFIX}.balance.${provider.id}.key`, key);
|
|
1800
|
+
setBalanceRefresh((v) => v + 1);
|
|
1801
|
+
if (key) {
|
|
1802
|
+
api.ui.toast({
|
|
1803
|
+
message: zh ? "API Key \u5DF2\u4FDD\u5B58\uFF0C\u6B63\u5728\u67E5\u8BE2\u4F59\u989D..." : "API Key saved, fetching balance..."
|
|
1804
|
+
});
|
|
1805
|
+
} else {
|
|
1806
|
+
api.ui.toast({
|
|
1807
|
+
message: zh ? "API Key \u5DF2\u6E05\u9664" : "API Key cleared"
|
|
1808
|
+
});
|
|
1809
|
+
}
|
|
1810
|
+
dialog?.clear();
|
|
1811
|
+
},
|
|
1812
|
+
onCancel: () => dialog?.clear()
|
|
1813
|
+
}));
|
|
1814
|
+
};
|
|
1370
1815
|
api.command?.register(() => [{
|
|
1371
1816
|
title: "Cache: Set Currency",
|
|
1372
1817
|
value: "cache.currency",
|
|
@@ -1388,6 +1833,8 @@ var tui = async (api) => {
|
|
|
1388
1833
|
const defRate = DEFAULT_RATES[opt.value] ?? 1;
|
|
1389
1834
|
api.kv.set(`${KV_PREFIX}.currency`, sym);
|
|
1390
1835
|
api.kv.set(`${KV_PREFIX}.rate`, defRate);
|
|
1836
|
+
api.kv.set(`${KV_PREFIX}.balance_currency`, opt.value);
|
|
1837
|
+
signals.setBalanceCurrency(opt.value);
|
|
1391
1838
|
signals.setCurrencySymbol(sym);
|
|
1392
1839
|
signals.setExchangeRate(defRate);
|
|
1393
1840
|
api.ui.toast({
|
|
@@ -1408,9 +1855,9 @@ var tui = async (api) => {
|
|
|
1408
1855
|
dialog?.replace(() => _$createComponent(api.ui.DialogPrompt, {
|
|
1409
1856
|
title: "Exchange Rate",
|
|
1410
1857
|
description: () => (() => {
|
|
1411
|
-
var _el$
|
|
1412
|
-
_$insertNode(_el$
|
|
1413
|
-
return _el$
|
|
1858
|
+
var _el$94 = _$createElement("text");
|
|
1859
|
+
_$insertNode(_el$94, _$createTextNode(`Enter the exchange rate from USD to your currency (e.g. 7.2 for CNY)`));
|
|
1860
|
+
return _el$94;
|
|
1414
1861
|
})(),
|
|
1415
1862
|
placeholder: "1.0",
|
|
1416
1863
|
get value() {
|
|
@@ -1441,6 +1888,7 @@ var tui = async (api) => {
|
|
|
1441
1888
|
const modelOn = Boolean(api.kv.get(`${KV_PREFIX}.section.model`, true));
|
|
1442
1889
|
const distOn = Boolean(api.kv.get(`${KV_PREFIX}.section.dist`, true));
|
|
1443
1890
|
const skillsOn = Boolean(api.kv.get(`${KV_PREFIX}.section.skills`, true));
|
|
1891
|
+
const balanceOn = Boolean(api.kv.get(`${KV_PREFIX}.section.balance`, true));
|
|
1444
1892
|
const borderOn = Boolean(api.kv.get(`${KV_PREFIX}.border`, true));
|
|
1445
1893
|
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
1446
1894
|
title: "Toggle Section",
|
|
@@ -1456,6 +1904,9 @@ var tui = async (api) => {
|
|
|
1456
1904
|
}, {
|
|
1457
1905
|
title: `Loaded Skills [${skillsOn ? "ON" : "OFF"}]`,
|
|
1458
1906
|
value: "skills"
|
|
1907
|
+
}, {
|
|
1908
|
+
title: `Balance [${balanceOn ? "ON" : "OFF"}]`,
|
|
1909
|
+
value: "balance"
|
|
1459
1910
|
}, {
|
|
1460
1911
|
title: `Panel Border [${borderOn ? "ON" : "OFF"}]`,
|
|
1461
1912
|
value: "border"
|
|
@@ -1476,6 +1927,7 @@ var tui = async (api) => {
|
|
|
1476
1927
|
if (opt.value === "model") signals.setSectionModel(!cur);
|
|
1477
1928
|
if (opt.value === "dist") signals.setSectionDist(!cur);
|
|
1478
1929
|
if (opt.value === "skills") signals.setSectionSkills(!cur);
|
|
1930
|
+
if (opt.value === "balance") signals.setSectionBalance(!cur);
|
|
1479
1931
|
api.ui.toast({
|
|
1480
1932
|
message: `${opt.value} section ${!cur ? "shown" : "hidden"}`
|
|
1481
1933
|
});
|
|
@@ -1498,9 +1950,10 @@ var tui = async (api) => {
|
|
|
1498
1950
|
const model = Boolean(api.kv.get(`${KV_PREFIX}.section.model`, true));
|
|
1499
1951
|
const dist = Boolean(api.kv.get(`${KV_PREFIX}.section.dist`, true));
|
|
1500
1952
|
const skills = Boolean(api.kv.get(`${KV_PREFIX}.section.skills`, true));
|
|
1953
|
+
const balance = Boolean(api.kv.get(`${KV_PREFIX}.section.balance`, true));
|
|
1501
1954
|
api.ui.toast({
|
|
1502
1955
|
title: "Cache Panel Config",
|
|
1503
|
-
message: `Currency: ${sym} | Rate: ${rate} | Detail: ${detail ? "ON" : "OFF"} | Model: ${model ? "ON" : "OFF"} | Dist: ${dist ? "ON" : "OFF"} | Skills: ${skills ? "ON" : "OFF"}`,
|
|
1956
|
+
message: `Currency: ${sym} | Rate: ${rate} | Detail: ${detail ? "ON" : "OFF"} | Model: ${model ? "ON" : "OFF"} | Dist: ${dist ? "ON" : "OFF"} | Skills: ${skills ? "ON" : "OFF"} | Balance: ${balance ? "ON" : "OFF"}`,
|
|
1504
1957
|
duration: 8e3
|
|
1505
1958
|
});
|
|
1506
1959
|
dialog?.clear();
|
|
@@ -1534,6 +1987,86 @@ var tui = async (api) => {
|
|
|
1534
1987
|
}
|
|
1535
1988
|
}));
|
|
1536
1989
|
}
|
|
1990
|
+
}, {
|
|
1991
|
+
title: "Cache: Switch Balance Provider",
|
|
1992
|
+
value: "cache.balance",
|
|
1993
|
+
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",
|
|
1994
|
+
slash: {
|
|
1995
|
+
name: "cache-balance"
|
|
1996
|
+
},
|
|
1997
|
+
onSelect: (dialog) => {
|
|
1998
|
+
const zh = langZH();
|
|
1999
|
+
const current = signals.balanceProviderId();
|
|
2000
|
+
const auto = signals.autoBalance();
|
|
2001
|
+
const autoLabel = auto ? zh ? "\u81EA\u52A8\u5207\u6362\u63D0\u4F9B\u5546 [\u5F00]" : "Auto-switch provider [ON]" : zh ? "\u81EA\u52A8\u5207\u6362\u63D0\u4F9B\u5546 [\u5173]" : "Auto-switch provider [OFF]";
|
|
2002
|
+
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
2003
|
+
title: zh ? "\u4F59\u989D\u63D0\u4F9B\u5546 / \u81EA\u52A8\u5207\u6362" : "Balance Provider / Auto-switch",
|
|
2004
|
+
get options() {
|
|
2005
|
+
return [{
|
|
2006
|
+
title: autoLabel,
|
|
2007
|
+
value: "__auto__"
|
|
2008
|
+
}, ...balanceProviders.map((p) => ({
|
|
2009
|
+
title: providerOptionTitle(p, current),
|
|
2010
|
+
value: p.id
|
|
2011
|
+
}))];
|
|
2012
|
+
},
|
|
2013
|
+
onSelect: (opt) => {
|
|
2014
|
+
if (opt.value === "__auto__") {
|
|
2015
|
+
const next = !auto;
|
|
2016
|
+
api.kv.set(`${KV_PREFIX}.balance.auto`, next);
|
|
2017
|
+
signals.setAutoBalance(next);
|
|
2018
|
+
api.ui.toast({
|
|
2019
|
+
message: zh ? `\u81EA\u52A8\u5207\u6362\u4F59\u989D\u63D0\u4F9B\u5546: ${next ? "\u5F00" : "\u5173"}` : `Auto-switch balance provider: ${next ? "ON" : "OFF"}`
|
|
2020
|
+
});
|
|
2021
|
+
dialog?.clear();
|
|
2022
|
+
} else {
|
|
2023
|
+
const provider = getBalanceProvider(opt.value);
|
|
2024
|
+
api.kv.set(`${KV_PREFIX}.balance.provider`, provider.id);
|
|
2025
|
+
api.kv.set(`${KV_PREFIX}.balance.auto`, false);
|
|
2026
|
+
signals.setBalanceProviderId(provider.id);
|
|
2027
|
+
signals.setAutoBalance(false);
|
|
2028
|
+
signals.setBalanceRefresh(signals.balanceRefresh() + 1);
|
|
2029
|
+
const hasKey = !!api.kv.get(`${KV_PREFIX}.balance.${provider.id}.key`, "");
|
|
2030
|
+
if (!hasKey) {
|
|
2031
|
+
promptBalanceKey(dialog, provider);
|
|
2032
|
+
} else {
|
|
2033
|
+
api.ui.toast({
|
|
2034
|
+
message: zh ? `\u4F59\u989D\u63D0\u4F9B\u5546: ${provider.name}\uFF08\u81EA\u52A8\u5207\u6362\u5DF2\u5173\u95ED\uFF09` : `Balance provider: ${provider.name} (auto-switch off)`
|
|
2035
|
+
});
|
|
2036
|
+
dialog?.clear();
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
}));
|
|
2041
|
+
}
|
|
2042
|
+
}, {
|
|
2043
|
+
title: "Cache: Set Balance API Key",
|
|
2044
|
+
value: "cache.balance.key",
|
|
2045
|
+
description: "Select a provider and set its API key for balance display",
|
|
2046
|
+
slash: {
|
|
2047
|
+
name: "cache-balance-key"
|
|
2048
|
+
},
|
|
2049
|
+
onSelect: (dialog) => {
|
|
2050
|
+
const zh = langZH();
|
|
2051
|
+
dialog?.replace(() => _$createComponent(api.ui.DialogSelect, {
|
|
2052
|
+
title: zh ? "\u9009\u62E9\u4F59\u989D\u63D0\u4F9B\u5546" : "Select Balance Provider",
|
|
2053
|
+
get options() {
|
|
2054
|
+
return balanceProviders.map((p) => ({
|
|
2055
|
+
title: providerOptionTitle(p),
|
|
2056
|
+
value: p.id
|
|
2057
|
+
}));
|
|
2058
|
+
},
|
|
2059
|
+
onSelect: (opt) => {
|
|
2060
|
+
const provider = getBalanceProvider(opt.value);
|
|
2061
|
+
api.kv.set(`${KV_PREFIX}.balance.provider`, provider.id);
|
|
2062
|
+
api.kv.set(`${KV_PREFIX}.balance.auto`, false);
|
|
2063
|
+
signals.setBalanceProviderId(provider.id);
|
|
2064
|
+
signals.setAutoBalance(false);
|
|
2065
|
+
signals.setBalanceRefresh(signals.balanceRefresh() + 1);
|
|
2066
|
+
promptBalanceKey(dialog, provider);
|
|
2067
|
+
}
|
|
2068
|
+
}));
|
|
2069
|
+
}
|
|
1537
2070
|
}, {
|
|
1538
2071
|
title: "Cache: Debug Skills Detection",
|
|
1539
2072
|
value: "cache.debug-skills",
|
|
@@ -1684,9 +2217,9 @@ var tui = async (api) => {
|
|
|
1684
2217
|
return signals.overrideSessionId() ? zh ? "\u5207\u6362\u5B50\u4EE3\u7406" : "Switch Sub" : zh ? "\u67E5\u770B\u5B50\u4EE3\u7406\u7F13\u5B58" : "View Sub Cache";
|
|
1685
2218
|
},
|
|
1686
2219
|
description: () => (() => {
|
|
1687
|
-
var _el$
|
|
1688
|
-
_$insert(_el$
|
|
1689
|
-
return _el$
|
|
2220
|
+
var _el$96 = _$createElement("text");
|
|
2221
|
+
_$insert(_el$96, zh ? "\u672A\u627E\u5230\u5B50\u4EE3\u7406\uFF0C\u8BF7\u624B\u52A8\u7C98\u8D34 Session ID" : "No sub-agents found. Paste a Session ID manually");
|
|
2222
|
+
return _el$96;
|
|
1690
2223
|
})(),
|
|
1691
2224
|
placeholder: "ses_...",
|
|
1692
2225
|
get value() {
|