@cryer/star-cli 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -9
- package/dist/{chunk-GN236FD4.js → chunk-DZWTIMJ2.js} +563 -272
- package/dist/chunk-DZWTIMJ2.js.map +1 -0
- package/dist/{loop-ADVWZA62.js → loop-EIODKYPT.js} +2 -2
- package/dist/main.js +185 -65
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-GN236FD4.js.map +0 -1
- /package/dist/{loop-ADVWZA62.js.map → loop-EIODKYPT.js.map} +0 -0
package/dist/main.js
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
compactMessages,
|
|
15
15
|
createDefaultRegistry,
|
|
16
16
|
createIgnorePredicate,
|
|
17
|
+
defaultAgentTasks,
|
|
17
18
|
defaultTaskManager,
|
|
18
19
|
discoverSkills,
|
|
19
20
|
estimateTokens,
|
|
@@ -29,6 +30,8 @@ import {
|
|
|
29
30
|
isGitRepo,
|
|
30
31
|
isSensitivePath,
|
|
31
32
|
listSnapshots,
|
|
33
|
+
loadTodos,
|
|
34
|
+
parseTodoArgs,
|
|
32
35
|
projectConfigPath,
|
|
33
36
|
reconcileToolCalls,
|
|
34
37
|
resolveShell,
|
|
@@ -38,7 +41,7 @@ import {
|
|
|
38
41
|
summarizeMessages,
|
|
39
42
|
undoTurnSnapshots,
|
|
40
43
|
userMemoryPath
|
|
41
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-DZWTIMJ2.js";
|
|
42
45
|
|
|
43
46
|
// src/main.tsx
|
|
44
47
|
import { Command } from "commander";
|
|
@@ -272,8 +275,8 @@ var UsageTracker = class {
|
|
|
272
275
|
};
|
|
273
276
|
|
|
274
277
|
// src/cli/repl.tsx
|
|
275
|
-
import { Box as
|
|
276
|
-
import { useCallback, useEffect as useEffect2, useMemo, useRef as
|
|
278
|
+
import { Box as Box11, Text as Text12, render, useApp, useInput as useInput6 } from "ink";
|
|
279
|
+
import { useCallback, useEffect as useEffect2, useMemo, useRef as useRef3, useState as useState3 } from "react";
|
|
277
280
|
|
|
278
281
|
// src/config/save.ts
|
|
279
282
|
import fs from "fs";
|
|
@@ -368,6 +371,20 @@ var ConfigSchema = z.object({
|
|
|
368
371
|
// gracefully (some relays never send the terminal chunks). Applies once
|
|
369
372
|
// streaming has started; the first part gets a longer, fixed allowance.
|
|
370
373
|
streamIdleTimeoutSec: z.number().positive().default(20),
|
|
374
|
+
// Seconds to wait for the very first stream part before giving up; slow
|
|
375
|
+
// thinking-model relays can buffer for minutes before sending anything.
|
|
376
|
+
streamFirstChunkTimeoutSec: z.number().positive().default(300),
|
|
377
|
+
// Extra attempts per model request when a stream fails transiently
|
|
378
|
+
// (network error, 429/5xx, idle watchdog cutoff) or comes back empty, so a
|
|
379
|
+
// relay hiccup does not silently end a half-finished turn. 0 disables.
|
|
380
|
+
// Retries after a timeout/empty failure scale both stream timeouts up
|
|
381
|
+
// (attempt number ×, capped at 3x) since the relay is likely overloaded.
|
|
382
|
+
streamMaxRetries: z.number().int().min(0).default(3),
|
|
383
|
+
// How many times a turn may be nudged to continue when the model ends it
|
|
384
|
+
// with a text-only reply that announces pending work ("我将…", "I will…")
|
|
385
|
+
// instead of tool calls — a common premature-stop failure of weaker
|
|
386
|
+
// agentic models. Never fires in plan mode. 0 disables.
|
|
387
|
+
maxAutoContinues: z.number().int().min(0).default(2),
|
|
371
388
|
contextCompaction: z.enum(["summary", "truncate"]).default("summary"),
|
|
372
389
|
// Optional per-session dollar budget; when set, the REPL stops the session
|
|
373
390
|
// once the estimated cost for the session reaches this amount.
|
|
@@ -2562,6 +2579,16 @@ function InputBox({
|
|
|
2562
2579
|
return;
|
|
2563
2580
|
}
|
|
2564
2581
|
if (key.return) {
|
|
2582
|
+
if (key.shift) {
|
|
2583
|
+
edit(`${value.slice(0, cursor)}
|
|
2584
|
+
${value.slice(cursor)}`, cursor + 1);
|
|
2585
|
+
return;
|
|
2586
|
+
}
|
|
2587
|
+
if (value[cursor - 1] === "\\") {
|
|
2588
|
+
edit(`${value.slice(0, cursor - 1)}
|
|
2589
|
+
${value.slice(cursor)}`, cursor);
|
|
2590
|
+
return;
|
|
2591
|
+
}
|
|
2565
2592
|
const text = value.trim();
|
|
2566
2593
|
if (text.length > 0) {
|
|
2567
2594
|
setHistory((prev) => [...prev, text]);
|
|
@@ -2572,6 +2599,11 @@ function InputBox({
|
|
|
2572
2599
|
draftRef.current = "";
|
|
2573
2600
|
return;
|
|
2574
2601
|
}
|
|
2602
|
+
if (input === "\n" || input === "\r" || /^\[13;\d+u$/.test(input)) {
|
|
2603
|
+
edit(`${value.slice(0, cursor)}
|
|
2604
|
+
${value.slice(cursor)}`, cursor + 1);
|
|
2605
|
+
return;
|
|
2606
|
+
}
|
|
2575
2607
|
if (key.tab) {
|
|
2576
2608
|
if (key.shift) return;
|
|
2577
2609
|
if (suggestionCount > 0) {
|
|
@@ -2648,19 +2680,18 @@ function InputBox({
|
|
|
2648
2680
|
return;
|
|
2649
2681
|
}
|
|
2650
2682
|
if (input && !key.ctrl && !key.meta) {
|
|
2651
|
-
|
|
2683
|
+
const text = input.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
2684
|
+
edit(value.slice(0, cursor) + text + value.slice(cursor), cursor + text.length);
|
|
2652
2685
|
}
|
|
2653
2686
|
});
|
|
2654
2687
|
const before = value.slice(0, cursor);
|
|
2655
|
-
const at = value[cursor]
|
|
2688
|
+
const at = value[cursor];
|
|
2656
2689
|
const after = value.slice(cursor + 1);
|
|
2690
|
+
const cursorChar = at === "\n" || at === void 0 ? " " : at;
|
|
2691
|
+
const tail = (at === "\n" ? "\n" : "") + after;
|
|
2692
|
+
const styled = `\x1B[36m> \x1B[39m${before}\x1B[7m${cursorChar}\x1B[27m${tail}`;
|
|
2657
2693
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
2658
|
-
/* @__PURE__ */
|
|
2659
|
-
/* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "> " }),
|
|
2660
|
-
/* @__PURE__ */ jsx2(Text2, { children: before }),
|
|
2661
|
-
/* @__PURE__ */ jsx2(Text2, { inverse: true, children: at }),
|
|
2662
|
-
/* @__PURE__ */ jsx2(Text2, { children: after })
|
|
2663
|
-
] }),
|
|
2694
|
+
/* @__PURE__ */ jsx2(Box2, { borderStyle: "round", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsx2(Text2, { children: styled }) }),
|
|
2664
2695
|
suggestions.length > 0 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", paddingLeft: 2, children: suggestions.map((cmd, index) => {
|
|
2665
2696
|
const label = cmd.usage ?? `/${cmd.name}`;
|
|
2666
2697
|
return index === activeIndex ? /* @__PURE__ */ jsx2(Text2, { bold: true, inverse: true, children: `${label} - ${cmd.description}` }, cmd.name) : /* @__PURE__ */ jsxs2(Text2, { children: [
|
|
@@ -2777,25 +2808,30 @@ function RewindConfirmPrompt({ summary, onDecision }) {
|
|
|
2777
2808
|
|
|
2778
2809
|
// src/cli/components/SelectPrompt.tsx
|
|
2779
2810
|
import { Box as Box6, Text as Text7, useInput as useInput5 } from "ink";
|
|
2780
|
-
import { useState as useState2 } from "react";
|
|
2811
|
+
import { useRef as useRef2, useState as useState2 } from "react";
|
|
2781
2812
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2782
2813
|
var SELECT_PROMPT_MAX_VISIBLE = 9;
|
|
2783
2814
|
function SelectPrompt({ title, options, onSelect, onCancel }) {
|
|
2784
2815
|
const [index, setIndex] = useState2(0);
|
|
2816
|
+
const indexRef = useRef2(0);
|
|
2817
|
+
const move = (delta) => {
|
|
2818
|
+
indexRef.current = Math.max(0, Math.min(indexRef.current + delta, options.length - 1));
|
|
2819
|
+
setIndex(indexRef.current);
|
|
2820
|
+
};
|
|
2785
2821
|
useInput5((input, key) => {
|
|
2786
2822
|
if (key.escape) {
|
|
2787
2823
|
onCancel();
|
|
2788
2824
|
return;
|
|
2789
2825
|
}
|
|
2790
2826
|
if (key.return) {
|
|
2791
|
-
const option = options[
|
|
2827
|
+
const option = options[indexRef.current];
|
|
2792
2828
|
if (option) onSelect(option.value);
|
|
2793
2829
|
return;
|
|
2794
2830
|
}
|
|
2795
2831
|
if (key.downArrow || input === "j") {
|
|
2796
|
-
|
|
2832
|
+
move(1);
|
|
2797
2833
|
} else if (key.upArrow || input === "k") {
|
|
2798
|
-
|
|
2834
|
+
move(-1);
|
|
2799
2835
|
}
|
|
2800
2836
|
});
|
|
2801
2837
|
const maxStart = Math.max(0, options.length - SELECT_PROMPT_MAX_VISIBLE);
|
|
@@ -2943,6 +2979,31 @@ function ThinkingIndicator({
|
|
|
2943
2979
|
] });
|
|
2944
2980
|
}
|
|
2945
2981
|
|
|
2982
|
+
// src/cli/components/TodoPanel.tsx
|
|
2983
|
+
import { Box as Box10, Text as Text11 } from "ink";
|
|
2984
|
+
import { jsx as jsx9, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2985
|
+
var SYMBOLS = {
|
|
2986
|
+
pending: "[ ]",
|
|
2987
|
+
in_progress: "[~]",
|
|
2988
|
+
done: "[x]"
|
|
2989
|
+
};
|
|
2990
|
+
function TodoPanel({ todos }) {
|
|
2991
|
+
if (todos.length === 0) return null;
|
|
2992
|
+
return /* @__PURE__ */ jsx9(Box10, { flexDirection: "column", children: todos.map((todo) => /* @__PURE__ */ jsxs11(
|
|
2993
|
+
Text11,
|
|
2994
|
+
{
|
|
2995
|
+
dimColor: todo.status === "done",
|
|
2996
|
+
color: todo.status === "in_progress" ? "cyan" : void 0,
|
|
2997
|
+
children: [
|
|
2998
|
+
SYMBOLS[todo.status],
|
|
2999
|
+
" ",
|
|
3000
|
+
todo.title
|
|
3001
|
+
]
|
|
3002
|
+
},
|
|
3003
|
+
todo.id
|
|
3004
|
+
)) });
|
|
3005
|
+
}
|
|
3006
|
+
|
|
2946
3007
|
// src/cli/components/ToolCallCard.tsx
|
|
2947
3008
|
function formatToolCard(card) {
|
|
2948
3009
|
const header = `${card.name} ${card.argsSummary}${card.isError ? " [error]" : ""}`;
|
|
@@ -3118,13 +3179,15 @@ async function checkForUpdate(currentVersion, fetcher = defaultFetcher2) {
|
|
|
3118
3179
|
}
|
|
3119
3180
|
|
|
3120
3181
|
// src/cli/repl.tsx
|
|
3121
|
-
import { jsx as
|
|
3182
|
+
import { jsx as jsx10, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3122
3183
|
var CLEAR_TERMINAL = process.platform === "win32" ? "\x1B[2J\x1B[0f" : "\x1B[2J\x1B[3J\x1B[H";
|
|
3123
3184
|
function emptyUsage() {
|
|
3124
3185
|
return { requests: 0, promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
3125
3186
|
}
|
|
3126
3187
|
function runningTaskLabels() {
|
|
3127
|
-
|
|
3188
|
+
const shells = defaultTaskManager.list().filter((t) => t.status === "running").map((t) => t.description ?? t.command);
|
|
3189
|
+
const agents = defaultAgentTasks.list().filter((t) => t.status === "running").map((t) => t.description ?? t.id);
|
|
3190
|
+
return [...shells, ...agents];
|
|
3128
3191
|
}
|
|
3129
3192
|
var SESSION_MODE_CYCLE = ["ask", "auto", "readonly", "plan"];
|
|
3130
3193
|
function formatUsage(usage) {
|
|
@@ -3165,44 +3228,45 @@ function Repl({
|
|
|
3165
3228
|
const [spinnerTick, setSpinnerTick] = useState3(0);
|
|
3166
3229
|
const [activity, setActivity] = useState3(null);
|
|
3167
3230
|
const [bgLabels, setBgLabels] = useState3(() => runningTaskLabels());
|
|
3231
|
+
const [todos, setTodos] = useState3([]);
|
|
3168
3232
|
const [permissionModeState, setPermissionModeState] = useState3(permissionMode);
|
|
3169
3233
|
const [planApproval, setPlanApprovalState] = useState3(false);
|
|
3170
3234
|
const [pendingRewind, setPendingRewindState] = useState3(null);
|
|
3171
3235
|
const [picker, setPickerState] = useState3(null);
|
|
3172
|
-
const backendRef =
|
|
3173
|
-
const nextIdRef =
|
|
3174
|
-
const abortRef =
|
|
3175
|
-
const streamedRef =
|
|
3176
|
-
const thinkingRef =
|
|
3177
|
-
const reasoningRef =
|
|
3178
|
-
const tickerStopRef =
|
|
3179
|
-
const flushedRef =
|
|
3180
|
-
const toolCardsRef =
|
|
3181
|
-
const pendingRef =
|
|
3182
|
-
const alwaysAllowedRef =
|
|
3183
|
-
const prevModeRef =
|
|
3184
|
-
const planApprovalRef =
|
|
3185
|
-
const pendingRewindRef =
|
|
3186
|
-
const pickerRef =
|
|
3187
|
-
const modelNameRef =
|
|
3188
|
-
const sessionStoreRef =
|
|
3189
|
-
const usageRef =
|
|
3190
|
-
const turnChunksRef =
|
|
3191
|
-
const messagesRef =
|
|
3236
|
+
const backendRef = useRef3(backend);
|
|
3237
|
+
const nextIdRef = useRef3(initialDisplay.length);
|
|
3238
|
+
const abortRef = useRef3(null);
|
|
3239
|
+
const streamedRef = useRef3("");
|
|
3240
|
+
const thinkingRef = useRef3(false);
|
|
3241
|
+
const reasoningRef = useRef3("");
|
|
3242
|
+
const tickerStopRef = useRef3(null);
|
|
3243
|
+
const flushedRef = useRef3({ streamed: "", reasoning: "" });
|
|
3244
|
+
const toolCardsRef = useRef3(/* @__PURE__ */ new Map());
|
|
3245
|
+
const pendingRef = useRef3(null);
|
|
3246
|
+
const alwaysAllowedRef = useRef3(/* @__PURE__ */ new Set());
|
|
3247
|
+
const prevModeRef = useRef3(null);
|
|
3248
|
+
const planApprovalRef = useRef3(false);
|
|
3249
|
+
const pendingRewindRef = useRef3(null);
|
|
3250
|
+
const pickerRef = useRef3(null);
|
|
3251
|
+
const modelNameRef = useRef3(model);
|
|
3252
|
+
const sessionStoreRef = useRef3(sessionStore);
|
|
3253
|
+
const usageRef = useRef3(initialUsage ? { ...initialUsage } : emptyUsage());
|
|
3254
|
+
const turnChunksRef = useRef3(0);
|
|
3255
|
+
const messagesRef = useRef3(initialDisplay);
|
|
3192
3256
|
const [queueItems, setQueueItems] = useState3([]);
|
|
3193
|
-
const queueRef =
|
|
3257
|
+
const queueRef = useRef3(new PromptQueue());
|
|
3194
3258
|
const [pendingImages, setPendingImages] = useState3([]);
|
|
3195
|
-
const pendingImagesRef =
|
|
3196
|
-
const imageSeqRef =
|
|
3259
|
+
const pendingImagesRef = useRef3([]);
|
|
3260
|
+
const imageSeqRef = useRef3(1);
|
|
3197
3261
|
const [inputRefill, setInputRefill] = useState3();
|
|
3198
|
-
const refillSeqRef =
|
|
3199
|
-
const lastEscRef =
|
|
3262
|
+
const refillSeqRef = useRef3(0);
|
|
3263
|
+
const lastEscRef = useRef3(null);
|
|
3200
3264
|
const [gitBranch, setGitBranch] = useState3(null);
|
|
3201
3265
|
const [contextPercent, setContextPercent] = useState3(null);
|
|
3202
3266
|
const [initialHistory] = useState3(() => loadHistory());
|
|
3203
|
-
const budgetWarnedRef =
|
|
3204
|
-
const budgetExceededRef =
|
|
3205
|
-
const runStreamRef =
|
|
3267
|
+
const budgetWarnedRef = useRef3(false);
|
|
3268
|
+
const budgetExceededRef = useRef3(false);
|
|
3269
|
+
const runStreamRef = useRef3(
|
|
3206
3270
|
null
|
|
3207
3271
|
);
|
|
3208
3272
|
const pushMessage = useCallback(
|
|
@@ -3351,6 +3415,10 @@ function Repl({
|
|
|
3351
3415
|
if (message) pushMessage("system", message);
|
|
3352
3416
|
});
|
|
3353
3417
|
}, [pushMessage]);
|
|
3418
|
+
useEffect2(() => {
|
|
3419
|
+
loadTodos(cwd).then(setTodos).catch(() => {
|
|
3420
|
+
});
|
|
3421
|
+
}, [cwd]);
|
|
3354
3422
|
useEffect2(() => {
|
|
3355
3423
|
const onUpdate = (task) => {
|
|
3356
3424
|
setBgLabels(runningTaskLabels());
|
|
@@ -3366,10 +3434,28 @@ function Repl({
|
|
|
3366
3434
|
});
|
|
3367
3435
|
}
|
|
3368
3436
|
};
|
|
3437
|
+
const onAgentUpdate = (task) => {
|
|
3438
|
+
setBgLabels(runningTaskLabels());
|
|
3439
|
+
const label = task.description ? `: ${task.description}` : "";
|
|
3440
|
+
pushMessage(
|
|
3441
|
+
"system",
|
|
3442
|
+
task.status === "running" ? `Background subagent ${task.id} started${label}` : `Background subagent ${task.id} ${task.status}${label}`
|
|
3443
|
+
);
|
|
3444
|
+
if (task.status !== "running") {
|
|
3445
|
+
notifyBell({
|
|
3446
|
+
enabled: config.notifyBell,
|
|
3447
|
+
thresholdSec: config.notifyBellThresholdSec,
|
|
3448
|
+
noNotifyEnv: process.env.STAR_NO_NOTIFY === "1"
|
|
3449
|
+
});
|
|
3450
|
+
}
|
|
3451
|
+
};
|
|
3369
3452
|
defaultTaskManager.on("update", onUpdate);
|
|
3453
|
+
defaultAgentTasks.on("update", onAgentUpdate);
|
|
3370
3454
|
return () => {
|
|
3371
3455
|
defaultTaskManager.off("update", onUpdate);
|
|
3456
|
+
defaultAgentTasks.off("update", onAgentUpdate);
|
|
3372
3457
|
defaultTaskManager.cleanup();
|
|
3458
|
+
defaultAgentTasks.cleanup();
|
|
3373
3459
|
};
|
|
3374
3460
|
}, [pushMessage, config]);
|
|
3375
3461
|
const interrupt = useCallback(() => {
|
|
@@ -3409,11 +3495,10 @@ function Repl({
|
|
|
3409
3495
|
}, [pushMessage, redrawMessages]);
|
|
3410
3496
|
const handleExit = useCallback(() => {
|
|
3411
3497
|
const killed = defaultTaskManager.cleanup();
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
);
|
|
3498
|
+
const killedAgents = defaultAgentTasks.cleanup();
|
|
3499
|
+
const stopped = [...killed.map((t) => t.id), ...killedAgents.map((t) => t.id)];
|
|
3500
|
+
if (stopped.length > 0) {
|
|
3501
|
+
pushMessage("system", `Stopped ${stopped.length} background task(s): ${stopped.join(", ")}`);
|
|
3417
3502
|
}
|
|
3418
3503
|
exit();
|
|
3419
3504
|
}, [exit, pushMessage]);
|
|
@@ -3598,6 +3683,10 @@ function Repl({
|
|
|
3598
3683
|
name: event.name,
|
|
3599
3684
|
argsSummary: summarizeArgs(event.args)
|
|
3600
3685
|
});
|
|
3686
|
+
if (event.name === "todo_write") {
|
|
3687
|
+
const list = parseTodoArgs(event.args);
|
|
3688
|
+
if (list) setTodos(list);
|
|
3689
|
+
}
|
|
3601
3690
|
setActivity(`running ${event.name}: ${summarizeArgs(event.args, 60)}`);
|
|
3602
3691
|
} else if (event.type === "tool-result") {
|
|
3603
3692
|
const card = toolCardsRef.current.get(event.id) ?? {
|
|
@@ -3630,6 +3719,13 @@ function Repl({
|
|
|
3630
3719
|
sessionStoreRef.current?.addUsage(event.usage).catch(() => {
|
|
3631
3720
|
});
|
|
3632
3721
|
}
|
|
3722
|
+
} else if (event.type === "retry") {
|
|
3723
|
+
pushMessage(
|
|
3724
|
+
"system",
|
|
3725
|
+
`Request failed, retrying (${event.attempt}/${event.maxAttempts}): ${event.reason}`
|
|
3726
|
+
);
|
|
3727
|
+
} else if (event.type === "notice") {
|
|
3728
|
+
pushMessage("system", event.message);
|
|
3633
3729
|
} else if (event.type === "error") {
|
|
3634
3730
|
pushMessage("system", `Error: ${formatStreamError(event.error)}`);
|
|
3635
3731
|
}
|
|
@@ -4068,6 +4164,9 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
4068
4164
|
`maxSteps: ${config.maxSteps}`,
|
|
4069
4165
|
`contextMaxTokens: ${config.contextMaxTokens}`,
|
|
4070
4166
|
`streamIdleTimeoutSec: ${config.streamIdleTimeoutSec}`,
|
|
4167
|
+
`streamFirstChunkTimeoutSec: ${config.streamFirstChunkTimeoutSec}`,
|
|
4168
|
+
`streamMaxRetries: ${config.streamMaxRetries}`,
|
|
4169
|
+
`maxAutoContinues: ${config.maxAutoContinues}`,
|
|
4071
4170
|
`permissions.allow (${config.permissions.allow.length}): ${config.permissions.allow.join(", ") || "(none)"}`,
|
|
4072
4171
|
`hooks (${config.hooks.length}): ${config.hooks.map((h) => h.event).join(", ") || "(none)"}`
|
|
4073
4172
|
].join("\n")
|
|
@@ -4192,9 +4291,9 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
4192
4291
|
}
|
|
4193
4292
|
}, [cwd, config, isStreaming, epoch]);
|
|
4194
4293
|
const sessionCost = sessionCostUsd();
|
|
4195
|
-
return /* @__PURE__ */
|
|
4196
|
-
/* @__PURE__ */
|
|
4197
|
-
(thinking || activity !== null) && /* @__PURE__ */
|
|
4294
|
+
return /* @__PURE__ */ jsxs12(Box11, { flexDirection: "column", children: [
|
|
4295
|
+
/* @__PURE__ */ jsx10(MessageList, { messages }, `messages-${epoch}`),
|
|
4296
|
+
(thinking || activity !== null) && /* @__PURE__ */ jsx10(
|
|
4198
4297
|
ThinkingIndicator,
|
|
4199
4298
|
{
|
|
4200
4299
|
reasoning: thinkingText,
|
|
@@ -4202,9 +4301,9 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
4202
4301
|
activity: activity ?? void 0
|
|
4203
4302
|
}
|
|
4204
4303
|
),
|
|
4205
|
-
!thinking && activity === null && thoughtSummary !== null && /* @__PURE__ */
|
|
4206
|
-
streamingText !== null && (streamingText !== "" || turnChunksRef.current === 0) && /* @__PURE__ */
|
|
4207
|
-
pending && /* @__PURE__ */
|
|
4304
|
+
!thinking && activity === null && thoughtSummary !== null && /* @__PURE__ */ jsx10(Text12, { dimColor: true, children: thoughtSummary }),
|
|
4305
|
+
streamingText !== null && (streamingText !== "" || turnChunksRef.current === 0) && /* @__PURE__ */ jsx10(StreamingMessage, { text: streamingText, continuation: turnChunksRef.current > 0 }),
|
|
4306
|
+
pending && /* @__PURE__ */ jsx10(
|
|
4208
4307
|
PermissionPrompt,
|
|
4209
4308
|
{
|
|
4210
4309
|
request: pending.request,
|
|
@@ -4212,9 +4311,9 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
4212
4311
|
onDecision: handleDecision
|
|
4213
4312
|
}
|
|
4214
4313
|
),
|
|
4215
|
-
planApproval && /* @__PURE__ */
|
|
4216
|
-
pendingRewind && /* @__PURE__ */
|
|
4217
|
-
picker && /* @__PURE__ */
|
|
4314
|
+
planApproval && /* @__PURE__ */ jsx10(ExitPlanPrompt, { onDecision: handlePlanDecision }),
|
|
4315
|
+
pendingRewind && /* @__PURE__ */ jsx10(RewindConfirmPrompt, { summary: pendingRewind.summary, onDecision: handleRewindDecision }),
|
|
4316
|
+
picker && /* @__PURE__ */ jsx10(
|
|
4218
4317
|
SelectPrompt,
|
|
4219
4318
|
{
|
|
4220
4319
|
title: picker.title,
|
|
@@ -4223,16 +4322,17 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
4223
4322
|
onCancel: handlePickerCancel
|
|
4224
4323
|
}
|
|
4225
4324
|
),
|
|
4226
|
-
queueItems.map((item) => /* @__PURE__ */
|
|
4325
|
+
queueItems.map((item) => /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
4227
4326
|
"queued: ",
|
|
4228
4327
|
item.text.length > 80 ? `${item.text.slice(0, 80)}\u2026` : item.text
|
|
4229
4328
|
] }, item.id)),
|
|
4230
|
-
pendingImages.map((staged) => /* @__PURE__ */
|
|
4329
|
+
pendingImages.map((staged) => /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
4231
4330
|
"[image attached: ",
|
|
4232
4331
|
staged.image.path,
|
|
4233
4332
|
"]"
|
|
4234
4333
|
] }, staged.id)),
|
|
4235
|
-
/* @__PURE__ */
|
|
4334
|
+
/* @__PURE__ */ jsx10(TodoPanel, { todos }),
|
|
4335
|
+
/* @__PURE__ */ jsx10(
|
|
4236
4336
|
InputBox,
|
|
4237
4337
|
{
|
|
4238
4338
|
isStreaming,
|
|
@@ -4247,7 +4347,7 @@ ${plan.affected.length} file change(s) will be reverted, ${messageCount} message
|
|
|
4247
4347
|
onPasteImage: handlePasteImage
|
|
4248
4348
|
}
|
|
4249
4349
|
),
|
|
4250
|
-
/* @__PURE__ */
|
|
4350
|
+
/* @__PURE__ */ jsx10(
|
|
4251
4351
|
StatusBar,
|
|
4252
4352
|
{
|
|
4253
4353
|
cwd,
|
|
@@ -4267,7 +4367,7 @@ function renderRepl(backend, opts) {
|
|
|
4267
4367
|
defaultTaskManager.cleanup();
|
|
4268
4368
|
});
|
|
4269
4369
|
return render(
|
|
4270
|
-
/* @__PURE__ */
|
|
4370
|
+
/* @__PURE__ */ jsx10(
|
|
4271
4371
|
Repl,
|
|
4272
4372
|
{
|
|
4273
4373
|
backend,
|
|
@@ -4327,7 +4427,13 @@ function loadConfigSync(cwd, overrides) {
|
|
|
4327
4427
|
var SYSTEM_PROMPT = `You are Star CLI, an AI coding agent running in the user's terminal.
|
|
4328
4428
|
You help with software engineering tasks: reading, writing and editing code, running shell commands, and managing todos.
|
|
4329
4429
|
Be concise and direct. Use tools when they help accomplish the task.
|
|
4330
|
-
|
|
4430
|
+
For any task with two or more steps, start by creating a todo list with todo_write and keep it updated as you progress; only mark an item completed after you have verified its result.
|
|
4431
|
+
The working directory is the user's project root; never touch files outside it without explicit instruction.
|
|
4432
|
+
For conversion, batch-processing, or other scriptable tasks, write a script file into the working directory and run it instead of pasting long inline code into the shell; once the script's output is verified, delete the script unless the user asked to keep it.
|
|
4433
|
+
When a tool call or command fails, read the error output, work out the cause, and try again with a corrected or alternative approach \u2014 never repeat an identical failing call without changing something.
|
|
4434
|
+
Never consider the task finished until you have verified the result yourself: run the tests, the build, or a check command that proves the output is correct, and if verification fails or reveals gaps, keep fixing until it passes.
|
|
4435
|
+
Do not end your turn while the task is still incomplete; keep going until it is done or you are genuinely blocked, and if you are blocked, state exactly what is missing.
|
|
4436
|
+
Never end a reply by announcing what you will do next \u2014 either do it now with tool calls, or do not mention it. Narrating future actions is not progress.`;
|
|
4331
4437
|
async function createLoop(config, modelName, cwd, sessionStore) {
|
|
4332
4438
|
const model = createModel(config, modelName);
|
|
4333
4439
|
const registry = createDefaultRegistry();
|
|
@@ -4411,6 +4517,19 @@ async function printMode(loop, prompt, cwd, json, imagePaths) {
|
|
|
4411
4517
|
case "finish":
|
|
4412
4518
|
usage.add(event.usage);
|
|
4413
4519
|
break;
|
|
4520
|
+
case "retry":
|
|
4521
|
+
if (!json)
|
|
4522
|
+
process.stderr.write(
|
|
4523
|
+
`
|
|
4524
|
+
[retry ${event.attempt}/${event.maxAttempts}] ${event.reason}
|
|
4525
|
+
`
|
|
4526
|
+
);
|
|
4527
|
+
break;
|
|
4528
|
+
case "notice":
|
|
4529
|
+
if (!json) process.stderr.write(`
|
|
4530
|
+
[notice] ${event.message}
|
|
4531
|
+
`);
|
|
4532
|
+
break;
|
|
4414
4533
|
case "error":
|
|
4415
4534
|
if (!json) process.stderr.write(`
|
|
4416
4535
|
[error] ${formatStreamError(event.error)}
|
|
@@ -4444,6 +4563,7 @@ async function printMode(loop, prompt, cwd, json, imagePaths) {
|
|
|
4444
4563
|
}
|
|
4445
4564
|
if (!json) process.stdout.write("\n");
|
|
4446
4565
|
defaultTaskManager.cleanup();
|
|
4566
|
+
defaultAgentTasks.cleanup();
|
|
4447
4567
|
return exitCode;
|
|
4448
4568
|
}
|
|
4449
4569
|
var program = new Command();
|