@cryer/star-cli 0.3.6 → 0.3.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/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/main.tsx","../src/cli/markdown.ts","../src/cli/terminal-text.ts","../src/cli/format.ts","../src/cli/mentions.ts","../src/cli/image.ts","../src/cli/print-json.ts","../src/cli/repl.tsx","../src/config/save.ts","../src/llm/provider.ts","../src/llm/registry.ts","../src/llm/sse-normalize.ts","../src/session/checkpoints.ts","../src/session/clear.ts","../src/session/store.ts","../src/session/list.ts","../src/session/resume.ts","../src/cli/cost.ts","../src/session/usage.ts","../src/version.ts","../src/cli/budget.ts","../src/cli/cache-stats.ts","../src/cli/clipboard.ts","../src/cli/commands/actions.ts","../src/cli/commands/builtin.ts","../src/session/search.ts","../src/cli/diff-preview.ts","../src/cli/commands/connect.ts","../src/config/env.ts","../src/cli/commands/custom.ts","../src/cli/commands/doctor.ts","../src/cli/commands/init-project.ts","../src/cli/commands/redo.ts","../src/cli/commands/registry.ts","../src/cli/commands/rewind.ts","../src/cli/commands/suggest.ts","../src/cli/commands/undo.ts","../src/cli/components/ConnectWizard.tsx","../src/cli/use-input.ts","../src/cli/keypress.ts","../src/cli/components/SelectPrompt.tsx","../src/cli/components/TextField.tsx","../src/cli/components/InputBox.tsx","../src/cli/path-suggest.ts","../src/cli/components/ExitPlanPrompt.tsx","../src/cli/components/MessageList.tsx","../src/cli/components/DiffLines.tsx","../src/cli/components/PermissionPrompt.tsx","../src/cli/components/RewindConfirmPrompt.tsx","../src/cli/components/StatusBar.tsx","../src/cli/icons.ts","../src/cli/components/StreamingMessage.tsx","../src/cli/components/ThinkingIndicator.tsx","../src/cli/components/TodoPanel.tsx","../src/cli/components/ToolCallCard.tsx","../src/cli/double-esc.ts","../src/cli/history.ts","../src/cli/notify.ts","../src/cli/queue.ts","../src/cli/shell-bang.ts","../src/cli/system-prompt.ts","../src/cli/ticker.ts","../src/cli/update-check.ts","../src/config/loader.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { defaultAgentTasks } from \"./agent/agent-tasks\";\nimport { AgentLoop } from \"./agent/loop\";\nimport { formatStreamError } from \"./cli/format\";\nimport { MAX_IMAGE_BYTES, imageMimeType, readImageInput, resolveMentions } from \"./cli/mentions\";\nimport { UsageTracker, eventToJsonLine } from \"./cli/print-json\";\nimport { renderRepl } from \"./cli/repl\";\nimport { SYSTEM_PROMPT } from \"./cli/system-prompt\";\nimport { loadConfigSync } from \"./config/loader\";\nimport { type StarConfig, contextWindowTokens } from \"./config/schema\";\nimport { type CoreMessage, type ImageInput, reconcileToolCalls } from \"./core/messages\";\nimport { createModel, reasoningEffortMetadata } from \"./llm/provider\";\nimport { loadSessionSnapshots } from \"./session/checkpoints\";\nimport { clearSessions } from \"./session/clear\";\nimport {\n findLatestSession,\n formatSessionEntries,\n listSessionEntries,\n resolveSessionId,\n} from \"./session/list\";\nimport { type SessionMeta, SessionStore } from \"./session/store\";\nimport { defaultTaskManager } from \"./tasks/manager\";\nimport { createDefaultRegistry } from \"./tools\";\nimport { hydrateSnapshots } from \"./tools/fs/snapshots\";\nimport { loadTodos } from \"./tools/todo\";\nimport { VERSION } from \"./version\";\n\nasync function createLoop(\n config: StarConfig,\n modelName: string,\n cwd: string,\n sessionStore: SessionStore | null,\n) {\n const model = createModel(config, modelName);\n const registry = createDefaultRegistry();\n return new AgentLoop({\n model,\n registry,\n config,\n cwd,\n system: SYSTEM_PROMPT,\n sessionStore,\n contextMaxTokens: contextWindowTokens(config, modelName),\n providerMetadata: reasoningEffortMetadata(config, modelName),\n });\n}\n\nasync function printMode(\n loop: AgentLoop,\n prompt: string,\n cwd: string,\n json: boolean,\n imagePaths: string[],\n sessionStore: SessionStore | null,\n): Promise<number> {\n const flagImages: ImageInput[] = [];\n for (const imagePath of imagePaths) {\n if (!imageMimeType(imagePath)) {\n process.stderr.write(\n `[error] unsupported image type: ${imagePath} (supported: png, jpg, jpeg, gif, webp)\\n`,\n );\n return 1;\n }\n const image = await readImageInput(imagePath, cwd);\n if (!image) {\n process.stderr.write(\n `[error] cannot read image: ${imagePath} (missing, unreadable, or larger than ${MAX_IMAGE_BYTES / (1024 * 1024)}MB)\\n`,\n );\n return 1;\n }\n flagImages.push(image);\n }\n const controller = new AbortController();\n process.on(\"SIGINT\", () => controller.abort());\n loop.onHookWarning = (message) => {\n process.stderr.write(`[hook] ${message}\\n`);\n };\n const resolved = await resolveMentions(prompt, cwd);\n if (resolved.attached.length > 0) {\n process.stderr.write(`[attached] ${resolved.attached.join(\", \")}\\n`);\n }\n for (const skip of resolved.skipped) {\n process.stderr.write(`[skipped] @${skip.path}: ${skip.reason}\\n`);\n }\n const images = [...flagImages, ...resolved.images];\n const input: string | { text: string; images: ImageInput[] } =\n images.length > 0 ? { text: resolved.input, images } : resolved.input;\n const usage = new UsageTracker();\n let exitCode = 0;\n try {\n for await (const event of loop.stream(input, controller.signal, {\n persistAs: prompt,\n })) {\n if (json) {\n const line = eventToJsonLine(event);\n if (line) process.stdout.write(`${line}\\n`);\n }\n switch (event.type) {\n case \"text-delta\":\n if (!json) process.stdout.write(event.text);\n break;\n case \"reasoning\":\n break;\n case \"tool-call\":\n if (!json) process.stderr.write(`\\n[tool] ${event.name} ${JSON.stringify(event.args)}\\n`);\n break;\n case \"tool-result\": {\n if (!json) {\n const preview =\n event.content.length > 500\n ? `${event.content.slice(0, 500)}... (truncated)`\n : event.content;\n process.stderr.write(`[result] ${event.isError ? \"ERROR: \" : \"\"}${preview}\\n`);\n }\n break;\n }\n case \"finish\":\n usage.add(event.usage);\n // A resumed session (-c/-r -p) must accumulate this turn's usage,\n // same as the REPL does; plain print runs have no store.\n if (event.usage) {\n sessionStore?.addUsage(event.usage).catch(() => {});\n }\n break;\n case \"retry\": {\n if (!json) {\n const wait =\n event.delayMs !== undefined && event.delayMs >= 1000\n ? ` in ${Math.round(event.delayMs / 1000)}s`\n : \"\";\n process.stderr.write(\n `\\n[retry ${event.attempt}/${event.maxAttempts}${wait}] ${event.reason}\\n`,\n );\n }\n break;\n }\n case \"notice\":\n if (!json) process.stderr.write(`\\n[notice] ${event.message}\\n`);\n break;\n case \"error\":\n if (!json) process.stderr.write(`\\n[error] ${formatStreamError(event.error)}\\n`);\n exitCode = 1;\n break;\n }\n if (exitCode !== 0) break;\n }\n } catch (error) {\n if (!(error instanceof DOMException && error.name === \"AbortError\")) {\n const message = error instanceof Error ? formatStreamError(error) : String(error);\n process.stderr.write(`\\n[error] ${message}\\n`);\n exitCode = 1;\n }\n }\n const usageLine = usage.toJsonLine();\n if (usageLine) {\n if (json) {\n process.stdout.write(`${usageLine}\\n`);\n } else {\n const t = usage.totals;\n process.stderr.write(\n `[usage] ${t.requests} requests, ${t.promptTokens} prompt + ${t.completionTokens} completion = ${t.totalTokens} tokens\\n`,\n );\n }\n }\n if (!json) process.stdout.write(\"\\n\");\n const killedShells = defaultTaskManager.cleanup();\n const killedAgents = defaultAgentTasks.cleanup();\n const stopped = killedShells.length + killedAgents.length;\n if (stopped > 0) {\n process.stderr.write(\n `[info] ${stopped} background task(s) were still running and have been stopped.\\n`,\n );\n }\n return exitCode;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"star\")\n .description(\"Star CLI — an AI agent command-line interface\")\n .version(VERSION)\n .option(\"-m, --model <model>\", \"model to use\")\n .option(\"--permission-mode <mode>\", \"permission mode: ask | auto | readonly | yolo | plan\")\n .option(\"-p, --print <prompt>\", \"non-interactive print mode\")\n .option(\"--json\", \"output NDJSON events on stdout (print mode only)\")\n .option(\n \"--image <path>\",\n \"attach an image file (png/jpg/jpeg/gif/webp, max 5MB); repeatable\",\n (value: string, previous: string[]) => [...previous, value],\n [] as string[],\n )\n .option(\"-r, --resume [sessionId]\", \"resume a previous session (lists sessions when no id given)\")\n .option(\"-c, --continue\", \"continue the most recent session for the current directory\")\n .option(\n \"--clear-sessions [scope]\",\n \"delete stored sessions for the current directory ('all' deletes every session) and exit\",\n )\n .action(async (opts) => {\n const cwd = process.cwd();\n\n if (opts.json && opts.print === undefined) {\n console.error(\n '--json requires print mode: use star -p \"...\" --json (the interactive REPL does not support JSON output).',\n );\n process.exit(1);\n }\n\n if (opts.resume !== undefined && opts.continue) {\n console.error(\"Options --resume and --continue are mutually exclusive: pick one.\");\n process.exit(1);\n }\n\n if (opts.resume === true) {\n const entries = await listSessionEntries(cwd);\n if (entries.length === 0) {\n console.error(\"No sessions found for this directory.\");\n } else {\n console.log(formatSessionEntries(entries));\n }\n process.exit(0);\n }\n\n if (opts.clearSessions !== undefined) {\n const scope = opts.clearSessions;\n if (scope !== true && scope !== \"all\") {\n console.error(`Invalid scope: ${scope}. Use --clear-sessions or --clear-sessions all.`);\n process.exit(1);\n }\n const all = scope === \"all\";\n const removed = await clearSessions(all ? undefined : cwd);\n console.log(\n all\n ? `Deleted ${removed} session(s) across all directories.`\n : `Deleted ${removed} session(s) for this directory.`,\n );\n process.exit(0);\n }\n\n let config: StarConfig;\n try {\n config = loadConfigSync(cwd, { model: opts.model, permissionMode: opts.permissionMode });\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n const modelName = opts.model ?? config.defaultModel;\n if (!modelName) {\n console.error(\n \"No model configured. Add one to ~/.star-cli/config.toml or pass --model.\\n\" +\n \"See README.md for configuration examples.\",\n );\n process.exit(1);\n }\n\n let sessionStore: SessionStore | null = null;\n let resumed: { meta: SessionMeta; messages: CoreMessage[] } | null = null;\n let resumeId: string | null = null;\n if (typeof opts.resume === \"string\") {\n resumeId = await resolveSessionId(opts.resume);\n if (!resumeId) {\n console.error(`Session not found: ${opts.resume}`);\n process.exit(1);\n }\n } else if (opts.continue) {\n const latest = await findLatestSession(cwd);\n if (latest) {\n resumeId = latest.id;\n } else {\n process.stderr.write(\"No previous session for this directory — starting a new session.\\n\");\n }\n }\n\n if (resumeId) {\n // Open the store once and read through it: resumeSession() would open a\n // second SessionStore instance on the same directory whose independent\n // meta cache could race this instance's writes.\n sessionStore = await SessionStore.open(resumeId);\n if (!sessionStore) {\n console.error(`Session not found: ${resumeId}`);\n process.exit(1);\n }\n const [meta, loaded] = await Promise.all([sessionStore.meta(), sessionStore.messages()]);\n const messages = reconcileToolCalls(loaded);\n if (messages.length !== loaded.length) {\n await sessionStore.replaceMessages(messages);\n }\n resumed = { meta, messages };\n } else if (!opts.print) {\n sessionStore = await SessionStore.create(cwd, modelName);\n }\n\n let loop: AgentLoop;\n try {\n loop = await createLoop(config, modelName, cwd, sessionStore);\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n if (resumed) {\n await loop.loadMessages(resumed.messages);\n // Resuming explicitly continues the project: rehydrate its todo list\n // (fresh sessions leave it alone even when .star/todos.json exists).\n await loadTodos(cwd);\n if (sessionStore) {\n hydrateSnapshots(await loadSessionSnapshots(sessionStore.dir));\n }\n }\n\n if (opts.print) {\n // Let the loop drain instead of process.exit(): force-exiting on Windows\n // can hit a libuv assertion while undici keep-alive handles are closing.\n process.exitCode = await printMode(\n loop,\n opts.print,\n cwd,\n Boolean(opts.json),\n opts.image ?? [],\n sessionStore,\n );\n return;\n }\n\n renderRepl(loop, {\n model: modelName,\n permissionMode: config.permissionMode,\n config,\n cwd,\n sessionStore,\n initialMessages: resumed?.messages,\n initialUsage: resumed?.meta.usage,\n });\n });\n\nprogram.parse(process.argv);\n","// Minimal markdown renderer for terminal output: compiles a markdown subset\n// (headings, bold/italic/strikethrough, inline code, fenced code blocks,\n// links, images, blockquotes, horizontal rules, pipe tables) into an\n// ANSI-styled string suitable for a single Ink <Text> node.\n//\n// `base` is the ANSI SGR code of the surrounding text color (e.g. \"32\" for\n// the green assistant text): every styled span ends with a full reset, so\n// the base must be re-opened after each span or the rest of the line would\n// lose its color.\n//\n// Streaming-safe: unclosed inline markers and fences render as literal text\n// until completed. Width accounting uses display cells (CJK/emoji = 2) so\n// tables stay aligned for CJK content.\n\nconst ESC = \"\\u001B[\";\nconst RESET = `${ESC}0m`;\n\nfunction styled(open: string, text: string, base: string): string {\n const reopen = base ? `${ESC}${base}m` : \"\";\n return `${ESC}${open}m${text}${RESET}${reopen}`;\n}\n\nconst bold = (t: string, b: string) => styled(\"1\", t, b);\nconst dim = (t: string, b: string) => styled(\"2\", t, b);\nconst italic = (t: string, b: string) => styled(\"3\", t, b);\nconst underline = (t: string, b: string) => styled(\"4\", t, b);\nconst strike = (t: string, b: string) => styled(\"9\", t, b);\nconst yellow = (t: string, b: string) => styled(\"33\", t, b);\nconst cyanBold = (t: string, b: string) => styled(\"1;36\", t, b);\n\n// Display width in terminal cells: CJK-wide and emoji ranges count 2,\n// combining marks / ZWJ / variation selectors count 0. Good enough for table\n// alignment; Ink does its own precise width math for wrapping.\nexport function cellWidth(text: string): number {\n let width = 0;\n for (const ch of text) {\n const cp = ch.codePointAt(0) ?? 0;\n if ((cp >= 0x0300 && cp <= 0x036f) || cp === 0x200d || (cp >= 0xfe00 && cp <= 0xfe0f)) {\n continue;\n }\n if (\n (cp >= 0x1100 && cp <= 0x115f) ||\n (cp >= 0x2e80 && cp <= 0x9fff) ||\n (cp >= 0xa000 && cp <= 0xa4cf) ||\n (cp >= 0xac00 && cp <= 0xd7a3) ||\n (cp >= 0xf900 && cp <= 0xfaff) ||\n (cp >= 0xfe30 && cp <= 0xfe4f) ||\n (cp >= 0xff00 && cp <= 0xff60) ||\n (cp >= 0xffe0 && cp <= 0xffe6) ||\n (cp >= 0x1f000 && cp <= 0x1faff) ||\n (cp >= 0x20000 && cp <= 0x3fffd)\n ) {\n width += 2;\n } else {\n width += 1;\n }\n }\n return width;\n}\n\nconst IMAGE_RE = /!\\[([^\\]]*)\\]\\(([^)\\s]+)\\)/g;\nconst LINK_RE = /\\[([^\\]]+)\\]\\(([^)\\s]+)\\)/g;\nconst BOLD_RE = /\\*\\*([^*\\n]+)\\*\\*|__([^_\\n]+)__/g;\nconst STRIKE_RE = /~~([^~\\n]+)~~/g;\nconst STAR_ITALIC_RE = /\\*([^*\\n]+)\\*/g;\n// _emphasis_ only at word boundaries so snake_case stays literal.\nconst UNDERSCORE_ITALIC_RE = /(^|[^\\w])_([^_\\n]+)_(?=[^\\w]|$)/g;\n\n// Inline styles. Code spans are split out first so their contents are never\n// re-parsed for emphasis markers.\nexport function renderInline(text: string, base = \"\"): string {\n return text\n .split(/`([^`\\n]+)`/)\n .map((segment, index) => {\n // Odd segments are code-span contents.\n if (index % 2 === 1) return yellow(segment, base);\n return segment\n .replace(IMAGE_RE, (_m, alt: string) => dim(`[image: ${alt}]`, base))\n .replace(\n LINK_RE,\n (_m, label: string, url: string) => `${underline(label, base)}${dim(` (${url})`, base)}`,\n )\n .replace(BOLD_RE, (_m, star: string, under: string) => bold(star ?? under, base))\n .replace(STRIKE_RE, (_m, t: string) => strike(t, base))\n .replace(STAR_ITALIC_RE, (_m, t: string) => italic(t, base))\n .replace(UNDERSCORE_ITALIC_RE, (_m, pre: string, t: string) => pre + italic(t, base));\n })\n .join(\"\");\n}\n\nconst HEADING_RE = /^#{1,6}\\s+(.*)$/;\nconst HR_RE = /^\\s{0,3}(?:-{3,}|\\*{3,}|_{3,})\\s*$/;\nconst QUOTE_RE = /^\\s{0,3}>\\s?(.*)$/;\nconst FENCE_RE = /^\\s{0,3}(```+|~~~+)/;\nconst TABLE_SEPARATOR_CELL_RE = /^:?-{3,}:?$/;\n\nfunction isTableSeparator(line: string): boolean {\n const cells = splitTableRow(line);\n return (\n cells !== null &&\n cells.length > 0 &&\n cells.every((cell) => TABLE_SEPARATOR_CELL_RE.test(cell.trim()))\n );\n}\n\nfunction splitTableRow(line: string): string[] | null {\n const trimmed = line.trim();\n if (!trimmed.includes(\"|\")) return null;\n const stripped = trimmed.replace(/^\\|/, \"\").replace(/\\|$/, \"\");\n return stripped.split(\"|\").map((cell) => cell.trim());\n}\n\nconst MIN_COLUMN_WIDTH = 4;\n\n// Wraps a cell to its column width by display cells. Breaks at the last\n// space when there is one, hard-breaks otherwise (CJK text has no spaces).\nfunction wrapCell(text: string, width: number): string[] {\n const lines: string[] = [];\n let current = \"\";\n let currentWidth = 0;\n for (const ch of text) {\n const w = cellWidth(ch);\n if (currentWidth > 0 && currentWidth + w > width) {\n const lastSpace = current.lastIndexOf(\" \");\n if (lastSpace > 0 && ch !== \" \") {\n lines.push(current.slice(0, lastSpace));\n current = current.slice(lastSpace + 1) + ch;\n } else {\n lines.push(current);\n current = ch === \" \" ? \"\" : ch;\n }\n currentWidth = cellWidth(current);\n } else {\n current += ch;\n currentWidth += w;\n }\n }\n if (current.length > 0 || lines.length === 0) lines.push(current);\n return lines;\n}\n\nfunction renderTable(lines: string[], base: string, maxWidth: number): string[] {\n const rows: string[][] = [];\n for (const line of lines) {\n const cells = splitTableRow(line);\n if (cells) rows.push(cells);\n }\n if (rows.length < 2) return lines;\n const columnCount = Math.max(...rows.map((row) => row.length));\n // Natural widths first: columns only shrink when the whole grid would\n // exceed the terminal — then the widest column gives up one cell at a\n // time. Overlong cell text wraps onto extra lines instead of truncating.\n const widths = Array.from({ length: columnCount }, (_, column) =>\n Math.max(1, ...rows.map((row) => cellWidth(row[column] ?? \"\"))),\n );\n // 2 for the indent, 3 per \" │ \" joiner.\n const totalWidth = () =>\n 2 + widths.reduce((sum, width) => sum + width, 0) + 3 * (columnCount - 1);\n while (totalWidth() > maxWidth) {\n const widest = widths.indexOf(Math.max(...widths));\n if (widths[widest] === undefined || widths[widest] <= MIN_COLUMN_WIDTH) break;\n widths[widest] -= 1;\n }\n // Widths come from the raw cell text; padding is appended after styling so\n // ANSI bytes never skew the alignment.\n const joiner = ` ${dim(\"│\", base)} `;\n const formatRow = (row: string[], style: (cell: string) => string): string[] => {\n const wrapped = widths.map((width, column) => wrapCell(row[column] ?? \"\", width));\n const height = Math.max(...wrapped.map((cell) => cell.length));\n const out: string[] = [];\n for (let line = 0; line < height; line++) {\n out.push(\n ` ${widths\n .map((width, column) => {\n const raw = wrapped[column]?.[line] ?? \"\";\n return style(raw) + \" \".repeat(Math.max(0, width - cellWidth(raw)));\n })\n .join(joiner)\n .trimEnd()}`,\n );\n }\n return out;\n };\n const separator = dim(` ${widths.map((width) => \"─\".repeat(width)).join(\"─┼─\")}`, base);\n const [header, , ...body] = rows as [string[], string[], ...string[][]];\n return [\n ...formatRow(header, (cell) => bold(cell, base)),\n separator,\n ...body.flatMap((row, index) => {\n const lines = formatRow(row, (cell) => renderInline(cell, base));\n return index < body.length - 1 ? [...lines, separator] : lines;\n }),\n ];\n}\n\n// Longest leading run of lines that ends at a markdown block boundary: not\n// inside a fenced code block, and not inside a run of pipe lines (a table, or\n// a would-be table whose separator is still streaming). The REPL commits\n// streamed text to static history in chunks and each chunk is rendered\n// standalone, so a chunk must never end mid-construct — a table split in two\n// would render its tail as raw pipe text.\nexport function committableLineCount(lines: string[]): number {\n let inFence = false;\n let safe = 0;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n if (FENCE_RE.test(line)) inFence = !inFence;\n const isPipe = line.includes(\"|\");\n // For the last line the next line is still streaming, so assume the worst.\n const nextIsPipe = i + 1 >= lines.length || (lines[i + 1] ?? \"\").includes(\"|\");\n if (!inFence && !(isPipe && nextIsPipe)) safe = i + 1;\n }\n return safe;\n}\n\n// Renders a markdown block into an ANSI-styled string. `base` re-opens the\n// surrounding text color after each styled span (see module docstring).\n// `maxWidth` caps rendered table grids so rows never wrap in the terminal.\nexport function renderMarkdown(text: string, base = \"\", maxWidth = 80): string {\n const lines = text.split(\"\\n\");\n const out: string[] = [];\n let inFence = false;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n if (inFence) {\n if (FENCE_RE.test(line)) {\n inFence = false;\n } else {\n out.push(`${dim(\" ▎\", base)}${line}`);\n }\n continue;\n }\n const fence = FENCE_RE.exec(line);\n if (fence) {\n inFence = true;\n const lang = line\n .trim()\n .slice(fence[1]?.length ?? 0)\n .trim();\n if (lang) out.push(dim(` ▎ ${lang}`, base));\n continue;\n }\n const heading = HEADING_RE.exec(line);\n if (heading) {\n out.push(cyanBold(heading[1] ?? \"\", base));\n continue;\n }\n if (HR_RE.test(line)) {\n out.push(dim(\" ────────\", base));\n continue;\n }\n const quote = QUOTE_RE.exec(line);\n if (quote) {\n out.push(`${dim(\" ▎\", base)}${italic(renderInline(quote[1] ?? \"\", base), base)}`);\n continue;\n }\n // Pipe table: a header row followed by a --- separator row.\n const headerCells = splitTableRow(line);\n if (headerCells && i + 1 < lines.length && isTableSeparator(lines[i + 1] ?? \"\")) {\n const block = [line];\n let j = i + 1;\n while (j < lines.length && splitTableRow(lines[j] ?? \"\") !== null) {\n block.push(lines[j] ?? \"\");\n j += 1;\n }\n out.push(...renderTable(block, base, maxWidth));\n i = j - 1;\n continue;\n }\n out.push(renderInline(line, base));\n }\n return out.join(\"\\n\");\n}\n","// Model/tool-controlled text lands in Ink's live region, where each frame is\n// erased and redrawn based on Ink's own width math. string-width reports \\t\n// as width 0 while real terminals expand it to the next tab stop, and raw\n// control bytes (\\r, ESC, …) move the cursor — both make the on-screen frame\n// taller than Ink counted, so the erase misses lines and every spinner tick\n// leaves a stale duplicate behind (the \"scroll spam\" bug). Normalize such\n// text before it reaches the terminal: tabs become two spaces, all other C0\n// controls except \\n are dropped. Display-only — persisted messages and tool\n// results keep the original bytes.\n// biome-ignore lint/suspicious/noControlCharactersInRegex: matching control characters is the whole point\nconst UNSAFE_CHARS = /[\\x00-\\x09\\x0b-\\x1f\\x7f]/;\n// biome-ignore lint/suspicious/noControlCharactersInRegex: matching control characters is the whole point\nconst CONTROL_CHARS = /[\\x00-\\x08\\x0b-\\x1f\\x7f]/g;\nconst TABS = /\\t/g;\n\nexport function toTerminalSafe(text: string): string {\n if (!UNSAFE_CHARS.test(text)) return text;\n return text.replace(TABS, \" \").replace(CONTROL_CHARS, \"\");\n}\n","import type { CoreMessage } from \"../core/messages\";\nimport type { DisplayMessage } from \"./components/MessageList\";\nimport { committableLineCount } from \"./markdown\";\nimport { toTerminalSafe } from \"./terminal-text\";\n\nexport function summarizeArgs(args: unknown, maxLength = 120): string {\n let json: string;\n try {\n json = JSON.stringify(args) ?? String(args);\n } catch {\n json = String(args);\n }\n return json.length > maxLength ? `${json.slice(0, maxLength)}...` : json;\n}\n\nexport function previewLines(text: string, maxLines = 10): { text: string; truncated: boolean } {\n const lines = text.split(\"\\n\");\n if (lines.length <= maxLines) return { text, truncated: false };\n return { text: lines.slice(0, maxLines).join(\"\\n\"), truncated: true };\n}\n\n// Splits a streaming buffer into a committable head (complete lines) and a\n// remainder, once the buffer holds at least minCompleteLines complete lines.\n// The last line is always kept in the remainder: it may still be growing.\n// The head is further capped at a markdown block boundary (never mid-table\n// or mid-fence) because committed chunks render standalone in static history.\n// Returns null when there is nothing worth committing yet.\nexport function splitCommittableLines(\n text: string,\n minCompleteLines: number,\n): { committed: string; rest: string } | null {\n const lastNewline = text.lastIndexOf(\"\\n\");\n if (lastNewline < 0) return null;\n const complete = text.slice(0, lastNewline);\n const lines = complete.split(\"\\n\");\n const count = committableLineCount(lines);\n if (count < minCompleteLines) return null;\n const committed = lines.slice(0, count).join(\"\\n\");\n return { committed, rest: text.slice(committed.length + 1) };\n}\n\nexport function formatStreamError(error: Error): string {\n if (error.message.includes(\"Unexpected end of JSON input\")) {\n return `${error.message} (response stream was truncated — try again)`;\n }\n return error.message;\n}\n\nexport function coreMessageText(message: CoreMessage): string {\n const content = message.content;\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .filter((part) => part.type === \"text\")\n .map((part) => (\"text\" in part ? part.text : \"\"))\n .join(\" \");\n }\n return \"\";\n}\n\nexport function buildDisplayMessages(messages: CoreMessage[]): DisplayMessage[] {\n const display: DisplayMessage[] = [];\n let collapsed = 0;\n for (const message of messages) {\n if (message.role === \"user\" || message.role === \"assistant\") {\n const text = coreMessageText(message);\n if (text) {\n // Restored history skips the streaming ingestion path, so escape it\n // here instead (idempotent — live-turn text is already normalized).\n display.push({ id: display.length, role: message.role, text: toTerminalSafe(text) });\n } else {\n collapsed++;\n }\n } else if (message.role === \"tool\") {\n collapsed++;\n }\n }\n if (collapsed > 0) {\n display.push({\n id: display.length,\n role: \"system\",\n text: `Restored ${collapsed} history message(s) not shown here.`,\n });\n }\n return display;\n}\n","import { readFile, readdir, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { ImageInput } from \"../core/messages\";\nimport {\n type IgnorePredicate,\n SKIP_DIRS,\n createIgnorePredicate,\n isSensitivePath,\n} from \"../tools/fs/util\";\nimport { downsampleImageIfNeeded } from \"./image\";\n\nexport const MAX_MENTION_BYTES = 100 * 1024;\nexport const MAX_IMAGE_BYTES = 5 * 1024 * 1024;\nexport const MAX_DIR_MENTION_ENTRIES = 200;\nexport const MAX_DIR_MENTION_DEPTH = 10;\n// Backstop for the total-entry count: past this the listing reports \"many\n// more entries\" instead of counting a huge tree (e.g. @. in a repo) to the\n// end.\nexport const MAX_DIR_MENTION_TOTAL = 5000;\n\nconst IMAGE_MIME_TYPES: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n};\n\nexport function imageMimeType(filePath: string): string | null {\n return IMAGE_MIME_TYPES[path.extname(filePath).toLowerCase()] ?? null;\n}\n\n// Reads an image file into a base64 ImageInput, downsampling anything past\n// the dimension cap. Returns null when the path is not a supported image or\n// cannot be read.\nexport async function readImageInput(filePath: string, cwd: string): Promise<ImageInput | null> {\n const mimeType = imageMimeType(filePath);\n if (!mimeType) return null;\n const abs = path.resolve(cwd, filePath);\n const st = await stat(abs).catch(() => null);\n if (!st || !st.isFile() || st.size > MAX_IMAGE_BYTES) return null;\n const buf = await readFile(abs).catch(() => null);\n if (!buf) return null;\n const result = await downsampleImageIfNeeded({\n path: filePath,\n mimeType,\n data: buf.toString(\"base64\"),\n });\n return result.image;\n}\n\nexport interface ParsedMentions {\n cleanText: string;\n mentions: string[];\n}\n\n// CJK ranges cover unified ideographs, Hangul syllables, compatibility\n// ideographs and fullwidth forms so @中文文件名.md mentions parse. Keep in\n// sync with the token charset path-suggest's extractAtToken accepts (\\S).\nconst MENTION_RE =\n /(?<=^|\\s)@([A-Za-z]:[\\\\/][A-Za-z0-9._\\-/\\\\\\u2e80-\\u9fff\\uac00-\\ud7af\\uf900-\\ufaff\\uff00-\\uffef]*|[A-Za-z0-9._\\-/\\\\\\u2e80-\\u9fff\\uac00-\\ud7af\\uf900-\\ufaff\\uff00-\\uffef]+)/g;\n\nexport function parseMentions(text: string): ParsedMentions {\n const mentions: string[] = [];\n const seen = new Set<string>();\n const ranges: Array<[number, number]> = [];\n for (const match of text.matchAll(MENTION_RE)) {\n const mention = match[1];\n const full = match[0];\n if (mention === undefined || full === undefined) continue;\n ranges.push([match.index, match.index + full.length]);\n if (!seen.has(mention)) {\n seen.add(mention);\n mentions.push(mention);\n }\n }\n if (ranges.length === 0) {\n return { cleanText: text, mentions };\n }\n let clean = \"\";\n let last = 0;\n for (const [start, end] of ranges) {\n clean += text.slice(last, start);\n last = end;\n }\n clean += text.slice(last);\n const cleanText = clean\n .replace(/[ \\t]+\\n/g, \"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n return { cleanText, mentions };\n}\n\nexport interface MentionSkip {\n path: string;\n reason: string;\n}\n\nexport interface ResolvedMentions {\n input: string;\n attached: string[];\n skipped: MentionSkip[];\n images: ImageInput[];\n}\n\nfunction isBinaryContent(buf: Buffer): boolean {\n const probe = buf.subarray(0, 8000);\n return probe.includes(0);\n}\n\ninterface DirListState {\n lines: string[];\n shown: number;\n total: number;\n capped: boolean;\n}\n\nasync function listDirEntries(\n dir: string,\n prefix: string,\n depth: number,\n state: DirListState,\n ignore: IgnorePredicate | undefined,\n): Promise<void> {\n if (state.capped) return;\n const entries = await readdir(dir, { withFileTypes: true }).catch(() => null);\n if (!entries) return;\n const visible = entries\n .filter((entry) => entry.isDirectory() || entry.isFile())\n .filter((entry) => !(entry.isDirectory() && SKIP_DIRS.has(entry.name)))\n .filter((entry) => !isSensitivePath(entry.name))\n .filter((entry) => !ignore?.(path.join(dir, entry.name), entry.isDirectory()))\n .sort((a, b) => {\n const dirDiff = Number(b.isDirectory()) - Number(a.isDirectory());\n return dirDiff !== 0 ? dirDiff : a.name.localeCompare(b.name);\n });\n for (let i = 0; i < visible.length; i++) {\n if (state.total >= MAX_DIR_MENTION_TOTAL) {\n state.capped = true;\n return;\n }\n const entry = visible[i];\n if (!entry) continue;\n state.total += 1;\n const last = i === visible.length - 1;\n const isDir = entry.isDirectory();\n if (state.shown < MAX_DIR_MENTION_ENTRIES) {\n state.shown += 1;\n state.lines.push(`${prefix}${last ? \"└── \" : \"├── \"}${entry.name}${isDir ? \"/\" : \"\"}`);\n if (isDir && depth < MAX_DIR_MENTION_DEPTH) {\n await listDirEntries(\n path.join(dir, entry.name),\n `${prefix}${last ? \" \" : \"│ \"}`,\n depth + 1,\n state,\n ignore,\n );\n }\n } else if (isDir && depth < MAX_DIR_MENTION_DEPTH) {\n await listDirEntries(path.join(dir, entry.name), prefix, depth + 1, state, ignore);\n }\n }\n}\n\n// Renders a directory mention as an indented tree block. Returns null when the\n// directory cannot be read at all.\nasync function directoryBlock(\n abs: string,\n mention: string,\n ignore: IgnorePredicate | undefined,\n): Promise<string | null> {\n const display = `${mention.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\")}/`;\n const state: DirListState = { lines: [`${display}`], shown: 0, total: 0, capped: false };\n const probe = await readdir(abs).catch(() => null);\n if (!probe) return null;\n await listDirEntries(abs, \"\", 1, state, ignore);\n if (state.capped) {\n state.lines.push(\"... (truncated, many more entries)\");\n } else if (state.total > state.shown) {\n state.lines.push(\n `... (truncated, ${state.total - state.shown} more entries — use glob/grep tools or mention a subdirectory to see more)`,\n );\n }\n return `--- @${display} (directory) ---\\n${state.lines.join(\"\\n\")}\\n--- end ---`;\n}\n\nexport async function resolveMentions(text: string, cwd: string): Promise<ResolvedMentions> {\n const { cleanText, mentions } = parseMentions(text);\n if (mentions.length === 0) {\n return { input: text, attached: [], skipped: [], images: [] };\n }\n const blocks: string[] = [];\n const attached: string[] = [];\n const skipped: MentionSkip[] = [];\n const images: ImageInput[] = [];\n let ignore: IgnorePredicate | null | undefined;\n for (const mention of mentions) {\n const abs = path.resolve(cwd, mention);\n if (isSensitivePath(abs)) {\n skipped.push({ path: mention, reason: \"sensitive file\" });\n continue;\n }\n const mimeType = imageMimeType(mention);\n if (mimeType) {\n const st = await stat(abs).catch(() => null);\n if (!st || !st.isFile()) {\n skipped.push({ path: mention, reason: st ? \"is a directory\" : \"file not found\" });\n continue;\n }\n if (st.size > MAX_IMAGE_BYTES) {\n skipped.push({ path: mention, reason: \"image too large\" });\n continue;\n }\n const buf = await readFile(abs).catch(() => null);\n if (!buf) {\n skipped.push({ path: mention, reason: \"unreadable\" });\n continue;\n }\n const result = await downsampleImageIfNeeded({\n path: mention,\n mimeType,\n data: buf.toString(\"base64\"),\n });\n attached.push(mention);\n images.push(result.image);\n continue;\n }\n const st = await stat(abs).catch(() => null);\n if (!st) {\n skipped.push({ path: mention, reason: \"file not found\" });\n continue;\n }\n if (st.isDirectory()) {\n if (ignore === undefined) {\n ignore = createIgnorePredicate(cwd) ?? null;\n }\n const block = await directoryBlock(abs, mention, ignore ?? undefined);\n if (!block) {\n skipped.push({ path: mention, reason: \"unreadable\" });\n continue;\n }\n attached.push(mention);\n blocks.push(block);\n continue;\n }\n if (st.size > MAX_MENTION_BYTES) {\n skipped.push({ path: mention, reason: `exceeds ${MAX_MENTION_BYTES / 1024}KB limit` });\n continue;\n }\n const buf = await readFile(abs).catch(() => null);\n if (!buf) {\n skipped.push({ path: mention, reason: \"unreadable\" });\n continue;\n }\n if (isBinaryContent(buf)) {\n skipped.push({ path: mention, reason: \"binary file\" });\n continue;\n }\n attached.push(mention);\n blocks.push(`--- @${mention} ---\\n${buf.toString(\"utf8\")}\\n--- end ---`);\n }\n const input = [cleanText, ...blocks].filter((s) => s.length > 0).join(\"\\n\\n\") || text;\n return { input, attached, skipped, images };\n}\n","import { execFile } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { readFile, unlink, writeFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { MAX_IMAGE_DIMENSION, probeImageDimensions } from \"../core/image\";\nimport type { ImageInput } from \"../core/messages\";\n\nexport const RESIZE_TIMEOUT_MS = 10_000;\n\nconst execFileAsync = promisify(execFile);\n\nexport interface ResizeCommand {\n command: string;\n args: string[];\n}\n\nexport function windowsResizeScript(\n inputFile: string,\n outputFile: string,\n maxDimension: number,\n): string {\n const input = inputFile.replace(/'/g, \"''\");\n const output = outputFile.replace(/'/g, \"''\");\n return [\n \"Add-Type -AssemblyName System.Drawing\",\n `$img = [System.Drawing.Image]::FromFile('${input}')`,\n `$scale = [Math]::Min(1.0, ${maxDimension} / [Math]::Max($img.Width, $img.Height))`,\n \"$w = [int][Math]::Max(1, [Math]::Round($img.Width * $scale))\",\n \"$h = [int][Math]::Max(1, [Math]::Round($img.Height * $scale))\",\n \"$bmp = New-Object System.Drawing.Bitmap($w, $h)\",\n \"$g = [System.Drawing.Graphics]::FromImage($bmp)\",\n \"$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic\",\n \"$g.DrawImage($img, 0, 0, $w, $h)\",\n `$bmp.Save('${output}', [System.Drawing.Imaging.ImageFormat]::Png)`,\n \"$g.Dispose(); $bmp.Dispose(); $img.Dispose()\",\n ].join(\"; \");\n}\n\n// Platform-native resize command, or null when no tool is available. All\n// variants keep the aspect ratio and bound the longest side to maxDimension;\n// the output is always PNG.\nexport function resizeImagePlan(\n platform: NodeJS.Platform,\n inputFile: string,\n outputFile: string,\n maxDimension: number,\n tools: { hasConvert?: boolean; hasFfmpeg?: boolean } = {},\n): ResizeCommand | null {\n if (platform === \"win32\") {\n return {\n command: \"powershell.exe\",\n args: [\n \"-NoProfile\",\n \"-NonInteractive\",\n \"-Command\",\n windowsResizeScript(inputFile, outputFile, maxDimension),\n ],\n };\n }\n if (platform === \"darwin\") {\n return {\n command: \"sips\",\n args: [\"-Z\", String(maxDimension), inputFile, \"--out\", outputFile],\n };\n }\n if (platform === \"linux\") {\n if (tools.hasConvert) {\n return {\n command: \"convert\",\n // -auto-orient keeps EXIF-rotated photos upright after the resize\n // strips their orientation metadata.\n args: [\n inputFile,\n \"-auto-orient\",\n \"-resize\",\n `${maxDimension}x${maxDimension}>`,\n outputFile,\n ],\n };\n }\n if (tools.hasFfmpeg) {\n return {\n command: \"ffmpeg\",\n args: [\n \"-y\",\n \"-i\",\n inputFile,\n \"-vf\",\n `scale='if(gt(iw,ih),min(iw,${maxDimension}),-1)':'if(gt(iw,ih),-1,min(ih,${maxDimension}))'`,\n outputFile,\n ],\n };\n }\n return null;\n }\n return null;\n}\n\nasync function commandExists(command: string): Promise<boolean> {\n const checker = process.platform === \"win32\" ? \"where\" : \"which\";\n try {\n await execFileAsync(checker, [command], { timeout: RESIZE_TIMEOUT_MS });\n return true;\n } catch {\n return false;\n }\n}\n\nexport interface DownsampledImage {\n image: ImageInput;\n /** The source exceeded MAX_IMAGE_DIMENSION on its longest side. */\n oversized: boolean;\n /** The image was actually resized to fit; false when no platform tool was available or resizing failed. */\n resized: boolean;\n}\n\n// Downsamples an image whose longest side exceeds MAX_IMAGE_DIMENSION using\n// platform-native tools (no npm image dependency). Undimensionable or small\n// images pass through untouched; when resizing is impossible the original is\n// kept with oversized=true so the caller can warn instead of failing silently.\nexport async function downsampleImageIfNeeded(image: ImageInput): Promise<DownsampledImage> {\n const buf = Buffer.from(image.data, \"base64\");\n const dims = probeImageDimensions(buf);\n if (!dims || Math.max(dims.width, dims.height) <= MAX_IMAGE_DIMENSION) {\n return { image, oversized: false, resized: false };\n }\n const inputFile = path.join(os.tmpdir(), `star-image-${randomUUID()}.src`);\n const outputFile = path.join(os.tmpdir(), `star-image-${randomUUID()}.png`);\n try {\n const [hasConvert, hasFfmpeg] =\n process.platform === \"linux\"\n ? await Promise.all([commandExists(\"convert\"), commandExists(\"ffmpeg\")])\n : [false, false];\n const plan = resizeImagePlan(process.platform, inputFile, outputFile, MAX_IMAGE_DIMENSION, {\n hasConvert,\n hasFfmpeg,\n });\n if (!plan) return { image, oversized: true, resized: false };\n await writeFile(inputFile, buf);\n await execFileAsync(plan.command, plan.args, { timeout: RESIZE_TIMEOUT_MS });\n const out = await readFile(outputFile).catch(() => null);\n if (!out || out.length === 0) return { image, oversized: true, resized: false };\n return {\n image: { path: image.path, mimeType: \"image/png\", data: out.toString(\"base64\") },\n oversized: true,\n resized: true,\n };\n } catch {\n return { image, oversized: true, resized: false };\n } finally {\n await unlink(inputFile).catch(() => {});\n await unlink(outputFile).catch(() => {});\n }\n}\n","import type { StreamEvent, TokenUsage } from \"../core/events\";\n\nexport function eventToJsonLine(event: StreamEvent): string | null {\n switch (event.type) {\n case \"finish\":\n return null;\n case \"error\":\n return JSON.stringify({ type: \"error\", error: { message: event.error.message } });\n default:\n return JSON.stringify(event);\n }\n}\n\nexport class UsageTracker {\n private requests = 0;\n private promptTokens = 0;\n private completionTokens = 0;\n private totalTokens = 0;\n\n add(usage?: TokenUsage): void {\n if (!usage) return;\n this.requests += 1;\n this.promptTokens += usage.promptTokens;\n this.completionTokens += usage.completionTokens;\n this.totalTokens += usage.totalTokens;\n }\n\n get totals(): TokenUsage & { requests: number } {\n return {\n requests: this.requests,\n promptTokens: this.promptTokens,\n completionTokens: this.completionTokens,\n totalTokens: this.totalTokens,\n };\n }\n\n toJsonLine(): string | null {\n if (this.requests === 0) return null;\n return JSON.stringify({\n type: \"usage\",\n requests: this.requests,\n promptTokens: this.promptTokens,\n completionTokens: this.completionTokens,\n totalTokens: this.totalTokens,\n });\n }\n}\n","import { Box, Text, render, useApp } from \"ink\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n type AgentTaskSnapshot,\n defaultAgentTasks,\n formatAgentTaskUpdate,\n} from \"../agent/agent-tasks\";\nimport { AgentLoop } from \"../agent/loop\";\nimport { globalConfigPath } from \"../config/paths\";\nimport { addAllowRule, savePermissionMode, saveReasoningEffort } from \"../config/save\";\nimport { type StarConfig, contextWindowTokens } from \"../config/schema\";\nimport { estimateTokens } from \"../context/tokens\";\nimport { getGitSummary } from \"../core/git\";\nimport { MAX_IMAGE_DIMENSION } from \"../core/image\";\nimport type { CoreMessage, ImageInput } from \"../core/messages\";\nimport { createModel, reasoningEffortMetadata } from \"../llm/provider\";\nimport { listModels } from \"../llm/registry\";\nimport { buildAllowRule, isAllowedByRules } from \"../permissions/allow\";\nimport type { PermissionRequest } from \"../permissions/types\";\nimport { loadSessionSnapshots } from \"../session/checkpoints\";\nimport { clearSessions } from \"../session/clear\";\nimport {\n formatSessionEntries,\n listSessionEntries,\n relativeTime,\n resolveSessionId,\n sessionPreview,\n shortSessionId,\n} from \"../session/list\";\nimport { resumeSession } from \"../session/resume\";\nimport { SessionStore } from \"../session/store\";\nimport { collectUsageStats, formatUsageDashboard } from \"../session/usage\";\nimport { formatTaskFinished, formatTaskList, formatTaskStarted } from \"../tasks/format\";\nimport { type TaskSnapshot, defaultTaskManager } from \"../tasks/manager\";\nimport { TodoStore, createDefaultRegistry } from \"../tools\";\nimport {\n clearSnapshots,\n hydrateSnapshots,\n listSnapshots,\n listTurnSnapshots,\n rewindToSnapshot,\n} from \"../tools/fs/snapshots\";\nimport { type TodoItem, formatTodos, loadTodos, parseTodoArgs, resetTodos } from \"../tools/todo\";\nimport { VERSION } from \"../version\";\nimport type { ChatBackend } from \"./backend\";\nimport { budgetState } from \"./budget\";\nimport {\n type CacheTotals,\n addToCacheTotals,\n cacheHitPercent,\n cacheUsageReported,\n} from \"./cache-stats\";\nimport { copyText, readClipboardImage } from \"./clipboard\";\nimport { compactSession, exportSession } from \"./commands/actions\";\nimport { registerBuiltinCommands } from \"./commands/builtin\";\nimport {\n type ConnectAnswers,\n openConfigFile,\n saveConnection,\n saveDefaultModel,\n} from \"./commands/connect\";\nimport { registerCustomCommands } from \"./commands/custom\";\nimport { formatDoctorReport, runDoctor } from \"./commands/doctor\";\nimport { initProject } from \"./commands/init-project\";\nimport { formatRedoResult, formatRedoSummary } from \"./commands/redo\";\nimport { type CommandContext, CommandRegistry, parseSlashCommand } from \"./commands/registry\";\nimport { formatCheckpointList, planRewind } from \"./commands/rewind\";\nimport { didYouMeanSuffix } from \"./commands/suggest\";\nimport { buildUndoDiffs, buildUndoTreeDiffs } from \"./commands/undo\";\nimport { ConnectWizard } from \"./components/ConnectWizard\";\nimport { type ExitPlanDecision, ExitPlanPrompt } from \"./components/ExitPlanPrompt\";\nimport { InputBox } from \"./components/InputBox\";\nimport { type DisplayMessage, MessageList } from \"./components/MessageList\";\nimport { type PermissionDecision, PermissionPrompt } from \"./components/PermissionPrompt\";\nimport {\n type ConfirmDiff,\n RewindConfirmPrompt,\n type RewindDecision,\n} from \"./components/RewindConfirmPrompt\";\nimport { type SelectOption, SelectPrompt } from \"./components/SelectPrompt\";\nimport { StatusBar } from \"./components/StatusBar\";\nimport { StreamingMessage } from \"./components/StreamingMessage\";\nimport {\n THOUGHT_SUMMARY_LENGTH,\n ThinkingIndicator,\n truncateTail,\n} from \"./components/ThinkingIndicator\";\nimport { TodoPanel } from \"./components/TodoPanel\";\nimport { type ToolCardData, formatToolCard } from \"./components/ToolCallCard\";\nimport { computeCostUsd, estimateCost, formatDollars } from \"./cost\";\nimport { type DiffPreview, generateDiffPreview } from \"./diff-preview\";\nimport { isDoubleEscape } from \"./double-esc\";\nimport {\n buildDisplayMessages,\n coreMessageText,\n formatStreamError,\n splitCommittableLines,\n summarizeArgs,\n} from \"./format\";\nimport { appendHistory, loadHistory } from \"./history\";\nimport { thinkingIcon, toolIcon } from \"./icons\";\nimport { resolveMentions } from \"./mentions\";\nimport { notifyBell } from \"./notify\";\nimport { PromptQueue, type QueuedPrompt } from \"./queue\";\nimport { executeShellBang } from \"./shell-bang\";\nimport { SYSTEM_PROMPT } from \"./system-prompt\";\nimport { toTerminalSafe } from \"./terminal-text\";\nimport { type FlushState, nextFlush, startTicker } from \"./ticker\";\nimport { checkForUpdate } from \"./update-check\";\nimport { useInput } from \"./use-input\";\n\n// Matches ansi-escapes' clearTerminal (Ink pulls the same sequence for its\n// own full redraws): erase screen + scrollback, cursor home.\nconst CLEAR_TERMINAL =\n process.platform === \"win32\" ? \"\\u001B[2J\\u001B[0f\" : \"\\u001B[2J\\u001B[3J\\u001B[H\";\n\nexport interface UsageStats {\n requests: number;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n // Prompt-cache totals; absent until a provider reports cache fields.\n cachedPromptTokens?: number;\n cacheReadInputTokens?: number;\n cache?: CacheTotals;\n}\n\nfunction emptyUsage(): UsageStats {\n return { requests: 0, promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n}\n\nfunction runningTaskLabels(): string[] {\n const shells = defaultTaskManager\n .list()\n .filter((t) => t.status === \"running\")\n .map((t) => t.description ?? t.command);\n const agents = defaultAgentTasks\n .list()\n .filter((t) => t.status === \"running\")\n .map((t) => t.description ?? t.id);\n return [...shells, ...agents];\n}\n\n// Shift+Tab cycles these in order; yolo is reachable only via /permission.\nconst SESSION_MODE_CYCLE = [\"ask\", \"auto\", \"readonly\", \"plan\"] as const;\n\n// Commands that rewrite the conversation, the persistence target, or files:\n// running them mid-turn would corrupt the session underneath the active loop,\n// so they are refused while a turn streams. Read-only commands are unaffected.\n// Exported for tests.\nexport const BUSY_BLOCKED_COMMANDS = new Set([\n \"new\",\n \"resume\",\n \"undo\",\n \"redo\",\n \"rewind\",\n \"compact\",\n \"fork\",\n \"clear-sessions\",\n \"model\",\n \"connect\",\n \"memory\",\n]);\n\nfunction formatUsage(usage: UsageStats): string {\n return `API usage this session: ${usage.requests} requests, ${usage.promptTokens} prompt + ${usage.completionTokens} completion = ${usage.totalTokens} tokens`;\n}\n\ninterface PendingPermission {\n request: PermissionRequest;\n preview: DiffPreview | null;\n resolve: (approved: boolean) => void;\n}\n\ninterface PendingRewind {\n summary: string;\n title?: string;\n confirmLabel?: string;\n diffs?: ConfirmDiff[];\n resolve: (confirmed: boolean) => void;\n}\n\ninterface PendingPicker {\n title: string;\n options: SelectOption[];\n resolve: (value: string | null) => void;\n}\n\ninterface PendingConnect {\n resolve: (message: string) => void;\n}\n\nconst SESSION_PICKER_CAP = 20;\n\n// First-user-message previews are trimmed to a single ~60-char line in the\n// resume picker description.\nconst SESSION_PREVIEW_MAX = 60;\n\n// Queued typeahead entries rendered in the live region: a bounded count so\n// the live region can never grow to terminal height (see TodoPanel).\nconst MAX_VISIBLE_QUEUED = 5;\n\n// Reasoning-effort presets offered by the /model follow-up picker. Level\n// naming is not standardized across models (some add none/xhigh...), so the\n// config accepts any string and a custom value already set on the model is\n// appended to this list.\nconst REASONING_EFFORT_LEVELS = [\"minimal\", \"low\", \"medium\", \"high\", \"max\"];\n\ninterface ReplProps {\n backend: ChatBackend;\n model: string;\n permissionMode: string;\n config: StarConfig;\n cwd: string;\n sessionStore: SessionStore | null;\n initialMessages?: CoreMessage[];\n initialUsage?: UsageStats;\n}\n\nexport function Repl({\n backend,\n model,\n permissionMode,\n config,\n cwd,\n sessionStore,\n initialMessages,\n initialUsage,\n}: ReplProps) {\n const { exit } = useApp();\n const [initialDisplay] = useState(() => buildDisplayMessages(initialMessages ?? []));\n const [messages, setMessages] = useState<DisplayMessage[]>(initialDisplay);\n const [epoch, setEpoch] = useState(0);\n const [streamingText, setStreamingText] = useState<string | null>(null);\n const [isStreaming, setIsStreaming] = useState(false);\n const [thinking, setThinking] = useState(false);\n const [thinkingText, setThinkingText] = useState(\"\");\n const [thoughtSummary, setThoughtSummary] = useState<string | null>(null);\n // usageVersion bump counter: the value is never read; setting it re-renders\n // so usageRef contents flow into StatusBar.\n const [, setUsageVersion] = useState(0);\n const [modelName, setModelName] = useState(model);\n const [pending, setPending] = useState<PendingPermission | null>(null);\n const [spinnerTick, setSpinnerTick] = useState(0);\n const [activity, setActivity] = useState<string | null>(null);\n const [bgLabels, setBgLabels] = useState<string[]>(() => runningTaskLabels());\n const [todos, setTodos] = useState<TodoItem[]>([]);\n const [permissionModeState, setPermissionModeState] = useState(permissionMode);\n const [planApproval, setPlanApprovalState] = useState(false);\n const [pendingRewind, setPendingRewindState] = useState<PendingRewind | null>(null);\n const [picker, setPickerState] = useState<PendingPicker | null>(null);\n const [pendingConnect, setPendingConnectState] = useState<PendingConnect | null>(null);\n\n const backendRef = useRef<ChatBackend>(backend);\n const nextIdRef = useRef(initialDisplay.length);\n const abortRef = useRef<AbortController | null>(null);\n const streamedRef = useRef(\"\");\n // Chars of streamedRef already committed to static history by the ticker.\n // The live region renders only the suffix past this point, and a stream\n // retry rolls the buffer back to it (the resend re-streams from scratch).\n const lastCommittedLenRef = useRef(0);\n const thinkingRef = useRef(false);\n const reasoningRef = useRef(\"\");\n const tickerStopRef = useRef<(() => void) | null>(null);\n const flushedRef = useRef<FlushState>({ streamed: \"\", reasoning: \"\" });\n const toolCardsRef = useRef(new Map<string, ToolCardData>());\n const pendingRef = useRef<PendingPermission | null>(null);\n // Promise chain serializing permission prompts: a background subagent's\n // request queues behind the open prompt instead of overwriting its resolve\n // (the single pending slot can only hold one request at a time).\n const permissionChainRef = useRef<Promise<void>>(Promise.resolve());\n const alwaysAllowedRef = useRef(new Set<string>());\n // Mode the session was in before plan mode was entered; restored on plan\n // approval or /plan toggle. null when plan mode is not active.\n const prevModeRef = useRef<StarConfig[\"permissionMode\"] | null>(null);\n const planApprovalRef = useRef(false);\n const pendingRewindRef = useRef<PendingRewind | null>(null);\n const pickerRef = useRef<PendingPicker | null>(null);\n const pendingConnectRef = useRef<PendingConnect | null>(null);\n const modelNameRef = useRef(model);\n // Live session store: /new swaps it mid-session, so callbacks must go\n // through the ref rather than the prop captured at mount.\n const sessionStoreRef = useRef<SessionStore | null>(sessionStore);\n // Latest config for mount-only listeners (a new config object identity must\n // not re-register — and thereby kill — the background-task listeners).\n const configRef = useRef(config);\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n const usageRef = useRef<UsageStats>(initialUsage ? { ...initialUsage } : emptyUsage());\n // Number of assistant chunks already committed to static history this turn;\n // 0 means the next streamed text still needs the \"star\" header.\n const turnChunksRef = useRef(0);\n // Mirror of `messages` for code that needs the current list synchronously\n // (e.g. computing the /undo cut point before redrawing).\n const messagesRef = useRef<DisplayMessage[]>(initialDisplay);\n\n const [queueItems, setQueueItems] = useState<QueuedPrompt[]>([]);\n const queueRef = useRef(new PromptQueue());\n // Clipboard images staged via Alt+V (or Ctrl+V where the terminal passes it\n // through), merged into the next submitted prompt.\n const [pendingImages, setPendingImages] = useState<{ id: number; image: ImageInput }[]>([]);\n const pendingImagesRef = useRef<{ id: number; image: ImageInput }[]>([]);\n const imageSeqRef = useRef(1);\n const [inputRefill, setInputRefill] = useState<{ text: string; seq: number } | undefined>();\n const refillSeqRef = useRef(0);\n // Timestamp of the last idle Esc; a second one within the window restores\n // the last user message for editing.\n const lastEscRef = useRef<number | null>(null);\n const [gitBranch, setGitBranch] = useState<string | null>(null);\n const [contextPercent, setContextPercent] = useState<number | null>(null);\n // Persistent input history, loaded once per process (STAR_HOME is fixed).\n const [initialHistory] = useState(() => loadHistory());\n const budgetWarnedRef = useRef(false);\n const budgetExceededRef = useRef(false);\n // Latest runStream, so a finishing turn can drain the queue by re-entering\n // it without a circular useCallback dependency.\n const runStreamRef = useRef<((text: string, images?: ImageInput[]) => Promise<void>) | null>(\n null,\n );\n\n const pushMessage = useCallback(\n (\n role: DisplayMessage[\"role\"],\n text: string,\n note?: string,\n tight?: boolean,\n interrupted?: boolean,\n ) => {\n setMessages((prev) => {\n const next = [...prev, { id: nextIdRef.current++, role, text, note, tight, interrupted }];\n messagesRef.current = next;\n return next;\n });\n },\n [],\n );\n\n // Replace the whole history and remount the list (fresh Static instance).\n const applyMessages = useCallback((next: DisplayMessage[]) => {\n messagesRef.current = next;\n setMessages(next);\n setEpoch((e) => e + 1);\n }, []);\n\n // Ink's <Static> can only append — dropping items from state does not erase\n // them from the terminal. Clear the screen first, then let the remounted\n // Static rewrite the surviving history.\n const redrawMessages = useCallback(\n (next: DisplayMessage[]) => {\n if (process.stdout.isTTY) {\n process.stdout.write(CLEAR_TERMINAL);\n }\n applyMessages(next);\n },\n [applyMessages],\n );\n\n const pushAssistantChunk = useCallback(\n (text: string, tight: boolean, interrupted = false) => {\n const role: DisplayMessage[\"role\"] =\n turnChunksRef.current === 0 ? \"assistant\" : \"assistant-cont\";\n turnChunksRef.current += 1;\n pushMessage(role, text, undefined, tight, interrupted);\n },\n [pushMessage],\n );\n\n const setPendingPermission = useCallback((p: PendingPermission | null) => {\n pendingRef.current = p;\n setPending(p);\n }, []);\n\n const setPlanApproval = useCallback((v: boolean) => {\n planApprovalRef.current = v;\n setPlanApprovalState(v);\n }, []);\n\n const setPendingRewind = useCallback((p: PendingRewind | null) => {\n pendingRewindRef.current = p;\n setPendingRewindState(p);\n }, []);\n\n const setPicker = useCallback((p: PendingPicker | null) => {\n pickerRef.current = p;\n setPickerState(p);\n }, []);\n\n const setPendingConnect = useCallback((p: PendingConnect | null) => {\n pendingConnectRef.current = p;\n setPendingConnectState(p);\n }, []);\n\n // One picker at a time; a second request while one is open resolves null\n // immediately so callers never hang.\n const showPicker = useCallback(\n (title: string, options: SelectOption[]): Promise<string | null> => {\n if (pickerRef.current) return Promise.resolve(null);\n return new Promise<string | null>((resolve) => {\n setPicker({ title, options, resolve });\n });\n },\n [setPicker],\n );\n\n const handlePickerSelect = useCallback(\n (value: string) => {\n const p = pickerRef.current;\n if (!p) return;\n setPicker(null);\n p.resolve(value);\n },\n [setPicker],\n );\n\n const handlePickerCancel = useCallback(() => {\n const p = pickerRef.current;\n if (!p) return;\n setPicker(null);\n p.resolve(null);\n }, [setPicker]);\n\n const stageClipboardImage = useCallback((img: ImageInput) => {\n pendingImagesRef.current = [\n ...pendingImagesRef.current,\n { id: imageSeqRef.current++, image: img },\n ];\n setPendingImages(pendingImagesRef.current);\n }, []);\n\n const clearPendingImages = useCallback(() => {\n pendingImagesRef.current = [];\n setPendingImages([]);\n }, []);\n\n // Numeric session cost (USD) from the accumulated usage; null when the\n // active model has no pricing configured.\n const sessionCostUsd = useCallback(\n () =>\n computeCostUsd(\n usageRef.current,\n config.models.find((m) => m.name === modelNameRef.current),\n ),\n [config],\n );\n\n const handlePasteImage = useCallback(() => {\n void readClipboardImage().then((result) => {\n if (!result) return;\n if (result.oversized) {\n pushMessage(\n \"system\",\n `Image exceeds ${MAX_IMAGE_DIMENSION}px on its longest side and could not be resized automatically; the model may reject it.`,\n );\n }\n stageClipboardImage(result.image);\n });\n }, [stageClipboardImage, pushMessage]);\n\n const handleRewindDecision = useCallback(\n (decision: RewindDecision) => {\n const p = pendingRewindRef.current;\n if (!p) return;\n setPendingRewind(null);\n p.resolve(decision === \"yes\");\n },\n [setPendingRewind],\n );\n\n // Persists the wizard result: key into ~/.star-cli/.env (exported into this\n // process so the model works without a restart), provider/model appended to\n // config.toml, and both pushed into the live config so /model sees them.\n const handleConnectSave = useCallback(\n async (answers: ConnectAnswers): Promise<string> => {\n const result = saveConnection(answers);\n config.providers.push(result.provider);\n config.models.push(result.model);\n 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}.`;\n },\n [config],\n );\n\n const handleConnectOpenConfig = useCallback((): string => {\n const file = globalConfigPath();\n openConfigFile(file);\n return `Opening ${file} with the system default app (open it manually if nothing showed up).`;\n }, []);\n\n const finishConnect = useCallback(\n (message: string) => {\n const p = pendingConnectRef.current;\n if (!p) return;\n setPendingConnect(null);\n p.resolve(message);\n },\n [setPendingConnect],\n );\n\n const cancelConnect = useCallback(() => {\n finishConnect(\"Connect cancelled — nothing was saved.\");\n }, [finishConnect]);\n\n // Session-scoped mode switch: mutates the shared config object the AgentLoop\n // reads on every tool call. Entering plan mode remembers the previous mode\n // for later restoration; unlike /permission nothing is written to config.\n const applySessionMode = useCallback(\n (mode: StarConfig[\"permissionMode\"]) => {\n if (mode === config.permissionMode) return;\n if (mode === \"plan\") {\n prevModeRef.current = config.permissionMode;\n } else if (config.permissionMode === \"plan\") {\n prevModeRef.current = null;\n }\n config.permissionMode = mode;\n setPermissionModeState(mode);\n },\n [config],\n );\n\n const attachConfirmHandler = useCallback(\n (target: ChatBackend) => {\n target.confirmHandler = (req) => {\n if (isAllowedByRules([...alwaysAllowedRef.current], req)) {\n return Promise.resolve(true);\n }\n const ask = async (): Promise<boolean> => {\n const preview = await generateDiffPreview(req.toolName, req.args, cwd).catch(() => null);\n return new Promise<boolean>((resolve) => {\n setPendingPermission({ request: req, preview, resolve });\n });\n };\n // Queue behind the currently open prompt: a concurrent request (e.g.\n // from a background subagent) that took the pending slot directly\n // would overwrite the previous resolve and leak its promise forever.\n const decision = permissionChainRef.current.then(ask);\n permissionChainRef.current = decision.then(\n () => undefined,\n () => undefined,\n );\n return decision;\n };\n target.onHookWarning = (message) => pushMessage(\"system\", message);\n },\n [setPendingPermission, cwd, pushMessage],\n );\n\n useEffect(() => {\n attachConfirmHandler(backendRef.current);\n return () => {\n tickerStopRef.current?.();\n abortRef.current?.abort();\n pendingRef.current?.resolve(false);\n };\n }, [attachConfirmHandler]);\n\n useEffect(() => {\n if (process.env.STAR_NO_UPDATE_CHECK === \"1\") return;\n void checkForUpdate(VERSION).then((message) => {\n if (message) pushMessage(\"system\", message);\n });\n }, [pushMessage]);\n\n // Restore the todo panel only when this session explicitly continues the\n // project (started via -c/-r; /resume is handled in the resume callback).\n // A fresh session starts with an empty list even when the project's\n // .star/todos.json still holds a previous session's items.\n const resumedAtStart = initialMessages !== undefined;\n useEffect(() => {\n if (!resumedAtStart) return;\n loadTodos(cwd)\n .then(setTodos)\n .catch(() => {});\n }, [cwd, resumedAtStart]);\n\n // Mount-only listener registration: re-running this effect would detach and\n // cleanup() the managers, killing every in-flight background task, so it\n // must not depend on the config object identity (configRef reads instead).\n useEffect(() => {\n const onUpdate = (task: TaskSnapshot) => {\n setBgLabels(runningTaskLabels());\n pushMessage(\n \"system\",\n toTerminalSafe(\n task.status === \"running\" ? formatTaskStarted(task) : formatTaskFinished(task),\n ),\n );\n // Background tasks are exactly the case where the user has looked away.\n if (task.status !== \"running\") {\n notifyBell({\n enabled: configRef.current.notifyBell,\n thresholdSec: configRef.current.notifyBellThresholdSec,\n noNotifyEnv: process.env.STAR_NO_NOTIFY === \"1\",\n });\n }\n };\n const onAgentUpdate = (task: AgentTaskSnapshot) => {\n setBgLabels(runningTaskLabels());\n pushMessage(\"system\", toTerminalSafe(formatAgentTaskUpdate(task)));\n if (task.status !== \"running\") {\n notifyBell({\n enabled: configRef.current.notifyBell,\n thresholdSec: configRef.current.notifyBellThresholdSec,\n noNotifyEnv: process.env.STAR_NO_NOTIFY === \"1\",\n });\n }\n };\n defaultTaskManager.on(\"update\", onUpdate);\n defaultAgentTasks.on(\"update\", onAgentUpdate);\n return () => {\n defaultTaskManager.off(\"update\", onUpdate);\n defaultAgentTasks.off(\"update\", onAgentUpdate);\n defaultTaskManager.cleanup();\n defaultAgentTasks.cleanup();\n };\n }, [pushMessage]);\n\n const interrupt = useCallback(() => {\n abortRef.current?.abort();\n const p = pendingRef.current;\n if (p) {\n setPendingPermission(null);\n p.resolve(false);\n }\n const cleared = queueRef.current.clear();\n if (cleared.length > 0) {\n setQueueItems([]);\n pushMessage(\"system\", `cleared ${cleared.length} queued message(s)`);\n }\n }, [setPendingPermission, pushMessage]);\n\n // Double-Esc while idle: retract the last user turn and put the originally\n // typed text back into the input for editing.\n const editLastMessage = useCallback(async () => {\n const current = backendRef.current;\n if (typeof current.retractLastTurn !== \"function\") return;\n const visible = messagesRef.current;\n let cut = -1;\n let text = \"\";\n for (let i = visible.length - 1; i >= 0; i--) {\n const msg = visible[i];\n if (msg?.role === \"user\") {\n cut = i;\n text = msg.text;\n break;\n }\n }\n if (cut < 0) return;\n const { removed } = await current.retractLastTurn();\n if (removed === 0) return;\n redrawMessages(visible.slice(0, cut));\n refillSeqRef.current += 1;\n setInputRefill({ text, seq: refillSeqRef.current });\n pushMessage(\"system\", \"last message restored for editing\");\n }, [pushMessage, redrawMessages]);\n\n const handleExit = useCallback(() => {\n const killed = defaultTaskManager.cleanup();\n const killedAgents = defaultAgentTasks.cleanup();\n const stopped = killed.length + killedAgents.length;\n if (stopped > 0) {\n pushMessage(\"system\", `${stopped} background task(s) still running; reports will be lost.`);\n // Let the warning commit to static output before the app tears down.\n setTimeout(exit, 50);\n return;\n }\n exit();\n }, [exit, pushMessage]);\n\n useInput((_input, key) => {\n if (key.escape) {\n const busy =\n abortRef.current !== null ||\n pendingRef.current !== null ||\n planApprovalRef.current ||\n pendingRewindRef.current !== null ||\n pendingConnectRef.current !== null ||\n pickerRef.current !== null;\n if (busy) {\n lastEscRef.current = null;\n interrupt();\n return;\n }\n const now = Date.now();\n if (isDoubleEscape(lastEscRef.current, now)) {\n lastEscRef.current = null;\n void editLastMessage();\n } else {\n lastEscRef.current = now;\n }\n return;\n }\n lastEscRef.current = null;\n if (key.shift && key.tab) {\n // Don't yank the mode out from under a running turn or an open prompt.\n if (\n abortRef.current ||\n pendingRef.current ||\n planApprovalRef.current ||\n pendingRewindRef.current ||\n pendingConnectRef.current ||\n pickerRef.current\n )\n return;\n const current = config.permissionMode as (typeof SESSION_MODE_CYCLE)[number];\n const index = SESSION_MODE_CYCLE.indexOf(current);\n const next = SESSION_MODE_CYCLE[(index + 1) % SESSION_MODE_CYCLE.length] ?? \"ask\";\n applySessionMode(next);\n }\n });\n\n const handleDecision = useCallback(\n (decision: PermissionDecision) => {\n const p = pendingRef.current;\n if (!p) return;\n if (decision === \"always\") {\n const rule = buildAllowRule(p.request);\n alwaysAllowedRef.current.add(rule);\n void addAllowRule(rule)\n .then((added) => {\n pushMessage(\n \"system\",\n added\n ? `Always allow ${rule} — saved to config`\n : `Always allow ${rule} (already in config)`,\n );\n })\n .catch(() => {\n pushMessage(\"system\", `Always allow ${rule} for this session (failed to save)`);\n });\n }\n setPendingPermission(null);\n p.resolve(decision !== \"no\");\n },\n [setPendingPermission, pushMessage],\n );\n\n const switchModel = useCallback(\n async (name: string): Promise<string> => {\n try {\n const newModel = createModel(config, name);\n const loop = new AgentLoop({\n model: newModel,\n registry: createDefaultRegistry(),\n config,\n cwd,\n system: SYSTEM_PROMPT,\n sessionStore: sessionStoreRef.current,\n contextMaxTokens: contextWindowTokens(config, name),\n providerMetadata: reasoningEffortMetadata(config, name),\n });\n const prev = backendRef.current;\n if (prev instanceof AgentLoop) {\n await loop.loadMessages([...prev.getMessages()]);\n }\n attachConfirmHandler(loop);\n backendRef.current = loop;\n modelNameRef.current = name;\n setModelName(name);\n return `Switched to model \"${name}\".`;\n } catch (error) {\n return `Failed to switch model: ${error instanceof Error ? error.message : String(error)}`;\n }\n },\n [config, cwd, attachConfirmHandler],\n );\n\n // Follow-up to the model picker: applies the chosen reasoning effort to the\n // live loop (no rebuild), then persists it to the model's [[models]] block.\n const pickReasoningEffort = useCallback(\n async (name: string): Promise<string> => {\n const modelConfig = config.models.find((m) => m.name === name);\n const current = modelConfig?.reasoningEffort;\n const levels =\n current && !REASONING_EFFORT_LEVELS.includes(current)\n ? [...REASONING_EFFORT_LEVELS, current]\n : REASONING_EFFORT_LEVELS;\n const options: SelectOption[] = [\n {\n value: \"\",\n label: \"default\",\n description: \"send no effort field — the provider's server-side default applies\",\n hint: current === undefined ? \"current\" : undefined,\n },\n ...levels.map((level) => ({\n value: level,\n label: level,\n description: \"only works if the model/provider supports this level\",\n hint: level === current ? \"current\" : undefined,\n })),\n ];\n const picked = await showPicker(`Reasoning effort for \"${name}\"`, options);\n if (picked === null || (picked === \"\" && current === undefined) || picked === current) {\n return `Reasoning effort unchanged${current ? ` — still \"${current}\"` : \" — server default\"}.`;\n }\n const effort = picked === \"\" ? undefined : picked;\n if (modelConfig) modelConfig.reasoningEffort = effort;\n const backend = backendRef.current;\n if (backend instanceof AgentLoop) {\n backend.setProviderMetadata(reasoningEffortMetadata(config, name));\n }\n const saved = await saveReasoningEffort(name, effort);\n const applied = effort === undefined ? \"server default\" : `\"${effort}\"`;\n const suffix = saved\n ? \"Saved to config.\"\n : `This session only — \"${name}\" has no [[models]] block in the global config file; add reasoningEffort there to persist it.`;\n return `Reasoning effort for \"${name}\" set to ${applied}. ${suffix}`;\n },\n [config, showPicker],\n );\n\n const handleConnectSetDefault = useCallback(\n async (modelName: string): Promise<string> => {\n saveDefaultModel(modelName);\n config.defaultModel = modelName;\n const switched = await switchModel(modelName);\n return `Default model set to \"${modelName}\" (saved to config). ${switched}`;\n },\n [config, switchModel],\n );\n\n const resume = useCallback(\n async (id: string): Promise<string> => {\n const current = backendRef.current;\n if (!(current instanceof AgentLoop)) {\n return \"Current backend does not support resuming sessions.\";\n }\n const resolvedId = await resolveSessionId(id);\n if (!resolvedId) {\n return `Session not found: ${id}`;\n }\n const resumed = await resumeSession(resolvedId);\n if (!resumed) {\n return `Session not found: ${id}`;\n }\n const store = await SessionStore.open(resolvedId);\n if (!store) {\n return `Session not found: ${id}`;\n }\n await current.loadMessages(resumed.messages);\n // Rebind persistence to the resumed session before anything else can\n // write: without this, new messages/usage/snapshots keep landing in the\n // previous session's directory.\n current.setSessionStore(store);\n sessionStoreRef.current = store;\n // Resuming is the explicit \"continue this project\" gesture: bring the\n // persisted todo list back into the panel (and the model's todo_read).\n setTodos(await loadTodos(cwd));\n hydrateSnapshots(await loadSessionSnapshots(store.dir));\n const display = buildDisplayMessages(resumed.messages);\n nextIdRef.current = display.length;\n applyMessages(display);\n usageRef.current = resumed.meta.usage ? { ...resumed.meta.usage } : emptyUsage();\n setUsageVersion((v) => v + 1);\n return `Resumed session ${resolvedId} (${resumed.messages.length} messages).`;\n },\n [applyMessages, cwd],\n );\n\n const runStream = useCallback(\n async (input: string, extraImages: ImageInput[] = []) => {\n const resolved = await resolveMentions(input, cwd);\n const images = [...resolved.images, ...extraImages];\n pushMessage(\n \"user\",\n input,\n resolved.attached.length + extraImages.length > 0\n ? `attached: ${[...resolved.attached, ...extraImages.map((img) => img.path)].join(\", \")}`\n : undefined,\n );\n for (const skip of resolved.skipped) {\n pushMessage(\"system\", `Skipped @${skip.path}: ${skip.reason}`);\n }\n const controller = new AbortController();\n abortRef.current = controller;\n const turnStartedAt = Date.now();\n streamedRef.current = \"\";\n lastCommittedLenRef.current = 0;\n thinkingRef.current = true;\n reasoningRef.current = \"\";\n turnChunksRef.current = 0;\n setThinking(true);\n setThinkingText(\"\");\n setThoughtSummary(null);\n setStreamingText(\"\");\n setIsStreaming(true);\n flushedRef.current = { streamed: \"\", reasoning: \"\" };\n // Move the current streaming buffer into static history. Used at tool-call\n // boundaries (to keep chronological order) and by the ticker for long\n // answers, so the live redraw area — and with it the visible flicker —\n // stays small no matter how long the answer gets.\n const commitStreamed = (tight: boolean) => {\n const uncommitted = streamedRef.current.slice(lastCommittedLenRef.current);\n if (uncommitted.length > 0) {\n pushAssistantChunk(uncommitted, tight);\n }\n streamedRef.current = \"\";\n lastCommittedLenRef.current = 0;\n flushedRef.current = { ...flushedRef.current, streamed: \"\" };\n setStreamingText(\"\");\n };\n tickerStopRef.current = startTicker((tick) => {\n setSpinnerTick(tick);\n const uncommitted = streamedRef.current.slice(lastCommittedLenRef.current);\n const split = splitCommittableLines(uncommitted, 8);\n if (split) {\n pushAssistantChunk(split.committed, true);\n // +1 for the newline splitCommittableLines consumed but did not\n // include in either half.\n lastCommittedLenRef.current += split.committed.length + 1;\n }\n const next: FlushState = {\n streamed: streamedRef.current.slice(lastCommittedLenRef.current),\n reasoning: reasoningRef.current,\n };\n if (nextFlush(flushedRef.current, next) !== null) {\n flushedRef.current = next;\n setStreamingText(next.streamed);\n setThinkingText(next.reasoning);\n }\n });\n try {\n for await (const event of backendRef.current.stream(\n images.length > 0 ? { text: resolved.input, images } : resolved.input,\n controller.signal,\n {\n persistAs:\n extraImages.length > 0\n ? `${input}${\" [clipboard image]\".repeat(extraImages.length)}`\n : input,\n },\n )) {\n if (event.type === \"text-delta\") {\n if (thinkingRef.current) {\n thinkingRef.current = false;\n setThinking(false);\n if (reasoningRef.current.length > 0) {\n setThoughtSummary(\n `${thinkingIcon} thought: ${truncateTail(reasoningRef.current, THOUGHT_SUMMARY_LENGTH)}`,\n );\n }\n }\n streamedRef.current += toTerminalSafe(event.text);\n } else if (event.type === \"reasoning\") {\n reasoningRef.current += toTerminalSafe(event.text);\n } else if (event.type === \"tool-call\") {\n // Flush the text spoken before this call into history first, so the\n // card lands in chronological order instead of after the whole turn.\n commitStreamed(true);\n toolCardsRef.current.set(event.id, {\n id: event.id,\n name: event.name,\n argsSummary: summarizeArgs(event.args),\n });\n if (event.name === \"todo_write\") {\n const list = parseTodoArgs(event.args);\n if (list) setTodos(list);\n }\n setActivity(\n `${toolIcon(event.name)} running ${event.name}: ${summarizeArgs(event.args, 60)}`,\n );\n } else if (event.type === \"tool-result\") {\n const card = toolCardsRef.current.get(event.id) ?? {\n id: event.id,\n name: event.name,\n argsSummary: \"\",\n };\n toolCardsRef.current.delete(event.id);\n // Rendered once, straight into static history — no live card region\n // that would have to be erased (and could linger) at turn end.\n pushMessage(\n \"tool\",\n formatToolCard({\n ...card,\n result: event.content,\n isError: event.isError ?? false,\n }),\n );\n setActivity(null);\n thinkingRef.current = true;\n reasoningRef.current = \"\";\n setThinking(true);\n setThinkingText(\"\");\n } else if (event.type === \"finish\") {\n if (event.usage) {\n const usage = usageRef.current;\n usage.requests += 1;\n usage.promptTokens += event.usage.promptTokens;\n usage.completionTokens += event.usage.completionTokens;\n usage.totalTokens += event.usage.totalTokens;\n if (event.usage.cachedPromptTokens) {\n usage.cachedPromptTokens =\n (usage.cachedPromptTokens ?? 0) + event.usage.cachedPromptTokens;\n }\n if (event.usage.cacheReadInputTokens) {\n usage.cacheReadInputTokens =\n (usage.cacheReadInputTokens ?? 0) + event.usage.cacheReadInputTokens;\n }\n if (cacheUsageReported(event.usage)) {\n if (!usage.cache) usage.cache = { cachedTokens: 0, promptTokens: 0 };\n addToCacheTotals(usage.cache, event.usage);\n }\n setUsageVersion((v) => v + 1);\n sessionStoreRef.current?.addUsage(event.usage).catch(() => {});\n }\n } else if (event.type === \"retry\") {\n // The resend re-streams the reply from scratch, so roll the\n // buffer back to the committed prefix: the failed attempt's\n // uncommitted tail must go before it duplicates on screen.\n // Already-committed chunks stay (static history can't be edited).\n streamedRef.current = streamedRef.current.slice(0, lastCommittedLenRef.current);\n flushedRef.current = { ...flushedRef.current, streamed: \"\" };\n setStreamingText(\"\");\n const wait =\n event.delayMs !== undefined && event.delayMs >= 1000\n ? ` in ${Math.round(event.delayMs / 1000)}s`\n : \"\";\n pushMessage(\n \"system\",\n `Request failed, retrying (${event.attempt}/${event.maxAttempts})${wait}: ${event.reason}`,\n );\n } else if (event.type === \"notice\") {\n pushMessage(\"system\", event.message);\n } else if (event.type === \"error\") {\n pushMessage(\"system\", `Error: ${formatStreamError(event.error)}`);\n }\n }\n } catch (error) {\n const aborted =\n controller.signal.aborted ||\n (error instanceof DOMException && error.name === \"AbortError\");\n if (!aborted) {\n pushMessage(\n \"system\",\n `Error: ${error instanceof Error ? formatStreamError(error) : String(error)}`,\n );\n }\n } finally {\n tickerStopRef.current?.();\n tickerStopRef.current = null;\n abortRef.current = null;\n setIsStreaming(false);\n thinkingRef.current = false;\n reasoningRef.current = \"\";\n setThinking(false);\n setThinkingText(\"\");\n setThoughtSummary(null);\n setActivity(null);\n const finalText = streamedRef.current.slice(lastCommittedLenRef.current);\n streamedRef.current = \"\";\n lastCommittedLenRef.current = 0;\n setStreamingText(null);\n const interrupted = controller.signal.aborted;\n notifyBell({\n enabled: config.notifyBell,\n thresholdSec: config.notifyBellThresholdSec,\n noNotifyEnv: process.env.STAR_NO_NOTIFY === \"1\",\n interrupted,\n elapsedMs: Date.now() - turnStartedAt,\n });\n if (finalText.length > 0) {\n pushAssistantChunk(finalText, false, interrupted);\n } else if (interrupted && turnChunksRef.current > 0) {\n // The partial reply was already committed to history in pieces, so\n // the marker lands as its own trailing chunk instead.\n pushAssistantChunk(\"\", false, true);\n }\n // Cards whose result event never arrived (e.g. hard abort) still get\n // flushed so no call vanishes from the transcript.\n for (const card of toolCardsRef.current.values()) {\n pushMessage(\"tool\", formatToolCard(card));\n }\n toolCardsRef.current.clear();\n turnChunksRef.current = 0;\n const p = pendingRef.current;\n if (p) {\n setPendingPermission(null);\n p.resolve(false);\n }\n // A plan-mode turn that ran to completion ends in a plan, not in\n // changes — offer to approve it and switch back to execution.\n if (!interrupted && config.permissionMode === \"plan\") {\n setPlanApproval(true);\n }\n // Session budget (sessionBudgetUsd): warn once at 80%, error + block\n // further prompts at 100%. Unevaluable without per-model pricing.\n const cost = sessionCostUsd();\n const budget = config.sessionBudgetUsd;\n const status = budgetState(cost, budget);\n if (status === \"warn\" && !budgetWarnedRef.current) {\n budgetWarnedRef.current = true;\n pushMessage(\n \"system\",\n `Session cost $${formatDollars(cost ?? 0)} has passed 80% of the $${formatDollars(budget ?? 0)} session budget (sessionBudgetUsd).`,\n );\n }\n if (status === \"exceeded\" && !budgetExceededRef.current) {\n budgetExceededRef.current = true;\n pushMessage(\n \"system\",\n `Session budget exceeded: $${formatDollars(cost ?? 0)} of $${formatDollars(budget ?? 0)} (sessionBudgetUsd). New prompts are blocked — raise sessionBudgetUsd in the config or start a /new session.`,\n );\n }\n // Typeahead queue: send the next queued prompt FIFO once this turn is\n // fully done (permission prompts included). A crossed budget drops the\n // queue instead.\n const nextPrompt = queueRef.current.dequeue();\n if (nextPrompt) {\n if (status === \"exceeded\") {\n const dropped = queueRef.current.clear().length + 1;\n setQueueItems([]);\n pushMessage(\n \"system\",\n `Dropped ${dropped} queued message(s) — session budget exceeded.`,\n );\n } else {\n setQueueItems(queueRef.current.list());\n void runStreamRef.current?.(nextPrompt.text, nextPrompt.images);\n }\n }\n }\n },\n [\n pushMessage,\n pushAssistantChunk,\n setPendingPermission,\n setPlanApproval,\n cwd,\n config,\n sessionCostUsd,\n ],\n );\n\n useEffect(() => {\n runStreamRef.current = runStream;\n }, [runStream]);\n\n const handlePlanDecision = useCallback(\n (decision: ExitPlanDecision) => {\n setPlanApproval(false);\n if (decision === \"no\") return;\n const restore = prevModeRef.current ?? \"ask\";\n applySessionMode(restore);\n pushMessage(\"system\", `Plan approved — permission mode restored to ${restore}.`);\n void runStream(\"The plan above is approved. Proceed with the implementation.\");\n },\n [applySessionMode, pushMessage, runStream, setPlanApproval],\n );\n\n const registry = useMemo(() => {\n const ctx: CommandContext = {\n cwd,\n addSystemMessage: (text) => pushMessage(\"system\", text),\n showDiff: (text, lines, note) => {\n setMessages((prev) => {\n const next = [\n ...prev,\n { id: nextIdRef.current++, role: \"system\" as const, text, note, diff: lines },\n ];\n messagesRef.current = next;\n return next;\n });\n },\n clearMessages: () => {\n redrawMessages([]);\n },\n conversationText: (scope) => {\n const current = backendRef.current;\n if (!(current instanceof AgentLoop)) return null;\n const messages = current.getMessages();\n if (scope === \"all\") {\n const parts = messages\n .filter((m) => m.role === \"user\" || m.role === \"assistant\")\n .map((m) => coreMessageText(m))\n .filter((text) => text.length > 0);\n return parts.length > 0 ? parts.join(\"\\n\\n\") : null;\n }\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i];\n if (message?.role === \"assistant\") {\n const text = coreMessageText(message);\n if (text) return text;\n }\n }\n return null;\n },\n copyToClipboard: (text) => copyText(text),\n exit: () => handleExit(),\n listModels: () => {\n const models = listModels(config);\n if (models.length === 0) return \"No models configured.\";\n const lines = models.map(\n (m) =>\n `${m.name === modelNameRef.current ? \"*\" : \" \"} ${m.name} (${m.provider}/${m.model})${m.reasoningEffort ? ` [effort: ${m.reasoningEffort}]` : \"\"}`,\n );\n return `Models (* = current):\\n${lines.join(\"\\n\")}`;\n },\n switchModel,\n listSessions: async (all) => {\n const entries = await listSessionEntries(all ? undefined : cwd);\n if (entries.length === 0) {\n return all ? \"No sessions found.\" : \"No sessions found for this directory.\";\n }\n return formatSessionEntries(entries, { showCwd: all });\n },\n resumeSession: resume,\n pickModel: async () => {\n const models = listModels(config);\n if (models.length === 0) return \"No models configured.\";\n const options: SelectOption[] = models.map((m) => {\n const parts = [`${m.provider}/${m.model}`, `${contextWindowTokens(config, m.name)} ctx`];\n if (m.reasoningEffort) parts.push(`effort: ${m.reasoningEffort}`);\n if (m.promptPrice !== undefined && m.completionPrice !== undefined) {\n parts.push(`$${m.promptPrice}/$${m.completionPrice} per 1M tokens`);\n }\n return {\n value: m.name,\n label: m.name,\n description: parts.join(\" · \"),\n hint: m.name === modelNameRef.current ? \"current\" : undefined,\n };\n });\n const picked = await showPicker(\"Select a model\", options);\n if (!picked) return `Model unchanged — still \"${modelNameRef.current}\".`;\n const results: string[] = [];\n if (picked === modelNameRef.current) {\n results.push(`Model unchanged — still \"${picked}\".`);\n } else {\n const switched = await switchModel(picked);\n if (switched.startsWith(\"Failed to switch model:\")) return switched;\n results.push(switched);\n }\n results.push(await pickReasoningEffort(picked));\n return results.join(\"\\n\");\n },\n pickPermissionMode: async () => {\n const current = config.permissionMode;\n const descriptions: Record<string, string> = {\n ask: \"reads allowed; writes/exec ask for confirmation\",\n auto: \"everything allowed except hard-denied dangerous commands/paths\",\n readonly: \"read-only; all writes/exec denied\",\n yolo: \"allow everything, never ask (disables ALL safety checks)\",\n plan: \"read-only research, then approve a plan before executing (this session only)\",\n };\n const options: SelectOption[] = [\"ask\", \"auto\", \"readonly\", \"yolo\", \"plan\"].map((m) => ({\n value: m,\n label: m,\n description: descriptions[m],\n hint: m === current ? \"current\" : undefined,\n }));\n const picked = await showPicker(\"Select a permission mode\", options);\n if (!picked || picked === current) {\n return `Permission mode unchanged — still ${current}.`;\n }\n if (picked === \"plan\") return ctx.planMode();\n return ctx.permissionMode(picked);\n },\n pickSession: async (all) => {\n // Resuming the live session would open a second SessionStore on the\n // same directory and race its own meta writes — exclude it.\n const currentId = sessionStoreRef.current?.id;\n const entries = (await listSessionEntries(all ? undefined : cwd))\n .filter((entry) => entry.meta.id !== currentId)\n .slice(0, SESSION_PICKER_CAP);\n if (entries.length === 0) {\n return all ? \"No sessions found.\" : \"No sessions found for this directory.\";\n }\n const options: SelectOption[] = await Promise.all(\n entries.map(async ({ meta, messageCount }) => {\n const parts = [`${messageCount} messages · ${relativeTime(meta.updatedAt)}`];\n const preview = await sessionPreview(meta.id);\n if (preview) {\n parts.push(\n preview.length > SESSION_PREVIEW_MAX\n ? `${preview.slice(0, SESSION_PREVIEW_MAX)}…`\n : preview,\n );\n }\n if (all) parts.push(`[${meta.cwd}]`);\n return {\n value: meta.id,\n label: meta.title || shortSessionId(meta.id),\n description: parts.join(\" · \"),\n };\n }),\n );\n const picked = await showPicker(\n all ? \"Resume a session (all directories)\" : \"Resume a session\",\n options,\n );\n if (!picked) return \"Session unchanged — picker cancelled.\";\n return resume(picked);\n },\n forkSession: async () => {\n const current = backendRef.current;\n const store = sessionStoreRef.current;\n if (!(current instanceof AgentLoop) || !store) {\n return \"Nothing to fork — no active session.\";\n }\n const messages = await store.messages();\n if (messages.length === 0) {\n return \"Nothing to fork — the current session has no messages yet.\";\n }\n const fork = await SessionStore.create(cwd, modelNameRef.current);\n await fork.replaceMessages(messages);\n const oldMeta = await store.meta();\n const title = `Fork of ${oldMeta.title || shortSessionId(oldMeta.id)}`;\n await fork.setTitle(title);\n current.setSessionStore(fork);\n sessionStoreRef.current = fork;\n return `Forked into new session ${fork.id} (\"${title}\") and switched to it. Checkpoints and rewind history do not carry over.`;\n },\n newSession: async () => {\n const current = backendRef.current;\n if (!(current instanceof AgentLoop)) {\n return \"Current backend does not support starting a new session.\";\n }\n const store = await SessionStore.create(cwd, modelNameRef.current);\n current.setSessionStore(store);\n sessionStoreRef.current = store;\n // Keep the leading system prompt, drop everything else.\n const [first] = current.getMessages();\n await current.loadMessages(first?.role === \"system\" ? [first] : []);\n clearSnapshots();\n redrawMessages([]);\n // A new session no longer carries the project's persisted todo list.\n resetTodos();\n setTodos([]);\n usageRef.current = emptyUsage();\n budgetWarnedRef.current = false;\n budgetExceededRef.current = false;\n setUsageVersion((v) => v + 1);\n return `Started a new session (${store.id}) with a clean context.`;\n },\n connect: async () => {\n if (pendingConnectRef.current) return \"The connect wizard is already open.\";\n return new Promise<string>((resolve) => {\n setPendingConnect({ resolve });\n });\n },\n clearSessions: async (all) => {\n const currentId = sessionStoreRef.current?.id;\n const removed = await clearSessions(all ? undefined : cwd, currentId);\n if (removed === 0) {\n return all ? \"No stored sessions to delete.\" : \"No stored sessions for this directory.\";\n }\n const scope = all ? \"across all directories\" : \"for this directory\";\n const kept = currentId ? \" The current session is still active.\" : \"\";\n return `Deleted ${removed} session(s) ${scope}.${kept}`;\n },\n showTodos: async () => {\n const store = new TodoStore();\n await store.load(cwd);\n return formatTodos(store.list());\n },\n listTasks: () => formatTaskList(defaultTaskManager.list()),\n showUsage: () => {\n const modelConfig = config.models.find((m) => m.name === modelNameRef.current);\n return `${formatUsage(usageRef.current)}\\n${estimateCost(usageRef.current, modelNameRef.current, modelConfig)}`;\n },\n showGlobalUsage: async () => formatUsageDashboard(await collectUsageStats(), config.models),\n compactContext: async () => {\n let summaryModel = null;\n try {\n summaryModel = createModel(config, modelNameRef.current);\n } catch {\n summaryModel = null;\n }\n // /compact is refused mid-turn, so the stream ticker is free to reuse:\n // drive the spinner with a busy label while compaction runs — the\n // summary call alone can take up to 60s on a slow relay.\n tickerStopRef.current = startTicker((tick) => setSpinnerTick(tick));\n setActivity(\"compacting context…\");\n try {\n const result = await compactSession({\n backend: backendRef.current,\n sessionStore: sessionStoreRef.current,\n config,\n model: summaryModel,\n });\n if (result.compacted && result.messages) {\n const display = buildDisplayMessages(result.messages);\n nextIdRef.current = display.length;\n applyMessages(display);\n }\n return result.message;\n } finally {\n tickerStopRef.current?.();\n tickerStopRef.current = null;\n setActivity(null);\n }\n },\n exportSession: (arg) =>\n exportSession({\n backend: backendRef.current,\n sessionStore: sessionStoreRef.current,\n cwd,\n arg,\n }),\n undo: async () => {\n const current = backendRef.current;\n if (!(current instanceof AgentLoop)) {\n return \"Nothing to undo.\";\n }\n // Read-only preview first: how many messages the retraction drops and\n // which file reverts the turn implies — the whole-tree file list when\n // a git snapshot tracked the turn, per-file diffs otherwise. Nothing\n // is touched until the user confirms.\n const preview = current.previewLastTurnRetraction();\n if (preview.removed === 0) {\n return \"Nothing to undo (no conversation turn to retract).\";\n }\n const diffs = preview.tree\n ? await buildUndoTreeDiffs(cwd, preview.tree)\n : await buildUndoDiffs(\n preview.turn !== undefined ? listTurnSnapshots(preview.turn) : [],\n cwd,\n );\n const summary = preview.tree\n ? `${preview.removed} message(s) will be retracted, and the working tree restored to the turn's start (git snapshot — covers changes from any tool, bash included).`\n : `${preview.removed} message(s) will be retracted, ${diffs.length} file change(s) reverted.`;\n // Undo is destructive: confirm before touching files or history.\n const confirmed = await new Promise<boolean>((resolve) => {\n setPendingRewind({\n title: \"Undo last turn\",\n confirmLabel: \"undo\",\n summary,\n diffs,\n resolve,\n });\n });\n if (!confirmed) {\n return \"Undo cancelled.\";\n }\n // Turn-scoped undo: retract the last turn's messages, and revert file\n // changes only when they provably belong to that same turn — a git\n // tree restore when the turn was tracked (feeding the redo stack),\n // per-file snapshots otherwise.\n const outcome = await current.undoLastTurn();\n if (outcome.removed === 0) {\n return \"Nothing to undo (no conversation turn to retract).\";\n }\n // Mirror the retraction on screen: drop the last prompt and everything\n // the turn produced (answer chunks, tool cards, notifications). Static\n // output cannot be edited in place, so the surviving history is\n // redrawn from a cleared screen.\n const visible = messagesRef.current;\n let cut = -1;\n for (let i = visible.length - 1; i >= 0; i--) {\n if (visible[i]?.role === \"user\") {\n cut = i;\n break;\n }\n }\n redrawMessages(cut >= 0 ? visible.slice(0, cut) : visible);\n return [\n ...outcome.reverted,\n `Retracted the last conversation turn (${outcome.removed} messages).`,\n ].join(\"\\n\");\n },\n redo: async () => {\n const current = backendRef.current;\n if (!(current instanceof AgentLoop)) {\n return \"Nothing to redo.\";\n }\n const entry = current.peekRedo();\n if (!entry) {\n return \"Nothing to redo.\";\n }\n // Redo rewrites the working tree: confirm first, like /undo.\n const confirmed = await new Promise<boolean>((resolve) => {\n setPendingRewind({\n title: \"Redo last undo\",\n confirmLabel: \"redo\",\n summary: formatRedoSummary(entry),\n resolve,\n });\n });\n if (!confirmed) {\n return \"Redo cancelled.\";\n }\n const result = await current.redoLastUndo();\n if (!result) {\n return \"Nothing to redo.\";\n }\n return formatRedoResult(result);\n },\n rewind: async (args) => {\n if (!args) {\n return formatCheckpointList(listSnapshots(), cwd);\n }\n const id = Number.parseInt(args, 10);\n if (!Number.isFinite(id) || String(id) !== args) {\n return `Usage: /rewind <n> — \"${args}\" is not a checkpoint number.`;\n }\n const plan = planRewind(listSnapshots(), id);\n if (!plan) {\n return `Checkpoint #${id} not found (it may already have been rewound). /rewind lists the current checkpoints.`;\n }\n const current = backendRef.current;\n const messageCount =\n plan.messageIndex !== null && current instanceof AgentLoop\n ? current.countRetraction(plan.messageIndex)\n : 0;\n // Rewinds are destructive: confirm before touching files or history.\n const confirmed = await new Promise<boolean>((resolve) => {\n setPendingRewind({\n summary: `Rewind to just before checkpoint #${id} (${plan.target.toolName} ${plan.target.path}):\\n${plan.affected.length} file change(s) will be reverted, ${messageCount} message(s) retracted.`,\n resolve,\n });\n });\n if (!confirmed) {\n return \"Rewind cancelled.\";\n }\n const result = await rewindToSnapshot(id);\n if (!result) {\n return `Checkpoint #${id} is no longer available.`;\n }\n let retracted = 0;\n if (result.messageIndex !== null && current instanceof AgentLoop) {\n retracted = await current.retractFromIndex(result.messageIndex);\n if (retracted > 0) {\n const display = buildDisplayMessages([...current.getMessages()]);\n nextIdRef.current = display.length;\n redrawMessages(display);\n }\n }\n return [\n ...result.reverted,\n `Rewound to before checkpoint #${id}: ${result.reverted.length} file change(s) reverted, ${retracted} message(s) retracted.`,\n ].join(\"\\n\");\n },\n permissionMode: async (args) => {\n const current = config.permissionMode;\n if (!args) {\n const mark = (m: string) => (m === current ? \"*\" : \" \");\n return [\n \"Permission modes (* = current):\",\n `${mark(\"ask\")} ask — reads allowed; writes/exec ask for confirmation`,\n `${mark(\"auto\")} auto — everything allowed except hard-denied dangerous commands/paths`,\n `${mark(\"readonly\")} readonly — read-only; all writes/exec denied`,\n `${mark(\"yolo\")} yolo — allow everything, never ask (disables ALL safety checks)`,\n ].join(\"\\n\");\n }\n const mode = args.toLowerCase();\n if (![\"ask\", \"auto\", \"readonly\", \"yolo\"].includes(mode)) {\n return `Unknown permission mode: ${args} (expected ask | auto | readonly | yolo)`;\n }\n config.permissionMode = mode as StarConfig[\"permissionMode\"];\n prevModeRef.current = null;\n setPermissionModeState(mode);\n await savePermissionMode(mode);\n return mode === \"yolo\"\n ? \"Permission mode set to yolo — ALL safety checks disabled, tools run without asking. Saved to config.\"\n : `Permission mode set to ${mode}. Saved to config.`;\n },\n planMode: async () => {\n if (config.permissionMode === \"plan\") {\n const restore = prevModeRef.current ?? \"ask\";\n applySessionMode(restore);\n return `Exited plan mode — permission mode back to ${restore} (this session only).`;\n }\n applySessionMode(\"plan\");\n return \"Entered plan mode: the agent researches with read-only tools and presents a plan for approval before anything is executed. /plan again to exit.\";\n },\n initProject: async (args) => {\n let model = null;\n try {\n model = createModel(config, modelNameRef.current);\n } catch {\n model = null;\n }\n const result = await initProject({ cwd, args, model });\n return result.message;\n },\n runDoctor: async () => formatDoctorReport(await runDoctor({ cwd, config })),\n submitPrompt: async (text) => {\n await runStream(text);\n },\n describeConfig: () =>\n [\n `defaultModel: ${config.defaultModel || \"(none)\"}`,\n `permissionMode: ${config.permissionMode}`,\n `providers (${config.providers.length}): ${config.providers.map((p) => p.name).join(\", \") || \"(none)\"}`,\n `models (${config.models.length}): ${config.models.map((m) => m.name).join(\", \") || \"(none)\"}`,\n `maxSteps: ${config.maxSteps === 0 ? \"unlimited\" : config.maxSteps}`,\n `contextMaxTokens: ${config.contextMaxTokens}`,\n `compactThresholdTokens: ${config.compactThresholdTokens ?? \"(context window)\"}`,\n `streamIdleTimeoutSec: ${config.streamIdleTimeoutSec}`,\n `streamFirstChunkTimeoutSec: ${config.streamFirstChunkTimeoutSec}`,\n `streamMaxRetries: ${config.streamMaxRetries}`,\n `maxAutoContinues: ${config.maxAutoContinues}`,\n `permissions.allow (${config.permissions.allow.length}): ${config.permissions.allow.join(\", \") || \"(none)\"}`,\n `hooks (${config.hooks.length}): ${config.hooks.map((h) => h.event).join(\", \") || \"(none)\"}`,\n ].join(\"\\n\"),\n };\n const reg = new CommandRegistry();\n registerBuiltinCommands(reg);\n registerCustomCommands(reg, cwd);\n return Object.assign(reg, { ctx });\n }, [\n pushMessage,\n handleExit,\n config,\n cwd,\n switchModel,\n pickReasoningEffort,\n resume,\n runStream,\n applyMessages,\n redrawMessages,\n applySessionMode,\n setPendingRewind,\n setPendingConnect,\n showPicker,\n ]);\n\n const runShellBang = useCallback(\n async (raw: string) => {\n pushMessage(\"user\", `!${raw.trim()}`);\n const controller = new AbortController();\n abortRef.current = controller;\n try {\n const outcome = await executeShellBang(raw, cwd, controller.signal);\n if (!outcome.ok) {\n pushMessage(\n \"system\",\n outcome.reason === \"dangerous\"\n ? `Refused to run dangerous command: ${raw.trim()}`\n : \"Usage: !<command>\",\n );\n return;\n }\n pushMessage(\n \"tool\",\n formatToolCard({\n id: `bang-${nextIdRef.current}`,\n name: \"bash\",\n argsSummary: outcome.command,\n result: outcome.output,\n isError: outcome.isError,\n }),\n );\n const current = backendRef.current;\n if (current instanceof AgentLoop) {\n await current.appendContextMessage(outcome.contextMessage);\n }\n } finally {\n if (abortRef.current === controller) {\n abortRef.current = null;\n }\n }\n },\n [cwd, pushMessage],\n );\n\n const handleSubmit = useCallback(\n (text: string) => {\n appendHistory(text);\n if (text.startsWith(\"!\")) {\n // A bang would clobber the streaming turn's abort controller, so it\n // waits in the queue like a regular prompt.\n if (abortRef.current) {\n queueRef.current.enqueue({ text, images: [] });\n setQueueItems(queueRef.current.list());\n return;\n }\n void runShellBang(text.slice(1));\n return;\n }\n if (text.startsWith(\"/\")) {\n const parsed = parseSlashCommand(text);\n if (!parsed) return;\n const command = registry.get(parsed.name);\n if (!command) {\n const suggestions = registry.complete(parsed.name).map((cmd) => cmd.name);\n pushMessage(\n \"system\",\n `Unknown command: /${parsed.name} (try /help)${didYouMeanSuffix(suggestions)}`,\n );\n return;\n }\n if (abortRef.current && BUSY_BLOCKED_COMMANDS.has(parsed.name)) {\n pushMessage(\"system\", \"Busy — wait for the turn to finish or press Esc to interrupt it.\");\n return;\n }\n void command.run(parsed.args, registry.ctx);\n return;\n }\n const budget = config.sessionBudgetUsd;\n if (budgetState(sessionCostUsd(), budget) === \"exceeded\") {\n pushMessage(\n \"system\",\n `Session budget of $${formatDollars(budget ?? 0)} (sessionBudgetUsd) is exceeded — prompts are blocked. Slash commands still work; raise sessionBudgetUsd in the config or start a /new session.`,\n );\n return;\n }\n const images = pendingImagesRef.current.map((staged) => staged.image);\n if (images.length > 0) clearPendingImages();\n if (abortRef.current) {\n queueRef.current.enqueue({ text, images });\n setQueueItems(queueRef.current.list());\n return;\n }\n void runStream(text, images);\n },\n [registry, pushMessage, runStream, runShellBang, config, clearPendingImages, sessionCostUsd],\n );\n\n const commandHints = useMemo(\n () =>\n registry.list().map((cmd) => ({\n name: cmd.name,\n description: cmd.description,\n usage: cmd.usage ?? `/${cmd.name}`,\n })),\n [registry],\n );\n\n // Expensive status-bar bits (sync git call, token estimate over the full\n // history) refresh on turn boundaries and history rewrites, not per tick.\n // biome-ignore lint/correctness/useExhaustiveDependencies: isStreaming and epoch are deliberate refresh triggers, not values read inside\n useEffect(() => {\n setGitBranch(getGitSummary(cwd)?.branch ?? null);\n const current = backendRef.current;\n if (current instanceof AgentLoop) {\n const window_ = contextWindowTokens(config, modelNameRef.current);\n const pct = (estimateTokens([...current.getMessages()]) / window_) * 100;\n // One decimal below 10% so small-but-real usage doesn't display as 0%.\n setContextPercent(pct < 10 ? Math.round(pct * 10) / 10 : Math.round(pct));\n } else {\n setContextPercent(null);\n }\n }, [cwd, config, isStreaming, epoch]);\n\n const sessionCost = sessionCostUsd();\n\n return (\n <Box flexDirection=\"column\">\n <MessageList key={`messages-${epoch}`} messages={messages} />\n {(thinking || activity !== null) && (\n <ThinkingIndicator\n reasoning={thinkingText}\n frame={spinnerTick}\n activity={activity ?? undefined}\n />\n )}\n {!thinking && activity === null && thoughtSummary !== null && (\n <Text dimColor>{thoughtSummary}</Text>\n )}\n {streamingText !== null && (streamingText !== \"\" || turnChunksRef.current === 0) && (\n <StreamingMessage text={streamingText} continuation={turnChunksRef.current > 0} />\n )}\n {pending && (\n <PermissionPrompt\n request={pending.request}\n preview={pending.preview}\n onDecision={handleDecision}\n />\n )}\n {planApproval && <ExitPlanPrompt onDecision={handlePlanDecision} />}\n {pendingRewind && (\n <RewindConfirmPrompt\n summary={pendingRewind.summary}\n title={pendingRewind.title}\n confirmLabel={pendingRewind.confirmLabel}\n diffs={pendingRewind.diffs}\n onDecision={handleRewindDecision}\n />\n )}\n {picker && (\n <SelectPrompt\n title={picker.title}\n options={picker.options}\n onSelect={handlePickerSelect}\n onCancel={handlePickerCancel}\n />\n )}\n {pendingConnect && (\n <ConnectWizard\n existingProviderNames={config.providers.map((p) => p.name)}\n existingModelNames={config.models.map((m) => m.name)}\n onSave={handleConnectSave}\n onSetDefault={handleConnectSetDefault}\n onOpenConfig={handleConnectOpenConfig}\n onFinish={finishConnect}\n onCancel={cancelConnect}\n />\n )}\n {queueItems.slice(0, MAX_VISIBLE_QUEUED).map((item) => (\n <Text key={item.id} dimColor>\n queued: {item.text.length > 80 ? `${item.text.slice(0, 80)}…` : item.text}\n </Text>\n ))}\n {queueItems.length > MAX_VISIBLE_QUEUED && (\n <Text dimColor>… {queueItems.length - MAX_VISIBLE_QUEUED} more queued</Text>\n )}\n {pendingImages.map((staged) => (\n <Text key={staged.id} dimColor>\n [image attached: {staged.image.path}]\n </Text>\n ))}\n <TodoPanel todos={todos} />\n <InputBox\n isStreaming={isStreaming}\n disabled={\n pending !== null ||\n planApproval ||\n pendingRewind !== null ||\n pendingConnect !== null ||\n picker !== null\n }\n commands={commandHints}\n cwd={cwd}\n refill={inputRefill}\n initialHistory={initialHistory}\n onSubmit={handleSubmit}\n onInterrupt={interrupt}\n onExit={handleExit}\n onPasteImage={handlePasteImage}\n />\n <StatusBar\n cwd={cwd}\n model={modelName}\n permissionMode={permissionModeState}\n tokens={usageRef.current.totalTokens}\n gitBranch={gitBranch}\n contextPercent={contextPercent}\n cachePercent={usageRef.current.cache ? cacheHitPercent(usageRef.current.cache) : null}\n sessionCostUsd={sessionCost}\n backgroundTasks={bgLabels}\n />\n </Box>\n );\n}\n\nexport interface ReplOptions {\n model: string;\n permissionMode: string;\n config: StarConfig;\n cwd: string;\n sessionStore: SessionStore | null;\n initialMessages?: CoreMessage[];\n initialUsage?: UsageStats;\n}\n\nexport function renderRepl(backend: ChatBackend, opts: ReplOptions) {\n // Backstop for abnormal exits: never leave orphaned background processes.\n process.on(\"exit\", () => {\n defaultTaskManager.cleanup();\n });\n return render(\n <Repl\n backend={backend}\n model={opts.model}\n permissionMode={opts.permissionMode}\n config={opts.config}\n cwd={opts.cwd}\n sessionStore={opts.sessionStore}\n initialMessages={opts.initialMessages}\n initialUsage={opts.initialUsage}\n />,\n );\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { parse, stringify } from \"smol-toml\";\nimport { globalConfigPath } from \"./paths\";\n\nexport async function addAllowRule(rule: string): Promise<boolean> {\n return addPermissionRule(\"allow\", rule);\n}\n\nexport async function addDenyRule(rule: string): Promise<boolean> {\n return addPermissionRule(\"deny\", rule);\n}\n\n// TOML basic strings share JSON string escaping.\nfunction tomlString(value: string): string {\n return JSON.stringify(value);\n}\n\nasync function writeFileAtomic(filePath: string, content: string): Promise<void> {\n const tmpPath = `${filePath}.${process.pid}.tmp`;\n await fs.promises.writeFile(tmpPath, content, \"utf8\");\n await fs.promises.rename(tmpPath, filePath);\n}\n\n// Text-level upsert of a rule list into the [permissions] table so comments\n// and unrelated formatting survive: the key line is replaced in place when it\n// is a complete inline array, inserted right after the table header when the\n// key is missing, and the whole table is appended when absent. Returns null\n// when the file's formatting defeats line-level surgery (exotic table header,\n// multi-line array) and the caller must regenerate instead.\nfunction upsertPermissionRuleText(\n content: string,\n kind: \"allow\" | \"deny\",\n rules: string[],\n hadPermissionsTable: boolean,\n): string | null {\n const newLine = `${kind} = [${rules.map(tomlString).join(\", \")}]`;\n const lines = content.split(\"\\n\");\n let sectionStart = -1;\n let sectionEnd = lines.length;\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n if (!/^\\s*\\[/.test(line)) continue;\n if (sectionStart === -1) {\n if (/^\\s*\\[\\s*permissions\\s*\\]\\s*(?:#.*)?$/.test(line)) sectionStart = i;\n } else {\n sectionEnd = i;\n break;\n }\n }\n if (sectionStart === -1) {\n if (hadPermissionsTable) return null;\n const separator = content === \"\" ? \"\" : content.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n return `${content}${separator}[permissions]\\n${newLine}\\n`;\n }\n const inlineArray = new RegExp(`^(\\\\s*)${kind}\\\\s*=\\\\s*\\\\[.*\\\\](\\\\s*(?:#.*)?)$`);\n const anyKey = new RegExp(`^\\\\s*${kind}\\\\s*=`);\n for (let i = sectionStart + 1; i < sectionEnd; i++) {\n const line = lines[i] ?? \"\";\n const match = inlineArray.exec(line);\n if (match) {\n lines[i] = `${match[1]}${newLine}${match[2]}`;\n return lines.join(\"\\n\");\n }\n if (anyKey.test(line)) return null;\n }\n lines.splice(sectionStart + 1, 0, newLine);\n return lines.join(\"\\n\");\n}\n\nasync function addPermissionRule(kind: \"allow\" | \"deny\", rule: string): Promise<boolean> {\n const filePath = globalConfigPath();\n let content = \"\";\n let raw: Record<string, unknown> = {};\n try {\n content = await fs.promises.readFile(filePath, \"utf8\");\n raw = parse(content) as Record<string, unknown>;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n const permissions =\n typeof raw.permissions === \"object\" && raw.permissions !== null\n ? (raw.permissions as Record<string, unknown>)\n : {};\n const rules = Array.isArray(permissions[kind]) ? (permissions[kind] as string[]) : [];\n if (rules.includes(rule)) return false;\n const nextRules = [...rules, rule];\n await fs.promises.mkdir(path.dirname(filePath), { recursive: true });\n const updated = upsertPermissionRuleText(content, kind, nextRules, raw.permissions !== undefined);\n if (updated !== null) {\n await writeFileAtomic(filePath, updated);\n return true;\n }\n permissions[kind] = nextRules;\n raw.permissions = permissions;\n await writeFileAtomic(filePath, stringify(raw));\n return true;\n}\n\n// Top-level keys live before the first [table] header: replace the key line\n// in place when present (comments and unrelated formatting survive), insert\n// right before the first table otherwise.\nfunction upsertTopLevelKeyText(content: string, key: string, value: string): string {\n const newLine = `${key} = ${tomlString(value)}`;\n if (content.trim() === \"\") return `${newLine}\\n`;\n const lines = content.split(\"\\n\");\n const firstTable = lines.findIndex((line) => /^\\s*\\[/.test(line));\n const end = firstTable === -1 ? lines.length : firstTable;\n const keyLine = new RegExp(`^\\\\s*${key}\\\\s*=`);\n for (let i = 0; i < end; i++) {\n const line = lines[i] ?? \"\";\n if (keyLine.test(line)) {\n const comment = /\\s+#.*$/.exec(line);\n lines[i] = `${newLine}${comment?.[0] ?? \"\"}`;\n return lines.join(\"\\n\");\n }\n }\n lines.splice(end, 0, newLine);\n return lines.join(\"\\n\");\n}\n\nexport async function savePermissionMode(mode: string): Promise<void> {\n const filePath = globalConfigPath();\n let content = \"\";\n try {\n content = await fs.promises.readFile(filePath, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n await fs.promises.mkdir(path.dirname(filePath), { recursive: true });\n await writeFileAtomic(filePath, upsertTopLevelKeyText(content, \"permissionMode\", mode));\n}\n\n// Unquotes a TOML basic (\"...\") or literal ('...') string; returns null for\n// anything else (the value comparison then simply never matches).\nfunction unquoteTomlString(raw: string): string | null {\n if (raw.startsWith(\"'\") && raw.endsWith(\"'\")) return raw.slice(1, -1);\n try {\n return JSON.parse(raw) as string;\n } catch {\n return null;\n }\n}\n\n// Text-level upsert of reasoningEffort into the [[models]] block whose name\n// matches, so comments and sibling keys survive: the key line is replaced in\n// place (trailing comment kept), removed when effort is undefined, inserted\n// after the model/name line when missing. Returns null when no block declares\n// this model — the caller then applies the change for the session only\n// instead of appending a fragment block that would fail schema validation.\nexport function setReasoningEffortInToml(\n content: string,\n modelName: string,\n effort: string | undefined,\n): string | null {\n const lines = content.split(\"\\n\");\n const header = /^\\s*\\[\\[\\s*models\\s*\\]\\]\\s*(?:#.*)?$/;\n const anyHeader = /^\\s*\\[/;\n const nameLine = /^\\s*name\\s*=\\s*(\"(?:[^\"\\\\]|\\\\.)*\"|'[^']*')/;\n for (let start = 0; start < lines.length; start++) {\n if (!header.test(lines[start] ?? \"\")) continue;\n let end = lines.length;\n for (let i = start + 1; i < lines.length; i++) {\n if (anyHeader.test(lines[i] ?? \"\")) {\n end = i;\n break;\n }\n }\n let nameIndex = -1;\n for (let i = start + 1; i < end; i++) {\n const match = nameLine.exec(lines[i] ?? \"\");\n if (match?.[1] && unquoteTomlString(match[1]) === modelName) {\n nameIndex = i;\n break;\n }\n }\n if (nameIndex === -1) continue;\n const keyLine = /^\\s*reasoningEffort\\s*=/;\n for (let i = start + 1; i < end; i++) {\n if (!keyLine.test(lines[i] ?? \"\")) continue;\n if (effort === undefined) {\n lines.splice(i, 1);\n } else {\n const comment = /\\s+#.*$/.exec(lines[i] ?? \"\");\n lines[i] = `reasoningEffort = ${tomlString(effort)}${comment?.[0] ?? \"\"}`;\n }\n return lines.join(\"\\n\");\n }\n if (effort === undefined) return content;\n let insertAt = nameIndex + 1;\n for (let i = start + 1; i < end; i++) {\n if (/^\\s*model\\s*=/.test(lines[i] ?? \"\")) {\n insertAt = i + 1;\n break;\n }\n }\n lines.splice(insertAt, 0, `reasoningEffort = ${tomlString(effort)}`);\n return lines.join(\"\\n\");\n }\n return null;\n}\n\n// Persists a model's reasoningEffort to the global config. Returns false when\n// the file declares no [[models]] block for it (e.g. the model only exists in\n// a project config) — nothing is written then.\nexport async function saveReasoningEffort(\n modelName: string,\n effort: string | undefined,\n): Promise<boolean> {\n const filePath = globalConfigPath();\n let content = \"\";\n try {\n content = await fs.promises.readFile(filePath, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n const updated = setReasoningEffortInToml(content, modelName, effort);\n if (updated === null) return false;\n await fs.promises.mkdir(path.dirname(filePath), { recursive: true });\n await writeFileAtomic(filePath, updated);\n return true;\n}\n","import { createAnthropic } from \"@ai-sdk/anthropic\";\nimport { createOpenAI } from \"@ai-sdk/openai\";\nimport { createOpenAICompatible } from \"@ai-sdk/openai-compatible\";\nimport type { LanguageModel } from \"ai\";\nimport type { ProviderConfig, StarConfig } from \"../config/schema\";\nimport { resolveModelConfig } from \"./registry\";\nimport { createSseNormalizingFetch } from \"./sse-normalize\";\n\nexport type ProviderMetadata = Record<string, Record<string, unknown>>;\n\nfunction resolveApiKey(provider: ProviderConfig): string {\n const fromEnv = provider.apiKeyEnv ? process.env[provider.apiKeyEnv] : undefined;\n const apiKey = fromEnv ?? provider.apiKey;\n if (!apiKey) {\n const hint = provider.apiKeyEnv\n ? `set ${provider.apiKeyEnv} or configure apiKey`\n : \"configure apiKey\";\n throw new Error(`Missing API key for provider \"${provider.name}\": ${hint}`);\n }\n return apiKey;\n}\n\nexport function createModel(config: StarConfig, modelName?: string): LanguageModel {\n const modelConfig = resolveModelConfig(config, modelName);\n const provider = config.providers.find((p) => p.name === modelConfig.provider);\n if (!provider) {\n const available = config.providers.map((p) => p.name).join(\", \") || \"(none)\";\n throw new Error(\n `Provider \"${modelConfig.provider}\" for model \"${modelConfig.name}\" not found. Available providers: ${available}`,\n );\n }\n const apiKey = resolveApiKey(provider);\n switch (provider.protocol) {\n case \"anthropic\":\n return createAnthropic({\n baseURL: provider.baseURL,\n apiKey,\n headers: provider.headers,\n })(modelConfig.model);\n case \"openai-compatible\":\n // The per-model config asks the relay for a terminal usage chunk\n // (stream_options.include_usage): relays following OpenAI semantics\n // (DeepSeek, Moonshot) omit usage from streams without it, which left\n // /cost, /usage and the status bar reading zero.\n return createOpenAICompatible({\n name: provider.name,\n baseURL: provider.baseURL,\n apiKey,\n headers: provider.headers,\n })(modelConfig.model, {}, { includeUsage: true });\n case \"openai-responses\":\n return createOpenAI({\n baseURL: provider.baseURL,\n apiKey,\n headers: provider.headers,\n // Relays fronting the Responses API sometimes batch several JSON\n // events into one SSE data payload, which the SDK's parser cannot\n // read; normalize the wire format back to one event per data line.\n fetch: createSseNormalizingFetch(),\n }).responses(modelConfig.model);\n }\n}\n\n// Builds the per-call provider metadata carrying the model's configured\n// reasoningEffort. The metadata key must equal the provider instance name:\n// \"openai\" for the responses-protocol provider (createOpenAI fixes it), the\n// provider's own name for openai-compatible (createOpenAICompatible names the\n// instance after it). Anthropic maps effort to a thinking budget rather than\n// an effort enum — unsupported, so no metadata is produced for it. Returns\n// undefined when the model sets no reasoningEffort (request unchanged).\nexport function reasoningEffortMetadata(\n config: StarConfig,\n modelName?: string,\n): ProviderMetadata | undefined {\n const modelConfig = resolveModelConfig(config, modelName);\n if (!modelConfig.reasoningEffort) return undefined;\n const provider = config.providers.find((p) => p.name === modelConfig.provider);\n if (!provider || provider.protocol === \"anthropic\") return undefined;\n const key = provider.protocol === \"openai-responses\" ? \"openai\" : provider.name;\n return { [key]: { reasoningEffort: modelConfig.reasoningEffort } };\n}\n","import type { ModelConfig, StarConfig } from \"../config/schema\";\n\nexport function listModels(config: StarConfig): ModelConfig[] {\n return config.models;\n}\n\nexport function resolveModelConfig(config: StarConfig, modelName?: string): ModelConfig {\n const name = modelName ?? config.defaultModel;\n const model = config.models.find((m) => m.name === name);\n if (!model) {\n const available = config.models.map((m) => m.name).join(\", \") || \"(none)\";\n throw new Error(`Model \"${name}\" not found. Available models: ${available}`);\n }\n return model;\n}\n","// Some relays (this one fronts the OpenAI Responses API behind\n// /v1/responses) batch several compact JSON events into ONE SSE data\n// payload instead of one event per `data:` line. The AI SDK's SSE parser\n// JSON-parses each data payload whole, so a batched payload fails with\n// \"Unexpected non-whitespace character after JSON\". Codex and opencode\n// parse events line-by-line and tolerate this. Since we stay on the AI SDK,\n// normalize the wire format at the fetch layer: split every batched data\n// payload back into one event per JSON object.\n//\n// The output is NOT byte-equivalent to the input: every event is re-emitted\n// as `data: <payload>` followed by a blank line, so CRLF endings become LF\n// and a `data:{...}` line gains the space after the colon. Lines are split\n// on \\n only — a stream using bare \\r as its line terminator is not\n// supported.\n\n// Splits SSE text into events at blank lines, then re-emits each data\n// payload that holds multiple JSON objects as separate `data:` events.\n// Streaming-safe: lines are buffered across chunks, and a trailing partial\n// line is held until it completes or the stream ends.\nexport class SseNormalizeTransform extends TransformStream<string, string> {\n constructor() {\n let buffer = \"\";\n // Payload of the data field currently being assembled (without the\n // \"data:\" prefix), or null when no event is open.\n let pending: string | null = null;\n\n const flushPending = (controller: TransformStreamDefaultController<string>) => {\n if (pending === null) return;\n controller.enqueue(`data: ${pending}\\n\\n`);\n pending = null;\n };\n\n const handleLine = (raw: string, controller: TransformStreamDefaultController<string>) => {\n const line = raw.endsWith(\"\\r\") ? raw.slice(0, -1) : raw;\n if (line === \"\") {\n flushPending(controller);\n return;\n }\n if (line.startsWith(\"data:\")) {\n // A new data field closes any event already being assembled.\n flushPending(controller);\n pending = line.slice(5).replace(/^ /, \"\");\n return;\n }\n if (line.startsWith(\"{\") && pending !== null) {\n // A continuation line of a batched payload: the previous object is\n // complete, so it becomes its own event and this line opens the next.\n flushPending(controller);\n pending = line;\n return;\n }\n // Comments, event:/id:/retry: fields, and anything else: pass through\n // as a standalone line once no data payload is open.\n flushPending(controller);\n controller.enqueue(`${line}\\n`);\n };\n\n super({\n transform(chunk, controller) {\n buffer += chunk;\n let index = buffer.indexOf(\"\\n\");\n while (index !== -1) {\n handleLine(buffer.slice(0, index), controller);\n buffer = buffer.slice(index + 1);\n index = buffer.indexOf(\"\\n\");\n }\n },\n flush(controller) {\n if (buffer.length > 0) handleLine(buffer, controller);\n flushPending(controller);\n },\n });\n }\n}\n\n// Wraps a base fetch (default: global) so SSE responses are piped through\n// SseNormalizeTransform; non-SSE responses (JSON errors, etc.) pass through\n// untouched. Used for the openai-responses protocol only — chat-completions\n// relays already emit one event per data line.\nexport function createSseNormalizingFetch(baseFetch: typeof fetch = fetch): typeof fetch {\n return async (input, init) => {\n const response = await baseFetch(input, init);\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (!response.body || !contentType.includes(\"text/event-stream\")) {\n return response;\n }\n const body = response.body\n .pipeThrough(new TextDecoderStream())\n .pipeThrough(new SseNormalizeTransform())\n .pipeThrough(new TextEncoderStream());\n // The rewritten body no longer matches the original bytes, so the old\n // content-length/content-encoding would lie about (and corrupt) it.\n const headers = new Headers(response.headers);\n headers.delete(\"content-length\");\n headers.delete(\"content-encoding\");\n return new Response(body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n };\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { FileSnapshot } from \"../tools/fs/snapshots\";\n\nexport interface CheckpointRecord {\n id: number;\n timestamp: number;\n path: string;\n existed: boolean;\n toolName: string;\n turn: number;\n messageIndex: number;\n owner?: \"root\" | \"subagent\";\n // Set when the original content exceeded the snapshot size cap: no content\n // file exists and reverts must skip the file.\n contentTooLarge?: boolean;\n}\n\nfunction checkpointsDir(sessionDir: string): string {\n return path.join(sessionDir, \"checkpoints\");\n}\n\nfunction indexPath(sessionDir: string): string {\n return path.join(checkpointsDir(sessionDir), \"index.json\");\n}\n\n// Read-modify-write on index.json is serialized per session directory, the\n// same pattern as SessionStore's metaWriteQueue: the root loop and background\n// subagents append checkpoints concurrently, and unprotected read-then-write\n// loses records.\nconst indexWriteQueues = new Map<string, Promise<void>>();\n\nfunction enqueueIndexWrite<T>(sessionDir: string, op: () => Promise<T>): Promise<T> {\n const queued = indexWriteQueues.get(sessionDir) ?? Promise.resolve();\n const run = queued.then(op);\n indexWriteQueues.set(\n sessionDir,\n run.then(\n () => {},\n () => {},\n ),\n );\n return run;\n}\n\nexport function checkpointContentPath(sessionDir: string, id: number): string {\n return path.join(checkpointsDir(sessionDir), `${id}.snapshot`);\n}\n\nexport async function listCheckpointRecords(sessionDir: string): Promise<CheckpointRecord[]> {\n let raw: string;\n try {\n raw = await fs.readFile(indexPath(sessionDir), \"utf8\");\n } catch {\n return [];\n }\n try {\n const parsed = JSON.parse(raw) as CheckpointRecord[];\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\n// Lazily creates the checkpoints directory on first use, mirroring\n// SessionStore's lazy creation — a session without file writes leaves no\n// checkpoints on disk.\nexport async function appendCheckpointRecord(\n sessionDir: string,\n record: CheckpointRecord,\n content: string | null,\n): Promise<void> {\n await enqueueIndexWrite(sessionDir, async () => {\n await fs.mkdir(checkpointsDir(sessionDir), { recursive: true, mode: 0o700 });\n if (record.existed && content !== null) {\n await fs.writeFile(checkpointContentPath(sessionDir, record.id), content, \"utf8\");\n }\n const records = await listCheckpointRecords(sessionDir);\n records.push(record);\n await fs.writeFile(indexPath(sessionDir), JSON.stringify(records, null, 2));\n });\n}\n\nexport async function removeCheckpointRecords(sessionDir: string, ids: number[]): Promise<void> {\n if (ids.length === 0) return;\n await enqueueIndexWrite(sessionDir, async () => {\n const drop = new Set(ids);\n const records = await listCheckpointRecords(sessionDir);\n const kept = records.filter((record) => !drop.has(record.id));\n if (kept.length === records.length) return;\n await fs.mkdir(checkpointsDir(sessionDir), { recursive: true, mode: 0o700 });\n await fs.writeFile(indexPath(sessionDir), JSON.stringify(kept, null, 2));\n for (const id of ids) {\n await fs.rm(checkpointContentPath(sessionDir, id), { force: true });\n }\n });\n}\n\n// Maps persisted records back into snapshots whose content is read lazily\n// from the per-checkpoint content file, for hydrating the in-memory stack\n// after a session resume.\nexport async function loadSessionSnapshots(sessionDir: string): Promise<FileSnapshot[]> {\n const records = await listCheckpointRecords(sessionDir);\n return records.map((record) => ({\n ...record,\n content: null,\n contentFile:\n record.existed && !record.contentTooLarge\n ? checkpointContentPath(sessionDir, record.id)\n : undefined,\n }));\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { sessionsDir } from \"../config/paths\";\nimport { SessionStore } from \"./store\";\n\n// Deletes stored sessions and returns how many were removed. With a cwd only\n// sessions recorded for that directory go (directories with an unreadable\n// meta.json cannot be matched and stay); without it every session directory\n// under sessionsDir is removed. excludeId keeps the caller's live session on\n// disk (the REPL's /clear-sessions must not pull its own store away).\nexport async function clearSessions(cwd?: string, excludeId?: string): Promise<number> {\n if (cwd !== undefined) {\n const metas = await SessionStore.list(cwd);\n let removed = 0;\n for (const meta of metas) {\n if (meta.id === excludeId) continue;\n await fs.rm(path.join(sessionsDir(), meta.id), { recursive: true, force: true });\n removed += 1;\n }\n return removed;\n }\n let entries: string[];\n try {\n entries = await fs.readdir(sessionsDir());\n } catch {\n return 0;\n }\n let removed = 0;\n for (const entry of entries) {\n if (entry === excludeId) continue;\n await fs.rm(path.join(sessionsDir(), entry), { recursive: true, force: true });\n removed += 1;\n }\n return removed;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { sessionsDir } from \"../config/paths\";\nimport type { CoreMessage } from \"../core/messages\";\nimport {\n type CheckpointRecord,\n appendCheckpointRecord,\n listCheckpointRecords,\n removeCheckpointRecords,\n} from \"./checkpoints\";\n\nexport interface SessionUsage {\n requests: number;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n // Prompt-cache totals; present only after a provider reports cache fields.\n cachedPromptTokens?: number;\n cacheReadInputTokens?: number;\n}\n\nexport interface DayUsageBucket {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\nexport interface SessionMeta {\n id: string;\n title: string;\n model: string;\n cwd: string;\n createdAt: number;\n updatedAt: number;\n usage?: SessionUsage;\n // Per-day token buckets keyed by local date (YYYY-MM-DD), recorded alongside\n // `usage` from the day this field was introduced; older sessions only have\n // the grand totals in `usage`.\n usageByDay?: Record<string, DayUsageBucket>;\n}\n\nfunction generateId(now: Date): string {\n const pad = (n: number) => String(n).padStart(2, \"0\");\n const stamp =\n `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}` +\n `${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;\n const suffix = Math.random().toString(16).slice(2, 8).padEnd(6, \"0\");\n return `${stamp}-${suffix}`;\n}\n\nfunction debugWarn(message: string): void {\n if (process.env.STAR_DEBUG === \"1\") process.stderr.write(`[star-cli] ${message}\\n`);\n}\n\n// Windows antivirus and search indexers briefly lock freshly written files,\n// so a rename right after the write can come back EPERM/EACCES/EBUSY; a few\n// short retries ride out the scan.\nconst META_WRITE_MAX_ATTEMPTS = 5;\nconst META_WRITE_RETRY_DELAY_MS = 25;\n\nfunction isTransientFsError(error: unknown): boolean {\n const code = (error as NodeJS.ErrnoException).code;\n return code === \"EPERM\" || code === \"EACCES\" || code === \"EBUSY\";\n}\n\n// Brands the fallback meta returned for a corrupt/unreadable meta.json so\n// writeMeta can refuse to persist it: writing the empty defaults back would\n// wipe the real model/cwd/usage fields still sitting in the damaged file.\nconst FALLBACK_META: unique symbol = Symbol(\"star.fallbackMeta\");\n\nfunction isFallbackMeta(meta: SessionMeta): boolean {\n return (meta as unknown as Record<symbol, unknown>)[FALLBACK_META] === true;\n}\n\nexport function dayKey(date: Date): string {\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;\n}\n\nexport class SessionStore {\n readonly id: string;\n readonly dir: string;\n\n private pendingMeta: { cwd: string; model: string; createdAt: number } | null = null;\n private initialized = false;\n private cachedMeta: SessionMeta | null = null;\n private metaTmpSeq = 0;\n private metaWriteQueue: Promise<void> = Promise.resolve();\n\n private constructor(id: string) {\n this.id = id;\n this.dir = path.join(sessionsDir(), id);\n }\n\n private metaPath(): string {\n return path.join(this.dir, \"meta.json\");\n }\n\n private messagesPath(): string {\n return path.join(this.dir, \"messages.jsonl\");\n }\n\n static async create(cwd: string, model: string): Promise<SessionStore> {\n const store = new SessionStore(generateId(new Date()));\n store.pendingMeta = { cwd, model, createdAt: Date.now() };\n return store;\n }\n\n static async open(id: string): Promise<SessionStore | null> {\n const store = new SessionStore(id);\n let raw: string;\n try {\n raw = await fs.readFile(store.metaPath(), \"utf8\");\n } catch {\n return null;\n }\n try {\n const meta = JSON.parse(raw) as SessionMeta;\n if (meta.id !== id) return null;\n } catch {\n // meta.json is corrupt (e.g. truncated write); open anyway and let\n // meta() fall back to defaults so messages stay resumable.\n debugWarn(`session ${id}: corrupt meta.json, using defaults`);\n }\n await store.sweepTmpFiles();\n store.initialized = true;\n return store;\n }\n\n static async list(cwd?: string): Promise<SessionMeta[]> {\n let entries: string[];\n try {\n entries = await fs.readdir(sessionsDir());\n } catch {\n return [];\n }\n const metas = await Promise.all(\n entries.map(async (entry) => {\n try {\n const raw = await fs.readFile(path.join(sessionsDir(), entry, \"meta.json\"), \"utf8\");\n const meta = JSON.parse(raw) as SessionMeta;\n if (meta.id === entry && (cwd === undefined || meta.cwd === cwd)) return meta;\n } catch {\n // 跳过损坏的会话目录\n }\n return null;\n }),\n );\n return metas\n .filter((meta): meta is SessionMeta => meta !== null)\n .sort((a, b) => b.updatedAt - a.updatedAt);\n }\n\n // Meta writes are serialized per instance and land atomically (tmp file +\n // rename) over a cached in-memory meta: the fire-and-forget title/usage\n // writers race the loop's own appends, and a truncated read once turned\n // fallbackMeta's empty defaults into a persisted wipe of model/cwd/usage.\n // A branded fallback meta is never written back for the same reason.\n // A write that still fails after retries is dropped rather than thrown:\n // meta.json is bookkeeping the cached meta rebuilds on the next write,\n // while the conversation itself lives in messages.jsonl — killing the\n // agent turn over a stale updatedAt would be the wrong trade.\n private writeMeta(meta: SessionMeta): Promise<void> {\n if (isFallbackMeta(meta)) return Promise.resolve();\n const tmp = `${this.metaPath()}.tmp-${process.pid}-${this.metaTmpSeq++}`;\n const run = this.metaWriteQueue.then(async () => {\n for (let attempt = 0; attempt < META_WRITE_MAX_ATTEMPTS; attempt++) {\n try {\n await fs.writeFile(tmp, JSON.stringify(meta, null, 2));\n await fs.rename(tmp, this.metaPath());\n return;\n } catch (error) {\n if (isTransientFsError(error) && attempt + 1 < META_WRITE_MAX_ATTEMPTS) {\n await new Promise((resolve) =>\n setTimeout(resolve, META_WRITE_RETRY_DELAY_MS * (attempt + 1)),\n );\n continue;\n }\n await fs.unlink(tmp).catch(() => {});\n debugWarn(\n `session ${this.id}: meta write failed (${(error as NodeJS.ErrnoException).code ?? String(error)}), skipping`,\n );\n return;\n }\n }\n });\n this.metaWriteQueue = run.catch(() => {});\n return run;\n }\n\n private async ensureInitialized(): Promise<void> {\n if (this.initialized) return;\n const pending = this.pendingMeta;\n if (!pending) {\n this.initialized = true;\n return;\n }\n // Session directories hold file contents (checkpoints); keep them private\n // on shared machines. The mode is a no-op on Windows.\n await fs.mkdir(this.dir, { recursive: true, mode: 0o700 });\n await this.sweepTmpFiles();\n const meta: SessionMeta = {\n id: this.id,\n title: \"\",\n model: pending.model,\n cwd: pending.cwd,\n createdAt: pending.createdAt,\n updatedAt: pending.createdAt,\n };\n await this.writeMeta(meta);\n this.cachedMeta = meta;\n this.initialized = true;\n }\n\n // Removes meta.json.tmp-* orphans left behind by a crashed meta write\n // (tmp file + rename); best-effort, the directory may not even exist yet.\n private async sweepTmpFiles(): Promise<void> {\n let entries: string[];\n try {\n entries = await fs.readdir(this.dir);\n } catch {\n return;\n }\n await Promise.all(\n entries\n .filter((entry) => entry.startsWith(\"meta.json.tmp-\"))\n .map((entry) => fs.unlink(path.join(this.dir, entry)).catch(() => {})),\n );\n }\n\n async append(message: CoreMessage): Promise<void> {\n await this.ensureInitialized();\n await fs.appendFile(this.messagesPath(), `${JSON.stringify(message)}\\n`);\n const meta = await this.meta();\n meta.updatedAt = Date.now();\n await this.writeMeta(meta);\n }\n\n async replaceMessages(messages: CoreMessage[]): Promise<void> {\n await this.ensureInitialized();\n const content = messages.map((message) => JSON.stringify(message)).join(\"\\n\");\n await fs.writeFile(this.messagesPath(), content ? `${content}\\n` : \"\");\n const meta = await this.meta();\n meta.updatedAt = Date.now();\n await this.writeMeta(meta);\n }\n\n async messages(): Promise<CoreMessage[]> {\n let raw: string;\n try {\n raw = await fs.readFile(this.messagesPath(), \"utf8\");\n } catch {\n return [];\n }\n const messages: CoreMessage[] = [];\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n messages.push(JSON.parse(trimmed) as CoreMessage);\n } catch {\n debugWarn(`session ${this.id}: skipping corrupt messages.jsonl line`);\n }\n }\n return messages;\n }\n\n private fallbackMeta(): SessionMeta {\n const now = Date.now();\n const meta: SessionMeta = {\n id: this.id,\n title: \"\",\n model: \"\",\n cwd: \"\",\n createdAt: now,\n updatedAt: now,\n };\n // Non-enumerable, so it neither shows up in JSON.stringify nor spreads.\n Object.defineProperty(meta, FALLBACK_META, { value: true, enumerable: false });\n return meta;\n }\n\n async meta(): Promise<SessionMeta> {\n await this.ensureInitialized();\n if (this.cachedMeta) return this.cachedMeta;\n try {\n const raw = await fs.readFile(this.metaPath(), \"utf8\");\n this.cachedMeta = JSON.parse(raw) as SessionMeta;\n return this.cachedMeta;\n } catch {\n // The fallback is neither cached nor written back: a transient read\n // failure must not turn into a persisted wipe of the real meta.\n debugWarn(`session ${this.id}: unreadable meta.json, using defaults`);\n return this.fallbackMeta();\n }\n }\n\n async setTitle(title: string): Promise<void> {\n await this.ensureInitialized();\n const meta = await this.meta();\n meta.title = title;\n meta.updatedAt = Date.now();\n await this.writeMeta(meta);\n }\n\n async appendCheckpoint(record: CheckpointRecord, content: string | null): Promise<void> {\n await this.ensureInitialized();\n await appendCheckpointRecord(this.dir, record, content);\n }\n\n async listCheckpoints(): Promise<CheckpointRecord[]> {\n return listCheckpointRecords(this.dir);\n }\n\n async removeCheckpoints(ids: number[]): Promise<void> {\n await removeCheckpointRecords(this.dir, ids);\n }\n\n async addUsage(delta: {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n cachedPromptTokens?: number;\n cacheReadInputTokens?: number;\n }): Promise<void> {\n await this.ensureInitialized();\n const meta = await this.meta();\n const usage = meta.usage ?? {\n requests: 0,\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n };\n usage.requests += 1;\n usage.promptTokens += delta.promptTokens;\n usage.completionTokens += delta.completionTokens;\n usage.totalTokens += delta.totalTokens;\n if (delta.cachedPromptTokens) {\n usage.cachedPromptTokens = (usage.cachedPromptTokens ?? 0) + delta.cachedPromptTokens;\n }\n if (delta.cacheReadInputTokens) {\n usage.cacheReadInputTokens = (usage.cacheReadInputTokens ?? 0) + delta.cacheReadInputTokens;\n }\n meta.usage = usage;\n const day = dayKey(new Date());\n const byDay = meta.usageByDay ?? {};\n const bucket = byDay[day] ?? { promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n bucket.promptTokens += delta.promptTokens;\n bucket.completionTokens += delta.completionTokens;\n bucket.totalTokens += delta.totalTokens;\n byDay[day] = bucket;\n meta.usageByDay = byDay;\n await this.writeMeta(meta);\n }\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { sessionsDir } from \"../config/paths\";\nimport type { CoreMessage } from \"../core/messages\";\nimport { type SessionMeta, SessionStore } from \"./store\";\n\nexport interface SessionListEntry {\n meta: SessionMeta;\n messageCount: number;\n}\n\nasync function countMessages(id: string): Promise<number> {\n let raw: string;\n try {\n raw = await fs.readFile(path.join(sessionsDir(), id, \"messages.jsonl\"), \"utf8\");\n } catch {\n return 0;\n }\n let count = 0;\n for (const line of raw.split(\"\\n\")) {\n if (line.trim()) count += 1;\n }\n return count;\n}\n\nexport async function listSessionEntries(cwd?: string): Promise<SessionListEntry[]> {\n const metas = await SessionStore.list(cwd);\n return Promise.all(\n metas.map(async (meta) => ({ meta, messageCount: await countMessages(meta.id) })),\n );\n}\n\nexport async function findLatestSession(cwd: string): Promise<SessionMeta | null> {\n const [latest] = await SessionStore.list(cwd);\n return latest ?? null;\n}\n\n// Reads only the head of messages.jsonl and extracts the first user message's\n// text, whitespace-collapsed onto one line — the /resume picker needs a\n// preview per session and must not parse every full history for it. The final\n// partial line at the read boundary and any corrupt lines are skipped.\n// Returns null when no user text is found (or the file is unreadable).\nexport async function sessionPreview(id: string, maxBytes = 4096): Promise<string | null> {\n let handle: fs.FileHandle | null = null;\n try {\n handle = await fs.open(path.join(sessionsDir(), id, \"messages.jsonl\"), \"r\");\n const buffer = Buffer.alloc(maxBytes);\n const { bytesRead } = await handle.read(buffer, 0, maxBytes, 0);\n const head = buffer.toString(\"utf8\", 0, bytesRead);\n for (const line of head.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const message = JSON.parse(trimmed) as CoreMessage;\n if (message.role !== \"user\") continue;\n const text =\n typeof message.content === \"string\"\n ? message.content\n : message.content\n .filter((part) => part.type === \"text\")\n .map((part) => (part.type === \"text\" ? part.text : \"\"))\n .join(\" \");\n const collapsed = text.replace(/\\s+/g, \" \").trim();\n if (collapsed) return collapsed;\n } catch {\n // Half line at the read boundary or a corrupt line — keep looking.\n }\n }\n return null;\n } catch {\n return null;\n } finally {\n await handle?.close().catch(() => {});\n }\n}\n\nexport function shortSessionId(id: string): string {\n const dash = id.lastIndexOf(\"-\");\n return dash === -1 ? id : id.slice(dash + 1);\n}\n\nexport async function resolveSessionId(query: string): Promise<string | null> {\n const metas = await SessionStore.list();\n const exact = metas.find((meta) => meta.id === query);\n if (exact) return exact.id;\n const matches = metas.filter(\n (meta) => shortSessionId(meta.id) === query || meta.id.startsWith(query),\n );\n return matches.length === 1 ? (matches[0]?.id ?? null) : null;\n}\n\nexport function relativeTime(timestamp: number): string {\n const diff = Date.now() - timestamp;\n const minutes = Math.floor(diff / 60_000);\n if (minutes < 1) return \"just now\";\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n if (days < 30) return `${days}d ago`;\n const months = Math.floor(days / 30);\n if (months < 12) return `${months}mo ago`;\n return `${Math.floor(months / 12)}y ago`;\n}\n\nexport function formatSessionEntries(\n entries: SessionListEntry[],\n options: { showCwd?: boolean } = {},\n): string {\n return entries\n .map(({ meta, messageCount }) => {\n const title = meta.title || \"(untitled)\";\n const base =\n `${shortSessionId(meta.id)} ${title} ` +\n `${messageCount} messages updated ${relativeTime(meta.updatedAt)}`;\n return options.showCwd ? `${base} [${meta.cwd}]` : base;\n })\n .join(\"\\n\");\n}\n","import { type CoreMessage, reconcileToolCalls } from \"../core/messages\";\nimport { type SessionMeta, SessionStore } from \"./store\";\n\nexport async function resumeSession(\n id: string,\n): Promise<{ meta: SessionMeta; messages: CoreMessage[] } | null> {\n const store = await SessionStore.open(id);\n if (!store) return null;\n const [meta, loaded] = await Promise.all([store.meta(), store.messages()]);\n const messages = reconcileToolCalls(loaded);\n if (messages.length !== loaded.length) {\n await store.replaceMessages(messages);\n }\n return { meta, messages };\n}\n","import type { ModelConfig } from \"../config/schema\";\n\nexport interface TokenUsage {\n promptTokens: number;\n completionTokens: number;\n // Prompt tokens served from the provider cache, a subset of promptTokens\n // (OpenAI / openai-compatible style).\n cachedPromptTokens?: number;\n // Cache-read tokens reported on top of promptTokens (Anthropic style).\n cacheReadInputTokens?: number;\n}\n\nexport function formatDollars(cost: number): string {\n let s = cost.toFixed(4).replace(/0+$/, \"\");\n if (s.endsWith(\".\")) {\n s += \"00\";\n } else if (s.split(\".\")[1]?.length === 1) {\n s += \"0\";\n }\n return s;\n}\n\n// Numeric session cost in USD; null when the model has no pricing configured.\n// Cache pricing: OpenAI-style cached tokens are a subset of promptTokens, so\n// the uncached rest bills at promptPrice and the cached share at\n// cacheReadPrice (full promptPrice when no cache price is configured);\n// Anthropic-style cache reads come on top of promptTokens and bill at\n// cacheReadPrice only (unconfigured = unbilled, as before).\nexport function computeCostUsd(usage: TokenUsage, model: ModelConfig | undefined): number | null {\n if (model?.promptPrice === undefined || model.completionPrice === undefined) {\n return null;\n }\n const cached = Math.min(Math.max(usage.cachedPromptTokens ?? 0, 0), usage.promptTokens);\n const promptUsd =\n (usage.promptTokens - cached) * model.promptPrice +\n cached * (model.cacheReadPrice ?? model.promptPrice) +\n (usage.cacheReadInputTokens ?? 0) * (model.cacheReadPrice ?? 0);\n return (promptUsd + usage.completionTokens * model.completionPrice) / 1_000_000;\n}\n\nexport function estimateCost(\n usage: TokenUsage,\n modelName: string,\n model: ModelConfig | undefined,\n): string {\n const cost = computeCostUsd(usage, model);\n if (cost === null) {\n if (model !== undefined) {\n const missing = [\n model.promptPrice === undefined ? \"promptPrice\" : null,\n model.completionPrice === undefined ? \"completionPrice\" : null,\n ].filter((f) => f !== null);\n if (missing.length === 1) {\n return `Estimated cost: unknown (${model.name} is missing ${missing[0]} — both prices are needed)`;\n }\n }\n return `Estimated cost: unknown (no price configured for ${modelName})`;\n }\n const cachePrice =\n model?.cacheReadPrice !== undefined ? `, $${model.cacheReadPrice}/M cache read` : \"\";\n return `Estimated cost: $${formatDollars(cost)} (${model?.name} @ $${model?.promptPrice}/M prompt, $${model?.completionPrice}/M completion${cachePrice})`;\n}\n","import { computeCostUsd, formatDollars } from \"../cli/cost\";\nimport type { ModelConfig } from \"../config/schema\";\nimport { type SessionMeta, SessionStore } from \"./store\";\n\nexport interface UsageBucket {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\nexport interface DayUsage extends UsageBucket {\n date: string;\n}\n\nexport interface ModelUsage extends UsageBucket {\n model: string;\n sessions: number;\n requests: number;\n // Prompt-cache totals for cache-aware pricing; absent until reported.\n cachedPromptTokens?: number;\n cacheReadInputTokens?: number;\n}\n\nexport interface GlobalUsageStats {\n sessions: number;\n sessionsWithUsage: number;\n requests: number;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n // Ascending by date (YYYY-MM-DD, local).\n days: DayUsage[];\n // Tokens recorded before per-day bucketing existed (usage totals minus the\n // sum of usageByDay), null when nothing predates it.\n legacy: UsageBucket | null;\n // Descending by totalTokens.\n models: ModelUsage[];\n}\n\nexport const USAGE_MAX_DAYS = 14;\n\nfunction tokens(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : 0;\n}\n\nfunction bucketOf(value: unknown): UsageBucket {\n const record = (typeof value === \"object\" && value !== null ? value : {}) as Record<\n string,\n unknown\n >;\n const promptTokens = tokens(record.promptTokens);\n const completionTokens = tokens(record.completionTokens);\n return {\n promptTokens,\n completionTokens,\n totalTokens: tokens(record.totalTokens) || promptTokens + completionTokens,\n };\n}\n\nfunction addTo(target: UsageBucket, source: UsageBucket): void {\n target.promptTokens += source.promptTokens;\n target.completionTokens += source.completionTokens;\n target.totalTokens += source.totalTokens;\n}\n\nexport function aggregateUsage(metas: SessionMeta[]): GlobalUsageStats {\n const days = new Map<string, UsageBucket>();\n const models = new Map<string, ModelUsage>();\n const legacy: UsageBucket = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n let hasLegacy = false;\n let sessionsWithUsage = 0;\n let requests = 0;\n const grand: UsageBucket = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n\n for (const meta of metas) {\n const dayBuckets: [string, UsageBucket][] = [];\n if (meta.usageByDay !== null && typeof meta.usageByDay === \"object\") {\n for (const [date, value] of Object.entries(meta.usageByDay)) {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) continue;\n dayBuckets.push([date, bucketOf(value)]);\n }\n }\n const daySum: UsageBucket = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n for (const [, bucket] of dayBuckets) addTo(daySum, bucket);\n\n const hasTotals = meta.usage !== null && typeof meta.usage === \"object\";\n const totals = hasTotals ? bucketOf(meta.usage) : daySum;\n const requestCount = hasTotals && meta.usage ? tokens(meta.usage.requests) : 0;\n if (!hasTotals && dayBuckets.length === 0) continue;\n\n sessionsWithUsage += 1;\n addTo(grand, totals);\n requests += requestCount;\n\n for (const [date, bucket] of dayBuckets) {\n const acc = days.get(date) ?? { promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n addTo(acc, bucket);\n days.set(date, acc);\n }\n\n if (hasTotals) {\n const rest: UsageBucket = {\n promptTokens: Math.max(0, totals.promptTokens - daySum.promptTokens),\n completionTokens: Math.max(0, totals.completionTokens - daySum.completionTokens),\n totalTokens: Math.max(0, totals.totalTokens - daySum.totalTokens),\n };\n if (rest.promptTokens > 0 || rest.completionTokens > 0 || rest.totalTokens > 0) {\n addTo(legacy, rest);\n hasLegacy = true;\n }\n }\n\n const name = typeof meta.model === \"string\" && meta.model.trim() ? meta.model : \"unknown\";\n const entry = models.get(name) ?? {\n model: name,\n sessions: 0,\n requests: 0,\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n };\n entry.sessions += 1;\n entry.requests += requestCount;\n addTo(entry, totals);\n if (hasTotals && meta.usage) {\n const cached = tokens(meta.usage.cachedPromptTokens);\n const cacheRead = tokens(meta.usage.cacheReadInputTokens);\n if (cached > 0) entry.cachedPromptTokens = (entry.cachedPromptTokens ?? 0) + cached;\n if (cacheRead > 0) entry.cacheReadInputTokens = (entry.cacheReadInputTokens ?? 0) + cacheRead;\n }\n models.set(name, entry);\n }\n\n return {\n sessions: metas.length,\n sessionsWithUsage,\n requests,\n promptTokens: grand.promptTokens,\n completionTokens: grand.completionTokens,\n totalTokens: grand.totalTokens,\n days: [...days.entries()]\n .map(([date, bucket]) => ({ date, ...bucket }))\n .sort((a, b) => a.date.localeCompare(b.date)),\n legacy: hasLegacy ? legacy : null,\n models: [...models.values()].sort((a, b) => b.totalTokens - a.totalTokens),\n };\n}\n\nexport async function collectUsageStats(): Promise<GlobalUsageStats> {\n return aggregateUsage(await SessionStore.list());\n}\n\nfunction fmt(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n\nconst BAR_WIDTH = 30;\n\nexport function formatUsageDashboard(\n stats: GlobalUsageStats,\n models: ModelConfig[],\n options: { maxDays?: number } = {},\n): string {\n if (stats.sessions === 0) return \"No sessions found.\";\n\n const lines: string[] = [\n \"Token usage across all sessions\",\n \"\",\n `Total: ${stats.sessions} sessions (${stats.sessionsWithUsage} with usage) · ` +\n `${fmt(stats.requests)} requests · ` +\n `${fmt(stats.promptTokens)} prompt + ${fmt(stats.completionTokens)} completion = ` +\n `${fmt(stats.totalTokens)} tokens`,\n ];\n\n if (stats.sessionsWithUsage === 0) {\n lines.push(\"\", \"No token usage recorded yet.\");\n return lines.join(\"\\n\");\n }\n\n const maxDays = options.maxDays ?? USAGE_MAX_DAYS;\n const recent = stats.days.slice(-maxDays);\n if (recent.length > 0) {\n lines.push(\"\");\n lines.push(\n stats.days.length > maxDays\n ? `By day (last ${maxDays} of ${stats.days.length} days with usage):`\n : \"By day:\",\n );\n const maxTotal = Math.max(...recent.map((day) => day.totalTokens));\n for (const day of recent) {\n const barLen =\n maxTotal > 0 ? Math.max(1, Math.round((day.totalTokens / maxTotal) * BAR_WIDTH)) : 0;\n lines.push(`${day.date} ${fmt(day.totalTokens).padStart(12)} ${\"█\".repeat(barLen)}`);\n }\n }\n if (stats.legacy) {\n lines.push(\n `Earlier usage without per-day records: ${fmt(stats.legacy.totalTokens)} tokens ` +\n `(${fmt(stats.legacy.promptTokens)} prompt + ${fmt(stats.legacy.completionTokens)} completion)`,\n );\n }\n\n lines.push(\"\", \"By model:\");\n const configured = new Map(models.map((m) => [m.name, m]));\n const rows = stats.models.map((entry) => {\n const cfg = configured.get(entry.model);\n const cost = computeCostUsd(entry, cfg);\n return { entry, cost };\n });\n const header = [\"model\", \"requests\", \"prompt\", \"completion\", \"total\", \"cost\"];\n const cells = rows.map(({ entry, cost }) => [\n entry.model,\n fmt(entry.requests),\n fmt(entry.promptTokens),\n fmt(entry.completionTokens),\n fmt(entry.totalTokens),\n cost === null ? \"—\" : `$${formatDollars(cost)}`,\n ]);\n const widths = header.map((h, i) =>\n Math.max(h.length, ...cells.map((row) => row[i]?.length ?? 0)),\n );\n const renderRow = (row: string[]) =>\n row\n .map((cell, i) => (i === 0 ? cell.padEnd(widths[0] ?? 0) : cell.padStart(widths[i] ?? 0)))\n .join(\" \");\n lines.push(renderRow(header));\n for (const row of cells) lines.push(renderRow(row));\n\n const pricedCosts = rows.filter((row) => row.cost !== null).map((row) => row.cost as number);\n const unpriced = rows.filter((row) => row.cost === null).map((row) => row.entry.model);\n if (pricedCosts.length > 0) {\n const total = pricedCosts.reduce((sum, cost) => sum + cost, 0);\n const note =\n unpriced.length > 0 ? ` (excludes ${unpriced.join(\", \")} — no price configured)` : \"\";\n lines.push(\"\", `Estimated cost: $${formatDollars(total)}${note}`);\n } else {\n lines.push(\"\", \"Estimated cost: unknown (no per-model pricing configured)\");\n }\n\n return lines.join(\"\\n\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nfunction readPackageVersion(): string {\n try {\n const pkgPath = path.join(path.dirname(fileURLToPath(import.meta.url)), \"..\", \"package.json\");\n const pkg: unknown = JSON.parse(fs.readFileSync(pkgPath, \"utf8\"));\n if (typeof pkg === \"object\" && pkg !== null) {\n const version = (pkg as { version?: unknown }).version;\n if (typeof version === \"string\") return version;\n }\n } catch {\n // fall through to placeholder\n }\n return \"0.0.0\";\n}\n\nexport const VERSION = readPackageVersion();\n","export type BudgetStatus = \"ok\" | \"warn\" | \"exceeded\";\n\nexport const BUDGET_WARN_RATIO = 0.8;\n\n// Session budget decision against config.sessionBudgetUsd. Cost is null when\n// the model has no pricing configured — the budget cannot be evaluated then.\nexport function budgetState(costUsd: number | null, budgetUsd: number | undefined): BudgetStatus {\n if (budgetUsd === undefined || costUsd === null) return \"ok\";\n if (costUsd >= budgetUsd) return \"exceeded\";\n if (costUsd >= budgetUsd * BUDGET_WARN_RATIO) return \"warn\";\n return \"ok\";\n}\n","import type { TokenUsage } from \"../core/events\";\n\n// Session prompt-cache totals backing the StatusBar \"cache:\" field.\n// `promptTokens` is the cache-eligible prompt denominator: OpenAI-style\n// providers report cache hits as a subset of promptTokens, while Anthropic\n// reports cache reads on top of it, so those reads are added here as well.\nexport interface CacheTotals {\n cachedTokens: number;\n promptTokens: number;\n}\n\nexport function cacheUsageReported(usage: TokenUsage): boolean {\n return usage.cachedPromptTokens != null || usage.cacheReadInputTokens != null;\n}\n\nexport function addToCacheTotals(totals: CacheTotals, usage: TokenUsage): void {\n totals.cachedTokens += (usage.cachedPromptTokens ?? 0) + (usage.cacheReadInputTokens ?? 0);\n totals.promptTokens += usage.promptTokens + (usage.cacheReadInputTokens ?? 0);\n}\n\n// Hit rate 0-100, or null when no cache-eligible prompt tokens accumulated.\nexport function cacheHitPercent(totals: CacheTotals): number | null {\n if (totals.promptTokens <= 0) return null;\n const rate = totals.cachedTokens / totals.promptTokens;\n return Math.round(Math.min(1, Math.max(0, rate)) * 100);\n}\n","import { execFile } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { readFile, stat, unlink } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport type { ImageInput } from \"../core/messages\";\nimport { downsampleImageIfNeeded } from \"./image\";\n\nexport const CLIPBOARD_TIMEOUT_MS = 5000;\nexport const MAX_CLIPBOARD_IMAGE_BYTES = 10 * 1024 * 1024;\n\nconst execFileAsync = promisify(execFile);\n\nexport type ClipboardImagePlan =\n | { kind: \"temp-file\"; command: string; args: string[] }\n | { kind: \"stdout\"; command: string; args: string[] };\n\n// PowerShell saves the clipboard image to the temp PNG; with no image on the\n// clipboard it writes nothing and the missing file is the \"empty\" signal.\nexport function windowsClipboardImageScript(tempFile: string): string {\n const escaped = tempFile.replace(/'/g, \"''\");\n return [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n \"$img = [Windows.Forms.Clipboard]::GetImage()\",\n \"if ($null -ne $img) {\",\n ` $img.Save('${escaped}', [System.Drawing.Imaging.ImageFormat]::Png)`,\n \" $img.Dispose()\",\n \"}\",\n ].join(\"; \");\n}\n\n// osascript line set: `the clipboard as «class PNGf»` errors when the\n// clipboard holds no PNG, which surfaces as a non-zero exit.\nexport function macOsClipboardImageLines(tempFile: string): string[] {\n const posix = tempFile.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n return [\n \"set pngData to the clipboard as «class PNGf»\",\n `set theFile to open for access (POSIX file \"${posix}\") with write permission`,\n \"write pngData to theFile\",\n \"close access theFile\",\n ];\n}\n\nexport function clipboardImagePlan(\n platform: NodeJS.Platform,\n tempFile: string,\n hasPngpaste: boolean,\n): ClipboardImagePlan | null {\n if (platform === \"win32\") {\n return {\n kind: \"temp-file\",\n command: \"powershell.exe\",\n args: [\n \"-NoProfile\",\n \"-NonInteractive\",\n \"-STA\",\n \"-Command\",\n windowsClipboardImageScript(tempFile),\n ],\n };\n }\n if (platform === \"darwin\") {\n if (hasPngpaste) {\n return { kind: \"temp-file\", command: \"pngpaste\", args: [tempFile] };\n }\n return {\n kind: \"temp-file\",\n command: \"osascript\",\n args: macOsClipboardImageLines(tempFile).flatMap((line) => [\"-e\", line]),\n };\n }\n if (platform === \"linux\") {\n return {\n kind: \"stdout\",\n command: \"xclip\",\n args: [\"-selection\", \"clipboard\", \"-t\", \"image/png\", \"-o\"],\n };\n }\n return null;\n}\n\nexport function clipboardCopyCommand(\n platform: NodeJS.Platform,\n): { command: string; args: string[] } | null {\n if (platform === \"win32\") return { command: \"clip.exe\", args: [] };\n if (platform === \"darwin\") return { command: \"pbcopy\", args: [] };\n if (platform === \"linux\") return { command: \"xclip\", args: [\"-selection\", \"clipboard\"] };\n return null;\n}\n\nasync function commandExists(command: string): Promise<boolean> {\n const checker = process.platform === \"win32\" ? \"where\" : \"which\";\n try {\n await execFileAsync(checker, [command], { timeout: CLIPBOARD_TIMEOUT_MS });\n return true;\n } catch {\n return false;\n }\n}\n\nexport interface ClipboardImage {\n image: ImageInput;\n /** The source exceeded the model-friendly dimension cap but could not be\n * resized (no platform tool or resize failure) — the caller should warn. */\n oversized: boolean;\n}\n\nasync function finalizeClipboardImage(image: ImageInput): Promise<ClipboardImage> {\n const result = await downsampleImageIfNeeded(image);\n return { image: result.image, oversized: result.oversized && !result.resized };\n}\n\n// Reads the temp PNG the platform command wrote, refusing oversized files\n// before they load into memory (the xclip stdout branch is bounded by\n// maxBuffer instead). Null on a missing, empty or too-large file.\nexport async function readClipboardTempFile(tempFile: string): Promise<ImageInput | null> {\n const st = await stat(tempFile).catch(() => null);\n if (!st || st.size === 0 || st.size > MAX_CLIPBOARD_IMAGE_BYTES) return null;\n const buf = await readFile(tempFile).catch(() => null);\n if (!buf || buf.length === 0) return null;\n return { path: \"clipboard.png\", mimeType: \"image/png\", data: buf.toString(\"base64\") };\n}\n\n// Reads a PNG image from the system clipboard, downsampling anything larger\n// than MAX_IMAGE_DIMENSION on its longest side. Every read failure —\n// unsupported platform, missing tool, no image on the clipboard, timeout —\n// returns null.\nexport async function readClipboardImage(): Promise<ClipboardImage | null> {\n const tempFile = path.join(os.tmpdir(), `star-clipboard-${randomUUID()}.png`);\n const hasPngpaste = process.platform === \"darwin\" ? await commandExists(\"pngpaste\") : false;\n const plan = clipboardImagePlan(process.platform, tempFile, hasPngpaste);\n if (!plan) return null;\n try {\n if (plan.kind === \"stdout\") {\n const { stdout } = await execFileAsync(plan.command, plan.args, {\n timeout: CLIPBOARD_TIMEOUT_MS,\n maxBuffer: MAX_CLIPBOARD_IMAGE_BYTES,\n encoding: \"buffer\",\n });\n const buf = stdout as unknown as Buffer;\n if (buf.length === 0) return null;\n return finalizeClipboardImage({\n path: \"clipboard.png\",\n mimeType: \"image/png\",\n data: buf.toString(\"base64\"),\n });\n }\n await execFileAsync(plan.command, plan.args, { timeout: CLIPBOARD_TIMEOUT_MS });\n const image = await readClipboardTempFile(tempFile);\n if (!image) return null;\n return finalizeClipboardImage(image);\n } catch {\n return null;\n } finally {\n if (plan.kind === \"temp-file\") {\n await unlink(tempFile).catch(() => {});\n }\n }\n}\n\n// Copies text to the system clipboard; false on any failure.\nexport async function copyText(text: string): Promise<boolean> {\n const plan = clipboardCopyCommand(process.platform);\n if (!plan) return false;\n return new Promise((resolve) => {\n const child = execFile(plan.command, plan.args, { timeout: CLIPBOARD_TIMEOUT_MS }, (error) =>\n resolve(error === null),\n );\n child.stdin?.on(\"error\", () => {});\n child.stdin?.end(text);\n });\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { LanguageModel } from \"ai\";\nimport { AgentLoop } from \"../../agent/loop\";\nimport type { StarConfig } from \"../../config/schema\";\nimport { compactMessages, summarizeMessages } from \"../../context/compaction\";\nimport type { CompactionResult } from \"../../context/compaction\";\nimport { estimateTokens } from \"../../context/tokens\";\nimport type { CoreMessage } from \"../../core/messages\";\nimport type { SessionStore } from \"../../session/store\";\nimport type { ChatBackend } from \"../backend\";\n\nconst MIN_COMPACT_MESSAGES = 4;\n\nexport interface CompactSessionOptions {\n backend: ChatBackend;\n sessionStore: SessionStore | null;\n config: StarConfig;\n model: LanguageModel | null;\n}\n\nexport interface CompactSessionResult {\n message: string;\n compacted: boolean;\n messages?: CoreMessage[];\n}\n\nexport async function compactSession(opts: CompactSessionOptions): Promise<CompactSessionResult> {\n const { backend, sessionStore, config, model } = opts;\n if (!(backend instanceof AgentLoop)) {\n return { message: \"Current backend does not support compaction.\", compacted: false };\n }\n const messages = [...backend.getMessages()];\n if (messages.length < MIN_COMPACT_MESSAGES) {\n return {\n message: `Nothing to compact: history has only ${messages.length} message(s).`,\n compacted: false,\n };\n }\n const beforeTokens = estimateTokens(messages);\n // Manual compaction is explicit user intent: force it regardless of the\n // token budget instead of refusing while under contextMaxTokens.\n const compacted = compactMessages(messages, config.contextMaxTokens, { force: true });\n if (!compacted.compacted) {\n return {\n message: `Nothing to compact: history is too short to drop a whole turn (~${beforeTokens} estimated tokens).`,\n compacted: false,\n };\n }\n const next = await applyCompactionSummary(messages, compacted, config, model);\n await backend.loadMessages(next);\n await sessionStore?.replaceMessages(next);\n const afterTokens = estimateTokens(next);\n return {\n message: `Compacted context: ${messages.length} -> ${next.length} messages (~${beforeTokens} -> ~${afterTokens} estimated tokens).`,\n compacted: true,\n messages: next,\n };\n}\n\nasync function applyCompactionSummary(\n original: CoreMessage[],\n compacted: CompactionResult,\n config: StarConfig,\n model: LanguageModel | null,\n): Promise<CoreMessage[]> {\n if (config.contextCompaction !== \"summary\" || !model) {\n return compacted.messages;\n }\n const headCount = compacted.messages[0]?.role === \"system\" ? 1 : 0;\n const dropped = original.slice(headCount, headCount + compacted.droppedCount);\n try {\n const summary = await summarizeMessages(dropped, model);\n const messages = compacted.messages.slice();\n messages[headCount] = {\n role: \"user\",\n content: `[earlier conversation summarized]\\n${summary}`,\n };\n return messages;\n } catch {\n return compacted.messages;\n }\n}\n\nexport interface ExportSessionOptions {\n backend: ChatBackend;\n sessionStore: SessionStore | null;\n cwd: string;\n arg: string;\n}\n\nexport async function exportSession(opts: ExportSessionOptions): Promise<string> {\n const { backend, sessionStore, cwd, arg } = opts;\n if (!(backend instanceof AgentLoop)) {\n return \"Current backend does not support exporting sessions.\";\n }\n const messages = [...backend.getMessages()];\n if (messages.length === 0) {\n return \"Nothing to export: the session has no messages.\";\n }\n const sessionId = sessionStore?.id ?? `unknown-${Date.now()}`;\n const target = arg ? path.resolve(cwd, arg) : path.resolve(cwd, `star-session-${sessionId}.md`);\n const existed = await fileExists(target);\n await fs.mkdir(path.dirname(target), { recursive: true });\n await fs.writeFile(target, renderSessionMarkdown(sessionId, messages));\n return existed\n ? `Exported ${messages.length} messages to ${target} (overwrote existing file).`\n : `Exported ${messages.length} messages to ${target}.`;\n}\n\nasync function fileExists(target: string): Promise<boolean> {\n try {\n await fs.access(target);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function renderSessionMarkdown(\n sessionId: string,\n messages: readonly CoreMessage[],\n exportedAt: Date = new Date(),\n): string {\n const lines: string[] = [\n `# Star CLI Session ${sessionId}`,\n \"\",\n `_Exported at ${exportedAt.toISOString()}_`,\n \"\",\n ];\n for (const message of messages) {\n lines.push(`## ${roleHeading(message.role)}`, \"\");\n lines.push(...renderContent(message), \"\");\n }\n return lines.join(\"\\n\");\n}\n\nfunction roleHeading(role: string): string {\n return role.charAt(0).toUpperCase() + role.slice(1);\n}\n\nfunction renderContent(message: CoreMessage): string[] {\n const content = message.content;\n if (typeof content === \"string\") return [content];\n const lines: string[] = [];\n for (const part of content) {\n if (part.type === \"text\") {\n lines.push(part.text, \"\");\n } else if (part.type === \"tool-call\") {\n lines.push(\n `**Tool call: ${part.toolName}**`,\n \"\",\n \"```json\",\n JSON.stringify(part.args, null, 2),\n \"```\",\n \"\",\n );\n } else if (part.type === \"tool-result\") {\n lines.push(\n `**Tool result: ${part.toolName}**`,\n \"\",\n \"```\",\n stringifyPart(part.result),\n \"```\",\n \"\",\n );\n } else if (part.type === \"reasoning\") {\n lines.push(part.text, \"\");\n } else {\n lines.push(`[${part.type}]`, \"\");\n }\n }\n while (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\n return lines;\n}\n\nfunction stringifyPart(value: unknown): string {\n return typeof value === \"string\" ? value : JSON.stringify(value, null, 2);\n}\n","import { readFileSync } from \"node:fs\";\nimport { discoverSkills } from \"../../agent/skills\";\nimport { appendUserMemory } from \"../../agent/user-memory\";\nimport { userMemoryPath } from \"../../config/paths\";\nimport {\n WORKING_DIFF_MAX_LINES,\n buildCommitPrompt,\n collectCommitContext,\n collectWorkingDiff,\n isGitRepo,\n} from \"../../core/git\";\nimport { formatSearchResults, searchSessions } from \"../../session/search\";\nimport { parseGitDiffLines } from \"../diff-preview\";\nimport type { CommandRegistry, SlashCommand } from \"./registry\";\n\nexport function registerBuiltinCommands(registry: CommandRegistry): void {\n const register = (command: SlashCommand) => registry.register(command);\n\n register({\n name: \"help\",\n description: \"List available commands\",\n usage: \"/help\",\n category: \"General\",\n run(_args, ctx) {\n const groups = new Map<string, string[]>();\n for (const cmd of registry.list()) {\n const category = cmd.category ?? \"Other\";\n const usage = cmd.usage ?? `/${cmd.name}`;\n const lines = groups.get(category) ?? [];\n lines.push(` ${usage} - ${cmd.description}`);\n groups.set(category, lines);\n }\n const sections = [...groups.entries()].map(([name, lines]) => [name, ...lines].join(\"\\n\"));\n ctx.addSystemMessage(`Available commands:\\n\\n${sections.join(\"\\n\\n\")}`);\n },\n });\n\n register({\n name: \"clear\",\n description: \"Clear message history\",\n usage: \"/clear\",\n category: \"General\",\n run(_args, ctx) {\n ctx.clearMessages();\n },\n });\n\n register({\n name: \"new\",\n description: \"Start a new session with a clean context\",\n usage: \"/new\",\n category: \"Sessions\",\n async run(_args, ctx) {\n if (!ctx.newSession) {\n ctx.addSystemMessage(\"/new: this context cannot start a new session.\");\n return;\n }\n ctx.addSystemMessage(await ctx.newSession());\n },\n });\n\n register({\n name: \"clear-sessions\",\n description:\n \"Delete stored sessions: this directory by default, every session with --all (the current session is kept)\",\n usage: \"/clear-sessions [--all]\",\n category: \"Sessions\",\n async run(args, ctx) {\n const arg = args.trim();\n if (arg !== \"\" && arg !== \"--all\") {\n ctx.addSystemMessage(\n `/clear-sessions: unknown argument \"${arg}\". Usage: /clear-sessions [--all]`,\n );\n return;\n }\n if (!ctx.clearSessions) {\n ctx.addSystemMessage(\"/clear-sessions: this context cannot delete sessions.\");\n return;\n }\n ctx.addSystemMessage(await ctx.clearSessions(arg === \"--all\"));\n },\n });\n\n register({\n name: \"exit\",\n description: \"Exit the application\",\n usage: \"/exit\",\n category: \"General\",\n run(_args, ctx) {\n ctx.exit();\n },\n });\n\n register({\n name: \"q\",\n description: \"Exit the application (alias of /exit)\",\n usage: \"/q\",\n category: \"General\",\n run(_args, ctx) {\n ctx.exit();\n },\n });\n\n register({\n name: \"model\",\n description: \"Switch the current model (opens a picker when no name is given)\",\n usage: \"/model [name]\",\n category: \"Settings\",\n async run(args, ctx) {\n if (!args) {\n ctx.addSystemMessage(await ctx.pickModel());\n } else {\n ctx.addSystemMessage(await ctx.switchModel(args));\n }\n },\n });\n\n register({\n name: \"resume\",\n description: \"Resume a session by id, or pick one from a list (--all for every directory)\",\n usage: \"/resume [sessionId | --all]\",\n category: \"Sessions\",\n async run(args, ctx) {\n const arg = args.trim();\n if (arg === \"--all\") {\n ctx.addSystemMessage(await ctx.pickSession(true));\n } else if (!arg) {\n ctx.addSystemMessage(await ctx.pickSession(false));\n } else {\n ctx.addSystemMessage(await ctx.resumeSession(arg));\n }\n },\n });\n\n register({\n name: \"fork\",\n description: \"Fork the current session into a new one and switch to it\",\n usage: \"/fork\",\n category: \"Sessions\",\n async run(_args, ctx) {\n ctx.addSystemMessage(await ctx.forkSession());\n },\n });\n\n register({\n name: \"search\",\n description: \"Full-text search across all stored sessions\",\n usage: \"/search <query>\",\n category: \"Sessions\",\n async run(args, ctx) {\n const query = args.trim();\n if (!query) {\n ctx.addSystemMessage(\"Usage: /search <query>\");\n return;\n }\n ctx.addSystemMessage(formatSearchResults(await searchSessions(query), query));\n },\n });\n\n register({\n name: \"todo\",\n description: \"Show the current todo list\",\n usage: \"/todo\",\n category: \"Info\",\n async run(_args, ctx) {\n ctx.addSystemMessage(await ctx.showTodos());\n },\n });\n\n register({\n name: \"tasks\",\n description: \"List background shell tasks\",\n usage: \"/tasks\",\n category: \"Info\",\n run(_args, ctx) {\n ctx.addSystemMessage(ctx.listTasks());\n },\n });\n\n register({\n name: \"cost\",\n description: \"Show API token usage for this session\",\n usage: \"/cost\",\n category: \"Info\",\n run(_args, ctx) {\n ctx.addSystemMessage(ctx.showUsage());\n },\n });\n\n register({\n name: \"usage\",\n description: \"Show token usage aggregated across all sessions\",\n usage: \"/usage\",\n category: \"Info\",\n async run(_args, ctx) {\n ctx.addSystemMessage(await ctx.showGlobalUsage());\n },\n });\n\n register({\n name: \"config\",\n description: \"Show the current configuration\",\n usage: \"/config\",\n category: \"Info\",\n run(_args, ctx) {\n ctx.addSystemMessage(ctx.describeConfig());\n },\n });\n\n register({\n name: \"compact\",\n description: \"Compact the conversation history to free up context\",\n usage: \"/compact\",\n category: \"Sessions\",\n async run(_args, ctx) {\n ctx.addSystemMessage(await ctx.compactContext());\n },\n });\n\n register({\n name: \"export\",\n description: \"Export the current session to a Markdown file\",\n usage: \"/export [path]\",\n category: \"Sessions\",\n async run(args, ctx) {\n ctx.addSystemMessage(await ctx.exportSession(args));\n },\n });\n\n register({\n name: \"permission\",\n description: \"Set the permission mode (opens a picker when no mode is given)\",\n usage: \"/permission [ask|auto|readonly|yolo]\",\n category: \"Settings\",\n async run(args, ctx) {\n const arg = args.trim();\n if (!arg) {\n ctx.addSystemMessage(await ctx.pickPermissionMode());\n } else {\n ctx.addSystemMessage(await ctx.permissionMode(arg));\n }\n },\n });\n\n register({\n name: \"plan\",\n description: \"Toggle plan mode: read-only research, then approve the plan before executing\",\n usage: \"/plan\",\n category: \"Settings\",\n async run(_args, ctx) {\n ctx.addSystemMessage(await ctx.planMode());\n },\n });\n\n register({\n name: \"memory\",\n description: \"Show user memory (MEMORY.md), or add an entry\",\n usage: \"/memory [add <text>]\",\n category: \"Settings\",\n run(args, ctx) {\n const arg = args.trim();\n if (arg === \"add\" || arg.startsWith(\"add \")) {\n const text = arg.slice(3).trim();\n if (!text) {\n ctx.addSystemMessage(\"Usage: /memory add <text>\");\n return;\n }\n appendUserMemory(text);\n ctx.addSystemMessage(`Saved to user memory: - ${text}`);\n return;\n }\n if (arg) {\n ctx.addSystemMessage(`Unknown argument \"${arg}\". Usage: /memory [add <text>]`);\n return;\n }\n const file = userMemoryPath();\n let content = \"\";\n try {\n content = readFileSync(file, \"utf8\").trim();\n } catch {\n content = \"\";\n }\n if (!content) {\n ctx.addSystemMessage(\n `No user memory yet (${file}).\\nAdd entries with /memory add <text> or ask the agent to remember something.`,\n );\n return;\n }\n ctx.addSystemMessage(`User memory (${file}):\\n${content}`);\n },\n });\n\n register({\n name: \"undo\",\n description:\n \"Undo the last conversation turn: revert its file changes (any tool, bash included, when git snapshots are on) and retract its messages\",\n usage: \"/undo\",\n category: \"Changes\",\n async run(_args, ctx) {\n ctx.addSystemMessage(await ctx.undo());\n },\n });\n\n register({\n name: \"redo\",\n description: \"Redo the last git-snapshot undo: restore the working tree to its pre-undo state\",\n usage: \"/redo\",\n category: \"Changes\",\n async run(_args, ctx) {\n ctx.addSystemMessage(await ctx.redo());\n },\n });\n\n register({\n name: \"rewind\",\n description:\n \"List file-change checkpoints, or rewind to just before one: restore files and retract the conversation\",\n usage: \"/rewind [n]\",\n category: \"Changes\",\n async run(args, ctx) {\n ctx.addSystemMessage(await ctx.rewind(args.trim()));\n },\n });\n\n register({\n name: \"connect\",\n description:\n \"Interactive wizard: add an LLM provider + model, store the key safely, and save to config\",\n usage: \"/connect\",\n category: \"Settings\",\n async run(_args, ctx) {\n if (!ctx.connect) {\n ctx.addSystemMessage(\"/connect: this context cannot run the interactive wizard.\");\n return;\n }\n ctx.addSystemMessage(await ctx.connect());\n },\n });\n\n register({\n name: \"init\",\n description: \"Generate an AGENTS.md for the current project\",\n usage: \"/init [force]\",\n category: \"Settings\",\n async run(args, ctx) {\n ctx.addSystemMessage(await ctx.initProject(args));\n },\n });\n\n register({\n name: \"doctor\",\n description: \"Run environment and configuration checks\",\n usage: \"/doctor\",\n category: \"Info\",\n async run(_args, ctx) {\n ctx.addSystemMessage(await ctx.runDoctor());\n },\n });\n\n register({\n name: \"skills\",\n description: \"List available skills (project scope overrides user scope)\",\n usage: \"/skills\",\n category: \"Info\",\n run(_args, ctx) {\n const skills = discoverSkills(ctx.cwd ?? process.cwd());\n if (skills.length === 0) {\n ctx.addSystemMessage(\n \"No skills found. Add a SKILL.md under .star/skills/<name>/ (project) or ~/.star-cli/skills/<name>/ (user).\",\n );\n return;\n }\n const lines = skills.map((s) => `${s.name} [${s.scope}] — ${s.description}`);\n ctx.addSystemMessage(`Available skills:\\n${lines.join(\"\\n\")}`);\n },\n });\n\n register({\n name: \"commit\",\n description: \"Analyze uncommitted changes and create a git commit (Conventional Commits)\",\n usage: \"/commit [instructions]\",\n category: \"Changes\",\n async run(args, ctx) {\n const cwd = ctx.cwd ?? process.cwd();\n if (!isGitRepo(cwd)) {\n ctx.addSystemMessage(\"/commit: not a git repository — nothing to do.\");\n return;\n }\n const context = collectCommitContext(cwd);\n if (!context) {\n ctx.addSystemMessage(\"/commit: working tree clean — nothing to commit.\");\n return;\n }\n const prompt = buildCommitPrompt(context, args);\n if (ctx.submitPrompt) {\n return ctx.submitPrompt(prompt);\n }\n ctx.addSystemMessage(\"/commit: this context cannot submit prompts to the model.\");\n },\n });\n\n register({\n name: \"copy\",\n description:\n \"Copy the last assistant reply to the clipboard (`all` for the whole conversation)\",\n usage: \"/copy [all]\",\n category: \"Sessions\",\n async run(args, ctx) {\n const arg = args.trim();\n if (arg !== \"\" && arg !== \"all\") {\n ctx.addSystemMessage(`/copy: unknown argument \"${arg}\". Usage: /copy [all]`);\n return;\n }\n if (!ctx.conversationText || !ctx.copyToClipboard) {\n ctx.addSystemMessage(\"/copy: this context cannot access the clipboard.\");\n return;\n }\n const scope = arg === \"all\" ? \"all\" : \"last\";\n const text = ctx.conversationText(scope);\n if (!text) {\n ctx.addSystemMessage(\n scope === \"all\" ? \"Nothing to copy yet.\" : \"No assistant reply yet — nothing to copy.\",\n );\n return;\n }\n const ok = await ctx.copyToClipboard(text);\n ctx.addSystemMessage(\n ok\n ? `Copied ${text.length} chars to clipboard.`\n : \"Copy failed — no clipboard command available on this platform.\",\n );\n },\n });\n\n register({\n name: \"diff\",\n description: \"Show uncommitted changes (git status + colored diff)\",\n usage: \"/diff\",\n category: \"Changes\",\n run(_args, ctx) {\n const cwd = ctx.cwd ?? process.cwd();\n if (!isGitRepo(cwd)) {\n ctx.addSystemMessage(\"/diff: not a git repository — nothing to show.\");\n return;\n }\n const result = collectWorkingDiff(cwd);\n if (!result || result.status === \"\") {\n ctx.addSystemMessage(\"Working tree clean — no uncommitted changes.\");\n return;\n }\n const header = `git status --short:\\n${result.status}`;\n if (result.diff === \"\") {\n ctx.addSystemMessage(\n `${header}\\n\\nOnly untracked files — no tracked modifications to diff.`,\n );\n return;\n }\n const note = result.truncated\n ? `diff truncated at ${WORKING_DIFF_MAX_LINES} lines`\n : undefined;\n if (ctx.showDiff) {\n ctx.showDiff(header, parseGitDiffLines(result.diff), note);\n return;\n }\n ctx.addSystemMessage(`${header}\\n\\n${result.diff}${note ? `\\n... (${note})` : \"\"}`);\n },\n });\n}\n","import type { CoreMessage } from \"../core/messages\";\nimport { relativeTime, shortSessionId } from \"./list\";\nimport { type SessionMeta, SessionStore } from \"./store\";\n\nexport interface SessionSearchHit {\n meta: SessionMeta;\n snippet: string;\n}\n\nconst SNIPPET_LENGTH = 100;\n\nfunction flattenMessage(message: CoreMessage): string {\n const content = message.content;\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n const parts: string[] = [];\n for (const part of content) {\n if (part.type === \"text\") {\n parts.push(part.text);\n } else if (part.type === \"tool-call\") {\n parts.push(JSON.stringify(part.args));\n } else if (part.type === \"tool-result\") {\n parts.push(typeof part.result === \"string\" ? part.result : JSON.stringify(part.result));\n }\n }\n return parts.join(\"\\n\");\n}\n\n// ~100 chars of the (whitespace-collapsed) haystack centered on the first\n// case-insensitive match, with … markers where text was cut off.\nfunction makeSnippet(text: string, query: string): string {\n const flat = text.replace(/\\s+/g, \" \").trim();\n const index = flat.toLowerCase().indexOf(query.toLowerCase());\n if (index === -1 || flat.length <= SNIPPET_LENGTH) return flat.slice(0, SNIPPET_LENGTH);\n const side = Math.max(0, Math.floor((SNIPPET_LENGTH - query.length) / 2));\n let start = Math.max(0, index - side);\n const end = Math.min(flat.length, start + SNIPPET_LENGTH);\n start = Math.max(0, end - SNIPPET_LENGTH);\n return `${start > 0 ? \"…\" : \"\"}${flat.slice(start, end)}${end < flat.length ? \"…\" : \"\"}`;\n}\n\n// Full-text search across every stored session, most recently updated first.\n// Unreadable sessions and corrupt jsonl lines are skipped silently.\nexport async function searchSessions(query: string, limit = 10): Promise<SessionSearchHit[]> {\n const hits: SessionSearchHit[] = [];\n const needle = query.toLowerCase();\n for (const meta of await SessionStore.list()) {\n if (hits.length >= limit) break;\n const store = await SessionStore.open(meta.id);\n if (!store) continue;\n const text = (await store.messages())\n .map(flattenMessage)\n .filter((part) => part.length > 0)\n .join(\"\\n\");\n if (text.toLowerCase().includes(needle)) {\n hits.push({ meta, snippet: makeSnippet(text, query) });\n }\n }\n return hits;\n}\n\nexport function formatSearchResults(hits: SessionSearchHit[], query: string): string {\n if (hits.length === 0) return `No sessions matching \"${query}\".`;\n const lines = hits.map(({ meta, snippet }) => {\n const title = meta.title || \"(untitled)\";\n return `${shortSessionId(meta.id)} ${title} (${relativeTime(meta.updatedAt)})\\n ${snippet}`;\n });\n return [...lines, \"Resume with /resume <id>\"].join(\"\\n\");\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport type DiffLineKind = \"add\" | \"del\" | \"context\" | \"marker\";\n\nexport interface DiffLine {\n kind: DiffLineKind;\n text: string;\n}\n\nexport interface DiffPreview {\n type: \"diff\" | \"new-file\";\n label: string;\n lines: DiffLine[];\n}\n\nconst CONTEXT_LINES = 2;\nconst MAX_HUNK_LINES = 15;\nconst MAX_TOTAL_LINES = 12;\nconst NEW_FILE_PREVIEW_LINES = 10;\nconst MAX_DP_CELLS = 250_000;\n\ninterface Op {\n kind: Exclude<DiffLineKind, \"marker\">;\n text: string;\n}\n\nfunction diffOps(oldText: string, newText: string): Op[] {\n const a = oldText.split(\"\\n\");\n const b = newText.split(\"\\n\");\n let start = 0;\n while (start < a.length && start < b.length && a[start] === b[start]) start += 1;\n let endA = a.length;\n let endB = b.length;\n while (endA > start && endB > start && a[endA - 1] === b[endB - 1]) {\n endA -= 1;\n endB -= 1;\n }\n const prefix: Op[] = a.slice(0, start).map((text) => ({ kind: \"context\" as const, text }));\n const suffix: Op[] = a.slice(endA).map((text) => ({ kind: \"context\" as const, text }));\n const midA = a.slice(start, endA);\n const midB = b.slice(start, endB);\n const prefixLen = prefix.length;\n const ops: Op[] = [...prefix];\n if (midA.length * midB.length > MAX_DP_CELLS) {\n for (const text of midA) ops.push({ kind: \"del\", text });\n for (const text of midB) ops.push({ kind: \"add\", text });\n } else if (midA.length > 0 || midB.length > 0) {\n const rows = midA.length + 1;\n const cols = midB.length + 1;\n const dp = new Uint32Array(rows * cols);\n const cell = (r: number, c: number): number => dp[r * cols + c] ?? 0;\n for (let i = 1; i < rows; i++) {\n for (let j = 1; j < cols; j++) {\n dp[i * cols + j] =\n midA[i - 1] === midB[j - 1]\n ? cell(i - 1, j - 1) + 1\n : Math.max(cell(i - 1, j), cell(i, j - 1));\n }\n }\n const lineAt = (lines: string[], index: number): string => lines[index] ?? \"\";\n const middle: Op[] = [];\n let i = midA.length;\n let j = midB.length;\n while (i > 0 && j > 0) {\n if (midA[i - 1] === midB[j - 1]) {\n middle.push({ kind: \"context\", text: lineAt(midA, i - 1) });\n i -= 1;\n j -= 1;\n } else if (cell(i, j - 1) >= cell(i - 1, j)) {\n middle.push({ kind: \"add\", text: lineAt(midB, j - 1) });\n j -= 1;\n } else {\n middle.push({ kind: \"del\", text: lineAt(midA, i - 1) });\n i -= 1;\n }\n }\n while (i > 0) {\n middle.push({ kind: \"del\", text: lineAt(midA, i - 1) });\n i -= 1;\n }\n while (j > 0) {\n middle.push({ kind: \"add\", text: lineAt(midB, j - 1) });\n j -= 1;\n }\n middle.reverse();\n ops.push(...middle);\n }\n ops.push(...suffix);\n return ops.length === prefixLen + suffix.length ? [] : ops;\n}\n\nfunction hunkRanges(ops: Op[]): Array<[number, number]> {\n const changes: number[] = [];\n for (let i = 0; i < ops.length; i++) {\n const op = ops[i];\n if (op && op.kind !== \"context\") changes.push(i);\n }\n const ranges: Array<[number, number]> = [];\n let groupStart = 0;\n for (let k = 1; k <= changes.length; k++) {\n const cur = changes[k];\n const prev = changes[k - 1];\n const first = changes[groupStart];\n if (prev === undefined || first === undefined) break;\n if (cur === undefined || cur - prev > CONTEXT_LINES * 2 + 1) {\n ranges.push([\n Math.max(0, first - CONTEXT_LINES),\n Math.min(ops.length, prev + CONTEXT_LINES + 1),\n ]);\n groupStart = k;\n }\n }\n return ranges;\n}\n\nexport function buildDiffLines(oldText: string, newText: string): DiffLine[] {\n const ops = diffOps(oldText, newText);\n if (ops.length === 0) return [];\n const ranges = hunkRanges(ops);\n const lines: DiffLine[] = [];\n let omitted = 0;\n for (const [rangeIndex, [start, end]] of ranges.entries()) {\n if (rangeIndex > 0) lines.push({ kind: \"marker\", text: \"···\" });\n const hunk = ops.slice(start, end);\n let shown = hunk;\n if (hunk.length > MAX_HUNK_LINES) {\n const headCount = Math.ceil(MAX_HUNK_LINES / 2);\n shown = [...hunk.slice(0, headCount), ...hunk.slice(headCount - MAX_HUNK_LINES)];\n }\n if (hunk.length > shown.length) {\n omitted += hunk.length - shown.length;\n }\n for (const op of shown) lines.push(op);\n }\n if (lines.length > MAX_TOTAL_LINES) {\n omitted += lines.length - MAX_TOTAL_LINES;\n lines.length = MAX_TOTAL_LINES;\n }\n if (omitted > 0) lines.push({ kind: \"marker\", text: `... (${omitted} more lines)` });\n return lines;\n}\n\n// Maps raw `git diff` output onto the same line kinds used by the write/edit\n// preview so both render with the same colors. The leading +/- sigil is\n// stripped because the renderer re-adds it; a leading space on context lines\n// is stripped for the same reason.\nexport function parseGitDiffLines(diffText: string): DiffLine[] {\n return diffText.split(\"\\n\").map((raw) => {\n if (raw.startsWith(\"+\") && !raw.startsWith(\"+++\")) {\n return { kind: \"add\", text: raw.slice(1) };\n }\n if (raw.startsWith(\"-\") && !raw.startsWith(\"---\")) {\n return { kind: \"del\", text: raw.slice(1) };\n }\n if (\n raw.startsWith(\"@@\") ||\n raw.startsWith(\"diff \") ||\n raw.startsWith(\"index \") ||\n raw.startsWith(\"#\") ||\n raw.startsWith(\"+++\") ||\n raw.startsWith(\"---\")\n ) {\n return { kind: \"marker\", text: raw };\n }\n return { kind: \"context\", text: raw.startsWith(\" \") ? raw.slice(1) : raw };\n });\n}\n\nfunction getStringArg(args: unknown, key: string): string | undefined {\n if (typeof args === \"object\" && args !== null) {\n const value = (args as Record<string, unknown>)[key];\n if (typeof value === \"string\") return value;\n }\n return undefined;\n}\n\nfunction applyEdit(\n content: string,\n oldString: string,\n newString: string,\n replaceAll: boolean,\n): string | null {\n let count = 0;\n let idx = content.indexOf(oldString);\n while (idx !== -1) {\n count += 1;\n idx = content.indexOf(oldString, idx + oldString.length);\n }\n if (count === 0) return null;\n if (count > 1 && !replaceAll) return null;\n return replaceAll\n ? content.split(oldString).join(newString)\n : content.replace(oldString, () => newString);\n}\n\nfunction newFilePreview(content: string, label: string): DiffPreview {\n const all = content.split(\"\\n\");\n const shown = all.slice(0, NEW_FILE_PREVIEW_LINES);\n const lines: DiffLine[] = shown.map((text) => ({ kind: \"add\", text }));\n if (all.length > shown.length) {\n lines.push({ kind: \"marker\", text: `... (${all.length - shown.length} more lines)` });\n }\n return { type: \"new-file\", label, lines };\n}\n\nexport async function generateDiffPreview(\n toolName: string,\n args: unknown,\n cwd: string,\n): Promise<DiffPreview | null> {\n if (toolName !== \"edit_file\" && toolName !== \"write_file\") return null;\n const filePath = getStringArg(args, \"path\");\n if (filePath === undefined) return null;\n const absolute = path.resolve(cwd, filePath);\n let existing: string | null;\n try {\n existing = await readFile(absolute, \"utf8\");\n } catch {\n existing = null;\n }\n if (toolName === \"edit_file\") {\n const oldString = getStringArg(args, \"old_string\");\n const newString = getStringArg(args, \"new_string\");\n if (existing === null || oldString === undefined || newString === undefined) return null;\n const replaceAll =\n typeof args === \"object\" &&\n args !== null &&\n (args as Record<string, unknown>).replace_all === true;\n const updated = applyEdit(existing, oldString, newString, replaceAll);\n if (updated === null) return null;\n return { type: \"diff\", label: filePath, lines: buildDiffLines(existing, updated) };\n }\n const content = getStringArg(args, \"content\");\n if (content === undefined) return null;\n if (existing === null) return newFilePreview(content, filePath);\n return { type: \"diff\", label: filePath, lines: buildDiffLines(existing, content) };\n}\n","import { spawn } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { upsertEnvContent } from \"../../config/env\";\nimport { envFilePath, globalConfigPath } from \"../../config/paths\";\nimport type { ModelConfig, ProviderConfig } from \"../../config/schema\";\n\nexport type Protocol = ProviderConfig[\"protocol\"];\n\nexport interface ProviderPreset {\n key: string;\n label: string;\n baseURL: string;\n protocol: Protocol;\n // example model id shown as the placeholder of the model prompt\n modelHint: string;\n}\n\nexport const PROVIDER_PRESETS: ProviderPreset[] = [\n {\n key: \"openai\",\n label: \"OpenAI\",\n baseURL: \"https://api.openai.com/v1\",\n protocol: \"openai-compatible\",\n modelHint: \"gpt-4o\",\n },\n {\n key: \"anthropic\",\n label: \"Anthropic\",\n baseURL: \"https://api.anthropic.com\",\n protocol: \"anthropic\",\n modelHint: \"claude-sonnet-4-5\",\n },\n {\n key: \"moonshot\",\n label: \"Kimi (Moonshot)\",\n baseURL: \"https://api.moonshot.cn/v1\",\n protocol: \"openai-compatible\",\n modelHint: \"kimi-k2-0905-preview\",\n },\n {\n key: \"deepseek\",\n label: \"DeepSeek\",\n baseURL: \"https://api.deepseek.com/v1\",\n protocol: \"openai-compatible\",\n modelHint: \"deepseek-chat\",\n },\n];\n\nexport const PROTOCOLS: Protocol[] = [\"openai-compatible\", \"anthropic\", \"openai-responses\"];\n\nexport const PROTOCOL_DESCRIPTIONS: Record<Protocol, string> = {\n \"openai-compatible\": \"POST /chat/completions — most providers\",\n anthropic: \"Anthropic Messages API\",\n \"openai-responses\": \"OpenAI Responses API (endpoints exposing only /responses)\",\n};\n\n// Context window written into new [[models]] blocks; edit after saving when\n// the real limit differs.\nexport const CONNECT_DEFAULT_CONTEXT_TOKENS = 128_000;\n\nexport interface ConnectAnswers {\n providerName: string;\n protocol: Protocol;\n baseURL: string;\n apiKeyEnv: string;\n apiKey: string;\n modelName: string;\n modelId: string;\n}\n\n// Derives a config name from the baseURL host: \"https://openrouter.ai/api/v1\"\n// → \"openrouter\", \"https://api.openai.com/v1\" → \"openai\". Falls back to\n// \"provider\" when nothing usable can be extracted.\nexport function deriveProviderName(baseURL: string): string {\n let host = baseURL;\n try {\n host = new URL(baseURL).hostname;\n } catch {\n host = baseURL.replace(/^[a-z]+:\\/\\//i, \"\").split(/[/:?#]/)[0] ?? baseURL;\n }\n const labels = host.toLowerCase().split(\".\");\n const skip = new Set([\"www\", \"api\"]);\n const meaningful = labels.filter((label) => label !== \"\" && !skip.has(label));\n const raw = meaningful[0] ?? \"provider\";\n const slug = raw\n .replace(/[^a-z0-9-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return slug || \"provider\";\n}\n\nexport function dedupeName(base: string, taken: string[]): string {\n const names = new Set(taken);\n if (!names.has(base)) return base;\n for (let i = 2; ; i++) {\n const candidate = `${base}-${i}`;\n if (!names.has(candidate)) return candidate;\n }\n}\n\nexport function apiKeyEnvFor(providerName: string): string {\n return `STAR_API_KEY_${providerName.toUpperCase().replace(/[^A-Z0-9]/g, \"_\")}`;\n}\n\n// Masks a key for display: long keys show a short prefix and suffix, short\n// ones are hidden completely. The full key must never appear in the UI.\nexport function maskApiKey(key: string): string {\n if (key.length <= 8) return \"••••••\";\n return `${key.slice(0, 3)}…${key.slice(-4)}`;\n}\n\n// TOML basic strings share JSON string escaping.\nfunction tomlString(value: string): string {\n return JSON.stringify(value);\n}\n\nexport function buildProviderTomlBlock(provider: ProviderConfig): string {\n return [\n \"[[providers]]\",\n `name = ${tomlString(provider.name)}`,\n \"# wire format: openai-compatible | anthropic | openai-responses\",\n `protocol = ${tomlString(provider.protocol)}`,\n `baseURL = ${tomlString(provider.baseURL)}`,\n \"# environment variable holding the API key; the key itself lives in\",\n \"# ~/.star-cli/.env (written by /connect), never in this file\",\n `apiKeyEnv = ${tomlString(provider.apiKeyEnv ?? \"\")}`,\n \"# inline key instead of apiKeyEnv (not recommended):\",\n '# apiKey = \"sk-...\"',\n \"# extra HTTP headers sent to the provider:\",\n '# headers = { \"X-Title\" = \"star-cli\" }',\n \"\",\n \"\",\n ].join(\"\\n\");\n}\n\nexport function buildModelTomlBlock(model: ModelConfig): string {\n return [\n \"[[models]]\",\n `name = ${tomlString(model.name)}`,\n `provider = ${tomlString(model.provider)}`,\n `model = ${tomlString(model.model)}`,\n \"# per-model context window in tokens — overrides the top-level\",\n \"# contextMaxTokens for compaction and the ctx % in the status bar\",\n `contextMaxTokens = ${model.contextMaxTokens ?? CONNECT_DEFAULT_CONTEXT_TOKENS}`,\n \"# pricing in USD per 1M tokens — set your provider's rates; BOTH\",\n \"# promptPrice and completionPrice are required together for the $\",\n \"# estimates in /cost and /usage (0 prices a token at $0)\",\n `promptPrice = ${model.promptPrice ?? 0}`,\n `completionPrice = ${model.completionPrice ?? 0}`,\n \"# cap on generated tokens per reply:\",\n \"# maxTokens = 8192\",\n \"\",\n \"\",\n ].join(\"\\n\");\n}\n\nexport interface ConnectResult {\n provider: ProviderConfig;\n model: ModelConfig;\n configPath: string;\n envPath: string;\n}\n\n// Persists a /connect result: the key goes into ~/.star-cli/.env (updated in\n// place when the variable already exists, chmod 600 where the platform\n// honors it) and is exported into this process so the model works without a\n// restart; the [[providers]]/[[models]] blocks are appended to config.toml as\n// text so existing content and comments survive.\nexport function saveConnection(\n answers: ConnectAnswers,\n configPath: string = globalConfigPath(),\n envPath: string = envFilePath(),\n): ConnectResult {\n const provider: ProviderConfig = {\n name: answers.providerName,\n protocol: answers.protocol,\n baseURL: answers.baseURL,\n apiKeyEnv: answers.apiKeyEnv,\n };\n const model: ModelConfig = {\n name: answers.modelName,\n provider: answers.providerName,\n model: answers.modelId,\n contextMaxTokens: CONNECT_DEFAULT_CONTEXT_TOKENS,\n promptPrice: 0,\n completionPrice: 0,\n };\n\n fs.mkdirSync(path.dirname(envPath), { recursive: true });\n let envContent = \"\";\n try {\n envContent = fs.readFileSync(envPath, \"utf8\");\n } catch {\n envContent = \"\";\n }\n fs.writeFileSync(\n envPath,\n upsertEnvContent(envContent, provider.apiKeyEnv ?? \"\", answers.apiKey),\n {\n encoding: \"utf8\",\n mode: 0o600,\n },\n );\n try {\n fs.chmodSync(envPath, 0o600);\n } catch {\n // chmod is a no-op on Windows; best effort only.\n }\n if (provider.apiKeyEnv) {\n process.env[provider.apiKeyEnv] = answers.apiKey;\n }\n\n fs.mkdirSync(path.dirname(configPath), { recursive: true });\n let existing = \"\";\n try {\n existing = fs.readFileSync(configPath, \"utf8\");\n } catch {\n existing = \"\";\n }\n const separator = existing === \"\" ? \"\" : existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n fs.writeFileSync(\n configPath,\n existing + separator + buildProviderTomlBlock(provider) + buildModelTomlBlock(model),\n \"utf8\",\n );\n\n return { provider, model, configPath, envPath };\n}\n\n// Rewrites the top-level defaultModel line in place (other content and\n// comments preserved); inserts the line at the top when missing.\nexport function setDefaultModelInToml(content: string, modelName: string): string {\n const line = `defaultModel = ${tomlString(modelName)}`;\n const lines = content.split(\"\\n\");\n let inTopLevel = true;\n for (let i = 0; i < lines.length; i++) {\n const current = lines[i] ?? \"\";\n if (/^\\s*\\[/.test(current)) inTopLevel = false;\n if (inTopLevel && /^\\s*defaultModel\\s*=/.test(current)) {\n lines[i] = line;\n return lines.join(\"\\n\");\n }\n }\n return `${line}\\n${content}`;\n}\n\nexport function saveDefaultModel(modelName: string, configPath: string = globalConfigPath()): void {\n let content = \"\";\n try {\n content = fs.readFileSync(configPath, \"utf8\");\n } catch {\n content = \"\";\n }\n fs.mkdirSync(path.dirname(configPath), { recursive: true });\n fs.writeFileSync(configPath, setDefaultModelInToml(content, modelName), \"utf8\");\n}\n\n// Opens a file with the system default handler, fire-and-forget; failures\n// are silent (the caller already shows the path).\nexport function openConfigFile(filePath: string): void {\n const [command, args] =\n process.platform === \"win32\"\n ? [\"cmd\", [\"/c\", \"start\", \"\", filePath]]\n : process.platform === \"darwin\"\n ? [\"open\", [filePath]]\n : [\"xdg-open\", [filePath]];\n try {\n const child = spawn(command, args, { detached: true, stdio: \"ignore\" });\n child.on(\"error\", () => {});\n child.unref();\n } catch {\n // no handler available — nothing to do\n }\n}\n","import fs from \"node:fs\";\nimport { envFilePath } from \"./paths\";\n\nconst ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n// Parses dotenv-style KEY=VALUE lines; blank lines and # comments are\n// skipped, surrounding quotes on the value are stripped.\nexport function parseEnvContent(content: string): Record<string, string> {\n const vars: Record<string, string> = {};\n for (const rawLine of content.split(/\\r?\\n/)) {\n const line = rawLine.trim();\n if (!line || line.startsWith(\"#\")) continue;\n const eq = line.indexOf(\"=\");\n if (eq <= 0) continue;\n const key = line.slice(0, eq).trim();\n if (!ENV_KEY_PATTERN.test(key)) continue;\n let value = line.slice(eq + 1).trim();\n if (\n value.length >= 2 &&\n ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\")))\n ) {\n value = value.slice(1, -1);\n }\n vars[key] = value;\n }\n return vars;\n}\n\n// Fills process.env from ~/.star-cli/.env. Variables already set in the real\n// environment always win — the file only supplies missing values. Never\n// throws: a missing or unreadable file means no keys.\nexport function loadEnvFile(filePath: string = envFilePath()): void {\n let content: string;\n try {\n content = fs.readFileSync(filePath, \"utf8\");\n } catch {\n return;\n }\n for (const [key, value] of Object.entries(parseEnvContent(content))) {\n if (process.env[key] === undefined) {\n process.env[key] = value;\n }\n }\n}\n\n// Returns content with key set to value: the existing KEY= line is replaced\n// in place (comments and other variables untouched), otherwise a new line is\n// appended.\nexport function upsertEnvContent(content: string, key: string, value: string): string {\n const entry = `${key}=${value.replace(/[\\r\\n]/g, \"\")}`;\n const pattern = new RegExp(`^\\\\s*${key}\\\\s*=`);\n const lines = content.split(\"\\n\");\n while (lines.length > 0 && (lines[lines.length - 1] ?? \"\").trim() === \"\") lines.pop();\n for (let i = 0; i < lines.length; i++) {\n if (pattern.test(lines[i] ?? \"\")) {\n lines[i] = entry;\n return `${lines.join(\"\\n\")}\\n`;\n }\n }\n lines.push(entry);\n return `${lines.join(\"\\n\")}\\n`;\n}\n","import { readFileSync, readdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { starHome } from \"../../config/paths\";\nimport type { CommandRegistry } from \"./registry\";\n\nconst NAME_PATTERN = /^[a-z0-9-]+$/;\nconst DESCRIPTION_PATTERN = /^<!--\\s*description:\\s*(.+?)\\s*-->\\s*$/;\nconst DEFAULT_DESCRIPTION = \"Custom prompt command\";\n\nexport interface CustomCommand {\n name: string;\n description: string;\n template: string;\n source: string;\n}\n\nfunction parseCommandFile(filePath: string, name: string): CustomCommand | null {\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf8\");\n } catch {\n return null;\n }\n const lines = raw.split(/\\r?\\n/);\n let description = DEFAULT_DESCRIPTION;\n const first = lines[0] ?? \"\";\n const match = first.match(DESCRIPTION_PATTERN);\n if (match) {\n description = match[1] ?? DEFAULT_DESCRIPTION;\n lines.shift();\n if (lines[0] !== undefined && lines[0].trim() === \"\") lines.shift();\n }\n const template = lines.join(\"\\n\").trim();\n if (!template) return null;\n return { name, description, template, source: filePath };\n}\n\nfunction scanDir(dir: string, into: Map<string, CustomCommand>): void {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n for (const entry of entries.sort()) {\n if (!entry.endsWith(\".md\")) continue;\n const name = entry.slice(0, -\".md\".length);\n if (!NAME_PATTERN.test(name)) continue;\n const parsed = parseCommandFile(path.join(dir, entry), name);\n if (parsed) into.set(name, parsed);\n }\n}\n\nexport function loadCustomCommands(cwd: string, home: string = starHome()): CustomCommand[] {\n const byName = new Map<string, CustomCommand>();\n scanDir(path.join(home, \"commands\"), byName);\n scanDir(path.join(cwd, \".star\", \"commands\"), byName);\n return [...byName.values()];\n}\n\nexport function registerCustomCommands(\n registry: CommandRegistry,\n cwd: string,\n home?: string,\n): CustomCommand[] {\n const registered: CustomCommand[] = [];\n for (const command of loadCustomCommands(cwd, home)) {\n if (registry.get(command.name)) continue;\n registry.register({\n name: command.name,\n description: command.description,\n usage: `/${command.name} [args]`,\n category: \"Custom\",\n run(args, ctx) {\n const prompt = command.template.split(\"$ARGUMENTS\").join(args);\n if (ctx.submitPrompt) {\n return ctx.submitPrompt(prompt);\n }\n ctx.addSystemMessage(`/${command.name}: this context cannot submit prompts to the model.`);\n },\n });\n registered.push(command);\n }\n return registered;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { starHome } from \"../../config/paths\";\nimport type { StarConfig } from \"../../config/schema\";\nimport { resolveShell } from \"../../tools/bash\";\n\nconst MIN_NODE_MAJOR = 20;\nconst REGISTRY_URL = \"https://registry.npmjs.org/\";\nconst REGISTRY_TIMEOUT_MS = 5000;\n\nexport interface DoctorCheck {\n name: string;\n ok: boolean;\n detail: string;\n optional?: boolean;\n}\n\nexport interface DoctorReport {\n checks: DoctorCheck[];\n passed: number;\n failed: number;\n}\n\nexport type DoctorFetcher = (url: string, timeoutMs: number) => Promise<boolean>;\n\nasync function defaultFetcher(url: string, timeoutMs: number): Promise<boolean> {\n const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });\n return res.ok;\n}\n\nexport interface DoctorOptions {\n cwd: string;\n config: StarConfig;\n env?: NodeJS.ProcessEnv;\n home?: string;\n nodeVersion?: string;\n shellLabel?: string;\n shellPath?: string;\n fetcher?: DoctorFetcher;\n}\n\nfunction nodeMajor(version: string): number | null {\n const match = /^v?(\\d+)/.exec(version);\n return match ? Number.parseInt(match[1] ?? \"\", 10) : null;\n}\n\nasync function pathExists(target: string): Promise<boolean> {\n try {\n await fs.access(target);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction resolveApiKeyConfigured(\n config: StarConfig,\n providerName: string,\n env: NodeJS.ProcessEnv,\n): boolean | null {\n const provider = config.providers.find((p) => p.name === providerName);\n if (!provider) return null;\n const fromEnv = provider.apiKeyEnv ? env[provider.apiKeyEnv] : undefined;\n return Boolean(fromEnv ?? provider.apiKey);\n}\n\nexport async function runDoctor(opts: DoctorOptions): Promise<DoctorReport> {\n const env = opts.env ?? process.env;\n const home = opts.home ?? starHome();\n const checks: DoctorCheck[] = [];\n\n const version = opts.nodeVersion ?? process.version;\n const major = nodeMajor(version);\n const nodeOk = major !== null && major >= MIN_NODE_MAJOR;\n checks.push({\n name: \"Node.js version\",\n ok: nodeOk,\n detail: nodeOk\n ? `${version} (>= ${MIN_NODE_MAJOR} required)`\n : `${version} — Node.js >= ${MIN_NODE_MAJOR} is required`,\n });\n\n if (opts.shellLabel !== undefined || opts.shellPath !== undefined) {\n checks.push({\n name: \"Shell for bash tool\",\n ok: true,\n detail: `${opts.shellLabel ?? \"unknown\"}${opts.shellPath ? ` (${opts.shellPath})` : \"\"}`,\n });\n } else {\n const spec = resolveShell();\n checks.push({\n name: \"Shell for bash tool\",\n ok: true,\n detail: `${spec.label} (${spec.shell})`,\n });\n }\n\n const configPath = path.join(home, \"config.toml\");\n const configExists = await pathExists(configPath);\n checks.push({\n name: \"STAR_HOME / config\",\n ok: configExists,\n detail: configExists\n ? `STAR_HOME=${home}, config.toml found at ${configPath}`\n : `STAR_HOME=${home}, config.toml missing at ${configPath}`,\n });\n\n const defaultModel = opts.config.defaultModel;\n if (!defaultModel) {\n checks.push({\n name: \"Default model\",\n ok: false,\n detail: \"no defaultModel configured\",\n });\n } else {\n const modelConfig = opts.config.models.find((m) => m.name === defaultModel);\n if (!modelConfig) {\n checks.push({\n name: \"Default model\",\n ok: false,\n detail: `model \"${defaultModel}\" not found in configured models`,\n });\n } else {\n const provider = opts.config.providers.find((p) => p.name === modelConfig.provider);\n checks.push({\n name: \"Default model\",\n ok: provider !== undefined,\n detail: provider\n ? `${modelConfig.name} (${provider.name}/${modelConfig.model}, ${provider.baseURL})`\n : `provider \"${modelConfig.provider}\" for model \"${modelConfig.name}\" not found`,\n });\n const keyConfigured = resolveApiKeyConfigured(opts.config, modelConfig.provider, env);\n checks.push({\n name: \"Provider API key\",\n ok: keyConfigured === true,\n detail:\n keyConfigured === null\n ? `provider \"${modelConfig.provider}\" not found`\n : keyConfigured\n ? `apiKey resolved for provider \"${modelConfig.provider}\"`\n : `apiKey missing for provider \"${modelConfig.provider}\"${\n provider?.apiKeyEnv ? ` (set ${provider.apiKeyEnv} or configure apiKey)` : \"\"\n }`,\n });\n }\n }\n\n const sessions = path.join(home, \"sessions\");\n let writable = false;\n let writeError = \"\";\n try {\n await fs.mkdir(sessions, { recursive: true });\n const probe = path.join(sessions, `.doctor-probe-${process.pid}`);\n await fs.writeFile(probe, \"ok\");\n await fs.unlink(probe);\n writable = true;\n } catch (error) {\n writeError = error instanceof Error ? error.message : String(error);\n }\n checks.push({\n name: \"Sessions directory writable\",\n ok: writable,\n detail: writable ? `${sessions} is writable` : `${sessions} not writable: ${writeError}`,\n });\n\n const fetcher = opts.fetcher ?? defaultFetcher;\n let registryOk = false;\n try {\n registryOk = await fetcher(REGISTRY_URL, REGISTRY_TIMEOUT_MS);\n } catch {\n registryOk = false;\n }\n checks.push({\n name: \"npm registry connectivity\",\n ok: registryOk,\n detail: registryOk\n ? `${REGISTRY_URL} reachable`\n : `${REGISTRY_URL} unreachable (optional — only affects update checks)`,\n optional: true,\n });\n\n const passed = checks.filter((c) => c.ok).length;\n return { checks, passed, failed: checks.length - passed };\n}\n\nexport function formatDoctorReport(report: DoctorReport): string {\n const lines = report.checks.map(\n (check) => `${check.ok ? \"✓\" : \"✗\"} ${check.name}: ${check.detail}`,\n );\n lines.push(\"\", `${report.passed} passed, ${report.failed} failed`);\n return lines.join(\"\\n\");\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { type LanguageModel, generateText } from \"ai\";\n\nconst IGNORED_DIRS = new Set([\"node_modules\", \".git\", \"dist\", \"build\", \"out\", \"coverage\"]);\nconst MAX_ENTRIES = 20;\nconst README_HEAD_LINES = 5;\n\nexport interface ProjectFacts {\n name: string | null;\n dirName: string;\n packageManager: string | null;\n scripts: Record<string, string>;\n dependencies: string[];\n devDependencies: string[];\n commands: {\n test: string | null;\n build: string | null;\n lint: string | null;\n typecheck: string | null;\n };\n hasTsconfig: boolean;\n isGitRepo: boolean;\n readmeHead: string[];\n entries: string[];\n}\n\nasync function fileExists(target: string): Promise<boolean> {\n try {\n await fs.access(target);\n return true;\n } catch {\n return false;\n }\n}\n\ninterface PackageJson {\n name?: unknown;\n scripts?: unknown;\n dependencies?: unknown;\n devDependencies?: unknown;\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJson | null> {\n try {\n const raw = await fs.readFile(path.join(cwd, \"package.json\"), \"utf8\");\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null) return null;\n return parsed as PackageJson;\n } catch {\n return null;\n }\n}\n\nfunction stringRecord(value: unknown): Record<string, string> {\n if (typeof value !== \"object\" || value === null) return {};\n const out: Record<string, string> = {};\n for (const [key, val] of Object.entries(value)) {\n if (typeof val === \"string\") out[key] = val;\n }\n return out;\n}\n\nasync function detectPackageManager(cwd: string): Promise<string | null> {\n if (await fileExists(path.join(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (await fileExists(path.join(cwd, \"yarn.lock\"))) return \"yarn\";\n if (await fileExists(path.join(cwd, \"package-lock.json\"))) return \"npm\";\n if (await fileExists(path.join(cwd, \"bun.lockb\"))) return \"bun\";\n return null;\n}\n\nfunction inferCommands(\n pm: string | null,\n scripts: Record<string, string>,\n): ProjectFacts[\"commands\"] {\n const runner = pm ?? \"npm\";\n const pick = (script: string): string | null =>\n script in scripts ? `${runner} ${script}` : null;\n return {\n test: pick(\"test\"),\n build: pick(\"build\"),\n lint: pick(\"lint\"),\n typecheck: pick(\"typecheck\"),\n };\n}\n\nasync function listEntries(cwd: string): Promise<string[]> {\n try {\n const dirents = await fs.readdir(cwd, { withFileTypes: true });\n const entries: string[] = [];\n for (const dirent of dirents) {\n if (dirent.isDirectory()) {\n if (IGNORED_DIRS.has(dirent.name)) continue;\n entries.push(`${dirent.name}/`);\n } else if (!dirent.name.startsWith(\".\")) {\n entries.push(dirent.name);\n }\n if (entries.length >= MAX_ENTRIES) break;\n }\n return entries.sort();\n } catch {\n return [];\n }\n}\n\nasync function readReadmeHead(cwd: string): Promise<string[]> {\n for (const name of [\"README.md\", \"readme.md\", \"README\"]) {\n try {\n const raw = await fs.readFile(path.join(cwd, name), \"utf8\");\n return raw\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .slice(0, README_HEAD_LINES);\n } catch {\n // try the next candidate name\n }\n }\n return [];\n}\n\nexport async function scanProject(cwd: string): Promise<ProjectFacts> {\n const pkg = await readPackageJson(cwd);\n const packageManager = await detectPackageManager(cwd);\n const scripts = stringRecord(pkg?.scripts);\n return {\n name: typeof pkg?.name === \"string\" ? pkg.name : null,\n dirName: path.basename(cwd),\n packageManager,\n scripts,\n dependencies: Object.keys(stringRecord(pkg?.dependencies)),\n devDependencies: Object.keys(stringRecord(pkg?.devDependencies)),\n commands: inferCommands(packageManager, scripts),\n hasTsconfig: await fileExists(path.join(cwd, \"tsconfig.json\")),\n isGitRepo: await fileExists(path.join(cwd, \".git\")),\n readmeHead: await readReadmeHead(cwd),\n entries: await listEntries(cwd),\n };\n}\n\nexport function renderAgentsMd(facts: ProjectFacts): string {\n const title = facts.name ?? facts.dirName;\n const lines: string[] = [\n \"# AGENTS.md\",\n \"\",\n \"Guidance for AI agents working in this repository.\",\n \"\",\n \"## Project\",\n \"\",\n facts.readmeHead.length > 0 ? facts.readmeHead.join(\" \") : `${title}`,\n \"\",\n ];\n const commandLines: string[] = [];\n const push = (label: string, command: string | null) => {\n if (command) commandLines.push(`- \\`${command}\\` — ${label}`);\n };\n push(\"run tests\", facts.commands.test);\n push(\"build\", facts.commands.build);\n push(\"lint\", facts.commands.lint);\n push(\"typecheck\", facts.commands.typecheck);\n if (commandLines.length > 0) {\n lines.push(\"## Commands\", \"\", ...commandLines, \"\");\n }\n lines.push(\"## Layout\", \"\");\n for (const entry of facts.entries) {\n lines.push(`- \\`${entry}\\``);\n }\n lines.push(\"\", \"## Conventions\", \"\");\n const conventions: string[] = [];\n if (facts.hasTsconfig) conventions.push(\"TypeScript project (tsconfig.json present).\");\n if (facts.packageManager) conventions.push(`Use ${facts.packageManager} as the package manager.`);\n if (facts.isGitRepo) conventions.push(\"Git repository.\");\n if (facts.dependencies.length > 0) {\n conventions.push(`Key dependencies: ${facts.dependencies.slice(0, 10).join(\", \")}.`);\n }\n if (conventions.length === 0) conventions.push(\"No conventions detected yet — fill this in.\");\n for (const item of conventions) lines.push(`- ${item}`);\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\nconst INIT_SYSTEM_PROMPT = [\n \"You are writing an AGENTS.md file that guides AI coding agents working in a repository.\",\n \"You are given scanned project facts as JSON.\",\n \"Produce a concise Markdown document with sections: Project, Commands, Layout, Conventions.\",\n \"Keep commands exactly as given in the facts. Do not invent tools, scripts, or directories.\",\n \"Output only the Markdown, no preamble, no code fences.\",\n].join(\"\\n\");\n\nasync function polishWithModel(facts: ProjectFacts, model: LanguageModel): Promise<string | null> {\n const { text } = await generateText({\n model,\n system: INIT_SYSTEM_PROMPT,\n prompt: `Project facts:\\n\\n${JSON.stringify(facts, null, 2)}\\n\\nWrite the AGENTS.md.`,\n });\n const trimmed = text.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nexport interface InitProjectOptions {\n cwd: string;\n args: string;\n model: LanguageModel | null;\n}\n\nexport interface InitProjectResult {\n message: string;\n written: boolean;\n path: string;\n lines: number;\n usedLlm: boolean;\n}\n\nexport async function initProject(opts: InitProjectOptions): Promise<InitProjectResult> {\n const { cwd, args, model } = opts;\n const target = path.join(cwd, \"AGENTS.md\");\n const force = args.split(/\\s+/).includes(\"force\");\n if (!force && (await fileExists(target))) {\n return {\n message: `AGENTS.md already exists at ${target}. Use /init force to overwrite it.`,\n written: false,\n path: target,\n lines: 0,\n usedLlm: false,\n };\n }\n const facts = await scanProject(cwd);\n let usedLlm = false;\n let content: string;\n let note = \"\";\n if (model) {\n try {\n const polished = await polishWithModel(facts, model);\n if (polished) {\n content = polished.endsWith(\"\\n\") ? polished : `${polished}\\n`;\n usedLlm = true;\n } else {\n content = renderAgentsMd(facts);\n note =\n \" Model returned an empty draft; used the template instead — review and refine manually.\";\n }\n } catch {\n content = renderAgentsMd(facts);\n note = \" Model refinement failed; used the template instead — review and refine manually.\";\n }\n } else {\n content = renderAgentsMd(facts);\n note = \" No model available; used the template — review and refine manually.\";\n }\n await fs.writeFile(target, content);\n const lines = content.split(\"\\n\").length;\n const how = usedLlm ? \"generated with model refinement\" : \"generated from template\";\n return {\n message: `Wrote ${target} (${lines} lines, ${how}).${note}`,\n written: true,\n path: target,\n lines,\n usedLlm,\n };\n}\n","// Pure formatting behind /redo (rendering lives in the REPL, mirroring\n// undo.ts/rewind.ts). A redo restores the working tree to the state captured\n// just before a git-path /undo; it never touches conversation messages.\n\nexport interface RedoEntry {\n tree: string;\n label: string;\n}\n\nexport interface RedoOutcome {\n ok: boolean;\n tree: string;\n label: string;\n files: number | null;\n}\n\n// Summary line for the confirm prompt: which pre-undo state comes back.\nexport function formatRedoSummary(entry: RedoEntry): string {\n const label = entry.label !== \"\" ? ` of \"${entry.label}\"` : \"\";\n return `Restore the working tree to its state before the undo${label} (tree ${entry.tree.slice(0, 8)}). Conversation messages are not restored.`;\n}\n\nexport function formatRedoResult(result: RedoOutcome): string {\n if (!result.ok) {\n return `Redo failed — git could not restore the snapshot (tree ${result.tree.slice(0, 8)}). The redo entry was kept; try again or check that git is working.`;\n }\n const files = result.files === null ? \"unknown number of\" : `${result.files}`;\n const label = result.label !== \"\" ? ` — \"${result.label}\"` : \"\";\n return `Redone: restored ${files} file(s) to the pre-undo state (tree ${result.tree.slice(0, 8)})${label}.`;\n}\n","import type { DiffLine } from \"../diff-preview\";\n\nexport interface CommandContext {\n addSystemMessage(text: string): void;\n clearMessages(): void;\n exit(): void;\n listModels(): string;\n switchModel(name: string): Promise<string>;\n listSessions(all?: boolean): Promise<string>;\n resumeSession(id: string): Promise<string>;\n showTodos(): Promise<string>;\n listTasks(): string;\n showUsage(): string;\n showGlobalUsage(): Promise<string>;\n describeConfig(): string;\n compactContext(): Promise<string>;\n exportSession(path: string): Promise<string>;\n undo(): Promise<string>;\n redo(): Promise<string>;\n rewind(args: string): Promise<string>;\n permissionMode(args: string): Promise<string>;\n planMode(): Promise<string>;\n // Interactive pickers backed by the REPL's SelectPrompt; each returns the\n // user-facing result text (an \"unchanged\" note when the picker is cancelled).\n pickModel(): Promise<string>;\n pickPermissionMode(): Promise<string>;\n pickSession(all?: boolean): Promise<string>;\n // Forks the live session into a new stored session and swaps to it.\n forkSession(): Promise<string>;\n initProject(args: string): Promise<string>;\n runDoctor(): Promise<string>;\n submitPrompt?(text: string): void | Promise<void>;\n // Starts a fresh session with a clean context (REPL-only).\n newSession?(): Promise<string>;\n // Runs the interactive provider-onboarding wizard (REPL-only).\n connect?(): Promise<string>;\n // Deletes stored sessions: current directory by default, every directory\n // when all is true. The live session is kept.\n clearSessions?(all: boolean): Promise<string>;\n // Working directory of the session; commands that shell out (e.g. /commit,\n // /diff) fall back to process.cwd() when the host does not provide it.\n cwd?: string;\n // Renders structured diff lines with per-line colors in the message area.\n showDiff?(text: string, lines: DiffLine[], note?: string): void;\n // Copies text to the system clipboard; resolves false when unavailable.\n copyToClipboard?(text: string): Promise<boolean>;\n // Plain-text conversation for /copy: \"last\" is the latest assistant reply,\n // \"all\" the whole conversation. null when there is nothing to copy.\n conversationText?(scope: \"last\" | \"all\"): string | null;\n}\n\nexport interface SlashCommand {\n name: string;\n description: string;\n usage?: string;\n // /help groups commands under this heading; uncategorized commands fall\n // into \"Other\".\n category?: string;\n run(args: string, ctx: CommandContext): void | Promise<void>;\n}\n\nexport class CommandRegistry {\n private commands = new Map<string, SlashCommand>();\n\n register(command: SlashCommand): void {\n this.commands.set(command.name, command);\n }\n\n list(): SlashCommand[] {\n return [...this.commands.values()].sort((a, b) => a.name.localeCompare(b.name));\n }\n\n get(name: string): SlashCommand | undefined {\n return this.commands.get(name);\n }\n\n complete(prefix: string): SlashCommand[] {\n const stripped = prefix.startsWith(\"/\") ? prefix.slice(1) : prefix;\n return this.list().filter((cmd) => cmd.name.startsWith(stripped));\n }\n}\n\nexport interface ParsedCommand {\n name: string;\n args: string;\n}\n\nexport function parseSlashCommand(input: string): ParsedCommand | null {\n if (!input.startsWith(\"/\")) return null;\n const body = input.slice(1).trim();\n if (body.length === 0) return null;\n const spaceIndex = body.search(/\\s/);\n if (spaceIndex === -1) return { name: body, args: \"\" };\n return {\n name: body.slice(0, spaceIndex),\n args: body.slice(spaceIndex).trim(),\n };\n}\n","import path from \"node:path\";\nimport type { FileSnapshot } from \"../../tools/fs/snapshots\";\n\nexport interface RewindPlan {\n target: FileSnapshot;\n affected: FileSnapshot[];\n // Smallest conversation message index among affected snapshots; null when\n // none carries turn context (then a rewind reverts files only).\n messageIndex: number | null;\n}\n\n// Selects the snapshots a rewind to just before checkpoint `id` would revert:\n// the target itself and everything after it.\nexport function planRewind(snapshots: FileSnapshot[], id: number): RewindPlan | null {\n const target = snapshots.find((snapshot) => snapshot.id === id);\n if (!target) return null;\n const affected = snapshots.filter((snapshot) => snapshot.id >= id);\n let messageIndex: number | null = null;\n for (const snapshot of affected) {\n if (snapshot.messageIndex >= 0) {\n messageIndex =\n messageIndex === null\n ? snapshot.messageIndex\n : Math.min(messageIndex, snapshot.messageIndex);\n }\n }\n return { target, affected, messageIndex };\n}\n\nfunction displayPath(filePath: string, cwd: string): string {\n const relative = path.relative(cwd, filePath);\n return relative !== \"\" && !relative.startsWith(\"..\") ? relative : filePath;\n}\n\nfunction formatTime(timestamp: number): string {\n const pad = (n: number) => String(n).padStart(2, \"0\");\n const date = new Date(timestamp);\n return `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;\n}\n\nexport function formatCheckpointList(snapshots: FileSnapshot[], cwd: string): string {\n if (snapshots.length === 0) {\n return \"No checkpoints yet — checkpoints are recorded on every successful write_file/edit_file.\";\n }\n const lines = snapshots.map((snapshot) => {\n const label = snapshot.existed ? snapshot.toolName : `${snapshot.toolName} (new file)`;\n return `#${snapshot.id} ${formatTime(snapshot.timestamp)} ${label} ${displayPath(snapshot.path, cwd)}`;\n });\n return [\n `Checkpoints (${snapshots.length}):`,\n ...lines,\n \"Use /rewind <n> to restore files and conversation to just before checkpoint n.\",\n ].join(\"\\n\");\n}\n","export interface SlashCommandHint {\n name: string;\n description: string;\n usage?: string;\n}\n\nexport const MAX_SUGGESTIONS = 5;\n\nfunction isSubsequence(query: string, target: string): boolean {\n let i = 0;\n for (const ch of target) {\n if (ch === query[i]) i += 1;\n if (i === query.length) return true;\n }\n return query.length === 0;\n}\n\nexport function filterCommands(input: string, commands: SlashCommandHint[]): SlashCommandHint[] {\n if (!input.startsWith(\"/\")) return [];\n if (/\\s/.test(input)) return [];\n const prefix = input.slice(1).toLowerCase();\n const byName = (a: SlashCommandHint, b: SlashCommandHint) => a.name.localeCompare(b.name);\n const prefixed = commands.filter((cmd) => cmd.name.toLowerCase().startsWith(prefix)).sort(byName);\n const fuzzy = commands\n .filter(\n (cmd) =>\n !cmd.name.toLowerCase().startsWith(prefix) && isSubsequence(prefix, cmd.name.toLowerCase()),\n )\n .sort(byName);\n return [...prefixed, ...fuzzy].slice(0, MAX_SUGGESTIONS);\n}\n\n// Up to 3 prefix-matched command names as a \"Did you mean\" hint, or \"\".\nexport function didYouMeanSuffix(names: string[]): string {\n if (names.length === 0) return \"\";\n const listed = names.slice(0, 3).map((name) => `/${name}`);\n return ` Did you mean: ${listed.join(\", \")}?`;\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { diffTreeNames } from \"../../snapshot/git-tree\";\nimport { type FileSnapshot, resolveSnapshotContent } from \"../../tools/fs/snapshots\";\nimport { type DiffLine, buildDiffLines } from \"../diff-preview\";\n\nexport interface UndoFileDiff {\n label: string;\n lines: DiffLine[];\n}\n\nfunction displayPath(filePath: string, cwd: string): string {\n const relative = path.relative(cwd, filePath);\n return relative !== \"\" && !relative.startsWith(\"..\") ? relative : filePath;\n}\n\n// Read-only preview of the file reverts a turn-scoped /undo would apply: for\n// every snapshot of the retracted turn, the diff from the current on-disk\n// content back to the pre-change content (all deletions for a file the turn\n// created, all additions when the file has since been deleted).\nexport async function buildUndoDiffs(\n snapshots: FileSnapshot[],\n cwd: string,\n): Promise<UndoFileDiff[]> {\n const diffs: UndoFileDiff[] = [];\n for (const snapshot of snapshots) {\n let current = \"\";\n try {\n current = await readFile(snapshot.path, \"utf8\");\n } catch {\n // file currently missing — reverting recreates it from the snapshot\n }\n const before = snapshot.existed ? await resolveSnapshotContent(snapshot) : \"\";\n const lines =\n before === null\n ? [{ kind: \"marker\" as const, text: \"(snapshot content unavailable)\" }]\n : buildDiffLines(current, before);\n diffs.push({ label: displayPath(snapshot.path, cwd), lines });\n }\n return diffs;\n}\n\n// Read-only preview of the git-tree /undo path: the per-file diffs degrade to\n// a flat list of the working-tree files restoring the turn-start tree would\n// touch (tracked files that differ, plus untracked files the clean would\n// remove). Returns [] when the list cannot be produced (git unavailable) —\n// the confirm prompt then shows just its summary line.\nexport async function buildUndoTreeDiffs(cwd: string, tree: string): Promise<UndoFileDiff[]> {\n const names = await diffTreeNames(cwd, tree);\n if (!names || names.length === 0) return [];\n return [\n {\n label: \"Working-tree files restoring the turn's start will touch:\",\n lines: names.map((name) => ({ kind: \"marker\" as const, text: name })),\n },\n ];\n}\n","import { Box, Text } from \"ink\";\nimport { useRef, useState } from \"react\";\nimport {\n type ConnectAnswers,\n PROTOCOLS,\n PROTOCOL_DESCRIPTIONS,\n PROVIDER_PRESETS,\n type Protocol,\n type ProviderPreset,\n apiKeyEnvFor,\n dedupeName,\n deriveProviderName,\n maskApiKey,\n} from \"../commands/connect\";\nimport { useInput } from \"../use-input\";\nimport { type SelectOption, SelectPrompt } from \"./SelectPrompt\";\nimport { TextField } from \"./TextField\";\n\ntype Step =\n | \"provider\"\n | \"protocol\"\n | \"baseUrl\"\n | \"apiKey\"\n | \"model\"\n | \"confirm\"\n | \"setDefault\"\n | \"openFile\";\n\ninterface ConnectWizardProps {\n existingProviderNames: string[];\n existingModelNames: string[];\n // Persists the provider/model and returns the user-facing result line.\n onSave(answers: ConnectAnswers): Promise<string>;\n onSetDefault(modelName: string): Promise<string>;\n onOpenConfig(): string;\n onFinish(message: string): void;\n onCancel(): void;\n}\n\nfunction YN({ question, onAnswer }: { question: string; onAnswer(yes: boolean): void }) {\n useInput((input, key) => {\n const ch = input.toLowerCase();\n if (ch === \"y\") onAnswer(true);\n else if (ch === \"n\" || key.escape) onAnswer(false);\n });\n return (\n <Text>\n {question} <Text dimColor>[y] yes [n] no</Text>\n </Text>\n );\n}\n\nexport function ConnectWizard({\n existingProviderNames,\n existingModelNames,\n onSave,\n onSetDefault,\n onOpenConfig,\n onFinish,\n onCancel,\n}: ConnectWizardProps) {\n const [step, setStep] = useState<Step>(\"provider\");\n const [preset, setPreset] = useState<ProviderPreset | null>(null);\n const [protocol, setProtocol] = useState<Protocol>(\"openai-compatible\");\n const [baseURL, setBaseURL] = useState(\"\");\n const [apiKey, setApiKey] = useState(\"\");\n const [modelId, setModelId] = useState(\"\");\n const [answers, setAnswers] = useState<ConnectAnswers | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const [notes, setNotes] = useState<string[]>([]);\n const busyRef = useRef(false);\n const notesRef = useRef<string[]>([]);\n\n const pushNote = (note: string) => {\n notesRef.current = [...notesRef.current, note];\n setNotes(notesRef.current);\n };\n\n const providerOptions: SelectOption[] = [\n ...PROVIDER_PRESETS.map((p) => ({ value: p.key, label: p.label, description: p.baseURL })),\n {\n value: \"custom\",\n label: \"Custom\",\n description: \"any OpenAI/Anthropic-compatible endpoint\",\n },\n ];\n\n const handleProviderSelect = (value: string) => {\n const found = PROVIDER_PRESETS.find((p) => p.key === value) ?? null;\n setPreset(found);\n if (found) {\n setProtocol(found.protocol);\n setBaseURL(found.baseURL);\n setStep(\"baseUrl\");\n } else {\n setStep(\"protocol\");\n }\n };\n\n const handleProtocolSelect = (value: string) => {\n setProtocol(value as Protocol);\n setStep(\"baseUrl\");\n };\n\n const submitBaseURL = (value: string) => {\n if (!value) {\n setError(\"baseURL is required\");\n return;\n }\n setError(null);\n setBaseURL(value);\n setStep(\"apiKey\");\n };\n\n const submitApiKey = (value: string) => {\n if (!value) {\n setError(\"API key is required\");\n return;\n }\n setError(null);\n setApiKey(value);\n setStep(\"model\");\n };\n\n const submitModel = (value: string) => {\n if (!value) {\n setError(\"model id is required\");\n return;\n }\n setError(null);\n setModelId(value);\n const providerName = dedupeName(deriveProviderName(baseURL), existingProviderNames);\n setAnswers({\n providerName,\n protocol,\n baseURL,\n apiKeyEnv: apiKeyEnvFor(providerName),\n apiKey,\n modelName: dedupeName(value, existingModelNames),\n modelId: value,\n });\n setStep(\"confirm\");\n };\n\n const handleConfirm = async (yes: boolean) => {\n if (!yes) {\n onCancel();\n return;\n }\n if (busyRef.current || !answers) return;\n busyRef.current = true;\n setBusy(true);\n try {\n pushNote(await onSave(answers));\n } catch (saveError) {\n busyRef.current = false;\n setBusy(false);\n setError(\n `Save failed: ${saveError instanceof Error ? saveError.message : String(saveError)}`,\n );\n return;\n }\n busyRef.current = false;\n setBusy(false);\n setStep(\"setDefault\");\n };\n\n const handleSetDefault = async (yes: boolean) => {\n if (busyRef.current || !answers) return;\n busyRef.current = true;\n setBusy(true);\n try {\n pushNote(yes ? await onSetDefault(answers.modelName) : \"Default model unchanged.\");\n } catch (setDefaultError) {\n pushNote(\n `Could not set the default model: ${setDefaultError instanceof Error ? setDefaultError.message : String(setDefaultError)}`,\n );\n }\n busyRef.current = false;\n setBusy(false);\n setStep(\"openFile\");\n };\n\n const handleOpenFile = (yes: boolean) => {\n if (yes) pushNote(onOpenConfig());\n onFinish(notesRef.current.join(\"\\n\"));\n };\n\n return (\n <Box flexDirection=\"column\">\n <Text bold color=\"cyan\">\n Connect a provider\n </Text>\n {notes.map((note, index) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: notes are append-only\n <Text key={index} dimColor>\n {note}\n </Text>\n ))}\n {step === \"provider\" && (\n <SelectPrompt\n title=\"Which provider?\"\n options={providerOptions}\n onSelect={handleProviderSelect}\n onCancel={onCancel}\n />\n )}\n {step === \"protocol\" && (\n <SelectPrompt\n title=\"API format (protocol)?\"\n options={PROTOCOLS.map((p) => ({\n value: p,\n label: p,\n description: PROTOCOL_DESCRIPTIONS[p],\n }))}\n onSelect={handleProtocolSelect}\n onCancel={onCancel}\n />\n )}\n {step === \"baseUrl\" && (\n <TextField\n label=\"baseURL:\"\n initialValue={preset?.baseURL ?? \"\"}\n placeholder=\"https://api.example.com/v1\"\n onSubmit={submitBaseURL}\n onCancel={onCancel}\n />\n )}\n {step === \"apiKey\" && (\n <TextField\n label=\"API key:\"\n masked\n placeholder=\"paste your key (hidden)\"\n onSubmit={submitApiKey}\n onCancel={onCancel}\n />\n )}\n {step === \"model\" && (\n <TextField\n label=\"Model id:\"\n placeholder={preset?.modelHint ?? \"e.g. gpt-4o\"}\n onSubmit={submitModel}\n onCancel={onCancel}\n />\n )}\n {step === \"confirm\" && answers && (\n <Box flexDirection=\"column\">\n <Text>{` provider: ${answers.providerName} (${answers.protocol})`}</Text>\n <Text>{` baseURL: ${answers.baseURL}`}</Text>\n <Text>{` API key: ${maskApiKey(answers.apiKey)} → ${answers.apiKeyEnv} (stored in ~/.star-cli/.env)`}</Text>\n <Text>{` model: ${answers.modelName} → ${answers.modelId}`}</Text>\n {busy ? (\n <Text dimColor>Saving…</Text>\n ) : (\n <YN question=\"Save this provider and model?\" onAnswer={handleConfirm} />\n )}\n </Box>\n )}\n {step === \"setDefault\" &&\n (busy ? (\n <Text dimColor>Saving…</Text>\n ) : (\n <YN\n question={`Set \"${answers?.modelName}\" as the default model and switch to it?`}\n onAnswer={handleSetDefault}\n />\n ))}\n {step === \"openFile\" && <YN question=\"Open the config file now?\" onAnswer={handleOpenFile} />}\n {error && <Text color=\"red\">{error}</Text>}\n </Box>\n );\n}\n","import { useStdin } from \"ink\";\nimport { useEffect, useRef } from \"react\";\nimport { type Key, splitKeypresses, splitTrailingIncomplete, toInputKey } from \"./keypress\";\n\nexport type InputHandler = (input: string, key: Key) => void;\n\n// Drop-in replacement for Ink's useInput that first splits each stdin chunk\n// into individual keypresses (see keypress.ts). Ink parses one keypress per\n// chunk, so coalesced rapid keys — repeated arrow presses while browsing\n// history, double-Esc, a key landing right after a paste — after the first\n// were silently dropped.\nexport function useInput(inputHandler: InputHandler, options: { isActive?: boolean } = {}) {\n const { setRawMode, internal_exitOnCtrlC, internal_eventEmitter } = useStdin();\n // An escape sequence split across two reads is held here until the rest\n // arrives (a bare trailing ESC is never held — it is the Escape key).\n const pendingRef = useRef(\"\");\n\n useEffect(() => {\n if (options.isActive === false) return;\n setRawMode(true);\n return () => {\n setRawMode(false);\n };\n }, [options.isActive, setRawMode]);\n\n useEffect(() => {\n if (options.isActive === false) return;\n const handleData = (data: string) => {\n const { head, tail } = splitTrailingIncomplete(pendingRef.current + data);\n pendingRef.current = tail;\n for (const unit of splitKeypresses(head)) {\n const { input, key } = toInputKey(unit);\n // Same guard as Ink: Ctrl+C is left to Ink's own exit handler unless\n // the app opted out of exit-on-Ctrl-C.\n if (!(input === \"c\" && key.ctrl) || !internal_exitOnCtrlC) {\n inputHandler(input, key);\n }\n }\n };\n internal_eventEmitter?.on(\"input\", handleData);\n return () => {\n internal_eventEmitter?.removeListener(\"input\", handleData);\n };\n }, [options.isActive, internal_exitOnCtrlC, internal_eventEmitter, inputHandler]);\n}\n","// Keypress parsing and stdin-chunk splitting.\n//\n// Ink's useInput parses each stdin chunk as exactly ONE keypress, so when the\n// terminal coalesces rapid keys into a single read (ESC[A ESC[A from fast\n// arrow presses or key repeat), every key after the first is silently dropped\n// — history navigation and line hopping then feel dead. Here a chunk is first\n// split into individual keypress units (escape sequences vs. maximal plain\n// text runs, so pasted text still arrives as one string), and each unit is\n// parsed separately.\n//\n// parseKeypress is a TypeScript port of Ink's parse-keypress.js (itself from\n// enquirer's keypress.js, MIT), kept behavior-identical so existing handlers\n// see the same (input, key) pairs as before.\n\nexport interface Keypress {\n name: string | undefined;\n ctrl: boolean;\n meta: boolean;\n shift: boolean;\n option: boolean;\n sequence: string;\n code?: string;\n}\n\n// biome-ignore lint/suspicious/noControlCharactersInRegex: parsing escape sequences is the whole point\nconst metaKeyCodeRe = /^(?:\\u001B)([a-zA-Z0-9])$/;\n// biome-ignore lint/suspicious/noControlCharactersInRegex: parsing escape sequences is the whole point\nconst fnKeyRe = /^(?:\\u001B+)(O|N|\\[|\\[\\[)(?:(\\d+)(?:;(\\d+))?([~^$])|(?:1;)?(\\d+)?([a-zA-Z]))/;\n\nconst keyName: Record<string, string> = {\n OP: \"f1\",\n OQ: \"f2\",\n OR: \"f3\",\n OS: \"f4\",\n \"[11~\": \"f1\",\n \"[12~\": \"f2\",\n \"[13~\": \"f3\",\n \"[14~\": \"f4\",\n \"[[A\": \"f1\",\n \"[[B\": \"f2\",\n \"[[C\": \"f3\",\n \"[[D\": \"f4\",\n \"[[E\": \"f5\",\n \"[15~\": \"f5\",\n \"[17~\": \"f6\",\n \"[18~\": \"f7\",\n \"[19~\": \"f8\",\n \"[20~\": \"f9\",\n \"[21~\": \"f10\",\n \"[23~\": \"f11\",\n \"[24~\": \"f12\",\n \"[A\": \"up\",\n \"[B\": \"down\",\n \"[C\": \"right\",\n \"[D\": \"left\",\n \"[E\": \"clear\",\n \"[F\": \"end\",\n \"[H\": \"home\",\n OA: \"up\",\n OB: \"down\",\n OC: \"right\",\n OD: \"left\",\n OE: \"clear\",\n OF: \"end\",\n OH: \"home\",\n \"[1~\": \"home\",\n \"[2~\": \"insert\",\n \"[3~\": \"delete\",\n \"[4~\": \"end\",\n \"[5~\": \"pageup\",\n \"[6~\": \"pagedown\",\n \"[[5~\": \"pageup\",\n \"[[6~\": \"pagedown\",\n \"[7~\": \"home\",\n \"[8~\": \"end\",\n \"[a\": \"up\",\n \"[b\": \"down\",\n \"[c\": \"right\",\n \"[d\": \"left\",\n \"[e\": \"clear\",\n \"[2$\": \"insert\",\n \"[3$\": \"delete\",\n \"[5$\": \"pageup\",\n \"[6$\": \"pagedown\",\n \"[7$\": \"home\",\n \"[8$\": \"end\",\n Oa: \"up\",\n Ob: \"down\",\n Oc: \"right\",\n Od: \"left\",\n Oe: \"clear\",\n \"[2^\": \"insert\",\n \"[3^\": \"delete\",\n \"[5^\": \"pageup\",\n \"[6^\": \"pagedown\",\n \"[7^\": \"home\",\n \"[8^\": \"end\",\n \"[Z\": \"tab\",\n};\n\nexport const nonAlphanumericKeys = [...Object.values(keyName), \"backspace\"];\n\nconst shiftKeyCodes = new Set([\n \"[a\",\n \"[b\",\n \"[c\",\n \"[d\",\n \"[e\",\n \"[2$\",\n \"[3$\",\n \"[5$\",\n \"[6$\",\n \"[7$\",\n \"[8$\",\n \"[Z\",\n]);\n\nconst ctrlKeyCodes = new Set([\n \"Oa\",\n \"Ob\",\n \"Oc\",\n \"Od\",\n \"Oe\",\n \"[2^\",\n \"[3^\",\n \"[5^\",\n \"[6^\",\n \"[7^\",\n \"[8^\",\n]);\n\nexport function parseKeypress(s: string): Keypress {\n const key: Keypress = {\n name: undefined,\n ctrl: false,\n meta: false,\n shift: false,\n option: false,\n sequence: s,\n };\n if (s === \"\\r\") {\n key.name = \"return\";\n } else if (s === \"\\n\") {\n key.name = \"enter\";\n } else if (s === \"\\t\") {\n key.name = \"tab\";\n } else if (s === \"\\b\" || s === \"\\u001B\\b\") {\n key.name = \"backspace\";\n key.meta = s.charAt(0) === \"\\u001B\";\n } else if (s === \"\\x7f\" || s === \"\\u001B\\x7f\") {\n key.name = \"delete\";\n key.meta = s.charAt(0) === \"\\u001B\";\n } else if (s === \"\\u001B\" || s === \"\\u001B\\u001B\") {\n key.name = \"escape\";\n key.meta = s.length === 2;\n } else if (s === \" \" || s === \"\\u001B \") {\n key.name = \"space\";\n key.meta = s.length === 2;\n } else if (s.length === 1 && s <= \"\\x1a\") {\n key.name = String.fromCharCode(s.charCodeAt(0) + \"a\".charCodeAt(0) - 1);\n key.ctrl = true;\n } else if (s.length === 1 && s >= \"0\" && s <= \"9\") {\n key.name = \"number\";\n } else if (s.length === 1 && s >= \"a\" && s <= \"z\") {\n key.name = s;\n } else if (s.length === 1 && s >= \"A\" && s <= \"Z\") {\n key.name = s.toLowerCase();\n key.shift = true;\n }\n const metaMatch = key.name === undefined ? metaKeyCodeRe.exec(s) : null;\n const fnMatch = key.name === undefined && metaMatch === null ? fnKeyRe.exec(s) : null;\n if (metaMatch) {\n key.meta = true;\n key.shift = /^[A-Z]$/.test(metaMatch[1] ?? \"\");\n } else if (fnMatch) {\n const segs = [...s];\n if (segs[0] === \"\\u001B\" && segs[1] === \"\\u001B\") {\n key.option = true;\n }\n const code = [fnMatch[1], fnMatch[2], fnMatch[4], fnMatch[6]].filter(Boolean).join(\"\");\n const modifier = Number(fnMatch[3] || fnMatch[5] || 1) - 1;\n key.ctrl = !!(modifier & 4);\n key.meta = !!(modifier & 10);\n key.shift = !!(modifier & 1);\n key.code = code;\n key.name = keyName[code];\n key.shift = shiftKeyCodes.has(code) || key.shift;\n key.ctrl = ctrlKeyCodes.has(code) || key.ctrl;\n }\n return key;\n}\n\n// Splits a raw stdin chunk into keypress units. Escape sequences (CSI:\n// ESC [ … final-byte; SS3: ESC O char; meta: ESC + char, including the\n// ESC ESC [ … meta-sequence form) each become one unit; everything between\n// them stays one intact text run so multi-character paste chunks keep\n// arriving as a single input string. A trailing incomplete sequence is\n// returned as-is — the same thing Ink would have parsed from the chunk.\nexport function splitKeypresses(chunk: string): string[] {\n const units: string[] = [];\n let i = 0;\n const csiLength = (start: number): number => {\n // start points just past \"ESC [\". Consume until the final byte\n // (0x40–0x7E) or the end of the chunk.\n let j = start;\n while (j < chunk.length) {\n const code = chunk.charCodeAt(j);\n j += 1;\n if (code >= 0x40 && code <= 0x7e) break;\n }\n return j;\n };\n while (i < chunk.length) {\n if (chunk[i] !== \"\\u001B\") {\n const next = chunk.indexOf(\"\\u001B\", i);\n const end = next === -1 ? chunk.length : next;\n units.push(chunk.slice(i, end));\n i = end;\n continue;\n }\n const next = chunk[i + 1];\n if (next === undefined) {\n units.push(\"\\u001B\");\n i += 1;\n } else if (next === \"[\") {\n const end = csiLength(i + 2);\n units.push(chunk.slice(i, end));\n i = end;\n } else if (next === \"O\") {\n const end = Math.min(i + 3, chunk.length);\n units.push(chunk.slice(i, end));\n i = end;\n } else if (next === \"\\u001B\" && (chunk[i + 2] === \"[\" || chunk[i + 2] === \"O\")) {\n // Meta + arrow (ESC ESC [ A): keep as one unit.\n const end = chunk[i + 2] === \"[\" ? csiLength(i + 3) : Math.min(i + 4, chunk.length);\n units.push(chunk.slice(i, end));\n i = end;\n } else if (next === \"\\u001B\") {\n // Two bare ESCs (double-Esc editing): dispatch them separately.\n units.push(\"\\u001B\");\n i += 1;\n } else {\n // Meta + character.\n units.push(chunk.slice(i, i + 2));\n i += 2;\n }\n }\n return units;\n}\n\nexport interface Key {\n upArrow: boolean;\n downArrow: boolean;\n leftArrow: boolean;\n rightArrow: boolean;\n pageDown: boolean;\n pageUp: boolean;\n return: boolean;\n escape: boolean;\n ctrl: boolean;\n shift: boolean;\n tab: boolean;\n backspace: boolean;\n delete: boolean;\n meta: boolean;\n}\n\n// A chunk tail that is the beginning of an escape sequence split across two\n// reads (\"ESC[20\" of an incoming \"ESC[201~\"). Held back by the dispatcher and\n// prepended to the next chunk. A bare trailing ESC is deliberately NOT held:\n// it is the Escape key and must dispatch immediately.\n// biome-ignore lint/suspicious/noControlCharactersInRegex: matching escape-sequence prefixes is the whole point\nconst INCOMPLETE_TAIL_RE = /\\u001B(?:\\[(?:[0-9;?]*)?|O|\\u001B(?:\\[(?:[0-9;?]*)?|O))$/;\n\n// Splits a chunk into the dispatchable head and an incomplete escape-sequence\n// tail to hold for the next chunk.\nexport function splitTrailingIncomplete(chunk: string): { head: string; tail: string } {\n const match = INCOMPLETE_TAIL_RE.exec(chunk);\n if (!match) return { head: chunk, tail: \"\" };\n return { head: chunk.slice(0, chunk.length - match[0].length), tail: match[0] };\n}\n\n// Maps one keypress unit to the (input, key) pair Ink's useInput would have\n// produced for it, so handlers can stay unchanged.\nexport function toInputKey(unit: string): { input: string; key: Key } {\n const keypress = parseKeypress(unit);\n const key: Key = {\n upArrow: keypress.name === \"up\",\n downArrow: keypress.name === \"down\",\n leftArrow: keypress.name === \"left\",\n rightArrow: keypress.name === \"right\",\n pageDown: keypress.name === \"pagedown\",\n pageUp: keypress.name === \"pageup\",\n return: keypress.name === \"return\",\n escape: keypress.name === \"escape\",\n ctrl: keypress.ctrl,\n shift: keypress.shift,\n tab: keypress.name === \"tab\",\n backspace: keypress.name === \"backspace\",\n delete: keypress.name === \"delete\",\n meta: keypress.meta || keypress.name === \"escape\" || keypress.option,\n };\n let input = keypress.ctrl ? (keypress.name ?? \"\") : keypress.sequence;\n if (nonAlphanumericKeys.includes(keypress.name ?? \"\")) {\n input = \"\";\n }\n if (input.startsWith(\"\\u001B\")) {\n input = input.slice(1);\n }\n if (input.length === 1 && /[A-Z]/.test(input)) {\n key.shift = true;\n }\n return { input, key };\n}\n","import { Box, Text } from \"ink\";\nimport { useRef, useState } from \"react\";\nimport { useInput } from \"../use-input\";\n\nexport interface SelectOption {\n value: string;\n label: string;\n description?: string;\n hint?: string;\n}\n\ninterface SelectPromptProps {\n title: string;\n options: SelectOption[];\n onSelect(value: string): void;\n onCancel(): void;\n}\n\nexport const SELECT_PROMPT_MAX_VISIBLE = 9;\n\nexport function SelectPrompt({ title, options, onSelect, onCancel }: SelectPromptProps) {\n const [index, setIndex] = useState(0);\n const indexRef = useRef(0);\n const move = (delta: number) => {\n indexRef.current = Math.max(0, Math.min(indexRef.current + delta, options.length - 1));\n setIndex(indexRef.current);\n };\n\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n return;\n }\n if (key.return) {\n const option = options[indexRef.current];\n if (option) onSelect(option.value);\n return;\n }\n if (key.downArrow || input === \"j\") {\n move(1);\n } else if (key.upArrow || input === \"k\") {\n move(-1);\n }\n });\n\n const maxStart = Math.max(0, options.length - SELECT_PROMPT_MAX_VISIBLE);\n const start = Math.min(Math.max(0, index - Math.floor(SELECT_PROMPT_MAX_VISIBLE / 2)), maxStart);\n const visible = options.slice(start, start + SELECT_PROMPT_MAX_VISIBLE);\n const above = start;\n const below = options.length - start - visible.length;\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Text bold color=\"cyan\">\n {title}\n </Text>\n {above > 0 && <Text dimColor>… {above} more above</Text>}\n {visible.map((option, i) => {\n const active = start + i === index;\n return (\n <Text key={option.value}>\n <Text bold={active} inverse={active}>\n {active ? \"❯ \" : \" \"}\n {option.label}\n </Text>\n {option.hint && <Text dimColor> ({option.hint})</Text>}\n {option.description && <Text dimColor> — {option.description}</Text>}\n </Text>\n );\n })}\n {below > 0 && <Text dimColor>… {below} more below</Text>}\n <Text dimColor>[↑/↓ or j/k] move [Enter] select [Esc] cancel</Text>\n </Box>\n );\n}\n","import { Box, Text } from \"ink\";\nimport { useRef, useState } from \"react\";\nimport { useInput } from \"../use-input\";\nimport { type BracketPasteState, feedBracketedPaste } from \"./InputBox\";\n\ninterface TextFieldProps {\n label: string;\n initialValue?: string;\n // echoes bullets instead of the raw text (API keys)\n masked?: boolean;\n placeholder?: string;\n onSubmit(value: string): void;\n onCancel(): void;\n}\n\nconst MASK_CAP = 24;\n\n// Minimal single-line text input for wizard-style prompts; Enter submits the\n// trimmed value, Backspace deletes, Esc cancels.\nexport function TextField({\n label,\n initialValue = \"\",\n masked = false,\n placeholder,\n onSubmit,\n onCancel,\n}: TextFieldProps) {\n const [value, setValue] = useState(initialValue);\n const valueRef = useRef(initialValue);\n const bracketRef = useRef<BracketPasteState>({ active: false, buffer: \"\", pending: \"\" });\n\n // A paste whose end marker never arrived keeps its content buffered; fold it\n // into the value before any key acts on it (mirrors InputBox's flush).\n const flushBracket = () => {\n const bracket = bracketRef.current;\n const content = bracket.buffer.replace(/[\\r\\n]+/g, \"\");\n bracket.active = false;\n bracket.buffer = \"\";\n bracket.pending = \"\";\n if (content.length > 0) {\n valueRef.current += content;\n setValue(valueRef.current);\n }\n };\n\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n return;\n }\n if (key.return) {\n flushBracket();\n onSubmit(valueRef.current.trim());\n return;\n }\n if (key.backspace || key.delete) {\n flushBracket();\n valueRef.current = valueRef.current.slice(0, -1);\n setValue(valueRef.current);\n return;\n }\n if (key.ctrl || key.meta || !input) return;\n // Pasted text arrives wrapped in bracketed-paste markers (InputBox enables\n // the mode terminal-wide); feed through the shared state machine so the\n // markers never land in the value and the field stays editable. Null means\n // the event carried only (partial) markers — nothing to append.\n const segments = feedBracketedPaste(bracketRef.current, input);\n if (segments === null) return;\n const text = segments\n .map((segment) => segment.text)\n .join(\"\")\n .replace(/[\\r\\n]+/g, \"\");\n if (text.length === 0) return;\n valueRef.current += text;\n setValue(valueRef.current);\n });\n\n const echo = masked ? \"•\".repeat(Math.min(value.length, MASK_CAP)) : value;\n return (\n <Box flexDirection=\"column\">\n <Text>\n {label} <Text bold>{echo}</Text>\n {value === \"\" && placeholder ? <Text dimColor>{placeholder}</Text> : null}\n </Text>\n <Text dimColor>[Enter] confirm [Esc] cancel</Text>\n </Box>\n );\n}\n","import { Box, Text, useStdout } from \"ink\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { type SlashCommandHint, filterCommands } from \"../commands/suggest\";\nimport { type PathSuggestion, extractAtToken, suggestPaths } from \"../path-suggest\";\nimport { useInput } from \"../use-input\";\n\nexport interface InputRefill {\n text: string;\n seq: number;\n}\n\n// Cursor position one visual line up/down (lines split on \\n), keeping the\n// column clamped to the target line's length. Null when there is no line in\n// that direction.\nexport function moveCursorLines(value: string, cursor: number, delta: -1 | 1): number | null {\n const lineStart = value.lastIndexOf(\"\\n\", cursor - 1) + 1;\n const col = cursor - lineStart;\n if (delta === -1) {\n if (lineStart === 0) return null;\n const prevEnd = lineStart - 1;\n const prevStart = value.lastIndexOf(\"\\n\", prevEnd - 1) + 1;\n return prevStart + Math.min(col, prevEnd - prevStart);\n }\n const lineEndIndex = value.indexOf(\"\\n\", cursor);\n if (lineEndIndex === -1) return null;\n const nextStart = lineEndIndex + 1;\n const nextEndIndex = value.indexOf(\"\\n\", nextStart);\n const nextEnd = nextEndIndex === -1 ? value.length : nextEndIndex;\n return nextStart + Math.min(col, nextEnd - nextStart);\n}\n\n// Case-insensitive substring scan for reverse history search: step -1 walks\n// from `from` toward older entries, step 1 toward newer ones. Null on no match.\nexport function findHistoryMatch(\n history: string[],\n query: string,\n from: number,\n step: -1 | 1,\n): number | null {\n const needle = query.toLowerCase();\n for (let i = from; i >= 0 && i < history.length; i += step) {\n if ((history[i] ?? \"\").toLowerCase().includes(needle)) return i;\n }\n return null;\n}\n\ninterface ReverseSearch {\n query: string;\n // Index into history of the currently shown match; null when nothing matches.\n match: number | null;\n}\n\n// A single input event inserting at least this many lines or characters is\n// treated as a paste and collapsed into a placeholder instead of expanding\n// into the editable text.\nexport const PASTE_COLLAPSE_MIN_LINES = 10;\nexport const PASTE_COLLAPSE_MIN_CHARS = 500;\n\n// Fallback for terminals without bracketed paste: after a collapse, input\n// arriving within this window right after the placeholder and looking\n// paste-like (has a newline or is at least this long) is folded into the\n// same paste entry instead of leaking into the editable text. The bounds\n// keep characters typed right after a paste from being swallowed.\nexport const PASTE_MERGE_WINDOW_MS = 100;\nexport const PASTE_MERGE_MIN_CHARS = 32;\n\n// Zero-width spaces delimit the placeholder token so the visible label\n// \"[pasted #1: 12 lines]\" typed by hand never collides with a real one.\nconst PASTE_DELIM = \"\\u200B\";\nconst PASTE_TOKEN_RE = /\\u200B\\[pasted #(\\d+): \\d+ lines?\\]\\u200B/g;\n// Bracketed-paste markers. Ink strips a chunk-leading ESC, so at the start\n// of an input event they show up without it (\"[200~\" / \"[201~\").\nconst BRACKETED_PASTE_START = \"\\u001B[200~\";\nconst BRACKETED_PASTE_END = \"\\u001B[201~\";\n// A tail that could be the beginning of a marker split across two input\n// events; held back until the next event resolves it.\n// biome-ignore lint/suspicious/noControlCharactersInRegex: matches an ESC-prefixed marker fragment\nconst PARTIAL_BRACKET_RE = /\\u001B(?:\\[(?:2(?:0(?:[01])?)?)?)?$/;\n\nexport interface BracketPasteState {\n // Inside the bracket: everything is buffered until the end marker.\n active: boolean;\n buffer: string;\n // Unresolved trailing bytes that may complete a marker in the next event.\n pending: string;\n}\n\nexport type PasteSegment = { type: \"text\" | \"paste\"; text: string };\n\n// Character-stream state machine over Ink's chunked input events: splits an\n// event into plain-text and complete-bracketed-paste segments, buffering\n// paste content (and marker fragments) across events. Null when the event\n// was fully absorbed into the buffer. Stray ESC bytes are stripped from\n// text segments so a marker fragment that never completes can never reach\n// the editable text.\nexport function feedBracketedPaste(state: BracketPasteState, raw: string): PasteSegment[] | null {\n let stream = state.pending + raw;\n state.pending = \"\";\n if (stream.startsWith(\"[200~\") || stream.startsWith(\"[201~\")) {\n stream = `\\u001B${stream}`;\n }\n const segments: PasteSegment[] = [];\n let buffer = state.buffer;\n let bracketed = state.active;\n let i = 0;\n const pushText = (text: string) => {\n const cleaned = text.replaceAll(\"\\u001B\", \"\");\n if (cleaned.length > 0) segments.push({ type: \"text\", text: cleaned });\n };\n const holdPartial = (tail: string) => {\n const partial = PARTIAL_BRACKET_RE.exec(tail);\n if (!partial) return tail;\n state.pending = partial[0];\n return tail.slice(0, tail.length - partial[0].length);\n };\n while (i < stream.length) {\n if (bracketed) {\n const idx = stream.indexOf(BRACKETED_PASTE_END, i);\n if (idx === -1) {\n buffer += holdPartial(stream.slice(i));\n i = stream.length;\n } else {\n buffer += stream.slice(i, idx);\n segments.push({ type: \"paste\", text: buffer });\n buffer = \"\";\n bracketed = false;\n i = idx + BRACKETED_PASTE_END.length;\n }\n } else {\n const idx = stream.indexOf(BRACKETED_PASTE_START, i);\n if (idx === -1) {\n pushText(holdPartial(stream.slice(i)));\n i = stream.length;\n } else {\n pushText(stream.slice(i, idx));\n buffer = \"\";\n bracketed = true;\n i = idx + BRACKETED_PASTE_START.length;\n }\n }\n }\n state.active = bracketed;\n state.buffer = buffer;\n return segments.length === 0 ? null : segments;\n}\n\nfunction pasteToken(id: number, lineCount: number): string {\n const label = `[pasted #${id}: ${lineCount} ${lineCount === 1 ? \"line\" : \"lines\"}]`;\n return `${PASTE_DELIM}${label}${PASTE_DELIM}`;\n}\n\nfunction stylePasteTokens(segment: string): string {\n return segment.replace(PASTE_TOKEN_RE, (match) => `\\u001B[2m${match}\\u001B[22m`);\n}\n\ninterface InputBoxProps {\n isStreaming: boolean;\n disabled?: boolean;\n commands?: SlashCommandHint[];\n cwd?: string;\n // Refill request (double-Esc edit): when seq changes, the input is replaced.\n refill?: InputRefill;\n // History entries loaded from disk; used only as the initial history state.\n initialHistory?: string[];\n onSubmit(text: string): void;\n onInterrupt(): void;\n onExit(): void;\n // Async clipboard-image read (Alt+V / Ctrl+V); staging is the parent's job.\n onPasteImage?(): void;\n}\n\nexport function InputBox({\n isStreaming,\n disabled,\n commands,\n cwd,\n refill,\n initialHistory,\n onSubmit,\n onInterrupt,\n onExit,\n onPasteImage,\n}: InputBoxProps) {\n const [value, setValue] = useState(\"\");\n const [cursor, setCursor] = useState(0);\n const [history, setHistory] = useState<string[]>(() => initialHistory ?? []);\n const [highlight, setHighlight] = useState(0);\n const [suggestionsDismissed, setSuggestionsDismissed] = useState(false);\n const [pathSuggestions, setPathSuggestions] = useState<PathSuggestion[]>([]);\n const historyIndexRef = useRef<number | null>(null);\n const draftRef = useRef(\"\");\n const refillSeqRef = useRef(0);\n const [search, setSearch] = useState<ReverseSearch | null>(null);\n const searchSavedRef = useRef<{ value: string; cursor: number } | null>(null);\n // Collapsed paste contents by placeholder id; expanded back on submit.\n const pastesRef = useRef(new Map<number, string>());\n const pasteSeqRef = useRef(0);\n const bracketRef = useRef<BracketPasteState>({ active: false, buffer: \"\", pending: \"\" });\n // The most recent placeholder: id, current token text, cursor position\n // right after it, and when it was created/last merged into.\n const lastPasteRef = useRef<{ id: number; token: string; cursor: number; time: number } | null>(\n null,\n );\n // Ref mirrors of value/cursor: paste chunks drained from stdin in one go\n // are handled by a stale render closure, so the paste paths must not rely\n // on the state variables.\n const valueRef = useRef(value);\n const cursorRef = useRef(cursor);\n useEffect(() => {\n valueRef.current = value;\n cursorRef.current = cursor;\n });\n\n // Ask the terminal to wrap pastes in bracketed-paste markers so a paste\n // split into several stdin chunks can be reassembled reliably.\n const { stdout } = useStdout();\n useEffect(() => {\n if (!stdout?.isTTY) return;\n stdout.write(\"\\u001B[?2004h\");\n return () => {\n stdout.write(\"\\u001B[?2004l\");\n };\n }, [stdout]);\n\n const expandPastes = (raw: string) =>\n raw.replace(PASTE_TOKEN_RE, (match, id) => pastesRef.current.get(Number(id)) ?? match);\n\n const clearPastes = () => {\n pastesRef.current.clear();\n pasteSeqRef.current = 0;\n lastPasteRef.current = null;\n const bracket = bracketRef.current;\n bracket.active = false;\n bracket.buffer = \"\";\n bracket.pending = \"\";\n };\n\n const edit = (next: string, nextCursor: number) => {\n // Editing a recalled history entry (or typing anything else) ends the\n // pristine history-browsing state, so up/down go back to moving the\n // cursor between lines instead of switching entries.\n const idx = historyIndexRef.current;\n if (idx !== null && next !== history[idx]) historyIndexRef.current = null;\n const clamped = Math.max(0, Math.min(nextCursor, next.length));\n valueRef.current = next;\n cursorRef.current = clamped;\n setValue(next);\n setCursor(clamped);\n setHighlight(0);\n setSuggestionsDismissed(false);\n };\n\n const normalizeNewlines = (text: string) => text.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\n // Collapse text into a placeholder when it crosses the paste thresholds,\n // otherwise insert it at the cursor.\n const collapseOrInsert = (text: string) => {\n const currentValue = valueRef.current;\n const currentCursor = cursorRef.current;\n const lineCount = text.split(\"\\n\").length;\n if (lineCount >= PASTE_COLLAPSE_MIN_LINES || text.length >= PASTE_COLLAPSE_MIN_CHARS) {\n const id = ++pasteSeqRef.current;\n pastesRef.current.set(id, text);\n const token = pasteToken(id, lineCount);\n const nextCursor = currentCursor + token.length;\n edit(\n currentValue.slice(0, currentCursor) + token + currentValue.slice(currentCursor),\n nextCursor,\n );\n lastPasteRef.current = { id, token, cursor: nextCursor, time: Date.now() };\n return;\n }\n edit(\n currentValue.slice(0, currentCursor) + text + currentValue.slice(currentCursor),\n currentCursor + text.length,\n );\n };\n\n const insertPlainText = (rawText: string) => {\n const text = normalizeNewlines(rawText);\n const currentValue = valueRef.current;\n const currentCursor = cursorRef.current;\n // Chunked paste without bracket markers: the first chunk collapsed and\n // the terminal keeps feeding the rest. Fold follow-up chunks into the\n // same paste entry (and refresh the placeholder's line count) instead\n // of leaking them into the editable text.\n const last = lastPasteRef.current;\n if (\n last &&\n Date.now() - last.time <= PASTE_MERGE_WINDOW_MS &&\n currentCursor === last.cursor &&\n currentValue.endsWith(last.token, currentCursor) &&\n (text.includes(\"\\n\") || text.length >= PASTE_MERGE_MIN_CHARS)\n ) {\n const merged = (pastesRef.current.get(last.id) ?? \"\") + text;\n pastesRef.current.set(last.id, merged);\n const token = pasteToken(last.id, merged.split(\"\\n\").length);\n const start = currentCursor - last.token.length;\n const nextCursor = start + token.length;\n edit(currentValue.slice(0, start) + token + currentValue.slice(currentCursor), nextCursor);\n lastPasteRef.current = { id: last.id, token, cursor: nextCursor, time: Date.now() };\n return;\n }\n collapseOrInsert(text);\n };\n\n // End the bracket early (a key arrived mid-paste, or the terminal never\n // sent the end marker): collapse whatever was buffered.\n const flushBracketPaste = () => {\n const bracket = bracketRef.current;\n const content = bracket.buffer;\n bracket.active = false;\n bracket.buffer = \"\";\n bracket.pending = \"\";\n if (content.length > 0) collapseOrInsert(normalizeNewlines(content));\n };\n\n const applyPasteSegments = (segments: PasteSegment[]) => {\n if (search) {\n // A paste landing during reverse search extends the query.\n const query = search.query + normalizeNewlines(segments.map((seg) => seg.text).join(\"\"));\n setSearch({ query, match: findHistoryMatch(history, query, history.length - 1, -1) });\n return;\n }\n for (const seg of segments) {\n if (seg.type === \"paste\") {\n collapseOrInsert(normalizeNewlines(seg.text));\n } else {\n insertPlainText(seg.text);\n }\n }\n };\n\n useEffect(() => {\n if (refill && refill.seq !== refillSeqRef.current) {\n refillSeqRef.current = refill.seq;\n edit(refill.text, refill.text.length);\n }\n });\n\n const suggestionsEnabled = !isStreaming && !disabled && !suggestionsDismissed && !search;\n const suggestions = suggestionsEnabled && commands ? filterCommands(value, commands) : [];\n\n useEffect(() => {\n if (!suggestionsEnabled || !cwd) {\n setPathSuggestions([]);\n return;\n }\n const token = extractAtToken(value, cursor);\n if (!token) {\n setPathSuggestions([]);\n return;\n }\n let cancelled = false;\n void suggestPaths(token.token, cwd).then((result) => {\n if (!cancelled) setPathSuggestions(result);\n });\n return () => {\n cancelled = true;\n };\n }, [value, cursor, cwd, suggestionsEnabled]);\n\n const showPathSuggestions = suggestions.length === 0 && pathSuggestions.length > 0;\n const suggestionCount = suggestions.length > 0 ? suggestions.length : pathSuggestions.length;\n const activeIndex = suggestionCount === 0 ? 0 : Math.min(highlight, suggestionCount - 1);\n\n const completeHighlighted = () => {\n if (suggestions.length > 0) {\n const cmd = suggestions[activeIndex];\n if (!cmd) return;\n const text = `/${cmd.name} `;\n edit(text, text.length);\n return;\n }\n const sugg = pathSuggestions[activeIndex];\n const token = extractAtToken(value, cursor);\n if (!sugg || !token) return;\n const replacement = `@${sugg.path}${sugg.isDir ? \"\" : \" \"}`;\n edit(\n value.slice(0, token.start) + replacement + value.slice(token.end),\n token.start + replacement.length,\n );\n };\n\n useInput((input, key) => {\n // Bracketed-paste state machine, before every other key handling so a\n // paste split across several input events is reassembled first and no\n // key (Enter included) fires mid-paste.\n if (!disabled) {\n const bracket = bracketRef.current;\n const feedable = input.length > 0 && !key.ctrl && !key.meta;\n if (bracket.active && (!feedable || input === \"\\r\")) {\n flushBracketPaste();\n // A bare \\r mid-paste is swallowed, never a half-paste submit; any\n // other key falls through and is handled normally below.\n if (feedable) return;\n }\n if (feedable) {\n const segments = feedBracketedPaste(bracket, input);\n if (segments === null) return;\n const only = segments.length === 1 ? segments[0] : undefined;\n if (!only || only.type !== \"text\" || only.text !== input) {\n applyPasteSegments(segments);\n return;\n }\n // Untouched plain text: fall through to the normal handling.\n } else {\n bracket.pending = \"\";\n }\n }\n // Ctrl+R: bash-style reverse history search. Entering remembers the\n // current input so cancel (Esc/Ctrl+C/Ctrl+G) can restore it.\n if (key.ctrl && input === \"r\") {\n if (isStreaming || disabled) return;\n if (search) {\n // Already searching: jump to the next older match (stops at the end).\n const from = (search.match ?? history.length) - 1;\n const older = findHistoryMatch(history, search.query, from, -1);\n if (older !== null) setSearch({ ...search, match: older });\n } else {\n searchSavedRef.current = { value, cursor };\n setSearch({ query: \"\", match: history.length > 0 ? history.length - 1 : null });\n }\n return;\n }\n if (search) {\n const exitSearch = (accept: boolean) => {\n const saved = searchSavedRef.current;\n setSearch(null);\n searchSavedRef.current = null;\n const match = accept && search.match !== null ? history[search.match] : undefined;\n if (match !== undefined) {\n edit(match, match.length);\n } else if (saved) {\n edit(saved.value, saved.cursor);\n }\n };\n if (key.escape || (key.ctrl && (input === \"c\" || input === \"g\"))) {\n exitSearch(false);\n return;\n }\n if (key.return) {\n exitSearch(true);\n return;\n }\n // A query change always re-searches from the newest entry backwards.\n const requery = (query: string) =>\n setSearch({ query, match: findHistoryMatch(history, query, history.length - 1, -1) });\n if (key.backspace || key.delete) {\n requery(search.query.slice(0, -1));\n return;\n }\n if (key.upArrow) {\n const from = (search.match ?? history.length) - 1;\n const older = findHistoryMatch(history, search.query, from, -1);\n if (older !== null) setSearch({ ...search, match: older });\n return;\n }\n if (key.downArrow) {\n if (search.match !== null) {\n const newer = findHistoryMatch(history, search.query, search.match + 1, 1);\n if (newer !== null) setSearch({ ...search, match: newer });\n }\n return;\n }\n if (input && !key.ctrl && !key.meta) {\n const text = input.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n requery(search.query + text);\n }\n // Every other key (Tab, arrows, ctrl editing keys, ...) is ignored.\n return;\n }\n if (key.ctrl && input === \"c\") {\n if (isStreaming || disabled) {\n onInterrupt();\n } else {\n edit(\"\", 0);\n clearPastes();\n historyIndexRef.current = null;\n }\n return;\n }\n if (key.ctrl && input === \"d\") {\n onExit();\n return;\n }\n // Alt+V is the reliable binding: Windows Terminal (and cmd's conhost)\n // intercept Ctrl+V as their own paste, so the key never reaches us.\n if ((key.meta || key.ctrl) && input === \"v\") {\n onPasteImage?.();\n return;\n }\n if (disabled) return;\n if (key.escape) {\n // While streaming, Esc is the Repl-level interrupt; idle Esc only\n // dismisses suggestions here (double-Esc editing lives in the Repl).\n if (!isStreaming && suggestionCount > 0) setSuggestionsDismissed(true);\n return;\n }\n if (key.return) {\n // Backslash immediately before the cursor + Enter: universal manual\n // newline (works on every terminal, Claude-Code style).\n const currentValue = valueRef.current;\n const currentCursor = cursorRef.current;\n if (currentValue[currentCursor - 1] === \"\\\\\") {\n edit(\n `${currentValue.slice(0, currentCursor - 1)}\\n${currentValue.slice(currentCursor)}`,\n currentCursor,\n );\n return;\n }\n const text = expandPastes(currentValue).trim();\n if (text.length > 0) {\n // Slash commands are ephemeral; keep them out of the history.\n if (!text.startsWith(\"/\")) setHistory((prev) => [...prev, text]);\n onSubmit(text);\n }\n edit(\"\", 0);\n clearPastes();\n historyIndexRef.current = null;\n draftRef.current = \"\";\n return;\n }\n // Ctrl+J arrives as a raw \\n and Alt+Enter as ESC+CR (Ink strips the ESC).\n if (input === \"\\n\" || input === \"\\r\") {\n edit(`${value.slice(0, cursor)}\\n${value.slice(cursor)}`, cursor + 1);\n return;\n }\n if (key.tab) {\n // Shift+Tab cycles permission modes at the Repl level; never complete.\n if (key.shift) return;\n if (suggestionCount > 0) {\n completeHighlighted();\n return;\n }\n } else if (key.upArrow) {\n // Pristine history browsing beats suggestion cycling: a recalled\n // slash command activates the suggestion menu and would otherwise\n // trap the arrows in it.\n if (historyIndexRef.current !== null) {\n if (historyIndexRef.current > 0) {\n historyIndexRef.current -= 1;\n const entry = history[historyIndexRef.current] ?? \"\";\n edit(entry, entry.length);\n }\n return;\n }\n if (suggestionCount > 0) {\n setHighlight((prev) => (prev - 1 + suggestionCount) % suggestionCount);\n return;\n }\n // Own (or edited) text: move the cursor between lines first.\n const moved = moveCursorLines(value, cursor, -1);\n if (moved !== null) {\n setCursor(moved);\n return;\n }\n if (history.length === 0) return;\n draftRef.current = value;\n historyIndexRef.current = history.length - 1;\n const entry = history[historyIndexRef.current] ?? \"\";\n edit(entry, entry.length);\n return;\n } else if (key.downArrow) {\n if (historyIndexRef.current !== null) {\n if (historyIndexRef.current < history.length - 1) {\n historyIndexRef.current += 1;\n const entry = history[historyIndexRef.current] ?? \"\";\n edit(entry, entry.length);\n } else {\n historyIndexRef.current = null;\n edit(draftRef.current, draftRef.current.length);\n }\n return;\n }\n if (suggestionCount > 0) {\n setHighlight((prev) => (prev + 1) % suggestionCount);\n return;\n }\n const moved = moveCursorLines(value, cursor, 1);\n if (moved !== null) setCursor(moved);\n return;\n } else if (key.leftArrow) {\n setCursor((prev) => Math.max(0, prev - 1));\n return;\n } else if (key.rightArrow) {\n if (suggestionCount > 0 && cursor === value.length) {\n completeHighlighted();\n } else {\n setCursor((prev) => Math.min(value.length, prev + 1));\n }\n return;\n }\n if (key.ctrl && input === \"a\") {\n setCursor(0);\n return;\n }\n if (key.ctrl && input === \"e\") {\n setCursor(value.length);\n return;\n }\n if (key.ctrl && input === \"u\") {\n edit(value.slice(cursor), 0);\n return;\n }\n if (key.ctrl && input === \"k\") {\n edit(value.slice(0, cursor), cursor);\n return;\n }\n if (key.ctrl && input === \"w\") {\n const trimmed = value.slice(0, cursor).replace(/\\s+$/, \"\");\n const wordStart = trimmed.search(/\\S+$/);\n const next = value.slice(0, wordStart === -1 ? 0 : wordStart) + value.slice(cursor);\n edit(next, wordStart === -1 ? 0 : wordStart);\n return;\n }\n // Ink maps both \\b and \\x7f/Delete-key to backspace/delete; real terminals send\n // \\x7f for Backspace, so both act as delete-before-cursor here.\n if (key.backspace || key.delete) {\n if (cursor === 0) return;\n // A placeholder immediately before the cursor is deleted as a unit so\n // it can never be half-removed (which would break expansion).\n let remove = 1;\n for (const match of value.matchAll(PASTE_TOKEN_RE)) {\n if (match.index + match[0].length === cursor) {\n remove = match[0].length;\n const id = Number(match[1]);\n pastesRef.current.delete(id);\n if (lastPasteRef.current?.id === id) lastPasteRef.current = null;\n break;\n }\n }\n edit(value.slice(0, cursor - remove) + value.slice(cursor), cursor - remove);\n return;\n }\n if (input && !key.ctrl && !key.meta) {\n insertPlainText(input);\n }\n });\n\n const before = value.slice(0, cursor);\n const at = value[cursor];\n const after = value.slice(cursor + 1);\n // A newline under the cursor is shown as an inverse space at the line end,\n // with the newline itself rendered after it. The (invisible) paste-token\n // delimiter also yields an inverse space so the cursor stays visible.\n const cursorChar = at === \"\\n\" || at === undefined || at === PASTE_DELIM ? \" \" : at;\n const tail = (at === \"\\n\" ? \"\\n\" : \"\") + stylePasteTokens(after);\n\n // One pre-styled string in a single Text node. Sibling Text nodes wrap\n // independently (stranding the cursor on its own line on soft-wrap), and\n // inserting/removing children inside ink-text skips Yoga's dirty marking\n // (ink's insertBeforeNode early-return), leaving the node measured at a\n // stale width so text spills over the border. A lone string child only\n // ever updates nodeValue, which always re-measures.\n const styled = search\n ? `\\u001B[36m(reverse-search) \\u001B[39m'${search.query}': ${\n search.match === null\n ? \"\\u001B[2mno match\\u001B[22m\\u001B[7m \\u001B[27m\"\n : `${history[search.match]}\\u001B[7m \\u001B[27m`\n }`\n : `\\u001B[36m❯ \\u001B[39m${stylePasteTokens(before)}\\u001B[7m${cursorChar}\\u001B[27m${tail}`;\n\n return (\n <Box flexDirection=\"column\">\n <Box borderStyle=\"round\" borderColor=\"gray\" paddingX={1}>\n <Text>{styled}</Text>\n </Box>\n {suggestions.length > 0 && (\n <Box flexDirection=\"column\" paddingLeft={2}>\n {suggestions.map((cmd, index) => {\n const label = cmd.usage ?? `/${cmd.name}`;\n return index === activeIndex ? (\n <Text key={cmd.name} bold inverse>{`${label} - ${cmd.description}`}</Text>\n ) : (\n <Text key={cmd.name}>\n <Text color=\"cyan\">{label}</Text>\n <Text dimColor>{` - ${cmd.description}`}</Text>\n </Text>\n );\n })}\n </Box>\n )}\n {showPathSuggestions && (\n <Box flexDirection=\"column\" paddingLeft={2}>\n {pathSuggestions.map((sugg, index) =>\n index === activeIndex ? (\n <Text key={sugg.path} bold inverse>{`@${sugg.path}`}</Text>\n ) : (\n <Text key={sugg.path}>\n <Text color=\"cyan\">{`@${sugg.path}`}</Text>\n {sugg.isDir && <Text dimColor> - directory</Text>}\n </Text>\n ),\n )}\n </Box>\n )}\n </Box>\n );\n}\n","import { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { SKIP_DIRS, createIgnorePredicate } from \"../tools/fs/util\";\nimport { MAX_SUGGESTIONS } from \"./commands/suggest\";\n\n// Lazy scan: only the single directory the typed prefix points into is read,\n// and no more than this many entries are examined per lookup.\nexport const MAX_SCAN_ENTRIES = 2000;\n\nexport interface AtToken {\n // Path prefix typed after the \"@\".\n token: string;\n // Index of the \"@\" in the input value.\n start: number;\n // Cursor position (end of the token).\n end: number;\n}\n\n// The \"@token\" immediately before the cursor: preceded by start-of-input or\n// whitespace, with no whitespace inside the token itself.\nexport function extractAtToken(value: string, cursor: number): AtToken | null {\n const before = value.slice(0, cursor);\n const match = /(?:^|\\s)@(\\S*)$/.exec(before);\n if (!match) return null;\n const token = match[1] ?? \"\";\n return { token, start: cursor - token.length - 1, end: cursor };\n}\n\nexport interface PathSuggestion {\n // Path relative to cwd; directories carry a trailing \"/\" so Tab descends.\n path: string;\n isDir: boolean;\n}\n\nexport async function suggestPaths(\n token: string,\n cwd: string,\n maxScanEntries: number = MAX_SCAN_ENTRIES,\n maxSuggestions: number = MAX_SUGGESTIONS,\n): Promise<PathSuggestion[]> {\n const normalized = token.replace(/\\\\/g, \"/\");\n const slash = normalized.lastIndexOf(\"/\");\n const dirPart = slash >= 0 ? normalized.slice(0, slash + 1) : \"\";\n const basePrefix = slash >= 0 ? normalized.slice(slash + 1) : normalized;\n if (dirPart.split(\"/\").some((segment) => SKIP_DIRS.has(segment))) return [];\n const dirAbs = path.resolve(cwd, dirPart === \"\" ? \".\" : dirPart);\n const entries = await readdir(dirAbs, { withFileTypes: true }).catch(() => null);\n if (!entries) return [];\n const ignore = createIgnorePredicate(cwd);\n const lower = basePrefix.toLowerCase();\n const matches: PathSuggestion[] = [];\n let scanned = 0;\n for (const entry of entries) {\n if (scanned >= maxScanEntries) break;\n scanned += 1;\n const isDir = entry.isDirectory();\n if (!isDir && !entry.isFile()) continue;\n if (isDir && SKIP_DIRS.has(entry.name)) continue;\n if (entry.name.startsWith(\".\") && !basePrefix.startsWith(\".\")) continue;\n if (!entry.name.toLowerCase().startsWith(lower)) continue;\n if (ignore?.(path.join(dirAbs, entry.name), isDir)) continue;\n matches.push({ path: `${dirPart}${entry.name}${isDir ? \"/\" : \"\"}`, isDir });\n }\n matches.sort((a, b) => a.path.localeCompare(b.path));\n return matches.slice(0, maxSuggestions);\n}\n","import { Box, Text } from \"ink\";\nimport { useInput } from \"../use-input\";\n\nexport type ExitPlanDecision = \"yes\" | \"no\";\n\ninterface ExitPlanPromptProps {\n onDecision(decision: ExitPlanDecision): void;\n}\n\nexport function ExitPlanPrompt({ onDecision }: ExitPlanPromptProps) {\n useInput((input, key) => {\n const ch = input.toLowerCase();\n if (ch === \"y\") onDecision(\"yes\");\n else if (ch === \"n\" || key.escape) onDecision(\"no\");\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Text bold color=\"cyan\">\n Plan ready (plan mode)\n </Text>\n <Text>The plan above was produced without making any changes.</Text>\n <Text>[y] approve and execute [n] keep refining (Esc = n)</Text>\n </Box>\n );\n}\n","import { Box, Static, Text, useStdout } from \"ink\";\nimport { memo } from \"react\";\nimport type { DiffLine } from \"../diff-preview\";\nimport { renderMarkdown } from \"../markdown\";\nimport { DiffLines } from \"./DiffLines\";\n\nexport interface DisplayMessage {\n id: number;\n role: \"user\" | \"assistant\" | \"assistant-cont\" | \"system\" | \"tool\";\n text: string;\n note?: string;\n // Structured diff lines (e.g. from /diff) rendered with per-line colors\n // below the message text instead of as one flat block.\n diff?: DiffLine[];\n // tight = no bottom margin; used for mid-turn continuation chunks so a\n // long streamed answer committed in pieces still reads as one block.\n tight?: boolean;\n // Set on the last chunk of a turn cut short with Esc: renders a dim\n // \"[interrupted]\" marker after the text. Display-only — the session store\n // carries its own marker (see AgentLoop.persistInterrupted).\n interrupted?: boolean;\n}\n\nconst roleStyles: Record<\n Exclude<DisplayMessage[\"role\"], \"assistant-cont\" | \"user\" | \"tool\">,\n { label: string; color: string }\n> = {\n assistant: { label: \"✦ star\", color: \"green\" },\n system: { label: \"● system\", color: \"yellow\" },\n};\n\nconst interruptedMarker = (text: string) => (\n <Text dimColor>{text.length > 0 ? \" [interrupted]\" : \"[interrupted]\"}</Text>\n);\n\nexport const MessageList = memo(function MessageList({ messages }: { messages: DisplayMessage[] }) {\n const { stdout } = useStdout();\n const termWidth = stdout.columns ?? 80;\n return (\n <Static items={messages}>\n {(message) => {\n const marginBottom = message.tight ? 0 : 1;\n if (message.role === \"assistant-cont\") {\n return (\n <Box key={message.id} flexDirection=\"column\" marginBottom={marginBottom}>\n <Text color=\"green\">\n {renderMarkdown(message.text, \"32\", termWidth)}\n {message.interrupted && interruptedMarker(message.text)}\n </Text>\n </Box>\n );\n }\n if (message.role === \"user\") {\n return (\n <Box key={message.id} flexDirection=\"column\" marginBottom={marginBottom}>\n <Box>\n <Text bold color=\"cyan\">\n {\"❯ \"}\n </Text>\n <Text color=\"cyan\">\n {message.text}\n {message.interrupted && interruptedMarker(message.text)}\n </Text>\n </Box>\n {message.note && <Text dimColor> {message.note}</Text>}\n </Box>\n );\n }\n if (message.role === \"tool\") {\n // The card text carries its own tool icon + name header, so no\n // separate label line is needed.\n return (\n <Box key={message.id} flexDirection=\"column\" marginBottom={marginBottom}>\n <Text color=\"magenta\">{message.text}</Text>\n </Box>\n );\n }\n const style = roleStyles[message.role];\n return (\n <Box key={message.id} flexDirection=\"column\" marginBottom={marginBottom}>\n <Text bold color={style.color}>\n {style.label}\n </Text>\n <Text color={style.color}>\n {message.role === \"assistant\"\n ? renderMarkdown(message.text, \"32\", termWidth)\n : message.text}\n {message.interrupted && interruptedMarker(message.text)}\n </Text>\n {message.diff && <DiffLines lines={message.diff} />}\n {message.note && <Text dimColor>{message.note}</Text>}\n </Box>\n );\n }}\n </Static>\n );\n});\n","import { Text } from \"ink\";\nimport type { DiffLine } from \"../diff-preview\";\nimport { toTerminalSafe } from \"../terminal-text\";\n\nexport function DiffLineView({ line }: { line: DiffLine }) {\n // Diff content is model/tool-controlled text rendered outside the streaming\n // ingestion path, so it is normalized here at the render layer instead.\n const text = toTerminalSafe(line.text);\n if (line.kind === \"add\") return <Text color=\"green\">+ {text}</Text>;\n if (line.kind === \"del\") return <Text color=\"red\">- {text}</Text>;\n if (line.kind === \"marker\") return <Text dimColor>{text}</Text>;\n return <Text dimColor> {text}</Text>;\n}\n\nexport function DiffLines({ lines }: { lines: DiffLine[] }) {\n return (\n <>\n {lines.map((line, index) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: diff lines have no stable identity\n <DiffLineView key={index} line={line} />\n ))}\n </>\n );\n}\n","import { Box, Text } from \"ink\";\nimport type { PermissionRequest } from \"../../permissions/types\";\nimport type { DiffPreview } from \"../diff-preview\";\nimport { summarizeArgs } from \"../format\";\nimport { toTerminalSafe } from \"../terminal-text\";\nimport { useInput } from \"../use-input\";\nimport { DiffLines } from \"./DiffLines\";\n\nexport type PermissionDecision = \"yes\" | \"no\" | \"always\";\n\ninterface PermissionPromptProps {\n request: PermissionRequest;\n preview?: DiffPreview | null;\n onDecision(decision: PermissionDecision): void;\n}\n\n// Bash commands render in full and wrap: a tail-truncated command would let a\n// malicious payload hide past the visible cutoff. Only absurdly long commands\n// are middle-truncated, keeping both ends in view.\nconst BASH_COMMAND_MAX = 1000;\n\nfunction middleTruncate(text: string, max: number): string {\n if (text.length <= max) return text;\n const half = Math.floor((max - 1) / 2);\n return `${text.slice(0, half)}…${text.slice(text.length - half)}`;\n}\n\nfunction bashCommand(args: unknown): string | null {\n if (typeof args !== \"object\" || args === null) return null;\n const command = (args as { command?: unknown }).command;\n return typeof command === \"string\" ? command : null;\n}\n\nexport function PermissionPrompt({ request, preview, onDecision }: PermissionPromptProps) {\n useInput((input) => {\n const ch = input.toLowerCase();\n if (ch === \"y\") onDecision(\"yes\");\n else if (ch === \"n\") onDecision(\"no\");\n else if (ch === \"a\") onDecision(\"always\");\n });\n\n const command = request.toolName === \"bash\" ? bashCommand(request.args) : null;\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text bold color=\"yellow\">\n Permission required: {request.toolName} ({request.level})\n </Text>\n {preview ? (\n <Box flexDirection=\"column\">\n <Text dimColor>\n {preview.type === \"new-file\" ? \"New file: \" : \"\"}\n {toTerminalSafe(preview.label)}\n </Text>\n <DiffLines lines={preview.lines} />\n </Box>\n ) : command !== null ? (\n <Text>{toTerminalSafe(middleTruncate(command, BASH_COMMAND_MAX))}</Text>\n ) : (\n <Text>{toTerminalSafe(summarizeArgs(request.args))}</Text>\n )}\n <Text>[y] allow [n] deny [a] always (saved to config)</Text>\n </Box>\n );\n}\n","import { Box, Text } from \"ink\";\nimport type { DiffLine } from \"../diff-preview\";\nimport { useInput } from \"../use-input\";\nimport { DiffLines } from \"./DiffLines\";\n\nexport type RewindDecision = \"yes\" | \"no\";\n\nexport interface ConfirmDiff {\n label: string;\n lines: DiffLine[];\n}\n\ninterface RewindConfirmPromptProps {\n summary: string;\n title?: string;\n confirmLabel?: string;\n diffs?: ConfirmDiff[];\n onDecision(decision: RewindDecision): void;\n}\n\nexport function RewindConfirmPrompt({\n summary,\n title = \"Rewind checkpoints\",\n confirmLabel = \"rewind\",\n diffs,\n onDecision,\n}: RewindConfirmPromptProps) {\n useInput((input, key) => {\n const ch = input.toLowerCase();\n if (ch === \"y\") onDecision(\"yes\");\n else if (ch === \"n\" || key.escape) onDecision(\"no\");\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text bold color=\"yellow\">\n {title}\n </Text>\n <Text>{summary}</Text>\n {diffs?.map((diff) => (\n <Box key={diff.label} flexDirection=\"column\">\n <Text dimColor>{diff.label}</Text>\n <DiffLines lines={diff.lines} />\n </Box>\n ))}\n <Text>[y] {confirmLabel} [n] cancel (Esc = n)</Text>\n </Box>\n );\n}\n","import { Box, Text, useStdout } from \"ink\";\nimport { memo } from \"react\";\nimport { formatDollars } from \"../cost\";\nimport { folderIcon } from \"../icons\";\nimport { toTerminalSafe } from \"../terminal-text\";\n\ninterface StatusBarProps {\n cwd: string;\n model: string;\n permissionMode: string;\n tokens: number;\n // Git branch, refreshed on turn boundaries by the parent (null = not a repo).\n gitBranch?: string | null;\n // Context window usage in percent; null when unknown (non-loop backend).\n contextPercent?: number | null;\n // Prompt cache hit rate 0-100; null when the provider never reported cache\n // fields (rendered as \"Not provided\").\n cachePercent?: number | null;\n sessionCostUsd?: number | null;\n // Labels of currently running background tasks (description or command).\n backgroundTasks?: string[];\n}\n\nconst BG_LABEL_MAX = 40;\nconst WIDE_COLUMNS = 120;\n\nfunction cwdLabel(cwd: string, wide: boolean): string {\n if (wide) return cwd;\n const base = cwd\n .replace(/[\\\\/]+$/, \"\")\n .split(/[\\\\/]/)\n .pop();\n return base && base.length > 0 ? base : cwd;\n}\n\nexport const StatusBar = memo(function StatusBar({\n cwd,\n model,\n permissionMode,\n tokens,\n gitBranch,\n contextPercent,\n cachePercent,\n sessionCostUsd,\n backgroundTasks = [],\n}: StatusBarProps) {\n const { stdout } = useStdout();\n const wide = (stdout?.columns ?? 80) >= WIDE_COLUMNS;\n // Task commands/descriptions are model-influenced; escape before display.\n const joined = backgroundTasks.map((label) => toTerminalSafe(label)).join(\", \");\n const labels = joined.length > BG_LABEL_MAX ? `${joined.slice(0, BG_LABEL_MAX)}…` : joined;\n return (\n <Box justifyContent=\"space-between\">\n <Text dimColor>\n {folderIcon}\n {cwdLabel(cwd, wide)}\n {gitBranch ? ` [${gitBranch}]` : \"\"}\n </Text>\n {backgroundTasks.length > 0 && (\n <Text color=\"yellow\">\n bg: {backgroundTasks.length} ({labels})\n </Text>\n )}\n <Text dimColor>✦ {model}</Text>\n {contextPercent != null && <Text dimColor>ctx: {contextPercent}%</Text>}\n <Text dimColor>cache: {cachePercent != null ? `${cachePercent}%` : \"Not provided\"}</Text>\n {sessionCostUsd != null && sessionCostUsd > 0 && (\n <Text dimColor>${formatDollars(sessionCostUsd)}</Text>\n )}\n <Text dimColor>{tokens} tokens</Text>\n <Text dimColor>mode: {permissionMode}</Text>\n </Box>\n );\n});\n","// Decorative icons with a terminal-capability fallback.\n//\n// Emoji glyphs are double-width only on terminals with real emoji support.\n// On GBK/CJK consoles and mintty without emoji fonts they render as narrow\n// single-cell fallback glyphs while Ink's width math (string-width) counts\n// them double — a line near the wrap boundary then occupies fewer terminal\n// rows than Ink counted, the frame erase overshoots, and every spinner tick\n// leaves the display scrambled (the \"scroll spam\" regression). Emoji icons\n// are therefore enabled only where the terminal is known to render them\n// double-width; elsewhere a plain single-width symbol set is used.\n// STAR_ICONS=emoji|plain overrides the detection.\n//\n// Plain-set rule: every glyph must have string-width 1, which means no\n// Emoji-property characters at all — string-width counts even text-presentation\n// emoji candidates (✔, ☰, ⚙, ↗…) as width 2. Stick to neutral/ambiguous\n// symbols (✦ ❯ ◦ ▸ ‣ ✧ ✎ ※ ◉ ≡ × § ¶ …).\n\nexport type IconMode = \"emoji\" | \"plain\";\n\nconst EMOJI_TERM_PROGRAMS = new Set([\n \"vscode\",\n \"WezTerm\",\n \"iTerm.app\",\n \"Apple_Terminal\",\n \"ghostty\",\n \"kitty\",\n \"Hyper\",\n \"WarpTerminal\",\n]);\n\nexport function resolveIconMode(env: NodeJS.ProcessEnv = process.env): IconMode {\n const override = env.STAR_ICONS;\n if (override === \"emoji\" || override === \"plain\") return override;\n if (env.WT_SESSION) return \"emoji\"; // Windows Terminal\n if (EMOJI_TERM_PROGRAMS.has(env.TERM_PROGRAM ?? \"\")) return \"emoji\";\n const term = env.TERM ?? \"\";\n if (term.includes(\"kitty\") || term.includes(\"alacritty\")) return \"emoji\";\n return \"plain\";\n}\n\nexport const EMOJI_TOOL_ICONS: Record<string, string> = {\n bash: \"💻\",\n read_file: \"📄\",\n write_file: \"📝\",\n edit_file: \"✏️\",\n glob: \"📂\",\n grep: \"🔍\",\n web_search: \"🔎\",\n web_fetch: \"🌐\",\n todo_write: \"📋\",\n todo_read: \"📋\",\n task_list: \"🧵\",\n task_output: \"🧵\",\n task_kill: \"🛑\",\n subagent: \"🤖\",\n skill: \"✨\",\n remember: \"🧠\",\n};\n\nexport const PLAIN_TOOL_ICONS: Record<string, string> = {\n bash: \"$\",\n read_file: \"≡\",\n write_file: \"+\",\n edit_file: \"✎\",\n glob: \"*\",\n grep: \"/\",\n web_search: \"?\",\n web_fetch: \"⇓\",\n todo_write: \"‣\",\n todo_read: \"‣\",\n task_list: \"¶\",\n task_output: \"¶\",\n task_kill: \"×\",\n subagent: \"◉\",\n skill: \"✧\",\n remember: \"※\",\n};\n\nconst iconMode = resolveIconMode();\n\nexport function toolIcon(name: string): string {\n const map = iconMode === \"emoji\" ? EMOJI_TOOL_ICONS : PLAIN_TOOL_ICONS;\n return map[name] ?? (iconMode === \"emoji\" ? \"🔧\" : \"▸\");\n}\n\n// 💭 / ✧ — thinking spinner label and the collapsed thought summary.\nexport const thinkingIcon = iconMode === \"emoji\" ? \"💭\" : \"✧\";\n\n// 📁 prefix for the status-bar cwd; plain mode keeps the bare path.\nexport const folderIcon = iconMode === \"emoji\" ? \"📁 \" : \"\";\n","import { Box, Text, useStdout } from \"ink\";\nimport { memo } from \"react\";\nimport { renderMarkdown } from \"../markdown\";\n\nexport const StreamingMessage = memo(function StreamingMessage({\n text,\n continuation,\n}: { text: string; continuation?: boolean }) {\n const { stdout } = useStdout();\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n {!continuation && (\n <Text bold color=\"green\">\n ✦ star\n </Text>\n )}\n {/* The outer green stays: styled spans reset and re-open the base color. */}\n <Text color=\"green\">{renderMarkdown(text, \"32\", stdout.columns ?? 80)}</Text>\n </Box>\n );\n});\n","import { Box, Text } from \"ink\";\n\nimport { thinkingIcon } from \"../icons\";\n\nexport const SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\nexport const REASONING_TAIL_LENGTH = 200;\nexport const THOUGHT_SUMMARY_LENGTH = 100;\n\nexport function truncateTail(text: string, max: number): string {\n const flat = text.replace(/\\s+/g, \" \").trim();\n if (flat.length <= max) return flat;\n return `…${flat.slice(flat.length - max)}`;\n}\n\n// The spinner frame is driven by the caller's render ticker (see cli/ticker.ts);\n// keeping no internal interval avoids a second full-tree Ink rewrite per frame.\n// `activity` replaces the default label, e.g. while a tool call is executing.\nexport function ThinkingIndicator({\n reasoning,\n frame = 0,\n activity,\n}: { reasoning?: string; frame?: number; activity?: string }) {\n const tail = reasoning ? truncateTail(reasoning, REASONING_TAIL_LENGTH) : \"\";\n const spinner = SPINNER_FRAMES[frame % SPINNER_FRAMES.length];\n // Tool-running activities carry their own per-tool icon in the label\n // (see repl.tsx), so the 💭 prefix only applies while thinking.\n const label = activity ?? `${thinkingIcon} star is thinking…`;\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>\n {spinner} {label}\n </Text>\n {tail !== \"\" && (\n <Text dimColor>\n {\" \"}\n {tail}\n </Text>\n )}\n </Box>\n );\n}\n","import { Box, Text } from \"ink\";\nimport type { TodoItem } from \"../../tools/todo\";\nimport { toTerminalSafe } from \"../terminal-text\";\n\nconst SYMBOLS: Record<TodoItem[\"status\"], string> = {\n pending: \"○\",\n in_progress: \"◐\",\n done: \"●\",\n};\n\n// The panel lives in Ink's live region, so its height must stay bounded:\n// an unbounded list can reach terminal height, at which point Ink repaints\n// the entire static history on every frame (the \"scroll spam\" bug).\nexport const MAX_VISIBLE_TODOS = 10;\n\nexport interface TodoWindow {\n items: TodoItem[];\n hiddenBefore: number;\n hiddenAfter: number;\n}\n\n// Window of at most `max` items. When the list overflows, the window starts\n// at the in-progress item (or the list head) so the active task and what\n// comes next stay visible.\nexport function visibleTodoWindow(\n todos: readonly TodoItem[],\n max: number = MAX_VISIBLE_TODOS,\n): TodoWindow {\n if (todos.length <= max) return { items: [...todos], hiddenBefore: 0, hiddenAfter: 0 };\n const active = todos.findIndex((todo) => todo.status === \"in_progress\");\n const start = active > 0 ? Math.min(active, todos.length - max) : 0;\n const items = todos.slice(start, start + max);\n return {\n items,\n hiddenBefore: start,\n hiddenAfter: todos.length - start - items.length,\n };\n}\n\n// Persistent todo list rendered in the live region above the input box, so\n// it survives spinner/thinking redraws; finished items are dimmed.\nexport function TodoPanel({ todos }: { todos: TodoItem[] }) {\n if (todos.length === 0) return null;\n const { items, hiddenBefore, hiddenAfter } = visibleTodoWindow(todos);\n return (\n <Box flexDirection=\"column\">\n {hiddenBefore > 0 && <Text dimColor> … {hiddenBefore} more above</Text>}\n {items.map((todo) => (\n <Text\n key={todo.id}\n dimColor={todo.status === \"done\"}\n strikethrough={todo.status === \"done\"}\n color={todo.status === \"in_progress\" ? \"cyan\" : undefined}\n >\n {SYMBOLS[todo.status]} {toTerminalSafe(todo.title)}\n </Text>\n ))}\n {hiddenAfter > 0 && <Text dimColor> … {hiddenAfter} more</Text>}\n </Box>\n );\n}\n","import { previewLines } from \"../format\";\nimport { toolIcon } from \"../icons\";\nimport { toTerminalSafe } from \"../terminal-text\";\n\nexport interface ToolCardData {\n id: string;\n name: string;\n argsSummary: string;\n result?: string;\n isError?: boolean;\n}\n\nexport function formatToolCard(card: ToolCardData): string {\n const header = `${toolIcon(card.name)} ${card.name} ${card.argsSummary}${card.isError ? \" [error]\" : \"\"}`;\n if (card.result === undefined) return header;\n const preview = previewLines(toTerminalSafe(card.result), 10);\n return `${header}\\n${preview.text}${preview.truncated ? \"\\n... (truncated)\" : \"\"}`;\n}\n","export const DOUBLE_ESC_WINDOW_MS = 600;\n\n// Two Esc presses within the window (while idle) trigger edit-last-message.\nexport function isDoubleEscape(\n previous: number | null,\n now: number,\n windowMs: number = DOUBLE_ESC_WINDOW_MS,\n): boolean {\n return previous !== null && now - previous <= windowMs;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { starHome } from \"../config/paths\";\n\nconst HISTORY_LIMIT = 50;\n// A line made of one repeated character (20+) is key-repeat garbage, not input.\nconst JUNK_ENTRY_PATTERN = /^(.)\\1{19,}$/;\n\nfunction historyPath(): string {\n return path.join(starHome(), \"history\");\n}\n\nfunction readLines(file: string): string[] {\n const raw = fs.readFileSync(file, \"utf8\");\n return raw\n .split(\"\\n\")\n .map((line) => line.replace(/\\r$/, \"\"))\n .filter((line) => line.trim().length > 0);\n}\n\nfunction writeHistory(file: string, lines: string[]): void {\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, `${lines.join(\"\\n\")}\\n`);\n}\n\nexport function isJunkHistoryEntry(line: string): boolean {\n return JUNK_ENTRY_PATTERN.test(line);\n}\n\n// Slash commands are ephemeral REPL actions, not reusable input.\nfunction isSkippableEntry(line: string): boolean {\n return isJunkHistoryEntry(line) || line.startsWith(\"/\");\n}\n\nexport function loadHistory(limit = HISTORY_LIMIT): string[] {\n try {\n const file = historyPath();\n const lines = readLines(file);\n const clean = lines.filter((line) => !isSkippableEntry(line));\n if (clean.length !== lines.length || clean.length > HISTORY_LIMIT) {\n // Self-heal: drop junk and enforce the cap so old polluted files recover.\n writeHistory(file, clean.slice(-HISTORY_LIMIT));\n }\n return clean.slice(-limit);\n } catch {\n return [];\n }\n}\n\nexport function appendHistory(entry: string): void {\n const line = entry.replace(/[\\r\\n]+/g, \" \").trim();\n if (line.length === 0 || isSkippableEntry(line)) return;\n try {\n const file = historyPath();\n let existing: string[] = [];\n try {\n existing = readLines(file);\n } catch {\n // Missing or unreadable history file starts fresh.\n }\n if (existing[existing.length - 1] === line) return;\n if (existing.length >= HISTORY_LIMIT) {\n writeHistory(file, [...existing.slice(-(HISTORY_LIMIT - 1)), line]);\n return;\n }\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.appendFileSync(file, `${line}\\n`);\n } catch {\n // History is best-effort and must never crash the REPL.\n }\n}\n","export const BELL = \"\\x07\";\n\nexport interface NotifyBellInput {\n enabled: boolean;\n thresholdSec: number;\n noNotifyEnv: boolean;\n interrupted?: boolean;\n // Turn duration; omit for events with no meaningful threshold (background\n // task completion always qualifies).\n elapsedMs?: number;\n}\n\nexport function shouldNotifyBell(input: NotifyBellInput, isTTY: boolean): boolean {\n if (!input.enabled || input.noNotifyEnv || !isTTY) return false;\n if (input.interrupted) return false;\n if (input.elapsedMs !== undefined && input.elapsedMs < input.thresholdSec * 1000) return false;\n return true;\n}\n\nexport interface NotifyBellDeps {\n write?: (text: string) => void;\n isTTY?: boolean;\n}\n\nexport function notifyBell(input: NotifyBellInput, deps: NotifyBellDeps = {}): boolean {\n const isTTY = deps.isTTY ?? Boolean(process.stdout.isTTY);\n if (!shouldNotifyBell(input, isTTY)) return false;\n (deps.write ?? ((text: string) => process.stdout.write(text)))(BELL);\n return true;\n}\n","import type { ImageInput } from \"../core/messages\";\n\nexport interface QueuedPrompt {\n // Stable id for keyed rendering of the queued list.\n id: number;\n text: string;\n images: ImageInput[];\n}\n\n// FIFO typeahead queue: prompts submitted while a turn is streaming wait here\n// and are auto-sent (in order) once the turn finishes.\nexport class PromptQueue {\n private items: QueuedPrompt[] = [];\n private nextId = 1;\n\n enqueue(prompt: { text: string; images: ImageInput[] }): number {\n this.items.push({ id: this.nextId++, ...prompt });\n return this.items.length;\n }\n\n dequeue(): QueuedPrompt | undefined {\n return this.items.shift();\n }\n\n // Empties the queue and returns what was dropped (for the \"cleared N\" note).\n clear(): QueuedPrompt[] {\n const removed = this.items;\n this.items = [];\n return removed;\n }\n\n get size(): number {\n return this.items.length;\n }\n\n list(): QueuedPrompt[] {\n return [...this.items];\n }\n}\n","import { isDangerousCommand } from \"../permissions/gate\";\nimport { bashTool } from \"../tools/bash\";\n\nexport const SHELL_BANG_DISPLAY_MAX_CHARS = 3000;\n\nexport type ShellBangOutcome =\n | {\n ok: true;\n command: string;\n output: string;\n isError: boolean;\n contextMessage: string;\n }\n | { ok: false; reason: \"empty\" | \"dangerous\" };\n\nexport function truncateShellOutput(\n output: string,\n max: number = SHELL_BANG_DISPLAY_MAX_CHARS,\n): string {\n if (output.length <= max) return output;\n const half = Math.floor(max / 2);\n return `${output.slice(0, half)}\\n... [${output.length - max} characters truncated] ...\\n${output.slice(-half)}`;\n}\n\nexport function buildShellContextMessage(command: string, output: string): string {\n return `The user ran \\`!${command}\\` directly in the shell (no permission prompt). Output:\\n${output}`;\n}\n\nexport async function executeShellBang(\n raw: string,\n cwd: string,\n signal?: AbortSignal,\n): Promise<ShellBangOutcome> {\n const command = raw.trim();\n if (!command) return { ok: false, reason: \"empty\" };\n if (isDangerousCommand(command)) return { ok: false, reason: \"dangerous\" };\n const result = await bashTool.execute({ command }, { cwd, abortSignal: signal });\n const output = truncateShellOutput(result.content);\n return {\n ok: true,\n command,\n output,\n isError: result.isError ?? false,\n contextMessage: buildShellContextMessage(command, output),\n };\n}\n","// Base system prompt shared by main.tsx (initial loop) and the REPL's\n// switchModel (rebuilt loop): syncSystemMessage re-derives the prompt from\n// opts.system every turn, so a rebuilt loop without it would silently drop\n// the core instructions whenever AGENTS.md/git/skills context exists.\nexport const SYSTEM_PROMPT = `You are Star CLI, an AI coding agent running in the user's terminal.\nYou help with software engineering tasks: reading, writing and editing code, running shell commands, and managing todos.\nBe concise and direct. Use tools when they help accomplish the task.\nFor 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.\nThe working directory is the user's project root; never touch files outside it without explicit instruction.\nFor 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.\nWhen a tool call or command fails, read the error output, work out the cause, and try again with a corrected or alternative approach — never repeat an identical failing call without changing something.\nNever 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.\nDo 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.\nNever end a reply by announcing what you will do next — either do it now with tool calls, or do not mention it. Narrating future actions is not progress.`;\n","export const TICK_MS = 100;\n\nexport interface FlushState {\n streamed: string;\n reasoning: string;\n}\n\n// Returns the next flush state, or null when nothing changed since prev,\n// so callers can skip the state update (and the full Ink re-render) entirely.\nexport function nextFlush(prev: FlushState, next: FlushState): FlushState | null {\n if (prev.streamed === next.streamed && prev.reasoning === next.reasoning) return null;\n return next;\n}\n\n// Single render ticker: one interval drives both stream flushes and the\n// spinner frame. Returns a stop function; the callback receives the tick count.\nexport function startTicker(onTick: (tick: number) => void, intervalMs = TICK_MS): () => void {\n let tick = 0;\n const timer = setInterval(() => {\n tick += 1;\n onTick(tick);\n }, intervalMs);\n return () => clearInterval(timer);\n}\n","const REGISTRY_URL = \"https://registry.npmjs.org/@cryer%2fstar-cli/latest\";\nconst TIMEOUT_MS = 5000;\n\nexport interface FetchResponse {\n ok: boolean;\n json(): Promise<unknown>;\n}\n\nexport type UpdateFetcher = (url: string) => Promise<FetchResponse>;\n\nasync function defaultFetcher(url: string): Promise<FetchResponse> {\n return fetch(url, { signal: AbortSignal.timeout(TIMEOUT_MS) });\n}\n\nexport function isNewerVersion(latest: string, current: string): boolean {\n const parse = (v: string) =>\n v\n .split(\".\")\n .slice(0, 3)\n .map((part) => Number.parseInt(part, 10));\n const a = parse(latest);\n const b = parse(current);\n for (let i = 0; i < 3; i++) {\n const x = a[i] ?? 0;\n const y = b[i] ?? 0;\n if (Number.isNaN(x) || Number.isNaN(y)) return false;\n if (x !== y) return x > y;\n }\n return false;\n}\n\nexport async function checkForUpdate(\n currentVersion: string,\n fetcher: UpdateFetcher = defaultFetcher,\n): Promise<string | null> {\n try {\n const res = await fetcher(REGISTRY_URL);\n if (!res.ok) return null;\n const data: unknown = await res.json();\n const latest =\n typeof data === \"object\" && data !== null ? (data as { version?: unknown }).version : null;\n if (typeof latest !== \"string\" || !isNewerVersion(latest, currentVersion)) return null;\n return `New version available: ${currentVersion} -> ${latest} — run: npm i -g @cryer/star-cli`;\n } catch {\n return null;\n }\n}\n","import fs from \"node:fs\";\nimport { parse } from \"smol-toml\";\nimport { loadEnvFile } from \"./env\";\nimport { globalConfigPath, projectConfigPath } from \"./paths\";\nimport { type CliOverrides, ConfigSchema, type StarConfig } from \"./schema\";\n\nconst PartialConfigSchema = ConfigSchema.partial();\n\ntype PartialConfig = ReturnType<typeof PartialConfigSchema.parse>;\n\nfunction parseTomlFile(content: string, filePath: string): PartialConfig {\n let raw: unknown;\n try {\n raw = parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to parse TOML in ${filePath}: ${message}`);\n }\n const result = PartialConfigSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(`Invalid config in ${filePath}: ${result.error.message}`);\n }\n return result.data;\n}\n\nfunction mergeConfig(base: PartialConfig, override: PartialConfig): PartialConfig {\n return { ...base, ...override };\n}\n\n// Keys a project-level .star/config.toml may set. Anything else (providers,\n// permissionMode, permissions, hooks, ...) stays global-only: a checked-out\n// repo must not be able to plant shell hooks, force yolo mode, or redirect\n// provider traffic to a key-harvesting endpoint.\nconst PROJECT_ALLOWED_KEYS = new Set([\n \"defaultModel\",\n \"models\",\n \"maxSteps\",\n \"contextMaxTokens\",\n \"compactThresholdTokens\",\n \"streamIdleTimeoutSec\",\n \"streamFirstChunkTimeoutSec\",\n \"streamMaxRetries\",\n \"maxAutoContinues\",\n \"contextCompaction\",\n \"sessionBudgetUsd\",\n \"notifyBell\",\n \"notifyBellThresholdSec\",\n \"doomLoopThreshold\",\n \"gitSnapshots\",\n]);\n\nfunction sanitizeProjectConfig(project: PartialConfig, filePath: string): PartialConfig {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(project)) {\n if (value === undefined) continue;\n if (PROJECT_ALLOWED_KEYS.has(key)) {\n sanitized[key] = value;\n } else {\n process.stderr.write(\n `[star] ignoring \"${key}\" in ${filePath}: project config cannot set this key\\n`,\n );\n }\n }\n return sanitized as PartialConfig;\n}\n\nfunction applyOverrides(config: PartialConfig, overrides?: CliOverrides): PartialConfig {\n if (!overrides) return config;\n const merged = { ...config };\n if (overrides.model !== undefined) merged.defaultModel = overrides.model;\n if (overrides.permissionMode !== undefined) merged.permissionMode = overrides.permissionMode;\n return merged;\n}\n\nasync function readTomlFile(filePath: string): Promise<PartialConfig> {\n let content: string;\n try {\n content = await fs.promises.readFile(filePath, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return {};\n throw error;\n }\n return parseTomlFile(content, filePath);\n}\n\nfunction readTomlFileSync(filePath: string): PartialConfig {\n if (!fs.existsSync(filePath)) return {};\n const content = fs.readFileSync(filePath, \"utf8\");\n return parseTomlFile(content, filePath);\n}\n\nexport async function loadConfig(cwd: string, overrides?: CliOverrides): Promise<StarConfig> {\n loadEnvFile();\n const global = await readTomlFile(globalConfigPath());\n const projectPath = projectConfigPath(cwd);\n const project = sanitizeProjectConfig(await readTomlFile(projectPath), projectPath);\n const merged = applyOverrides(mergeConfig(global, project), overrides);\n return ConfigSchema.parse(merged);\n}\n\nexport function loadConfigSync(cwd: string, overrides?: CliOverrides): StarConfig {\n loadEnvFile();\n const global = readTomlFileSync(globalConfigPath());\n const projectPath = projectConfigPath(cwd);\n const project = sanitizeProjectConfig(readTomlFileSync(projectPath), projectPath);\n const merged = applyOverrides(mergeConfig(global, project), overrides);\n return ConfigSchema.parse(merged);\n}\n"],"mappings":"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","names":["lines","readFile","path","path","readFile","st","buf","Box","Text","useEffect","useRef","useState","path","path","fs","path","fs","path","fs","path","path","fs","removed","fs","path","fs","path","fs","path","fs","path","execFile","randomUUID","readFile","stat","unlink","os","path","promisify","execFileAsync","promisify","execFile","commandExists","stat","readFile","path","os","randomUUID","unlink","fs","path","path","fs","readFile","path","i","j","fs","path","fs","fs","tomlString","fs","path","readFileSync","path","readFileSync","path","fs","path","fs","path","fs","path","fileExists","path","readFile","path","displayPath","path","readFile","Box","Text","useRef","useState","next","useRef","useRef","Box","Text","useRef","useState","Box","Text","useEffect","useRef","useState","readdir","path","path","readdir","jsx","jsxs","useState","useRef","useEffect","entry","styled","Box","Text","jsx","jsxs","useState","useRef","Box","Text","jsx","jsxs","Text","useState","useRef","Box","Box","Text","jsx","jsxs","Box","Text","Box","Text","useStdout","Text","jsx","jsxs","Text","jsx","jsxs","Text","MessageList","useStdout","Box","Box","Text","jsx","jsxs","Box","Text","Box","Text","jsx","jsxs","Box","Text","Box","Text","useStdout","memo","jsxs","memo","StatusBar","tokens","useStdout","Box","Text","Box","Text","useStdout","memo","jsx","jsxs","memo","StreamingMessage","useStdout","Box","Text","Box","Text","jsxs","Box","Text","Box","Text","jsxs","Box","Text","fs","path","path","fs","REGISTRY_URL","defaultFetcher","parse","jsx","jsxs","useState","useRef","useEffect","backend","modelName","messages","model","Box","Text","fs","parse","parse","fs"]}
1
+ {"version":3,"sources":["../src/main.tsx","../src/cli/print-json.ts","../src/config/loader.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { defaultAgentTasks } from \"./agent/agent-tasks\";\nimport { AgentLoop } from \"./agent/loop\";\nimport { formatTokens } from \"./cli/cost\";\nimport { formatStreamError } from \"./cli/format\";\nimport { MAX_IMAGE_BYTES, imageMimeType, readImageInput, resolveMentions } from \"./cli/mentions\";\nimport { UsageTracker, eventToJsonLine } from \"./cli/print-json\";\nimport { SYSTEM_PROMPT } from \"./cli/system-prompt\";\nimport { loadConfigSync } from \"./config/loader\";\nimport { type StarConfig, contextWindowTokens } from \"./config/schema\";\nimport { type CoreMessage, type ImageInput, reconcileToolCalls } from \"./core/messages\";\nimport { createModel, reasoningEffortMetadata } from \"./llm/provider\";\nimport { resolveModelConfig } from \"./llm/registry\";\nimport { loadSessionSnapshots } from \"./session/checkpoints\";\nimport { clearSessions } from \"./session/clear\";\nimport {\n findLatestSession,\n formatSessionEntries,\n listSessionEntries,\n resolveSessionId,\n} from \"./session/list\";\nimport { type SessionMeta, SessionStore } from \"./session/store\";\nimport { defaultTaskManager } from \"./tasks/manager\";\nimport { createDefaultRegistry } from \"./tools\";\nimport { hydrateSnapshots } from \"./tools/fs/snapshots\";\nimport { loadTodos } from \"./tools/todo\";\nimport { VERSION } from \"./version\";\n\nasync function createLoop(\n config: StarConfig,\n modelName: string,\n cwd: string,\n sessionStore: SessionStore | null,\n) {\n const model = createModel(config, modelName);\n const registry = createDefaultRegistry();\n const modelConfig = resolveModelConfig(config, modelName);\n return new AgentLoop({\n model,\n registry,\n config,\n cwd,\n system: SYSTEM_PROMPT,\n sessionStore,\n contextMaxTokens: contextWindowTokens(config, modelName),\n providerMetadata: reasoningEffortMetadata(config, modelName),\n temperature: modelConfig.temperature,\n streamIdleTimeoutSec: modelConfig.streamIdleTimeoutSec,\n streamFirstChunkTimeoutSec: modelConfig.streamFirstChunkTimeoutSec,\n });\n}\n\nasync function printMode(\n loop: AgentLoop,\n prompt: string,\n cwd: string,\n json: boolean,\n imagePaths: string[],\n sessionStore: SessionStore | null,\n): Promise<number> {\n const flagImages: ImageInput[] = [];\n for (const imagePath of imagePaths) {\n if (!imageMimeType(imagePath)) {\n process.stderr.write(\n `[error] unsupported image type: ${imagePath} (supported: png, jpg, jpeg, gif, webp)\\n`,\n );\n return 1;\n }\n const image = await readImageInput(imagePath, cwd);\n if (!image) {\n process.stderr.write(\n `[error] cannot read image: ${imagePath} (missing, unreadable, or larger than ${MAX_IMAGE_BYTES / (1024 * 1024)}MB)\\n`,\n );\n return 1;\n }\n flagImages.push(image);\n }\n const controller = new AbortController();\n process.on(\"SIGINT\", () => controller.abort());\n loop.onHookWarning = (message) => {\n process.stderr.write(`[hook] ${message}\\n`);\n };\n const resolved = await resolveMentions(prompt, cwd);\n if (resolved.attached.length > 0) {\n process.stderr.write(`[attached] ${resolved.attached.join(\", \")}\\n`);\n }\n for (const skip of resolved.skipped) {\n process.stderr.write(`[skipped] @${skip.path}: ${skip.reason}\\n`);\n }\n const images = [...flagImages, ...resolved.images];\n const input: string | { text: string; images: ImageInput[] } =\n images.length > 0 ? { text: resolved.input, images } : resolved.input;\n const usage = new UsageTracker();\n let exitCode = 0;\n try {\n for await (const event of loop.stream(input, controller.signal, {\n persistAs: prompt,\n })) {\n if (json) {\n const line = eventToJsonLine(event);\n if (line) process.stdout.write(`${line}\\n`);\n }\n switch (event.type) {\n case \"text-delta\":\n if (!json) process.stdout.write(event.text);\n break;\n case \"reasoning\":\n break;\n case \"tool-call\":\n if (!json) process.stderr.write(`\\n[tool] ${event.name} ${JSON.stringify(event.args)}\\n`);\n break;\n case \"tool-result\": {\n if (!json) {\n const preview =\n event.content.length > 500\n ? `${event.content.slice(0, 500)}... (truncated)`\n : event.content;\n process.stderr.write(`[result] ${event.isError ? \"ERROR: \" : \"\"}${preview}\\n`);\n }\n break;\n }\n case \"finish\":\n usage.add(event.usage);\n // A resumed session (-c/-r -p) must accumulate this turn's usage,\n // same as the REPL does; plain print runs have no store.\n if (event.usage) {\n sessionStore?.addUsage(event.usage).catch(() => {});\n }\n break;\n case \"retry\": {\n if (!json) {\n const wait =\n event.delayMs !== undefined && event.delayMs >= 1000\n ? ` in ${Math.round(event.delayMs / 1000)}s`\n : \"\";\n process.stderr.write(\n `\\n[retry ${event.attempt}/${event.maxAttempts}${wait}] ${event.reason}\\n`,\n );\n }\n break;\n }\n case \"notice\":\n if (!json) process.stderr.write(`\\n[notice] ${event.message}\\n`);\n break;\n case \"error\":\n if (!json) process.stderr.write(`\\n[error] ${formatStreamError(event.error)}\\n`);\n exitCode = 1;\n break;\n }\n if (exitCode !== 0) break;\n }\n } catch (error) {\n if (!(error instanceof DOMException && error.name === \"AbortError\")) {\n const message = error instanceof Error ? formatStreamError(error) : String(error);\n process.stderr.write(`\\n[error] ${message}\\n`);\n exitCode = 1;\n }\n }\n const usageLine = usage.toJsonLine();\n if (usageLine) {\n if (json) {\n process.stdout.write(`${usageLine}\\n`);\n } else {\n const t = usage.totals;\n process.stderr.write(\n `[usage] ${t.requests} requests, ${formatTokens(t.promptTokens)} prompt + ${formatTokens(t.completionTokens)} completion = ${formatTokens(t.totalTokens)} tokens\\n`,\n );\n }\n }\n if (!json) process.stdout.write(\"\\n\");\n const killedShells = defaultTaskManager.cleanup();\n const killedAgents = defaultAgentTasks.cleanup();\n const stopped = killedShells.length + killedAgents.length;\n if (stopped > 0) {\n process.stderr.write(\n `[info] ${stopped} background task(s) were still running and have been stopped.\\n`,\n );\n }\n return exitCode;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"star\")\n .description(\"Star CLI — an AI agent command-line interface\")\n .version(VERSION)\n .option(\"-m, --model <model>\", \"model to use\")\n .option(\"--permission-mode <mode>\", \"permission mode: ask | auto | readonly | yolo | plan\")\n .option(\"-p, --print <prompt>\", \"non-interactive print mode\")\n .option(\"--json\", \"output NDJSON events on stdout (print mode only)\")\n .option(\n \"--image <path>\",\n \"attach an image file (png/jpg/jpeg/gif/webp, max 5MB); repeatable\",\n (value: string, previous: string[]) => [...previous, value],\n [] as string[],\n )\n .option(\"-r, --resume [sessionId]\", \"resume a previous session (lists sessions when no id given)\")\n .option(\"-c, --continue\", \"continue the most recent session for the current directory\")\n .option(\n \"--clear-sessions [scope]\",\n \"delete stored sessions for the current directory ('all' deletes every session) and exit\",\n )\n .action(async (opts) => {\n const cwd = process.cwd();\n\n if (opts.json && opts.print === undefined) {\n console.error(\n '--json requires print mode: use star -p \"...\" --json (the interactive REPL does not support JSON output).',\n );\n process.exit(1);\n }\n\n if (opts.resume !== undefined && opts.continue) {\n console.error(\"Options --resume and --continue are mutually exclusive: pick one.\");\n process.exit(1);\n }\n\n if (opts.resume === true) {\n const entries = await listSessionEntries(cwd);\n if (entries.length === 0) {\n console.error(\"No sessions found for this directory.\");\n } else {\n console.log(formatSessionEntries(entries));\n }\n process.exit(0);\n }\n\n if (opts.clearSessions !== undefined) {\n const scope = opts.clearSessions;\n if (scope !== true && scope !== \"all\") {\n console.error(`Invalid scope: ${scope}. Use --clear-sessions or --clear-sessions all.`);\n process.exit(1);\n }\n const all = scope === \"all\";\n const removed = await clearSessions(all ? undefined : cwd);\n console.log(\n all\n ? `Deleted ${removed} session(s) across all directories.`\n : `Deleted ${removed} session(s) for this directory.`,\n );\n process.exit(0);\n }\n\n let config: StarConfig;\n try {\n config = loadConfigSync(cwd, { model: opts.model, permissionMode: opts.permissionMode });\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n const modelName = opts.model ?? config.defaultModel;\n if (!modelName) {\n console.error(\n \"No model configured. Add one to ~/.star-cli/config.toml or pass --model.\\n\" +\n \"See README.md for configuration examples.\",\n );\n process.exit(1);\n }\n\n let sessionStore: SessionStore | null = null;\n let resumed: { meta: SessionMeta; messages: CoreMessage[] } | null = null;\n let resumeId: string | null = null;\n if (typeof opts.resume === \"string\") {\n resumeId = await resolveSessionId(opts.resume);\n if (!resumeId) {\n console.error(`Session not found: ${opts.resume}`);\n process.exit(1);\n }\n } else if (opts.continue) {\n const latest = await findLatestSession(cwd);\n if (latest) {\n resumeId = latest.id;\n } else {\n process.stderr.write(\"No previous session for this directory — starting a new session.\\n\");\n }\n }\n\n if (resumeId) {\n // Open the store once and read through it: resumeSession() would open a\n // second SessionStore instance on the same directory whose independent\n // meta cache could race this instance's writes.\n sessionStore = await SessionStore.open(resumeId);\n if (!sessionStore) {\n console.error(`Session not found: ${resumeId}`);\n process.exit(1);\n }\n const [meta, loaded] = await Promise.all([sessionStore.meta(), sessionStore.messages()]);\n const messages = reconcileToolCalls(loaded);\n if (messages.length !== loaded.length) {\n await sessionStore.replaceMessages(messages);\n }\n resumed = { meta, messages };\n } else if (!opts.print) {\n sessionStore = await SessionStore.create(cwd, modelName);\n }\n\n let loop: AgentLoop;\n try {\n loop = await createLoop(config, modelName, cwd, sessionStore);\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n if (resumed) {\n await loop.loadMessages(resumed.messages);\n // Resuming explicitly continues the project: rehydrate its todo list\n // (fresh sessions leave it alone even when .star/todos.json exists).\n await loadTodos(cwd);\n if (sessionStore) {\n hydrateSnapshots(await loadSessionSnapshots(sessionStore.dir));\n }\n }\n\n if (opts.print) {\n // Let the loop drain instead of process.exit(): force-exiting on Windows\n // can hit a libuv assertion while undici keep-alive handles are closing.\n process.exitCode = await printMode(\n loop,\n opts.print,\n cwd,\n Boolean(opts.json),\n opts.image ?? [],\n sessionStore,\n );\n return;\n }\n\n // The REPL pulls in Ink and every interactive component (~0.4s of module\n // evaluation): load it only on the interactive path so -p, --version,\n // --clear-sessions and session listing stay cheap.\n const { renderRepl } = await import(\"./cli/repl\");\n renderRepl(loop, {\n model: modelName,\n permissionMode: config.permissionMode,\n config,\n cwd,\n sessionStore,\n initialMessages: resumed?.messages,\n initialUsage: resumed?.meta.usage,\n });\n });\n\nprogram.parse(process.argv);\n","import type { StreamEvent, TokenUsage } from \"../core/events\";\n\nexport function eventToJsonLine(event: StreamEvent): string | null {\n switch (event.type) {\n case \"finish\":\n return null;\n case \"error\":\n return JSON.stringify({ type: \"error\", error: { message: event.error.message } });\n default:\n return JSON.stringify(event);\n }\n}\n\nexport class UsageTracker {\n private requests = 0;\n private promptTokens = 0;\n private completionTokens = 0;\n private totalTokens = 0;\n\n add(usage?: TokenUsage): void {\n if (!usage) return;\n this.requests += 1;\n this.promptTokens += usage.promptTokens;\n this.completionTokens += usage.completionTokens;\n this.totalTokens += usage.totalTokens;\n }\n\n get totals(): TokenUsage & { requests: number } {\n return {\n requests: this.requests,\n promptTokens: this.promptTokens,\n completionTokens: this.completionTokens,\n totalTokens: this.totalTokens,\n };\n }\n\n toJsonLine(): string | null {\n if (this.requests === 0) return null;\n return JSON.stringify({\n type: \"usage\",\n requests: this.requests,\n promptTokens: this.promptTokens,\n completionTokens: this.completionTokens,\n totalTokens: this.totalTokens,\n });\n }\n}\n","import fs from \"node:fs\";\nimport { parse } from \"smol-toml\";\nimport { loadEnvFile } from \"./env\";\nimport { globalConfigPath, projectConfigPath } from \"./paths\";\nimport { type CliOverrides, ConfigSchema, type ModelConfig, type StarConfig } from \"./schema\";\n\nconst PartialConfigSchema = ConfigSchema.partial();\n\ntype PartialConfig = ReturnType<typeof PartialConfigSchema.parse>;\n\nfunction parseTomlFile(content: string, filePath: string): PartialConfig {\n let raw: unknown;\n try {\n raw = parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to parse TOML in ${filePath}: ${message}`);\n }\n const result = PartialConfigSchema.safeParse(raw);\n if (!result.success) {\n throw new Error(`Invalid config in ${filePath}: ${result.error.message}`);\n }\n return result.data;\n}\n\n// Keys a project-level .star/config.toml may set. Anything else (providers,\n// permissionMode, permissions, hooks, ...) stays global-only: a checked-out\n// repo must not be able to plant shell hooks, force yolo mode, or redirect\n// provider traffic to a key-harvesting endpoint.\nconst PROJECT_ALLOWED_KEYS = new Set([\n \"defaultModel\",\n \"models\",\n \"maxSteps\",\n \"contextMaxTokens\",\n \"compactThresholdTokens\",\n \"streamIdleTimeoutSec\",\n \"streamFirstChunkTimeoutSec\",\n \"streamMaxRetries\",\n \"maxAutoContinues\",\n \"contextCompaction\",\n \"sessionBudgetUsd\",\n \"notifyBell\",\n \"notifyBellThresholdSec\",\n \"doomLoopThreshold\",\n \"gitSnapshots\",\n]);\n\n// Safe ranges for the project-provided streaming knobs: a repo must not set\n// pathological values (sub-second idle timeouts, thousands of retries).\nconst PROJECT_STREAM_RANGES = {\n streamIdleTimeoutSec: { min: 5, max: 120 },\n streamFirstChunkTimeoutSec: { min: 30, max: 900 },\n streamMaxRetries: { min: 0, max: 10 },\n} as const;\n\n// 0 disables these protections, so a project may only tighten them, never\n// turn them off (handled at merge time via min()).\nconst PROJECT_PROTECTIVE_MIN_KEYS = new Set([\"maxSteps\", \"doomLoopThreshold\"]);\n\nfunction warnProject(filePath: string, message: string): void {\n process.stderr.write(`[star] ${message} in ${filePath}\\n`);\n}\n\n// Price fields are stripped from project models: a repo defining $0 prices\n// would silently zero out /cost and defeat sessionBudgetUsd.\nfunction stripModelPrices(models: ModelConfig[], filePath: string): ModelConfig[] {\n let stripped = false;\n const out = models.map((model) => {\n const { promptPrice, completionPrice, cacheReadPrice, ...rest } = model;\n if (\n promptPrice !== undefined ||\n completionPrice !== undefined ||\n cacheReadPrice !== undefined\n ) {\n stripped = true;\n }\n return rest;\n });\n if (stripped) {\n warnProject(filePath, \"ignoring price fields in project [[models]]: pricing stays global-only\");\n }\n return out;\n}\n\nfunction sanitizeProjectConfig(project: PartialConfig, filePath: string): PartialConfig {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(project)) {\n if (value === undefined) continue;\n if (!PROJECT_ALLOWED_KEYS.has(key)) {\n process.stderr.write(\n `[star] ignoring \"${key}\" in ${filePath}: project config cannot set this key\\n`,\n );\n continue;\n }\n if (key === \"gitSnapshots\" && value === false) {\n // Snapshot tracking protects /undo and /redo; a repo may enable but\n // never disable it.\n warnProject(\n filePath,\n 'ignoring \"gitSnapshots = false\": project config cannot disable this protection',\n );\n continue;\n }\n if (PROJECT_PROTECTIVE_MIN_KEYS.has(key) && value === 0) {\n warnProject(filePath, `ignoring \"${key} = 0\": project config cannot disable this protection`);\n continue;\n }\n const range = PROJECT_STREAM_RANGES[key as keyof typeof PROJECT_STREAM_RANGES];\n if (range && typeof value === \"number\") {\n const clamped = Math.min(range.max, Math.max(range.min, value));\n if (clamped !== value) {\n warnProject(\n filePath,\n `clamping \"${key}\" from ${value} to ${clamped}: project config is limited to ${range.min}–${range.max}`,\n );\n }\n sanitized[key] = clamped;\n continue;\n }\n if (key === \"models\" && Array.isArray(value)) {\n sanitized[key] = stripModelPrices(value as ModelConfig[], filePath);\n continue;\n }\n sanitized[key] = value;\n }\n return sanitized as PartialConfig;\n}\n\n// Project values merge protectively: a repo can tighten safeguards but never\n// relax them. Budgets take the lower bound; guard thresholds take the lower\n// bound too (0 = disabled was already filtered out above).\nfunction mergeProjectConfig(global: PartialConfig, project: PartialConfig): PartialConfig {\n const merged: PartialConfig = { ...global, ...project };\n if (project.sessionBudgetUsd !== undefined && global.sessionBudgetUsd !== undefined) {\n merged.sessionBudgetUsd = Math.min(global.sessionBudgetUsd, project.sessionBudgetUsd);\n }\n if (project.maxSteps !== undefined) {\n merged.maxSteps = Math.min(global.maxSteps ?? 100, project.maxSteps);\n }\n if (project.doomLoopThreshold !== undefined) {\n merged.doomLoopThreshold = Math.min(global.doomLoopThreshold ?? 3, project.doomLoopThreshold);\n }\n return merged;\n}\n\nfunction applyOverrides(config: PartialConfig, overrides?: CliOverrides): PartialConfig {\n if (!overrides) return config;\n const merged = { ...config };\n if (overrides.model !== undefined) merged.defaultModel = overrides.model;\n if (overrides.permissionMode !== undefined) merged.permissionMode = overrides.permissionMode;\n return merged;\n}\n\nasync function readTomlFile(filePath: string): Promise<PartialConfig> {\n let content: string;\n try {\n content = await fs.promises.readFile(filePath, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return {};\n throw error;\n }\n return parseTomlFile(content, filePath);\n}\n\nfunction readTomlFileSync(filePath: string): PartialConfig {\n if (!fs.existsSync(filePath)) return {};\n const content = fs.readFileSync(filePath, \"utf8\");\n return parseTomlFile(content, filePath);\n}\n\nexport async function loadConfig(cwd: string, overrides?: CliOverrides): Promise<StarConfig> {\n loadEnvFile();\n const global = await readTomlFile(globalConfigPath());\n const projectPath = projectConfigPath(cwd);\n const project = sanitizeProjectConfig(await readTomlFile(projectPath), projectPath);\n const merged = applyOverrides(mergeProjectConfig(global, project), overrides);\n return ConfigSchema.parse(merged);\n}\n\nexport function loadConfigSync(cwd: string, overrides?: CliOverrides): StarConfig {\n loadEnvFile();\n const global = readTomlFileSync(globalConfigPath());\n const projectPath = projectConfigPath(cwd);\n const project = sanitizeProjectConfig(readTomlFileSync(projectPath), projectPath);\n const merged = applyOverrides(mergeProjectConfig(global, project), overrides);\n return ConfigSchema.parse(merged);\n}\n"],"mappings":"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","names":[]}