@cryer/star-cli 0.3.10 → 0.3.12
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/{chunk-PDFC7QVW.js → chunk-2GAUAYCU.js} +40 -8
- package/dist/chunk-2GAUAYCU.js.map +1 -0
- package/dist/{chunk-MNVCCOI2.js → chunk-F5RWZMQY.js} +224 -12
- package/dist/chunk-F5RWZMQY.js.map +1 -0
- package/dist/{chunk-A5PXPWHB.js → chunk-LSYGHLRU.js} +13 -1
- package/dist/chunk-LSYGHLRU.js.map +1 -0
- package/dist/{chunk-IJGUW4PM.js → chunk-MYHD3SZB.js} +6 -5
- package/dist/chunk-MYHD3SZB.js.map +1 -0
- package/dist/{chunk-URC7JXKX.js → chunk-Q5FJN4LN.js} +7 -3
- package/dist/{chunk-URC7JXKX.js.map → chunk-Q5FJN4LN.js.map} +1 -1
- package/dist/{loop-TW2FHL7J.js → loop-BYXBNFFY.js} +5 -5
- package/dist/main.js +8 -9
- package/dist/main.js.map +1 -1
- package/dist/{repl-GBVIW5QR.js → repl-SSCURTAH.js} +322 -57
- package/dist/repl-SSCURTAH.js.map +1 -0
- package/dist/{tools-7EBGCYYE.js → tools-BH55BVIS.js} +3 -3
- package/package.json +25 -16
- package/dist/chunk-A5PXPWHB.js.map +0 -1
- package/dist/chunk-IJGUW4PM.js.map +0 -1
- package/dist/chunk-MNVCCOI2.js.map +0 -1
- package/dist/chunk-PDFC7QVW.js.map +0 -1
- package/dist/repl-GBVIW5QR.js.map +0 -1
- /package/dist/{loop-TW2FHL7J.js.map → loop-BYXBNFFY.js.map} +0 -0
- /package/dist/{tools-7EBGCYYE.js.map → tools-BH55BVIS.js.map} +0 -0
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
buildDisplayMessages,
|
|
7
7
|
clearSessions,
|
|
8
8
|
computeCostUsd,
|
|
9
|
+
deleteSession,
|
|
9
10
|
estimateCost,
|
|
10
11
|
folderIcon,
|
|
11
12
|
formatByteCount,
|
|
@@ -14,11 +15,13 @@ import {
|
|
|
14
15
|
formatSessionEntries,
|
|
15
16
|
formatStreamError,
|
|
16
17
|
formatTokens,
|
|
18
|
+
formatTokensCompact,
|
|
17
19
|
listSessionEntries,
|
|
18
20
|
loadSessionSnapshots,
|
|
19
21
|
previewLines,
|
|
20
22
|
relativeTime,
|
|
21
23
|
renderMarkdown,
|
|
24
|
+
resolveIconMode,
|
|
22
25
|
resolveMentions,
|
|
23
26
|
resolveSessionId,
|
|
24
27
|
sessionPreview,
|
|
@@ -28,7 +31,7 @@ import {
|
|
|
28
31
|
thinkingIcon,
|
|
29
32
|
toTerminalSafe,
|
|
30
33
|
toolIcon
|
|
31
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-2GAUAYCU.js";
|
|
32
35
|
import {
|
|
33
36
|
AgentLoop,
|
|
34
37
|
WORKING_DIFF_MAX_LINES,
|
|
@@ -45,14 +48,14 @@ import {
|
|
|
45
48
|
isDangerousCommand,
|
|
46
49
|
isGitRepo,
|
|
47
50
|
summarizeMessages
|
|
48
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-F5RWZMQY.js";
|
|
49
52
|
import {
|
|
50
53
|
contextWindowTokens,
|
|
51
54
|
coreMessageText,
|
|
52
55
|
diffTreeNames,
|
|
53
56
|
reconcileStarMessages,
|
|
54
57
|
toCoreMessages
|
|
55
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-MYHD3SZB.js";
|
|
56
59
|
import {
|
|
57
60
|
createModel,
|
|
58
61
|
reasoningEffortMetadata
|
|
@@ -66,7 +69,7 @@ import {
|
|
|
66
69
|
formatTaskFinished,
|
|
67
70
|
formatTaskList,
|
|
68
71
|
formatTaskStarted
|
|
69
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-Q5FJN4LN.js";
|
|
70
73
|
import {
|
|
71
74
|
MAX_IMAGE_DIMENSION,
|
|
72
75
|
SKIP_DIRS,
|
|
@@ -95,7 +98,7 @@ import {
|
|
|
95
98
|
starHome,
|
|
96
99
|
upsertEnvContent,
|
|
97
100
|
userMemoryPath
|
|
98
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-LSYGHLRU.js";
|
|
99
102
|
|
|
100
103
|
// src/cli/repl.tsx
|
|
101
104
|
import { Box as Box13, Text as Text14, render, useApp } from "ink";
|
|
@@ -662,7 +665,7 @@ async function compactSession(opts) {
|
|
|
662
665
|
return {
|
|
663
666
|
message: `Compacted context: ${messages.length} -> ${next.length} messages (~${formatTokens(beforeTokens)} -> ~${formatTokens(afterTokens)} estimated tokens).`,
|
|
664
667
|
compacted: true,
|
|
665
|
-
messages:
|
|
668
|
+
messages: next
|
|
666
669
|
};
|
|
667
670
|
}
|
|
668
671
|
async function applyCompactionSummary(original, compacted, config, model, temperature, signal) {
|
|
@@ -1586,13 +1589,30 @@ var PROVIDER_PRESETS = [
|
|
|
1586
1589
|
modelHint: "deepseek-chat"
|
|
1587
1590
|
}
|
|
1588
1591
|
];
|
|
1589
|
-
var PROTOCOLS = ["openai-
|
|
1592
|
+
var PROTOCOLS = ["openai-responses", "openai-compatible", "anthropic"];
|
|
1593
|
+
var DEFAULT_CUSTOM_PROTOCOL = "openai-responses";
|
|
1590
1594
|
var PROTOCOL_DESCRIPTIONS = {
|
|
1591
1595
|
"openai-compatible": "POST /chat/completions \u2014 most providers",
|
|
1592
1596
|
anthropic: "Anthropic Messages API",
|
|
1593
1597
|
"openai-responses": "OpenAI Responses API (endpoints exposing only /responses)"
|
|
1594
1598
|
};
|
|
1595
1599
|
var CONNECT_DEFAULT_CONTEXT_TOKENS = 128e3;
|
|
1600
|
+
var CONFIG_DOCS_URL = "https://github.com/cryer/star-cli";
|
|
1601
|
+
function buildNewConfigHeader() {
|
|
1602
|
+
return [
|
|
1603
|
+
`# star-cli configuration \u2014 more config details on ${CONFIG_DOCS_URL}`,
|
|
1604
|
+
"",
|
|
1605
|
+
"# progress checkpoint: max model round-trips per turn; 0 = unlimited",
|
|
1606
|
+
"maxSteps = 0",
|
|
1607
|
+
"# context window in tokens; a [[models]] contextMaxTokens overrides it per model",
|
|
1608
|
+
"contextMaxTokens = 200000",
|
|
1609
|
+
"# auto-compact the history once the estimated usage crosses this threshold",
|
|
1610
|
+
"compactThresholdTokens = 100000",
|
|
1611
|
+
'# how compaction shrinks the history: "summary" (LLM summary) or "truncate"',
|
|
1612
|
+
'contextCompaction = "summary"',
|
|
1613
|
+
""
|
|
1614
|
+
].join("\n");
|
|
1615
|
+
}
|
|
1596
1616
|
function deriveProviderName(baseURL) {
|
|
1597
1617
|
let host = baseURL;
|
|
1598
1618
|
try {
|
|
@@ -1712,6 +1732,7 @@ function saveConnection(answers, configPath = globalConfigPath(), envPath = envF
|
|
|
1712
1732
|
} catch {
|
|
1713
1733
|
existing = "";
|
|
1714
1734
|
}
|
|
1735
|
+
if (existing === "") existing = buildNewConfigHeader();
|
|
1715
1736
|
const separator = existing === "" ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
|
|
1716
1737
|
fs4.writeFileSync(
|
|
1717
1738
|
configPath,
|
|
@@ -2261,7 +2282,7 @@ function filterCommands(input, commands) {
|
|
|
2261
2282
|
const fuzzy = commands.filter(
|
|
2262
2283
|
(cmd) => !cmd.name.toLowerCase().startsWith(prefix) && isSubsequence(prefix, cmd.name.toLowerCase())
|
|
2263
2284
|
).sort(byName);
|
|
2264
|
-
return [...prefixed, ...fuzzy]
|
|
2285
|
+
return [...prefixed, ...fuzzy];
|
|
2265
2286
|
}
|
|
2266
2287
|
function didYouMeanSuffix(names) {
|
|
2267
2288
|
if (names.length === 0) return "";
|
|
@@ -2281,7 +2302,7 @@ function filterArgHints(input, commands) {
|
|
|
2281
2302
|
const candidates = typeof source === "function" ? source(argPrefix) : source;
|
|
2282
2303
|
const prefix = argPrefix.toLowerCase();
|
|
2283
2304
|
const stem = input.slice(0, input.length - argPrefix.length);
|
|
2284
|
-
return candidates.filter((candidate) => candidate.toLowerCase().startsWith(prefix)).
|
|
2305
|
+
return candidates.filter((candidate) => candidate.toLowerCase().startsWith(prefix)).map((value) => ({ value, replacement: `${stem}${value}` }));
|
|
2285
2306
|
}
|
|
2286
2307
|
|
|
2287
2308
|
// src/cli/commands/undo.ts
|
|
@@ -2607,14 +2628,38 @@ import { Box, Text } from "ink";
|
|
|
2607
2628
|
import { useRef as useRef2, useState } from "react";
|
|
2608
2629
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2609
2630
|
var SELECT_PROMPT_MAX_VISIBLE = 9;
|
|
2610
|
-
function SelectPrompt({ title, options, onSelect, onCancel }) {
|
|
2631
|
+
function SelectPrompt({ title, options, onSelect, onCancel, onDelete }) {
|
|
2611
2632
|
const [index, setIndex] = useState(0);
|
|
2612
2633
|
const indexRef = useRef2(0);
|
|
2634
|
+
const [confirming, setConfirming] = useState(null);
|
|
2635
|
+
const confirmingRef = useRef2(null);
|
|
2636
|
+
const deletingRef = useRef2(false);
|
|
2637
|
+
const setConfirm = (option) => {
|
|
2638
|
+
confirmingRef.current = option;
|
|
2639
|
+
setConfirming(option);
|
|
2640
|
+
};
|
|
2613
2641
|
const move = (delta) => {
|
|
2614
2642
|
indexRef.current = Math.max(0, Math.min(indexRef.current + delta, options.length - 1));
|
|
2615
2643
|
setIndex(indexRef.current);
|
|
2616
2644
|
};
|
|
2617
2645
|
useInput((input, key) => {
|
|
2646
|
+
const pending = confirmingRef.current;
|
|
2647
|
+
if (pending) {
|
|
2648
|
+
if (input === "y" || input === "Y") {
|
|
2649
|
+
setConfirm(null);
|
|
2650
|
+
if (onDelete && !deletingRef.current) {
|
|
2651
|
+
deletingRef.current = true;
|
|
2652
|
+
void onDelete(pending.value).catch(() => options).then((next) => {
|
|
2653
|
+
deletingRef.current = false;
|
|
2654
|
+
indexRef.current = Math.min(indexRef.current, Math.max(0, next.length - 1));
|
|
2655
|
+
setIndex(indexRef.current);
|
|
2656
|
+
});
|
|
2657
|
+
}
|
|
2658
|
+
} else if (input === "n" || input === "N" || key.escape) {
|
|
2659
|
+
setConfirm(null);
|
|
2660
|
+
}
|
|
2661
|
+
return;
|
|
2662
|
+
}
|
|
2618
2663
|
if (key.escape) {
|
|
2619
2664
|
onCancel();
|
|
2620
2665
|
return;
|
|
@@ -2624,6 +2669,11 @@ function SelectPrompt({ title, options, onSelect, onCancel }) {
|
|
|
2624
2669
|
if (option) onSelect(option.value);
|
|
2625
2670
|
return;
|
|
2626
2671
|
}
|
|
2672
|
+
if (onDelete && key.ctrl && input === "x") {
|
|
2673
|
+
const option = options[indexRef.current];
|
|
2674
|
+
if (option) setConfirm(option);
|
|
2675
|
+
return;
|
|
2676
|
+
}
|
|
2627
2677
|
if (key.downArrow || input === "j") {
|
|
2628
2678
|
move(1);
|
|
2629
2679
|
} else if (key.upArrow || input === "k") {
|
|
@@ -2665,7 +2715,15 @@ function SelectPrompt({ title, options, onSelect, onCancel }) {
|
|
|
2665
2715
|
below,
|
|
2666
2716
|
" more below"
|
|
2667
2717
|
] }),
|
|
2668
|
-
/* @__PURE__ */
|
|
2718
|
+
confirming ? /* @__PURE__ */ jsxs(Text, { color: "red", children: [
|
|
2719
|
+
"Delete ",
|
|
2720
|
+
confirming.label,
|
|
2721
|
+
"? [y] yes [n] no"
|
|
2722
|
+
] }) : /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
2723
|
+
"[\u2191/\u2193 or j/k] move [Enter] select",
|
|
2724
|
+
onDelete ? " [Ctrl+X] delete" : "",
|
|
2725
|
+
" [Esc] cancel"
|
|
2726
|
+
] })
|
|
2669
2727
|
] });
|
|
2670
2728
|
}
|
|
2671
2729
|
|
|
@@ -2966,7 +3024,7 @@ var InputBox = memo(function InputBox2({
|
|
|
2966
3024
|
if (suggestions.length > 0) {
|
|
2967
3025
|
const cmd = suggestions[activeIndex];
|
|
2968
3026
|
if (!cmd) return;
|
|
2969
|
-
const text = `/${cmd.name}
|
|
3027
|
+
const text = `/${cmd.name}`;
|
|
2970
3028
|
edit(text, text.length);
|
|
2971
3029
|
return;
|
|
2972
3030
|
}
|
|
@@ -3095,7 +3153,11 @@ ${currentValue.slice(currentCursor)}`,
|
|
|
3095
3153
|
);
|
|
3096
3154
|
return;
|
|
3097
3155
|
}
|
|
3098
|
-
|
|
3156
|
+
let text = expandPastes(currentValue).trim();
|
|
3157
|
+
if (suggestions.length > 0 && text.startsWith("/") && text.length > 1) {
|
|
3158
|
+
const cmd = suggestions[activeIndex];
|
|
3159
|
+
if (cmd) text = `/${cmd.name}`;
|
|
3160
|
+
}
|
|
3099
3161
|
if (text.length > 0) {
|
|
3100
3162
|
if (!text.startsWith("/")) setHistory((prev) => [...prev, text]);
|
|
3101
3163
|
onSubmit(text);
|
|
@@ -3219,18 +3281,47 @@ ${value.slice(cursor)}`, cursor + 1);
|
|
|
3219
3281
|
const cursorChar = at === "\n" || at === void 0 || at === PASTE_DELIM ? " " : at;
|
|
3220
3282
|
const tail = (at === "\n" ? "\n" : "") + stylePasteTokens(after);
|
|
3221
3283
|
const styled = search ? `\x1B[36m(reverse-search) \x1B[39m'${search.query}': ${search.match === null ? "\x1B[2mno match\x1B[22m\x1B[7m \x1B[27m" : `${history[search.match]}\x1B[7m \x1B[27m`}` : `\x1B[36m\u276F \x1B[39m${stylePasteTokens(before)}\x1B[7m${cursorChar}\x1B[27m${tail}`;
|
|
3284
|
+
const menuStart = Math.min(
|
|
3285
|
+
Math.max(0, activeIndex - Math.floor(MAX_SUGGESTIONS / 2)),
|
|
3286
|
+
Math.max(0, suggestionCount - MAX_SUGGESTIONS)
|
|
3287
|
+
);
|
|
3288
|
+
const menuEnd = Math.min(suggestionCount, menuStart + MAX_SUGGESTIONS);
|
|
3222
3289
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
3223
3290
|
/* @__PURE__ */ jsx2(Box2, { borderStyle: "round", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsx2(Text2, { children: styled }) }),
|
|
3224
|
-
suggestions.length > 0 && /* @__PURE__ */
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
] },
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3291
|
+
suggestions.length > 0 && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingLeft: 2, children: [
|
|
3292
|
+
menuStart > 0 && /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
3293
|
+
"\u2026 ",
|
|
3294
|
+
menuStart,
|
|
3295
|
+
" more above"
|
|
3296
|
+
] }),
|
|
3297
|
+
suggestions.slice(menuStart, menuEnd).map((cmd, index) => {
|
|
3298
|
+
const label = cmd.usage ?? `/${cmd.name}`;
|
|
3299
|
+
return menuStart + index === activeIndex ? /* @__PURE__ */ jsx2(Text2, { bold: true, inverse: true, children: `${label} - ${cmd.description}` }, cmd.name) : /* @__PURE__ */ jsxs2(Text2, { children: [
|
|
3300
|
+
/* @__PURE__ */ jsx2(Text2, { color: "cyan", children: label }),
|
|
3301
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: ` - ${cmd.description}` })
|
|
3302
|
+
] }, cmd.name);
|
|
3303
|
+
}),
|
|
3304
|
+
menuEnd < suggestions.length && /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
3305
|
+
"\u2026 ",
|
|
3306
|
+
suggestions.length - menuEnd,
|
|
3307
|
+
" more below"
|
|
3308
|
+
] })
|
|
3309
|
+
] }),
|
|
3310
|
+
argHints.length > 0 && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingLeft: 2, children: [
|
|
3311
|
+
menuStart > 0 && /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
3312
|
+
"\u2026 ",
|
|
3313
|
+
menuStart,
|
|
3314
|
+
" more above"
|
|
3315
|
+
] }),
|
|
3316
|
+
argHints.slice(menuStart, menuEnd).map(
|
|
3317
|
+
(hint, index) => menuStart + index === activeIndex ? /* @__PURE__ */ jsx2(Text2, { bold: true, inverse: true, children: hint.value }, hint.value) : /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: hint.value }, hint.value)
|
|
3318
|
+
),
|
|
3319
|
+
menuEnd < argHints.length && /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
3320
|
+
"\u2026 ",
|
|
3321
|
+
argHints.length - menuEnd,
|
|
3322
|
+
" more below"
|
|
3323
|
+
] })
|
|
3324
|
+
] }),
|
|
3234
3325
|
showPathSuggestions && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", paddingLeft: 2, children: pathSuggestions.map(
|
|
3235
3326
|
(sugg, index) => index === activeIndex ? /* @__PURE__ */ jsx2(Text2, { bold: true, inverse: true, children: `@${sugg.path}` }, sugg.path) : /* @__PURE__ */ jsxs2(Text2, { children: [
|
|
3236
3327
|
/* @__PURE__ */ jsx2(Text2, { color: "cyan", children: `@${sugg.path}` }),
|
|
@@ -3326,7 +3417,7 @@ function ConnectWizard({
|
|
|
3326
3417
|
}) {
|
|
3327
3418
|
const [step, setStep] = useState4("provider");
|
|
3328
3419
|
const [preset, setPreset] = useState4(null);
|
|
3329
|
-
const [protocol, setProtocol] = useState4(
|
|
3420
|
+
const [protocol, setProtocol] = useState4(DEFAULT_CUSTOM_PROTOCOL);
|
|
3330
3421
|
const [baseURL, setBaseURL] = useState4("");
|
|
3331
3422
|
const [apiKey, setApiKey] = useState4("");
|
|
3332
3423
|
const [modelId, setModelId] = useState4("");
|
|
@@ -3463,6 +3554,7 @@ function ConnectWizard({
|
|
|
3463
3554
|
options: PROTOCOLS.map((p) => ({
|
|
3464
3555
|
value: p,
|
|
3465
3556
|
label: p,
|
|
3557
|
+
hint: p === DEFAULT_CUSTOM_PROTOCOL ? "default" : void 0,
|
|
3466
3558
|
description: PROTOCOL_DESCRIPTIONS[p]
|
|
3467
3559
|
})),
|
|
3468
3560
|
onSelect: handleProtocolSelect,
|
|
@@ -3600,10 +3692,11 @@ var MessageList = memo2(function MessageList2({ messages }) {
|
|
|
3600
3692
|
] }) }, message.id);
|
|
3601
3693
|
}
|
|
3602
3694
|
if (message.role === "user") {
|
|
3695
|
+
const color = message.steer ? "magenta" : "cyan";
|
|
3603
3696
|
return /* @__PURE__ */ jsxs7(Box6, { flexDirection: "column", marginBottom, children: [
|
|
3604
3697
|
/* @__PURE__ */ jsxs7(Box6, { children: [
|
|
3605
|
-
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "
|
|
3606
|
-
/* @__PURE__ */ jsxs7(Text7, { color
|
|
3698
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color, children: message.steer ? "\xBB " : "\u276F " }),
|
|
3699
|
+
/* @__PURE__ */ jsxs7(Text7, { color, children: [
|
|
3607
3700
|
message.text,
|
|
3608
3701
|
message.interrupted && interruptedMarker(message.text)
|
|
3609
3702
|
] })
|
|
@@ -3722,6 +3815,7 @@ var StatusBar = memo3(function StatusBar2({
|
|
|
3722
3815
|
tokens: tokens2,
|
|
3723
3816
|
gitBranch,
|
|
3724
3817
|
contextPercent,
|
|
3818
|
+
contextTokens,
|
|
3725
3819
|
cachePercent,
|
|
3726
3820
|
sessionCostUsd,
|
|
3727
3821
|
backgroundTasks = []
|
|
@@ -3750,7 +3844,8 @@ var StatusBar = memo3(function StatusBar2({
|
|
|
3750
3844
|
contextPercent != null && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3751
3845
|
"ctx: ",
|
|
3752
3846
|
contextPercent,
|
|
3753
|
-
"%"
|
|
3847
|
+
"%",
|
|
3848
|
+
contextTokens ? ` (${formatTokensCompact(contextTokens.used)}/${formatTokensCompact(contextTokens.window)})` : ""
|
|
3754
3849
|
] }),
|
|
3755
3850
|
/* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
3756
3851
|
"cache: ",
|
|
@@ -3815,6 +3910,14 @@ function truncateTail(text, max) {
|
|
|
3815
3910
|
if (flat.length <= max) return flat;
|
|
3816
3911
|
return `\u2026${flat.slice(flat.length - max)}`;
|
|
3817
3912
|
}
|
|
3913
|
+
function roughReasoningTokens(text) {
|
|
3914
|
+
let weight = 0;
|
|
3915
|
+
for (let i = 0; i < text.length; i++) {
|
|
3916
|
+
const code = text.charCodeAt(i);
|
|
3917
|
+
weight += code >= 12288 && code <= 12543 || code >= 13312 && code <= 19903 || code >= 19968 && code <= 40959 || code >= 63744 && code <= 64255 || code >= 65280 && code <= 65519 ? 4 : 1;
|
|
3918
|
+
}
|
|
3919
|
+
return Math.ceil(weight / 4);
|
|
3920
|
+
}
|
|
3818
3921
|
var ThinkingIndicator = memo5(function ThinkingIndicator2({
|
|
3819
3922
|
reasoning,
|
|
3820
3923
|
frame,
|
|
@@ -3827,13 +3930,17 @@ var ThinkingIndicator = memo5(function ThinkingIndicator2({
|
|
|
3827
3930
|
const spinner = SPINNER_FRAMES[(frame ?? tick) % SPINNER_FRAMES.length];
|
|
3828
3931
|
const label = activity ?? `${thinkingIcon} star is thinking\u2026`;
|
|
3829
3932
|
const elapsedSec = startedAt === void 0 ? void 0 : Math.max(0, Math.floor((Date.now() - startedAt) / 1e3));
|
|
3830
|
-
const
|
|
3933
|
+
const stats = [];
|
|
3934
|
+
if (elapsedSec !== void 0 && elapsedSec >= 3) stats.push(formatElapsedSeconds(elapsedSec));
|
|
3935
|
+
const thoughtTokens = reasoning ? roughReasoningTokens(reasoning) : 0;
|
|
3936
|
+
if (thoughtTokens > 0) stats.push(`~${formatTokens(thoughtTokens)} thought`);
|
|
3937
|
+
const status = stats.length > 0 ? ` (${stats.join(" \xB7 ")})` : "";
|
|
3831
3938
|
return /* @__PURE__ */ jsxs12(Box11, { flexDirection: "column", children: [
|
|
3832
3939
|
/* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
3833
3940
|
spinner,
|
|
3834
3941
|
" ",
|
|
3835
3942
|
label,
|
|
3836
|
-
|
|
3943
|
+
status
|
|
3837
3944
|
] }),
|
|
3838
3945
|
tail !== "" && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
3839
3946
|
" ",
|
|
@@ -3990,6 +4097,12 @@ var PromptQueue = class {
|
|
|
3990
4097
|
this.items.push({ id: this.nextId++, ...prompt });
|
|
3991
4098
|
return this.items.length;
|
|
3992
4099
|
}
|
|
4100
|
+
// Jump the queue: steering prompts the running turn never delivered are
|
|
4101
|
+
// recovered here when the turn ends, and they were submitted before the
|
|
4102
|
+
// already-queued entries.
|
|
4103
|
+
enqueueFront(prompt) {
|
|
4104
|
+
this.items.unshift({ id: this.nextId++, ...prompt });
|
|
4105
|
+
}
|
|
3993
4106
|
dequeue() {
|
|
3994
4107
|
return this.items.shift();
|
|
3995
4108
|
}
|
|
@@ -4035,9 +4148,56 @@ async function executeShellBang(raw, cwd, signal) {
|
|
|
4035
4148
|
};
|
|
4036
4149
|
}
|
|
4037
4150
|
|
|
4151
|
+
// src/cli/terminal-title.ts
|
|
4152
|
+
import path14 from "path";
|
|
4153
|
+
var SPINNER_FRAMES2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
4154
|
+
var TITLE_INTERVAL_MS = 120;
|
|
4155
|
+
var CONTROL_CHARS = /[\x00-\x1f\x7f]/g;
|
|
4156
|
+
function setTerminalTitle(title, deps = {}) {
|
|
4157
|
+
const isTTY = deps.isTTY ?? Boolean(process.stdout.isTTY);
|
|
4158
|
+
if (!isTTY) return;
|
|
4159
|
+
const write = deps.write ?? ((text) => process.stdout.write(text));
|
|
4160
|
+
write(`\x1B]0;${title.replace(CONTROL_CHARS, "")}\x07`);
|
|
4161
|
+
}
|
|
4162
|
+
var TerminalTitle = class _TerminalTitle {
|
|
4163
|
+
constructor(base, deps) {
|
|
4164
|
+
this.base = base;
|
|
4165
|
+
this.deps = deps;
|
|
4166
|
+
}
|
|
4167
|
+
base;
|
|
4168
|
+
deps;
|
|
4169
|
+
timer = null;
|
|
4170
|
+
frame = 0;
|
|
4171
|
+
static forCwd(cwd, deps = {}) {
|
|
4172
|
+
return new _TerminalTitle(`star-cli \u2014 ${path14.basename(cwd) || cwd}`, deps);
|
|
4173
|
+
}
|
|
4174
|
+
start() {
|
|
4175
|
+
if (this.timer) return;
|
|
4176
|
+
this.render(SPINNER_FRAMES2[this.frame] ?? "\u280B");
|
|
4177
|
+
this.timer = setInterval(() => {
|
|
4178
|
+
this.frame = (this.frame + 1) % SPINNER_FRAMES2.length;
|
|
4179
|
+
this.render(SPINNER_FRAMES2[this.frame] ?? "\u280B");
|
|
4180
|
+
}, TITLE_INTERVAL_MS);
|
|
4181
|
+
this.timer.unref();
|
|
4182
|
+
}
|
|
4183
|
+
// "done" leaves a bell glyph in the title until the next turn starts;
|
|
4184
|
+
// "idle" (interrupt, unmount) restores the bare title.
|
|
4185
|
+
stop(kind = "done") {
|
|
4186
|
+
if (this.timer) {
|
|
4187
|
+
clearInterval(this.timer);
|
|
4188
|
+
this.timer = null;
|
|
4189
|
+
}
|
|
4190
|
+
this.frame = 0;
|
|
4191
|
+
this.render(kind === "done" ? resolveIconMode(this.deps.env) === "emoji" ? "\u{1F514}" : "!" : "");
|
|
4192
|
+
}
|
|
4193
|
+
render(prefix) {
|
|
4194
|
+
setTerminalTitle(prefix ? `${prefix} ${this.base}` : this.base, this.deps);
|
|
4195
|
+
}
|
|
4196
|
+
};
|
|
4197
|
+
|
|
4038
4198
|
// src/cli/update-check.ts
|
|
4039
4199
|
import { mkdir, readFile as readFile4, rename, writeFile } from "fs/promises";
|
|
4040
|
-
import
|
|
4200
|
+
import path15 from "path";
|
|
4041
4201
|
var REGISTRY_URL2 = "https://registry.npmjs.org/@cryer%2fstar-cli/latest";
|
|
4042
4202
|
var TIMEOUT_MS = 5e3;
|
|
4043
4203
|
var THROTTLE_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -4045,7 +4205,7 @@ async function defaultFetcher2(url) {
|
|
|
4045
4205
|
return fetch(url, { signal: AbortSignal.timeout(TIMEOUT_MS) });
|
|
4046
4206
|
}
|
|
4047
4207
|
function defaultStatePath() {
|
|
4048
|
-
return
|
|
4208
|
+
return path15.join(starHome(), "update-check.json");
|
|
4049
4209
|
}
|
|
4050
4210
|
async function readState(statePath) {
|
|
4051
4211
|
try {
|
|
@@ -4060,7 +4220,7 @@ async function readState(statePath) {
|
|
|
4060
4220
|
}
|
|
4061
4221
|
async function writeState(statePath, state) {
|
|
4062
4222
|
try {
|
|
4063
|
-
await mkdir(
|
|
4223
|
+
await mkdir(path15.dirname(statePath), { recursive: true });
|
|
4064
4224
|
const tmp = `${statePath}.tmp-${process.pid}`;
|
|
4065
4225
|
await writeFile(tmp, JSON.stringify(state), "utf8");
|
|
4066
4226
|
await rename(tmp, statePath);
|
|
@@ -4131,7 +4291,7 @@ var BUSY_BLOCKED_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
4131
4291
|
function formatUsage(usage) {
|
|
4132
4292
|
return `API usage this session: ${usage.requests} requests, ${formatTokens(usage.promptTokens)} prompt + ${formatTokens(usage.completionTokens)} completion = ${formatTokens(usage.totalTokens)} tokens`;
|
|
4133
4293
|
}
|
|
4134
|
-
var SESSION_PICKER_CAP =
|
|
4294
|
+
var SESSION_PICKER_CAP = 100;
|
|
4135
4295
|
var SESSION_PREVIEW_MAX = 60;
|
|
4136
4296
|
var MAX_VISIBLE_QUEUED = 5;
|
|
4137
4297
|
var REASONING_EFFORT_LEVELS = ["minimal", "low", "medium", "high", "max"];
|
|
@@ -4186,6 +4346,7 @@ function Repl({
|
|
|
4186
4346
|
const planApprovalRef = useRef6(false);
|
|
4187
4347
|
const pendingRewindRef = useRef6(null);
|
|
4188
4348
|
const pickerRef = useRef6(null);
|
|
4349
|
+
const titleRef = useRef6(null);
|
|
4189
4350
|
const pendingConnectRef = useRef6(null);
|
|
4190
4351
|
const modelNameRef = useRef6(model);
|
|
4191
4352
|
const sessionStoreRef = useRef6(sessionStore);
|
|
@@ -4205,7 +4366,7 @@ function Repl({
|
|
|
4205
4366
|
const refillSeqRef = useRef6(0);
|
|
4206
4367
|
const lastEscRef = useRef6(null);
|
|
4207
4368
|
const [gitBranch, setGitBranch] = useState7(null);
|
|
4208
|
-
const [
|
|
4369
|
+
const [contextUsage, setContextUsage] = useState7(null);
|
|
4209
4370
|
const [initialHistory] = useState7(() => loadHistory());
|
|
4210
4371
|
const budgetWarnedRef = useRef6(false);
|
|
4211
4372
|
const budgetExceededRef = useRef6(false);
|
|
@@ -4213,11 +4374,11 @@ function Repl({
|
|
|
4213
4374
|
null
|
|
4214
4375
|
);
|
|
4215
4376
|
const pushMessage = useCallback(
|
|
4216
|
-
(role, text, note, tight, interrupted, diff) => {
|
|
4377
|
+
(role, text, note, tight, interrupted, diff, steer) => {
|
|
4217
4378
|
setMessages((prev) => {
|
|
4218
4379
|
const next = [
|
|
4219
4380
|
...prev,
|
|
4220
|
-
{ id: nextIdRef.current++, role, text, note, tight, interrupted, diff }
|
|
4381
|
+
{ id: nextIdRef.current++, role, text, note, tight, interrupted, diff, steer }
|
|
4221
4382
|
];
|
|
4222
4383
|
messagesRef.current = next;
|
|
4223
4384
|
return next;
|
|
@@ -4268,10 +4429,10 @@ function Repl({
|
|
|
4268
4429
|
setPendingConnectState(p);
|
|
4269
4430
|
}, []);
|
|
4270
4431
|
const showPicker = useCallback(
|
|
4271
|
-
(title, options) => {
|
|
4432
|
+
(title, options, onDelete) => {
|
|
4272
4433
|
if (pickerRef.current) return Promise.resolve(null);
|
|
4273
4434
|
return new Promise((resolve) => {
|
|
4274
|
-
setPicker({ title, options, resolve });
|
|
4435
|
+
setPicker({ title, options, resolve, onDelete });
|
|
4275
4436
|
});
|
|
4276
4437
|
},
|
|
4277
4438
|
[setPicker]
|
|
@@ -4335,7 +4496,8 @@ function Repl({
|
|
|
4335
4496
|
const result = saveConnection(answers);
|
|
4336
4497
|
config.providers.push(result.provider);
|
|
4337
4498
|
config.models.push(result.model);
|
|
4338
|
-
return `Saved provider "${result.provider.name}" and model "${result.model.name}" to ${result.configPath}; the key is stored as ${result.provider.apiKeyEnv} in ${result.envPath}
|
|
4499
|
+
return `Saved provider "${result.provider.name}" and model "${result.model.name}" to ${result.configPath}; the key is stored as ${result.provider.apiKeyEnv} in ${result.envPath}.
|
|
4500
|
+
Full configuration details: ${CONFIG_DOCS_URL}`;
|
|
4339
4501
|
},
|
|
4340
4502
|
[config]
|
|
4341
4503
|
);
|
|
@@ -4398,6 +4560,7 @@ function Repl({
|
|
|
4398
4560
|
tickerStopRef.current?.();
|
|
4399
4561
|
abortRef.current?.abort();
|
|
4400
4562
|
pendingRef.current?.resolve(false);
|
|
4563
|
+
titleRef.current?.stop("idle");
|
|
4401
4564
|
};
|
|
4402
4565
|
}, [attachConfirmHandler]);
|
|
4403
4566
|
useEffect4(() => {
|
|
@@ -4664,7 +4827,7 @@ function Repl({
|
|
|
4664
4827
|
setTodoSession(store.id);
|
|
4665
4828
|
setTodos(await loadTodos(cwd, store.id));
|
|
4666
4829
|
hydrateSnapshots(await loadSessionSnapshots(store.dir));
|
|
4667
|
-
const display = buildDisplayMessages(
|
|
4830
|
+
const display = buildDisplayMessages(resumed.messages);
|
|
4668
4831
|
nextIdRef.current = display.length;
|
|
4669
4832
|
applyMessages(display);
|
|
4670
4833
|
usageRef.current = resumed.meta.usage ? { ...resumed.meta.usage } : emptyUsage();
|
|
@@ -4674,6 +4837,10 @@ function Repl({
|
|
|
4674
4837
|
},
|
|
4675
4838
|
[applyMessages, cwd, stopBackgroundWork]
|
|
4676
4839
|
);
|
|
4840
|
+
const terminalTitle = useCallback(() => {
|
|
4841
|
+
titleRef.current ??= TerminalTitle.forCwd(cwd);
|
|
4842
|
+
return titleRef.current;
|
|
4843
|
+
}, [cwd]);
|
|
4677
4844
|
const runStream = useCallback(
|
|
4678
4845
|
async (input, extraImages = []) => {
|
|
4679
4846
|
const resolved = await resolveMentions(input, cwd);
|
|
@@ -4700,6 +4867,7 @@ function Repl({
|
|
|
4700
4867
|
setThoughtSummary(null);
|
|
4701
4868
|
setStreamingText("");
|
|
4702
4869
|
setIsStreaming(true);
|
|
4870
|
+
terminalTitle().start();
|
|
4703
4871
|
flushedRef.current = { streamed: "", reasoning: "" };
|
|
4704
4872
|
const commitStreamed = (tight) => {
|
|
4705
4873
|
const uncommitted = streamedRef.current.slice(lastCommittedLenRef.current);
|
|
@@ -4859,6 +5027,7 @@ function Repl({
|
|
|
4859
5027
|
lastCommittedLenRef.current = 0;
|
|
4860
5028
|
setStreamingText(null);
|
|
4861
5029
|
const interrupted = controller.signal.aborted;
|
|
5030
|
+
terminalTitle().stop(interrupted ? "idle" : "done");
|
|
4862
5031
|
notifyBell({
|
|
4863
5032
|
enabled: config.notifyBell,
|
|
4864
5033
|
thresholdSec: config.notifyBellThresholdSec,
|
|
@@ -4901,6 +5070,14 @@ function Repl({
|
|
|
4901
5070
|
`Session budget exceeded: $${formatDollars(cost ?? 0)} of $${formatDollars(budget ?? 0)} (sessionBudgetUsd). New prompts are blocked \u2014 raise sessionBudgetUsd in the config or start a /new session.`
|
|
4902
5071
|
);
|
|
4903
5072
|
}
|
|
5073
|
+
const backend2 = backendRef.current;
|
|
5074
|
+
if (backend2 instanceof AgentLoop) {
|
|
5075
|
+
const undelivered = backend2.takeUndeliveredSteers();
|
|
5076
|
+
for (const text of [...undelivered].reverse()) {
|
|
5077
|
+
queueRef.current.enqueueFront({ text, images: [] });
|
|
5078
|
+
}
|
|
5079
|
+
if (undelivered.length > 0) setQueueItems(queueRef.current.list());
|
|
5080
|
+
}
|
|
4904
5081
|
const nextPrompt = queueRef.current.dequeue();
|
|
4905
5082
|
if (nextPrompt) {
|
|
4906
5083
|
if (status === "exceeded") {
|
|
@@ -4924,7 +5101,8 @@ function Repl({
|
|
|
4924
5101
|
setPlanApproval,
|
|
4925
5102
|
cwd,
|
|
4926
5103
|
config,
|
|
4927
|
-
sessionCostUsd
|
|
5104
|
+
sessionCostUsd,
|
|
5105
|
+
terminalTitle
|
|
4928
5106
|
]
|
|
4929
5107
|
);
|
|
4930
5108
|
useEffect4(() => {
|
|
@@ -5072,11 +5250,41 @@ ${lines.join("\n")}`;
|
|
|
5072
5250
|
};
|
|
5073
5251
|
})
|
|
5074
5252
|
);
|
|
5253
|
+
const deleted = [];
|
|
5254
|
+
const onDelete = async (id) => {
|
|
5255
|
+
const picker2 = pickerRef.current;
|
|
5256
|
+
const option = (picker2?.options ?? options).find((o) => o.value === id);
|
|
5257
|
+
try {
|
|
5258
|
+
await deleteSession(id);
|
|
5259
|
+
} catch (error) {
|
|
5260
|
+
pushMessage(
|
|
5261
|
+
"system",
|
|
5262
|
+
`Failed to delete session ${shortSessionId(id)}: ${error instanceof Error ? error.message : String(error)}`
|
|
5263
|
+
);
|
|
5264
|
+
return picker2?.options ?? options;
|
|
5265
|
+
}
|
|
5266
|
+
deleted.push(option?.label ?? shortSessionId(id));
|
|
5267
|
+
const remaining = (picker2?.options ?? options).filter((o) => o.value !== id);
|
|
5268
|
+
if (picker2) {
|
|
5269
|
+
if (remaining.length === 0) {
|
|
5270
|
+
handlePickerCancel();
|
|
5271
|
+
} else {
|
|
5272
|
+
setPicker({ ...picker2, options: remaining });
|
|
5273
|
+
}
|
|
5274
|
+
}
|
|
5275
|
+
return remaining;
|
|
5276
|
+
};
|
|
5075
5277
|
const picked = await showPicker(
|
|
5076
5278
|
all ? "Resume a session (all directories)" : "Resume a session",
|
|
5077
|
-
options
|
|
5279
|
+
options,
|
|
5280
|
+
onDelete
|
|
5078
5281
|
);
|
|
5079
|
-
if (!picked)
|
|
5282
|
+
if (!picked) {
|
|
5283
|
+
if (deleted.length > 0) {
|
|
5284
|
+
return `Deleted ${deleted.length} session(s): ${deleted.join(", ")}.`;
|
|
5285
|
+
}
|
|
5286
|
+
return "Session unchanged \u2014 picker cancelled.";
|
|
5287
|
+
}
|
|
5080
5288
|
return resume(picked);
|
|
5081
5289
|
},
|
|
5082
5290
|
forkSession: async () => {
|
|
@@ -5293,7 +5501,7 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
5293
5501
|
if (result.messageIndex !== null && current instanceof AgentLoop) {
|
|
5294
5502
|
retracted = await current.retractFromIndex(result.messageIndex);
|
|
5295
5503
|
if (retracted > 0) {
|
|
5296
|
-
const display = buildDisplayMessages([...current.
|
|
5504
|
+
const display = buildDisplayMessages([...current.getStarMessages()]);
|
|
5297
5505
|
nextIdRef.current = display.length;
|
|
5298
5506
|
redrawMessages(display);
|
|
5299
5507
|
}
|
|
@@ -5390,6 +5598,8 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
5390
5598
|
setPendingRewind,
|
|
5391
5599
|
setPendingConnect,
|
|
5392
5600
|
showPicker,
|
|
5601
|
+
handlePickerCancel,
|
|
5602
|
+
setPicker,
|
|
5393
5603
|
stopBackgroundWork
|
|
5394
5604
|
]);
|
|
5395
5605
|
const runShellBang = useCallback(
|
|
@@ -5479,13 +5689,55 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
5479
5689
|
const images = pendingImagesRef.current.map((staged) => staged.image);
|
|
5480
5690
|
if (images.length > 0) clearPendingImages();
|
|
5481
5691
|
if (abortRef.current || busyCommandRef.current) {
|
|
5692
|
+
const backend2 = backendRef.current;
|
|
5693
|
+
if (abortRef.current && images.length === 0 && backend2 instanceof AgentLoop) {
|
|
5694
|
+
void (async () => {
|
|
5695
|
+
const picked = await showPicker("Turn is running \u2014 how should this be sent?", [
|
|
5696
|
+
{
|
|
5697
|
+
value: "steer",
|
|
5698
|
+
label: "insert into the running turn",
|
|
5699
|
+
description: "delivered to the model at the next step boundary"
|
|
5700
|
+
},
|
|
5701
|
+
{
|
|
5702
|
+
value: "queue",
|
|
5703
|
+
label: "queue for after the turn",
|
|
5704
|
+
description: "sent as a new prompt once the current turn finishes"
|
|
5705
|
+
}
|
|
5706
|
+
]);
|
|
5707
|
+
if (picked === "steer") {
|
|
5708
|
+
backend2.injectUserMessage(text);
|
|
5709
|
+
pushMessage(
|
|
5710
|
+
"user",
|
|
5711
|
+
text,
|
|
5712
|
+
"steering the running turn \u2014 the model sees it at the next step",
|
|
5713
|
+
void 0,
|
|
5714
|
+
void 0,
|
|
5715
|
+
void 0,
|
|
5716
|
+
true
|
|
5717
|
+
);
|
|
5718
|
+
return;
|
|
5719
|
+
}
|
|
5720
|
+
queueRef.current.enqueue({ text, images });
|
|
5721
|
+
setQueueItems(queueRef.current.list());
|
|
5722
|
+
})();
|
|
5723
|
+
return;
|
|
5724
|
+
}
|
|
5482
5725
|
queueRef.current.enqueue({ text, images });
|
|
5483
5726
|
setQueueItems(queueRef.current.list());
|
|
5484
5727
|
return;
|
|
5485
5728
|
}
|
|
5486
5729
|
void runStream(text, images);
|
|
5487
5730
|
},
|
|
5488
|
-
[
|
|
5731
|
+
[
|
|
5732
|
+
registry,
|
|
5733
|
+
pushMessage,
|
|
5734
|
+
runStream,
|
|
5735
|
+
runShellBang,
|
|
5736
|
+
config,
|
|
5737
|
+
clearPendingImages,
|
|
5738
|
+
sessionCostUsd,
|
|
5739
|
+
showPicker
|
|
5740
|
+
]
|
|
5489
5741
|
);
|
|
5490
5742
|
const commandHints = useMemo(
|
|
5491
5743
|
() => registry.list().map((cmd) => ({
|
|
@@ -5497,15 +5749,26 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
5497
5749
|
[registry]
|
|
5498
5750
|
);
|
|
5499
5751
|
useEffect4(() => {
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5752
|
+
const refresh = () => {
|
|
5753
|
+
setGitBranch(getGitSummaryCached(cwd)?.branch ?? null);
|
|
5754
|
+
const current = backendRef.current;
|
|
5755
|
+
if (current instanceof AgentLoop) {
|
|
5756
|
+
const window_ = contextWindowTokens(config, modelNameRef.current);
|
|
5757
|
+
const used = current.estimateContextTokens();
|
|
5758
|
+
const pct = used / window_ * 100;
|
|
5759
|
+
setContextUsage({
|
|
5760
|
+
percent: pct < 10 ? Math.round(pct * 10) / 10 : Math.round(pct),
|
|
5761
|
+
used,
|
|
5762
|
+
window: window_
|
|
5763
|
+
});
|
|
5764
|
+
} else {
|
|
5765
|
+
setContextUsage(null);
|
|
5766
|
+
}
|
|
5767
|
+
};
|
|
5768
|
+
refresh();
|
|
5769
|
+
if (!isStreaming) return;
|
|
5770
|
+
const timer = setInterval(refresh, 2e3);
|
|
5771
|
+
return () => clearInterval(timer);
|
|
5509
5772
|
}, [cwd, config, isStreaming, epoch, modelName]);
|
|
5510
5773
|
const sessionCost = sessionCostUsd();
|
|
5511
5774
|
return /* @__PURE__ */ jsxs14(Box13, { flexDirection: "column", children: [
|
|
@@ -5545,7 +5808,8 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
5545
5808
|
title: picker.title,
|
|
5546
5809
|
options: picker.options,
|
|
5547
5810
|
onSelect: handlePickerSelect,
|
|
5548
|
-
onCancel: handlePickerCancel
|
|
5811
|
+
onCancel: handlePickerCancel,
|
|
5812
|
+
onDelete: picker.onDelete
|
|
5549
5813
|
}
|
|
5550
5814
|
),
|
|
5551
5815
|
pendingConnect && /* @__PURE__ */ jsx11(
|
|
@@ -5598,7 +5862,8 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
5598
5862
|
permissionMode: permissionModeState,
|
|
5599
5863
|
tokens: usageRef.current.totalTokens,
|
|
5600
5864
|
gitBranch,
|
|
5601
|
-
contextPercent,
|
|
5865
|
+
contextPercent: contextUsage?.percent ?? null,
|
|
5866
|
+
contextTokens: contextUsage ? { used: contextUsage.used, window: contextUsage.window } : null,
|
|
5602
5867
|
cachePercent: usageRef.current.cache ? cacheHitPercent(usageRef.current.cache) : null,
|
|
5603
5868
|
sessionCostUsd: sessionCost,
|
|
5604
5869
|
backgroundTasks: bgLabels
|
|
@@ -5634,4 +5899,4 @@ export {
|
|
|
5634
5899
|
Repl,
|
|
5635
5900
|
renderRepl
|
|
5636
5901
|
};
|
|
5637
|
-
//# sourceMappingURL=repl-
|
|
5902
|
+
//# sourceMappingURL=repl-SSCURTAH.js.map
|