opencode-visual-cache 1.6.2 → 1.7.0-beta.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/LICENSE +21 -21
- package/README.md +247 -247
- package/README_EN.md +247 -247
- package/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/core/color.d.ts +37 -0
- package/dist/core/color.js +108 -0
- package/dist/core/currency.d.ts +17 -0
- package/dist/core/currency.js +43 -0
- package/dist/core/estimate.d.ts +1 -0
- package/dist/core/estimate.js +40 -0
- package/dist/core/format.d.ts +15 -0
- package/dist/core/format.js +90 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +5 -0
- package/dist/core/types.d.ts +17 -0
- package/dist/core/types.js +1 -0
- package/dist/index.js +12 -818
- package/dist/panel/TokenCachePanel.d.ts +10 -0
- package/dist/panel/TokenCachePanel.js +549 -0
- package/dist/panel/panel-api.d.ts +119 -0
- package/dist/panel/panel-api.js +1 -0
- package/dist/tui.js +223 -209
- package/dist/v2/commands.d.ts +10 -0
- package/dist/v2/commands.js +490 -0
- package/dist/v2/data.d.ts +27 -0
- package/dist/v2/data.js +103 -0
- package/dist/v2/index.d.ts +4 -0
- package/dist/v2/index.js +163 -0
- package/dist/v2/sidebar.d.ts +6 -0
- package/dist/v2/sidebar.js +36 -0
- package/dist/v2/status.d.ts +14 -0
- package/dist/v2/status.js +83 -0
- package/dist/v2/theme.d.ts +8 -0
- package/dist/v2/theme.js +16 -0
- package/dist/v2/types.d.ts +219 -0
- package/dist/v2/types.js +6 -0
- package/dist/v2/v2-panel-api.d.ts +8 -0
- package/dist/v2/v2-panel-api.js +176 -0
- package/dist/v2.js +2941 -0
- package/package.json +70 -67
- package/src/_version.ts +1 -1
- package/src/balance-providers.ts +153 -153
- package/src/core/color.ts +108 -0
- package/src/core/currency.ts +46 -0
- package/src/core/estimate.ts +36 -0
- package/src/core/format.ts +81 -0
- package/src/core/index.ts +5 -0
- package/src/core/types.ts +17 -0
- package/src/i18n.ts +380 -380
- package/src/index.tsx +1035 -2120
- package/src/panel/TokenCachePanel.tsx +776 -0
- package/src/panel/panel-api.ts +104 -0
- package/src/server.ts +10 -10
- package/src/v2/commands.ts +471 -0
- package/src/v2/data.ts +112 -0
- package/src/v2/index.tsx +184 -0
- package/src/v2/sidebar.tsx +69 -0
- package/src/v2/status.tsx +96 -0
- package/src/v2/theme.ts +19 -0
- package/src/v2/types.ts +159 -0
- package/src/v2/v2-panel-api.ts +177 -0
package/dist/tui.js
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
// src/index.tsx
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { insertNode as _$
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { memo as _$memo } from "@opentui/solid";
|
|
12
|
-
import { createElement as _$createElement } from "@opentui/solid";
|
|
13
|
-
import { createMemo, createSignal, createEffect, onMount, onCleanup, Show, For, untrack } from "solid-js";
|
|
14
|
-
|
|
15
|
-
// src/_version.ts
|
|
16
|
-
var PLUGIN_VERSION = "1.6.2";
|
|
2
|
+
import { createTextNode as _$createTextNode2 } from "@opentui/solid";
|
|
3
|
+
import { memo as _$memo2 } from "@opentui/solid";
|
|
4
|
+
import { effect as _$effect2 } from "@opentui/solid";
|
|
5
|
+
import { insertNode as _$insertNode2 } from "@opentui/solid";
|
|
6
|
+
import { createComponent as _$createComponent2 } from "@opentui/solid";
|
|
7
|
+
import { insert as _$insert2 } from "@opentui/solid";
|
|
8
|
+
import { setProp as _$setProp2 } from "@opentui/solid";
|
|
9
|
+
import { createElement as _$createElement2 } from "@opentui/solid";
|
|
10
|
+
import { createMemo as createMemo2, createSignal as createSignal2, createEffect as createEffect2, onMount as onMount2, onCleanup as onCleanup2, Show as Show2, For, untrack as untrack2 } from "solid-js";
|
|
17
11
|
|
|
18
12
|
// src/balance-providers.ts
|
|
19
13
|
var BalanceError = class extends Error {
|
|
@@ -471,49 +465,7 @@ function detectLang() {
|
|
|
471
465
|
}
|
|
472
466
|
}
|
|
473
467
|
|
|
474
|
-
// src/
|
|
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();
|
|
468
|
+
// src/core/color.ts
|
|
517
469
|
function rgb(raw) {
|
|
518
470
|
if (typeof raw === "string" && raw.startsWith("#")) {
|
|
519
471
|
const h = raw.slice(1);
|
|
@@ -584,6 +536,48 @@ var FALLBACK = {
|
|
|
584
536
|
border: "#6B6B63"
|
|
585
537
|
};
|
|
586
538
|
var MAX_SAT = 0.28;
|
|
539
|
+
|
|
540
|
+
// src/core/format.ts
|
|
541
|
+
function charColumns(c) {
|
|
542
|
+
const code = c.codePointAt(0) ?? 0;
|
|
543
|
+
if (code < 32) return 0;
|
|
544
|
+
if (code < 127) return 1;
|
|
545
|
+
if (code < 160) return 0;
|
|
546
|
+
if (code >= 4352 && code <= 4447 || // Hangul Jamo
|
|
547
|
+
code >= 11904 && code <= 42191 || // CJK Radicals … Yi
|
|
548
|
+
code >= 44032 && code <= 55203 || // Hangul
|
|
549
|
+
code >= 63744 && code <= 64255 || // CJK Compat
|
|
550
|
+
code >= 65040 && code <= 65135 || // Vertical / Compat
|
|
551
|
+
code >= 65281 && code <= 65376 || // Fullwidth
|
|
552
|
+
code >= 65504 && code <= 65510 || // Fullwidth signs
|
|
553
|
+
code >= 127744 && code <= 128591 || // Misc Symbols (emoji)
|
|
554
|
+
code >= 131072 && code <= 262141)
|
|
555
|
+
return 2;
|
|
556
|
+
return 1;
|
|
557
|
+
}
|
|
558
|
+
function visualWidth(s) {
|
|
559
|
+
let w = 0;
|
|
560
|
+
for (const c of s) w += charColumns(c);
|
|
561
|
+
return w;
|
|
562
|
+
}
|
|
563
|
+
function visualPadEnd(s, cols) {
|
|
564
|
+
const pad = cols - visualWidth(s);
|
|
565
|
+
return pad > 0 ? s + " ".repeat(pad) : s;
|
|
566
|
+
}
|
|
567
|
+
function truncateVisual(s, maxCols) {
|
|
568
|
+
if (visualWidth(s) <= maxCols) return s;
|
|
569
|
+
let result = "", w = 0;
|
|
570
|
+
for (const c of s) {
|
|
571
|
+
const cw = charColumns(c);
|
|
572
|
+
if (w + cw > maxCols - 1) {
|
|
573
|
+
result += "\u2026";
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
result += c;
|
|
577
|
+
w += cw;
|
|
578
|
+
}
|
|
579
|
+
return result;
|
|
580
|
+
}
|
|
587
581
|
function progressBar(percent, width) {
|
|
588
582
|
const clamped = Math.max(0, Math.min(100, percent));
|
|
589
583
|
const filled = Math.round(clamped / 100 * width);
|
|
@@ -604,50 +598,6 @@ function fmtCost(n, symbol = "$", rate = 1) {
|
|
|
604
598
|
if (v >= 0.01) return symbol + v.toFixed(3);
|
|
605
599
|
return symbol + v.toFixed(4);
|
|
606
600
|
}
|
|
607
|
-
function estimateTokens(text) {
|
|
608
|
-
if (!text || text.length === 0) return 0;
|
|
609
|
-
let ascii = 0;
|
|
610
|
-
let cjk = 0;
|
|
611
|
-
for (const c of text) {
|
|
612
|
-
const code = c.codePointAt(0) ?? 0;
|
|
613
|
-
if (code >= 19968 && code <= 40959) cjk++;
|
|
614
|
-
else if (code >= 12352 && code <= 12543) cjk++;
|
|
615
|
-
else if (code >= 44032 && code <= 55203) cjk++;
|
|
616
|
-
else if (code >= 4352 && code <= 4607) cjk++;
|
|
617
|
-
else if (code >= 11904 && code <= 12031) cjk++;
|
|
618
|
-
else ascii++;
|
|
619
|
-
}
|
|
620
|
-
const trimmed = text.trimStart();
|
|
621
|
-
const strippedFence = trimmed.replace(/^\x60{3}\w*\s*\n?/, "");
|
|
622
|
-
const jsonLike = (strippedFence.startsWith("{") || strippedFence.startsWith("[")) && /"[^"]+"\s*:/.test(text);
|
|
623
|
-
const codeLike = !jsonLike && /```|^import |^export |^function |^const |^let |^var |^class |^interface |^type |^def |^fn |^pub |^use |^mod |^package /m.test(text);
|
|
624
|
-
const asciiPerToken = jsonLike ? 3.5 : codeLike ? 3.5 : 4;
|
|
625
|
-
return Math.max(1, Math.ceil(ascii / asciiPerToken + cjk / 1));
|
|
626
|
-
}
|
|
627
|
-
var BALANCE_POLL_MS = 5 * 60 * 1e3;
|
|
628
|
-
function convertBalance(target, targetRate, amount, from) {
|
|
629
|
-
if (from === target) return amount;
|
|
630
|
-
const fromRate = DEFAULT_RATES[from] ?? 1;
|
|
631
|
-
const usd = from === "USD" ? amount : amount / fromRate;
|
|
632
|
-
return target === "USD" ? usd : usd * targetRate;
|
|
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
|
-
}
|
|
647
|
-
function balanceSymbol(currency) {
|
|
648
|
-
const sym = CURRENCIES[currency];
|
|
649
|
-
return sym ?? currency + " ";
|
|
650
|
-
}
|
|
651
601
|
function fmtCompact(n) {
|
|
652
602
|
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
|
|
653
603
|
if (n >= 1e3) return (n / 1e3).toFixed(1) + "K";
|
|
@@ -656,25 +606,11 @@ function fmtCompact(n) {
|
|
|
656
606
|
function formatBalanceAmount(total) {
|
|
657
607
|
const n = parseFloat(total);
|
|
658
608
|
if (!Number.isFinite(n)) return total;
|
|
659
|
-
if (n === 0 || n >= 1) return n.toLocaleString("en-US", {
|
|
660
|
-
|
|
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;
|
|
609
|
+
if (n === 0 || n >= 1) return n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
610
|
+
return n.toLocaleString("en-US", { maximumFractionDigits: 6 });
|
|
677
611
|
}
|
|
612
|
+
|
|
613
|
+
// src/core/currency.ts
|
|
678
614
|
var CURRENCIES = {
|
|
679
615
|
USD: "$",
|
|
680
616
|
CNY: "\xA5",
|
|
@@ -691,6 +627,66 @@ var DEFAULT_RATES = {
|
|
|
691
627
|
GBP: 0.79,
|
|
692
628
|
KRW: 1350
|
|
693
629
|
};
|
|
630
|
+
function convertBalance(target, targetRate, amount, from) {
|
|
631
|
+
if (from === target) return amount;
|
|
632
|
+
const fromRate = DEFAULT_RATES[from] ?? 1;
|
|
633
|
+
const usd = from === "USD" ? amount : amount / fromRate;
|
|
634
|
+
return target === "USD" ? usd : usd * targetRate;
|
|
635
|
+
}
|
|
636
|
+
function balanceSymbol(currency) {
|
|
637
|
+
const sym = CURRENCIES[currency];
|
|
638
|
+
return sym ?? currency + " ";
|
|
639
|
+
}
|
|
640
|
+
function formatBalanceText(list, pref, rate) {
|
|
641
|
+
const native = pref ? list.find((x) => x.currency === pref) : void 0;
|
|
642
|
+
if (native) return balanceSymbol(native.currency) + formatBalanceAmount(native.total);
|
|
643
|
+
const base = list[0];
|
|
644
|
+
const baseAmt = parseFloat(base.total);
|
|
645
|
+
const converted = Number.isFinite(baseAmt) ? convertBalance(pref || base.currency, rate, baseAmt, base.currency) : baseAmt;
|
|
646
|
+
const shown = pref && base.currency !== pref ? converted.toLocaleString("en-US", { maximumFractionDigits: 2 }) : formatBalanceAmount(base.total);
|
|
647
|
+
return balanceSymbol(pref || base.currency) + shown;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// src/core/estimate.ts
|
|
651
|
+
function estimateTokens(text) {
|
|
652
|
+
if (!text || text.length === 0) return 0;
|
|
653
|
+
let ascii = 0;
|
|
654
|
+
let cjk = 0;
|
|
655
|
+
for (const c of text) {
|
|
656
|
+
const code = c.codePointAt(0) ?? 0;
|
|
657
|
+
if (code >= 19968 && code <= 40959) cjk++;
|
|
658
|
+
else if (code >= 12352 && code <= 12543) cjk++;
|
|
659
|
+
else if (code >= 44032 && code <= 55203) cjk++;
|
|
660
|
+
else if (code >= 4352 && code <= 4607) cjk++;
|
|
661
|
+
else if (code >= 11904 && code <= 12031) cjk++;
|
|
662
|
+
else ascii++;
|
|
663
|
+
}
|
|
664
|
+
const trimmed = text.trimStart();
|
|
665
|
+
const strippedFence = trimmed.replace(/^\x60{3}\w*\s*\n?/, "");
|
|
666
|
+
const jsonLike = (strippedFence.startsWith("{") || strippedFence.startsWith("[")) && /"[^"]+"\s*:/.test(text);
|
|
667
|
+
const codeLike = !jsonLike && /```|^import |^export |^function |^const |^let |^var |^class |^interface |^type |^def |^fn |^pub |^use |^mod |^package /m.test(text);
|
|
668
|
+
const asciiPerToken = jsonLike ? 3.5 : codeLike ? 3.5 : 4;
|
|
669
|
+
return Math.max(1, Math.ceil(ascii / asciiPerToken + cjk / 1));
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// src/panel/TokenCachePanel.tsx
|
|
673
|
+
import { createComponent as _$createComponent } from "@opentui/solid";
|
|
674
|
+
import { effect as _$effect } from "@opentui/solid";
|
|
675
|
+
import { createTextNode as _$createTextNode } from "@opentui/solid";
|
|
676
|
+
import { insertNode as _$insertNode } from "@opentui/solid";
|
|
677
|
+
import { insert as _$insert } from "@opentui/solid";
|
|
678
|
+
import { setProp as _$setProp } from "@opentui/solid";
|
|
679
|
+
import { use as _$use } from "@opentui/solid";
|
|
680
|
+
import { spread as _$spread } from "@opentui/solid";
|
|
681
|
+
import { mergeProps as _$mergeProps } from "@opentui/solid";
|
|
682
|
+
import { memo as _$memo } from "@opentui/solid";
|
|
683
|
+
import { createElement as _$createElement } from "@opentui/solid";
|
|
684
|
+
import { createMemo, createSignal, createEffect, onMount, onCleanup, Show, untrack } from "solid-js";
|
|
685
|
+
|
|
686
|
+
// src/_version.ts
|
|
687
|
+
var PLUGIN_VERSION = "1.7.0-beta.0";
|
|
688
|
+
|
|
689
|
+
// src/panel/TokenCachePanel.tsx
|
|
694
690
|
var MIN_PANEL_WIDTH = 20;
|
|
695
691
|
var DEFAULT_PANEL_WIDTH = 26;
|
|
696
692
|
var LABEL_GAP = 1;
|
|
@@ -1992,6 +1988,24 @@ function TokenCachePanel(props) {
|
|
|
1992
1988
|
return _el$;
|
|
1993
1989
|
})();
|
|
1994
1990
|
}
|
|
1991
|
+
|
|
1992
|
+
// src/index.tsx
|
|
1993
|
+
var DEBUG_LANG = typeof process !== "undefined" ? process.env?.CACHE_TUI_LANG : void 0;
|
|
1994
|
+
var INIT_LANG = DEBUG_LANG !== void 0 && LANG_META.some((m) => m.code === DEBUG_LANG) ? DEBUG_LANG : detectLang();
|
|
1995
|
+
var BALANCE_POLL_MS = 5 * 60 * 1e3;
|
|
1996
|
+
function findOpencodeKey(api, provider) {
|
|
1997
|
+
try {
|
|
1998
|
+
const provs = api.state.provider;
|
|
1999
|
+
const id = provider.id.toLowerCase();
|
|
2000
|
+
const hit = provs.find((p) => p.id.toLowerCase() === id) ?? provs.find((p) => p.id.toLowerCase().startsWith(id));
|
|
2001
|
+
if (!hit) return "";
|
|
2002
|
+
const k = typeof hit.key === "string" ? hit.key : "";
|
|
2003
|
+
if (k) return k;
|
|
2004
|
+
return typeof hit.options?.apiKey === "string" ? hit.options.apiKey : "";
|
|
2005
|
+
} catch {
|
|
2006
|
+
return "";
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
1995
2009
|
var PATH_CHROME = 2;
|
|
1996
2010
|
var HIDE_PATH_BELOW = 14;
|
|
1997
2011
|
function keyShortcut(api, command, fallback) {
|
|
@@ -2010,7 +2024,7 @@ function BottomStatusBar(props) {
|
|
|
2010
2024
|
const KV_PREFIX = "cache_panel";
|
|
2011
2025
|
const t = createT(() => props.signals.langCode());
|
|
2012
2026
|
const sid = props.sessionId;
|
|
2013
|
-
const stats =
|
|
2027
|
+
const stats = createMemo2(() => {
|
|
2014
2028
|
const id = sid;
|
|
2015
2029
|
if (!id) return null;
|
|
2016
2030
|
const msgs = props.api.state.session.messages(id);
|
|
@@ -2053,7 +2067,7 @@ function BottomStatusBar(props) {
|
|
|
2053
2067
|
write
|
|
2054
2068
|
};
|
|
2055
2069
|
});
|
|
2056
|
-
|
|
2070
|
+
createEffect2(() => {
|
|
2057
2071
|
if (!props.signals.autoBalance()) return;
|
|
2058
2072
|
const id = sid;
|
|
2059
2073
|
if (!id) return;
|
|
@@ -2084,7 +2098,7 @@ function BottomStatusBar(props) {
|
|
|
2084
2098
|
props.signals.setBalanceUnsupported(true);
|
|
2085
2099
|
}
|
|
2086
2100
|
});
|
|
2087
|
-
const pal =
|
|
2101
|
+
const pal = createMemo2(() => {
|
|
2088
2102
|
const th = props.api.theme.current;
|
|
2089
2103
|
const sat = (k, fb) => desaturateTo(th[k], MAX_SAT, fb);
|
|
2090
2104
|
return {
|
|
@@ -2095,45 +2109,45 @@ function BottomStatusBar(props) {
|
|
|
2095
2109
|
error: sat("error", FALLBACK.error)
|
|
2096
2110
|
};
|
|
2097
2111
|
});
|
|
2098
|
-
const hitColor =
|
|
2112
|
+
const hitColor = createMemo2(() => {
|
|
2099
2113
|
const r = stats()?.hitRate ?? -1;
|
|
2100
2114
|
if (r >= 85) return pal().success;
|
|
2101
2115
|
if (r >= 70) return pal().warning;
|
|
2102
2116
|
return pal().error;
|
|
2103
2117
|
});
|
|
2104
|
-
const trend =
|
|
2118
|
+
const trend = createMemo2(() => {
|
|
2105
2119
|
const s = stats();
|
|
2106
2120
|
if (!s || s.prevHitRate < 0 || s.hitRate < 0) return null;
|
|
2107
2121
|
const d = s.hitRate - s.prevHitRate;
|
|
2108
2122
|
return Math.abs(d) < 0.05 ? null : d;
|
|
2109
2123
|
});
|
|
2110
|
-
const balanceText =
|
|
2124
|
+
const balanceText = createMemo2(() => {
|
|
2111
2125
|
const s = props.signals.balanceState();
|
|
2112
2126
|
if (s.status === "ok" && s.data) return formatBalanceText(s.data, props.signals.balanceCurrency(), props.signals.exchangeRate());
|
|
2113
2127
|
if (s.status === "loading") return "\u2026";
|
|
2114
2128
|
if (s.status === "error") return "\u26A0";
|
|
2115
2129
|
return "-";
|
|
2116
2130
|
});
|
|
2117
|
-
const directory =
|
|
2131
|
+
const directory = createMemo2(() => {
|
|
2118
2132
|
try {
|
|
2119
2133
|
return props.api.state.path.directory;
|
|
2120
2134
|
} catch {
|
|
2121
2135
|
return "";
|
|
2122
2136
|
}
|
|
2123
2137
|
});
|
|
2124
|
-
const [termW, setTermW] =
|
|
2125
|
-
|
|
2138
|
+
const [termW, setTermW] = createSignal2(props.api.renderer.terminalWidth);
|
|
2139
|
+
createEffect2(() => {
|
|
2126
2140
|
const r = props.api.renderer;
|
|
2127
2141
|
if (typeof r.on !== "function" || typeof r.off !== "function") return;
|
|
2128
2142
|
const onResize = () => setTermW(props.api.renderer.terminalWidth);
|
|
2129
2143
|
r.on("resize", onResize);
|
|
2130
|
-
|
|
2144
|
+
onCleanup2(() => r.off("resize", onResize));
|
|
2131
2145
|
});
|
|
2132
|
-
|
|
2146
|
+
createEffect2(() => {
|
|
2133
2147
|
const timer = setInterval(() => setTermW(props.api.renderer.terminalWidth), 500);
|
|
2134
|
-
|
|
2148
|
+
onCleanup2(() => clearInterval(timer));
|
|
2135
2149
|
});
|
|
2136
|
-
const statsSegs =
|
|
2150
|
+
const statsSegs = createMemo2(() => {
|
|
2137
2151
|
const s = stats();
|
|
2138
2152
|
const hr = s && s.hitRate >= 0 ? (Math.floor(s.hitRate * 10) / 10).toFixed(1) + "%" : "--";
|
|
2139
2153
|
const segs = [{
|
|
@@ -2174,19 +2188,19 @@ function BottomStatusBar(props) {
|
|
|
2174
2188
|
});
|
|
2175
2189
|
return segs;
|
|
2176
2190
|
});
|
|
2177
|
-
const statsW =
|
|
2191
|
+
const statsW = createMemo2(() => {
|
|
2178
2192
|
let w = 0;
|
|
2179
2193
|
for (const sg of statsSegs()) w += visualWidth(sg.text);
|
|
2180
2194
|
return w;
|
|
2181
2195
|
});
|
|
2182
|
-
const sessionCost =
|
|
2196
|
+
const sessionCost = createMemo2(() => {
|
|
2183
2197
|
try {
|
|
2184
2198
|
return num(props.api.state.session.get(sid)?.cost);
|
|
2185
2199
|
} catch {
|
|
2186
2200
|
return 0;
|
|
2187
2201
|
}
|
|
2188
2202
|
});
|
|
2189
|
-
const usageText =
|
|
2203
|
+
const usageText = createMemo2(() => {
|
|
2190
2204
|
const id = sid;
|
|
2191
2205
|
if (!id) return "";
|
|
2192
2206
|
const msgs = props.api.state.session.messages(id);
|
|
@@ -2216,70 +2230,70 @@ function BottomStatusBar(props) {
|
|
|
2216
2230
|
const cost = sessionCost();
|
|
2217
2231
|
return cost > 0 ? context + " \xB7 " + fmtCost(cost) : context;
|
|
2218
2232
|
});
|
|
2219
|
-
const rightText =
|
|
2233
|
+
const rightText = createMemo2(() => {
|
|
2220
2234
|
const cmds = keyShortcut(props.api, "command.palette.show", "ctrl+p") + " commands";
|
|
2221
2235
|
const u = usageText();
|
|
2222
2236
|
if (u) return u + " " + cmds;
|
|
2223
2237
|
return keyShortcut(props.api, "agent.cycle", "") + " agents " + cmds;
|
|
2224
2238
|
});
|
|
2225
|
-
const rightW =
|
|
2226
|
-
const inputW =
|
|
2227
|
-
const dirDisplay =
|
|
2239
|
+
const rightW = createMemo2(() => visualWidth(rightText()));
|
|
2240
|
+
const inputW = createMemo2(() => termW() - (props.signals.sidebarVisible() ? 42 : 0) - 4);
|
|
2241
|
+
const dirDisplay = createMemo2(() => {
|
|
2228
2242
|
const avail = inputW() - statsW() - rightW() - PATH_CHROME;
|
|
2229
2243
|
if (avail < HIDE_PATH_BELOW) return "";
|
|
2230
2244
|
return truncateVisual(directory(), avail);
|
|
2231
2245
|
});
|
|
2232
|
-
const dirFallback =
|
|
2246
|
+
const dirFallback = createMemo2(() => {
|
|
2233
2247
|
const avail = inputW() - rightW() - PATH_CHROME;
|
|
2234
2248
|
if (avail < HIDE_PATH_BELOW) return "";
|
|
2235
2249
|
return truncateVisual(directory(), avail);
|
|
2236
2250
|
});
|
|
2237
|
-
|
|
2251
|
+
onMount2(() => {
|
|
2238
2252
|
try {
|
|
2239
2253
|
const v = props.api.kv.get(`${KV_PREFIX}.section.bottom`, true);
|
|
2240
2254
|
props.signals.setSectionBottom(v !== false);
|
|
2241
2255
|
} catch {
|
|
2242
2256
|
}
|
|
2243
2257
|
});
|
|
2244
|
-
return _$
|
|
2258
|
+
return _$createComponent2(Show2, {
|
|
2245
2259
|
get when() {
|
|
2246
2260
|
return props.signals.sectionBottom();
|
|
2247
2261
|
},
|
|
2248
2262
|
get fallback() {
|
|
2249
2263
|
return (() => {
|
|
2250
|
-
var _el$
|
|
2251
|
-
_$
|
|
2252
|
-
_$
|
|
2253
|
-
return _el$
|
|
2264
|
+
var _el$5 = _$createElement2("text");
|
|
2265
|
+
_$insert2(_el$5, dirFallback);
|
|
2266
|
+
_$effect2((_$p) => _$setProp2(_el$5, "fg", pal().muted, _$p));
|
|
2267
|
+
return _el$5;
|
|
2254
2268
|
})();
|
|
2255
2269
|
},
|
|
2256
2270
|
get children() {
|
|
2257
|
-
var _el$
|
|
2258
|
-
_$
|
|
2259
|
-
_$
|
|
2260
|
-
_$
|
|
2261
|
-
_$
|
|
2262
|
-
_$
|
|
2263
|
-
_$
|
|
2264
|
-
_$
|
|
2265
|
-
_$
|
|
2266
|
-
_$
|
|
2267
|
-
_$
|
|
2268
|
-
_$
|
|
2271
|
+
var _el$ = _$createElement2("box"), _el$2 = _$createElement2("text"), _el$3 = _$createElement2("box"), _el$4 = _$createElement2("text");
|
|
2272
|
+
_$insertNode2(_el$, _el$2);
|
|
2273
|
+
_$insertNode2(_el$, _el$3);
|
|
2274
|
+
_$setProp2(_el$, "marginLeft", 1);
|
|
2275
|
+
_$setProp2(_el$, "flexGrow", 1);
|
|
2276
|
+
_$setProp2(_el$, "flexShrink", 0);
|
|
2277
|
+
_$setProp2(_el$, "flexDirection", "row");
|
|
2278
|
+
_$setProp2(_el$, "justifyContent", "space-between");
|
|
2279
|
+
_$insert2(_el$2, dirDisplay);
|
|
2280
|
+
_$insertNode2(_el$3, _el$4);
|
|
2281
|
+
_$setProp2(_el$3, "flexDirection", "row");
|
|
2282
|
+
_$insert2(_el$4, _$createComponent2(For, {
|
|
2269
2283
|
get each() {
|
|
2270
2284
|
return statsSegs();
|
|
2271
2285
|
},
|
|
2272
2286
|
children: (sg) => (() => {
|
|
2273
|
-
var _el$
|
|
2274
|
-
_$
|
|
2275
|
-
_$
|
|
2287
|
+
var _el$6 = _$createElement2("span");
|
|
2288
|
+
_$insert2(_el$6, () => sg.text);
|
|
2289
|
+
_$effect2((_$p) => _$setProp2(_el$6, "style", {
|
|
2276
2290
|
fg: sg.color
|
|
2277
2291
|
}, _$p));
|
|
2278
|
-
return _el$
|
|
2292
|
+
return _el$6;
|
|
2279
2293
|
})()
|
|
2280
2294
|
}));
|
|
2281
|
-
_$
|
|
2282
|
-
return _el
|
|
2295
|
+
_$effect2((_$p) => _$setProp2(_el$2, "fg", pal().muted, _$p));
|
|
2296
|
+
return _el$;
|
|
2283
2297
|
}
|
|
2284
2298
|
});
|
|
2285
2299
|
}
|
|
@@ -2296,7 +2310,7 @@ function createSidebarSlot(api, signals) {
|
|
|
2296
2310
|
api.kv.set("cache_panel.session", "");
|
|
2297
2311
|
}
|
|
2298
2312
|
}
|
|
2299
|
-
return _$
|
|
2313
|
+
return _$createComponent2(TokenCachePanel, {
|
|
2300
2314
|
get theme() {
|
|
2301
2315
|
return ctx.theme.current;
|
|
2302
2316
|
},
|
|
@@ -2311,24 +2325,24 @@ function createSidebarSlot(api, signals) {
|
|
|
2311
2325
|
};
|
|
2312
2326
|
}
|
|
2313
2327
|
var tui = async (api) => {
|
|
2314
|
-
const [currencySymbol, setCurrencySymbol] =
|
|
2315
|
-
const [exchangeRate, setExchangeRate] =
|
|
2316
|
-
const [sectionDetail, setSectionDetail] =
|
|
2317
|
-
const [sectionModel, setSectionModel] =
|
|
2318
|
-
const [sectionDist, setSectionDist] =
|
|
2319
|
-
const [sectionSkills, setSectionSkills] =
|
|
2320
|
-
const [sectionBalance, setSectionBalance] =
|
|
2321
|
-
const [sectionBottom, setSectionBottom] =
|
|
2322
|
-
const [balanceRefresh, setBalanceRefresh] =
|
|
2323
|
-
const [balanceProviderId, setBalanceProviderId] =
|
|
2324
|
-
const [autoBalance, setAutoBalance] =
|
|
2325
|
-
const [balanceUnsupported, setBalanceUnsupported] =
|
|
2326
|
-
const [balanceCurrency, setBalanceCurrency] =
|
|
2327
|
-
const [borderVisible, setBorderVisible] =
|
|
2328
|
-
const [langCode, setLangCode] =
|
|
2329
|
-
const [overrideSessionId, setOverrideSessionId] =
|
|
2330
|
-
const [sidebarVisible, setSidebarVisible] =
|
|
2331
|
-
const [balanceState, setBalanceState] =
|
|
2328
|
+
const [currencySymbol, setCurrencySymbol] = createSignal2("$");
|
|
2329
|
+
const [exchangeRate, setExchangeRate] = createSignal2(1);
|
|
2330
|
+
const [sectionDetail, setSectionDetail] = createSignal2(true);
|
|
2331
|
+
const [sectionModel, setSectionModel] = createSignal2(true);
|
|
2332
|
+
const [sectionDist, setSectionDist] = createSignal2(true);
|
|
2333
|
+
const [sectionSkills, setSectionSkills] = createSignal2(true);
|
|
2334
|
+
const [sectionBalance, setSectionBalance] = createSignal2(true);
|
|
2335
|
+
const [sectionBottom, setSectionBottom] = createSignal2(true);
|
|
2336
|
+
const [balanceRefresh, setBalanceRefresh] = createSignal2(0);
|
|
2337
|
+
const [balanceProviderId, setBalanceProviderId] = createSignal2("deepseek");
|
|
2338
|
+
const [autoBalance, setAutoBalance] = createSignal2(true);
|
|
2339
|
+
const [balanceUnsupported, setBalanceUnsupported] = createSignal2(false);
|
|
2340
|
+
const [balanceCurrency, setBalanceCurrency] = createSignal2("");
|
|
2341
|
+
const [borderVisible, setBorderVisible] = createSignal2(true);
|
|
2342
|
+
const [langCode, setLangCode] = createSignal2(INIT_LANG);
|
|
2343
|
+
const [overrideSessionId, setOverrideSessionId] = createSignal2(void 0);
|
|
2344
|
+
const [sidebarVisible, setSidebarVisible] = createSignal2(false);
|
|
2345
|
+
const [balanceState, setBalanceState] = createSignal2({
|
|
2332
2346
|
status: "idle",
|
|
2333
2347
|
data: null,
|
|
2334
2348
|
lastFetch: 0
|
|
@@ -2376,7 +2390,7 @@ var tui = async (api) => {
|
|
|
2376
2390
|
order: 55,
|
|
2377
2391
|
slots: {
|
|
2378
2392
|
session_prompt(_ctx, input) {
|
|
2379
|
-
return _$
|
|
2393
|
+
return _$createComponent2(api.ui.Prompt, {
|
|
2380
2394
|
get sessionID() {
|
|
2381
2395
|
return input.session_id;
|
|
2382
2396
|
},
|
|
@@ -2390,11 +2404,11 @@ var tui = async (api) => {
|
|
|
2390
2404
|
return input.on_submit;
|
|
2391
2405
|
},
|
|
2392
2406
|
ref(r$) {
|
|
2393
|
-
var _ref$
|
|
2394
|
-
typeof _ref$
|
|
2407
|
+
var _ref$ = input.ref;
|
|
2408
|
+
typeof _ref$ === "function" ? _ref$(r$) : input.ref = r$;
|
|
2395
2409
|
},
|
|
2396
2410
|
get hint() {
|
|
2397
|
-
return _$
|
|
2411
|
+
return _$createComponent2(BottomStatusBar, {
|
|
2398
2412
|
api,
|
|
2399
2413
|
signals,
|
|
2400
2414
|
get sessionId() {
|
|
@@ -2488,9 +2502,9 @@ var tui = async (api) => {
|
|
|
2488
2502
|
});
|
|
2489
2503
|
}
|
|
2490
2504
|
};
|
|
2491
|
-
|
|
2505
|
+
createEffect2(() => {
|
|
2492
2506
|
void balanceRefresh();
|
|
2493
|
-
|
|
2507
|
+
untrack2(() => {
|
|
2494
2508
|
void pollBalance();
|
|
2495
2509
|
});
|
|
2496
2510
|
});
|
|
@@ -2507,16 +2521,16 @@ var tui = async (api) => {
|
|
|
2507
2521
|
const t = createT(() => langCode());
|
|
2508
2522
|
const current = api.kv.get(`${KV_PREFIX}.balance.${provider.id}.key`, "");
|
|
2509
2523
|
const masked = maskKey(current);
|
|
2510
|
-
dialog?.replace(() => _$
|
|
2524
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogPrompt, {
|
|
2511
2525
|
get title() {
|
|
2512
2526
|
return provider.name;
|
|
2513
2527
|
},
|
|
2514
2528
|
description: () => (() => {
|
|
2515
|
-
var _el$
|
|
2516
|
-
_$
|
|
2529
|
+
var _el$7 = _$createElement2("text");
|
|
2530
|
+
_$insert2(_el$7, () => t("balKeyPrompt", {
|
|
2517
2531
|
p: provider.name
|
|
2518
2532
|
}));
|
|
2519
|
-
return _el$
|
|
2533
|
+
return _el$7;
|
|
2520
2534
|
})(),
|
|
2521
2535
|
get placeholder() {
|
|
2522
2536
|
return provider.keyPlaceholder ?? "sk-...";
|
|
@@ -2556,7 +2570,7 @@ var tui = async (api) => {
|
|
|
2556
2570
|
name: "cache-currency"
|
|
2557
2571
|
},
|
|
2558
2572
|
onSelect: (dialog) => {
|
|
2559
|
-
dialog?.replace(() => _$
|
|
2573
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2560
2574
|
title: "Select Currency",
|
|
2561
2575
|
get options() {
|
|
2562
2576
|
return Object.entries(CURRENCIES).map(([code, sym]) => ({
|
|
@@ -2593,12 +2607,12 @@ var tui = async (api) => {
|
|
|
2593
2607
|
name: "cache-rate"
|
|
2594
2608
|
},
|
|
2595
2609
|
onSelect: (dialog) => {
|
|
2596
|
-
dialog?.replace(() => _$
|
|
2610
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogPrompt, {
|
|
2597
2611
|
title: "Exchange Rate",
|
|
2598
2612
|
description: () => (() => {
|
|
2599
|
-
var _el$
|
|
2600
|
-
_$
|
|
2601
|
-
return _el$
|
|
2613
|
+
var _el$8 = _$createElement2("text");
|
|
2614
|
+
_$insertNode2(_el$8, _$createTextNode2(`Enter the exchange rate from USD to your currency (e.g. 7.2 for CNY)`));
|
|
2615
|
+
return _el$8;
|
|
2602
2616
|
})(),
|
|
2603
2617
|
placeholder: "1.0",
|
|
2604
2618
|
get value() {
|
|
@@ -2646,7 +2660,7 @@ var tui = async (api) => {
|
|
|
2646
2660
|
border: t("secBorder")
|
|
2647
2661
|
};
|
|
2648
2662
|
const optTitle = (label, on) => `${visualPadEnd(label, 15)}[${on ? "ON" : "OFF"}]`;
|
|
2649
|
-
dialog?.replace(() => _$
|
|
2663
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2650
2664
|
get title() {
|
|
2651
2665
|
return t("secToggle");
|
|
2652
2666
|
},
|
|
@@ -2747,7 +2761,7 @@ var tui = async (api) => {
|
|
|
2747
2761
|
onSelect: (dialog) => {
|
|
2748
2762
|
const t = createT(() => langCode());
|
|
2749
2763
|
const cur = langCode();
|
|
2750
|
-
dialog?.replace(() => _$
|
|
2764
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2751
2765
|
get title() {
|
|
2752
2766
|
return t("langTitle");
|
|
2753
2767
|
},
|
|
@@ -2780,7 +2794,7 @@ var tui = async (api) => {
|
|
|
2780
2794
|
const current = signals.balanceProviderId();
|
|
2781
2795
|
const auto = signals.autoBalance();
|
|
2782
2796
|
const autoLabel = `${t("autoSwitchOpt")} [${auto ? "ON" : "OFF"}]`;
|
|
2783
|
-
dialog?.replace(() => _$
|
|
2797
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2784
2798
|
get title() {
|
|
2785
2799
|
return t("balProvTitle");
|
|
2786
2800
|
},
|
|
@@ -2834,7 +2848,7 @@ var tui = async (api) => {
|
|
|
2834
2848
|
},
|
|
2835
2849
|
onSelect: (dialog) => {
|
|
2836
2850
|
const t = createT(() => langCode());
|
|
2837
|
-
dialog?.replace(() => _$
|
|
2851
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2838
2852
|
get title() {
|
|
2839
2853
|
return t("balSelectTitle");
|
|
2840
2854
|
},
|
|
@@ -2976,7 +2990,7 @@ var tui = async (api) => {
|
|
|
2976
2990
|
description: ""
|
|
2977
2991
|
});
|
|
2978
2992
|
const currentIdx = currentSid ? options.findIndex((o) => o.value === currentSid) : -1;
|
|
2979
|
-
dialog?.replace(() => _$
|
|
2993
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogSelect, {
|
|
2980
2994
|
get title() {
|
|
2981
2995
|
return t("subSelectTitle");
|
|
2982
2996
|
},
|
|
@@ -3005,14 +3019,14 @@ var tui = async (api) => {
|
|
|
3005
3019
|
}));
|
|
3006
3020
|
} else {
|
|
3007
3021
|
const t = createT(() => langCode());
|
|
3008
|
-
dialog?.replace(() => _$
|
|
3022
|
+
dialog?.replace(() => _$createComponent2(api.ui.DialogPrompt, {
|
|
3009
3023
|
get title() {
|
|
3010
|
-
return _$
|
|
3024
|
+
return _$memo2(() => !!signals.overrideSessionId())() ? t("subSwitchTitle") : t("subViewTitle");
|
|
3011
3025
|
},
|
|
3012
3026
|
description: () => (() => {
|
|
3013
|
-
var _el$
|
|
3014
|
-
_$
|
|
3015
|
-
return _el$
|
|
3027
|
+
var _el$0 = _$createElement2("text");
|
|
3028
|
+
_$insert2(_el$0, () => t("subNoFound"));
|
|
3029
|
+
return _el$0;
|
|
3016
3030
|
})(),
|
|
3017
3031
|
placeholder: "ses_...",
|
|
3018
3032
|
get value() {
|