@cryer/star-cli 0.3.4 → 0.3.6
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 +11 -3
- package/README.zh-CN.md +10 -3
- package/dist/{chunk-K3R42LOX.js → chunk-I6FDXAWX.js} +50 -9
- package/dist/chunk-I6FDXAWX.js.map +1 -0
- package/dist/{loop-SDZVEQND.js → loop-XY3TE5NN.js} +2 -2
- package/dist/main.js +829 -120
- package/dist/main.js.map +1 -1
- package/dist/{stream-H4BYBVAZ.js → stream-EFQPULQQ.js} +4 -2
- package/dist/stream-EFQPULQQ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-K3R42LOX.js.map +0 -1
- package/dist/stream-H4BYBVAZ.js.map +0 -1
- /package/dist/{loop-SDZVEQND.js.map → loop-XY3TE5NN.js.map} +0 -0
package/README.md
CHANGED
|
@@ -52,6 +52,11 @@ Config file: `~/.star-cli/config.toml` (project-level override: `.star/config.to
|
|
|
52
52
|
defaultModel = "gpt"
|
|
53
53
|
permissionMode = "ask" # ask | auto | readonly | yolo | plan
|
|
54
54
|
contextMaxTokens = 100000
|
|
55
|
+
# Max model round-trips ("steps") per turn between progress checkpoints — one
|
|
56
|
+
# step is a reply plus the tool calls it asked for; retries and auto-continue
|
|
57
|
+
# nudges don't count. Reaching the cap while tools still execute resets it
|
|
58
|
+
# with a notice instead of stopping the turn; 0 disables the cap entirely.
|
|
59
|
+
maxSteps = 100
|
|
55
60
|
# compactThresholdTokens = 80000 # optional auto-compaction trigger in tokens; defaults to the
|
|
56
61
|
# context window. /compact always compacts, regardless of this.
|
|
57
62
|
contextCompaction = "summary" # summary | truncate — how over-budget history is compacted
|
|
@@ -83,6 +88,11 @@ model = "gpt-4o"
|
|
|
83
88
|
# optional per-model context window — overrides the top-level contextMaxTokens
|
|
84
89
|
# for compaction and the ctx % in the status bar
|
|
85
90
|
# contextMaxTokens = 272000
|
|
91
|
+
# optional reasoning intensity for thinking models — forwarded verbatim as
|
|
92
|
+
# reasoning_effort on every request. Level naming varies by provider
|
|
93
|
+
# (low/medium/high are common; some add minimal/max...). Unset = server
|
|
94
|
+
# default. The /model picker also offers these levels after a model pick.
|
|
95
|
+
# reasoningEffort = "high"
|
|
86
96
|
# optional per-model pricing in USD per 1M tokens — enables the $ estimate in
|
|
87
97
|
# /cost and /usage. promptPrice prices input tokens (system prompt, history,
|
|
88
98
|
# @file contents, tool results — resent every turn, so the bulk of usage);
|
|
@@ -166,9 +176,7 @@ star --clear-sessions all delete every stored session
|
|
|
166
176
|
|
|
167
177
|
Keys: `ESC` / `Ctrl+C` interrupts the current stream — the partial reply generated so far stays on screen (and in the session history) with a dim `[interrupted]` marker; on a permission prompt: `y` allow, `n` deny, `a` always allow — the generated allow-rule (e.g. `bash(npm test)`) is saved to `permissions.allow` in the config file and survives restarts. Write/edit prompts include a colored diff preview of the pending change. `Shift+Tab` cycles the permission mode for the session (`ask` → `auto` → `readonly` → `plan`; not saved to config). Input editing: arrow keys move the cursor, `Ctrl+A`/`Ctrl+E` jump to start/end, `Ctrl+U`/`Ctrl+K` delete before/after the cursor, `Ctrl+W` deletes the previous word, up/down recall history (persisted to `~/.star-cli/history` across sessions, capped at 50 entries, consecutive duplicates collapsed, slash commands and key-repeat garbage never recorded); while a recalled entry is unmodified up/down keep switching entries, but once you edit the text — or are typing your own multi-line input — up/down move the cursor between lines instead. `Ctrl+R` starts a reverse history search: type to filter (case-insensitive, newest match first), `Ctrl+R`/`↑` for older matches, `↓` for newer, `Enter` to accept the match into the input, `ESC`/`Ctrl+C`/`Ctrl+G` to cancel and restore what you had. Multi-line input: use `Ctrl+J` (or `Alt+Enter`), or end the line with `\` and press `Enter` — pasted multi-line text is kept intact. Pasting a large block (10+ lines or 500+ characters in one go) collapses it into a dim `[pasted #N: L lines]` placeholder so the input box stays compact; the full text is restored into what gets submitted, and `Backspace` removes the placeholder as a unit. A huge paste that the terminal delivers in several chunks is reassembled (via bracketed paste where the terminal supports it) and still collapses into a single placeholder. Typing `/` shows slash-command suggestions with their usage — prefix matches first, then fuzzy subsequence matches; `↑`/`↓` to highlight, `Tab` (or `→` at end of input) to complete, `ESC` to dismiss, and an unknown command name gets a `Did you mean: …` hint. Typing `@` completes file paths relative to the working directory with the same keys; directories end in `/` so `Tab` descends, and `node_modules`, `.git`, `dist` and `.starignore` entries are skipped. `Alt+V` pastes an image from the clipboard as an attachment (each one shows as `[image attached: clipboard.png]` above the input; uses PowerShell on Windows, pngpaste/osascript on macOS, xclip on Linux). Images larger than 2000px on the longest side are automatically downsampled to fit (keeping the aspect ratio, via platform-native tools — no extra installs on Windows/macOS; ImageMagick or ffmpeg on Linux); when resizing isn't possible the original is kept and a warning is shown. `Ctrl+V` also works where the terminal passes it through — Windows Terminal binds Ctrl+V to its own paste, so use `Alt+V` there. While a turn is streaming you can keep typing: submitted prompts (and `!` bangs) queue up as dimmed entries and auto-send in order once the turn finishes; `ESC` during a turn aborts it and clears the queue (the partial reply is kept, marked `[interrupted]`). Pressing `ESC` twice within half a second while idle retracts your last prompt and restores its text into the input for editing.
|
|
168
178
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
The status bar shows the working directory (full path on wide terminals), the git branch, the model, the permission mode, context usage as a percentage of the model's context window (its own `contextMaxTokens` when set, else the top-level one), the session prompt-cache hit rate when the provider reports cache usage (`cache: 42%`, or `cache: Not provided` when it never does), the session cost when the model has pricing configured, and total tokens.
|
|
179
|
+
The status bar shows the working directory (full path on wide terminals), the git branch, the model, the permission mode, context usage as a percentage of the model's context window (its own `contextMaxTokens` when set, else the top-level one), the session prompt-cache hit rate when the provider reports cache usage (`cache: 42%`, or `cache: Not provided` when it never does), the session cost when the model has pricing configured, and total tokens. Model replies render as markdown (headings, emphasis, code blocks, tables) directly in the terminal. Decorative icons use emoji on terminals known to render them double-width (Windows Terminal, VS Code, Kitty, …) and fall back to plain symbols elsewhere so the display never desyncs; force a style with `STAR_ICONS=emoji|plain`.
|
|
172
180
|
|
|
173
181
|
## !shell passthrough
|
|
174
182
|
|
package/README.zh-CN.md
CHANGED
|
@@ -52,6 +52,10 @@ star -p "hi" # non-interactive print mode
|
|
|
52
52
|
defaultModel = "gpt"
|
|
53
53
|
permissionMode = "ask" # ask | auto | readonly | yolo | plan
|
|
54
54
|
contextMaxTokens = 100000
|
|
55
|
+
# 每回合在进度检查点之间允许的最大模型往返("step")数——一个 step 是
|
|
56
|
+
# 一次回复加上它请求的所有工具调用;重试和 auto-continue nudge 不占 step。
|
|
57
|
+
# 到达上限时若工具仍在执行,会发提示并重置额度而不是终止回合;0 表示完全不限。
|
|
58
|
+
maxSteps = 100
|
|
55
59
|
# compactThresholdTokens = 80000 # optional auto-compaction trigger in tokens; defaults to the
|
|
56
60
|
# context window. /compact always compacts, regardless of this.
|
|
57
61
|
contextCompaction = "summary" # summary | truncate — how over-budget history is compacted
|
|
@@ -83,6 +87,11 @@ model = "gpt-4o"
|
|
|
83
87
|
# optional per-model context window — overrides the top-level contextMaxTokens
|
|
84
88
|
# for compaction and the ctx % in the status bar
|
|
85
89
|
# contextMaxTokens = 272000
|
|
90
|
+
# 可选的推理强度(思考模型用)——每次请求原样以 reasoning_effort 发送。
|
|
91
|
+
# 档位命名因服务商/模型而异(常见 low/medium/high,部分还有 minimal/max 等),
|
|
92
|
+
# 因此接受任意字符串,由服务端校验。不设置 = 服务端默认。
|
|
93
|
+
# /model 选完模型后也会接着让你选择推理强度。
|
|
94
|
+
# reasoningEffort = "high"
|
|
86
95
|
# optional per-model pricing in USD per 1M tokens — enables the $ estimate in
|
|
87
96
|
# /cost and /usage. promptPrice prices input tokens (system prompt, history,
|
|
88
97
|
# @file contents, tool results — resent every turn, so the bulk of usage);
|
|
@@ -166,9 +175,7 @@ star --clear-sessions all delete every stored session
|
|
|
166
175
|
|
|
167
176
|
按键:`ESC` / `Ctrl+C` 中断当前流——已生成的部分回复保留在屏幕上(以及会话历史中),并带暗色 `[interrupted]` 标记;在权限提示上:`y` 允许,`n` 拒绝,`a` 始终允许——生成的 allow 规则(如 `bash(npm test)`)会保存到配置文件的 `permissions.allow` 中,重启后依然有效。写入/编辑提示包含待变更内容的彩色 diff 预览。`Shift+Tab` 在会话内循环切换权限模式(`ask` → `auto` → `readonly` → `plan`;不保存到配置)。输入编辑:方向键移动光标,`Ctrl+A`/`Ctrl+E` 跳到行首/行尾,`Ctrl+U`/`Ctrl+K` 删除光标前/后的内容,`Ctrl+W` 删除前一个单词,上/下键回忆历史(跨会话持久化到 `~/.star-cli/history`,上限 50 条,连续重复自动折叠,斜杠命令与按键重复的垃圾输入从不记录);当回忆出的条目未被修改时,上/下键继续在条目间切换,而一旦你编辑了文本——或正在输入自己的多行内容——上/下键改为在行之间移动光标。`Ctrl+R` 启动反向历史搜索:输入以过滤(不区分大小写,最新匹配优先),`Ctrl+R`/`↑` 找更早的匹配,`↓` 找更新的,`Enter` 将匹配接进输入框,`ESC`/`Ctrl+C`/`Ctrl+G` 取消并恢复你原有的内容。多行输入:使用 `Ctrl+J`(或 `Alt+Enter`),或以 `\` 结尾再按 `Enter`——粘贴的多行文本会原样保留。一次性粘贴大块内容(10+ 行或 500+ 字符)会折叠成暗色占位符 `[pasted #N: L lines]`,让输入框保持紧凑;完整文本会在提交时还原,`Backspace` 可将占位符整体删除。终端分多个块送达的超长粘贴会被重新组装(在支持的终端上通过 bracketed paste),并仍然折叠为单个占位符。输入 `/` 会显示斜杠命令建议及其用法——前缀匹配优先,然后是模糊子序列匹配;`↑`/`↓` 高亮,`Tab`(或在输入末尾按 `→`)补全,`ESC` 关闭,未知命令名会给出 `Did you mean: …` 提示。输入 `@` 会以同样的按键补全相对工作目录的文件路径;目录以 `/` 结尾以便用 `Tab` 下钻,`node_modules`、`.git`、`dist` 和 `.starignore` 条目会被跳过。`Alt+V` 把剪贴板中的图片作为附件粘贴(每张图片在输入框上方显示为 `[image attached: clipboard.png]`;Windows 上使用 PowerShell,macOS 上使用 pngpaste/osascript,Linux 上使用 xclip)。最长边超过 2000px 的图片会自动缩放以符合限制(保持宽高比,使用平台原生工具——Windows/macOS 无需额外安装;Linux 上使用 ImageMagick 或 ffmpeg);无法缩放时保留原图并显示警告。在终端透传的地方 `Ctrl+V` 也可用——Windows Terminal 把 Ctrl+V 绑定为自己的粘贴,请在那里使用 `Alt+V`。回合流式输出期间你可以继续输入:提交的提示(和 `!` bang)会以暗色条目排队,回合结束后按序自动发送;回合中按 `ESC` 会中止该回合并清空队列(部分回复保留,标记为 `[interrupted]`)。空闲时半秒内连按两次 `ESC` 会撤回你上一条提示,并把原文恢复进输入框供编辑。
|
|
168
177
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
状态栏显示工作目录(宽终端上显示完整路径)、git 分支、模型、权限模式、上下文用量占模型上下文窗口的百分比(模型自身设置了 `contextMaxTokens` 时用它,否则用顶层值)、服务商上报缓存用量时的会话提示词缓存命中率(`cache: 42%`,从不上报时显示 `cache: Not provided`)、模型配置了定价时的会话成本,以及 token 总数。
|
|
178
|
+
状态栏显示工作目录(宽终端上显示完整路径)、git 分支、模型、权限模式、上下文用量占模型上下文窗口的百分比(模型自身设置了 `contextMaxTokens` 时用它,否则用顶层值)、服务商上报缓存用量时的会话提示词缓存命中率(`cache: 42%`,从不上报时显示 `cache: Not provided`)、模型配置了定价时的会话成本,以及 token 总数。模型回复会以 Markdown 形式直接在终端渲染(标题、强调、代码块、表格等)。装饰图标在已知能正确双宽渲染 emoji 的终端(Windows Terminal、VS Code、Kitty 等)上使用 emoji,其他终端回退为纯符号以避免显示错位;也可用 `STAR_ICONS=emoji|plain` 强制指定。
|
|
172
179
|
|
|
173
180
|
## !shell 直通
|
|
174
181
|
|
|
@@ -34,6 +34,14 @@ var ModelConfigSchema = z.object({
|
|
|
34
34
|
// Per-model context window; overrides the top-level contextMaxTokens for
|
|
35
35
|
// compaction and the status bar when set.
|
|
36
36
|
contextMaxTokens: z.number().int().positive().optional(),
|
|
37
|
+
// Reasoning intensity for thinking models, forwarded verbatim as
|
|
38
|
+
// OpenAI-style reasoning_effort on every request (llm/provider.ts
|
|
39
|
+
// reasoningEffortMetadata) — level naming varies by model/provider
|
|
40
|
+
// (low|medium|high are common; some add minimal/max/xhigh/none), so any
|
|
41
|
+
// non-empty string is accepted and the server validates it. Unset = the
|
|
42
|
+
// request carries no effort field and the server-side default applies.
|
|
43
|
+
// Anthropic maps effort to a thinking budget instead — ignored there.
|
|
44
|
+
reasoningEffort: z.string().min(1).optional(),
|
|
37
45
|
// Cost estimation needs BOTH prices (USD per 1M tokens); with only one set
|
|
38
46
|
// the model is treated as unpriced.
|
|
39
47
|
promptPrice: z.number().nonnegative().optional(),
|
|
@@ -68,7 +76,13 @@ var ConfigSchema = z.object({
|
|
|
68
76
|
permissionMode: z.enum(["auto", "ask", "readonly", "yolo", "plan"]).default("ask"),
|
|
69
77
|
providers: z.array(ProviderConfigSchema).default([]),
|
|
70
78
|
models: z.array(ModelConfigSchema).default([]),
|
|
71
|
-
|
|
79
|
+
// Cap on model round-trips ("steps") per turn between progress checkpoints.
|
|
80
|
+
// One step is a streamed reply plus every tool call it asked for — stream
|
|
81
|
+
// retries and auto-continue nudges do not consume steps. Reaching the cap
|
|
82
|
+
// while tools still execute resets the budget with a notice; the turn stops
|
|
83
|
+
// only when no tool ran since the last checkpoint (the doom-loop
|
|
84
|
+
// signature). 0 disables the cap entirely (opencode/codex have none).
|
|
85
|
+
maxSteps: z.number().int().min(0).default(100),
|
|
72
86
|
contextMaxTokens: z.number().int().positive().default(1e5),
|
|
73
87
|
// Token threshold at which the agent loop auto-compacts the history.
|
|
74
88
|
// Defaults to the effective context window (compact only when full); set a
|
|
@@ -2924,7 +2938,7 @@ var MAX_SUBAGENT_DEPTH = 1;
|
|
|
2924
2938
|
var MAX_REPORT_CHARS = 2e4;
|
|
2925
2939
|
var SUBAGENT_PROMPT = "You are a subagent spawned to handle a focused subtask on behalf of the main agent. Work autonomously with the tools available to you, then finish with a concise report of what you found or did. Your final text is returned to the main agent as the tool result \u2014 make it self-contained.";
|
|
2926
2940
|
async function runSubagent(deps, args, cwd, signal) {
|
|
2927
|
-
const { AgentLoop: AgentLoop2 } = await import("./loop-
|
|
2941
|
+
const { AgentLoop: AgentLoop2 } = await import("./loop-XY3TE5NN.js");
|
|
2928
2942
|
const child = new AgentLoop2({
|
|
2929
2943
|
model: deps.model,
|
|
2930
2944
|
registry: createDefaultRegistry(),
|
|
@@ -2933,6 +2947,7 @@ async function runSubagent(deps, args, cwd, signal) {
|
|
|
2933
2947
|
system: deps.system ? `${deps.system}
|
|
2934
2948
|
|
|
2935
2949
|
${SUBAGENT_PROMPT}` : SUBAGENT_PROMPT,
|
|
2950
|
+
providerMetadata: deps.providerMetadata,
|
|
2936
2951
|
subagentDepth: deps.depth + 1
|
|
2937
2952
|
});
|
|
2938
2953
|
const confirmHandler = deps.getConfirmHandler?.();
|
|
@@ -3210,6 +3225,7 @@ var AgentLoop = class {
|
|
|
3210
3225
|
config: opts.config,
|
|
3211
3226
|
cwd: opts.cwd,
|
|
3212
3227
|
system: opts.system,
|
|
3228
|
+
providerMetadata: opts.providerMetadata,
|
|
3213
3229
|
depth,
|
|
3214
3230
|
getConfirmHandler: () => this.confirmHandler
|
|
3215
3231
|
})
|
|
@@ -3219,6 +3235,11 @@ var AgentLoop = class {
|
|
|
3219
3235
|
getMessages() {
|
|
3220
3236
|
return this.messages;
|
|
3221
3237
|
}
|
|
3238
|
+
// Rebinds the per-call provider metadata (e.g. after the reasoning effort
|
|
3239
|
+
// for the current model changed via /model) without recreating the loop.
|
|
3240
|
+
setProviderMetadata(metadata) {
|
|
3241
|
+
this.opts.providerMetadata = metadata;
|
|
3242
|
+
}
|
|
3222
3243
|
// Swaps the persistence target (/new starts a fresh session mid-REPL).
|
|
3223
3244
|
// Title generation is re-armed so the new session gets one after its first
|
|
3224
3245
|
// turn, and snapshot checkpoints now flow to the new store. The redo stack
|
|
@@ -3475,7 +3496,27 @@ var AgentLoop = class {
|
|
|
3475
3496
|
let lastWasNudge = false;
|
|
3476
3497
|
let usedToolsThisTurn = false;
|
|
3477
3498
|
let openTodos = [];
|
|
3478
|
-
|
|
3499
|
+
const maxSteps = config.maxSteps;
|
|
3500
|
+
let step = 0;
|
|
3501
|
+
let toolExecutedSinceCheckpoint = false;
|
|
3502
|
+
for (; ; ) {
|
|
3503
|
+
if (maxSteps > 0 && step >= maxSteps) {
|
|
3504
|
+
if (!toolExecutedSinceCheckpoint) {
|
|
3505
|
+
yield {
|
|
3506
|
+
type: "error",
|
|
3507
|
+
error: new Error(
|
|
3508
|
+
`Max steps (${maxSteps}) reached with no tool execution since the last checkpoint, stopping.`
|
|
3509
|
+
)
|
|
3510
|
+
};
|
|
3511
|
+
return;
|
|
3512
|
+
}
|
|
3513
|
+
toolExecutedSinceCheckpoint = false;
|
|
3514
|
+
step = 0;
|
|
3515
|
+
yield {
|
|
3516
|
+
type: "notice",
|
|
3517
|
+
message: `maxSteps (${maxSteps}) reached and the turn is still making progress; continuing. Press Esc to interrupt.`
|
|
3518
|
+
};
|
|
3519
|
+
}
|
|
3479
3520
|
if ((this.opts.subagentDepth ?? 0) === 0) {
|
|
3480
3521
|
for (const finished of defaultAgentTasks.drainNotifications()) {
|
|
3481
3522
|
const label = finished.description ? ` "${finished.description}"` : "";
|
|
@@ -3663,6 +3704,8 @@ ${finished.result}`
|
|
|
3663
3704
|
const refusal = this.doomLoopRefusal(call);
|
|
3664
3705
|
if (refusal !== null) {
|
|
3665
3706
|
yield { type: "notice", message: refusal };
|
|
3707
|
+
} else {
|
|
3708
|
+
toolExecutedSinceCheckpoint = true;
|
|
3666
3709
|
}
|
|
3667
3710
|
const result = refusal !== null ? { content: refusal, isError: true } : await this.executeTool(call, signal);
|
|
3668
3711
|
const toolMessage = {
|
|
@@ -3712,11 +3755,8 @@ ${finished.result}`
|
|
|
3712
3755
|
}
|
|
3713
3756
|
}
|
|
3714
3757
|
if (signal.aborted) return;
|
|
3758
|
+
step++;
|
|
3715
3759
|
}
|
|
3716
|
-
yield {
|
|
3717
|
-
type: "error",
|
|
3718
|
-
error: new Error(`Max steps (${config.maxSteps}) reached, stopping.`)
|
|
3719
|
-
};
|
|
3720
3760
|
}
|
|
3721
3761
|
// The permission mode can change at runtime, so the system message is
|
|
3722
3762
|
// recomputed at the start of every turn instead of being frozen by the
|
|
@@ -3773,12 +3813,13 @@ ${summary}`
|
|
|
3773
3813
|
}
|
|
3774
3814
|
}
|
|
3775
3815
|
async *streamOnce(aiTools, signal, timeoutScale = 1) {
|
|
3776
|
-
const { streamChat } = await import("./stream-
|
|
3816
|
+
const { streamChat } = await import("./stream-EFQPULQQ.js");
|
|
3777
3817
|
for await (const event of streamChat({
|
|
3778
3818
|
model: this.opts.model,
|
|
3779
3819
|
messages: this.messages,
|
|
3780
3820
|
tools: aiTools,
|
|
3781
3821
|
abortSignal: signal,
|
|
3822
|
+
providerMetadata: this.opts.providerMetadata,
|
|
3782
3823
|
idleTimeoutMs: this.opts.config.streamIdleTimeoutSec * 1e3 * timeoutScale,
|
|
3783
3824
|
firstPartTimeoutMs: this.opts.config.streamFirstChunkTimeoutSec * 1e3 * timeoutScale
|
|
3784
3825
|
})) {
|
|
@@ -3952,4 +3993,4 @@ export {
|
|
|
3952
3993
|
PLAN_MODE_PROMPT,
|
|
3953
3994
|
AgentLoop
|
|
3954
3995
|
};
|
|
3955
|
-
//# sourceMappingURL=chunk-
|
|
3996
|
+
//# sourceMappingURL=chunk-I6FDXAWX.js.map
|