clixad 0.0.1-beta.6 → 0.0.1-beta.7
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/dist/clixad.mjs +192 -62
- package/package.json +1 -1
package/dist/clixad.mjs
CHANGED
|
@@ -1504,6 +1504,10 @@ function centered(rendered, visibleW, colW) {
|
|
|
1504
1504
|
const lead = Math.max(0, Math.floor((colW - visibleW) / 2));
|
|
1505
1505
|
return cell(" ".repeat(lead) + rendered, lead + visibleW);
|
|
1506
1506
|
}
|
|
1507
|
+
function bannerTip(index) {
|
|
1508
|
+
const i = index ?? Math.floor(Math.random() * BANNER_TIPS.length);
|
|
1509
|
+
return BANNER_TIPS[(i % BANNER_TIPS.length + BANNER_TIPS.length) % BANNER_TIPS.length];
|
|
1510
|
+
}
|
|
1507
1511
|
function earnedLabel(opts) {
|
|
1508
1512
|
return `$${opts.earnedUsdToday.toFixed(2)}/$${opts.maxRewardUsd.toFixed(2)} today`;
|
|
1509
1513
|
}
|
|
@@ -1515,14 +1519,19 @@ function welcomeBanner(opts) {
|
|
|
1515
1519
|
const cwd = opts.cwd.replace(homedir5(), "~").replace(/\\/g, "/");
|
|
1516
1520
|
const welcome = opts.name ? `Welcome back, ${truncate(opts.name, 18)}!` : "Welcome to Clixad!";
|
|
1517
1521
|
const duck = duckLines();
|
|
1518
|
-
const model = truncate(opts.model, leftW - 4);
|
|
1519
1522
|
const home = truncate(cwd, leftW);
|
|
1523
|
+
const hint = bannerTip(opts.tipIndex);
|
|
1524
|
+
const hintDesc = truncate(hint.desc, Math.max(1, leftW - 3 - hint.key.length));
|
|
1520
1525
|
const left = [
|
|
1521
1526
|
centered(BOLD + TEXT + welcome + R2, welcome.length, leftW),
|
|
1522
1527
|
cell("", 0),
|
|
1523
1528
|
...duck.map((d) => centered(d, DUCK_W, leftW)),
|
|
1524
1529
|
cell("", 0),
|
|
1525
|
-
centered(
|
|
1530
|
+
centered(
|
|
1531
|
+
MANGO + "\u25C6 " + R2 + BOLD + TEXT + hint.key + R2 + FAINT + " " + hintDesc + R2,
|
|
1532
|
+
2 + hint.key.length + 1 + hintDesc.length,
|
|
1533
|
+
leftW
|
|
1534
|
+
),
|
|
1526
1535
|
centered(FAINT + home + R2, home.length, leftW)
|
|
1527
1536
|
];
|
|
1528
1537
|
const tip = (k, d) => cell(MANGO + k + R2 + FAINT + " " + d + R2, k.length + 1 + d.length);
|
|
@@ -1553,10 +1562,11 @@ function welcomeBanner(opts) {
|
|
|
1553
1562
|
}
|
|
1554
1563
|
function compactBanner(opts) {
|
|
1555
1564
|
const welcome = opts.name ? `Welcome back, ${opts.name}!` : "Welcome to Clixad!";
|
|
1565
|
+
const hint = bannerTip(opts.tipIndex);
|
|
1556
1566
|
return duckLines().map((d) => " " + d).join("\n") + `
|
|
1557
1567
|
|
|
1558
1568
|
${BOLD}${TEXT}${welcome}${R2}
|
|
1559
|
-
${MANGO}\u25C6${R2} ${
|
|
1569
|
+
${MANGO}\u25C6${R2} ${BOLD}${TEXT}${hint.key}${R2} ${FAINT}${hint.desc}${R2} ${FAINT}\xB7${R2} ${opts.balance.toLocaleString("en-US")} credits
|
|
1560
1570
|
`;
|
|
1561
1571
|
}
|
|
1562
1572
|
function clearScreen() {
|
|
@@ -1568,7 +1578,7 @@ function clearScreen() {
|
|
|
1568
1578
|
function visibleLength(s) {
|
|
1569
1579
|
return s.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
1570
1580
|
}
|
|
1571
|
-
var R2, BOLD, fg, bg, MANGO, TEXT, MUTED, FAINT, PAL, DUCK, DUCK_W, cell, padTo, truncate, MIN_BANNER_WIDTH, RIGHT_MAX;
|
|
1581
|
+
var R2, BOLD, fg, bg, MANGO, TEXT, MUTED, FAINT, PAL, DUCK, DUCK_W, cell, padTo, truncate, BANNER_TIPS, MIN_BANNER_WIDTH, RIGHT_MAX;
|
|
1572
1582
|
var init_banner = __esm({
|
|
1573
1583
|
"src/banner.ts"() {
|
|
1574
1584
|
"use strict";
|
|
@@ -1610,6 +1620,15 @@ var init_banner = __esm({
|
|
|
1610
1620
|
cell = (text, w) => ({ text, w });
|
|
1611
1621
|
padTo = (c2, width) => (c2?.text ?? "") + " ".repeat(Math.max(0, width - (c2?.w ?? 0)));
|
|
1612
1622
|
truncate = (s, max) => s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
1623
|
+
BANNER_TIPS = [
|
|
1624
|
+
{ key: "/init", desc: "make a CLIXAD.md" },
|
|
1625
|
+
{ key: "shift+tab", desc: "switch mode" },
|
|
1626
|
+
{ key: "@file", desc: "add a file to context" },
|
|
1627
|
+
{ key: "ctrl+o", desc: "expand tool output" },
|
|
1628
|
+
{ key: "esc", desc: "stop the current turn" },
|
|
1629
|
+
{ key: "/compact", desc: "free up context" },
|
|
1630
|
+
{ key: "/earn", desc: "top up credits" }
|
|
1631
|
+
];
|
|
1613
1632
|
MIN_BANNER_WIDTH = 66;
|
|
1614
1633
|
RIGHT_MAX = 34;
|
|
1615
1634
|
}
|
|
@@ -2158,6 +2177,45 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2158
2177
|
function lineCount(text, cols) {
|
|
2159
2178
|
return text.split("\n").reduce((n, line2) => n + Math.max(1, Math.ceil(visibleLength(line2) / Math.max(1, cols))), 0);
|
|
2160
2179
|
}
|
|
2180
|
+
function tailRows(text, cols, max) {
|
|
2181
|
+
if (max <= 0) return "";
|
|
2182
|
+
const width = Math.max(1, cols);
|
|
2183
|
+
const lines = text.split("\n");
|
|
2184
|
+
const kept = [];
|
|
2185
|
+
let used = 0;
|
|
2186
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
2187
|
+
const line2 = lines[i];
|
|
2188
|
+
const h = Math.max(1, Math.ceil(visibleLength(line2) / width));
|
|
2189
|
+
if (used + h <= max) {
|
|
2190
|
+
kept.unshift(line2);
|
|
2191
|
+
used += h;
|
|
2192
|
+
continue;
|
|
2193
|
+
}
|
|
2194
|
+
const room = max - used;
|
|
2195
|
+
if (room > 0) kept.unshift(line2.slice(-(room * width)));
|
|
2196
|
+
break;
|
|
2197
|
+
}
|
|
2198
|
+
return kept.join("\n");
|
|
2199
|
+
}
|
|
2200
|
+
function headRows(text, cols, max) {
|
|
2201
|
+
if (max <= 0) return "";
|
|
2202
|
+
const width = Math.max(1, cols);
|
|
2203
|
+
const lines = text.split("\n");
|
|
2204
|
+
const kept = [];
|
|
2205
|
+
let used = 0;
|
|
2206
|
+
for (const line2 of lines) {
|
|
2207
|
+
const h = Math.max(1, Math.ceil(visibleLength(line2) / width));
|
|
2208
|
+
if (used + h <= max) {
|
|
2209
|
+
kept.push(line2);
|
|
2210
|
+
used += h;
|
|
2211
|
+
continue;
|
|
2212
|
+
}
|
|
2213
|
+
const room = max - used;
|
|
2214
|
+
if (room > 0) kept.push(line2.slice(0, room * width));
|
|
2215
|
+
break;
|
|
2216
|
+
}
|
|
2217
|
+
return kept.join("\n");
|
|
2218
|
+
}
|
|
2161
2219
|
function entryHeight(entry, cols) {
|
|
2162
2220
|
const margin = entry.kind === "banner" ? 0 : 1;
|
|
2163
2221
|
switch (entry.kind) {
|
|
@@ -2204,7 +2262,7 @@ function EntryView({ entry }) {
|
|
|
2204
2262
|
) });
|
|
2205
2263
|
}
|
|
2206
2264
|
}
|
|
2207
|
-
var MANGO3, MANGO_BRIGHT;
|
|
2265
|
+
var MANGO3, MANGO_BRIGHT, SLATE, MODE_STYLE;
|
|
2208
2266
|
var init_views = __esm({
|
|
2209
2267
|
"src/tui/views.tsx"() {
|
|
2210
2268
|
"use strict";
|
|
@@ -2212,6 +2270,12 @@ var init_views = __esm({
|
|
|
2212
2270
|
init_markdown();
|
|
2213
2271
|
MANGO3 = "#f5b841";
|
|
2214
2272
|
MANGO_BRIGHT = "#ffcf6b";
|
|
2273
|
+
SLATE = "#8b98ae";
|
|
2274
|
+
MODE_STYLE = {
|
|
2275
|
+
normal: { color: SLATE, glyph: "\u23F5" },
|
|
2276
|
+
acceptEdits: { color: "#7ee787", glyph: "\u23F5\u23F5" },
|
|
2277
|
+
plan: { color: "#79c0ff", glyph: "\u23F8" }
|
|
2278
|
+
};
|
|
2215
2279
|
}
|
|
2216
2280
|
});
|
|
2217
2281
|
|
|
@@ -2289,13 +2353,34 @@ function App({ client, config, wallet, session, initialTask }) {
|
|
|
2289
2353
|
const lastOutputRef = useRef("");
|
|
2290
2354
|
const runningToolRef = useRef(null);
|
|
2291
2355
|
const pendingTaskRef = useRef(null);
|
|
2356
|
+
const deltaBufRef = useRef("");
|
|
2357
|
+
const deltaTimerRef = useRef(null);
|
|
2292
2358
|
const sponsorRef = useRef(sponsorSource());
|
|
2293
2359
|
const sponsorIdxRef = useRef(0);
|
|
2294
2360
|
const sponsorPrevRef = useRef(void 0);
|
|
2295
2361
|
const tallyRef = useRef(createTally());
|
|
2362
|
+
const heightCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
2296
2363
|
const push = useCallback((e) => {
|
|
2297
2364
|
setEntries((prev) => [...prev, { ...e, id: idRef.current++ }]);
|
|
2298
2365
|
}, []);
|
|
2366
|
+
const flushDelta = useCallback(() => {
|
|
2367
|
+
if (deltaTimerRef.current) {
|
|
2368
|
+
clearTimeout(deltaTimerRef.current);
|
|
2369
|
+
deltaTimerRef.current = null;
|
|
2370
|
+
}
|
|
2371
|
+
const buffered = deltaBufRef.current;
|
|
2372
|
+
if (!buffered) return;
|
|
2373
|
+
deltaBufRef.current = "";
|
|
2374
|
+
setLive((l) => ({ ...l ?? { text: "" }, text: (l?.text ?? "") + buffered }));
|
|
2375
|
+
}, []);
|
|
2376
|
+
const dropDelta = useCallback(() => {
|
|
2377
|
+
if (deltaTimerRef.current) {
|
|
2378
|
+
clearTimeout(deltaTimerRef.current);
|
|
2379
|
+
deltaTimerRef.current = null;
|
|
2380
|
+
}
|
|
2381
|
+
deltaBufRef.current = "";
|
|
2382
|
+
}, []);
|
|
2383
|
+
useEffect(() => dropDelta, [dropDelta]);
|
|
2299
2384
|
useEffect(() => {
|
|
2300
2385
|
const files = contextRef.current.files;
|
|
2301
2386
|
if (files.length) push({ kind: "notice", text: ` context: ${files.join(", ")}` });
|
|
@@ -2351,10 +2436,13 @@ function App({ client, config, wallet, session, initialTask }) {
|
|
|
2351
2436
|
}, []);
|
|
2352
2437
|
const handleEvent = useCallback(
|
|
2353
2438
|
(event) => {
|
|
2439
|
+
if (event.type === "delta") {
|
|
2440
|
+
deltaBufRef.current += event.text;
|
|
2441
|
+
if (!deltaTimerRef.current) deltaTimerRef.current = setTimeout(flushDelta, DELTA_FLUSH_MS);
|
|
2442
|
+
return;
|
|
2443
|
+
}
|
|
2444
|
+
flushDelta();
|
|
2354
2445
|
switch (event.type) {
|
|
2355
|
-
case "delta":
|
|
2356
|
-
setLive((l) => ({ ...l ?? { text: "" }, text: (l?.text ?? "") + event.text }));
|
|
2357
|
-
return;
|
|
2358
2446
|
case "message":
|
|
2359
2447
|
push({ kind: "assistant", text: event.content });
|
|
2360
2448
|
setLive((l) => ({ ...l ?? { text: "" }, text: "" }));
|
|
@@ -2394,7 +2482,7 @@ function App({ client, config, wallet, session, initialTask }) {
|
|
|
2394
2482
|
return;
|
|
2395
2483
|
}
|
|
2396
2484
|
},
|
|
2397
|
-
[cols, push]
|
|
2485
|
+
[cols, flushDelta, push]
|
|
2398
2486
|
);
|
|
2399
2487
|
const runTurn2 = useCallback(
|
|
2400
2488
|
async (task) => {
|
|
@@ -2474,12 +2562,13 @@ function App({ client, config, wallet, session, initialTask }) {
|
|
|
2474
2562
|
}
|
|
2475
2563
|
} finally {
|
|
2476
2564
|
abortRef.current = null;
|
|
2565
|
+
dropDelta();
|
|
2477
2566
|
setLive(null);
|
|
2478
2567
|
setBusy(false);
|
|
2479
2568
|
setSponsor(null);
|
|
2480
2569
|
}
|
|
2481
2570
|
},
|
|
2482
|
-
[client, contextWindow, handleEvent, model, nextSponsor, permit, push, root, session?.title]
|
|
2571
|
+
[client, contextWindow, dropDelta, handleEvent, model, nextSponsor, permit, push, root, session?.title]
|
|
2483
2572
|
);
|
|
2484
2573
|
const stopCurrent = useCallback(() => {
|
|
2485
2574
|
abortRef.current?.abort();
|
|
@@ -2860,62 +2949,95 @@ function App({ client, config, wallet, session, initialTask }) {
|
|
|
2860
2949
|
const elapsed = busy && startedAt ? Math.floor((Date.now() - startedAt) / 1e3) : 0;
|
|
2861
2950
|
const spinner = SPINNER[tick % SPINNER.length];
|
|
2862
2951
|
const sponsorLine = busy && sponsor ? sponsorText(sponsor, cols) : null;
|
|
2863
|
-
const
|
|
2864
|
-
const
|
|
2865
|
-
|
|
2952
|
+
const viewport = Math.max(6, rows - 1);
|
|
2953
|
+
const inputRows = Math.max(1, Math.min(MAX_INPUT_ROWS, editor.lines.length));
|
|
2954
|
+
const inputFrom = windowStart(editor.row, editor.lines.length, inputRows);
|
|
2955
|
+
const inputBoxHeight = 2 + inputRows;
|
|
2956
|
+
const chromeHeight = inputBoxHeight + 2 + (sponsorLine ? 1 : 0);
|
|
2957
|
+
let budget = Math.max(0, viewport - chromeHeight - menu.length);
|
|
2958
|
+
const PICKER_CHROME = 8;
|
|
2959
|
+
const pickerRows = picker ? Math.max(1, Math.min(MAX_PICKER_ROWS, picker.items.length, budget - PICKER_CHROME)) : 0;
|
|
2960
|
+
const pickerFrom = picker ? windowStart(pickerSel, picker.items.length, pickerRows) : 0;
|
|
2961
|
+
const pickerItems = picker ? picker.items.slice(pickerFrom, pickerFrom + pickerRows) : [];
|
|
2962
|
+
const pickerHeight = picker ? pickerItems.length + PICKER_CHROME : 0;
|
|
2963
|
+
const pickerLabelW = picker ? picker.items.reduce((w, i) => Math.max(w, i.label.length), 0) : 0;
|
|
2964
|
+
budget -= pickerHeight;
|
|
2965
|
+
const ASK_CHROME = 4;
|
|
2966
|
+
const askSummaryRows = ask2 ? lineCount(ask2.req.summary, cols) : 0;
|
|
2967
|
+
const askPreview = ask2?.req.preview ? headRows(ask2.req.preview, cols, Math.max(1, budget - ASK_CHROME - askSummaryRows)) : "";
|
|
2968
|
+
const askHeight = ask2 ? askSummaryRows + lineCount(askPreview, cols) * (askPreview ? 1 : 0) + ASK_CHROME : 0;
|
|
2969
|
+
budget -= askHeight;
|
|
2970
|
+
const busyHeight = busy ? 2 : 0;
|
|
2971
|
+
budget -= busyHeight;
|
|
2972
|
+
const liveRaw = [
|
|
2973
|
+
// Trailing blank lines are rows the clamp would spend on nothing, and a
|
|
2974
|
+
// streamed answer ends on one more often than not.
|
|
2975
|
+
(live?.text ?? "").replace(/\n+$/, ""),
|
|
2866
2976
|
live?.tool ? `\u23FA ${live.tool.name} ${live.tool.summary}` : "",
|
|
2867
2977
|
live?.tool?.output ?? ""
|
|
2868
2978
|
].filter(Boolean).join("\n");
|
|
2869
|
-
const
|
|
2870
|
-
const pickerHeight = picker ? picker.items.length + 8 : 0;
|
|
2871
|
-
const pickerLabelW = picker ? picker.items.reduce((w, i) => Math.max(w, i.label.length), 0) : 0;
|
|
2872
|
-
const inputBoxHeight = 2 + editor.lines.length;
|
|
2873
|
-
const chromeHeight = inputBoxHeight + 2 + (sponsorLine ? 1 : 0);
|
|
2979
|
+
const liveBlock = tailRows(liveRaw, cols, Math.max(0, budget - 1));
|
|
2874
2980
|
const liveHeight = liveBlock ? lineCount(liveBlock, cols) + 1 : 0;
|
|
2875
|
-
const
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2981
|
+
const printed = useMemo(() => {
|
|
2982
|
+
const cache = heightCacheRef.current;
|
|
2983
|
+
return entries.reduce((n, e) => {
|
|
2984
|
+
const key = `${e.id}:${cols}`;
|
|
2985
|
+
let h = cache.get(key);
|
|
2986
|
+
if (h === void 0) {
|
|
2987
|
+
h = entryHeight(e, cols);
|
|
2988
|
+
cache.set(key, h);
|
|
2989
|
+
}
|
|
2990
|
+
return n + h;
|
|
2991
|
+
}, 0);
|
|
2992
|
+
}, [entries, cols]);
|
|
2993
|
+
const used = chromeHeight + menu.length + pickerHeight + askHeight + busyHeight + liveHeight;
|
|
2994
|
+
const spacer = Math.max(0, viewport - printed - used);
|
|
2881
2995
|
const labelW = menu.reduce((w, c2) => Math.max(w, c2.label.length), 0);
|
|
2882
2996
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
2883
2997
|
/* @__PURE__ */ jsx2(Static, { items: entries, children: (entry) => /* @__PURE__ */ jsx2(EntryView, { entry }, entry.id) }),
|
|
2884
2998
|
spacer > 0 ? /* @__PURE__ */ jsx2(Box2, { height: spacer }) : null,
|
|
2885
2999
|
liveBlock ? /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { children: liveBlock }) }) : null,
|
|
3000
|
+
busy ? /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
|
|
3001
|
+
/* @__PURE__ */ jsxs2(Text2, { color: MANGO3, children: [
|
|
3002
|
+
spinner,
|
|
3003
|
+
" "
|
|
3004
|
+
] }),
|
|
3005
|
+
/* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
3006
|
+
busyLabel,
|
|
3007
|
+
" ",
|
|
3008
|
+
elapsed,
|
|
3009
|
+
"s \xB7 esc to stop"
|
|
3010
|
+
] })
|
|
3011
|
+
] }) : null,
|
|
2886
3012
|
ask2 ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2887
3013
|
/* @__PURE__ */ jsx2(Text2, { bold: true, color: "yellow", children: ask2.req.summary }),
|
|
2888
|
-
|
|
3014
|
+
askPreview ? /* @__PURE__ */ jsx2(Text2, { children: askPreview }) : null,
|
|
2889
3015
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "[y/\u23CE] once \xB7 [a] always \xB7 [n] no \xB7 esc cancels" })
|
|
2890
3016
|
] }) : null,
|
|
2891
3017
|
picker ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: MANGO3, paddingX: 1, children: [
|
|
2892
3018
|
/* @__PURE__ */ jsx2(Text2, { bold: true, color: MANGO_BRIGHT, children: picker.title }),
|
|
2893
3019
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: picker.subtitle }),
|
|
2894
3020
|
/* @__PURE__ */ jsx2(Box2, { height: 1 }),
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
3021
|
+
pickerItems.map((item, i) => {
|
|
3022
|
+
const index = pickerFrom + i;
|
|
3023
|
+
return /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
3024
|
+
/* @__PURE__ */ jsxs2(Text2, { color: index === pickerSel ? MANGO_BRIGHT : void 0, bold: index === pickerSel, children: [
|
|
3025
|
+
index === pickerSel ? "\u276F " : " ",
|
|
3026
|
+
`${index + 1}. `,
|
|
3027
|
+
item.label.padEnd(pickerLabelW + 2)
|
|
3028
|
+
] }),
|
|
3029
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: item.hint }),
|
|
3030
|
+
item.current ? /* @__PURE__ */ jsx2(Text2, { color: "green", children: " \u2190 current" }) : null
|
|
3031
|
+
] }, item.value);
|
|
3032
|
+
}),
|
|
2904
3033
|
/* @__PURE__ */ jsx2(Box2, { height: 1 }),
|
|
2905
3034
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "\u2191\u2193 choose \xB7 1-9 jump straight to a row \xB7 \u23CE confirm \xB7 esc cancel" })
|
|
2906
3035
|
] }) : null,
|
|
2907
3036
|
/* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginTop: 1, children: [
|
|
2908
3037
|
sponsorLine ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: sponsorLine }) : null,
|
|
2909
|
-
/* @__PURE__ */ jsxs2(Box2, { borderStyle: "round", borderColor: busy ?
|
|
2910
|
-
/* @__PURE__ */ jsx2(Text2, { color: MANGO_BRIGHT, children: "\u276F " }),
|
|
2911
|
-
busy ? /* @__PURE__ */
|
|
2912
|
-
spinner,
|
|
2913
|
-
" ",
|
|
2914
|
-
busyLabel,
|
|
2915
|
-
" ",
|
|
2916
|
-
elapsed,
|
|
2917
|
-
"s \xB7 esc to stop"
|
|
2918
|
-
] }) : /* @__PURE__ */ jsx2(Text2, { children: renderInput(editor) })
|
|
3038
|
+
/* @__PURE__ */ jsxs2(Box2, { borderStyle: "round", borderColor: busy ? SLATE : MANGO3, paddingX: 1, children: [
|
|
3039
|
+
/* @__PURE__ */ jsx2(Text2, { color: busy ? SLATE : MANGO_BRIGHT, children: "\u276F " }),
|
|
3040
|
+
busy ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: toText(editor) }) : /* @__PURE__ */ jsx2(Text2, { children: renderInput(editor, inputFrom, inputRows) })
|
|
2919
3041
|
] }),
|
|
2920
3042
|
menu.map((item, i) => /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
2921
3043
|
/* @__PURE__ */ jsxs2(Text2, { color: i === sel ? MANGO_BRIGHT : MANGO3, bold: i === sel, children: [
|
|
@@ -2924,17 +3046,20 @@ function App({ client, config, wallet, session, initialTask }) {
|
|
|
2924
3046
|
] }),
|
|
2925
3047
|
/* @__PURE__ */ jsx2(Text2, { dimColor: i !== sel, children: item.hint })
|
|
2926
3048
|
] }, item.value)),
|
|
2927
|
-
/* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
3049
|
+
quitHint || menu.length > 0 ? /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
2928
3050
|
" ",
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
3051
|
+
quitHint ? "press ctrl+c again to quit" : "\u2191\u2193 choose \xB7 \u23CE run \xB7 tab complete \xB7 esc close"
|
|
3052
|
+
] }) : /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
3053
|
+
/* @__PURE__ */ jsx2(Text2, { color: MODE_STYLE[mode].color, bold: true, children: ` ${MODE_STYLE[mode].glyph} ${MODE_LABEL[mode]}` }),
|
|
3054
|
+
/* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
3055
|
+
" ",
|
|
3056
|
+
statusLine({
|
|
3057
|
+
model,
|
|
3058
|
+
balance,
|
|
3059
|
+
spent,
|
|
3060
|
+
minutes: (Date.now() - runStartedAtRef.current) / 6e4
|
|
3061
|
+
})
|
|
3062
|
+
] })
|
|
2938
3063
|
] })
|
|
2939
3064
|
] })
|
|
2940
3065
|
] });
|
|
@@ -2951,9 +3076,10 @@ function sleep2(ms, signal) {
|
|
|
2951
3076
|
signal.addEventListener("abort", done, { once: true });
|
|
2952
3077
|
});
|
|
2953
3078
|
}
|
|
2954
|
-
function renderInput(state) {
|
|
2955
|
-
return state.lines.map((line2,
|
|
2956
|
-
const
|
|
3079
|
+
function renderInput(state, from, rows) {
|
|
3080
|
+
return state.lines.slice(from, from + rows).map((line2, i) => {
|
|
3081
|
+
const row = from + i;
|
|
3082
|
+
const prefix = i === 0 ? "" : "\n";
|
|
2957
3083
|
if (row !== state.row) return /* @__PURE__ */ jsx2(Text2, { children: prefix + line2 }, row);
|
|
2958
3084
|
const before = line2.slice(0, state.col);
|
|
2959
3085
|
const at = line2.slice(state.col, state.col + 1) || " ";
|
|
@@ -2966,19 +3092,20 @@ function renderInput(state) {
|
|
|
2966
3092
|
});
|
|
2967
3093
|
}
|
|
2968
3094
|
function statusLine(o) {
|
|
2969
|
-
if (o.quitHint) return "press ctrl+c again to quit";
|
|
2970
|
-
if (o.menu) return "\u2191\u2193 choose \xB7 \u23CE run \xB7 tab complete \xB7 esc close";
|
|
2971
3095
|
const burn = o.spent > 0 && o.minutes >= 1 ? `${Math.round(o.spent / o.minutes).toLocaleString("en-US")} cr/min` : void 0;
|
|
2972
3096
|
const parts = [
|
|
2973
3097
|
o.model,
|
|
2974
3098
|
`${o.balance.toLocaleString("en-US")} cr`,
|
|
2975
|
-
o.spent > 0 ? `\u2212${o.spent.toLocaleString("en-US")}
|
|
3099
|
+
o.spent > 0 ? `\u2212${o.spent.toLocaleString("en-US")}` : void 0,
|
|
2976
3100
|
burn,
|
|
2977
|
-
MODE_LABEL[o.mode],
|
|
2978
3101
|
"/help"
|
|
2979
3102
|
].filter(Boolean);
|
|
2980
3103
|
return parts.join(" \xB7 ");
|
|
2981
3104
|
}
|
|
3105
|
+
function windowStart(sel, total, size) {
|
|
3106
|
+
if (total <= size) return 0;
|
|
3107
|
+
return Math.max(0, Math.min(total - size, sel - Math.floor(size / 2)));
|
|
3108
|
+
}
|
|
2982
3109
|
function toEditorKey(ch, key) {
|
|
2983
3110
|
const name = key.leftArrow ? "left" : key.rightArrow ? "right" : key.upArrow ? "up" : key.downArrow ? "down" : key.backspace ? "backspace" : key.delete ? "delete" : void 0;
|
|
2984
3111
|
return {
|
|
@@ -3011,7 +3138,7 @@ function tailLines(text, max) {
|
|
|
3011
3138
|
const lines = text.split("\n");
|
|
3012
3139
|
return lines.length <= max ? text : lines.slice(-max).join("\n");
|
|
3013
3140
|
}
|
|
3014
|
-
var SPINNER, WORKING, WAITING_FOR_REWARD, LOADING, COMPACTING, SIGNING_IN, NOT_SIGNED_IN, LIVE_OUTPUT_LINES, COMMITTED_OUTPUT_LINES;
|
|
3141
|
+
var SPINNER, WORKING, WAITING_FOR_REWARD, LOADING, COMPACTING, SIGNING_IN, NOT_SIGNED_IN, LIVE_OUTPUT_LINES, COMMITTED_OUTPUT_LINES, DELTA_FLUSH_MS, MAX_INPUT_ROWS, MAX_PICKER_ROWS;
|
|
3015
3142
|
var init_app = __esm({
|
|
3016
3143
|
"src/tui/app.tsx"() {
|
|
3017
3144
|
"use strict";
|
|
@@ -3044,6 +3171,9 @@ var init_app = __esm({
|
|
|
3044
3171
|
NOT_SIGNED_IN = " Not signed in, or the stored token isn't valid for this gateway.\n Run /login to sign in.";
|
|
3045
3172
|
LIVE_OUTPUT_LINES = 5;
|
|
3046
3173
|
COMMITTED_OUTPUT_LINES = 4;
|
|
3174
|
+
DELTA_FLUSH_MS = 50;
|
|
3175
|
+
MAX_INPUT_ROWS = 10;
|
|
3176
|
+
MAX_PICKER_ROWS = 12;
|
|
3047
3177
|
}
|
|
3048
3178
|
});
|
|
3049
3179
|
|