@livx.cc/agentx 0.94.38

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/redact.ts","../src/tools.structured.ts","../src/todo.ts","../src/logging.ts","../src/tools.web.ts","../src/OverlayFilesystem.ts","../src/tools.ts","../src/NodeDiskFilesystem.ts","../src/JailedFilesystem.ts","../src/shell.sandbox.ts","../src/tools.shell.ts","../cli/cli.ts","../cli/clipboard.ts","../src/llm.ts","../src/Agent.ts","../src/tools.jobs.ts","../src/host.ts","../src/relevance.ts","../src/frontmatter.ts","../src/commands.ts","../src/skills.ts","../src/memory.ts","../src/instructions.ts","../src/subagent.ts","../src/agents.ts","../src/permissions.ts","../src/lint.ts","../src/reasoning.ts","../src/index.ts","../src/BodDbFilesystem.ts","../src/MountFilesystem.ts","../src/speculate.ts","../src/scheduler.ts","../src/presets.ts","../src/scratch.ts","../src/lessons.ts","../src/reflect.ts","../src/duplex.ts","../src/mcp.ts","../src/voice/engine.ts","../src/voice/soniox.ts","../src/voice/types.ts","../src/voice/cartesia.ts","../src/mcp.client.ts","../cli/mcpOAuth.ts","../cli/core.ts","../src/tools.notify.ts","../cli/util.ts","../cli/voice.ts","../cli/config.ts","../cli/hooks-config.ts","../cli/diff.ts","../cli/session.ts","../cli/checkpoints.ts","../cli/gitCheckpoints.ts","../cli/permissions.ts","../cli/complete.ts","../cli/lineEditor.ts","../cli/bidi.ts","../cli/markdown.ts","../cli/stdinSource.ts","../cli/osScheduler.ts","../cli/remoteTrigger.ts"],"sourcesContent":["/**\n * Mask secret-looking values in arbitrary text before it reaches the model.\n *\n * Two complementary seams use this: real-shell output (`cat .env`, `printenv`) and the\n * `Read` tool (so provider keys stored in `.agent/settings.json` are usable-but-masked).\n * The FS jail hides whole secret FILES by name; this hides secret VALUES wherever they\n * surface in otherwise-legitimate content.\n *\n * Both regexes are linear (no nested quantifiers) — safe against catastrophic backtracking\n * and cheap enough to run on every tool output (see tests/redact.bench).\n */\n\nexport const REDACTED = '‹redacted›';\n\n/** Config/control files that may carry provider keys — readers (Read/Grep) mask secret VALUES in\n * these while keeping the rest readable. (Whole secret FILES like .env are hidden by the FS jail.) */\nexport const CONFIG_FILE_RE = /(^|\\/)\\.(agent|claude)\\/(settings(\\.[\\w-]+)?\\.json|config\\.(json|js|mjs|cjs|ts))$/i;\n\n// (A) `NAME=value` / `\"name\": \"value\"` pairs where NAME looks like a secret. Masks the value only,\n// so the agent still sees WHICH key exists (useful config context) without the secret itself.\nconst SECRET_PAIR =\n /((?:^|[\\s,{[])(?:export\\s+)?[\"']?[\\w.\\-]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|PRIVATE_KEY|ACCESS_?KEY|AUTH(?:_?TOKEN)?|BEARER)[\\w.\\-]*[\"']?\\s*[:=]\\s*)([\"']?)([^\\s\"',{}\\]]+)/gi;\n\n// (B) Bare tokens by well-known shape — catches secrets that appear without an obvious key\n// (Authorization headers, URLs, JSON dumps). Conservative prefixes to avoid false positives.\nconst SECRET_TOKEN =\n /\\b(sk-ant-[\\w-]{12,}|sk-[A-Za-z0-9]{20,}|ghp_[A-Za-z0-9]{20,}|gho_[A-Za-z0-9]{20,}|github_pat_[\\w]{20,}|xox[baprs]-[\\w-]{10,}|AKIA[0-9A-Z]{12,}|AIza[\\w-]{20,}|eyJ[\\w-]{8,}\\.[\\w-]{8,}\\.[\\w-]{8,})\\b/g;\n\n/** Return `text` with secret values masked. Cheap no-op when nothing matches. */\nexport function redactSecrets(text: string): string {\n if (!text) return text;\n return text\n .replace(SECRET_PAIR, (_m, head, quote, _val) => `${head}${quote}${REDACTED}`)\n .replace(SECRET_TOKEN, REDACTED);\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\nimport type { AgentTool, ToolContext } from './tools';\nimport type { ChatResponse } from './llm';\nimport { redactSecrets, CONFIG_FILE_RE } from './redact';\n\n/**\n * Structured file tools — typed results straight from the VFS, no `bash` parsing.\n * These close the efficiency gap to Claude Code (its Grep/Glob/Write return one\n * structured result where our agent otherwise drives find/grep pipelines and re-reads).\n * Backend-agnostic: pure IFilesystem walks, so they run on Mem/Disk/IndexedDb alike.\n */\n\n/** Throw the moment a run is cancelled, so a long file walk/scan bails instead of pegging the CPU\n * uninterruptibly. dispatch() catches the throw → the run loop sees `aborted` and ends the turn. */\nfunction ckAbort(signal?: AbortSignal): void {\n if (signal?.aborted) throw new Error('aborted');\n}\n\n/** Recursively list every file path under `dir` (VFS-absolute), depth-first, sorted. Cancellable:\n * a cancelled run throws between entries so a huge tree walk (real-FS disk mode) doesn't wedge. */\nasync function walkFiles(fs: IFilesystem, dir: string, signal?: AbortSignal, out: string[] = []): Promise<string[]> {\n let entries: string[];\n try { entries = await fs.readDir(dir); } catch { return out; }\n for (const name of entries.sort()) {\n ckAbort(signal);\n const p = dir === '/' ? `/${name}` : `${dir}/${name}`;\n if (await fs.isDirectory(p)) await walkFiles(fs, p, signal, out);\n else out.push(p);\n }\n return out;\n}\n\n/**\n * Translate a glob (`**`, `*`, `?`) into an anchored RegExp over VFS-absolute paths.\n * `caseInsensitive` is used by the JailedFilesystem denylist so `/.ENV` can't slip past\n * a `.env` rule (file-matching tools keep the default case-sensitive behavior).\n */\nexport function globToRegExp(glob: string, caseInsensitive = false): RegExp {\n const g = glob.startsWith('/') ? glob : `/${glob}`;\n let re = '';\n for (let i = 0; i < g.length; i++) {\n const c = g[i];\n if (c === '*') {\n if (g[i + 1] === '*') { re += '.*'; i++; if (g[i + 1] === '/') i++; }\n else re += '[^/]*';\n } else if (c === '?') re += '[^/]';\n else re += c.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n return new RegExp(`^${re}$`, caseInsensitive ? 'i' : '');\n}\n\n/** The dir structured tools walk/anchor at — the FS's working dir. Keeps Glob/Grep/RepoMap scoped\n * to the project (or, in CC-parity disk mode where root '/' is the real machine, the launch dir)\n * instead of crawling the whole filesystem. Backward-compatible: Mem/jailed-at-cwd backends report '/'. */\nconst fsCwd = (fs: IFilesystem): string => fs.getCwd();\n\n/** Compile a glob, resolving a relative pattern under the FS cwd (mirrors a shell's cwd-relative globs).\n * Absolute patterns are used as-is. With cwd '/' this is identical to the old `/`-anchored behavior. */\nfunction anchoredGlob(fs: IFilesystem, glob: string): RegExp {\n const cwd = fsCwd(fs);\n const base = cwd === '/' ? '' : cwd;\n return globToRegExp(glob.startsWith('/') ? glob : `${base}/${glob}`);\n}\n\n/** List paths matching a glob, sorted — the structured alternative to `find`. */\nexport const globTool: AgentTool = {\n name: 'Glob',\n description:\n 'Find files by glob pattern (e.g. \"**/*.ts\", \"src/**/*.test.ts\"). Returns sorted paths, one per line. ' +\n 'Space-separated patterns combine; `!`-prefix excludes (e.g. \"**/*.ts !**/*.test.ts\"). Prefer over `bash find` for locating files — one call, structured output.',\n parameters: {\n type: 'object',\n required: ['pattern'],\n properties: { pattern: { type: 'string', description: 'glob pattern(s); ** matches across directories; prefix a pattern with ! to exclude' } },\n },\n async run({ pattern }, ctx) {\n const pats = String(pattern ?? '').trim().split(/\\s+/).filter(Boolean);\n const include = pats.filter((p) => !p.startsWith('!')).map((p) => anchoredGlob(ctx.fs, p));\n const exclude = pats.filter((p) => p.startsWith('!')).map((p) => anchoredGlob(ctx.fs, p.slice(1)));\n const includes = include.length ? include : [anchoredGlob(ctx.fs, '**')]; // only-excludes → start from everything\n const hits = (await walkFiles(ctx.fs, fsCwd(ctx.fs), ctx.signal)).filter(\n (p) => includes.some((re) => re.test(p)) && !exclude.some((re) => re.test(p)),\n );\n return hits.length ? hits.join('\\n') : '(no matches)';\n },\n};\n\n/** Search file contents by regex, returning typed `path:line:text` hits with optional context. */\nexport const grepTool: AgentTool = {\n name: 'Grep',\n description:\n 'Search file contents by regex. Returns `path:line: text` hits. Optional `glob` to scope files, `context` for surrounding lines, `filesOnly` for matching paths only. Prefer over `bash grep` for file content search — structured results, no re-parse needed. Use `bash` instead for running commands, tests, or piped workflows.',\n parameters: {\n type: 'object',\n required: ['pattern'],\n properties: {\n pattern: { type: 'string', description: 'JS regular expression' },\n glob: { type: 'string', description: 'optional file glob to restrict the search' },\n context: { type: 'number', description: 'lines of context before/after each hit' },\n filesOnly: { type: 'boolean', description: 'only list matching file paths' },\n },\n },\n async run({ pattern, glob, context, filesOnly }, ctx) {\n let re: RegExp;\n try { re = new RegExp(String(pattern ?? '')); } catch (e) { throw new Error(`invalid regex: ${String(e)}`); }\n const scope = glob ? anchoredGlob(ctx.fs, String(glob)) : null;\n const files = (await walkFiles(ctx.fs, fsCwd(ctx.fs), ctx.signal)).filter((p) => !scope || scope.test(p));\n const ctxN = Math.max(0, Number(context ?? 0));\n const out: string[] = [];\n const matched: string[] = [];\n let skipped = 0; // unreadable files (permissions, races) — surfaced, not silently dropped\n for (const path of files) {\n ckAbort(ctx.signal); // cancellable per-file: a wide grep over a big tree stops on Esc, not after\n let content: string;\n try { content = await ctx.fs.readFile(path); } catch { skipped++; continue; }\n const lines = content.split('\\n');\n const mask = CONFIG_FILE_RE.test(path); // mask secret values from config files in the hits\n let fileHit = false;\n for (let i = 0; i < lines.length; i++) {\n if (!re.test(lines[i])) continue;\n fileHit = true;\n if (filesOnly) break;\n const lo = Math.max(0, i - ctxN), hi = Math.min(lines.length - 1, i + ctxN);\n for (let j = lo; j <= hi; j++) out.push(`${path}:${j + 1}: ${mask ? redactSecrets(lines[j]) : lines[j]}`);\n }\n if (fileHit) matched.push(path);\n }\n const note = skipped ? `\\n[skipped ${skipped} unreadable file${skipped === 1 ? '' : 's'}]` : '';\n if (filesOnly) return (matched.length ? matched.join('\\n') : '(no matches)') + note;\n return (out.length ? out.join('\\n') : '(no matches)') + note;\n },\n};\n\n/** A line is a top-level declaration worth showing in the repo map. */\nconst SIG_RE = /^\\s*(export\\b|(?:export\\s+)?(?:async\\s+)?function\\s+\\*?\\w|(?:export\\s+)?(?:abstract\\s+)?class\\s+\\w|(?:export\\s+)?interface\\s+\\w|(?:export\\s+)?type\\s+\\w|(?:export\\s+)?enum\\s+\\w)/;\nconst isCode = (p: string) => /\\.(ts|tsx|js|jsx|mjs|cjs)$/.test(p);\nconst isDoc = (p: string) => /\\.(md|mdx|txt)$/.test(p);\n\n/** Extract heading hierarchy + first-paragraph summaries from a markdown file. */\nfunction docOutlineOf(content: string, cap = 20): string[] {\n const out: string[] = [];\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length && out.length < cap; i++) {\n const hm = lines[i].match(/^(#{1,4})\\s+(.+)/);\n if (hm) {\n out.push(hm[0].slice(0, 120));\n for (let j = i + 1; j < lines.length; j++) {\n const l = lines[j].trim();\n if (!l) continue;\n if (l.startsWith('#')) break;\n out.push(' ' + l.slice(0, 120));\n break;\n }\n }\n }\n return out;\n}\n\n/** One file's exported/top-level signatures (no bodies), capped. */\nfunction signaturesOf(content: string, cap = 40): string[] {\n const out: string[] = [];\n for (const line of content.split('\\n')) {\n if (!SIG_RE.test(line)) continue;\n let sig = line.trim();\n const brace = sig.indexOf('{');\n if (brace > 0) sig = sig.slice(0, brace).trim(); // drop the body\n sig = sig.replace(/\\s*=>?\\s*$/, '').replace(/=\\s*$/, '').slice(0, 120);\n if (sig && !out.includes(sig)) out.push(sig);\n if (out.length >= cap) break;\n }\n return out;\n}\n\n/**\n * Compact map of a VFS — code signatures and/or doc outlines. Edge-safe (pure IFilesystem walk).\n * `mode`: \"code\" (default) = top-level signatures; \"docs\" = heading outlines; \"all\" = both.\n */\nexport async function repoIndex(fs: IFilesystem, glob?: string, mode: 'code' | 'docs' | 'all' = 'code', signal?: AbortSignal): Promise<string> {\n const scope = glob ? anchoredGlob(fs, String(glob)) : null;\n const filter = mode === 'code' ? isCode : mode === 'docs' ? isDoc : (p: string) => isCode(p) || isDoc(p);\n const files = (await walkFiles(fs, fsCwd(fs), signal)).filter((p) => (scope ? scope.test(p) : filter(p)));\n const blocks: string[] = [];\n let shown = 0;\n for (const path of files) {\n ckAbort(signal);\n let content: string;\n try { content = await fs.readFile(path); } catch { continue; }\n const entries = isDoc(path) ? docOutlineOf(content) : signaturesOf(content);\n if (entries.length) { blocks.push(`${path}\\n${entries.map((s) => ' ' + s).join('\\n')}`); shown += entries.length; }\n if (shown >= 400) { blocks.push('… (map truncated; narrow with `glob`)'); break; }\n }\n const label = mode === 'code' ? 'code signatures' : mode === 'docs' ? 'document outlines' : 'entries';\n return blocks.length ? blocks.join('\\n') : `(no ${label} found)`;\n}\n\n/** Compact map of the codebase or document workspace — orient in ONE call, not many. */\nexport const repoMapTool: AgentTool = {\n name: 'RepoMap',\n description:\n 'Get a compact map of the workspace: code signatures and/or document outlines in ONE call. `scope`: \"code\" (default) = functions/classes/types; \"docs\" = markdown headings + summaries; \"all\" = both. Call once to orient before diving into specific files — avoids many exploratory Glob/Read calls.',\n parameters: {\n type: 'object',\n properties: {\n glob: { type: 'string', description: 'optional file glob to scope (default: all matching files)' },\n scope: { type: 'string', enum: ['code', 'docs', 'all'], description: 'what to map: \"code\" (default), \"docs\", or \"all\"' },\n },\n },\n run: ({ glob, scope }, ctx) => repoIndex(ctx.fs, glob, scope || 'code', ctx.signal),\n};\n\n/**\n * Whitespace-tolerant fallback for Edit: locate `oldStr` in `content` ignoring each line's\n * leading/trailing whitespace, and replace the UNIQUE matching region with `newStr`. Returns\n * null if there isn't exactly one match (caller then errors, forcing a re-read) — so it never\n * guesses. This kills the common re-Read+retry cascade when an exact Edit fails on indentation drift.\n */\nexport function fuzzyLineReplace(content: string, oldStr: string, newStr: string): string | null {\n const norm = (s: string) => s.trim();\n const cl = content.split('\\n');\n const ol = oldStr.split('\\n').map(norm);\n while (ol.length && ol[ol.length - 1] === '') ol.pop();\n while (ol.length && ol[0] === '') ol.shift();\n if (!ol.length) return null;\n const matches: number[] = [];\n for (let i = 0; i + ol.length <= cl.length; i++) {\n let ok = true;\n for (let j = 0; j < ol.length; j++) if (norm(cl[i + j]) !== ol[j]) { ok = false; break; }\n if (ok) matches.push(i);\n }\n if (matches.length !== 1) return null; // not found, or ambiguous → don't guess\n const i = matches[0];\n return [...cl.slice(0, i), ...newStr.split('\\n'), ...cl.slice(i + ol.length)].join('\\n');\n}\n\n/** Read-before-overwrite guard, shared by Write and ApplyEdits' whole-file branch: blindly replacing\n * an existing file the agent never Read destroys its unseen content (the taskify-board incident).\n * `key` is the resolved path (the readState key); a fresh Write arms readState, so re-writing your own\n * output passes. Returns true when the write would clobber un-Read content and should be refused. */\nasync function wouldClobberUnread(ctx: ToolContext, path: string, key: string): Promise<boolean> {\n return !ctx.readState.has(key) && (await ctx.fs.exists(path));\n}\n\n/** Create or overwrite a file, creating parent directories as needed (mkdir -p). */\nexport const writeTool: AgentTool = {\n name: 'Write',\n description:\n 'Create or overwrite a file with the given contents, creating parent directories as needed. Use for new files instead of `bash echo >`. To replace an EXISTING file you must Read it first — overwriting an un-Read file is refused (it would destroy unseen content).',\n parameters: {\n type: 'object',\n required: ['path', 'content'],\n properties: { path: { type: 'string' }, content: { type: 'string' } },\n },\n async run({ path, content }, ctx) {\n const body = String(content ?? '');\n const key = ctx.fs.resolvePath(path);\n if (await wouldClobberUnread(ctx, path, key))\n throw new Error(`Refusing to overwrite ${path}: it exists and hasn't been Read. Read it first, then Write to replace it (or Edit to change part of it).`);\n if (ctx.lint) { const err = ctx.lint(path, body); if (err) throw new Error(err); }\n await mkdirp(ctx.fs, parentDir(key));\n await ctx.fs.writeFile(path, body);\n ctx.readState.set(key, body); // arm Edit on a freshly written file\n return `Wrote ${path}`;\n },\n};\n\n/** Apply an ordered list of exact-substring edits to one file in a single call. */\nexport const multiEditTool: AgentTool = {\n name: 'MultiEdit',\n description:\n 'Apply several exact-substring replacements to one file in order, in a single call. Requires a prior Read. Each `old_string` must be unique at the time it is applied. All-or-nothing: if any edit fails, none are written.',\n parameters: {\n type: 'object',\n required: ['path', 'edits'],\n properties: {\n path: { type: 'string' },\n edits: {\n type: 'array',\n items: {\n type: 'object',\n required: ['old_string', 'new_string'],\n properties: { old_string: { type: 'string' }, new_string: { type: 'string' } },\n },\n },\n },\n },\n async run({ path, edits }, ctx) {\n const key = ctx.fs.resolvePath(path);\n const snapshot = ctx.readState.get(key);\n if (snapshot == null) throw new Error(`File has not been read yet: ${path}. Read it before editing.`);\n let current = await ctx.fs.readFile(path);\n if (current !== snapshot) throw new Error(`File ${path} changed since it was read (stale). Re-read before editing.`);\n const list = Array.isArray(edits) ? edits : [];\n if (!list.length) throw new Error('edits must be a non-empty array');\n for (const [i, e] of list.entries()) {\n const count = e.old_string === '' ? 0 : current.split(e.old_string).length - 1;\n if (count === 0) throw new Error(`edit ${i}: old_string not found in ${path}.`);\n if (count > 1) throw new Error(`edit ${i}: old_string is not unique in ${path} (${count} matches).`);\n current = current.replace(e.old_string, () => e.new_string);\n }\n if (ctx.lint) { const err = ctx.lint(path, current); if (err) throw new Error(err); }\n await ctx.fs.writeFile(path, current);\n ctx.readState.set(key, current);\n return `Applied ${list.length} edit(s) to ${path}`;\n },\n};\n\n/**\n * Cross-file batch edit — the multi-file refactor primitive. One call edits MANY files:\n * each entry with an `old_string` replaces that exact, UNIQUE substring (read fresh + verified,\n * so NO prior Read is needed — locate the sites with Grep, whose output is the text to match);\n * each entry WITHOUT `old_string` writes `new_string` as the whole file (creates it + parent dirs).\n * Validate-all-before-write → atomic across files. Collapses \"Grep + N×(Read+Edit)\" into \"Grep + ApplyEdits\".\n */\nexport const applyEditsTool: AgentTool = {\n name: 'ApplyEdits',\n description:\n 'Apply edits across one or MORE files in a single call — for cross-file refactors (rename/extract/move). edits=[{path, old_string?, new_string}]. WITH old_string: replace that exact substring (must be UNIQUE in the file — add surrounding context; read fresh + verified, no prior Read needed). WITHOUT old_string: write new_string as the whole file (creates it + parent dirs; but to OVERWRITE a file that already exists you must Read it first, else use old_string to edit part of it). Locate sites first with Grep (its output shows the exact text). Atomic: validated across all files before any write.',\n parameters: {\n type: 'object',\n required: ['edits'],\n properties: {\n edits: {\n type: 'array',\n items: {\n type: 'object',\n required: ['path', 'new_string'],\n properties: { path: { type: 'string' }, old_string: { type: 'string' }, new_string: { type: 'string' } },\n },\n },\n },\n },\n async run({ edits }, ctx) {\n const list = Array.isArray(edits) ? edits : [];\n if (!list.length) throw new Error('edits must be a non-empty array of {path, old_string?, new_string}');\n const planned = new Map<string, string>(); // resolved path -> final content (validate ALL before writing → atomic)\n for (const [i, e] of list.entries()) {\n const p = ctx.fs.resolvePath(String(e.path));\n const old = e.old_string == null ? '' : String(e.old_string);\n const neu = String(e.new_string ?? '');\n if (old === '') { // whole-file write / create\n // Same read-before-overwrite guard as Write (skip if an earlier edit in THIS batch already staged p).\n if (!planned.has(p) && (await wouldClobberUnread(ctx, String(e.path), p)))\n throw new Error(`edit ${i}: refusing to overwrite ${e.path} with a whole-file write — it exists and hasn't been Read. Read it first, or pass old_string to edit part of it.`);\n planned.set(p, neu); continue;\n }\n let cur = planned.has(p) ? planned.get(p)! : await ctx.fs.readFile(p).catch(() => { throw new Error(`edit ${i}: file not found: ${e.path}`); });\n const count = cur.split(old).length - 1;\n if (count > 1) throw new Error(`edit ${i}: old_string is not unique in ${e.path} (${count} matches) — add more context`);\n if (count === 1) cur = cur.replace(old, () => neu);\n else {\n const fz = fuzzyLineReplace(cur, old, neu);\n if (fz == null) throw new Error(`edit ${i}: old_string not found in ${e.path}`);\n cur = fz;\n }\n planned.set(p, cur);\n }\n if (ctx.lint) for (const [p, content] of planned) { const err = ctx.lint(p, content); if (err) throw new Error(err); } // validate ALL before any write\n for (const [p, content] of planned) { await mkdirp(ctx.fs, parentDir(p)); await ctx.fs.writeFile(p, content); ctx.readState.set(p, content); }\n return `Applied ${list.length} edit(s) across ${planned.size} file(s): ${[...planned.keys()].join(', ')}`;\n },\n};\n\nfunction parentDir(abs: string): string {\n const i = abs.lastIndexOf('/');\n return i <= 0 ? '/' : abs.slice(0, i);\n}\n\n/** mkdir -p over the VFS (idempotent, top-down). */\nexport async function mkdirp(fs: IFilesystem, dir: string): Promise<void> {\n if (dir === '/' || (await fs.exists(dir))) return;\n await mkdirp(fs, parentDir(dir));\n if (!(await fs.exists(dir))) await fs.createDir(dir);\n}\n\n/**\n * Review — verification WITHOUT execution: a fresh-context, adversarial critic pass over the\n * changes the agent just made. Verification-as-review (stolen from the review-fix-commit skill):\n * for an agent with no test runner, \"re-read to be sure\" is weak, but a COLD reviewer that reads\n * only {task + the produced files} (not the author's chain-of-thought) catches missed edge cases,\n * unstated implications, and subtle logic bugs a happy-path one-shot misses. Costs one model call.\n *\n * The `notes` arg is the with/without-CONTEXT knob: omit it for a pure cold review (the default,\n * least biased); pass it to feed the reviewer extra context. We don't decide which is better —\n * the self-evolution loop discovers it via its prompt rules.\n *\n * Degrades to a no-op notice if no model handle is wired (ctx.ai/ctx.model).\n */\nexport function reviewTool(): AgentTool {\n return {\n name: 'Review',\n description:\n 'Critically review your changes before finishing (verification without running code). Pass the task and the paths you changed; a fresh-context senior reviewer reads them COLD and returns concrete issues or \"LGTM\". Fix what it raises, then finish. Optional `notes` feeds the reviewer extra context.',\n parameters: {\n type: 'object',\n required: ['task', 'paths'],\n properties: {\n task: { type: 'string', description: 'what was asked — the spec/requirements to check the changes against' },\n paths: { type: 'array', items: { type: 'string' }, description: 'the files you changed/created, to be reviewed' },\n notes: { type: 'string', description: 'OPTIONAL extra context for the reviewer (rationale, constraints). Omit for a pure cold review.' },\n },\n },\n async run({ task, paths, notes }, ctx: ToolContext) {\n if (!ctx.ai || !ctx.model) return '[Review] no model handle wired — skipped.';\n const list: string[] = Array.isArray(paths) ? paths.map(String) : [];\n if (!list.length) return 'Error: pass the paths you changed in `paths`.';\n const files: string[] = [];\n for (const p of list.slice(0, 12)) {\n try {\n const body = await ctx.fs.readFile(p);\n files.push(`--- ${p} ---\\n${body.length > 4000 ? body.slice(0, 4000) + '\\n…(truncated)' : body}`);\n } catch {\n files.push(`--- ${p} ---\\n[could not read]`);\n }\n }\n const prompt =\n 'You are a senior engineer doing a critical code review. Review the changes below AGAINST THE TASK with deep, skeptical thinking — default to finding problems.\\n' +\n 'Focus on: correctness, edge cases (empty/boundary/negative inputs), unstated-but-implied requirements, and subtle logic bugs. Do NOT comment on style.\\n\\n' +\n `TASK:\\n${String(task ?? '').trim()}\\n\\n` +\n (notes ? `CONTEXT FROM THE AUTHOR:\\n${String(notes).trim()}\\n\\n` : '') +\n `CHANGED FILES:\\n${files.join('\\n\\n')}\\n\\n` +\n 'Reply with a short numbered list of concrete, actionable issues. If the changes correctly and completely satisfy the task with no edge cases missed, reply with exactly: LGTM';\n try {\n const r = (await ctx.ai.chat({ model: ctx.model, messages: [{ role: 'user', content: prompt }], stream: false })) as ChatResponse;\n const text = (r?.content ?? '').trim();\n return text || 'LGTM';\n } catch (e: any) {\n return `[Review] model error: ${e?.message ?? e} — skipped.`;\n }\n },\n };\n}\n","import type { AgentTool, ToolContext } from './tools';\n\n/** A single planning item. `in_progress` should mark exactly the one task currently being worked on. */\nexport interface TodoItem {\n content: string;\n status: 'pending' | 'in_progress' | 'completed';\n}\n\nconst MARK: Record<TodoItem['status'], string> = {\n pending: '[ ]',\n in_progress: '[~]',\n completed: '[x]',\n};\n\n/** Render a todo list as a stable checklist (one item per line). */\nfunction renderTodos(todos: TodoItem[]): string {\n if (todos.length === 0) return 'Todo list cleared (no items).';\n return todos.map((t) => `${MARK[t.status]} ${t.content}`).join('\\n');\n}\n\n/**\n * `TodoWrite` tool — the agent's planning scratchpad for multi-step tasks.\n * Use to lay out steps up front and keep them current (mark one `in_progress`,\n * flip finished ones to `completed`). Each call REPLACES the whole list.\n */\nexport const todoWriteTool: AgentTool = {\n name: 'TodoWrite',\n description:\n 'Maintain a todo list to plan and track a multi-step task. Replaces the current list with the provided todos and returns the rendered checklist. Mark exactly one item in_progress at a time; flip items to completed as you finish them.',\n parameters: {\n type: 'object',\n required: ['todos'],\n properties: {\n todos: {\n type: 'array',\n items: {\n type: 'object',\n required: ['content', 'status'],\n properties: {\n content: { type: 'string', description: 'the step to do' },\n status: { type: 'string', enum: ['pending', 'in_progress', 'completed'] },\n },\n },\n },\n },\n },\n async run({ todos }, ctx: ToolContext) {\n if (!Array.isArray(todos)) throw new Error('todos must be an array of { content, status } items.');\n const next: TodoItem[] = todos.map((t: any, i: number) => {\n const content = String(t?.content ?? '').trim();\n if (!content) throw new Error(`todos[${i}].content is required.`);\n const status = t?.status;\n if (status !== 'pending' && status !== 'in_progress' && status !== 'completed') {\n throw new Error(`todos[${i}].status must be one of pending|in_progress|completed (got ${JSON.stringify(status)}).`);\n }\n return { content, status };\n });\n ctx.todos = next; // replace the list in place on the shared context\n return renderTodos(next);\n },\n};\n","// Import the log module directly from libx.js source: libx.js's main bundle\n// doesn't re-export `log` as a named ESM export, and source-importing keeps\n// libx.js patches live (no rebuild) — matching the `bun link` workflow.\nimport { log } from 'libx.js/src/modules/log';\n\n/** Component-scoped logger (libx.js). debug/verbose gated via DEBUG env/localStorage. */\nexport const forComponent = (name: string) => log.forComponent(name);\nexport { log };\n","import type { AgentTool } from './tools';\nimport { forComponent } from './logging';\n\n/**\n * Web tools — `WebFetch` (retrieve a URL as readable text) and `WebSearch` (ranked\n * results via a configured provider). Opt-in (NOT in the default tool set): network\n * access is a deliberate capability. Factory-built with an injectable `fetch` so they\n * stay edge-portable and unit-testable without real network. `fetch` is read at call\n * time, so a no-network runtime simply has the tool return an error.\n */\nconst log = forComponent('web');\n\n/** Strip HTML to readable text — dependency-free: drop script/style/comments, block tags → newlines, decode common entities. */\nexport function htmlToText(html: string): string {\n let s = html\n .replace(/<script[\\s\\S]*?<\\/script>/gi, ' ')\n .replace(/<style[\\s\\S]*?<\\/style>/gi, ' ')\n .replace(/<title[\\s\\S]*?<\\/title>/gi, ' ') // drop title text (don't leak it into context)\n .replace(/<noscript[\\s\\S]*?<\\/noscript>/gi, ' ') // …same for noscript / textarea content\n .replace(/<textarea[\\s\\S]*?<\\/textarea>/gi, ' ')\n .replace(/<!--[\\s\\S]*?-->/g, ' ')\n .replace(/<\\/(p|div|li|h[1-6]|tr|section|article|header|footer|nav)>/gi, '\\n')\n .replace(/<br\\s*\\/?>/gi, '\\n')\n .replace(/<[^>]+>/g, ' ');\n s = s\n .replace(/&nbsp;/g, ' ').replace(/&amp;/g, '&').replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>').replace(/&quot;/g, '\"').replace(/&#0?39;/g, \"'\").replace(/&#x27;/gi, \"'\");\n return s\n .replace(/[ \\t\\f\\v]+/g, ' ')\n .split('\\n').map((l) => l.trim()).join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n}\n\nexport interface WebFetchOptions {\n /** Override the global fetch (tests inject a mock; edge runtimes can supply their own). */\n fetch?: typeof globalThis.fetch;\n maxBytes?: number; // cap the downloaded body (default 2 MB)\n maxChars?: number; // cap the returned text (default 100k)\n timeoutMs?: number; // request timeout (default 15s)\n /** Allow fetching private/loopback/link-local hosts (default false — blocks basic SSRF). */\n allowPrivateHosts?: boolean;\n}\n\n/**\n * Block obvious SSRF targets by hostname/IP literal (loopback, private ranges, link-local incl.\n * cloud metadata 169.254.169.254, `.internal`). Pure/edge-safe — no DNS, so DNS-rebinding and\n * redirect-to-internal are NOT covered (an embedder needing that should supply a vetting `fetch`).\n */\nexport function isPrivateHost(host: string): boolean {\n const h = host.toLowerCase().replace(/^\\[|\\]$/g, ''); // strip IPv6 brackets\n if (h === '' || h === 'localhost' || h.endsWith('.localhost') || h.endsWith('.internal')) return true;\n if (h === '::1' || h === '::' || h.startsWith('fe80:') || h.startsWith('fc') || h.startsWith('fd')) return true; // IPv6 loopback/link-local/ULA\n const m = h.match(/^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/);\n if (m) {\n const a = +m[1], b = +m[2];\n return a === 0 || a === 127 || a === 10 || (a === 169 && b === 254) || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168) || (a === 100 && b >= 64 && b <= 127);\n }\n return false;\n}\n\n/** Lazily-loaded node DNS resolver (absent on edge/browser) — closes DNS-rebinding (a public\n * hostname resolving to an internal IP) on the real-network path. Resolves null where unavailable. */\nlet _dnsLookup: ((h: string, opts?: any) => Promise<{ address: string }[]>) | null | undefined;\nasync function resolveIps(host: string): Promise<string[] | null> {\n if (_dnsLookup === undefined) {\n try { _dnsLookup = (await import('node:dns/promises')).lookup as any; }\n catch { _dnsLookup = null; } // edge/browser: no DNS — rely on the literal isPrivateHost check\n }\n if (!_dnsLookup) return null;\n try { return (await _dnsLookup(host, { all: true } as any)).map((a) => a.address); } catch { return null; }\n}\n\n/** Read a response body but stop at `maxBytes` of ACTUAL bytes (cancel the stream) — no unbounded download. */\nasync function readCapped(res: Response, maxBytes: number): Promise<string> {\n const reader = (res.body as any)?.getReader?.();\n if (!reader) { const t = await res.text(); return t.length > maxBytes ? t.slice(0, maxBytes) : t; }\n const chunks: Uint8Array[] = [];\n let total = 0;\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) { chunks.push(value); total += value.length; }\n if (total >= maxBytes) { try { await reader.cancel(); } catch { /* already closed */ } break; }\n }\n const out = new Uint8Array(Math.min(total, maxBytes));\n let off = 0;\n for (const c of chunks) { if (off >= out.length) break; const take = Math.min(c.length, out.length - off); out.set(c.subarray(0, take), off); off += take; }\n return new TextDecoder().decode(out);\n}\n\n/** Build a WebFetch tool. */\nexport function makeWebFetchTool(options: WebFetchOptions = {}): AgentTool {\n const maxBytes = options.maxBytes ?? 2_000_000;\n const maxChars = options.maxChars ?? 100_000;\n const timeoutMs = options.timeoutMs ?? 15_000;\n return {\n name: 'WebFetch',\n description:\n 'Fetch an http/https URL and return its readable text (HTML is stripped to text). Use to read docs or web pages. Returns the status line then up to ~100k chars of content.',\n parameters: { type: 'object', required: ['url'], properties: { url: { type: 'string', description: 'absolute http(s) URL' } } },\n async run({ url }) {\n const doFetch = options.fetch ?? globalThis.fetch;\n const customFetch = !!options.fetch; // injected fetch (tests/edge) owns its own vetting → skip DNS\n const u = String(url ?? '');\n try { new URL(u); } catch { return `Error: invalid URL: ${u}`; }\n if (!doFetch) return 'Error: no network (fetch) available in this runtime';\n // Reject a host that's a private/internal IP literal, or (on the real-network path) a name that\n // RESOLVES to one — re-checked on EVERY redirect hop so an external page can't bounce us internal.\n const hostBlock = async (hostname: string): Promise<string | null> => {\n if (options.allowPrivateHosts) return null;\n if (isPrivateHost(hostname)) return hostname;\n if (!customFetch) { const ips = await resolveIps(hostname); if (ips) for (const ip of ips) if (isPrivateHost(ip)) return `${hostname} → ${ip}`; }\n return null;\n };\n const ctl = new AbortController();\n const timer = setTimeout(() => ctl.abort(), timeoutMs);\n try {\n let current = u;\n let res: Response;\n for (let hop = 0; ; hop++) {\n const pu = new URL(current);\n if (pu.protocol !== 'http:' && pu.protocol !== 'https:') return `Error: only http/https URLs are allowed (got \"${pu.protocol}\")`;\n const blocked = await hostBlock(pu.hostname);\n if (blocked) return `Error: refusing to fetch a private/internal address (${blocked}) — set allowPrivateHosts to override`;\n res = await doFetch(current, { signal: ctl.signal, redirect: 'manual', headers: { 'user-agent': 'agentx (+https://github.com/Livshitz/agentx)' } });\n if (res.status >= 300 && res.status < 400 && res.headers.get('location')) {\n if (hop >= 5) return `Error fetching ${u}: too many redirects`;\n current = new URL(res.headers.get('location')!, current).toString(); // re-validated at loop top\n continue;\n }\n break;\n }\n const type = res.headers.get('content-type') ?? '';\n const body = await readCapped(res, maxBytes);\n const text = /html/i.test(type) || /^\\s*<(?:!doctype|html)/i.test(body) ? htmlToText(body) : body.trim();\n const capped = text.length > maxChars ? text.slice(0, maxChars) + `\\n… [truncated at ${maxChars} chars]` : text;\n return `${res.status} ${res.statusText} · ${new URL(current).host}\\n\\n${capped}`;\n } catch (e: any) {\n log.debug(`WebFetch ${u} failed`, e);\n return `Error fetching ${u}: ${e?.name === 'AbortError' ? `timed out after ${timeoutMs}ms` : (e?.message ?? e)}`;\n } finally {\n clearTimeout(timer);\n }\n },\n };\n}\n\nexport interface WebSearchOptions {\n fetch?: typeof globalThis.fetch;\n /** Provider: 'auto' (default) uses Tavily if an API key is present, else keyless DuckDuckGo. */\n provider?: 'auto' | 'tavily' | 'duckduckgo';\n /** API key for Tavily (default: process.env.TAVILY_API_KEY). */\n apiKey?: string;\n /** Tavily endpoint override. */\n endpoint?: string;\n maxResults?: number; // default 5\n timeoutMs?: number; // default 15s\n}\n\ninterface SearchHit { title: string; url: string; snippet: string }\n\n/** Decode a DuckDuckGo HTML result href: results are `//duckduckgo.com/l/?uddg=<encoded-target>` redirects. */\nexport function decodeDdgUrl(href: string): string {\n const m = href.match(/[?&]uddg=([^&]+)/);\n if (m) { try { return decodeURIComponent(m[1]); } catch { /* fall through */ } }\n return href.startsWith('//') ? 'https:' + href : href;\n}\n\n/** Parse DuckDuckGo's HTML results page into hits (title/url/snippet) — dependency-free, zips anchors to snippets in order. */\nexport function parseDdgHtml(html: string, max: number): SearchHit[] {\n const anchors = [...html.matchAll(/<a[^>]*class=\"[^\"]*result__a[^\"]*\"[^>]*href=\"([^\"]+)\"[^>]*>([\\s\\S]*?)<\\/a>/g)];\n const snippets = [...html.matchAll(/<a[^>]*class=\"[^\"]*result__snippet[^\"]*\"[^>]*>([\\s\\S]*?)<\\/a>/g)].map((m) => htmlToText(m[1]));\n const hits: SearchHit[] = [];\n for (let i = 0; i < anchors.length && hits.length < max; i++) {\n const url = decodeDdgUrl(anchors[i][1]);\n try { if (isPrivateHost(new URL(url).hostname)) continue; } catch { continue; } // skip junk/internal redirects\n hits.push({ title: htmlToText(anchors[i][2]) || '(untitled)', url, snippet: snippets[i] ?? '' });\n }\n return hits;\n}\n\nfunction formatHits(hits: SearchHit[]): string {\n if (!hits.length) return '(no results)';\n return hits.map((r, i) => `${i + 1}. ${r.title}\\n ${r.url}\\n ${r.snippet.replace(/\\s+/g, ' ').slice(0, 240)}`).join('\\n\\n');\n}\n\n/**\n * Build a WebSearch tool. Keyless by default (DuckDuckGo HTML) so it works in any deployment with\n * no setup; auto-upgrades to Tavily (better, agent-oriented results) when TAVILY_API_KEY is present.\n */\nexport function makeWebSearchTool(options: WebSearchOptions = {}): AgentTool {\n const tavilyEndpoint = options.endpoint ?? 'https://api.tavily.com/search';\n const maxResults = options.maxResults ?? 5;\n const timeoutMs = options.timeoutMs ?? 15_000;\n return {\n name: 'WebSearch',\n description:\n 'Search the web by query; returns ranked results (title, URL, snippet). Use to look things up, find pages, or research a topic — then WebFetch a result URL to read it in full.',\n parameters: { type: 'object', required: ['query'], properties: { query: { type: 'string' } } },\n async run({ query }) {\n const doFetch = options.fetch ?? globalThis.fetch;\n if (!doFetch) return 'Error: no network (fetch) available in this runtime';\n const q = String(query ?? '').trim();\n if (!q) return 'Error: empty query';\n const key = options.apiKey ?? process.env.TAVILY_API_KEY;\n const provider = options.provider ?? 'auto';\n const useTavily = provider === 'tavily' || (provider === 'auto' && !!key);\n const ctl = new AbortController();\n const timer = setTimeout(() => ctl.abort(), timeoutMs);\n try {\n if (useTavily) {\n if (!key) return 'Error: Tavily provider selected but TAVILY_API_KEY is not set';\n const res = await doFetch(tavilyEndpoint, {\n method: 'POST',\n signal: ctl.signal,\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ api_key: key, query: q, max_results: maxResults }),\n });\n if (!res.ok) return `Error: search provider returned ${res.status} ${res.statusText}`;\n const data: any = await res.json();\n const results = Array.isArray(data?.results) ? data.results.slice(0, maxResults) : [];\n return formatHits(results.map((r: any) => ({ title: r.title ?? '(untitled)', url: r.url ?? '', snippet: String(r.content ?? '') })));\n }\n // Keyless: DuckDuckGo HTML endpoint (no key, edge-portable).\n const res = await doFetch('https://html.duckduckgo.com/html/?q=' + encodeURIComponent(q), {\n signal: ctl.signal,\n headers: { 'user-agent': 'Mozilla/5.0 (compatible; agentx/1.0; +https://github.com/Livshitz/agentx)' },\n });\n if (!res.ok) return `Error: search returned ${res.status} ${res.statusText}`;\n return formatHits(parseDdgHtml(await res.text(), maxResults));\n } catch (e: any) {\n log.debug('WebSearch failed', e);\n return `Error searching: ${e?.name === 'AbortError' ? `timed out after ${timeoutMs}ms` : (e?.message ?? e)}`;\n } finally {\n clearTimeout(timer);\n }\n },\n };\n}\n\n/** Default instances (registered in the tool registry; opt-in by name). */\nexport const webFetchTool = makeWebFetchTool();\nexport const webSearchTool = makeWebSearchTool();\n","import type { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';\nimport type { AgentTool } from './tools';\n\n/**\n * Copy-on-write overlay over any base IFilesystem — the base is never touched until\n * you `commit()`. Writes/deletes/mkdirs accumulate in an in-memory overlay; reads see\n * overlay-then-base. This unlocks capabilities the swappable-VFS architecture makes\n * cheap and that a real agent wants:\n * - `snapshot()` / `rollback(token)` — checkpoint before a risky multi-file change and\n * undo it instantly (the `Checkpoint`/`Rollback` agent tools sit on these);\n * - `diff()` — exactly what changed vs the base (added/modified/deleted);\n * - `commit()` — flush the overlay down into the base when you're happy.\n * Edge-safe: pure IFilesystem, no node builtins.\n */\ninterface OverlayState {\n writes: Map<string, string>; // path -> content (created/modified)\n deletes: Set<string>; // tombstones hiding a base path\n dirs: Set<string>; // overlay-created directories\n}\n\nexport class OverlayFilesystem implements IFilesystem {\n private st: OverlayState = { writes: new Map(), deletes: new Set(), dirs: new Set() };\n private snapshots = new Map<string, OverlayState>();\n private seq = 0;\n\n constructor(private base: IFilesystem) {}\n\n // ---- path plumbing: delegate to the base so normalization/cwd are identical ----\n resolvePath(path: string, cwd?: string): string { return this.base.resolvePath(path, cwd ?? this.base.getCwd()); }\n getCwd(): string { return this.base.getCwd(); }\n setCwd(path: string): void { this.base.setCwd(path); }\n private abs(p: string): string { return this.resolvePath(p); }\n private parent(abs: string): string { const i = abs.lastIndexOf('/'); return i <= 0 ? '/' : abs.slice(0, i); }\n private name(abs: string): string { return abs.slice(abs.lastIndexOf('/') + 1); }\n\n // ---- reads (overlay wins; tombstones hide the base) ----\n async readFile(path: string): Promise<string> {\n const p = this.abs(path);\n if (this.st.deletes.has(p)) throw new Error(`File not found: ${path}`);\n if (this.st.writes.has(p)) return this.st.writes.get(p)!;\n return this.base.readFile(p);\n }\n\n async exists(path: string): Promise<boolean> {\n const p = this.abs(path);\n if (this.st.deletes.has(p)) return false;\n if (this.st.writes.has(p) || this.st.dirs.has(p)) return true;\n return this.base.exists(p);\n }\n\n async isFile(path: string): Promise<boolean> {\n const p = this.abs(path);\n if (this.st.deletes.has(p)) return false;\n if (this.st.writes.has(p)) return true;\n if (this.st.dirs.has(p)) return false;\n return this.base.isFile(p);\n }\n\n async isDirectory(path: string): Promise<boolean> {\n const p = this.abs(path);\n if (this.st.deletes.has(p)) return false;\n if (this.st.dirs.has(p)) return true;\n if (this.st.writes.has(p)) return false;\n return this.base.isDirectory(p);\n }\n\n async stat(path: string): Promise<FileMetadata> {\n const p = this.abs(path);\n if (this.st.deletes.has(p)) throw new Error(`File not found: ${path}`);\n if (this.st.writes.has(p)) {\n const size = this.st.writes.get(p)!.length;\n return { created: new Date(0), modified: new Date(0), size, permissions: '-rw-r--r--', isExecutable: false };\n }\n if (this.st.dirs.has(p)) return { created: new Date(0), modified: new Date(0), size: 0, permissions: 'drwxr-xr-x', isExecutable: false };\n return this.base.stat(p);\n }\n\n /** Merge base entries (minus tombstones) with overlay-created children of `path`. */\n async readDir(path: string): Promise<string[]> {\n const p = this.abs(path);\n if (await this.isFile(p)) throw new Error(`Not a directory: ${path}`); // match base contract (don't swallow → return [])\n const names = new Set<string>();\n try { for (const n of await this.base.readDir(p)) names.add(n); } catch { /* base dir may not exist; overlay may still have children */ }\n for (const w of [...this.st.writes.keys(), ...this.st.dirs]) if (this.parent(w) === p) names.add(this.name(w));\n for (const d of this.st.deletes) if (this.parent(d) === p) names.delete(this.name(d));\n if (names.size === 0 && !(await this.exists(p)) && p !== '/') throw new Error(`Directory not found: ${path}`);\n return [...names].sort();\n }\n\n // ---- writes (recorded in the overlay; base untouched until commit) ----\n async writeFile(path: string, content: string): Promise<void> {\n const p = this.abs(path);\n if (!(await this.exists(this.parent(p)))) throw new Error(`Parent directory does not exist: ${path}`);\n this.st.deletes.delete(p);\n this.st.writes.set(p, content);\n }\n\n async createDir(path: string): Promise<void> {\n const p = this.abs(path);\n if (await this.exists(p)) throw new Error(`File or directory already exists: ${path}`);\n if (!(await this.exists(this.parent(p)))) throw new Error(`Parent directory does not exist: ${path}`);\n this.st.deletes.delete(p);\n this.st.dirs.add(p);\n }\n\n async deleteFile(path: string): Promise<void> {\n const p = this.abs(path);\n if (!(await this.exists(p))) throw new Error(`File not found: ${path}`);\n if (await this.isDirectory(p) && (await this.readDir(p)).length > 0) throw new Error(`Directory not empty: ${path}`);\n this.st.writes.delete(p);\n this.st.dirs.delete(p);\n this.st.deletes.add(p); // tombstone (in case it exists in the base)\n }\n\n // ---- checkpointing ----\n private clone(s: OverlayState): OverlayState {\n return { writes: new Map(s.writes), deletes: new Set(s.deletes), dirs: new Set(s.dirs) };\n }\n\n /** Capture the current overlay; returns a token to `rollback(token)` to. */\n snapshot(label?: string): string {\n const token = label ?? `snap-${++this.seq}`;\n this.snapshots.set(token, this.clone(this.st));\n return token;\n }\n\n /** Discard all changes since the named snapshot (or the most recent if omitted). */\n rollback(token?: string): void {\n const key = token ?? [...this.snapshots.keys()].pop();\n if (key == null || !this.snapshots.has(key)) throw new Error(`No snapshot '${token ?? '(latest)'}'`);\n this.st = this.clone(this.snapshots.get(key)!);\n }\n\n /** Paths changed vs the base since this overlay was created (added = not in base, modified = was). */\n async diff(): Promise<{ added: string[]; modified: string[]; deleted: string[] }> {\n const added: string[] = [], modified: string[] = [];\n for (const p of this.st.writes.keys()) ((await this.base.exists(p)) ? modified : added).push(p);\n return { added: added.sort(), modified: modified.sort(), deleted: [...this.st.deletes].sort() };\n }\n\n /** Flush the overlay into the base (writes, mkdirs, deletes), then clear the overlay. */\n async commit(): Promise<void> {\n for (const d of this.st.dirs) if (!(await this.base.exists(d))) await this.base.createDir(d).catch(() => {});\n for (const [p, c] of this.st.writes) await this.base.writeFile(p, c);\n for (const p of this.st.deletes) if (await this.base.exists(p)) await this.base.deleteFile(p).catch(() => {});\n this.st = { writes: new Map(), deletes: new Set(), dirs: new Set() };\n this.snapshots.clear();\n }\n}\n\n/** Duck-typed checkpoint capability (so the tools work over any snapshot/rollback FS). */\ninterface Checkpointable { snapshot(label?: string): string; rollback(token?: string): void; }\nconst asCheckpointable = (fs: any): Checkpointable | null =>\n typeof fs?.snapshot === 'function' && typeof fs?.rollback === 'function' ? fs : null;\nconst NEEDS_OVERLAY = 'Error: checkpointing requires an OverlayFilesystem (run with `checkpoints: true` over one).';\n\n/** `Checkpoint` tool — snapshot the VFS before a risky multi-step change. */\nexport const checkpointTool: AgentTool = {\n name: 'Checkpoint',\n description: 'Snapshot the filesystem before a risky or exploratory multi-step change, so you can undo it. Returns a token to pass to Rollback if you need to revert.',\n parameters: { type: 'object', properties: { label: { type: 'string', description: 'optional name for the checkpoint' } } },\n async run({ label }, ctx) {\n const fs = asCheckpointable(ctx.fs);\n if (!fs) return NEEDS_OVERLAY;\n return `Checkpoint '${fs.snapshot(label ? String(label) : undefined)}' created — call Rollback with it to undo everything since.`;\n },\n};\n\n/** `Rollback` tool — undo all VFS changes since a Checkpoint. */\nexport const rollbackTool: AgentTool = {\n name: 'Rollback',\n description: 'Undo ALL filesystem changes made since a Checkpoint. Pass the token from Checkpoint, or omit to revert to the most recent one. Use when an approach went wrong.',\n parameters: { type: 'object', properties: { to: { type: 'string', description: 'checkpoint token (omit for most recent)' } } },\n async run({ to }, ctx) {\n const fs = asCheckpointable(ctx.fs);\n if (!fs) return NEEDS_OVERLAY;\n try { fs.rollback(to ? String(to) : undefined); return `Rolled back to checkpoint '${to ?? '(latest)'}'.`; }\n catch (e: any) { return `Error: ${e?.message ?? e}`; }\n },\n};\n\nexport const checkpointTools = (): AgentTool[] => [checkpointTool, rollbackTool];\n","import type { IFilesystem } from '@livx.cc/wcli/core';\nimport { CommandExecutor, registerHeadlessCommands } from '@livx.cc/wcli/core';\nimport type { Tool, ChatLike } from './llm';\nimport { grepTool, globTool, writeTool, multiEditTool, applyEditsTool, repoMapTool, reviewTool, fuzzyLineReplace } from './tools.structured';\nimport { todoWriteTool, type TodoItem } from './todo';\nimport { webFetchTool, webSearchTool } from './tools.web';\nimport { OverlayFilesystem } from './OverlayFilesystem';\nimport { redactSecrets, CONFIG_FILE_RE } from './redact';\nimport type { SandboxJobRegistry } from './tools.jobs';\n\n/** A structured multiple-choice question the model can pose to a human. */\nexport interface UserQuestion {\n question: string;\n header?: string;\n options: { label: string; description?: string }[];\n multiSelect?: boolean;\n}\n\n/**\n * The host / human-in-the-loop seam (the \"third seam\" beyond LLM + filesystem).\n * Injected per host: a CLI reads stdin, a browser renders a dialog, edge/headless\n * omits it. Unifies user-questions, permission/plan approvals, and notifications.\n */\nexport type HostEvent =\n | { kind: 'text_delta'; message: string }\n | { kind: 'thinking_delta'; message: string }\n | { kind: 'tool_use'; id: string; name: string; input: unknown }\n | { kind: 'tool_result'; id: string; output: string; isError?: boolean }\n | { kind: 'tool_result_image'; id: string; dataUrl: string }\n | { kind: string; message: string; data?: unknown };\n\nexport interface HostBridge {\n /** Ask the user a structured question; resolve to the chosen label(s) / free text. */\n ask?(q: UserQuestion): Promise<string>;\n /** Request approval for a sensitive action (permission 'ask' / plan approval). */\n confirm?(prompt: string, meta?: { tool: string; input: unknown }): Promise<boolean>;\n /** Emit a progress / notification event to the host UI (non-blocking). */\n notify?(event: HostEvent): void;\n}\n\nexport interface ToolContext {\n fs: IFilesystem;\n exec: CommandExecutor;\n /** path -> content snapshot at last Read/Edit; powers the read-before-edit staleness guard. */\n readState: Map<string, string>;\n /** optional host interaction channel; absent => autonomous/headless. */\n host?: HostBridge;\n /** optional run-cancellation signal (mirrors AgentOptions.signal); lets abort-aware tools\n * (e.g. the real shell) kill in-flight work when the run is cancelled. */\n signal?: AbortSignal;\n /** the agent's working todo list (TodoWrite planning aid); replaced wholesale per call. */\n todos: TodoItem[];\n /** optional syntax guardrail: if set, write-class tools refuse to persist a broken result. */\n lint?: (path: string, content: string) => string | null;\n /** optional PDF text extraction (node hosts wire a pdftotext-backed impl); absent => Read explains. */\n pdfText?: (path: string) => Promise<string>;\n /** optional model handle for tools that run their own LLM pass (e.g. Review, a self-critique).\n * Populated by the Agent from its own ai/model; absent => such tools degrade to a no-op. */\n ai?: ChatLike;\n model?: string;\n /** optional sandbox background-job registry; enables `bash({background:true})`. Absent => no backgrounding. */\n jobs?: SandboxJobRegistry;\n /** optional incremental-output channel: long-running tools (e.g. the real Shell) stream chunks\n * here mid-run. Wired PER CALL by Agent.dispatch to Hooks.onToolOutput (cleared when the call\n * settles — a late emit is a silent no-op). Fire-and-forget: never awaited, never part of the result. */\n emit?: (chunk: string) => void;\n /** Wrap a HUMAN-blocking await (permission/plan confirm, an interactive question) so the time\n * spent parked on the user is excluded from the run's wall-clock kill-switches. Wired by the Agent;\n * absent => no accounting (the promise is awaited as-is). Idle prompt time must not count as work. */\n parkHuman?<T>(p: Promise<T>): Promise<T>;\n}\n\nexport interface AgentTool {\n name: string;\n description: string;\n parameters: object; // JSON Schema for the function's arguments\n run(args: any, ctx: ToolContext): Promise<string | { text: string; images?: { mimeType: string; data: string }[] }>;\n}\n\n/** Build a tool context bound to a filesystem backend (Mem / Disk / …) and an optional host. */\nexport function makeContext(fs: IFilesystem, host?: HostBridge): ToolContext {\n const exec = new CommandExecutor(fs);\n registerHeadlessCommands(exec);\n return { fs, exec, readState: new Map(), host, todos: [] };\n}\n\n/** Convert AgentTools into the ai.libx.js `tools` array for chat(). */\nexport function toWireTools(tools: AgentTool[]): Tool[] {\n return tools.map((t) => ({\n type: 'function',\n function: { name: t.name, description: t.description, parameters: t.parameters },\n }));\n}\n\nconst numberLines = (content: string, offset = 0, limit?: number): string => {\n const lines = content.split('\\n');\n const start = Math.max(0, offset);\n const end = limit != null ? start + limit : lines.length;\n return lines\n .slice(start, end)\n .map((l, i) => `${start + i + 1}\\t${l}`)\n .join('\\n');\n};\n\n/** Keep huge tool output high-signal: head+tail with an omission marker (cuts re-runs to \"parse the wall\"). */\nexport function truncateOutput(s: string, headLines = 80, tailLines = 20): string {\n const lines = s.split('\\n');\n if (lines.length <= headLines + tailLines + 1) return s;\n const omitted = lines.length - headLines - tailLines;\n return [...lines.slice(0, headLines), `… (${omitted} lines omitted — narrow the command to see more) …`, ...lines.slice(-tailLines)].join('\\n');\n}\n\n/** Run any shell command line over the VFS (ls/cat/grep/find/head/tail/echo/mkdir/rm/mv/wc, pipes, redirects, &&/||/;). */\nexport const bashTool: AgentTool = {\n name: 'bash',\n description:\n 'Run a shell command. Supports ls, cat, grep, find, head, tail, echo, mkdir, rm, mv, cp, wc, pipes (|), redirects (>, >>), and chaining (&&, ||, ;). Best for: running tests/builds, file operations (mkdir/mv/rm), and piped workflows. For searching file contents, prefer `Grep` (structured results, no re-parse). For finding files by name, prefer `Glob`.',\n parameters: {\n type: 'object',\n required: ['command'],\n properties: {\n command: { type: 'string', description: 'the command line to execute' },\n background: { type: 'boolean', description: 'run detached over an isolated overlay (writes commit when it finishes); returns a job id to poll with JobOutput. Only worth it for slow work (remote VFS / long pipelines).' },\n },\n },\n async run({ command, background }, ctx) {\n if (background && ctx.jobs) return startBashJob(String(command ?? ''), ctx);\n const r = await ctx.exec.execute(String(command ?? ''));\n const out = truncateOutput((r.output ?? '').replace(/\\n+$/, ''));\n if (r.exitCode !== 0) {\n const err = (r.error ?? '').trim();\n return `[exit ${r.exitCode}]${err ? ' ' + err : ''}${out ? '\\n' + out : ''}`;\n }\n return out || '(command succeeded, no output)'; // explicit sentinel: don't re-run to \"check\"\n },\n};\n\n/** Kick a bash command into the background over an isolated overlay; its writes commit only on success.\n * A kill (abort) before completion skips the commit — the parent VFS is never touched mid-flight. */\nfunction startBashJob(command: string, ctx: ToolContext): string {\n const baseFs = ctx.fs;\n const id = ctx.jobs!.start(\n async ({ signal }) => {\n const overlay = new OverlayFilesystem(baseFs);\n const exec = new CommandExecutor(overlay);\n registerHeadlessCommands(exec);\n const r = await exec.execute(command); // wcli is sync-to-completion; abort can only gate the commit below\n if (signal.aborted) return '[killed before commit]';\n await overlay.commit(); // atomically flush this job's writes down into the parent VFS\n const out = truncateOutput((r.output ?? '').replace(/\\n+$/, ''));\n return r.exitCode !== 0 ? `[exit ${r.exitCode}] ${(r.error ?? '').trim()}\\n${out}`.trim() : out || '(command succeeded, no output)';\n },\n { kind: 'bash', label: command.slice(0, 60) },\n );\n return `Started background job ${id} — poll with JobOutput({id:\"${id}\"}) / JobStatus, stop with JobKill.`;\n}\n\n/** Image extensions the Read tool returns as a visual block (when the fs can read bytes). */\nconst IMG_MIME: Record<string, string> = { png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif', webp: 'image/webp' };\n\n/** Read a text file as 1-indexed numbered lines; arms the staleness guard for Edit. */\nexport const readTool: AgentTool = {\n name: 'Read',\n description:\n 'Read a file. Text files return 1-indexed numbered lines (with optional `offset`/`limit` and a re-Read pointer for partial reads). Image files (png/jpg/jpeg/gif/webp) return the picture itself so you can SEE it. PDFs return their extracted text. Always Read a file before Editing it.',\n parameters: {\n type: 'object',\n required: ['path'],\n properties: {\n path: { type: 'string' },\n offset: { type: 'number' },\n limit: { type: 'number' },\n },\n },\n async run({ path, offset, limit }, ctx) {\n // Image file → return it as a visual block. The adapter turns a tool result whose JSON carries a\n // `dataUrl` into an image tool_result the model can see. Needs a binary-capable fs (disk default);\n // the utf8 VFS (sandbox/Mem) can't, so we say so instead of corrupting the bytes.\n const ext = String(path).toLowerCase().split('.').pop() ?? '';\n // PDF → extracted text when the host wired an extractor (CLI: pdftotext); else say how to proceed.\n if (ext === 'pdf') {\n if (!ctx.pdfText) return `[${path} is a PDF — text extraction isn't available in this environment (install poppler's pdftotext and run on disk).]`;\n if (!(await ctx.fs.exists(path))) return `Error: File not found: ${path}`; // jail-aware: hidden paths read as absent\n const text = (await ctx.pdfText(ctx.fs.resolvePath(path))).trim();\n return text ? numberLines(text, Math.max(0, offset ?? 0), limit) : `[${path}: no extractable text (scanned/image-only PDF?)]`;\n }\n if (IMG_MIME[ext]) {\n const fs = ctx.fs as { readFileBytes?: (p: string) => Promise<Uint8Array> };\n if (typeof fs.readFileBytes !== 'function') {\n return `[${path} is an image, but this filesystem can't read binary — attach it as @${path} instead, or run on disk.]`;\n }\n const bytes = await fs.readFileBytes(path);\n const b64 = Buffer.from(bytes).toString('base64');\n return JSON.stringify({ dataUrl: `data:${IMG_MIME[ext]};base64,${b64}`, image: path });\n }\n const raw = await ctx.fs.readFile(path);\n ctx.readState.set(ctx.fs.resolvePath(path), raw); // staleness guard tracks the REAL content\n // Mask secret values in config files so keys can live there usably-but-hidden (line count is preserved).\n const content = CONFIG_FILE_RE.test(ctx.fs.resolvePath(path)) ? redactSecrets(raw) : raw;\n const total = content === '' ? 0 : content.split('\\n').length;\n const start = Math.max(0, offset ?? 0);\n const body = numberLines(content, start, limit);\n // snippet-with-pointer: when the slice doesn't cover the whole file, tell the\n // model what it's missing + how to pull it — so it expands precisely instead of re-reading blind.\n const shownEnd = limit != null ? Math.min(start + limit, total) : total;\n const shownCount = Math.max(0, shownEnd - start);\n if (shownCount >= total) return body; // whole file shown — no footer\n if (shownCount === 0) return `[no lines in range (offset ${start}${limit != null ? `, limit ${limit}` : ''}) — file has ${total} line(s)]`;\n return `${body}\\n\\n[lines ${start + 1}–${shownEnd} of ${total} · re-Read with offset/limit for the rest]`;\n },\n};\n\n/** Replace an exact, unique substring; requires a prior Read and guards against stale edits. */\nexport const editTool: AgentTool = {\n name: 'Edit',\n description:\n 'Replace an exact substring in a file. Requires a prior Read of the same file. `old_string` must occur exactly once — include surrounding context to disambiguate.',\n parameters: {\n type: 'object',\n required: ['path', 'old_string', 'new_string'],\n properties: {\n path: { type: 'string' },\n old_string: { type: 'string' },\n new_string: { type: 'string' },\n },\n },\n async run({ path, old_string, new_string }, ctx) {\n const key = ctx.fs.resolvePath(path);\n const snapshot = ctx.readState.get(key);\n if (snapshot == null) throw new Error(`File has not been read yet: ${path}. Read it before editing.`);\n const current = await ctx.fs.readFile(path);\n if (current !== snapshot) throw new Error(`File ${path} changed since it was read (stale). Re-read before editing.`);\n const count = old_string === '' ? 0 : current.split(old_string).length - 1;\n if (count > 1) throw new Error(`old_string is not unique in ${path} (${count} matches). Provide more surrounding context.`);\n let next: string, note = '';\n if (count === 1) {\n next = current.replace(old_string, () => new_string); // exact: function replacer, no $-pattern expansion\n } else {\n // exact match failed — try a whitespace-tolerant unique match before giving up (cuts re-read churn)\n const fuzzy = fuzzyLineReplace(current, old_string, new_string);\n if (fuzzy == null) throw new Error(`old_string not found in ${path}.`);\n next = fuzzy;\n note = ' (whitespace-tolerant match)';\n }\n if (ctx.lint) { const err = ctx.lint(path, next); if (err) throw new Error(err); }\n await ctx.fs.writeFile(path, next);\n ctx.readState.set(key, next);\n return `Edited ${path}${note}`;\n },\n};\n\n/** Session-exit tool: the model calls this when the user wants to end the conversation.\n * The `onExit` callback is injected by the host (CLI sets it to flip a flag that breaks the REPL loop). */\nexport function exitSessionTool(onExit: () => void): AgentTool {\n return {\n name: 'ExitSession',\n description:\n 'End the current session and exit the CLI. Call this when the user says goodbye, asks to quit, ' +\n 'or clearly indicates they want to stop the conversation (e.g. \"ok bye\", \"that\\'s all\", \"exit\", \"goodnight\").',\n parameters: { type: 'object', properties: {} },\n async run() {\n onExit();\n return 'Session ending. Goodbye!';\n },\n };\n}\n\nexport function defaultTools(): AgentTool[] {\n return [bashTool, readTool, editTool];\n}\n\n/**\n * The full catalog of selectable tools, keyed by name. The evolve loop's mutation\n * surface picks from this registry; embedders can build a custom tool set by name.\n */\nexport function toolRegistry(): Record<string, AgentTool> {\n const all = [bashTool, readTool, editTool, grepTool, globTool, writeTool, multiEditTool, applyEditsTool, repoMapTool, reviewTool(), todoWriteTool, webFetchTool, webSearchTool];\n return Object.fromEntries(all.map((t) => [t.name, t]));\n}\n\n/** Resolve a list of tool names against the registry (unknown names throw). */\nexport function toolsByName(names: string[]): AgentTool[] {\n const reg = toolRegistry();\n return names.map((n) => {\n const t = reg[n];\n if (!t) throw new Error(`unknown tool '${n}'. Known: ${Object.keys(reg).join(', ')}`);\n return t;\n });\n}\n","import { promises as fsp } from 'node:fs';\nimport * as np from 'node:path';\nimport type { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';\nimport { PathResolver } from '@livx.cc/wcli/core';\n\n/**\n * Real-disk backend implementing wcli's IFilesystem, rooted at `baseDir`.\n * The VFS path space ('/...') maps under baseDir, so the same agent/tools/commands\n * run unchanged against disk or memory — complete mem↔disk interchangeability.\n * Semantics mirror MemFilesystem (throws on missing parent / existing dir / etc.).\n */\nexport class NodeDiskFilesystem implements IFilesystem {\n private cwd = '/';\n private opts: { denySymlinks: boolean };\n\n constructor(private baseDir: string, opts: { denySymlinks?: boolean } = {}) {\n // denySymlinks (default ON): refuse to traverse a symlink anywhere in the path, so\n // a symlink planted inside the root cannot escape it (read/write/delete a target outside).\n this.opts = { denySymlinks: true, ...opts };\n }\n\n /** Ensure the root dir exists. */\n async init(): Promise<void> {\n await fsp.mkdir(this.baseDir, { recursive: true });\n }\n\n private real(vpath: string): string {\n return np.join(this.baseDir, '.' + vpath); // vpath is absolute in VFS space\n }\n\n // Verified non-symlink DIRECTORY components, with a short TTL: tree walks (Glob/Grep) hit the same\n // parents thousands of times; re-lstat'ing each per op is the dominant syscall cost. The 1s window\n // is an accepted race only against an out-of-band symlink swap mid-walk (this FS can't create\n // symlinks itself); leaf components are never cached.\n private verified = new Map<string, number>();\n private static VERIFY_TTL_MS = 1000;\n\n /** Throw if any existing component of `real` is a symlink (escape vector). */\n private async assertNoSymlink(real: string): Promise<void> {\n if (!this.opts.denySymlinks) return;\n const rel = np.relative(this.baseDir, real);\n if (rel === '' || rel.startsWith('..')) return; // root itself / outside (can't happen post-join)\n const parts = rel.split(np.sep);\n let cur = this.baseDir;\n const now = Date.now();\n for (let i = 0; i < parts.length; i++) {\n cur = np.join(cur, parts[i]);\n const isLeaf = i === parts.length - 1;\n if (!isLeaf && (this.verified.get(cur) ?? 0) > now) continue;\n let st;\n try { st = await fsp.lstat(cur); } catch { return; } // component doesn't exist yet (e.g. new file) — nothing further to check\n if (st.isSymbolicLink()) throw new Error('File not found: symlink not permitted');\n if (!isLeaf) {\n if (this.verified.size > 10_000) this.verified.clear(); // bound memory on huge trees\n this.verified.set(cur, now + NodeDiskFilesystem.VERIFY_TTL_MS);\n }\n }\n }\n\n resolvePath(path: string, cwd?: string): string {\n return PathResolver.resolve(path, cwd || this.cwd);\n }\n getCwd(): string { return this.cwd; }\n setCwd(path: string): void { this.cwd = PathResolver.normalize(path); }\n\n async readFile(path: string): Promise<string> {\n const r = this.real(this.resolvePath(path));\n try {\n await this.assertNoSymlink(r);\n const st = await fsp.stat(r);\n if (st.isDirectory()) throw new Error(`Not a file: ${path}`);\n return await fsp.readFile(r, 'utf8');\n } catch (e) {\n if (e instanceof Error && /Not a file/.test(e.message)) throw e;\n throw new Error(`File not found: ${path}`);\n }\n }\n\n /** Read raw bytes (for binary files like images). Not on the base IFilesystem (which is utf8-only) — an\n * optional capability the Read tool duck-types to return image blocks. Same symlink/jail guards as readFile. */\n async readFileBytes(path: string): Promise<Uint8Array> {\n const r = this.real(this.resolvePath(path));\n try {\n await this.assertNoSymlink(r);\n const st = await fsp.stat(r);\n if (st.isDirectory()) throw new Error(`Not a file: ${path}`);\n return await fsp.readFile(r); // no encoding → Buffer (Uint8Array)\n } catch (e) {\n if (e instanceof Error && /Not a file/.test(e.message)) throw e;\n throw new Error(`File not found: ${path}`);\n }\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n const r = this.real(this.resolvePath(path));\n await this.assertNoSymlink(r);\n const parent = np.dirname(r);\n try {\n if (!(await fsp.stat(parent)).isDirectory()) throw 0;\n } catch {\n throw new Error(`Parent directory does not exist: ${path}`);\n }\n await fsp.writeFile(r, content, 'utf8');\n }\n\n async deleteFile(path: string): Promise<void> {\n const r = this.real(this.resolvePath(path));\n await this.assertNoSymlink(r);\n let st;\n try { st = await fsp.stat(r); } catch { throw new Error(`File not found: ${path}`); }\n if (st.isDirectory()) {\n if ((await fsp.readdir(r)).length > 0) throw new Error(`Directory not empty: ${path}`);\n await fsp.rmdir(r);\n } else {\n await fsp.unlink(r);\n }\n }\n\n async readDir(path: string): Promise<string[]> {\n const r = this.real(this.resolvePath(path));\n try { await this.assertNoSymlink(r); return await fsp.readdir(r); }\n catch { throw new Error(`Directory not found: ${path}`); }\n }\n\n async createDir(path: string): Promise<void> {\n if (await this.exists(path)) throw new Error(`File or directory already exists: ${path}`);\n const r = this.real(this.resolvePath(path));\n await this.assertNoSymlink(r);\n const parent = np.dirname(r);\n try {\n if (!(await fsp.stat(parent)).isDirectory()) throw 0;\n } catch {\n throw new Error(`Parent directory does not exist: ${path}`);\n }\n await fsp.mkdir(r);\n }\n\n async exists(path: string): Promise<boolean> {\n const r = this.real(this.resolvePath(path));\n try { await this.assertNoSymlink(r); await fsp.stat(r); return true; } catch { return false; }\n }\n\n async stat(path: string): Promise<FileMetadata> {\n let s;\n const r = this.real(this.resolvePath(path));\n try { await this.assertNoSymlink(r); s = await fsp.stat(r); }\n catch { throw new Error(`File not found: ${path}`); }\n return {\n created: s.birthtime,\n modified: s.mtime,\n size: s.size,\n permissions: s.isDirectory() ? 'drwxr-xr-x' : '-rw-r--r--',\n isExecutable: false,\n };\n }\n\n async isDirectory(path: string): Promise<boolean> {\n const r = this.real(this.resolvePath(path));\n try { await this.assertNoSymlink(r); return (await fsp.stat(r)).isDirectory(); } catch { return false; }\n }\n async isFile(path: string): Promise<boolean> {\n const r = this.real(this.resolvePath(path));\n try { await this.assertNoSymlink(r); return (await fsp.stat(r)).isFile(); } catch { return false; }\n }\n}\n","import type { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';\nimport { globToRegExp } from './tools.structured';\n\n/**\n * Containment boundary A — a policy decorator over ANY IFilesystem.\n *\n * The agent only ever sees an IFilesystem, so what it can touch is exactly what we\n * mount. This jail:\n * - hides + blocks `deny` paths entirely (secrets: .env, keys, .git, …) — invisible\n * to read/stat/exists/readDir, unwritable;\n * - makes `readonly` paths readable but unwritable (the \"constitution\": pinned\n * grader/suite/criteria the self-evolve agent must never edit);\n * - optionally `confineTo` a set of subtrees (anything outside is denied);\n * - normalizes paths first, so `..` traversal (`/src/../.env`) is caught after resolution;\n * - reports every violation via `onViolation` (audit trail / circuit-breaker hook).\n *\n * Crucial limitation: this guards what the AGENT'S TOOLS touch. It does NOT contain\n * code executed against the real disk at eval time (the grader imports agent-written\n * code) — that is boundary B (a sandboxed subprocess). See mind/08-self-evolve.md.\n */\nexport class JailedFilesystem implements IFilesystem {\n public options: JailOptions;\n private denyRe: RegExp[];\n private roRe: RegExp[];\n private confineRe?: RegExp[];\n\n constructor(private inner: IFilesystem, options?: Partial<JailOptions>) {\n this.options = { ...new JailOptions(), ...options };\n // case-insensitive so /.ENV, /Id_Rsa, … can't slip past a lowercase rule.\n this.denyRe = this.options.deny.map((g) => globToRegExp(g, true));\n this.roRe = this.options.readonly.map((g) => globToRegExp(g, true));\n this.confineRe = this.options.confineTo?.map((g) => globToRegExp(g, true));\n }\n\n private abs(path: string): string {\n return this.inner.resolvePath(path, this.inner.getCwd());\n }\n\n /** Throw if reading `path` is not permitted (denied or out of confinement). */\n private guardRead(op: string, path: string): string {\n const abs = this.abs(path);\n if (this.confineRe && !this.confineRe.some((r) => r.test(abs))) return this.violate(op, abs, 'confine');\n if (this.denyRe.some((r) => r.test(abs))) return this.violate(op, abs, 'deny');\n return abs;\n }\n\n /** Throw if writing/deleting `path` is not permitted (denied, readonly, or out of confinement). */\n private guardWrite(op: string, path: string): string {\n const abs = this.guardRead(op, path); // write implies read access first\n if (this.roRe.some((r) => r.test(abs))) return this.violate(op, abs, 'readonly');\n return abs;\n }\n\n private violate(op: string, abs: string, rule: string): never {\n this.note(op, abs, rule);\n // Read denials masquerade as \"not found\" to avoid confirming a secret's existence.\n if (rule === 'deny' || rule === 'confine') throw new Error(`File not found: ${abs}`);\n throw new Error(`Blocked by filesystem jail (${rule}): ${abs}`);\n }\n\n /** Fire the audit hook without throwing (for boolean probes that must still return false). */\n private note(op: string, abs: string, rule: string): void {\n this.options.onViolation?.({ op, path: abs, rule });\n }\n\n /** Is `abs` (already-resolved) visible? If not, fire the audit hook (op given) and return false. */\n private visible(abs: string, op?: string): boolean {\n if (this.confineRe && !this.confineRe.some((r) => r.test(abs))) { if (op) this.note(op, abs, 'confine'); return false; }\n if (this.denyRe.some((r) => r.test(abs))) { if (op) this.note(op, abs, 'deny'); return false; }\n return true;\n }\n\n async readFile(path: string): Promise<string> { return this.inner.readFile(this.guardRead('readFile', path)); }\n /** Forward the optional binary-read capability (if the inner fs has it), jailed like readFile. */\n async readFileBytes(path: string): Promise<Uint8Array> {\n const inner = this.inner as { readFileBytes?: (p: string) => Promise<Uint8Array> };\n if (typeof inner.readFileBytes !== 'function') throw new Error('binary read not supported by this filesystem');\n return inner.readFileBytes(this.guardRead('readFileBytes', path));\n }\n async writeFile(path: string, content: string): Promise<void> { return this.inner.writeFile(this.guardWrite('writeFile', path), content); }\n async deleteFile(path: string): Promise<void> { return this.inner.deleteFile(this.guardWrite('deleteFile', path)); }\n async createDir(path: string): Promise<void> { return this.inner.createDir(this.guardWrite('createDir', path)); }\n async stat(path: string): Promise<FileMetadata> { return this.inner.stat(this.guardRead('stat', path)); }\n\n // Boolean probes stay invisible (return false on a denied path) BUT still fire the\n // audit hook — otherwise an agent could enumerate secrets via exists() without\n // ever tripping the circuit breaker.\n async exists(path: string): Promise<boolean> {\n const abs = this.abs(path);\n return this.visible(abs, 'exists') ? this.inner.exists(abs) : false;\n }\n async isDirectory(path: string): Promise<boolean> {\n const abs = this.abs(path);\n return this.visible(abs, 'isDirectory') ? this.inner.isDirectory(abs) : false;\n }\n async isFile(path: string): Promise<boolean> {\n const abs = this.abs(path);\n return this.visible(abs, 'isFile') ? this.inner.isFile(abs) : false;\n }\n\n /** List a directory, filtering out entries the policy hides. */\n async readDir(path: string): Promise<string[]> {\n const abs = this.guardRead('readDir', path);\n const entries = await this.inner.readDir(abs);\n return entries.filter((name) => this.visible(abs === '/' ? `/${name}` : `${abs}/${name}`));\n }\n\n resolvePath(path: string, cwd?: string): string { return this.inner.resolvePath(path, cwd ?? this.inner.getCwd()); }\n getCwd(): string { return this.inner.getCwd(); }\n /** Guard cwd too: the jail must never be able to \"stand\" on a denied/out-of-confine dir. */\n setCwd(path: string): void {\n const abs = this.abs(path);\n if (!this.visible(abs, 'setCwd')) throw new Error(`File not found: ${abs}`);\n this.inner.setCwd(abs);\n }\n}\n\n/** Default denylist: secrets and VCS internals that must never be read or written.\n * Patterns are matched case-insensitively (so /.ENV is covered too). */\nexport const DEFAULT_DENY: string[] = [\n // env / config secrets\n '**/.env', '**/.env.*', '**/.npmrc', '**/.netrc',\n // private keys & certs\n '**/*.pem', '**/*.key', '**/*.crt', '**/*.cert', '**/*.p12', '**/*.pfx',\n '**/id_rsa', '**/id_rsa.*', '**/id_ed25519', '**/id_ed25519.*',\n '**/id_dsa', '**/id_dsa.*', '**/id_ecdsa', '**/id_ecdsa.*',\n // credential stores (dir AND contents)\n '**/.ssh', '**/.ssh/**', '**/.aws', '**/.aws/**',\n '**/.docker', '**/.docker/**', '**/.dockercfg',\n '**/.kube', '**/.kube/**', '**/.kubeconfig',\n '**/credentials', '**/.credentials', '**/secrets.json',\n // VCS internals + git config (can carry tokens / remote creds)\n '**/.git', '**/.git/**', '**/.gitconfig', '**/.gitmodules',\n];\n\nexport class JailOptions {\n /** Globs that are invisible and unwritable (secrets). */\n deny: string[] = [...DEFAULT_DENY];\n /** Globs readable but not writable/deletable (the pinned constitution). */\n readonly: string[] = [];\n /** If set, only paths matching these globs are accessible at all. */\n confineTo?: string[];\n /** Audit hook fired on every blocked operation (drives the circuit breaker). */\n onViolation?: (v: { op: string; path: string; rule: string }) => void;\n}\n","/**\n * Tier-1 OS sandbox for the real `Shell` tool (mind/03-roadmap.md \"capability tiers\").\n *\n * Wraps the spawned `/bin/sh` in the platform's process sandbox so a hostile/buggy command\n * can read the machine but can only WRITE inside an allowlist (cwd + tmp + extra `writePaths`),\n * and gets no network unless granted:\n * - macOS: `sandbox-exec` (seatbelt) with a generated profile\n * - Linux: `bwrap` (bubblewrap) with `--ro-bind / /` + writable binds\n *\n * Pure argv builders (unit-testable, no node imports) + an async wrapper-binary locator.\n * This complements — does not replace — env secret-scrubbing and the permission prompt:\n * the FS jail can't contain a real process; this makes the *process* itself contained.\n */\n\nexport class OsSandboxOptions {\n /** Allow outbound network. Default OFF (Tier-1: no network unless granted). */\n network = false;\n /** Extra absolute paths writable beyond cwd + tmp (e.g. a build cache). */\n writePaths: string[] = [];\n}\n\nexport interface SandboxWrap {\n bin: string;\n args: string[]; // full argv: wrapper flags + /bin/sh -c <command>\n}\n\n/** Writable allowlist shared by both platforms: cwd, the tmp roots, /dev. */\nfunction writable(cwd: string, o: OsSandboxOptions, tmpDir?: string): string[] {\n const set = new Set<string>([cwd, '/tmp', '/private/tmp', '/private/var/folders', '/dev', ...(tmpDir ? [tmpDir] : []), ...o.writePaths]);\n return [...set];\n}\n\nconst sbQuote = (p: string) => `\"${p.replace(/([\"\\\\])/g, '\\\\$1')}\"`;\n\n/** macOS seatbelt profile: allow everything, then deny writes/network, then re-allow the allowlist\n * (seatbelt resolves conflicts by specificity, so subpath allows override the broad deny). */\nexport function seatbeltProfile(cwd: string, o: OsSandboxOptions, tmpDir?: string): string {\n const allows = writable(cwd, o, tmpDir).map((p) => `(subpath ${sbQuote(p)})`).join(' ');\n return [\n '(version 1)',\n '(allow default)',\n ...(o.network ? [] : ['(deny network*)']),\n '(deny file-write*)',\n `(allow file-write* ${allows})`,\n ].join('\\n');\n}\n\n/** Build the wrapped argv for `sh -c <command>`, or null if `platform` has no supported wrapper. */\nexport function sandboxArgv(command: string, cwd: string, opts: Partial<OsSandboxOptions> = {}, platform: string = process.platform, tmpDir?: string): SandboxWrap | null {\n const o = { ...new OsSandboxOptions(), ...opts };\n if (platform === 'darwin') {\n return { bin: '/usr/bin/sandbox-exec', args: ['-p', seatbeltProfile(cwd, o, tmpDir), '/bin/sh', '-c', command] };\n }\n if (platform === 'linux') {\n const binds = writable(cwd, o, tmpDir).filter((p) => p !== '/dev' && !p.startsWith('/private')).flatMap((p) => ['--bind-try', p, p]);\n return {\n bin: 'bwrap',\n args: ['--ro-bind', '/', '/', ...binds, '--dev', '/dev', '--proc', '/proc', '--die-with-parent', ...(o.network ? [] : ['--unshare-net']), '/bin/sh', '-c', command],\n };\n }\n return null;\n}\n\n/** Locate the wrapper binary for this platform; null = sandboxing unavailable here. */\nexport async function findSandboxWrapper(platform: string = process.platform): Promise<string | null> {\n const { existsSync } = await import('node:fs');\n if (platform === 'darwin') return existsSync('/usr/bin/sandbox-exec') ? '/usr/bin/sandbox-exec' : null;\n if (platform === 'linux') {\n for (const dir of (process.env.PATH ?? '/usr/bin:/bin').split(':')) if (dir && existsSync(`${dir}/bwrap`)) return `${dir}/bwrap`;\n return null;\n }\n return null;\n}\n","import type { AgentTool } from './tools';\nimport { truncateOutput } from './tools';\nimport { redactSecrets } from './redact';\nimport { forComponent } from './logging';\nimport { sandboxArgv, findSandboxWrapper, type OsSandboxOptions } from './shell.sandbox';\n\n/**\n * Real shell tool — node-only, OPT-IN, and deliberately NOT edge-portable.\n *\n * ⚠️ Unlike the default VFS `bash` (a sandboxed JS interpreter over the virtual filesystem),\n * this spawns a REAL `/bin/sh` process. It can run `bun`, `git`, `ssh`, scripts, deploys —\n * and, by the same token, it is NOT sandboxed: only cwd-binding constrains it. It is a\n * deliberate host escalation, kept out of `defaultTools()`/`toolRegistry()` and out of the\n * edge-safe `src/index.ts` (same policy as `mcp.client.ts`). A host opts in explicitly:\n *\n * tools: [...defaultTools(), makeRealShellTool({ cwd: nodeDiskRoot })]\n *\n * Mirrors `tools.web.ts`: a factory with an injectable `spawn` (tests + edge never import\n * node:child_process), an options bag, abort + timeout honored, output capped. Safety beyond\n * cwd-binding is the host's to add (e.g. a PermissionPolicy `decision:'ask'` per command, or\n * an OS sandbox wrapper) — see mind/03-roadmap.md \"OS-level access — capability tiers\".\n */\n\nconst log = forComponent('shell');\n\n/** Normalize shell output for return: trim trailing newlines, mask secret values, then size-truncate.\n * Redaction runs BEFORE truncation so a masked tail can't smuggle a secret past the line cap. */\nconst clean = (s: string): string => truncateOutput(redactSecrets(s.replace(/\\n+$/, '')));\n\n/** The slice of node's `child_process.spawn` we depend on — injectable so tests supply a fake. */\nexport type SpawnFn = (\n command: string,\n args: string[],\n options: {\n cwd?: string;\n env?: Record<string, string | undefined>;\n signal?: AbortSignal;\n /** stdio layout. We force stdin to /dev/null so a child can't block on (or steal) the REPL's input. */\n stdio?: ['ignore', 'pipe', 'pipe'];\n /** Run in a new session/process group (setsid) — detaches from the controlling terminal. See DETACHED. */\n detached?: boolean;\n },\n) => SpawnedProcess;\n\n/** Minimal `ChildProcess` surface this tool uses. */\nexport interface SpawnedProcess {\n stdout?: { on(ev: 'data', cb: (chunk: any) => void): void } | null;\n stderr?: { on(ev: 'data', cb: (chunk: any) => void): void } | null;\n on(ev: 'close', cb: (code: number | null) => void): void;\n on(ev: 'error', cb: (err: Error) => void): void;\n kill(signal?: string): void;\n /** Child PID — present on the real node child; used to signal the whole process group on abort. */\n pid?: number;\n}\n\n/**\n * Detach every spawned child from the REPL's controlling terminal.\n *\n * `stdio: ['ignore', 'pipe', 'pipe']` — stdin is /dev/null (clean EOF; nothing to block on).\n * `detached: true` — setsid() puts the child in its OWN session with NO controlling tty.\n *\n * Without this a child inherits the agent's tty: an interactive prompt (`sudo`, `ssh`, a git\n * credential helper) opens `/dev/tty` directly and then RACES the REPL's raw-mode input reader for\n * the user's keystrokes — a deadlock that also captures whatever the user types (e.g. a password)\n * into the agent instead of the program. Detached, those programs find no tty and fail FAST with a\n * legible error (\"sudo: a terminal is required …\") which the model can act on (tell the user to run\n * it via `!`), instead of hanging until the 120s timeout. Side benefit: the child is a process-group\n * leader, so abort/timeout can reap the whole subtree, not just /bin/sh. */\nconst DETACHED = { stdio: ['ignore', 'pipe', 'pipe'] as ['ignore', 'pipe', 'pipe'], detached: true };\n\n/** Signal a child's WHOLE process group (`-pid`). Children are group leaders (DETACHED), so `proc.kill`\n * hits only /bin/sh and orphans descendants; this reaps the subtree. Best-effort — the group may\n * already be gone, and the fake spawn in tests has no real pid. Returns false when nothing was signaled. */\nfunction killGroup(proc: SpawnedProcess | undefined, signal: 'SIGTERM' | 'SIGKILL'): boolean {\n if (!proc?.pid) return false;\n try { process.kill(-proc.pid, signal); return true; } catch { return false; /* already exited / no such group */ }\n}\n\nexport interface RealShellOptions {\n /** Working directory the shell is bound to (typically a NodeDiskFilesystem `baseDir`). Required. */\n cwd: string;\n /** Shell binary for `-c` (e.g. the user's `$SHELL`). Default `/bin/sh`. Only honored when NOT\n * OS-sandboxed (the sandbox wrapper pins its own shell). */\n shell?: string;\n /** Override the spawner (tests inject a fake; default lazily imports node:child_process). */\n spawn?: SpawnFn;\n /** Per-command wall-clock cap (kill on overrun). Default 120s. */\n timeoutMs?: number;\n /** Extra env merged over the (optionally scrubbed) base env for the child. */\n env?: Record<string, string>;\n /** Strip likely-secret vars (API keys, tokens, cloud creds) from the child's env. Default ON.\n * The FS jail does NOT contain a real process, so this is the seam that keeps `echo $ANTHROPIC_API_KEY`\n * from leaking the host's secrets to a spawned command. `false` passes `process.env` through verbatim. */\n redactEnv?: boolean;\n /** Job registry enabling `Shell({background:true})` (long-running processes). Pair with `makeShellJobTools`. */\n registry?: ShellJobRegistry;\n /** Tier-1 OS sandbox: wrap /bin/sh in sandbox-exec (macOS) / bwrap (Linux) — writes confined to\n * cwd+tmp, network blocked unless granted. `true` = defaults; commands FAIL (don't silently run\n * unsandboxed) if no wrapper exists on this platform. See src/shell.sandbox.ts. */\n osSandbox?: boolean | Partial<OsSandboxOptions>;\n}\n\n/** Resolve the (bin,args) to spawn for `command`, honoring the optional OS sandbox.\n * Throws when sandboxing was requested but this platform has no wrapper — fail closed. */\nasync function spawnArgvFor(command: string, cwd: string, osSandbox?: boolean | Partial<OsSandboxOptions>): Promise<{ bin: string; args: string[] }> {\n if (!osSandbox) return { bin: '/bin/sh', args: ['-c', command] };\n const opts = osSandbox === true ? {} : osSandbox;\n const wrapper = await findSandboxWrapper();\n const wrapped = wrapper ? sandboxArgv(command, cwd, opts, process.platform, process.env.TMPDIR) : null;\n if (!wrapped) throw new Error(`OS sandbox requested but no wrapper available on ${process.platform} (need sandbox-exec or bwrap)`);\n return wrapped;\n}\n\n/** Env var names that look like secrets and are dropped before spawning (unless redactEnv:false). */\nconst SECRET_ENV_RE = /(_API_KEY|_TOKEN|_SECRET|_PASSWORD|_PRIVATE_KEY|^AWS_|^GITHUB_TOKEN$|^OPENAI_|^ANTHROPIC_|^GOOGLE_|^GEMINI_|^GROQ_|^NPM_TOKEN$)/i;\n\n/** Build the child's env: `process.env` minus likely-secrets (when redacting), plus explicit `env`. */\nfunction childEnv(opts: { env?: Record<string, string>; redactEnv?: boolean }): Record<string, string | undefined> {\n const base: Record<string, string | undefined> = {};\n const redact = opts.redactEnv !== false; // default ON\n for (const [k, v] of Object.entries(process.env)) if (!(redact && SECRET_ENV_RE.test(k))) base[k] = v;\n return { ...base, ...opts.env };\n}\n\n/** Lazily resolve node's spawn (kept out of any eager edge import path). */\nlet _spawn: SpawnFn | undefined;\nasync function nodeSpawn(): Promise<SpawnFn> {\n if (!_spawn) _spawn = (await import('node:child_process')).spawn as unknown as SpawnFn;\n return _spawn;\n}\n\n// ---------------------------------------------------------------------------\n// Background jobs — long-running processes the agent starts, polls, and kills.\n// ---------------------------------------------------------------------------\nexport type JobStatus = 'running' | 'exited' | 'killed' | 'error';\n\nexport interface ShellJobConfig {\n cwd: string;\n spawn?: SpawnFn;\n env?: Record<string, string>;\n redactEnv?: boolean;\n /** Tail buffer cap per job (bytes); older output is dropped. Default 256 KB. */\n maxBuffer?: number;\n /** Kill all jobs on process exit (the CLI sets this; tests leave it off to avoid global handlers). */\n killOnExit?: boolean;\n /** Tier-1 OS sandbox for background jobs too (same semantics as RealShellOptions.osSandbox). */\n osSandbox?: boolean | Partial<OsSandboxOptions>;\n}\n\ninterface Job { command: string; buf: string; status: JobStatus; exitCode?: number; proc?: SpawnedProcess; }\n\n/**\n * Per-session registry of background `/bin/sh` jobs. Backs `Shell({background:true})` and the\n * `ShellOutput`/`ShellStatus`/`ShellKill` tools. Output accumulates into a tail-capped ring so a\n * chatty process can't OOM. Bounded + killable; the CLI wires `killOnExit` so children are reaped.\n */\nexport class ShellJobRegistry {\n private jobs = new Map<string, Job>();\n private seq = 0;\n constructor(private cfg: ShellJobConfig) {\n if (cfg.killOnExit && typeof process !== 'undefined') process.once('exit', () => this.killAll());\n }\n\n async start(command: string): Promise<string> {\n const id = `job-${++this.seq}`;\n const max = this.cfg.maxBuffer ?? 256 * 1024;\n const job: Job = { command, buf: '', status: 'running' };\n const append = (chunk: any) => {\n const s = typeof chunk === 'string' ? chunk : chunk?.toString?.('utf8') ?? '';\n job.buf = (job.buf + s).slice(-max); // ring: keep the tail\n };\n try {\n const spawn = this.cfg.spawn ?? (await nodeSpawn());\n const argv = this.cfg.osSandbox ? await spawnArgvFor(command, this.cfg.cwd, this.cfg.osSandbox) : { bin: '/bin/sh', args: ['-c', command] };\n const proc = spawn(argv.bin, argv.args, { cwd: this.cfg.cwd, env: childEnv(this.cfg), ...DETACHED });\n job.proc = proc;\n proc.stdout?.on('data', append);\n proc.stderr?.on('data', append);\n proc.on('error', (err: any) => { if (job.status === 'running') { job.status = 'error'; append(`\\n[error] ${err?.message ?? err}`); } });\n proc.on('close', (code: number | null) => { if (job.status === 'running') { job.status = 'exited'; job.exitCode = code ?? undefined; } });\n } catch (e: any) {\n job.status = 'error';\n job.buf = `failed to spawn: ${e?.message ?? e}`;\n }\n this.jobs.set(id, job);\n return id;\n }\n\n /** Current tail output for a job (null = no such job). */\n output(id: string): string | null { return this.jobs.get(id)?.buf ?? (this.jobs.has(id) ? '' : null); }\n\n status(id: string): { status: JobStatus; exitCode?: number; bytes: number } | null {\n const j = this.jobs.get(id);\n return j ? { status: j.status, exitCode: j.exitCode, bytes: j.buf.length } : null;\n }\n\n list(): Array<{ id: string; command: string; status: JobStatus }> {\n return [...this.jobs].map(([id, j]) => ({ id, command: j.command, status: j.status }));\n }\n\n kill(id: string): boolean {\n const j = this.jobs.get(id);\n if (!j) return false;\n // Group-kill: bg children are detached (own group), so SIGTERM the whole subtree — not just /bin/sh —\n // else a forked server survives the kill and the agent's exit teardown. Fall back to the pid for fakes.\n if (j.status === 'running') { if (!killGroup(j.proc, 'SIGTERM')) { try { j.proc?.kill('SIGTERM'); } catch { /* already gone */ } } j.status = 'killed'; }\n return true;\n }\n\n killAll(): void { for (const id of this.jobs.keys()) this.kill(id); }\n}\n\n/** Build an opt-in real-shell tool bound to `options.cwd`. */\nexport function makeRealShellTool(options: RealShellOptions): AgentTool {\n const timeoutMs = options.timeoutMs ?? 120_000;\n return {\n name: 'Shell',\n description:\n 'Run a shell command via /bin/sh in the working directory. ' +\n 'Executes any installed binary — ls, cat, grep, git, bun, node, curl, scripts, etc. ' +\n 'Returns combined stdout+stderr; non-zero exits are prefixed `[exit N]`. ' +\n 'Runs non-interactively with no terminal (stdin is /dev/null): commands that prompt for input ' +\n 'fail fast rather than hang — for privileged actions use a non-interactive flag (e.g. `sudo -n`), ' +\n 'or ask the user to run the command themselves. ' +\n 'Set `background:true` for long-running processes (servers, watchers) — returns a job id immediately; poll with ShellOutput, stop with ShellKill.',\n parameters: {\n type: 'object',\n required: ['command'],\n properties: {\n command: { type: 'string', description: 'the shell command line to execute' },\n background: { type: 'boolean', description: 'run detached and return a job id immediately (for servers/watchers/long builds)' },\n },\n },\n async run({ command, background }, ctx) {\n const cmd = String(command ?? '');\n if (!cmd.trim()) return '[exit 1] empty command';\n if (background) {\n if (!options.registry) return 'Error: background execution is not enabled in this host (no job registry).';\n const id = await options.registry.start(cmd);\n return `Started background job ${id}. Poll output with ShellOutput({id:\"${id}\"}), check ShellStatus({id:\"${id}\"}), stop with ShellKill({id:\"${id}\"}).`;\n }\n const spawn = options.spawn ?? (await nodeSpawn());\n // Sandbox-off keeps this path await-free (after spawn resolution) so an abort racing the call\n // start still lands before listener registration, exactly as pre-sandbox semantics.\n let argv = { bin: options.shell || '/bin/sh', args: ['-c', cmd] };\n if (options.osSandbox) {\n try {\n argv = await spawnArgvFor(cmd, options.cwd, options.osSandbox);\n } catch (e: any) {\n return `[exit 1] ${e?.message ?? e}`; // fail closed — never run unsandboxed when sandboxing was asked for\n }\n }\n // Compose abort: the run's signal (ctx.signal) OR our per-command timeout both kill the child.\n const ctl = new AbortController();\n const onAbort = () => ctl.abort();\n if (ctx.signal) { if (ctx.signal.aborted) ctl.abort(); else ctx.signal.addEventListener('abort', onAbort, { once: true }); }\n let timedOut = false;\n const timer = setTimeout(() => { timedOut = true; ctl.abort(); }, timeoutMs);\n // The child is its own process-group leader (DETACHED): node's `signal` kills only /bin/sh, so on\n // abort also SIGKILL the whole group to reap any descendants (see killGroup).\n // Incremental output → ctx.emit (when the host listens), coalesced to ≥250ms / ≥1KB batches\n // so a chatty child doesn't spam hooks. Redacted per batch (the final result is re-redacted\n // whole — a secret split across batch boundaries can slip the per-batch pass, hence the cap\n // on what consumers may do with chunks: display/digest, never persistence).\n let pend = '';\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n const flushEmit = (ctx: { emit?: (s: string) => void }) => {\n if (flushTimer) { clearTimeout(flushTimer); flushTimer = null; }\n if (pend) { ctx.emit?.(redactSecrets(pend)); pend = ''; }\n };\n try {\n return await new Promise<string>((resolve) => {\n let out = '';\n let settled = false;\n const finish = (s: string) => { if (settled) return; settled = true; resolve(s); };\n let proc: SpawnedProcess;\n try {\n proc = spawn(argv.bin, argv.args, { cwd: options.cwd, env: childEnv(options), signal: ctl.signal, ...DETACHED });\n } catch (e: any) {\n return finish(`[exit 1] failed to spawn shell: ${e?.message ?? e}`);\n }\n // Reap the detached group when the timeout/cancel fires (node's `signal` only hits /bin/sh).\n if (ctl.signal.aborted) killGroup(proc, 'SIGKILL');\n else ctl.signal.addEventListener('abort', () => killGroup(proc, 'SIGKILL'), { once: true });\n const collect = (chunk: any) => {\n const s = typeof chunk === 'string' ? chunk : chunk?.toString?.('utf8') ?? '';\n out += s;\n if (ctx.emit && !settled) {\n pend += s;\n if (pend.length >= 1024) flushEmit(ctx);\n else flushTimer ??= setTimeout(() => flushEmit(ctx), 250);\n }\n };\n proc.stdout?.on('data', collect);\n proc.stderr?.on('data', collect);\n proc.on('error', (err: any) => {\n // AbortError fires here when ctl.abort() kills the child — report timeout vs cancel.\n if (err?.name === 'AbortError' || ctl.signal.aborted) return finish(reasonFor(timedOut, timeoutMs, clean(out)));\n log.debug('shell spawn error', err);\n finish(`[exit 1] ${err?.message ?? err}${out ? '\\n' + clean(out) : ''}`);\n });\n proc.on('close', (code: number | null) => {\n flushEmit(ctx); // drain the coalesce buffer before settling (still pre-resolve, so ctx.emit is live)\n if (ctl.signal.aborted) return finish(reasonFor(timedOut, timeoutMs, clean(out)));\n const body = clean(out);\n if (code && code !== 0) return finish(`[exit ${code}]${body ? '\\n' + body : ''}`);\n finish(body || '(command succeeded, no output)');\n });\n });\n } finally {\n clearTimeout(timer);\n if (flushTimer) clearTimeout(flushTimer); // no emits after the call settles\n ctx.signal?.removeEventListener('abort', onAbort);\n }\n },\n };\n}\n\n/** Abort message: timeout vs external cancel, preserving any partial output. */\nfunction reasonFor(timedOut: boolean, timeoutMs: number, body: string): string {\n const head = timedOut ? `[exit 124] timed out after ${timeoutMs}ms (killed)` : '[exit 130] cancelled (killed)';\n return body ? `${head}\\n${body}` : head;\n}\n\nconst NO_JOB = (id: string) => `Error: no background job '${id}'. Use ShellStatus with no id to list jobs, or start one with Shell({background:true}).`;\n\n/** Build the background-job companion tools (ShellOutput / ShellStatus / ShellKill) over a registry. */\nexport function makeShellJobTools(registry: ShellJobRegistry): AgentTool[] {\n const idParam = { type: 'object', properties: { id: { type: 'string', description: 'the job id from Shell({background:true})' } } };\n return [\n {\n name: 'ShellOutput',\n description: 'Read the accumulated output (tail) of a background Shell job by id.',\n parameters: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } },\n async run({ id }) {\n const out = registry.output(String(id));\n if (out == null) return NO_JOB(String(id));\n const st = registry.status(String(id))!;\n return `[${st.status}${st.exitCode != null ? ` exit ${st.exitCode}` : ''}]\\n${clean(out) || '(no output yet)'}`;\n },\n },\n {\n name: 'ShellStatus',\n description: 'Status of a background Shell job (running/exited/killed + exit code). Omit `id` to list all jobs.',\n parameters: idParam,\n async run({ id }) {\n if (!id) {\n const jobs = registry.list();\n return jobs.length ? jobs.map((j) => `${j.id} ${j.status} ${j.command}`).join('\\n') : '(no background jobs)';\n }\n const st = registry.status(String(id));\n return st ? `${st.status}${st.exitCode != null ? ` (exit ${st.exitCode})` : ''} · ${st.bytes} byte(s) buffered` : NO_JOB(String(id));\n },\n },\n {\n name: 'ShellKill',\n description: 'Stop a running background Shell job by id (SIGTERM).',\n parameters: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } },\n async run({ id }) {\n return registry.kill(String(id)) ? `Killed job ${id}.` : NO_JOB(String(id));\n },\n },\n ];\n}\n","#!/usr/bin/env bun\n/**\n * agentx — a Claude-Code-style CLI for the agentx runtime.\n *\n * agentx # interactive REPL in the current dir\n * agentx \"fix the bug in src/x\" # headless: run once, print, exit\n * agentx -p \"…\" # explicit headless (pipeable: text→stdout, logs→stderr)\n * agentx -c \"keep going\" # continue the most recent session\n * agentx -r # resume — interactive session picker (or -r <id> for a specific one)\n * agentx -m openai/gpt-… -C ./pkg --plan \"refactor auth\"\n *\n * Flags: -m/--model, -C/--cwd, -p/--print, -c/--continue, --resume <id>, --no-stream,\n * --vfs/--sandbox, --shell, --plan, --ask, --yes, --subagents, --max-steps N, --max-tokens N, --timeout S, -h/--help.\n * Needs at least one provider key (ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_API_KEY /\n * GROQ_API_KEY; bun auto-loads .env).\n * Filesystem modes: real disk by default (jailed so secrets stay invisible); `--vfs` runs over an\n * in-memory copy (disk untouched); `--shell` adds a real /bin/sh. Mutations prompt for approval when\n * interactive, auto-approve (with a notice) when unattended — `--ask`/`--yes` force the choice.\n * Auto-loads ./.agent/{skills,commands,memory}, ./AGENTS.md|CLAUDE.md, and persists the\n * conversation to ./.agent/sessions/<id>.json so it can be resumed.\n */\nimport { createInterface } from 'node:readline/promises';\nimport { existsSync, readFileSync, appendFileSync, mkdirSync, writeFileSync, readdirSync, statSync, unlinkSync } from 'node:fs';\nimport { homedir, tmpdir } from 'node:os';\nimport { grabClipboardImage, copyTextToClipboard } from './clipboard';\nimport { join, resolve, basename, extname, dirname } from 'node:path';\nimport { AIClient, listModels, listProviders, getProviderFromModel, getModelInfo, resolveModel, isModelSupported, disposeCursorSessions } from 'ai.libx.js';\nimport {\n PermissionPolicy, loadCommands, expandCommand, expandEntry, loadSkills, scanCommands, scanSkills, forComponent, composeHooks, reflectOnRun,\n AgentOptions, exitSessionTool,\n CommandExecutor, registerHeadlessCommands, mkdirp, contentText, imagePart,\n type Agent, type ChatLike, type HostBridge, type Hooks, type IFilesystem, type CommandInfo, type SkillInfo, type RunResult, type AgentTool, type ToolUse, type Message, type ContentPart, type MessageContent, type ReasoningEffort,\n} from '../src/index';\nimport { Scheduler, makeScheduleTools } from '../src/scheduler';\nimport { loadAgents, type AgentDef } from '../src/agents';\nimport { mountMcpServer, mountMcpServers, type MountedMcp, type McpServerConfig } from '../src/mcp.client';\nimport { makeMcpToolSearchFromMounted } from '../src/mcp';\nimport { McpOAuth } from './mcpOAuth';\nimport { buildAgent, summarizeCall, cursorProviderOptions, type CliOptions } from './core';\nimport { DuplexAgent, type TaskRecord } from '../src/duplex';\nimport { detectedInputDevice, matchVoiceCommand, VoiceIO } from './voice';\nimport { forSpeech } from '../src/voice/engine';\nimport { loadConfig, type AgentConfig } from './config';\nimport { hooksFromConfig } from './hooks-config';\nimport { diffLines, statOf, formatDiff } from './diff';\nimport { SessionStore, titleOf, globalSessionLoad, globalSessionList, type SessionData, type TurnEvent } from './session';\nimport { CheckpointStack, type Checkpoints } from './checkpoints';\nimport { GitCheckpoints } from './gitCheckpoints';\nimport { parsePermRules, describeRule, loadPersistedRules, loadClaudeSettings, persistRule, mergePerms, isTrusted, trustDir } from './permissions';\nimport { completeLine, type DirLister } from './complete';\nimport { createLineEditor, selectMenu, REWIND, isPrintable, type SelectItem, type PasteClassifier, type LineEditor } from './lineEditor';\nimport { keyInput, releaseKeyInput } from './stdinSource';\nimport { EditorState, applyKey, isMenuActive } from './lineEditor';\nimport { MarkdownStream, plainLine, wrapAnsi } from './markdown';\nimport { dotDirs } from './util';\nimport { OsScheduler, routeTrigger, type OsJobSpec } from './osScheduler';\nimport { TriggerServer, makeRemoteTriggerTool } from './remoteTrigger';\nimport type { Trigger } from '../src/scheduler';\n\n// ---- tiny ANSI (auto-off when piped; honors NO_COLOR / FORCE_COLOR) ----\n// Precedence: explicit FORCE_COLOR wins (the CI case — force color through a pipe); else NO_COLOR forces\n// off (accessibility, https://no-color.org); else fall back to TTY detection.\nconst forceColor = process.env.FORCE_COLOR != null && process.env.FORCE_COLOR !== '' && process.env.FORCE_COLOR !== '0';\nconst useColor = forceColor || (!process.env.NO_COLOR && !!process.stdout.isTTY && !!process.stderr.isTTY);\nconst tty = process.stdout.isTTY && process.stderr.isTTY;\nconst C = (n: string) => (s: string) => (useColor ? `\\x1b[${n}m${s}\\x1b[0m` : String(s));\nconst dim = C('2'), cyan = C('36'), green = C('32'), red = C('31'), bold = C('1'), yellow = C('33');\nconst italic = C('3'), strike = C('9');\n// OSC 8 hyperlink: clickable styled text, ugly URL hidden (matches CC). Falls back to \"text (url)\" when piped.\nconst link = (text: string, url: string) => (useColor ? `\\x1b]8;;${url}\\x1b\\\\${cyan(text)}\\x1b]8;;\\x1b\\\\` : `${text} (${url})`);\nconst err = (s: string) => process.stderr.write(s);\nconst log = forComponent('cli');\n\n/** This CLI's version, read from package.json (so /version and the banner can't drift from the package). */\nconst VERSION: string = (() => {\n try { return JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version ?? '?'; }\n catch { return '?'; }\n})();\n\n// ---- thinking spinner (TTY only; cleared the instant real output arrives) ----\nconst spinner = (() => {\n const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n let timer: ReturnType<typeof setInterval> | undefined;\n let i = 0;\n let t0 = 0; // wall-clock start of the CURRENT spin run (elapsed survives stop/start within a turn via turnStart)\n return {\n /** Anchor for the elapsed counter; runTurn sets it once per turn so tool-call stop/start cycles don't reset it. */\n turnStart: 0,\n /** Mid-turn type-ahead, rendered as the frame's tail — the spinner repaints its row every 90ms,\n * so the typed text must live INSIDE the frame or it gets erased on the next tick. */\n tail: undefined as (() => string) | undefined,\n get active() { return !!timer; },\n start(label = 'thinking…') {\n if (!tty || timer) return; // no-op when piped or already spinning\n t0 = this.turnStart || Date.now();\n timer = setInterval(() => {\n const secs = Math.round((Date.now() - t0) / 1000);\n const tail = this.tail?.();\n err('\\r\\x1b[2K' + dim(` ${frames[i = (i + 1) % frames.length]} ${label} ${secs ? `${secs}s · ` : ''}esc to interrupt`) + (tail ? ' ' + tail : ''));\n }, 90);\n },\n stop() { if (timer) { clearInterval(timer); timer = undefined; err('\\r\\x1b[2K'); } },\n };\n})();\n\n/** Set the terminal tab/window title (OSC 0) — session topic, like CC. No-op when piped. */\nconst setTermTitle = (t: string) => { if (tty) err(`\\x1b]0;${t.replace(/[\\x00-\\x1f]/g, ' ').slice(0, 80)}\\x07`); };\n\n// The in-flight turn's aborter (Esc / Ctrl-C / SIGINT call .abort()); null when idle at the prompt.\nlet activeTurn: AbortController | null = null;\n/** Programmatic Esc — abort the in-flight turn (tests; the REPL keymap calls activeTurn directly). */\nexport const abortActiveTurn = (): void => activeTurn?.abort();\n// Set by the ExitSession tool when the model decides the user wants to quit (voice: \"ok bye\").\nlet exitRequested = false;\n\n// Input stash: type-ahead queue for input entered while a turn is running.\nconst inputStash: string[] = [];\n// Mid-turn type-ahead editor (a full EditorState: backspace/arrows/kill-keys/bracketed paste all\n// work while a turn streams). Built by the REPL (needs its paste classifiers); null when headless.\nlet stashEd: EditorState | null = null;\nconst stashText = (): string => stashEd?.buf ?? '';\n// True from the synchronous instant a line submits until its dispatch settles — keys buffered\n// behind the Enter in the same input burst land here (activeTurn is only set a few awaits later).\nlet dispatchPending = false;\n\n// Latest TodoWrite plan (captured off the tool call) — pinned compactly into the idle footer.\nlet latestTodos: { content: string; status: string }[] = [];\n\n// ---- arg parsing ----\ninterface Args {\n task?: string; model?: string; cwd?: string; stream: boolean; plan: boolean; ask: boolean; yes: boolean;\n vfs: boolean; shell: boolean | undefined; boddb?: string; seed: boolean;\n subagents: boolean; maxSteps?: number; maxTokens?: number; timeoutMs?: number; reasoning?: ReasoningEffort; help: boolean; version: boolean;\n duplex: boolean; voiceModel?: string; thinkModel?: string | false; voice: boolean;\n cont: boolean; resume?: string; sessionId?: string; fork?: boolean; outputFormat: 'text' | 'json' | 'stream-json';\n allowedTools?: string[]; disallowedTools?: string[]; appendSystemPrompt?: string; addDirs?: string[];\n print?: boolean; debug?: boolean; scratch?: boolean; harden?: boolean; hardenNet?: boolean;\n}\n/** Parse a numeric flag, failing fast on a missing/NaN/negative value so a typo can't silently disable a kill-switch. */\nfunction numFlag(raw: string | undefined, flag: string): number {\n const n = Number(raw);\n if (!Number.isFinite(n) || n < 0) throw new Error(`invalid ${flag}: ${raw ?? '(missing value)'}`);\n return n;\n}\n\n/** Parse `--reasoning` value: off|low|medium|high, or a raw token budget. */\nfunction parseReasoning(raw: string): ReasoningEffort {\n if (raw === 'off' || raw === 'low' || raw === 'medium' || raw === 'high') return raw;\n const n = Number(raw);\n if (Number.isFinite(n) && n > 0) return n;\n throw new Error(`invalid --reasoning: ${raw} (use off|low|medium|high or a token budget)`);\n}\n\nexport function parseArgs(argv: string[]): Args {\n const a: Args = { stream: true, plan: false, ask: false, yes: false, vfs: false, shell: undefined, seed: false, subagents: false, help: false, version: false, cont: false, outputFormat: 'text', duplex: false, voice: false, scratch: true };\n const rest: string[] = [];\n // read the value that follows a flag, failing loudly if it's missing (instead of a surprise default)\n const val = (i: number, flag: string): string => { const v = argv[i]; if (v === undefined) throw new Error(`${flag} requires a value`); return v; };\n for (let i = 0; i < argv.length; i++) {\n const x = argv[i];\n if (x === '-h' || x === '--help') a.help = true;\n else if (x === '-v' || x === '--version') a.version = true;\n else if (x === '-m' || x === '--model') a.model = val(++i, x);\n else if (x === '-C' || x === '--cwd') a.cwd = val(++i, x);\n else if (x === '-p' || x === '--print') {\n // CC-style: `-p \"task\"` uses the inline value; bare `-p` (piped) reads the prompt from stdin.\n const nxt = argv[i + 1];\n if (nxt !== undefined && !nxt.startsWith('-')) a.task = argv[++i];\n a.print = true;\n }\n else if (x === '--debug' || x === '--verbose') a.debug = true;\n else if (x === '-c' || x === '--continue') a.cont = true;\n else if (x === '--resume' || x === '-r') {\n // CC-style: `-r <id>` resumes that session; bare `-r` (no id / next is a flag) opens the picker.\n const nxt = argv[i + 1];\n a.resume = nxt !== undefined && !nxt.startsWith('-') ? argv[++i] : ''; // '' = sentinel → interactive pick\n }\n else if (x === '--no-stream') a.stream = false;\n else if (x === '--plan') a.plan = true;\n else if (x === '--ask') a.ask = true;\n else if (x === '--yes' || x === '-y') a.yes = true;\n else if (x === '--vfs' || x === '--sandbox') a.vfs = true;\n else if (x === '--scratch') a.scratch = true;\n else if (x === '--no-scratch') a.scratch = false;\n else if (x === '--boddb') a.boddb = val(++i, x);\n else if (x === '--seed') a.seed = true;\n else if (x === '--shell') a.shell = true;\n else if (x === '--no-shell') a.shell = false;\n else if (x === '--harden') a.harden = true;\n else if (x === '--harden-net') { a.harden = true; a.hardenNet = true; } // hardened, but outbound network stays allowed\n else if (x === '--subagents') a.subagents = true;\n else if (x === '--duplex') a.duplex = true;\n else if (x === '--conversational' || x === '--convo' || x === '--voice') { a.voice = true; a.duplex = true; } // duplex + human conversational register (--convo/--voice = aliases)\n else if (x === '--voice-model') a.voiceModel = val(++i, x);\n else if (x === '--think-model') a.thinkModel = val(++i, x);\n else if (x === '--no-think') a.thinkModel = false;\n else if (x === '--allowedTools' || x === '--allowed-tools') a.allowedTools = val(++i, x).split(',').map((s) => s.trim()).filter(Boolean);\n else if (x === '--disallowedTools' || x === '--disallowed-tools') a.disallowedTools = val(++i, x).split(',').map((s) => s.trim()).filter(Boolean);\n else if (x === '--append-system-prompt') a.appendSystemPrompt = val(++i, x);\n else if (x === '--add-dir') (a.addDirs ??= []).push(val(++i, x));\n else if (x === '--reasoning') a.reasoning = parseReasoning(val(++i, x));\n else if (x === '--session-id') a.sessionId = val(++i, x);\n else if (x === '--fork-session') a.fork = true;\n else if (x === '--max-steps') a.maxSteps = numFlag(argv[++i], '--max-steps');\n else if (x === '--max-tokens') a.maxTokens = numFlag(argv[++i], '--max-tokens');\n else if (x === '--timeout') a.timeoutMs = numFlag(argv[++i], '--timeout') * 1000; // seconds → ms\n else if (x === '--output-format') {\n const f = argv[++i];\n if (f !== 'text' && f !== 'json' && f !== 'stream-json') throw new Error(`invalid --output-format: ${f ?? '(missing)'} (use text|json|stream-json)`);\n a.outputFormat = f;\n }\n else rest.push(x);\n }\n if (!a.task && rest.length) a.task = rest.join(' ');\n if (a.boddb && a.vfs) throw new Error('--boddb and --sandbox are mutually exclusive (both are non-disk filesystems; pick one)');\n if (a.seed && !a.boddb) throw new Error('--seed only applies with --boddb (it seeds the database from cwd on first run)');\n if (a.duplex && (a.task || a.print)) throw new Error('--duplex is interactive-only (a conversational mode) — drop the task/-p');\n if (a.duplex && a.plan) throw new Error('--plan is not supported in --duplex (workers are non-interactive; a plan could never be approved)');\n if (a.voiceModel && !a.duplex) throw new Error('--voice-model only applies with --duplex');\n if (a.thinkModel !== undefined && !a.duplex) throw new Error('--think-model/--no-think only apply with --duplex');\n return a;\n}\n\nconst HELP = `agentx — agent runtime CLI\n\n agentx interactive REPL (current dir)\n agentx \"<task>\" run once and exit\n agentx -p \"<task>\" headless (stdout=answer, stderr=activity)\n echo \"<task>\" | agentx -p headless, prompt read from stdin\n agentx -c \"<task>\" continue the most recent session\n\nFlags:\n -m, --model <id> model (default anthropic/claude-sonnet-4-6)\n -C, --cwd <dir> working dir / project root (default .)\n -c, --continue resume the most recent session in this dir\n -r, --resume [id] resume a session — with an id, or bare for an interactive picker\n --no-stream disable token streaming\n (default: disk mode — full real filesystem access, like Claude Code)\n --vfs, --sandbox sandbox mode: work over an in-memory copy of cwd — real disk is NEVER modified\n --no-scratch disable scratch (on by default): paginate oversized tool output → recoverable\n scratch files (peek via Grep/Read/Ask) instead of a lossy crop\n --boddb <dir> database-backed workspace: files live in a persistent bod-db store at <dir>,\n surviving across runs — real disk is NEVER modified (DB-native; add --seed below)\n --seed with --boddb: hydrate the store from cwd on the first run (empty DB) only\n --shell force real /bin/sh on (default in disk mode); --no-shell to use VFS bash only\n --harden OS-sandbox the real shell (sandbox-exec/bwrap): writes confined to cwd+tmp,\n outbound network blocked; --harden-net keeps network allowed\n --plan plan mode: edits blocked until you approve a plan\n --ask confirm each mutating tool (bash/Shell/Write/Edit/…)\n --yes, -y auto-approve mutating tools (no prompts) — for trusted/unattended runs\n --verbose, --debug verbose logs (sets DEBUG=* — tool args, hook decisions, retries)\n --allowedTools <l> comma-list of tools to allow w/o asking, e.g. \"Edit,Shell(git *)\"\n --disallowedTools <l> comma-list of tools to deny outright (wins over allow), e.g. \"Shell(rm *)\"\n --append-system-prompt <t> extra instructions appended to the system prompt for this run\n --duplex duplex mode: a fast voice model replies instantly and delegates real work\n to a background worker agent (-m model); results are re-voiced when ready\n --conversational duplex with a conversation-native register — short fast turns, fillers,\n impulsive reactions, human pacing (implies --duplex; aliases: --convo, --voice)\n with SONIOX_API_KEY + CARTESIA_API_KEY(+VOICE_ID) set: real voice I/O — mic in,\n spoken replies out (echo-cancelled; speak over it to interrupt)\n --voice-model <id> with --duplex: the fast voice model (default groq/openai/gpt-oss-120b)\n --think-model <id> with --duplex: the premium deep-reasoning model (default anthropic/claude-opus-4-6)\n --no-think with --duplex: disable the Think tier (Act handles everything)\n --add-dir <path> mount another directory into the workspace (repeatable; disk mode only)\n --subagents allow the Task tool (spawn child agents)\n --reasoning <e> extended thinking: off|low|medium|high or a token budget (anthropic/openai)\n --session-id <id> use this id for the session (instead of an auto-generated one)\n --fork-session with -r/-c: branch the resumed session into a new id (source left untouched)\n --max-steps <n> step budget (default 30)\n --max-tokens <n> token budget kill-switch (default 200000)\n --timeout <sec> wall-clock kill-switch (default 120)\n --output-format <f> headless output: text (default) | json (one result object) | stream-json (NDJSON events: {type:text|thinking}… then {type:result})\n -v, --version print version and exit\n -h, --help\n\nPrompts may reference files with @path (e.g. \"explain @src/Agent.ts\") — they're inlined.\n\nProviders: set any of ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_API_KEY / GROQ_API_KEY.\nConfig: ./.agent/config.{ts,js,json} (project) or ~/.agent/config.* (user).\n export default { model, maxSteps, reasoning, permissionMode, editorMode, tools, apiKeys, baseUrls, hooks, permissions, mcpServers, maxTokens,\n timeoutMs, maxRepeats, maxToolCalls, keepToolOutputs, maxContextTokens,\n learnFromMistakes, reflectOnFailure, budget: {…} }\n hooks: { preToolUse|postToolUse|onStop: [{ tool?, command, block? }] } — shell hooks\n permissions: { allow|ask|deny: [\"Tool(glob)\", …] } — persisted rules (deny>allow>ask; deny applies even with --yes)\n mcpServers: { name: { command, args, env } | { url, headers } } — auto-mounted MCP servers\n learnFromMistakes: capture recurring tool failures as memory lessons (needs .agent/memory)\n reflectOnFailure: on a bad headless run, reflect once via the model + persist a novel lesson\n Precedence: CLI flags > project config > user config > defaults.\nProject instructions: ./AGENTS.md or ./CLAUDE.md are auto-loaded (scaffold with /init).\nAuto-loaded from ./.agent/: commands/, skills/, memory/, agents/.\n\nREPL shortcuts: !<cmd> runs a shell command inline · #<note> saves a memory · @path inlines a file\nREPL slash commands: /help /version /tools /permissions /status /cost /context /transcript /doctor /cwd /model /reasoning /config /rename /compact /memory /rewind /undo /clear /sessions /resume /commands /skills /reload /mcp /init /export /paste /goal /exit (duplex: /act /think /tasks /voice /voice-model /think-model)\nREPL completion: type / (commands+skills) or @ (files) for a LIVE menu — ↑/↓ select, ⏎/Tab accept, Esc dismiss.\nREPL multi-line: Option/Alt+Enter inserts a newline, or end a line with \\\\ to continue. Esc cancels a running turn / clears the input line; double-Esc jumps back to edit a previous message.\nREPL shortcuts: Shift+Tab cycles permission posture (ask → accept-edits → plan) · Alt+T toggles reasoning · Alt+P switches model · Ctrl+O toggles verbose tool output · Ctrl+X Ctrl+E edits the buffer in $EDITOR · → or Tab accepts the dim history ghost-suggestion · Alt+S/Ctrl+S stash/unstash.\nREPL stash: type while a turn is running → Enter queues it (auto-submits when the turn finishes). Alt+S (or Ctrl+S) with text stashes it; on an empty prompt pops the next entry for editing.\nREPL editing (emacs/readline): Ctrl-A/E line start/end · Ctrl-B/F char · Alt-B/F or Alt/Ctrl-←/→ word · Ctrl-W kill word · Ctrl-U/K kill to start/end · Ctrl-Y yank · Ctrl-_ undo · Alt-D kill word fwd · Ctrl-L clear screen. Set editorMode:'vim' (or /config) for modal vim editing.\nREPL paste: large/multi-line pastes collapse to a [Pasted text +N lines] preview (expands on send); a pasted image/file path attaches as [Image]/[File]; Ctrl-V or /paste grabs a clipboard image (macOS).`;\n\n// ---- provider keys (env + config; env wins) ----\n/** Newest supported model by releaseDate — the fallback when a requested model is unknown/dropped. */\nfunction newestModel(): string {\n return listModels().slice().sort((a, b) => (getModelInfo(b)?.releaseDate ?? '').localeCompare(getModelInfo(a)?.releaseDate ?? ''))[0] ?? '';\n}\n\n/** Resolve a requested model to a supported id; if it's gone from ai.libx.js (stale flag/config OR an\n * outdated built-in default), warn + fall back to the newest available so the first call never hard-errors. */\nfunction resolveModelOrNewest(model: string | undefined): string {\n const want = model ?? new AgentOptions().model; // single source of truth for the default\n const resolved = resolveModel(want);\n if (isModelSupported(resolved)) return resolved;\n const fallback = newestModel();\n if (!fallback) return want; // no catalog at all → pass through, let the API surface it\n err(yellow(` ⚠ model \"${want}\" not available — using ${fallback}\\n`));\n return fallback;\n}\n\n/** Extra env-var names accepted per provider beyond the `${PROVIDER}_API_KEY` convention. */\nconst ENV_KEY_ALIASES: Record<string, string[]> = { google: ['GEMINI_API_KEY'] };\n\n/** Fallback .env loader: Bun auto-loads .env from the CWD, but when agentx is launched from an unrelated\n * directory those keys are missing. So also read .env / .env.local from the agentx install/source repo\n * (the dir holding this file's package.json). Never overrides an existing var — CWD + shell still win. */\nfunction loadInstallEnv(): void {\n let dir = dirname(import.meta.path); // .../<pkg>/cli → walk up to the package root\n for (let i = 0; i < 5 && !existsSync(join(dir, 'package.json')); i++) dir = dirname(dir);\n for (const name of ['.env', '.env.local']) {\n const file = join(dir, name);\n if (!existsSync(file)) continue;\n for (const line of readFileSync(file, 'utf8').split('\\n')) {\n const m = line.match(/^\\s*(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.*)$/);\n if (!m || m[1] in process.env) continue;\n let val = m[2].trim();\n if ((val.startsWith('\"') && val.endsWith('\"')) || (val.startsWith(\"'\") && val.endsWith(\"'\"))) val = val.slice(1, -1);\n else val = val.replace(/\\s+#.*$/, '').trim(); // strip inline comment only on unquoted values\n process.env[m[1]] = val;\n }\n }\n}\n\n/** Map env vars → provider api keys. DYNAMIC over `listProviders()` (convention `${PROVIDER}_API_KEY` +\n * aliases), so a provider newly added to ai.libx.js is picked up automatically — no edit needed here. */\nfunction apiKeysFromEnv(): Record<string, string> {\n const e = process.env, keys: Record<string, string> = {};\n for (const provider of listProviders()) {\n const names = [`${provider.toUpperCase()}_API_KEY`, ...(ENV_KEY_ALIASES[provider] ?? [])];\n const val = names.map((n) => e[n]).find(Boolean);\n if (val) keys[provider] = val;\n }\n return keys;\n}\n\n// ---- terminal host (human-in-the-loop prompts) ----\nfunction makeHost(format: 'text' | 'json' | 'stream-json' = 'text', opts?: { stream?: boolean }): HostBridge & { flushText: () => void } {\n const streamJson = format === 'stream-json'; // emit NDJSON events on stdout as they arrive\n const cleanStdout = format === 'json'; // keep stdout for the single final result object\n // Render markdown only for the STREAMING host on a color-capable TTY; piped / NO_COLOR / json stay raw.\n // Gated on `opts.stream` so the throwaway confirm/permission hosts don't allocate a dead MarkdownStream\n // (and, below, don't each leak a process-lifetime SIGWINCH listener).\n const md = format === 'text' && useColor && opts?.stream ? new MarkdownStream({ bold, dim, cyan, italic, strike, green, link }, process.stdout.columns ?? 80) : null;\n if (md) process.on('SIGWINCH', () => md.resize(process.stdout.columns ?? 80)); // reflow streamed markdown on resize\n // Commit any pending streamed-markdown tail (terminating its line) — MUST run before any chrome prints\n // below the stream (tool headers, step notices, the done line), or the renderer's clear-math goes stale\n // and the next delta re-draws the old tail glued onto the new text.\n const flushText = () => { if (md && md.pending()) process.stdout.write(md.commit()); };\n // `thinking_delta` streams to stderr WITHOUT a trailing newline (a continuous dimmed reasoning flow).\n // Any other output that follows (the answer on stdout, a `· notice`, a ⚙ tool header) must first\n // close that open line — else it collides mid-word into the reasoning tail.\n let openReasonLine = false;\n const closeReasonLine = () => { if (openReasonLine) { process.stderr.write('\\n'); openReasonLine = false; } };\n return {\n flushText,\n notify(e) {\n // Step boundaries draw NO chrome (CC parity — `· step N` between tools read as debug noise):\n // the spinner keeps ticking, and consecutive read-only lookups group straight across steps.\n if (e.kind === 'turn_start') return;\n spinner.stop(); // real output arriving → clear the spinner first\n // NB: flushLookupGroup() runs only on paths that PRINT — structural tool events flow through\n // here too, and flushing on those would break lookups apart instead of grouping them.\n if (e.kind === 'text_delta') {\n flushLookupGroup(); // a pending `read N files` summary lands before the text it precedes\n if (streamJson) process.stdout.write(JSON.stringify({ type: 'text', text: e.message }) + '\\n');\n else if (md) { closeReasonLine(); process.stdout.write(md.feed(e.message)); } // line-buffered markdown render\n else { if (!cleanStdout) closeReasonLine(); (cleanStdout ? process.stderr : process.stdout).write(e.message); } // json keeps stdout clean → stderr\n return;\n }\n // extended-thinking (reasoning-native models): a dimmed stderr flow in text mode; a typed event in\n // stream-json; never on stdout in plain json (can't pollute the single result object).\n if (e.kind === 'thinking_delta') {\n if (streamJson) process.stdout.write(JSON.stringify({ type: 'thinking', text: e.message }) + '\\n');\n else if (!cleanStdout) {\n // flush any buffered answer (stdout) before the dimmed thinking (stderr) so the two streams\n // stay in order — otherwise late-flushed markdown lands after the thinking it preceded.\n flushLookupGroup();\n flushText();\n process.stderr.write(dim(e.message));\n openReasonLine = true; // unterminated reasoning line — next output must close it\n }\n return;\n }\n // Structural events (tool_use/tool_result/tool_result_image/turn_start) have dedicated renderers\n // (displayHooks ⚙ chrome) — never dump their raw `kind` as a `· notice`, or the\n // result preview gets sandwiched between junk `· tool_use`/`· tool_result` labels.\n if (!('message' in e)) return;\n flushLookupGroup();\n closeReasonLine(); // close an open reasoning line so the notice starts fresh (not glued mid-word)\n flushText(); // finish the in-progress line before a notice\n err(dim(` · ${e.message}\\n`)); // tool-activity notices stay on stderr (human chrome) for every format\n },\n async confirm(prompt) {\n // arrow-select on a TTY; fall back to a typed y/N when piped (selectMenu → null)\n const v = await selectMenu(process.stderr, { title: `? ${prompt}`, items: [{ label: 'Yes', value: 'y' }, { label: 'No', value: 'n' }], current: 'n' });\n if (v !== null) return v === 'y';\n const io = createInterface({ input: keyInput, output: process.stderr });\n try { return /^y(es)?$/i.test((await io.question(yellow(` ? ${prompt} [y/N] `))).trim()); } finally { io.close(); }\n },\n async ask(q) {\n const title = `? ${q.header ? '[' + q.header + '] ' : ''}${q.question}`;\n const v = await selectMenu(process.stderr, { title, items: q.options.map((o) => ({ label: o.label, value: o.label, desc: o.description })) });\n if (v !== null) return v;\n const io = createInterface({ input: keyInput, output: process.stderr });\n try {\n const lines = [yellow(' ' + title)];\n q.options.forEach((o, i) => lines.push(` ${i + 1}) ${o.label}${o.description ? dim(' — ' + o.description) : ''}`));\n const ans = (await io.question(lines.join('\\n') + '\\n > ')).trim();\n const n = Number(ans);\n return Number.isInteger(n) && q.options[n - 1] ? q.options[n - 1].label : ans;\n } finally { io.close(); }\n },\n };\n}\n\n/** Hooks that render tool activity to stderr: a preToolUse header, and for edits a colorized diff.\n * `opts.background` marks the agent as a BACKGROUND one (duplex workers): its chrome lands async on\n * top of a live prompt, so it must never drive the foreground spinner (the 'agentx › '/'⠹ thinking…'\n * flicker), clears the prompt line before printing, and repaints via the callback after. `opts.gate`\n * is evaluated per call — false renders nothing (minimal mode: task events only). */\n/** One-line collapsed summary for read-only lookup results (CC parity — `⎿ read 42 lines` instead of the\n * full body flooding the scrollback); null → tool keeps the N-line preview (shell output stays useful). */\nexport function summarizeResult(name: string, text: string): string | null {\n if (name !== 'Read' && name !== 'Glob' && name !== 'Grep') return null;\n if (text === '(no matches)' || text === '(empty file)') return text.slice(1, -1);\n // Read counts ALL lines (blank lines are content); Glob/Grep count nonempty (one path/hit per line)\n const n = name === 'Read' ? text.split('\\n').length : text.split('\\n').filter((l) => l.trim()).length;\n if (name === 'Read') return `read ${n} line${n === 1 ? '' : 's'}`;\n if (name === 'Glob') return `${n} file${n === 1 ? '' : 's'}`;\n return `${n} match${n === 1 ? '' : 'es'}`;\n}\n\n/** Foreground grouped-lookup flush seam — set by the active foreground displayHooks instance; the\n * host's notify() and the turn-done line call it so a pending `read N files` summary prints before\n * the text/done chrome it precedes. No-op until a foreground instance registers. */\nlet flushLookupGroup: () => void = () => {};\n\nfunction displayHooks(fs?: IFilesystem, opts?: { gate?: () => boolean; background?: () => void; flush?: () => void }): Hooks {\n const EDIT = new Set(['Edit', 'MultiEdit', 'Write']);\n const LOOKUP = new Set(['Read', 'Glob', 'Grep']);\n const before = new Map<string, string>();\n const MAX = 64 * 1024; // skip diffing very large files\n const bg = opts?.background;\n const on = () => !opts?.gate || opts.gate();\n const flush = () => opts?.flush?.(); // commit a pending streamed-markdown tail before printing chrome\n const read = async (p: unknown): Promise<string> => {\n if (!fs || typeof p !== 'string') return '';\n try { return await fs.readFile(p); } catch { return ''; }\n };\n // ⚙ header, word-wrapped at the terminal edge with a hanging indent (long Shell commands used to\n // hard-break mid-word). Leading \\n doubles as the closer for any open dimmed-reasoning line.\n const header = (call: ToolUse) => {\n const line = cyan(` ⚙ ${call.name}`) + dim(' ' + summarizeCall(call.name, call.args));\n return '\\n' + (process.stderr.isTTY ? wrapAnsi(line, process.stderr.columns ?? 80, ' ') : line) + '\\n';\n };\n // CC-style grouping: CONSECUTIVE read-only lookups (Read/Glob/Grep) print nothing while running;\n // the run flushes as one dim line (\"read 2 files · 1 glob\") when anything else needs the terminal.\n // A single grouped call keeps the detailed two-line form (header + ⎿ summary) — names beat counts.\n let group: { name: string; header: string; summary: string }[] = [];\n let pendingHeader: string | null = null; // deferred ⚙ header for the in-flight lookup call\n const flushGroup = () => {\n if (!group.length) return;\n flush(); // commit a pending streamed-markdown tail BEFORE chrome (the glued-tail bug class)\n if (group.length === 1) {\n err(group[0].header + dim(` ⎿ ${group[0].summary} (ctrl+o expands)\\n`));\n } else {\n const counts = new Map<string, number>();\n for (const g of group) counts.set(g.name, (counts.get(g.name) ?? 0) + 1);\n const parts = [...counts].map(([name, c]) =>\n name === 'Read' ? `read ${c} file${c > 1 ? 's' : ''}` : `${c} ${name.toLowerCase()}${c > 1 ? 's' : ''}`);\n err('\\n' + dim(` ${parts.join(' · ')} (ctrl+o expands)\\n`));\n }\n group = [];\n };\n if (!bg) flushLookupGroup = flushGroup; // foreground instance owns the module-level seam\n return {\n async preToolUse(call) {\n if (call.name === 'TodoWrite' && Array.isArray(call.args?.todos)) latestTodos = call.args.todos; // footer todo panel\n if (!on()) return;\n if (bg) err('\\r\\x1b[0J'); else spinner.stop(); // foreground: a tool is about to run → stop \"thinking…\"\n flush();\n if (!bg && !verboseOutput && LOOKUP.has(call.name)) { pendingHeader = header(call); return; } // defer — prints only if the result can't collapse\n flushGroup(); // anything non-collapsible ends the lookup run\n err(header(call));\n if (EDIT.has(call.name)) before.set(String(call.args?.path), await read(call.args?.path));\n bg?.();\n },\n onToolOutput(_call, chunk) {\n if (!verboseOutput || !on()) return; // Ctrl+O verbose: live-tail streaming tool output (default chrome stays calm)\n if (bg) err('\\r\\x1b[0J');\n for (const ln of String(chunk).split('\\n')) if (ln.trim()) err(dim(` ⋮ ${ln.length > 200 ? ln.slice(0, 200) + '…' : ln}\\n`));\n bg?.();\n },\n async postToolUse(call, result) {\n if (!on()) return;\n if (bg) err('\\r\\x1b[0J'); else spinner.stop();\n try {\n if (pendingHeader) {\n const t = String(result).replace(/\\s+$/, '');\n // Errors AND permission blocks (\"Blocked by hook: …\") must never collapse into a\n // \"read N lines\" count — that would render a denial as a successful lookup.\n const summary = /^(Error|Blocked)/i.test(t) ? null : summarizeResult(call.name, t);\n if (summary) { group.push({ name: call.name, header: pendingHeader, summary }); pendingHeader = null; return; }\n err(pendingHeader); pendingHeader = null; // error/blocked body → surface it via the normal path below\n }\n if (EDIT.has(call.name)) {\n const path = String(call.args?.path);\n const b = before.get(path) ?? '';\n const a = await read(path);\n before.delete(path);\n if (a !== b && b.length < MAX && a.length < MAX) {\n const ops = diffLines(b, a); // diff once → reuse for both the header stat and the body\n const { added, removed } = statOf(ops);\n err(dim(` ⎿ ${path} `) + green(`+${added}`) + ' ' + red(`-${removed}`) + '\\n');\n const body = formatDiff(ops, { add: green, del: red, dim, context: 2, maxLines: 80 });\n if (body) err(body + '\\n');\n return;\n }\n }\n const text = String(result).replace(/\\s+$/, '');\n if (text && !/^Edited|^Wrote|^Applied/.test(text)) {\n // CC-style collapse: read-only lookups summarize to one ⎿ line (full body via ctrl+o / /transcript)\n const summary = verboseOutput ? null : summarizeResult(call.name, text);\n if (summary) { err(dim(` ⎿ ${summary} (ctrl+o expands)\\n`)); return; }\n const lines = text.split('\\n');\n const shown = lines.slice(0, previewLines());\n for (const ln of shown) err(dim(` ${ln.length > 200 ? ln.slice(0, 200) + '…' : ln}\\n`));\n const more = lines.length - shown.length;\n if (more > 0) err(dim(` … (+${more} more line${more > 1 ? 's' : ''} · ctrl+o expands)\\n`));\n } else if (!text) {\n err(dim(' ⎿ (no output)\\n')); // empty result → confirm completion so it doesn't look hung\n }\n } finally {\n if (bg) bg(); // background: repaint the live prompt below the chrome — NEVER the spinner\n else spinner.start(); // foreground: tool done → the model is thinking about the next step\n }\n },\n };\n}\n\n/** Synthetic task-event user messages (\"[task t2 completed] <multi-KB worker dump>\") aren't real user\n * utterances — replaying the raw payload newline-collapsed + hard-cut at N chars garbles it (slices URLs\n * mid-token). Condense to a one-line marker. Non-task text is returned unchanged. */\nexport function condenseReplay(t: string): string {\n // The synthetic greeting instruction (\"[session started] First call QuickLook…\") is an internal prompt,\n // not a user utterance — hide it on replay/export so resume shows the agent's greeting, not its script (CC parity).\n if (/^\\[session (started|resumed)\\]/.test(t)) return '';\n const m = t.match(/^\\[task (t\\d+) (completed|failed|progress|asks)\\]\\s*([\\s\\S]*)$/);\n if (!m) return t;\n const [, id, kind, rest] = m;\n const gist = rest.replace(/https?:\\/\\/\\S+/g, '').replace(/[#>*`|_\\[\\]()]/g, ' ').replace(/\\s+/g, ' ').trim().slice(0, 80);\n return `⦿ task ${id} ${kind}${gist ? ' — ' + gist + '…' : ''}`;\n}\n\n/** Truncate on a whitespace boundary so we never slice a URL or word mid-token (the ' …' marks the cut). */\nconst clipReplay = (t: string, n: number): string => (t.length > n ? t.slice(0, n).replace(/\\S*$/, '').trimEnd() : t);\n\n/** Render a resumed conversation (like CC) so the user sees the context they're continuing: user\n * prompts, assistant narration, and a condensed line per tool action. Tool *results* are omitted\n * (verbose) and inlined @-mention blocks are stripped from prompts. Pure → unit-testable. */\nexport function formatHistory(messages: Message[]): string {\n const shown = messages.filter((m) => m.role !== 'system');\n if (!shown.length) return '';\n const out: string[] = [dim('\\n ── prior conversation ──────────────────────\\n')];\n for (const m of shown) {\n if (m.role === 'user') {\n const raw = contentText(m.content).split('\\n\\n--- @')[0].replace(/\\n+/g, ' ').trim(); // drop inlined @file blocks\n const t = condenseReplay(raw);\n if (t) out.push('\\n' + bold(cyan(' › ')) + (t.length > 1500 ? clipReplay(t, 1500) + dim(' …') : t) + '\\n');\n } else if (m.role === 'assistant') {\n const at = contentText(m.content);\n if (at.trim()) out.push(dim(' ') + at.trim() + '\\n');\n for (const tc of m.tool_calls ?? []) {\n let args: any = {};\n try { args = JSON.parse(tc.function.arguments || '{}'); } catch { /* unparsed args */ }\n out.push(cyan(' ⚙ ') + tc.function.name + dim(' ' + summarizeCall(tc.function.name, args)) + '\\n');\n }\n }\n }\n out.push(dim(' ────────────────────────────────────────────\\n'));\n return out.join('');\n}\n\n/** Render the FULL transcript — user prompts, assistant text, every tool call AND its complete\n * result body — for `/transcript` (the past-turn equivalent of Ctrl-O live verbose; CC's\n * transcript-viewer parity). `lastTurns` bounds output to the most recent N user turns.\n * Each tool result is capped at `resultLines` lines with an elision marker. Pure → unit-testable. */\nexport function formatTranscriptFull(messages: Message[], opts?: { lastTurns?: number; resultLines?: number }): string {\n const cap = opts?.resultLines ?? 200;\n let shown = messages.filter((m) => m.role !== 'system');\n if (opts?.lastTurns) {\n const userIdxs = shown.map((m, i) => (m.role === 'user' ? i : -1)).filter((i) => i >= 0);\n if (userIdxs.length > opts.lastTurns) shown = shown.slice(userIdxs[userIdxs.length - opts.lastTurns]);\n }\n if (!shown.length) return dim(' (empty transcript)\\n');\n // index tool results by call id so each renders under its own ⚙ header\n const results = new Map<string, Message>();\n for (const m of shown) if (m.role === 'tool' && m.tool_call_id) results.set(m.tool_call_id, m);\n const clip = (s: string) => {\n const lines = s.split('\\n');\n return lines.length > cap ? lines.slice(0, cap).join('\\n') + `\\n… (+${lines.length - cap} more lines)` : s;\n };\n const out: string[] = [dim('\\n ── transcript ──────────────────────────────\\n')];\n for (const m of shown) {\n if (m.role === 'user') {\n const t = contentText(m.content).trim();\n if (t) out.push('\\n' + bold(cyan(' › ')) + t.replace(/\\n/g, '\\n ') + '\\n');\n } else if (m.role === 'assistant') {\n const at = contentText(m.content).trim();\n if (at) out.push(' ' + at.replace(/\\n/g, '\\n ') + '\\n');\n for (const tc of m.tool_calls ?? []) {\n let args: any = {};\n try { args = JSON.parse(tc.function.arguments || '{}'); } catch { /* unparsed args */ }\n out.push(cyan(' ⚙ ') + tc.function.name + dim(' ' + summarizeCall(tc.function.name, args)) + '\\n');\n const r = results.get(tc.id);\n if (r) out.push(dim(' ' + clip(contentText(r.content).trimEnd()).replace(/\\n/g, '\\n ')) + '\\n');\n }\n }\n }\n out.push(dim(' ────────────────────────────────────────────\\n'));\n return out.join('');\n}\n\n/** Render a transcript to portable Markdown (no ANSI) for `/export`. Same shape as formatHistory —\n * user prompts + assistant narration + one quoted line per tool action; tool results omitted. Pure → unit-testable. */\nexport function exportMarkdown(\n meta: { id: string; title?: string; model?: string; turns?: number; created?: number; tokens?: number; costUsd?: number; costEstimated?: boolean },\n messages: Message[],\n): string {\n const shown = messages.filter((m) => m.role !== 'system');\n const stamp = meta.created ? new Date(meta.created).toISOString() : '';\n const cost = meta.costUsd ? ` · ${meta.costEstimated ? '~' : ''}${fmtUsd(meta.costUsd)}` : '';\n const head = [\n `# ${meta.title || 'Conversation'}`,\n '',\n `- **Session:** \\`${meta.id}\\``,\n ...(meta.model ? [`- **Model:** ${meta.model}`] : []),\n ...(stamp ? [`- **Date:** ${stamp}`] : []),\n ...(meta.turns != null ? [`- **Turns:** ${meta.turns}`] : []),\n ...(meta.tokens ? [`- **Usage:** ${(meta.tokens / 1000).toFixed(1)}k tok${cost}`] : []),\n '', '---', '',\n ];\n const body: string[] = [];\n for (const m of shown) {\n if (m.role === 'user') {\n const t = condenseReplay(contentText(m.content).split('\\n\\n--- @')[0].trim()); // drop inlined @file blocks\n if (t) body.push('## 👤 User', '', t, '');\n } else if (m.role === 'assistant') {\n const parts: string[] = [];\n const at = contentText(m.content).trim();\n if (at) parts.push(at);\n for (const tc of m.tool_calls ?? []) {\n let args: any = {};\n try { args = JSON.parse(tc.function.arguments || '{}'); } catch { /* unparsed args */ }\n parts.push(`> 🔧 \\`${tc.function.name}\\` — ${summarizeCall(tc.function.name, args)}`.trimEnd());\n }\n if (parts.length) body.push('## 🤖 Assistant', '', parts.join('\\n\\n'), '');\n }\n }\n return head.concat(body).join('\\n').replace(/\\n{3,}/g, '\\n\\n').trimEnd() + '\\n';\n}\n\n/** Replay a resumed conversation to stderr. */\nfunction printHistory(messages: Message[]): void {\n const s = formatHistory(messages);\n if (s) err(s);\n}\n\n/** Cache-read/write price multipliers over the input rate, by provider (derived from the model\n * prefix). Anthropic: write 1.25x / read 0.1x. OpenAI & Gemini auto-cache (no write surcharge),\n * reads 0.5x / 0.25x. DeepSeek read 0.1x. Unknown → no discount (1x/1x, safe over-estimate). */\nexport function cacheMultipliers(model?: string): { read: number; write: number } {\n const p = (model ?? '').split('/')[0];\n switch (p) {\n case 'anthropic': return { read: 0.1, write: 1.25 };\n case 'openai': return { read: 0.5, write: 1 };\n case 'google': return { read: 0.25, write: 1 };\n case 'deepseek': return { read: 0.1, write: 1 };\n default: return { read: 1, write: 1 };\n }\n}\n\n/** USD cost from a model's per-1K pricing (ai.libx.js ModelPricing) + token usage. 0 if unpriced.\n * Cache-aware: promptTokens includes cache reads/writes — priced at the provider's real multipliers\n * (via `model`) so cached runs aren't overstated. Omitting `model` falls back to Anthropic's rates. */\nexport function costOf(\n pricing: { inputCostPer1K: number; outputCostPer1K: number } | undefined,\n promptTokens = 0, completionTokens = 0, cacheCreationTokens = 0, cacheReadTokens = 0, model?: string,\n): number {\n if (!pricing) return 0;\n const mult = model ? cacheMultipliers(model) : { read: 0.1, write: 1.25 };\n const fresh = Math.max(0, promptTokens - cacheCreationTokens - cacheReadTokens);\n return (fresh / 1000) * pricing.inputCostPer1K\n + (cacheCreationTokens / 1000) * pricing.inputCostPer1K * mult.write\n + (cacheReadTokens / 1000) * pricing.inputCostPer1K * mult.read\n + (completionTokens / 1000) * pricing.outputCostPer1K;\n}\n\n/** Cost of one turn at `model`'s rate (looks up ai.libx.js pricing). */\nfunction turnCost(model: string, usage?: { promptTokens?: number; completionTokens?: number; cacheCreationTokens?: number; cacheReadTokens?: number }): number {\n return costOf(getModelInfo(model)?.pricing, usage?.promptTokens ?? 0, usage?.completionTokens ?? 0, usage?.cacheCreationTokens ?? 0, usage?.cacheReadTokens ?? 0, model);\n}\n\n/** Evaluate whether a goal condition has been met, based on recent transcript. */\nasync function evaluateGoal(ai: ChatLike, condition: string, transcript: Message[], log: (s: string) => void): Promise<{ met: boolean; reason: string }> {\n const recent = transcript\n .filter((m) => m.role === 'assistant')\n .slice(-8)\n .map((m) => {\n const text = typeof m.content === 'string' ? m.content : (m.content as ContentPart[]).filter((p: any) => p.type === 'text').map((p: any) => p.text).join(' ');\n return text.slice(0, 600);\n })\n .join('\\n---\\n');\n try {\n const r = await ai.chat({\n model: 'anthropic/claude-haiku-4-5',\n stream: false,\n messages: [\n { role: 'system', content: 'You judge whether a goal condition has been met based on conversation transcript. Respond ONLY with JSON: {\"met\": boolean, \"reason\": \"one sentence\"}. Be strict — only met:true if there is clear evidence in the transcript.' },\n { role: 'user', content: `Goal condition: ${condition}\\n\\nRecent assistant messages:\\n${recent}` },\n ],\n }) as { content: string };\n const match = r.content.match(/\\{[\\s\\S]*\\}/);\n if (match) return JSON.parse(match[0]);\n } catch (e: any) { log(dim(` (goal evaluator error: ${e?.message ?? e})\\n`)); }\n return { met: false, reason: 'evaluation unclear' };\n}\n\n/** Normalize a thrown/returned error into the persisted forensic shape. */\nfunction errInfo(e: any): { message: string; statusCode?: number; code?: string } {\n return { message: String(e?.message ?? e), statusCode: e?.statusCode, code: e?.code };\n}\n\n/** Format a USD amount: 2 decimals at $1+, 4 below (agent turns are sub-cent). */\nexport function fmtUsd(n: number): string {\n return n >= 1 ? `$${n.toFixed(2)}` : `$${n.toFixed(4)}`;\n}\n\n/** ~4 chars/token estimate over a transcript (matches the Agent's context-budget heuristic). */\nexport function estimateTranscriptTokens(messages: Message[]): number {\n let chars = 0;\n for (const m of messages) chars += (m.content?.length ?? 0) + (m.tool_calls ? JSON.stringify(m.tool_calls).length : 0);\n return Math.ceil(chars / 4);\n}\n\n/** One-screen session status (model, dir, fs-mode, tools, permission posture, turns/tokens). Pure. */\nexport function formatStatus(s: {\n model: string; cwd: string; mode: string; tools: string[]; permissions: string; turns: number; tokens: number; sessionId: string;\n /** Whether the token count is estimated (any turn streamed without provider usage). Defaults to estimated. */\n estimated?: boolean;\n}): string {\n const L = (k: string, v: string) => ` ${k.padEnd(12)} ${v}\\n`;\n const m = (s.estimated ?? true) ? '~' : '';\n return (\n L('model', s.model) + L('directory', s.cwd) + L('fs mode', s.mode) +\n L('permissions', s.permissions) + L('tools', `${s.tools.length} — ${s.tools.join(', ')}`) +\n L('session', `${s.sessionId} · ${s.turns} turn${s.turns === 1 ? '' : 's'} · ${m}${(s.tokens / 1000).toFixed(1)}k tok`)\n );\n}\n\n/** Run a `!cmd` line and return its output — no model call. With `realShell` it shells out to a real\n * /bin/sh (same executor as the agent's `Shell` tool, so `!open`/`!docker`/`!git` work); otherwise it\n * runs over the wcli VFS emulator (sandbox/boddb — a real shell would escape the in-memory/db isolation). */\nexport async function runShellLine(fs: IFilesystem, cmd: string, opts?: { realShell?: boolean; cwd?: string }): Promise<string> {\n // The `!` escape is the user's MANUAL shell. In full-FS mode it must hit a REAL /bin/sh (same executor\n // as the agent's `Shell` tool) — else system binaries (open, docker, pkill, …) 127 in wcli's emulator.\n // Sandbox/boddb keep the wcli VFS emulator: a real shell would escape the in-memory/db isolation to disk.\n if (opts?.realShell) {\n const { makeRealShellTool } = await import('../src/tools.shell');\n // Prefer the user's $SHELL (CC parity: the bang escape is their shell), falling back to /bin/sh.\n const r = await makeRealShellTool({ cwd: opts.cwd ?? process.cwd(), shell: process.env.SHELL }).run({ command: cmd }, {} as any);\n return typeof r === 'string' ? r : r.text;\n }\n const exec = new CommandExecutor(fs);\n registerHeadlessCommands(exec);\n const r = await exec.execute(cmd);\n const out = (r.output ?? '').replace(/\\n+$/, '');\n if (r.exitCode !== 0) return `[exit ${r.exitCode}]${r.error ? ' ' + r.error.trim() : ''}${out ? '\\n' + out : ''}`;\n return out || '(no output)';\n}\n\n/** Resolve a memoryDir (string or string[]) to the primary (write) dir. */\nfunction primaryMemDir(dir: string | string[] | undefined, fallback: string): string {\n return (Array.isArray(dir) ? dir[0] : dir) || fallback;\n}\n\n/** Append a `#note` to the memory index (creating the dir/file if needed). Returns the file path. */\nexport async function appendMemoryNote(fs: IFilesystem, dir: string, text: string): Promise<string> {\n await mkdirp(fs, dir);\n const idx = `${dir}/MEMORY.md`;\n let cur = '';\n try { cur = await fs.readFile(idx); } catch { /* new file */ }\n const head = cur ? cur.replace(/\\n*$/, '\\n') : '# Memory\\n\\n';\n await fs.writeFile(idx, head + `- ${text.replace(/\\s+/g, ' ').trim()}\\n`);\n return idx;\n}\n\nconst ASK_MUTATING = ['bash', 'Shell', 'Write', 'Edit', 'MultiEdit', 'deleteFile'];\nconst RESULT_PREVIEW_LINES = 6; // how many lines of a tool result to echo (vs the old single line)\n// Ctrl+O (CC parity): toggle full tool-result output vs the N-line preview. Module-level so both\n// REPLs, displayHooks and the duplex host read the live value.\nlet verboseOutput = false;\nconst previewLines = () => (verboseOutput ? Number.MAX_SAFE_INTEGER : RESULT_PREVIEW_LINES);\nconst toggleVerbose = (): string => {\n verboseOutput = !verboseOutput;\n err(dim(` ⌃O verbose output ${verboseOutput ? 'on — full tool results' : 'off — previews'}\\n`));\n return verboseOutput ? 'verbose' : 'preview';\n};\n\n/** Can we put an interactive prompt in front of a human? (TTY in + err; stdout may be piped). */\nconst canPrompt = !!(process.stdin.isTTY && process.stderr.isTTY);\n\nexport interface PermMode { gate: 'ask' | 'allow'; notice?: string }\n\n/**\n * Default permission posture — CC-inspired: **ask when a human can answer, allow when unattended.**\n * Pure + exported so the decision is unit-testable without a TTY. Precedence:\n * --yes → allow (explicit trust, no prompts)\n * --ask → ask (explicit gate, even headless)\n * interactive (TTY & not json) → ask (the safe default)\n * else (headless/piped) → allow, with a one-line notice so it's never silent.\n */\nexport function resolvePermMode(args: { yes?: boolean; ask?: boolean; outputFormat?: string }, interactiveCapable: boolean): PermMode {\n if (args.yes) return { gate: 'allow' };\n if (args.ask) return { gate: 'ask' };\n if (interactiveCapable && args.outputFormat === 'text') return { gate: 'ask' }; // json/stream-json ⇒ headless\n return { gate: 'allow', notice: 'unattended: mutating tools auto-approved — pass --ask to gate, --vfs to sandbox, --yes to silence' };\n}\n\n/** Interactive permission resolver: Yes / No / Always-allow / Always-deny. \"Always\" persists a rule\n * to `.agent/permissions.json` (and the policy remembers it for the session). Falls back to a\n * typed y/N when piped. */\nfunction makeAskResolver(cwd: string) {\n return async (call: ToolUse): Promise<{ decision: 'allow' | 'deny'; remember?: boolean } | undefined> => {\n // Deferred MCP routes through McpCall({name}) — ask/remember by the UNDERLYING tool name, or the\n // user can't see what they're approving and \"Always allow\" would blanket-approve every MCP tool.\n const name = call.name === 'McpCall' && typeof call.args?.name === 'string' ? String(call.args.name) : call.name;\n const tgt = call.args?.path ? ` on ${call.args.path}` : (call.args?.command ? `: ${String(call.args.command).slice(0, 60)}` : '');\n // The rich picker needs BOTH streams to be a TTY (it draws to stderr, reads keys from stdin).\n // When stderr is captured (e.g. agentx run as a child) we fall back to a typed y/N below —\n // NOT to the picker, whose `null` we reserve strictly for \"user cancelled\" (Esc = deny).\n const interactive = !!(process.stderr.isTTY && process.stdin.isTTY);\n if (interactive) {\n const v = await selectMenu(process.stderr, {\n title: `? Allow ${name}${tgt}?`,\n items: [\n { label: 'Yes (once)', value: 'allow' },\n { label: 'No', value: 'deny' },\n { label: `Always allow ${name}`, value: 'always-allow' },\n { label: `Always deny ${name}`, value: 'always-deny' },\n ],\n current: 'allow',\n });\n if (v === null) return { decision: 'deny' }; // Esc / Ctrl-C on the picker → deny (CC parity), don't re-ask\n if (v === 'always-allow') { persistRule(cwd, 'allow', name); err(dim(` ✓ remembered: always allow ${name}\\n`)); return { decision: 'allow', remember: true }; }\n if (v === 'always-deny') { persistRule(cwd, 'deny', name); err(dim(` ✓ remembered: always deny ${name}\\n`)); return { decision: 'deny', remember: true }; }\n return { decision: v as 'allow' | 'deny' };\n }\n // Typed y/N fallback (no picker) — abort-aware: a mid-prompt turn-abort (Esc/Ctrl-C flips the\n // signal) rejects io.question so the turn unwinds instantly, instead of hanging (the old\n // \"⚠ still cancelling\" wedge). Anything that isn't an explicit yes — incl. abort — denies.\n const io = createInterface({ input: keyInput, output: process.stderr });\n try {\n const answer = await io.question(yellow(` ? Allow ${name}${tgt}? [y/N] `), { signal: activeTurn?.signal });\n return { decision: /^y(es)?$/i.test(answer.trim()) ? 'allow' : 'deny' };\n } catch { return { decision: 'deny' }; } // aborted (or read error) → deny\n finally { io.close(); }\n };\n}\n\nfunction optsFor(args: Args, ai: ChatLike, cfg: Partial<AgentConfig> = {}, extraTools: AgentTool[] = []): CliOptions {\n const perm = resolvePermMode(args, canPrompt);\n if (perm.notice) err(dim(` ⚠ ${perm.notice}\\n`));\n // Persisted config rules (deny>allow>ask) take precedence; the run's ask-default fills the rest.\n // Config rules apply even under --yes, so a `deny Read(./.env)` can't be flag-bypassed.\n const configRules = parsePermRules(cfg.permissions);\n // --allowedTools / --disallowedTools: per-run grants, highest precedence (deny wins, then allow).\n const flagRules = [...parsePermRules({ deny: args.disallowedTools }), ...parsePermRules({ allow: args.allowedTools })];\n const askRules = perm.gate === 'ask' ? ASK_MUTATING.map((t) => ({ tool: t, decision: 'ask' as const })) : [];\n const rules = [...flagRules, ...configRules, ...askRules];\n if (configRules.length) err(dim(` ⊕ ${configRules.length} permission rule(s) from config\\n`));\n return {\n ai,\n model: resolveModelOrNewest(args.model ?? cfg.model),\n cwd: args.cwd,\n tools: cfg.tools,\n extraTools,\n sandbox: args.vfs,\n boddb: args.boddb,\n seed: args.seed,\n realShell: args.shell, // undefined → core.ts defaults (on for disk, off for sandbox/boddb)\n osSandbox: args.harden ? { network: !!args.hardenNet } : undefined,\n scratch: args.scratch,\n appendSystemPrompt: args.appendSystemPrompt,\n addDirs: args.addDirs,\n stream: args.stream,\n host: makeHost(args.outputFormat, { stream: true }),\n planMode: args.plan || cfg.planMode || false,\n permissions: rules.length\n ? new PermissionPolicy({ rules, default: 'allow', host: makeHost(), ask: makeAskResolver(resolve(args.cwd ?? process.cwd())) })\n : undefined,\n subagents: args.subagents || cfg.subagents || false,\n maxSteps: args.maxSteps ?? cfg.maxSteps,\n reasoning: args.reasoning ?? cfg.reasoning,\n // kill-switches: CLI flag > config > Agent default\n maxTokens: args.maxTokens ?? cfg.maxTokens,\n timeoutMs: args.timeoutMs ?? cfg.timeoutMs,\n maxRepeats: cfg.maxRepeats,\n maxToolCalls: cfg.maxToolCalls,\n keepToolOutputs: cfg.keepToolOutputs,\n maxContextTokens: cfg.maxContextTokens,\n learnFromMistakes: cfg.learnFromMistakes,\n // Forwarded to cursor/* delegations for environment parity (chat-model providers ignore it).\n // Raw config (pre-OAuth): unresolved-oauth http servers are skipped by the cursor mapper.\n mcpServers: cfg.mcpServers,\n };\n}\n\n/** Build the agent and attach fs-aware display hooks (+ any config-declared shell hooks). */\nasync function makeAgent(args: Args, ai: ChatLike, cfg: Partial<AgentConfig>, extraTools: AgentTool[] = []): Promise<Agent> {\n const virtual = args.vfs || !!args.boddb;\n if (virtual && args.shell) err(yellow(` ⚠ --shell ignored in ${args.boddb ? '--boddb' : '--vfs sandbox'} (a real shell would escape to disk)\\n`));\n if (virtual && args.addDirs?.length) err(yellow(` ⚠ --add-dir ignored in ${args.boddb ? '--boddb' : '--vfs sandbox'} (mounted real dirs would escape isolation)\\n`));\n if (args.addDirs?.length && !virtual) err(dim(` + mounted ${args.addDirs.length} extra dir(s): ${args.addDirs.join(', ')}\\n`));\n if (args.vfs) err(dim(' ⊝ sandbox (VFS): operating on an in-memory copy — the real disk will not be modified\\n'));\n else if (args.boddb) err(dim(` ⊝ boddb: files live in a database at ${args.boddb}${args.seed ? ' (seeded from cwd on first run)' : ''} — the real disk will not be modified\\n`));\n else if (args.shell === false) err(dim(' ⊖ --no-shell: VFS bash only (no real /bin/sh)\\n'));\n if (args.harden && !virtual) err(dim(` ⛨ hardened shell: writes confined to cwd+tmp${args.hardenNet ? '' : ', network blocked'} (sandbox-exec/bwrap)\\n`));\n const agent = await buildAgent(optsFor(args, ai, cfg, extraTools));\n const display = displayHooks(agent.options.fs, { flush: (agent.options.host as { flushText?: () => void } | undefined)?.flushText });\n agent.options.hooks = cfg.hooks ? composeHooks(display, hooksFromConfig(cfg.hooks)) : display;\n return agent;\n}\n\n/** For each `auth:'oauth'` http server, inject a cached bearer token (refreshing if needed). A server whose\n * token can't be resolved is left as-is — it'll fail mount with a needs-auth hint pointing at `/mcp login`. */\nasync function resolveOAuth(servers: Record<string, McpServerConfig> = {}, oauth: McpOAuth): Promise<Record<string, McpServerConfig>> {\n const out: Record<string, McpServerConfig> = {};\n for (const [name, cfg] of Object.entries(servers)) {\n if (cfg?.auth === 'oauth' && cfg.url && !cfg.bearerToken) {\n try { out[name] = { ...cfg, bearerToken: await oauth.tokenFor(cfg.url) }; }\n catch { err(yellow(` MCP \"${name}\" needs auth — run /mcp login ${name}\\n`)); out[name] = cfg; }\n } else out[name] = cfg;\n }\n return out;\n}\n\n/** Mount configured MCP servers (one-line summary to stderr); returns the mounted servers. */\nasync function mountMcp(cfg: Partial<AgentConfig>, oauth?: McpOAuth): Promise<MountedMcp[]> {\n const servers = oauth ? await resolveOAuth(cfg.mcpServers, oauth) : cfg.mcpServers;\n const mounted = await mountMcpServers(servers);\n const n = mounted.reduce((s, m) => s + m.tools.length, 0);\n if (n) err(dim(` + ${n} MCP tool(s) from ${mounted.map((m) => m.name).join(', ')}\\n`));\n return mounted;\n}\n\n/** Past this many tools, raw MCP mounts bloat EVERY request's schema (42 browser-bridge tools ≈ 80k\n * tok/turn on a trivial task) — switch to the deferred ToolSearch/McpCall pair (2 bounded tools). */\nconst MCP_DEFER_AT = 12;\n\n/** The agent-facing tool surface for mounted MCP servers: raw tools for small sets, the deferred\n * ToolSearch/McpCall pair beyond MCP_DEFER_AT. Rebuilt on /mcp add/remove/reconnect (the pair's\n * catalog snapshots `mounted` at build time). */\nfunction mcpAgentTools(mounted: MountedMcp[], opts?: { quiet?: boolean }): AgentTool[] {\n const n = mounted.reduce((s, m) => s + m.tools.length, 0);\n if (n <= MCP_DEFER_AT) return mounted.flatMap((m) => m.tools);\n const { tools } = makeMcpToolSearchFromMounted(mounted);\n if (!opts?.quiet) err(dim(` ∴ ${n} MCP tools deferred behind ToolSearch (prompt stays lean · /mcp tools lists them)\\n`));\n return tools;\n}\n\n/** Best-effort shutdown of mounted MCP servers (kills stdio children). */\nasync function closeMcp(mounted: MountedMcp[]): Promise<void> {\n await Promise.all(mounted.map((m) => m.client.close().catch((e) => log.debug('mcp close failed', e))));\n}\n\nconst IMG_EXT: Record<string, string> = { '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.webp': 'image/webp' };\n\n/** Extract `@ref` mentions: bare `@path` (no spaces) or quoted `@\"path with spaces\"` — the quoted\n * form is what lets a drag-dropped macOS screenshot (\"Screenshot 2026-06-11 at ….png\") attach at all.\n * Bare refs get trailing sentence punctuation stripped (e.g. \"@a.ts.\" / \"@a.ts?\"). */\nexport function mentionRefs(line: string): string[] {\n return [...line.matchAll(/(?:^|\\s)@(?:\"([^\"]+)\"|(\\S+))/g)]\n .map((m) => m[1] ?? m[2].replace(/[?!.,;:)\\]}'\">]+$/, ''))\n .filter(Boolean);\n}\n\n/** `~/` is shell syntax — expand it for every user-typed path (mentions, images, pastes). */\nconst untilde = (p: string) => (p.startsWith('~/') ? join(homedir(), p.slice(2)) : p);\n\n/** Read `@image.png` mentions from `line` as base64 image content parts (real files under cwd; binary,\n * so read via node fs — the VFS readFile is utf8). Unreadable/missing images are skipped silently\n * (expandMentions reports the missing @ref separately). */\nexport function readImageParts(cwd: string, line: string): ContentPart[] {\n const refs = mentionRefs(line);\n const parts: ContentPart[] = [];\n for (const ref of refs) {\n const mime = IMG_EXT[extname(ref).toLowerCase()];\n if (!mime) continue;\n const abs = ref.startsWith('~/') ? untilde(ref) : resolve(cwd, ref);\n try { parts.push(imagePart(`data:${mime};base64,${readFileSync(abs).toString('base64')}`)); }\n catch { /* missing/unreadable — skip */ }\n }\n return parts;\n}\n\n/** Classify a pasted blob as a file attachment when it's a drag-dropped/typed path to an existing file.\n * Returns an `@<abs>` ref the existing mention pipeline attaches (images) or inlines (other files); the\n * in-buffer placeholder shows `[Image #N]` / `[File name #N]`. Returns null for anything not a clear single\n * path (so ordinary text pastes are unaffected). Paths with spaces are skipped — the `@\\S+` pipeline can't carry them. */\nexport function pastePathClassifier(cwd: string): PasteClassifier {\n return (text: string) => {\n let t = text.trim();\n if (!t || t.includes('\\n')) return null;\n t = t.replace(/\\\\ /g, ' ').replace(/^['\"]|['\"]$/g, ''); // unescape drag-drop spaces / strip quotes\n if (!/^(\\/|~\\/|\\.\\/|\\.\\.\\/)/.test(t)) return null; // only obvious path-like pastes\n const abs = t.startsWith('~/') ? untilde(t) : resolve(cwd, t);\n try { if (!statSync(abs).isFile()) return null; } catch { return null; }\n const isImg = !!IMG_EXT[extname(abs).toLowerCase()];\n // spaced paths (default macOS screenshot names!) ride the quoted-mention form\n return { display: isImg ? 'Image' : `File ${basename(abs)}`, ref: /\\s/.test(abs) ? `@\"${abs}\"` : '@' + abs };\n };\n}\n\n/** Inline `@path` file mentions: append referenced files' contents so the model sees them (missing → warn, leave as-is). */\n/** Resolves an `@server:uri` MCP-resource mention to its text body; null = not an MCP ref (fall through\n * to file resolution). Set by the REPL once servers are mounted; headless runs leave it unset. */\nexport let mcpMentionResolver: ((ref: string) => Promise<string | null>) | undefined;\nexport function setMcpMentionResolver(fn: typeof mcpMentionResolver): void { mcpMentionResolver = fn; }\n\nexport async function expandMentions(fs: IFilesystem, line: string): Promise<{ text: string; loaded: string[]; missing: string[] }> {\n const refs = mentionRefs(line);\n if (!refs.length) return { text: line, loaded: [], missing: [] };\n const loaded: string[] = [], missing: string[] = [], blocks: string[] = [];\n for (const ref of refs) {\n if (IMG_EXT[extname(ref).toLowerCase()]) continue; // images are attached as content parts, not inlined as text\n if (loaded.includes(ref) || missing.includes(ref)) continue; // dedupe\n if (ref.includes(':') && mcpMentionResolver) { // @server:uri → MCP resource (CC @-resource mentions)\n const body = await mcpMentionResolver(ref).catch((e) => { log.debug('mcp mention resolve failed', e); return null; });\n if (body != null) { blocks.push(`--- @${ref} ---\\n${body}`); loaded.push(ref); continue; }\n }\n const path = untilde(ref);\n try {\n if (await fs.exists(path)) { blocks.push(`--- @${ref} ---\\n${await fs.readFile(path)}`); loaded.push(ref); }\n else missing.push(ref);\n } catch { missing.push(ref); }\n }\n return { text: blocks.length ? `${line}\\n\\n${blocks.join('\\n\\n')}` : line, loaded, missing };\n}\n\n/** The headless `--output-format json` result object for a turn. */\nexport function jsonResult(res: RunResult, session: SessionData) {\n const lastUser = res.messages.map((m) => m.role).lastIndexOf('user');\n return {\n ok: res.finishReason === 'stop',\n finishReason: res.finishReason,\n text: res.text,\n steps: res.steps,\n tools: res.messages.slice(lastUser).filter((m) => m.role === 'tool').length,\n usage: res.usage,\n sessionId: session.meta.id,\n ...(res.finishReason === 'error' && res.error ? { error: (res.error as any)?.message ?? String(res.error) } : {}),\n };\n}\n\n/**\n * Read one logical input, supporting `\\`-continuation for multi-line prompts: a line ending in\n * a backslash drops the `\\` and keeps reading; the parts are joined with newlines. `readLine`\n * is injected (the REPL passes a readline `question`; tests pass a scripted reader).\n */\nexport async function readMultiline(readLine: (continuing: boolean) => Promise<string | null>): Promise<string | null> {\n const parts: string[] = [];\n for (;;) {\n const part = await readLine(parts.length > 0);\n if (part == null) return null; // EOF (Ctrl-D) → exit the REPL\n if (part.endsWith('\\\\')) { parts.push(part.slice(0, -1)); continue; } // trailing \\ → keep going\n parts.push(part);\n return parts.join('\\n');\n }\n}\n\n/** Send one turn (expanding @file mentions), print the footer, persist the session.\n * `sendFn` overrides how the turn is dispatched (duplex routes through dx.send's mutex); `agent`\n * stays the transcript-owning agent (the voice, in duplex) — mentions/fs/signal/cost read off it. */\nexport async function runTurn(agent: Agent, store: SessionStore, session: SessionData, task: string, cp?: Checkpoints, cwd = process.cwd(), sendFn?: (content: MessageContent) => Promise<RunResult>): Promise<{ ok: boolean; res?: RunResult }> {\n const t0 = Date.now();\n await cp?.begin(task); // open a checkpoint frame so this turn's edits can be /rewound\n const { text, loaded, missing } = await expandMentions(agent.options.fs!, task);\n if (loaded.length) err(dim(` + inlined ${loaded.map((f) => '@' + f).join(' ')}\\n`));\n if (missing.length) err(yellow(` ⚠ not found: ${missing.map((f) => '@' + f).join(' ')}\\n`));\n // @image.png mentions → attach as multimodal content parts (needs a vision model).\n const images = readImageParts(cwd, task);\n if (images.length) err(dim(` + attached ${images.length} image(s)\\n`));\n // Don't waste a model call when the input was ONLY unresolved @-mentions (e.g. \"@asd\").\n if (missing.length && !loaded.length && !task.replace(/(?:^|\\s)@\\S+/g, '').trim()) {\n err(dim(' (nothing to send — that file doesn\\'t exist)\\n'));\n return { ok: false };\n }\n // per-turn aborter: Esc / Ctrl-C / SIGINT flips agent.options.signal so the loop stops between steps.\n const ctrl = new AbortController();\n activeTurn = ctrl;\n agent.options.signal = ctrl.signal;\n // Raw mode stays on for the whole REPL session (the line editor owns it), so the Esc/Ctrl-C\n // keypress is delivered live during the turn — no per-turn stdin juggling needed here.\n const content = images.length ? [{ type: 'text' as const, text }, ...images] : text;\n let res: RunResult;\n spinner.turnStart = t0; // elapsed counter spans the whole turn (tool calls stop/restart the spinner)\n spinner.start(sendFn ? 'voice…' : undefined);\n // Mid-turn persistence: a long agentic turn (many tool steps) otherwise lives ONLY in memory until\n // the turn ends — a crash mid-turn loses the whole transcript. The Agent fires `turn_start` at every\n // step boundary; piggyback on it to flush the committed-so-far transcript to disk.\n const msgsBefore = agent.transcript.length; // for the silent-abort discriminator below\n const host = agent.options.host;\n const origNotify = host?.notify?.bind(host);\n if (host && origNotify) host.notify = (e) => {\n if (e.kind === 'turn_start') {\n session.messages = agent.transcript;\n session.meta.updated = Date.now();\n try { store.save(session); } catch (ex) { log.debug('mid-turn session flush failed', ex); }\n }\n return origNotify(e);\n };\n try {\n res = await (sendFn ? sendFn(content) : agent.send(content));\n } catch (e: any) {\n spinner.stop();\n err(red(` error: ${e?.message ?? e}\\n`));\n // record the hard-throw turn too (this path used to persist nothing → no forensic trace)\n (session.meta.events ??= []).push({ ts: t0, durationMs: Date.now() - t0, model: agent.options.model, finishReason: 'error', steps: 0, tools: 0, error: errInfo(e) });\n session.meta.updated = Date.now();\n try { store.save(session); } catch { /* non-fatal */ }\n return { ok: false };\n } finally {\n spinner.stop();\n spinner.turnStart = 0;\n activeTurn = null;\n agent.options.signal = undefined;\n if (host && origNotify) host.notify = origNotify; // unwrap — turns must not stack flush wrappers\n }\n (agent.options.host as { flushText?: () => void } | undefined)?.flushText?.(); // emit any buffered markdown tail\n flushLookupGroup(); // a turn ending on read-only lookups still owes their grouped summary line\n const secs = ((Date.now() - t0) / 1000).toFixed(1);\n const cost = turnCost(agent.options.model, res.usage);\n const m = res.usageEstimated ? '~' : ''; // exact usage (provider-reported) drops the tilde\n const tok = res.usage?.totalTokens ? `${m}${(res.usage.totalTokens / 1000).toFixed(1)}k tok · ${cost > 0 ? m + fmtUsd(cost) + ' · ' : ''}` : '';\n const lastUser = res.messages.map((m) => m.role).lastIndexOf('user');\n const tools = res.messages.slice(lastUser).filter((m) => m.role === 'tool').length;\n const ok = res.finishReason === 'stop';\n const shortId = session.meta.id.replace(/^\\d{8}-/, ''); // drop YYYYMMDD- prefix → HHMMSS-folder\n // clear the (multi-line) ticking footer first — otherwise its tail glues onto this line (\"· 3.5s · e; keep chatting\")\n // newline FIRST, then clear-below: the cursor may sit at the end of a streamed text line (voice\n // mode) — clearing from it would erase the reply's last line; clearing from a fresh line only\n // removes footer residue below.\n // Barge-in aborts with zero tokens are normal turn-taking noise — suppress the footer\n // \"Did the model do any work?\" must be judged by transcript growth, NOT token count: providers\n // that don't report usage (cursor/*) show 0 tokens even after a long tool-heavy turn, and the\n // token heuristic silently dropped a whole aborted transcript (20260611-234609-test, 27min lost).\n const didWork = agent.transcript.slice(msgsBefore).some((m) => m.role === 'assistant' || m.role === 'tool');\n const silentAbort = res.finishReason === 'aborted' && !res.usage?.totalTokens && !didWork;\n if (!silentAbort)\n err('\\n' + (process.stderr.isTTY ? '\\r\\x1b[0J' : '') + (ok ? green(' ✓ done') : red(` ✗ ${res.finishReason}`)) + dim(` · ${res.steps} steps · ${tools} tools · ${tok}${secs}s · ${shortId}\\n`));\n // Long turn finished → terminal bell, so a user who tabbed away gets pinged (CC parity).\n if (!silentAbort && process.stderr.isTTY && Date.now() - t0 > 10_000) err('\\x07');\n // on a failed turn, show the provider's message so a billing/quota 400 isn't mistaken for a bad request\n if (res.finishReason === 'error' && res.error) {\n const e = res.error as any;\n err(red(` ${e?.message ?? e}`) + (e?.statusCode ? dim(` (${e.statusCode}${e.code ? ' ' + e.code : ''})`) : '') + '\\n');\n }\n // Skip persisting zero-token aborts (barge-in noise — no model work, no transcript change)\n if (silentAbort) return { ok: false, res };\n // persist (non-fatal on failure)\n session.messages = agent.transcript;\n session.meta.turns += 1;\n session.meta.tokens = (session.meta.tokens ?? 0) + (res.usage?.totalTokens ?? 0); // cumulative for /cost\n session.meta.costUsd = (session.meta.costUsd ?? 0) + cost; // cumulative USD (per-turn model rate)\n if (res.usageEstimated) session.meta.costEstimated = true; // sticky: any estimated turn → session total is estimated\n session.meta.updated = Date.now();\n session.meta.model = agent.options.model;\n const ev: TurnEvent = { ts: t0, durationMs: Date.now() - t0, model: agent.options.model, finishReason: res.finishReason, steps: res.steps, tools, tokens: res.usage?.totalTokens, costUsd: cost, estimated: res.usageEstimated };\n if (res.finishReason === 'error' && res.error) ev.error = errInfo(res.error);\n (session.meta.events ??= []).push(ev);\n if (!session.meta.title) { session.meta.title = titleOf(agent.transcript); if (session.meta.title) setTermTitle(`agentx · ${session.meta.title}`); }\n try { store.save(session); } catch (e: any) { err(dim(` (session not saved: ${e?.message ?? e})\\n`)); }\n return { ok, res };\n}\n\n/** Resolve the starting session: resume an existing one (seeding the transcript) or start fresh. */\nfunction startSession(args: Args, store: SessionStore, agent: Agent, cwd: string): SessionData {\n if (args.resume || args.cont) {\n const data = args.resume ? (store.load(args.resume) ?? globalSessionLoad(args.resume)) : store.latestData();\n if (data) {\n agent.transcript = data.messages;\n if (args.fork) { // --fork-session: branch into a NEW id so the source session is left untouched\n const now = Date.now();\n const forked: SessionData = { meta: { ...data.meta, id: args.sessionId ?? store.newId(now, cwd), created: now, updated: now, turns: data.meta.turns }, messages: data.messages };\n err(dim(` forked ${data.meta.id} → ${forked.meta.id} (${data.meta.turns} turns)\\n`));\n if (!args.task) printHistory(data.messages);\n return forked;\n }\n err(dim(` resumed session ${data.meta.id} (${data.meta.turns} turns) — ${data.meta.title}\\n`));\n if (!args.task) printHistory(data.messages); // replay the convo for an interactive resume (skip for headless -c \"task\")\n return data;\n }\n err(yellow(` no session to resume — starting fresh\\n`));\n }\n const now = Date.now();\n const id = args.sessionId ?? store.newId(now, cwd);\n if (!args.task) err(dim(` session ${id}\\n`)); // surface the id up front so it's quotable when reporting an issue\n return { meta: { id, created: now, updated: now, cwd, model: agent.options.model, turns: 0, title: '' }, messages: [] };\n}\n\nconst AGENTS_MD_TEMPLATE = `# ${'${name}'}\n\n## Overview\n<!-- What this project is, in 1-2 sentences. -->\n\n## Conventions\n- <!-- e.g. package manager, code style, module layout -->\n\n## Commands\n- build:\n- test:\n- run:\n\n## Notes\n<!-- Anything the agent should always keep in mind. -->\n`;\n\n/** Scaffold ./AGENTS.md if no project-instruction file exists yet. */\nfunction initInstructions(cwd: string): void {\n for (const f of ['AGENTS.md', 'CLAUDE.md']) {\n if (existsSync(join(cwd, f))) { err(yellow(` ${f} already exists — leaving it as-is\\n`)); return; }\n }\n const path = join(cwd, 'AGENTS.md');\n writeFileSync(path, AGENTS_MD_TEMPLATE.replace('${name}', basename(cwd)));\n err(green(` created ${path}\\n`) + dim(' edit it, then it auto-loads into every run.\\n'));\n}\n\n/** Persist a setting to ./.agent/settings.json so it survives restarts (loadConfig reads it back). */\nfunction persistSetting(cwd: string, key: string, value: unknown): void {\n const path = join(cwd, '.agent', 'settings.json');\n try {\n const obj = existsSync(path) ? JSON.parse(readFileSync(path, 'utf8')) : {};\n if (obj[key] === value) return;\n obj[key] = value;\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify(obj, null, 2) + '\\n');\n } catch (e: any) {\n err(yellow(` ⚠ couldn't persist ${key} to ${path} — ${e?.message ?? e}\\n`));\n }\n}\nconst persistModel = (cwd: string, model: string) => persistSetting(cwd, 'model', model);\n\n// The @cursor/sdk provider streams over ConnectRPC/HTTP-2 (connect-node). Aborting a run surfaces as a\n// *background* rejection that's never thrown into our for-await, so it can't be caught at the call site —\n// either a clean cancel (ConnectError [canceled] \"operation was aborted\", cause DOMException ABORT_ERR)\n// or, on a racing teardown, NGHTTP2_FRAME_SIZE_ERROR. Both are benign: they only happen because WE\n// cancelled. Swallow exactly those; surface anything else.\nconst isCancelTeardown = (e: any): boolean => {\n if (!e) return false;\n if (e.code === 20 || e.cause?.code === 20) return true; // DOMException ABORT_ERR\n const blob = `${e.code ?? ''} ${e.name ?? ''} ${e.cause?.name ?? ''} ${e.rawMessage ?? ''} ${e.message ?? ''}`;\n return /NGHTTP2_FRAME_SIZE_ERROR|ERR_HTTP2_STREAM_ERROR|operation was aborted|\\bAbortError\\b/i.test(blob);\n};\n/** Process-level guards shared by BOTH REPLs (normal + duplex — a duplex CancelTask on a cursor worker\n * fires the same background rejection): a rejection keeps the session alive, only a true uncaught\n * exception is fatal, and the benign cursor cancel-teardown is dropped to a debug line. */\nfunction installCancelGuards(mounted: MountedMcp[]): void {\n process.on('unhandledRejection', (e) => {\n if (isCancelTeardown(e)) { log.debug('suppressed unhandledRejection (cursor stream cancel)', e); return; }\n log.error('unhandledRejection', e);\n });\n process.on('uncaughtException', (e) => {\n if (isCancelTeardown(e)) { log.debug('suppressed uncaughtException (cursor stream cancel)', e); return; }\n console.error(e); void closeMcp(mounted); process.exit(1);\n });\n}\n\nasync function repl(args: Args, ai: ChatLike, cfg: Partial<AgentConfig>, cwd: string) {\n const oauth = new McpOAuth({ storePath: join(cwd, '.agent', 'mcp-auth.json') });\n const mounted = await mountMcp(cfg, oauth);\n let mcpToolNames = [] as string[]; // current MCP tool surface on the agent (raw names OR the deferred pair) — for /mcp rebuilds\n const initialMcpTools = mcpAgentTools(mounted);\n mcpToolNames = initialMcpTools.map((t) => t.name);\n // In duplex mode this agent is the WORKER TEMPLATE — it never sends; its options (fs mode,\n // permissions, hooks, MCP tools) become the per-task worker options below.\n const agent = await makeAgent(args, ai, cfg, initialMcpTools);\n\n // Non-duplex voice: let the model exit the session when the user says goodbye.\n // Duplex voice gets ExitSession via reflexOptions.tools (the agent here is the worker template — workers don't need it).\n if (args.voice && !args.duplex) agent.options.tools = [...(agent.options.tools ?? []), exitSessionTool(() => { exitRequested = true; })];\n\n // ── In-process scheduler: fires prompts on a timer while the session is alive.\n // When a job is due and no turn is running, it dispatches directly (like voice utterances).\n // When a turn IS running, it queues for drain after the turn finishes.\n const scheduleQueue: string[] = [];\n let scheduleTurn: ((prompt: string) => Promise<any>) | undefined; // bound once `turn` exists\n const scheduler = new Scheduler({\n fire: (job) => {\n if (!activeTurn && scheduleTurn) {\n err(dim(` ⏰ scheduled › ${job.prompt.slice(0, 60)}${job.prompt.length > 60 ? '…' : ''}\\n`));\n void scheduleTurn(job.prompt).then(() => editorRef?.redrawNow());\n } else {\n scheduleQueue.push(job.prompt);\n }\n },\n tickMs: 15_000,\n });\n // How an OS-fired job re-invokes this CLI: re-use the current interpreter + entry script (works\n // for dev `bun cli/cli.ts` and the installed bin shim alike); bare `agentx` as a last resort.\n const agentxInvocation = () => (process.argv[1] ? `${process.execPath} ${resolve(process.argv[1])}` : 'agentx');\n // OS-backend (mind/12): far one-offs (or explicit backend:'os') register with launchd/cron/at and\n // survive quitting — the fired job headless-resumes THIS session. sessionId reads lazily (the\n // session object is created below and can be swapped by /resume).\n const osSched = new OsScheduler({ agentx: agentxInvocation() });\n const osBackend = osSched.available() ? {\n get sessionId() { return session.meta.id; },\n cwd,\n route: (t: Trigger, hint?: string) => routeTrigger(t, hint),\n schedule: (spec: OsJobSpec) => osSched.schedule(spec),\n cancel: (id: string) => osSched.cancel(id),\n list: () => osSched.list(),\n } : undefined;\n agent.options.tools = [...(agent.options.tools ?? []), ...makeScheduleTools(scheduler, osBackend)];\n\n // ── RemoteTrigger: this session is live-triggerable via its unix socket (same-user only); the\n // injected prompt rides the scheduler's seam (direct when idle, queued mid-turn). The tool side\n // lets THIS agent trigger other sessions (live socket first, headless --resume fallback).\n const triggerServer = new TriggerServer((req) => {\n const tag = req.from ? `session ${req.from}` : 'remote trigger';\n if (!activeTurn && scheduleTurn) {\n err(dim(` ⚡ ${tag} › ${req.prompt.slice(0, 60)}${req.prompt.length > 60 ? '…' : ''}\\n`));\n void scheduleTurn(req.prompt).then(() => editorRef?.redrawNow());\n } else {\n scheduleQueue.push(req.prompt);\n }\n });\n agent.options.tools = [...(agent.options.tools ?? []), makeRemoteTriggerTool({ agentx: agentxInvocation(), selfId: () => session.meta.id })];\n\n // ── Duplex mode (`--duplex`): the REPL runs unchanged, but turns go through a fast VOICE agent\n // that answers instantly and delegates real work to background workers (re-voiced when done).\n // `face` = the transcript-owning agent the REPL drives (sessions, footer, Esc-abort, /compact);\n // `work` = the options that mean \"the working agent\" (/model, /reasoning, /tools, permissions —\n // in duplex these are the WORKERS' options; workers are constructed fresh per Act/Think).\n const duplex = args.duplex;\n let dx: DuplexAgent | undefined;\n let voiceIO: VoiceIO | undefined; // real voice I/O (--voice + keys): mic→STT in, text_delta→TTS out\n // Voice on-screen echo is APPEND-ONLY (no progressive climb-and-clear). In duplex many async writers\n // (task panels, the 🎤 utterance line, barge-in notices, editor repaints) interleave on stdout and\n // desync the MarkdownStream's in-place redraw — which then re-emits the whole in-progress line every\n // delta, producing the \"replay garble\" wall. Appending raw (markdown-stripped to match speech) is\n // immune to cursor desync. voiceLineOpen tracks whether a trailing newline is owed at turn end.\n let voiceLineOpen = false;\n const voiceEcho = (text: string) => { const s = forSpeech(text); if (!s) return; process.stdout.write(s); voiceLineOpen = true; };\n const voiceEchoEnd = () => { if (voiceLineOpen) { process.stdout.write('\\n'); voiceLineOpen = false; } };\n let toggleVoice: (() => Promise<void>) | undefined; // bound below (duplex + TTY): /voice flips mic on/off live\n let editorRef: LineEditor | undefined; // bound once the line editor exists — async chrome repaints the prompt via it\n // During a turn the user's type-ahead lives on a \"stash ›\" line (no active editor to own it). Async\n // chrome (streamed deltas, task events) lands on top of it — repaint the stash below, so it survives.\n let repaintStash: () => void = () => {};\n let workerOptions: AgentOptions | undefined;\n // Worker UI verbosity: 'full' = ⚙ tool chrome per worker step; 'minimal' = task events only\n // (started/progress/⦿ done). Voice defaults minimal (chrome is noise next to speech); /workers toggles live.\n let workerChrome: 'full' | 'minimal' = 'full';\n let duplexPersist: () => void = () => {}; // bound once the session exists (re-voice fires async)\n let duplexAccount: (data: any) => void = () => {}; // worker cost → session meta (bound below)\n // Workers are non-interactive: a permission 'ask' can't pop a menu mid-conversation (it would fight\n // the line editor for raw stdin). VOICE mode relays the ask through the conversation (park →\n // '[task asks]' re-voice → spoken yes/no via AnswerTask; timeout → deny). Text duplex (and the\n // relay's timeout path) auto-denies with a narratable reason — the worker adapts or reports back.\n let permSeq = 0;\n const duplexAsk = async (call: ToolUse): Promise<{ decision: 'allow' | 'deny' }> => {\n if (args.voice && dx) {\n const hint = summarizeCall(call.name, call.args).slice(0, 80);\n // Default: approve like a normal session — suspend the editor, pop an interactive picker\n // (Allow once / always / Deny). Set `voiceAskUi: 'relay'` to opt into the spoken park/relay flow.\n if ((cfg as any).voiceAskUi !== 'relay') {\n editorRef?.suspend();\n const v = await selectMenu(process.stderr, {\n title: `? background worker asks to run ${call.name} ${hint}`,\n items: [{ label: 'Allow once', value: 'y' }, { label: 'Allow always', value: 'a' }, { label: 'Deny', value: 'n' }],\n current: 'y',\n });\n editorRef?.resume();\n editorRef?.redrawNow();\n if (v === 'a') {\n // Remember a command-scoped allow: a live session rule (wins next ask; glob has no `*`\n // → exact-command match) + persist to .agent/permissions.json for future sessions.\n const cmd = typeof call.args?.command === 'string' ? call.args.command : null;\n work.permissions?.options.rules.unshift(cmd ? { tool: call.name, pathGlob: cmd, decision: 'allow' } : { tool: call.name, decision: 'allow' });\n persistRule(cwd, 'allow', cmd ? `${call.name}(${cmd})` : call.name);\n }\n return { decision: v === 'y' || v === 'a' ? 'allow' : 'deny' };\n }\n // NB: perm asks are keyed perm-N (PermissionPolicy.ask carries no task identity), so a\n // cancelled task can't clean its parked perm question — bounded by askTimeoutMs → deny.\n // (Chrome prints once via the task_ask notify below — no extra line here.)\n const id = `perm-${++permSeq}`;\n const a = await dx.parkQuestion(id, `Permission: may the background worker run ${call.name}${hint ? ` (${hint})` : ''}? Answer yes or no (you can also type it).`);\n const allow = /^\\s*(y(es|ep|eah)?|sure|ok(ay)?|allow|go|approved?|do it)\\b/i.test(a);\n err('\\r\\x1b[0J' + (allow ? green(` ✓ allowed ${call.name}`) : yellow(` ⊘ denied ${call.name}`)) + dim(` (${a.trim() || 'no answer'})\\n`));\n editorRef?.redrawNow();\n return { decision: allow ? 'allow' : 'deny' };\n }\n err('\\r\\x1b[0J' + yellow(` ⊘ worker asked to run ${call.name} — auto-denied (no interactive approval in duplex; use --yes or --allowedTools)\\n`));\n editorRef?.redrawNow(); // background event at a live prompt — repaint below the notice\n return { decision: 'deny' };\n };\n if (duplex) {\n // Workers must not stream into the voice channel — strip the host/stream seam (display hooks stay:\n // worker tool activity prints as dim stderr chrome). `signal` is per-task (duplex.ts owns it).\n // Drop providerOptions too: they're computed for the MAIN agent's model (e.g. cursor's cwd/cursorSession)\n // and must never leak onto a worker whose model differs — DuplexAgent recomputes them per worker model\n // via providerOptionsFor below. (A cursor cursorSession leaking onto an anthropic worker is a hard 400.)\n const { host: _host, stream: _stream, signal: _signal, providerOptions: _po, ...wo } = agent.options;\n workerOptions = wo as AgentOptions;\n if (workerOptions.permissions)\n workerOptions.permissions = new PermissionPolicy({ ...workerOptions.permissions.options, host: undefined, ask: duplexAsk });\n workerOptions.planMode = false; // a worker's plan could never be approved (no host) — it would stall to maxSteps\n // Workers are BACKGROUND agents: rebuild their display hooks so chrome never drives the foreground\n // spinner (the 'agentx › '/'⠹ thinking…' flicker) and repaints the live prompt after each print.\n workerChrome = args.voice ? 'minimal' : (cfg.workerChrome ?? 'full');\n const workerDisplay = displayHooks(agent.options.fs, { gate: () => workerChrome === 'full', background: () => editorRef?.redrawNow() });\n workerOptions.hooks = cfg.hooks ? composeHooks(workerDisplay, hooksFromConfig(cfg.hooks)) : workerDisplay;\n // The single voice: markdown-rendered deltas on stdout = the SPOKEN channel. Everything else\n // (⚙ tool chrome, task events, worker results) is VISUAL chrome on stderr — when wired to a\n // real voice API, only text_delta becomes speech; the rest feeds the screen.\n const base = makeHost('text', { stream: true });\n const host: typeof base = {\n ...base,\n notify(e: any) {\n // In live VOICE mode the reflex's raw reasoning (thinking_delta) and per-step headers (turn_start)\n // are screen noise — the spoken answer IS the product. Suppress them so the analysis channel\n // (\"User wants a table. Need weather…\") never lands on screen looking like leaked output. Text-duplex\n // (no mic) keeps them: they're useful chrome when you're reading, not listening.\n if (voiceIO && (e.kind === 'thinking_delta' || e.kind === 'turn_start')) return;\n // SPOKEN channel tap (mind/10-duplex.md): only the voice's text_delta becomes speech.\n // Streaming text to stdout while the line editor is LIVE corrupts the terminal (the editor's\n // climb-and-clear redraws fire mid-paragraph and erase it) — so the editor is SUSPENDED for\n // the duration of a streaming voice turn and resumed (fresh repaint) at turn end.\n if (e.kind === 'text_delta' && voiceIO) {\n voiceIO.speakDelta(e.message);\n editorRef?.suspend(); // no-op when already suspended\n voiceEcho(e.message); // append-only screen echo — NOT base.notify's progressive md render (cursor-desync → replay garble)\n return;\n } else if (e.kind === 'text_delta' && stashText()) {\n // TEXT mode with type-ahead pending: lift the sacred stash line, let the markdown stream\n // land, then repaint the stash below it (else the streamed ack overwrites what's being typed).\n process.stdout.write('\\r\\x1b[K');\n base.notify!(e);\n repaintStash();\n return;\n }\n if (e.kind === 'hold_filler' && voiceIO) {\n voiceIO.speakFiller(e.message);\n return;\n }\n if (e.kind === 'revoice_done') { // a re-voice turn ended outside runTurn's flush — drain the tail now\n if (voiceIO) voiceEchoEnd(); else { base.flushText(); process.stdout.write('\\n'); } // voice = append-only; text-duplex = md flush\n voiceIO?.endSpeech(); // a re-voice turn is spoken too — close its TTS context (idempotent)\n duplexPersist(); // a re-voice turn changed the transcript with no send() in flight — save it too\n editorRef?.resume(); // repaint the prompt block below the streamed text\n editorRef?.redrawNow();\n return;\n }\n if (e.kind === 'task_done' && e.data?.text) { // show the worker's full result visually (the voice only summarizes it)\n const lines = String(e.data.text).split('\\n');\n const shown = lines.slice(0, previewLines());\n // This lands ASYNC, often on top of the live prompt/footer — clear the current line first\n // (else footer residue glues onto the ⦿ header) and repaint the prompt block after.\n // \\x1b[0J (clear to end of screen): the ticking footer is MULTI-line — clearing one line\n // leaves \"…working in background…\" residue glued to this header; redrawNow repaints below.\n err('\\r\\x1b[0J\\n' + dim(` ⦿ ${e.message}\\n`) + shown.map((l) => dim(` ${plainLine(l)}\\n`)).join('')); // strip raw markdown markers in the preview\n if (lines.length > shown.length) err(dim(` … (+${lines.length - shown.length} more lines)\\n`));\n duplexAccount(e.data); // worker tokens/cost are real spend — fold into /cost\n editorRef?.redrawNow();\n repaintStash(); // type-ahead survives the async ⦿ landing\n return;\n }\n // Remaining task_* events (started/progress/cancelled/error) land ASYNC at a live prompt —\n // same treatment as task_done: clear the prompt line, print, repaint (bare err() leaves\n // residue glued to 'agentx › '). task_done returned above; everything else falls through.\n if (typeof e.kind === 'string' && e.kind.startsWith('task_')) {\n spinner.stop();\n // asks are decisions, not chatter — make them stand out (the voice also speaks them)\n err('\\r\\x1b[0J' + (e.kind === 'task_ask' ? yellow(` ? ${e.message} — answer by voice or type yes/no\\n`) : dim(` · ${e.message}\\n`)));\n editorRef?.redrawNow();\n repaintStash(); // type-ahead survives the async task event landing\n return;\n }\n base.notify!(e); // makeHost always provides notify (the HostBridge type just marks it optional)\n },\n };\n // Conversational undo: the voice can roll back per-task checkpoint frames (\"undo that\").\n const rewindFilesTool: AgentTool = {\n name: 'RewindFiles',\n description: 'Undo file changes made by Act/Think tasks: roll back the last N task checkpoints (default 1). Use when the user asks to undo/revert what a task changed.',\n parameters: { type: 'object', properties: { steps: { type: 'number', description: 'how many task checkpoints to undo (default 1)' } } },\n run: async ({ steps }) => {\n if (!checkpoints.size) return 'No file checkpoints to rewind yet.';\n if ([...(dx?.tasks.values() ?? [])].some((t) => t.status === 'running'))\n return 'A task is still running — cancel it first (CancelTask), then rewind.';\n const n = Math.min(Math.max(1, Number(steps ?? 1)), checkpoints.size);\n const r = await checkpoints.rewindTo(checkpoints.size - n);\n return `Rewound ${n} task checkpoint(s): restored ${r.restored} file(s), deleted ${r.deleted}.`;\n },\n };\n dx = new DuplexAgent({\n ai,\n fs: agent.options.fs,\n memoryDir: agent.options.memoryDir,\n memoryUserDir: agent.options.memoryUserDir,\n ...((args.voiceModel ?? cfg.reflexModel) ? { reflexModel: resolveModelOrNewest((args.voiceModel ?? cfg.reflexModel)!) } : {}),\n actModel: agent.options.model,\n actOptions: workerOptions,\n providerOptionsFor: (m) => cursorProviderOptions(m, cwd, cfg.mcpServers),\n ...((args.thinkModel ?? cfg.thinkModel) !== undefined ? { thinkModel: (args.thinkModel ?? cfg.thinkModel) === false ? false : resolveModelOrNewest(String(args.thinkModel ?? cfg.thinkModel)) } : {}),\n host,\n ...(args.voice ? { voiceStyle: 'conversational' as const, progressUpdates: true, askRelay: true } : {}), // voice: progress asides + worker questions relayed through the conversation\n // Per-TASK checkpoint frames (the natural undo unit in duplex = one delegation): opened BEFORE\n // the worker spawns (post-spawn would race its first edits). `checkpoints` is bound below.\n onTaskStart: async (_id, label) => { await checkpoints.begin(label); },\n // The jail deny-lists .git/** (VCS internals can carry credentials), so the engine's fs-based\n // 'branch' lookup can't see it — supply it host-side (one safe read-only file).\n quickLook: {\n branch: () => {\n try {\n const head = readFileSync(join(cwd, '.git', 'HEAD'), 'utf8').trim();\n return head.startsWith('ref: refs/heads/') ? `branch: ${head.slice('ref: refs/heads/'.length)}` : `detached HEAD at ${head.slice(0, 12)}`;\n } catch { return 'not a git repository'; }\n },\n memory: async () => {\n const _adot = (s: string) => `${(agent.options.fs!.getCwd() === '/' ? '' : agent.options.fs!.getCwd())}/.agent/${s}`;\n const dirs = Array.isArray(agent.options.memoryDir) ? agent.options.memoryDir : [agent.options.memoryDir || _adot('memory')];\n const parts: string[] = [];\n for (const d of dirs) {\n try { const idx = await fs.readFile(`${d}/MEMORY.md`); if (idx.trim()) parts.push(idx.trim()); } catch { /* dir doesn't exist yet */ }\n }\n return parts.length ? parts.join('\\n').slice(0, 2000) : '(no memory yet)';\n },\n },\n // The voice runs on the REAL fs (it has no fs tools — harmless) so @mentions, !cmd and #note\n // resolve against the project; + CC-parity chrome for its own tool calls (⚙ Act …).\n reflexOptions: { fs: agent.options.fs, hooks: displayHooks(agent.options.fs), tools: [rewindFilesTool, exitSessionTool(() => { exitRequested = true; })] },\n });\n }\n const face: Agent = dx ? dx.voice : agent; // the transcript-owning agent the REPL drives\n const work: AgentOptions = workerOptions ?? agent.options; // \"the working agent\" options\n const sendVia = dx ? (c: MessageContent) => dx!.send(c) : undefined; // runTurn dispatch override\n\n // ── Permission posture (Shift+Tab cycles it live; CC parity). default=ask · acceptEdits=ask only shell · plan ──\n // Re-read persisted rules each rebuild so \"Always allow/deny\" choices made earlier THIS session survive a cycle.\n const baseRules = () => [\n ...parsePermRules({ deny: args.disallowedTools }),\n ...parsePermRules({ allow: args.allowedTools }),\n ...parsePermRules(mergePerms(loadPersistedRules(cwd), cfg.permissions)),\n ];\n const askFor = (tools: string[]) => tools.map((t) => ({ tool: t, decision: 'ask' as const }));\n // No 'plan' in duplex — workers are non-interactive, an ExitPlanMode could never be approved.\n const POSTURES: readonly Posture[] = duplex ? ['default', 'acceptEdits'] : ['default', 'acceptEdits', 'plan'];\n type Posture = 'default' | 'acceptEdits' | 'plan';\n let posture: Posture = (!duplex && (args.plan || cfg.permissionMode === 'plan')) ? 'plan' : cfg.permissionMode === 'acceptEdits' ? 'acceptEdits' : 'default';\n const postureLabel = () => posture === 'default' ? 'ask (default)' : posture === 'acceptEdits' ? 'accept edits' : 'plan mode';\n const applyPosture = (p: Posture) => {\n posture = p;\n const ask = p === 'acceptEdits' ? askFor(['bash', 'Shell']) : askFor(ASK_MUTATING);\n // In duplex this rebuilds the WORKERS' policy (work = workerOptions; workers spawn fresh per task)\n // with the auto-deny ask; in normal mode it's the live agent's policy with the interactive menu.\n work.permissions = new PermissionPolicy({ rules: [...baseRules(), ...ask], default: 'allow', host: duplex ? undefined : makeHost(), ask: duplex ? duplexAsk : makeAskResolver(cwd) });\n if (!duplex) {\n agent.options.planMode = p === 'plan';\n agent.reprepare(); // rebuild prompt/tools/plan-mode/permission hooks on the next send\n }\n };\n const cyclePosture = (): string => { applyPosture(POSTURES[(POSTURES.indexOf(posture) + 1) % POSTURES.length]); err(dim(` ⇥ ${postureLabel()}\\n`)); return postureLabel(); };\n if (!args.yes) applyPosture(posture); // --yes keeps makeAgent's allow-all (don't impose asks); Shift+Tab still opts in\n\n // ── Quick reasoning toggle (Alt+T): off → low → medium → high → off ── (duplex: the workers' reasoning)\n const REASONING_CYCLE = ['off', 'low', 'medium', 'high'] as const;\n const toggleReasoning = (): string => {\n const cur = String(work.reasoning ?? 'off');\n const next = REASONING_CYCLE[(Math.max(0, REASONING_CYCLE.indexOf(cur as any)) + 1) % REASONING_CYCLE.length];\n work.reasoning = next;\n err(dim(` ~ reasoning → ${next}\\n`));\n return next;\n };\n // Model switching targets the WORKER in duplex (the voice model is a --voice-model startup choice).\n // Recompute providerOptions on switch: they're model-specific (cursor cwd/cursorSession) and the\n // anthropic/openai adapters Object.assign them into the request body — stale ones are a hard 400.\n const setModel = (m: string) => { work.model = m; work.providerOptions = cursorProviderOptions(m, cwd, cfg.mcpServers); if (dx) dx.options.actModel = m; persistModel(cwd, m); err(dim(' model → ' + m + '\\n')); };\n // Per-tier appliers (duplex only) — shared by /model's tier picker and the /voice-model · /think-model shortcuts (DRY).\n const applyReflexModel = (id: string) => { const m = resolveModelOrNewest(id); dx!.options.reflexModel = m; dx!.voice.options.model = m; err(green(` ✓ reflex model → ${m}\\n`)); };\n const applyThinkModel = (id: string) => { const m = resolveModelOrNewest(id); dx!.setThinkModel(m); err(green(` ✓ think model → ${m}\\n`)); };\n // Duplex `/model` with no arg → choose a tier, then its model. Surfaces all three seats in one place\n // (else `/model` silently retargets only the worker). Think can also be disabled here.\n const pickModelByTier = async () => {\n const thinkLabel = dx!.options.thinkModel === false ? 'off' : String(dx!.options.thinkModel);\n const tier = await selectMenu(process.stderr, { title: 'Set model for which tier?', items: [\n { label: 'Reflex (voice)', value: 'reflex', desc: dx!.options.reflexModel },\n { label: 'Act (worker)', value: 'act', desc: work.model },\n { label: 'Think', value: 'think', desc: thinkLabel },\n ] });\n if (!tier) return;\n if (tier === 'think') {\n const sub = await selectMenu(process.stderr, { title: 'Think tier', items: [\n { label: 'Choose a model…', value: '__pick__', desc: thinkLabel === 'off' ? 'currently off' : `current: ${thinkLabel}` },\n { label: 'Disable Think tier', value: '__off__' },\n ] });\n if (!sub) return;\n if (sub === '__off__') { dx!.setThinkModel(false); err(green(' ✓ think tier disabled\\n')); return; }\n const picked = await pickModel(dx!.options.thinkModel === false ? 'anthropic/claude-opus-4-6' : String(dx!.options.thinkModel));\n if (picked) applyThinkModel(picked);\n return;\n }\n const picked = await pickModel(tier === 'reflex' ? dx!.options.reflexModel : work.model);\n if (!picked) return;\n if (tier === 'reflex') applyReflexModel(picked); else setModel(picked);\n };\n // Tool mutations (/mcp add|remove|login) — duplex workers are constructed per spawn from work.tools.\n const addWorkTools = (ts: AgentTool[]) => { if (duplex) work.tools = [...(work.tools ?? []), ...ts]; else agent.addTools(ts); };\n const removeWorkTools = (names: string[]) => { if (duplex) work.tools = (work.tools ?? []).filter((t) => !names.includes(t.name)); else agent.removeTools(names); };\n // `mounted` changed (/mcp add/remove/reconnect/login) → swap the whole MCP tool surface in one go.\n // Raw-vs-deferred is re-decided per rebuild, and the deferred pair's catalog snapshot stays current.\n const remountMcpTools = () => {\n removeWorkTools(mcpToolNames);\n const ts = mcpAgentTools(mounted, { quiet: true });\n mcpToolNames = ts.map((t) => t.name);\n addWorkTools(ts);\n };\n\n const pendingImages: string[] = []; // clipboard images grabbed via /paste, attached to the next message\n const bangContext: string[] = []; // `!cmd` runs + output, folded into the next model turn (CC parity)\n // Grab an image off the OS clipboard → temp file → an `@<abs>` attachment ref. Shared by /paste and Cmd-V.\n const grabClipboardAttachment = (): { display: string; ref: string; path: string } | null => {\n const dir = join(tmpdir(), 'agentx-pasted');\n try { mkdirSync(dir, { recursive: true }); } catch { /* best-effort */ }\n const img = grabClipboardImage(dir, String(Date.now()));\n return img ? { display: 'Image', ref: '@' + img.path, path: img.path } : null;\n };\n // Hard teardown — used by the SIGINT path and the keypress force-quit escalation. Never let the\n // user get trapped: even if a turn's abort() fails to unwind (wedged stream/tool), this exits.\n const forceQuit = (code = 130) => {\n try { voiceIO?.stop(); } catch { /* mic/player may already be down */ }\n try { disposeCursorSessions(); } catch { /* reap warm cursor helpers, best-effort */ }\n void closeMcp(mounted);\n process.exit(code);\n };\n // Ctrl-C: cancel the in-flight turn if one's running; a second Ctrl-C while already cancelling\n // (i.e. the abort didn't unwind) force-quits. No active turn → clean up MCP children and exit.\n process.on('SIGINT', () => {\n if (activeTurn) {\n if (aborting) { err(red('\\n ⏻ force-quit\\n')); forceQuit(); return; } // already cancelling → hard escape\n activeTurn.abort(); voiceIO?.interrupt(); return;\n }\n forceQuit();\n });\n installCancelGuards(mounted);\n // @server:uri prompt mentions → inline the MCP resource body (text contents; non-text noted).\n setMcpMentionResolver(async (ref) => {\n const i = ref.indexOf(':');\n if (i <= 0) return null;\n const m = mounted.find((x) => x.name === ref.slice(0, i));\n if (!m) return null;\n const r = await m.client.readResource(ref.slice(i + 1));\n const parts = Array.isArray(r?.contents) ? r.contents : [];\n const texts = parts.map((c: any) => c?.text ?? (c?.blob ? `[binary ${c.mimeType ?? 'blob'}]` : '')).filter(Boolean);\n return texts.length ? texts.join('\\n') : JSON.stringify(r);\n });\n const store = new SessionStore(cwd);\n let session = startSession(args, store, face, cwd);\n triggerServer.start(session.meta.id); // live-triggerable from now on (re-bound on /resume and /clear)\n setTermTitle(`agentx · ${session.meta.title || cwd.split('/').pop() || 'session'}`);\n // Restore scheduled jobs from the resumed session (if any).\n if ((session.meta as any).scheduledJobs?.length) {\n scheduler.restore((session.meta as any).scheduledJobs);\n err(dim(` ⏰ ${scheduler.size} scheduled job(s) re-armed\\n`));\n }\n\n // File checkpoint/rewind — per TURN normally, per TASK in duplex (frames open via onTaskStart).\n // Disk mode → durable git-backed (whole tree incl. bash edits, survives sessions, CC parity).\n // Virtual modes (sandbox / boddb) → in-VFS stack over the same backing filesystem.\n const checkpoints: Checkpoints = (args.vfs || args.boddb)\n ? new CheckpointStack(agent.options.fs!)\n : new GitCheckpoints({ workTree: cwd, gitDir: join(cwd, '.agent', 'checkpoints.git'), addDirs: args.addDirs, sessionId: session.meta.id });\n const cpHooks = checkpoints.hooks?.();\n if (cpHooks) {\n agent.options.hooks = composeHooks(agent.options.hooks, cpHooks); // main REPL turns: the agent makes the edits\n work.hooks = composeHooks(work.hooks, cpHooks); // duplex: the workers make the edits — their hooks feed the frames\n }\n duplexPersist = () => {\n session.messages = face.transcript;\n session.meta.updated = Date.now();\n if (!session.meta.title) session.meta.title = titleOf(face.transcript);\n try { store.save(session); } catch (e: any) { err(dim(` (session not saved: ${e?.message ?? e})\\n`)); }\n };\n duplexAccount = (data) => { // worker runs never pass through runTurn — account their usage here\n if (!data?.usage?.totalTokens) return;\n session.meta.tokens = (session.meta.tokens ?? 0) + data.usage.totalTokens;\n session.meta.costUsd = (session.meta.costUsd ?? 0) + turnCost(work.model, data.usage);\n if (data.usageEstimated) session.meta.costEstimated = true;\n try { store.save(session); } catch { /* non-fatal */ }\n };\n\n // custom slash commands (same registry the model's SlashCommand tool uses) + skills.\n // Anchored at the FS working dir — in CC-parity disk mode root '/' is the real machine, so\n // .agent lives under the launch dir, not '/' (which would be the real filesystem root).\n const fs = agent.options.fs!; // the CLI always builds the agent with a concrete fs (buildAgent)\n const fsBase = fs.getCwd() === '/' ? '' : fs.getCwd();\n const adot = (sub: string) => `${fsBase}/.agent/${sub}`;\n // Search order lives in dotDirs() — same registry buildAgent's `dots()` uses. Unfiltered here:\n // paths are VFS-space, so disk existence can't be checked (loaders skip missing dirs themselves).\n const adots = (sub: string) => dotDirs(fsBase, sub);\n const cmds: CommandInfo[] = (await loadCommands(fs, adots('commands'))).commands;\n const skills: SkillInfo[] = (await loadSkills(fs, adots('skills'))).skills;\n\n // Mid-session catalog pickup (CC parity): skills/commands created or removed after launch are\n // detected per turn. The memoized system prompt stays frozen (cache-stable) — the delta reaches\n // the model as a <system-reminder> appended to the turn, exactly CC's mechanism. Also syncs the\n // REPL-side `skills`/`cmds` snapshots in place (tab-complete, /skills, /<cmd> dispatch).\n const refreshCatalogs = async (): Promise<string> => {\n const [freshSkills, freshCmds] = await Promise.all([scanSkills(fs, adots('skills')), scanCommands(fs, adots('commands'))]);\n const diff = <T extends { name: string; description: string }>(kind: string, old: T[], fresh: T[]) => {\n const had = new Set(old.map((x) => x.name)), has = new Set(fresh.map((x) => x.name));\n const added = fresh.filter((x) => !had.has(x.name)), removed = old.filter((x) => !has.has(x.name));\n old.splice(0, old.length, ...fresh); // sync the REPL snapshot in place\n return [\n ...added.map((x) => `+ ${kind} **${x.name}** — ${x.description}`),\n ...removed.map((x) => `- ${kind} ${x.name} (removed)`),\n ];\n };\n const lines = [...diff('skill', skills, freshSkills), ...diff('command', cmds, freshCmds)];\n if (!lines.length) return '';\n return `<system-reminder>\\nThe skill/command catalog changed on disk since the session started:\\n${lines.join('\\n')}\\nAdded entries are loadable now via the Skill/SlashCommand tools; removed ones are gone even if still listed in the system prompt.\\n</system-reminder>`;\n };\n\n // persisted input history (best-effort)\n const histPath = join(cwd, '.agent', 'history');\n const history = existsSync(histPath)\n ? readFileSync(histPath, 'utf8').split('\\n').filter(Boolean).reverse().slice(0, 500)\n : [];\n const remember = (line: string) => {\n try { mkdirSync(join(cwd, '.agent'), { recursive: true }); appendFileSync(histPath, line + '\\n'); }\n catch (e) { log.debug('history write failed', e); } // best-effort; never blocks the prompt\n };\n\n // ---- interactive helpers (reuse the selectMenu picker) ----\n const ago = (t: number) => {\n const s = Math.max(0, (Date.now() - t) / 1000);\n return s < 60 ? 'just now' : s < 3600 ? `${Math.floor(s / 60)}m ago` : s < 86400 ? `${Math.floor(s / 3600)}h ago` : `${Math.floor(s / 86400)}d ago`;\n };\n const resumeInto = (data: SessionData) => {\n face.transcript = data.messages; session = data; checkpoints.use?.(data.meta.id); triggerServer.use(data.meta.id);\n const m = data.meta as any;\n goalCondition = m.goalCondition; goalTurns = m.goalTurns ?? 0; goalTokens = m.goalTokens ?? 0; goalLastReason = m.goalLastReason;\n if (m.scheduledJobs?.length) { scheduler.restore(m.scheduledJobs); err(dim(` ⏰ ${scheduler.size} scheduled job(s) re-armed\\n`)); }\n err(dim(` resumed ${data.meta.id} (${data.meta.turns} turns)${data.meta.title ? ' — ' + data.meta.title : ''}\\n`));\n if (goalCondition) err(dim(` ◎ goal active: ${goalCondition} (${goalTurns} turns)\\n`));\n printHistory(data.messages);\n };\n // Double-Esc rewind (CC parity): pick an earlier user message, then choose what to restore —\n // conversation, code, or both. Returns the message text to pre-fill the prompt (when the conversation\n // is rewound) for editing + resend, or undefined (cancelled, or code-only).\n const rewindToMessage = async (): Promise<string | undefined> => {\n const users = face.transcript.map((m, i) => ({ m, i })).filter((x) => x.m.role === 'user');\n if (!users.length) { err(dim(' (no earlier messages to jump back to)\\n')); return undefined; }\n await checkpoints.refresh?.(); // sync size/list with the durable backend before mapping turns → frames\n // Newest-first (CC parity + consistent with /rewind). `value` = position among user turns.\n const items: SelectItem[] = users\n .map(({ m }, p) => {\n const t = contentText(m.content).split('\\n\\n--- @')[0].replace(/\\n+/g, ' ').trim(); // drop inlined @file blocks\n return { label: t.length > 60 ? t.slice(0, 59) + '…' : t || '(empty)', value: String(p) };\n })\n .reverse();\n const pick = await selectMenu(process.stderr, { title: 'Jump back to a message', items });\n if (pick == null) return undefined;\n const p = Number(pick);\n const idx = users[p].i;\n // Map a user-turn position to a checkpoint frame index. Frames may cover only the most recent turns\n // (in-memory cap, or pruned git history), so offset by however many of the oldest turns lack one.\n const frame = p - (users.length - checkpoints.size);\n // Offer what to restore — only surface the code options when this turn still has a file checkpoint.\n // Duplex: conversation-only — frames are per TASK, not per turn, so the turn↔frame mapping is invalid\n // (code rollback is /rewind, /undo, or saying \"undo that\" to the voice).\n let mode = 'convo';\n if (!duplex && frame >= 0 && frame < checkpoints.size) {\n const m = await selectMenu(process.stderr, { title: 'Restore…', items: [\n { label: 'Conversation and code', value: 'both' },\n { label: 'Conversation only', value: 'convo' },\n { label: 'Code only', value: 'code' },\n ] });\n if (m == null) return undefined;\n mode = m;\n }\n const text = contentText(face.transcript[idx].content).split('\\n\\n--- @')[0].trim();\n if (mode === 'code' || mode === 'both') {\n try {\n const { restored, deleted } = await checkpoints.rewindTo(frame);\n err(green(' ⟲ code restored') + dim(` — ${restored} file(s)${deleted ? `, removed ${deleted} new file(s)` : ''}\\n`));\n } catch (e: any) { err(red(` ${e?.message ?? e}\\n`)); }\n }\n if (mode === 'convo' || mode === 'both') {\n face.transcript = face.transcript.slice(0, idx); // rewind the conversation to before that message\n session.messages = face.transcript;\n try { store.save(session); } catch (e) { log.debug('session save after rewind failed', e); }\n err(green(' ⟲ jumped back') + dim(` — ${face.transcript.length} message(s) kept; edit + resend\\n`));\n return text;\n }\n return undefined; // code-only: nothing to pre-fill\n };\n const pickSession = async (global = false) => {\n const list = global ? globalSessionList() : store.list();\n if (!list.length) { err(dim(` (no saved sessions${global ? '' : ' in this project'} yet)\\n`)); return; }\n const items: SelectItem[] = list.slice(0, 50).map((m) => {\n const where = global && m.cwd !== cwd ? ` · ${m.cwd.split('/').pop()}` : '';\n return { label: `${m.id} ${m.title || '(untitled)'}`, value: m.id, desc: `${ago(m.updated)} · ${m.turns} turn${m.turns === 1 ? '' : 's'}${where}` };\n });\n const id = await selectMenu(process.stderr, { title: global ? 'Resume a session (all projects)' : 'Resume a session', items, current: session.meta.id });\n if (!id) return;\n const data = store.load(id) ?? globalSessionLoad(id);\n if (data) resumeInto(data); else err(red(' no such session\\n'));\n };\n const announcedTasks = new Set<string>(); // task ids whose ◔ in-flow marker already printed (once each)\n // One seam for every interactive turn: duplex dispatches through dx.send (mutex + delegation) and\n // skips per-turn checkpoints (frames are per task, opened by the engine's onTaskStart).\n const turn = async (task: string) => {\n // Prepend any `!cmd` output accumulated since the last turn (CC: bash mode adds to context).\n if (bangContext.length) { task = `${bangContext.join('\\n\\n')}\\n\\n${task}`; bangContext.length = 0; }\n const delta = await refreshCatalogs().catch((e) => { log.debug('catalog refresh failed', e); return ''; });\n if (delta) { err(dim(' ⟳ skill/command catalog changed — delta attached to this turn\\n')); task += '\\n\\n' + delta; }\n const r = await runTurn(face, store, session, task, duplex ? undefined : checkpoints, cwd, sendVia);\n if (voiceIO) { voiceEchoEnd(); editorRef?.resume(); } // append-only echo: close its line, then repaint below\n voiceIO?.endSpeech(); // close the spoken turn's TTS context (idempotent; audio drains out)\n // Duplex: a turn can END while work continues — mark it IN THE FLOW once per task (the \"✓ done\"\n // footer reads as \"turn over\"); after that the stacked ticking footer line carries the signal.\n if (dx) {\n const fresh = [...dx.tasks.values()].filter((t) => t.status === 'running' && !announcedTasks.has(t.id));\n fresh.forEach((t) => announcedTasks.add(t.id));\n if (fresh.length) err('\\r\\x1b[0J' + cyan(` ◔ ${fresh.length === 1 ? `task ${fresh[0].id} (${fresh[0].label})` : `${fresh.length} tasks`} working in the background`) + dim(' — the result will appear here; keep chatting meanwhile\\n'));\n }\n return r;\n };\n scheduleTurn = turn; // bind for the scheduler's fire callback\n const runSkill = async (sk: SkillInfo, extra = '') => {\n // expandEntry keeps the whole SKILL.md (frontmatter is part of the instructions) but fills\n // $ARGUMENTS/$1… and embeds @file refs — same expansion commands get (merged-namespace parity).\n try { await turn(await expandEntry(fs, sk.path, extra)); }\n catch (e: any) { err(red(` couldn't load skill ${sk.name}: ${e?.message ?? e}\\n`)); }\n };\n const runCommand = async (c: CommandInfo, extra = '') => { await turn(await expandCommand(fs, c, extra)); };\n const pickAndRun = async (kind: 'skill' | 'command') => {\n const pool = kind === 'skill' ? skills : cmds;\n if (!pool.length) { err(dim(` (none — add ./.agent/${kind === 'skill' ? 'skills/<name>/SKILL.md' : 'commands/<name>.md'})\\n`)); return; }\n const items: SelectItem[] = pool.map((p) => ({ label: p.name, value: p.name, desc: (p as { description?: string }).description }));\n const name = await selectMenu(process.stderr, { title: `Run a ${kind}`, items });\n if (!name) return;\n if (kind === 'skill') await runSkill(skills.find((s) => s.name === name)!);\n else await runCommand(cmds.find((c) => c.name === name)!);\n };\n\n const pickModel = async (current: string): Promise<string | null> => {\n const all = listModels();\n // group: provider → model line (by displayName prefix, e.g. \"Claude Opus\") → versions newest-first\n const byProvider = new Map<string, Map<string, { id: string; date: string; name: string }[]>>();\n for (const id of all) {\n const provider = getProviderFromModel(id) ?? 'other';\n const info = getModelInfo(id);\n const name = info?.displayName ?? id.slice(provider.length + 1);\n const line = name.replace(/\\s+\\d[\\d.]*$/, '') || name;\n if (!byProvider.has(provider)) byProvider.set(provider, new Map());\n const lines = byProvider.get(provider)!;\n if (!lines.has(line)) lines.set(line, []);\n lines.get(line)!.push({ id, date: info?.releaseDate ?? '', name });\n }\n const providerItems: SelectItem[] = [];\n for (const [provider, lines] of Array.from(byProvider.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {\n const lineItems: SelectItem[] = [];\n for (const [, versions] of Array.from(lines.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {\n versions.sort((a, b) => b.date.localeCompare(a.date));\n const head = versions[0];\n if (versions.length === 1) {\n lineItems.push({ label: head.name, value: head.id });\n } else {\n const children = versions.slice(1).map((v) => ({ label: v.id.split('/').pop()!, value: v.id, desc: v.date || undefined }));\n lineItems.push({ label: head.name, value: head.id, desc: `+${children.length} older`, children });\n }\n }\n const dateOf = (it: SelectItem) => getModelInfo(it.value)?.releaseDate ?? '0';\n lineItems.sort((a, b) => dateOf(b).localeCompare(dateOf(a)));\n const total = Array.from(lines.values()).reduce((n, v) => n + v.length, 0);\n providerItems.push({ label: provider, value: '__provider__', desc: `${total} models`, children: lineItems });\n }\n const picked = await selectMenu(process.stderr, { title: `Select a model · current: ${current}`, items: providerItems, current, filterable: true });\n return picked && !picked.startsWith('__') ? picked : null;\n };\n\n let goalCondition: string | undefined = (session.meta as any).goalCondition;\n let goalTurns: number = (session.meta as any).goalTurns ?? 0;\n let goalTokens: number = (session.meta as any).goalTokens ?? 0;\n let goalLastReason: string | undefined = (session.meta as any).goalLastReason;\n const GOAL_MAX_TURNS = 50;\n const persistGoal = () => {\n const m = session.meta as any;\n m.goalCondition = goalCondition; m.goalTurns = goalTurns; m.goalTokens = goalTokens; m.goalLastReason = goalLastReason;\n };\n\n // ---- /goal: autonomous loop with a halting condition ----\n const goalLoop = async () => {\n while (goalCondition && !aborting && !exitRequested && goalTurns < GOAL_MAX_TURNS) {\n const result = await evaluateGoal(ai, goalCondition, face.transcript, err);\n goalLastReason = result.reason;\n if (result.met) {\n err(green(` ✓ goal met: ${result.reason}\\n`));\n goalCondition = undefined; goalLastReason = undefined;\n persistGoal();\n return;\n }\n err(dim(` ◎ not yet (${result.reason}) — turn ${goalTurns + 1}\\n`));\n aborting = false;\n const tokensBefore = session.meta.tokens ?? 0;\n await turn(`Continue working toward the goal: ${goalCondition}`);\n goalTokens += (session.meta.tokens ?? 0) - tokensBefore;\n goalTurns++;\n persistGoal();\n if (exitRequested) return;\n }\n if (goalTurns >= GOAL_MAX_TURNS) {\n err(yellow(` ⚠ goal reached ${GOAL_MAX_TURNS} turns — pausing. /goal to check status, /goal clear to cancel\\n`));\n }\n };\n\n // ---- slash builtins: name → handler. Returns true to exit the REPL. ----\n const builtins: Record<string, { desc: string; run: (a: string[]) => boolean | void | Promise<boolean | void> }> = {\n help: { desc: 'show this help', run: () => { err(HELP + '\\n'); } },\n version: {\n desc: 'show CLI version + runtime',\n run: () => {\n const rt = (process.versions as any).bun ? `bun ${(process.versions as any).bun}` : `node ${process.versions.node}`;\n err(` ${bold('agentx')} ${cyan('v' + VERSION)}${dim(` · ${duplex ? `reflex ${dx!.options.reflexModel} · act ${work.model}${dx!.options.thinkModel !== false ? ` · think ${dx!.options.thinkModel}` : ''}` : work.model} · ${rt}`)}\\n`);\n },\n },\n tools: {\n desc: 'list available tools',\n run: () => {\n if (duplex) err(dim(' voice: ' + face.options.tools.map((t) => t.name).join(', ') + '\\n worker: ' + (work.tools ?? []).map((t) => t.name).join(', ') + '\\n'));\n else err(dim(' ' + agent.toolNames.join(', ') + '\\n'));\n },\n },\n permissions: {\n desc: 'show the active permission rules + default posture',\n run: () => {\n const pol = work.permissions;\n const rules = pol?.options.rules ?? [];\n if (!rules.length) err(dim(' (no rules — default: ' + (pol?.options.default ?? 'allow') + ')\\n'));\n else { err(dim(' default: ' + (pol!.options.default) + '\\n')); for (const r of rules) err(dim(' · ' + describeRule(r) + '\\n')); }\n err(dim(' add persisted rules under .agent/config → permissions: { allow|ask|deny: [\"Tool(glob)\"] }\\n'));\n },\n },\n status: {\n desc: 'session status — model, dir, fs-mode, permissions, tools, usage',\n run: () => {\n const mode = args.vfs ? 'sandbox (VFS — disk untouched)' : args.boddb ? `boddb (database workspace at ${args.boddb} — disk untouched)` : args.shell ? 'disk + real /bin/sh' : 'disk (full real FS, like Claude Code)';\n const pol = work.permissions;\n const perm = !pol ? 'allow all (unattended)' : `${pol.options.rules.length} rule(s), default ${pol.options.default}`;\n const model = duplex ? `reflex ${dx!.options.reflexModel} · act ${work.model}${dx!.options.thinkModel !== false ? ` · think ${dx!.options.thinkModel}` : ''}` : work.model;\n err(formatStatus({ model, cwd, mode, tools: (duplex ? work.tools ?? [] : agent.options.tools).map((t) => t.name), permissions: perm, turns: session.meta.turns, tokens: session.meta.tokens ?? 0, sessionId: session.meta.id, estimated: session.meta.costEstimated ?? false }));\n if (duplex && dx!.tasks.size) err(dim(` tasks: ${[...dx!.tasks.values()].map((t) => `${t.id}:${t.status}`).join(' ')}\\n`));\n },\n },\n cost: {\n desc: 'cumulative cost + token usage for this session',\n run: () => {\n const t = session.meta.tokens ?? 0, usd = session.meta.costUsd ?? 0;\n const priced = getModelInfo(work.model)?.pricing;\n const est = session.meta.costEstimated ?? false; // false once every turn reported exact usage\n const m = est ? '~' : '';\n const note = priced ? (est ? ' (estimated — some turns streamed without usage)' : ' (exact — provider-reported usage)') : ` (no pricing for ${work.model})`;\n err(dim(` ${usd > 0 ? m + fmtUsd(usd) + ' · ' : ''}${m}${(t / 1000).toFixed(1)}k tokens across ${session.meta.turns} turn(s)${note}\\n`));\n },\n },\n context: {\n desc: 'context-window usage (messages + estimated tokens)',\n run: () => {\n const est = estimateTranscriptTokens(face.transcript);\n const cap = face.options.maxTokens || 200_000;\n err(dim(` ${face.transcript.length} message(s) · ~${(est / 1000).toFixed(1)}k tokens (~${Math.round((est / cap) * 100)}% of ${Math.round(cap / 1000)}k budget)\\n`));\n },\n },\n transcript: {\n desc: 'full session transcript incl. complete tool results — /transcript [n] (last n turns), paged via less',\n run: async (a) => {\n const n = a[0] ? Math.max(1, Number(a[0]) || 1) : undefined;\n const text = formatTranscriptFull(face.transcript, { lastTurns: n });\n // Page through `less -R` on a TTY (ANSI-aware, q to exit); print directly when piped/short.\n if (tty && text.split('\\n').length > (process.stderr.rows ?? 40)) {\n const wasRaw = process.stdin.isTTY && process.stdin.isRaw;\n if (wasRaw) process.stdin.setRawMode(false);\n try {\n const { spawnSync } = await import('node:child_process');\n const r = spawnSync('less', ['-R'], { input: text, stdio: ['pipe', 'inherit', 'inherit'] });\n if (r.error) err(text); // no less on PATH → plain dump\n } finally { if (wasRaw) process.stdin.setRawMode(true); }\n } else err(text);\n },\n },\n doctor: {\n desc: 'environment sanity check — keys, config, sessions, memory, MCP, model pricing',\n run: async () => {\n const ok = (s: string) => err(green(' ✓ ') + s + '\\n');\n const warn = (s: string) => err(yellow(' ⚠ ') + s + '\\n');\n const bad = (s: string) => err(red(' ✗ ') + s + '\\n');\n err(dim(` agentx v${VERSION} · bun ${process.versions.bun ?? '?'} · ${process.platform}\\n`));\n // provider keys\n const keys = ['ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'GOOGLE_API_KEY', 'GROQ_API_KEY'].filter((k) => process.env[k]);\n keys.length ? ok(`provider keys: ${keys.join(', ')}`) : bad('no provider keys set (ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_API_KEY / GROQ_API_KEY)');\n // model + pricing\n const info = getModelInfo(work.model);\n info?.pricing ? ok(`model ${work.model} — priced (${info.pricing.inputCostPer1K}/${info.pricing.outputCostPer1K} per 1k in/out)`)\n : warn(`model ${work.model} — no pricing in the catalog (costs will show ~$0; verify the id)`);\n // config files\n const cfgFiles = ['ts', 'js', 'json'].flatMap((e) => [`${cwd}/.agent/config.${e}`, `${homedir()}/.agent/config.${e}`]).filter((p) => existsSync(p));\n cfgFiles.length ? ok(`config: ${cfgFiles.join(', ')}`) : warn('no .agent/config.* found (project or ~) — running on defaults');\n // session store writable\n try {\n const probe = `${cwd}/.agent/sessions/.doctor-probe`;\n mkdirSync(`${cwd}/.agent/sessions`, { recursive: true }); writeFileSync(probe, 'ok'); unlinkSync(probe);\n ok(`session store writable (${cwd}/.agent/sessions)`);\n } catch (e: any) { bad(`session store not writable: ${e?.message ?? e}`); }\n // memory\n const memDir = primaryMemDir(face.options.memoryDir, adot('memory'));\n try { const idx = await face.options.fs!.readFile(`${memDir}/MEMORY.md`); ok(`memory: ${memDir} (${idx.split('\\n').filter((l) => l.startsWith('- ')).length} pointer(s))`); }\n catch { warn(`memory: ${memDir} — no MEMORY.md yet (save one with #<note>)`); }\n // MCP: configured vs mounted\n const conf = Object.keys(cfg.mcpServers ?? {});\n const up = new Set(mounted.map((m) => m.name));\n const down = conf.filter((n) => !up.has(n) && !cfg.mcpServers?.[n]?.disabled);\n if (!conf.length && !mounted.length) ok('mcp: none configured');\n else if (down.length) bad(`mcp: ${down.length} configured server(s) not mounted: ${down.join(', ')} (try /mcp reconnect <name>)`);\n else ok(`mcp: ${mounted.length} server(s) mounted${conf.length ? ` (${conf.length} configured)` : ''}`);\n // fs / checkpoints / hooks\n ok(`fs: ${args.vfs ? 'sandbox (VFS)' : args.boddb ? `boddb (${args.boddb})` : 'disk'} · checkpoints: ${args.vfs || args.boddb ? 'in-memory/db' : 'git-backed'}`);\n const hookCount = Object.values(cfg.hooks ?? {}).reduce((n: number, v: any) => n + (Array.isArray(v) ? v.length : 0), 0);\n if (hookCount) ok(`hooks: ${hookCount} configured`);\n },\n },\n reload: {\n desc: 'rescan skills/commands dirs and rebuild the system prompt (one cache miss) — picks up entries created mid-session',\n run: async () => {\n await refreshCatalogs().catch((e) => { log.debug('catalog refresh failed', e); });\n face.reprepare(); // next send rebuilds prompt + tools (incl. Skill/SlashCommand catalogs)\n err(green(` ✓ reloaded — ${skills.length} skill(s), ${cmds.length} command(s); system prompt rebuilds on next message\\n`));\n },\n },\n cwd: {\n desc: 'print the working directory (to switch, relaunch with -C <dir>)',\n run: (a) => {\n if (a[0]) { err(yellow(` mid-session dir change isn't supported (fs + MCP are bound at startup) — relaunch:\\n`) + dim(` agentx -C ${a[0]}\\n`)); return; }\n err(dim(' ' + cwd + '\\n'));\n },\n },\n sandbox: {\n desc: 'show filesystem access mode (disk = full real FS like Claude Code · sandbox = in-memory copy); to switch, relaunch with/without --sandbox',\n run: () => {\n const access = args.boddb\n ? `boddb — files live in a database at ${args.boddb} (persists across runs), the real disk is never modified`\n : args.vfs\n ? 'sandbox — in-memory copy of cwd, the real disk is never modified'\n : 'disk — full real filesystem (root / = machine root), like Claude Code';\n const virtual = args.vfs || !!args.boddb;\n err(dim(` fs access: ${access}\\n`));\n err(dim(` checkpoints: ${virtual ? (args.boddb ? 'in-database (persists)' : 'in-memory (per session)') : 'durable git-backed — whole tree incl. bash edits, survives sessions'} · /rewind /undo\\n`));\n err(yellow(` switching mid-session isn't supported (the filesystem is bound at startup) — relaunch:\\n`) + dim(` agentx ${virtual ? '' : '--sandbox '}…\\n`));\n },\n },\n model: {\n desc: 'switch model — /model <id> (duplex: the worker), or /model alone for a picker (duplex: pick a tier first)',\n run: async (a) => {\n if (a[0]) { setModel(a[0]); return; } // arg form always targets the worker (scripting/muscle-memory)\n if (duplex) { await pickModelByTier(); return; } // no-arg in duplex → reflex/act/think submenu\n const picked = await pickModel(work.model);\n if (picked) setModel(picked);\n else err(dim(' ' + work.model + '\\n'));\n },\n },\n ...(duplex ? { workers: {\n desc: 'duplex worker chrome — /workers <full|minimal>: per-step ⚙ tool activity vs task events only',\n run: async (a: string[]) => {\n if (a[0] === 'full' || a[0] === 'minimal') { workerChrome = a[0]; err(green(` ✓ worker chrome → ${a[0]}\\n`)); return; }\n err(dim(` worker chrome: ${workerChrome} (use /workers full|minimal)\\n`));\n },\n }, voice: {\n desc: 'toggle live voice I/O on/off mid-session (or say \"voice off\"; needs SONIOX/CARTESIA keys + a TTY)',\n run: async () => {\n if (!toggleVoice) { err(dim(' (voice needs --duplex on a TTY)\\n')); return; }\n await toggleVoice();\n },\n }, 'voice-model': {\n desc: 'switch the reflex (voice) model — /voice-model <id>, or alone for a picker',\n run: async (a: string[]) => {\n if (a[0]) { applyReflexModel(a[0]); return; }\n const picked = await pickModel(dx!.options.reflexModel);\n if (picked) applyReflexModel(picked);\n else err(dim(` reflex ${dx!.options.reflexModel}\\n`));\n },\n }, 'think-model': {\n desc: 'switch the think (premium) model, or /think-model off to disable',\n run: async (a: string[]) => {\n if (a[0] === 'off' || a[0] === 'false') {\n dx!.setThinkModel(false); // live: removes the Think tool from the voice agent\n err(green(` ✓ think tier disabled\\n`));\n return;\n }\n if (a[0]) { applyThinkModel(a[0]); return; }\n const current = dx!.options.thinkModel === false ? undefined : dx!.options.thinkModel;\n const picked = await pickModel(current ?? 'anthropic/claude-opus-4-6');\n if (picked) applyThinkModel(picked);\n else err(dim(` think ${dx!.options.thinkModel === false ? 'off' : dx!.options.thinkModel}\\n`));\n },\n }, act: {\n desc: 'spawn a standard worker — /act <brief>',\n run: async (a: string[]) => {\n if (!a.length) { err(dim(' usage: /act <what to do>\\n')); return; }\n const id = await dx!.dispatch(a.join(' '), 'act');\n err(dim(` → task ${id} started\\n`));\n },\n }, think: {\n desc: 'spawn a deep-reasoning worker — /think <question>',\n run: async (a: string[]) => {\n if (!a.length) { err(dim(' usage: /think <what to reason about>\\n')); return; }\n const off = dx!.options.thinkModel === false; // dispatch silently downgrades — tell the user\n const id = await dx!.dispatch(a.join(' '), 'think');\n err(dim(` → task ${id} ${off ? '(think tier off — running as act)' : '(think)'} started\\n`));\n },\n }, tasks: {\n desc: 'background tasks — /tasks [cancel <id>], or alone for a picker (↵ inspects output; running tasks can be cancelled)',\n run: async (a: string[]) => {\n const all = [...dx!.tasks.values()];\n if (!all.length) { err(dim(' no background tasks\\n')); return; }\n if (a[0]?.toLowerCase() === 'cancel') {\n if (!a[1]) { err(yellow(' usage: /tasks cancel <id>\\n')); return; }\n err(dim(` ${dx!.cancelTask(a[1])}\\n`)); return;\n }\n const mark = (s: string) => (s === 'running' ? cyan('◔ running') : s === 'done' ? green('✓ done') : s === 'cancelled' ? yellow('⊘ cancelled') : red(`✗ ${s}`));\n const inspect = (t: TaskRecord) => {\n err(` ${t.id} ${mark(t.status)} ${dim(t.label)}\\n`);\n for (const l of t.tail.slice(-20)) err(dim(` ${l}\\n`));\n if (t.result) err(dim(` ⦿ ${t.result.split('\\n')[0].slice(0, 160)}\\n`));\n if (!t.tail.length && !t.result) err(dim(' (no activity yet)\\n'));\n };\n if (!process.stderr.isTTY || !process.stdin.isTTY) { // piped: no menu — plain dump (cancel via /tasks cancel <id>)\n for (const t of all) inspect(t);\n return;\n }\n const items: SelectItem[] = all.map((t) => ({ label: `${t.id} ${t.label.slice(0, 60)}`, value: t.id, desc: mark(t.status) + ' · ↵ inspect' }));\n const id = await selectMenu(process.stderr, { title: 'Background tasks · ↵ inspect · esc close', items });\n if (!id) return;\n const t = dx!.tasks.get(String(id))!;\n inspect(t);\n if (t.status === 'running') {\n const v = await selectMenu(process.stderr, { title: `Cancel ${t.id}?`, items: [{ label: 'Keep running', value: 'keep' }, { label: 'Cancel the task', value: 'cancel' }], current: 'keep' });\n if (v === 'cancel') err(dim(` ${dx!.cancelTask(t.id)}\\n`));\n }\n },\n } } : {}),\n reasoning: {\n desc: 'extended thinking — /reasoning <off|low|medium|high|tokens>, or alone for an interactive picker (duplex: the workers\\')',\n run: async (a) => {\n const current = String(work.reasoning ?? 'off');\n let next: ReasoningEffort;\n if (a[0]) {\n try { next = parseReasoning(a[0]); } catch (e: any) { err(yellow(' ' + (e?.message ?? e) + '\\n')); return; }\n } else {\n const items: SelectItem[] = [\n { label: 'off', value: 'off', desc: 'no extended thinking' },\n { label: 'low', value: 'low', desc: 'minimal reasoning (~2k tokens)' },\n { label: 'medium', value: 'medium', desc: 'balanced (~8k tokens)' },\n { label: 'high', value: 'high', desc: 'maximal reasoning (~24k tokens)' },\n ];\n const picked = await selectMenu(process.stderr, { title: `Reasoning effort · current: ${current}`, items, current });\n if (!picked) { err(dim(' ' + current + '\\n')); return; }\n next = picked as ReasoningEffort;\n }\n work.reasoning = next;\n if (next !== 'off' && getModelInfo(work.model)?.reasoning === false)\n err(yellow(` note: ${work.model} has no reasoning capability — setting may be ignored\\n`));\n err(dim(' reasoning → ' + next + '\\n'));\n },\n },\n config: {\n desc: 'view/change settings — model, reasoning, permission posture, streaming, editor mode',\n run: async () => {\n for (;;) {\n const items: SelectItem[] = [\n { label: 'model', value: 'model', desc: work.model },\n { label: 'reasoning', value: 'reasoning', desc: String(work.reasoning ?? 'off') },\n { label: 'permission posture', value: 'posture', desc: postureLabel() + ' (Shift+Tab)' },\n // streaming is the voice's lifeblood in duplex (always on) — only a normal-mode knob\n ...(duplex ? [] : [{ label: 'streaming', value: 'stream', desc: agent.options.stream ? 'on' : 'off' }]),\n { label: 'editor mode', value: 'editor', desc: cfg.editorMode === 'vim' ? 'vim' : 'normal' },\n ];\n const pick = await selectMenu(process.stderr, { title: 'Settings · ↵ change · esc close', items });\n if (!pick) return;\n if (pick === 'model') { const m = await pickModel(work.model); if (m) setModel(m); }\n else if (pick === 'reasoning') { await builtins.reasoning.run([]); persistSetting(cwd, 'reasoning', work.reasoning ?? 'off'); }\n else if (pick === 'posture') { cyclePosture(); persistSetting(cwd, 'permissionMode', posture); }\n else if (pick === 'stream') { agent.options.stream = !agent.options.stream; persistSetting(cwd, 'stream', agent.options.stream); err(dim(' streaming → ' + (agent.options.stream ? 'on' : 'off') + '\\n')); }\n else if (pick === 'editor') { cfg.editorMode = cfg.editorMode === 'vim' ? 'normal' : 'vim'; persistSetting(cwd, 'editorMode', cfg.editorMode); err(dim(' editor → ' + cfg.editorMode + '\\n')); }\n }\n },\n },\n rename: {\n desc: 'rename the current session — /rename <title>',\n run: (a) => {\n const t = a.join(' ').trim();\n if (!t) { err(dim(' title: ' + (session.meta.title || '(none)') + '\\n')); return; }\n session.meta.title = t;\n try { store.save(session); } catch { /* non-fatal */ }\n setTermTitle(`agentx · ${t}`);\n err(dim(' renamed → ' + t + '\\n'));\n },\n },\n compact: {\n desc: 'summarize older context to free up the window — /compact [what to preserve]',\n run: (a) => {\n const focus = a.join(' ').trim() || undefined;\n const n = face.compactNow(12, focus);\n session.messages = face.transcript; try { store.save(session); } catch { /* ignore */ }\n err(dim(` compacted — folded ${n} message(s)${focus && n ? ` (preserving: ${focus})` : ''}\\n`));\n },\n },\n copy: {\n desc: 'copy the last reply to the clipboard — /copy code = last code block only',\n run: (a) => {\n const last = [...face.transcript].reverse().find((m) => m.role === 'assistant' && contentText(m.content).trim());\n if (!last) { err(dim(' (nothing to copy yet)\\n')); return; }\n let text = contentText(last.content).trim();\n if (a[0] === 'code') {\n const fences = [...text.matchAll(/```[^\\n]*\\n([\\s\\S]*?)```/g)];\n if (!fences.length) { err(dim(' (no code block in the last reply)\\n')); return; }\n text = fences[fences.length - 1][1].trimEnd();\n }\n err(dim(copyTextToClipboard(text) ? ` ✓ copied ${text.length} chars\\n` : ' no clipboard tool found (pbcopy/wl-copy/xclip)\\n'));\n },\n },\n diff: {\n desc: 'show all file changes this session (oldest checkpoint → now)',\n run: async () => {\n if (!checkpoints.diff) { err(dim(' (diff not supported by this checkpoint backend)\\n')); return; }\n await checkpoints.refresh?.();\n if (!checkpoints.size) { err(dim(' (no checkpoints yet — make a turn first)\\n')); return; }\n const d = (await checkpoints.diff()).trim();\n if (!d) { err(dim(' (no file changes this session)\\n')); return; }\n err(d.split('\\n').map((l) => l.startsWith('+') && !l.startsWith('+++') ? green(l) : l.startsWith('-') && !l.startsWith('---') ? red(l) : dim(l)).join('\\n') + '\\n');\n },\n },\n memory: {\n desc: 'open the memory index in $EDITOR (.agent/memory/MEMORY.md)',\n run: async () => {\n const dir = primaryMemDir(face.options.memoryDir, adot('memory'));\n const idx = `${dir}/MEMORY.md`;\n const fs = face.options.fs!;\n if (args.vfs || args.boddb) { // virtual fs: $EDITOR can't see it — print instead\n try { err(dim(await fs.readFile(idx)) + '\\n'); } catch { err(dim(' (no memory yet — save one with `#<note>`)\\n')); }\n return;\n }\n try { await fs.readFile(idx); } catch { try { await mkdirp(fs, dir); await fs.writeFile(idx, '# Memory\\n\\n'); } catch (e: any) { err(red(` can't create ${idx}: ${e?.message ?? e}\\n`)); return; } }\n const ed = process.env.VISUAL || process.env.EDITOR || 'vi';\n const wasRaw = process.stdin.isTTY && process.stdin.isRaw;\n if (wasRaw) process.stdin.setRawMode(false);\n try {\n const { spawnSync } = await import('node:child_process');\n spawnSync(ed, [idx], { stdio: 'inherit' });\n } finally { if (wasRaw) process.stdin.setRawMode(true); }\n err(dim(` ✎ ${idx}\\n`));\n },\n },\n rewind: {\n desc: 'undo file edits back to before an earlier turn (interactive)',\n run: async () => {\n await checkpoints.refresh?.();\n const list = checkpoints.list();\n if (!list.length) { err(dim(' (no checkpoints yet — edits are captured per turn)\\n')); return; }\n const items: SelectItem[] = list.map((c) => ({ label: c.label, value: String(c.index), desc: ago(c.at) + (c.files ? ` · ${c.files} file${c.files === 1 ? '' : 's'}` : '') }));\n const pick = await selectMenu(process.stderr, { title: 'Rewind to before…', items });\n if (pick == null) return;\n try {\n const { restored, deleted } = await checkpoints.rewindTo(Number(pick));\n err(green(` ⟲ rewound`) + dim(` — restored ${restored} file(s)${deleted ? `, removed ${deleted} new file(s)` : ''}\\n`) + dim(' (files only; the conversation is unchanged)\\n'));\n } catch (e: any) { err(red(` ${e?.message ?? e}\\n`)); }\n },\n },\n undo: {\n desc: 'undo the file edits from the most recent turn',\n run: async () => {\n await checkpoints.refresh?.();\n if (!checkpoints.size) { err(dim(' (nothing to undo)\\n')); return; }\n const { restored, deleted } = await checkpoints.rewindTo(checkpoints.size - 1);\n err(green(` ⟲ undid last turn`) + dim(` — restored ${restored} file(s)${deleted ? `, removed ${deleted} new file(s)` : ''}\\n`));\n },\n },\n clear: {\n desc: 'start a fresh conversation (and clear the screen)',\n run: () => { face.transcript = []; bangContext.length = 0; session = startSession({ ...args, cont: false, resume: undefined }, store, face, cwd); triggerServer.use(session.meta.id); err('\\x1bc'); },\n },\n sessions: {\n desc: 'pick a saved session to resume — /sessions [all] (all = across all projects)',\n run: (a) => pickSession(a[0] === 'all'),\n },\n resume: {\n desc: 'resume a session — /resume <id>, or /resume alone to pick from a list',\n run: async (a) => {\n if (!a[0]) { await pickSession(); return; }\n const data = store.load(a[0]) ?? globalSessionLoad(a[0]);\n if (data) resumeInto(data); else err(red(` no such session\\n`));\n },\n },\n agents: {\n desc: 'list subagent types (./.agent/agents) — /agents new <name> scaffolds one',\n run: async (a) => {\n const fs = face.options.fs!;\n if (a[0] === 'new') {\n let name = a[1];\n if (!name) {\n const io = createInterface({ input: keyInput, output: process.stderr });\n try { name = (await io.question(yellow(' agent name: '))).trim(); } finally { io.close(); }\n }\n name = (name ?? '').replace(/[^A-Za-z0-9_-]/g, '-').replace(/^-+|-+$/g, '');\n if (!name) { err(yellow(' usage: /agents new <name>\\n')); return; }\n const dir = adot('agents'); const p = `${dir}/${name}.md`;\n if (await fs.exists(p)) { err(yellow(` ${p} already exists\\n`)); return; }\n await mkdirp(fs, dir);\n await fs.writeFile(p, [\n '---',\n `description: What \"${name}\" is for — the Task tool picks agents by this line`,\n '# model: anthropic/claude-haiku-4-5 # optional per-agent model override',\n '# tools: Read, Grep, Glob # optional tool allowlist (omit = all tools)',\n '---',\n '',\n `You are the \"${name}\" subagent.`,\n '',\n 'Describe the persona, scope, and output contract here — this body becomes the',\n \"child agent's system prompt when a Task is delegated with agentType: \\\"\" + name + '\".',\n '',\n ].join('\\n'));\n err(green(` ✓ ${p}`) + dim(` — used via Task(agentType:\"${name}\")${args.subagents ? '' : ' (enable with --subagents)'}\\n`));\n return;\n }\n const seen = new Map<string, { def: AgentDef; from: string }>();\n for (const d of adots('agents')) {\n try { for (const def of (await loadAgents(fs, d)).agents) if (!seen.has(def.name)) seen.set(def.name, { def, from: d }); }\n catch (e) { log.debug(`loadAgents(${d}) failed`, e); }\n }\n if (!seen.size) { err(dim(' (no subagents defined — scaffold one with /agents new <name>)\\n')); return; }\n for (const { def, from } of seen.values()) {\n const extras = [def.model, def.tools?.length ? `tools: ${def.tools.join(',')}` : ''].filter(Boolean).join(' · ');\n err(` ${cyan(def.name)} ${dim(`— ${def.description || '(no description)'}${extras ? ` (${extras})` : ''} · ${from}`)}\\n`);\n }\n err(dim(` delegated via the Task tool (agentType)${args.subagents ? '' : ' — enable with --subagents'} · /agents new <name> to scaffold\\n`));\n },\n },\n commands: { desc: 'pick a custom slash command to run (./.agent/commands)', run: () => pickAndRun('command') },\n skills: { desc: 'pick a skill to run (./.agent/skills)', run: () => pickAndRun('skill') },\n mcp: {\n desc: 'manage MCP servers — /mcp [add <name> <cmd|url>] [login <name>] [reconnect <name>] [remove <name>] [tools [name]] [resources [name]]',\n run: async (a) => {\n const sub = a[0]?.toLowerCase();\n if (sub === 'login') {\n const name = a[1];\n const target = name ? cfg.mcpServers?.[name] : undefined;\n if (!name || !target?.url) { err(yellow(' usage: /mcp login <name> (name must be a configured http server)\\n')); return; }\n try {\n err(dim(` opening browser to authorize \"${name}\"…\\n`));\n await oauth.register(target.url);\n err(green(` ✓ authorized \"${name}\"`) + dim(' — remounting with the new token\\n'));\n // remount this server with the freshly-minted bearer token\n const idx = mounted.findIndex((m) => m.name === name);\n if (idx >= 0) await mounted.splice(idx, 1)[0].client.close().catch(() => {});\n const m = await mountMcpServer(name, { ...target, bearerToken: await oauth.tokenFor(target.url) });\n mounted.push(m); remountMcpTools();\n err(green(` ✓ ${m.name}`) + dim(` — ${m.tools.length} tool(s)\\n`));\n } catch (e: any) { err(red(` login failed: ${e?.message ?? e}\\n`)); }\n return;\n }\n if (sub === 'add') {\n const name = a[1]; const target = a.slice(2).join(' ');\n if (!name || !target) { err(yellow(' usage: /mcp add <name> <command ...> | <url>\\n')); return; }\n if (mounted.find((m) => m.name === name)) { err(yellow(` MCP \"${name}\" already mounted\\n`)); return; }\n const cfg: McpServerConfig = target.startsWith('http://') || target.startsWith('https://') ? { url: target } : { command: target.split(' ')[0], args: target.split(' ').slice(1) };\n try {\n const m = await mountMcpServer(name, cfg);\n mounted.push(m);\n remountMcpTools();\n err(green(` ✓ ${m.name}`) + dim(` — ${m.tools.length} tool(s)${m.serverInfo?.name ? ` from ${m.serverInfo.name}` : ''}\\n`));\n } catch (e: any) { err(red(` failed to mount \"${name}\": ${e?.message ?? e}\\n`)); }\n return;\n }\n if (sub === 'reconnect') {\n const name = a[1];\n if (!name) { err(yellow(' usage: /mcp reconnect <name>\\n')); return; }\n const idx = mounted.findIndex((m) => m.name === name);\n const conf = idx >= 0 ? mounted[idx].config : cfg.mcpServers?.[name]; // mounted config survives ad-hoc /mcp add\n if (!conf) { err(yellow(` MCP \"${name}\" not found (not mounted and not in config)\\n`)); return; }\n if (idx >= 0) {\n const old = mounted.splice(idx, 1)[0];\n await old.client.close().catch((e) => log.debug('mcp close failed', e));\n }\n try {\n const m = await mountMcpServer(name, conf);\n mounted.push(m); remountMcpTools();\n err(green(` ✓ reconnected \"${name}\"`) + dim(` — ${m.tools.length} tool(s)\\n`));\n } catch (e: any) { err(red(` reconnect failed: ${e?.message ?? e}\\n`)); }\n return;\n }\n if (sub === 'remove') {\n const name = a[1];\n if (!name) { err(yellow(' usage: /mcp remove <name>\\n')); return; }\n const idx = mounted.findIndex((m) => m.name === name);\n if (idx < 0) { err(yellow(` MCP \"${name}\" not found\\n`)); return; }\n const m = mounted.splice(idx, 1)[0];\n remountMcpTools();\n await m.client.close().catch((e) => log.debug('mcp close failed', e));\n err(dim(` removed \"${name}\"\\n`));\n return;\n }\n if (sub === 'tools') {\n const filter = a[1];\n const targets = filter ? mounted.filter((m) => m.name === filter) : mounted;\n if (!targets.length) { err(dim(` (no ${filter ? `MCP server \"${filter}\"` : 'MCP servers'} found)\\n`)); return; }\n for (const m of targets) {\n err(` ${cyan(m.name)} ${dim(`(${m.tools.length} tools)`)}\\n`);\n for (const t of m.tools) err(dim(` - ${t.name.replace(`mcp__${m.name}__`, '')}${t.description ? ' — ' + t.description.split('\\n')[0] : ''}\\n`));\n }\n return;\n }\n if (sub === 'resources') {\n const filter = a[1];\n const targets = filter ? mounted.filter((m) => m.name === filter) : mounted;\n if (!targets.length) { err(dim(` (no ${filter ? `MCP server \"${filter}\"` : 'MCP servers'} found)\\n`)); return; }\n for (const m of targets) {\n try {\n const resources = await m.client.listResources();\n if (!resources.length) { err(dim(` ${m.name}: (no resources)\\n`)); continue; }\n err(` ${cyan(m.name)} ${dim(`(${resources.length} resources)`)}\\n`);\n for (const r of resources) err(dim(` - ${r.uri}${r.name ? ' — ' + r.name : ''}${r.mimeType ? ' [' + r.mimeType + ']' : ''}\\n`));\n } catch (e: any) { err(dim(` ${m.name}: resources not supported (${e?.message})\\n`)); }\n }\n return;\n }\n // default: interactive menu\n const listServers = () => {\n if (!mounted.length) { err(dim(' (no MCP servers mounted)\\n')); return; }\n for (const m of mounted) {\n const ver = m.serverInfo?.name ? dim(` · ${m.serverInfo.name}${m.serverInfo.version ? ' v' + m.serverInfo.version : ''}`) : '';\n err(` ${green('✓')} ${cyan(m.name)}${ver} ${dim(`(${m.tools.length} tools)`)}\\n`);\n }\n err(dim(' /mcp tools [name] to list tools · /mcp resources [name] for resources\\n'));\n };\n const items: SelectItem[] = [\n { label: 'list', value: 'list', desc: `show mounted servers (${mounted.length})` },\n { label: 'add', value: 'add', desc: 'mount a new MCP server' },\n ...(mounted.length ? [\n { label: 'tools', value: 'tools', desc: 'list a server\\'s tools' },\n { label: 'reconnect', value: 'reconnect', desc: 'remount a server (hung/restarted)' },\n { label: 'remove', value: 'remove', desc: 'unmount an MCP server' },\n { label: 'resources', value: 'resources', desc: 'list server resources' },\n ] : []),\n ];\n const picked = await selectMenu(process.stderr, { title: 'MCP servers', items });\n if (!picked) return;\n if (picked === 'list') { listServers(); return; }\n // re-dispatch to the subcommand handler\n a = [picked];\n if (picked === 'add') {\n const io = createInterface({ input: keyInput, output: process.stderr });\n try {\n const name = (await io.question(yellow(' name: '))).trim();\n const target = (await io.question(yellow(' command or url: '))).trim();\n if (!name || !target) { err(yellow(' cancelled\\n')); return; }\n a = ['add', name, ...target.split(' ')];\n } finally { io.close(); }\n } else if (picked === 'remove' || picked === 'reconnect') {\n const rv = await selectMenu(process.stderr, { title: `${picked} server`, items: mounted.map((m) => ({ label: m.name, value: m.name })) });\n if (!rv) return;\n a = [picked, rv];\n } else if (picked === 'tools' || picked === 'resources') {\n if (mounted.length === 1) { a = [picked, mounted[0].name]; }\n else {\n const rv = await selectMenu(process.stderr, { title: `server ${picked}`, items: [{ label: '(all)', value: '' }, ...mounted.map((m) => ({ label: m.name, value: m.name }))] });\n if (rv === null) return;\n a = rv ? [picked, rv] : [picked];\n }\n }\n // fall through to re-run with the assembled args\n return builtins.mcp.run(a);\n },\n },\n init: { desc: 'scaffold ./AGENTS.md project instructions', run: () => initInstructions(cwd) },\n paste: {\n desc: 'attach an image from the clipboard (macOS, = Ctrl-V) — /paste [message] sends now, /paste alone attaches to your next message',\n run: async (a) => {\n const att = grabClipboardAttachment();\n if (!att) { err(yellow(' no image on the clipboard') + dim(' — copy or screenshot one, then /paste\\n')); return; }\n const msg = a.join(' ').trim();\n if (msg) await turn(`${msg} ${att.ref}`); // grab + send in one go\n else { pendingImages.push(att.path); err(green(` ✓ image attached (#${pendingImages.length})`) + dim(' — type your message to send it\\n')); }\n },\n },\n export: {\n desc: 'save this conversation to Markdown — /export [path] (default ./.agent/exports/<id>.md)',\n run: (a) => {\n const shown = face.transcript.filter((m) => m.role !== 'system');\n if (!shown.length) { err(dim(' (nothing to export yet)\\n')); return; }\n const md = exportMarkdown(session.meta, shown);\n // Write to REAL disk (node fs) so the file is findable even in --vfs sandbox mode.\n const name = a[0] ? (extname(a[0]) ? a[0] : a[0] + '.md') : join('.agent', 'exports', `${session.meta.id}.md`);\n const path = resolve(cwd, name);\n try {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, md);\n err(green(` ✓ exported → ${path}\\n`) + dim(` ${shown.length} message(s) · ${md.length} chars\\n`));\n } catch (e: any) { err(red(` export failed: ${e?.message ?? e}\\n`)); }\n },\n },\n goal: {\n desc: 'autonomous loop — /goal <condition> | /goal (status) | /goal clear',\n run: async (a) => {\n if (!a.length) {\n if (!goalCondition) { err(dim(' no active goal\\n')); return; }\n const tokStr = goalTokens > 1000 ? `${(goalTokens / 1000).toFixed(1)}k` : String(goalTokens);\n err(` ${bold('◎ goal:')} ${goalCondition}\\n` + dim(` ${goalTurns} turn${goalTurns === 1 ? '' : 's'} · ${tokStr} tokens${goalLastReason ? ` · last: ${goalLastReason}` : ''}\\n`));\n return;\n }\n if (a[0] === 'clear') {\n if (!goalCondition) { err(dim(' no active goal\\n')); return; }\n goalCondition = undefined; goalTurns = 0; goalTokens = 0; goalLastReason = undefined;\n persistGoal();\n err(green(' ✓ goal cleared\\n'));\n return;\n }\n goalCondition = a.join(' ');\n goalTurns = 0; goalTokens = 0; goalLastReason = undefined;\n persistGoal();\n err(green(` ◎ goal set: ${goalCondition}\\n`) + dim(' working… (Esc to pause)\\n'));\n const tokensBefore = session.meta.tokens ?? 0;\n await turn(goalCondition);\n goalTokens += (session.meta.tokens ?? 0) - tokensBefore;\n goalTurns++;\n persistGoal();\n if (!exitRequested) await goalLoop();\n if (exitRequested) return true;\n },\n },\n exit: { desc: 'quit', run: () => true },\n quit: { desc: 'quit', run: () => true },\n };\n\n // Banner lines word-wrap with a hanging indent on a TTY (long cwd/model strings used to hard-break mid-word).\n const banner = (line: string) => err((process.stderr.isTTY ? wrapAnsi(line, process.stderr.columns ?? 80, ' ') : line) + '\\n');\n banner(bold('agentx') + cyan(' v' + VERSION) + dim(` — ${work.model} · ${cwd}`));\n banner(dim('Type a task, or /help. Type / or @ for live suggestions (↑/↓ ⏎). Esc cancels/clears; double-Esc jumps back; Ctrl-D exits.'));\n if (dx) banner(dim(`◑ duplex — reflex: ${dx.options.reflexModel} · act: ${work.model}${dx.options.thinkModel !== false ? ` · think: ${dx.options.thinkModel}` : ''} (real work runs in background tasks, re-voiced when done)`));\n // Live suggestions: file/dir entries from the real cwd; command/skill descriptions for the menu.\n const listDir: DirLister = (absDir) => {\n try {\n return readdirSync(join(cwd, absDir.replace(/^\\/+/, '')), { withFileTypes: true })\n .map((d) => ({ name: d.name, dir: d.isDirectory() }));\n } catch (e) { log.debug('completion readdir failed', absDir, e); return null; } // not a dir / unreadable\n };\n const commandNames = () => [...Object.keys(builtins).filter((k) => k !== 'quit'), ...cmds.map((c) => c.name), ...skills.map((s) => s.name)];\n const describe = (hit: string): string | undefined =>\n hit.startsWith('/') ? (builtins[hit.slice(1)]?.desc ?? cmds.find((c) => c.name === hit.slice(1))?.description ?? skills.find((s) => s.name === hit.slice(1))?.description) : undefined;\n const suggest = (lineToCursor: string) => {\n const [hits, token] = completeLine(lineToCursor, { commands: commandNames(), listDir, bangHistory: history });\n return { hits, token, describe };\n };\n\n const editor = createLineEditor(process.stderr);\n editorRef = editor; // async chrome (⦿ results, re-voice) repaints the live prompt through this\n let aborting = false; // first Esc of a turn aborts; a second Esc means \"…and jump back to edit\"\n let pendingRewind = false; // set by double-Esc during a run → REPL opens the jump-back picker once the turn unwinds\n // Esc / Ctrl-C cancel a RUNNING turn (raw mode stays on between prompts, so the key arrives live).\n // Double-Esc while running = cancel + jump back to edit a message (parity with double-Esc at the prompt).\n const classifyPaste = pastePathClassifier(cwd); // drag-dropped/pasted file paths → image/file attachments\n if (process.stdin.isTTY) {\n // Mid-turn type-ahead: a REAL editor (backspace/arrows/kill-keys + bracketed paste collapsing to\n // one placeholder), not a bare append-only buffer. Multi-line pastes land as ONE queued item.\n const sEd = new EditorState(() => ({ hits: [], token: '' }), [], classifyPaste, grabClipboardAttachment);\n stashEd = sEd;\n const inverse = (x: string) => `\\x1b[7m${x}\\x1b[0m`;\n const stashView = (): string => {\n const v = sEd.buf.replace(/\\n/g, '⏎');\n const c = Math.min(sEd.cursor, v.length);\n const at = c < v.length ? String.fromCodePoint(v.codePointAt(c)!) : ' '; // whole code point — v[c] alone can split an emoji\n const q = inputStash.length ? dim(` [${inputStash.length} queued]`) : '';\n return `${dim('› ')}${v.slice(0, c)}${inverse(at)}${v.slice(c + at.length)}${q}`;\n };\n spinner.tail = () => (sEd.buf ? stashView() : ''); // typed text rides the spinner frame (never erased)\n const renderStashBuf = () => {\n if (spinner.active) return; // the next 90ms tick paints it as the spinner tail\n err(`\\r\\x1b[K${sEd.buf ? ' ' + stashView() : ''}`);\n };\n repaintStash = renderStashBuf; // async chrome repaints the type-ahead line through this\n\n keyInput.on('keypress', (_s, key) => {\n if (isMenuActive()) return; // a live picker (permission ask) owns the keyboard\n if (!activeTurn && !dispatchPending) return;\n if (key?.ctrl && key?.name === 'o') { toggleVerbose(); return; }\n const k = key?.name;\n // Esc / Ctrl-C cancel the RUNNING turn immediately — typed-ahead text SURVIVES (carried into\n // the next prompt). Esc again → jump-back; Ctrl-C again → force-quit. (CC: Esc always interrupts.)\n if (!sEd.pasting && (k === 'escape' || (key?.ctrl && k === 'c'))) {\n if (!aborting) {\n aborting = true; activeTurn?.abort(); voiceIO?.interrupt();\n err(yellow('\\n ⎋ cancelling…') + dim(' (Ctrl-C again to force-quit)\\n'));\n // Watchdog: if the turn hasn't unwound shortly, the abort is wedged — surface the escape hatch.\n setTimeout(() => {\n if (activeTurn) err(red(' ⚠ still cancelling — press Ctrl-C to force-quit\\n'));\n }, 4000).unref?.();\n } else if (key?.ctrl && k === 'c') {\n err(red('\\n ⏻ force-quit\\n')); forceQuit(); // already cancelling + another Ctrl-C → never trapped\n } else if (k === 'escape' && !pendingRewind) { pendingRewind = true; err(dim(' ⎋⎋ jumping back to edit…\\n')); }\n return;\n }\n const action = applyKey(sEd, key ?? {}, _s);\n if (action === 'submit') {\n const text = sEd.expand().trim();\n sEd.reset();\n if (text) {\n inputStash.push(text);\n const view = text.replace(/\\n+/g, ' ⏎ '); // one-line preview (queued pastes carry real newlines)\n err(`\\r\\x1b[K${green(' ✓ stashed')} ${dim(`#${inputStash.length}: ${view.slice(0, 50)}${view.length > 50 ? '…' : ''}`)}\\n`);\n }\n return;\n }\n if (sEd.pasting) return; // accumulate silently; one render on paste-end\n if (action === 'eof' || action === 'rewind') return; // Ctrl-D / double-Esc have no meaning mid-turn\n renderStashBuf();\n });\n }\n const promptStr = bold(cyan('agentx › '));\n const contPrompt = dim(' … › '); // `\\`-continued lines\n const releaseStdin = () => { releaseKeyInput(); if (process.stdin.isTTY) { err('\\x1b[?2004l'); try { process.stdin.setRawMode(false); } catch { /* not a tty */ } } process.stdin.pause(); };\n\n let prefill: string | undefined; // set by double-Esc jump-back → pre-fills the next prompt\n let tick = 0; // footer spinner frame counter (advances on each ticked re-render)\n /** One dispatch seam for a submitted line — typed (REPL loop) and spoken (voiceIO.onUtterance)\n * share it, so voice gets !cmd/#note//commands/mentions/persistence identically. Returns 'quit'\n * when a builtin asked to exit. */\n const dispatchLine = async (line: string): Promise<'quit' | void> => {\n if (/^[!#/]/.test(line)) dispatchPending = false; // not a model turn — don't capture picker/question keys\n history.unshift(line.replace(/\\n+/g, ' ⏎ ')); // make this turn ↑-recallable in-session\n remember(line.replace(/\\n+/g, ' ⏎ ')); // persist (one entry per line)\n\n // `!cmd` — run a shell command inline (no model call), like CC's bash mode.\n if (line.startsWith('!')) {\n const cmd = line.slice(1).trim();\n // Mirror the agent's own Shell availability: real /bin/sh when on disk (unless --no-shell),\n // else wcli's VFS emulator (sandbox/boddb, or --no-shell opt-out).\n if (cmd) {\n const out = await runShellLine(agent.options.fs!, cmd, { realShell: !(args.vfs || args.boddb) && args.shell !== false, cwd });\n err(dim(out + '\\n'));\n // CC parity: the command + its output join the conversation context so the model can reason\n // about it on the next turn (folded into that turn's message — avoids a dangling user turn).\n bangContext.push(`<bash-input>${cmd}</bash-input>\\n<bash-output>\\n${out}\\n</bash-output>`);\n }\n return;\n }\n // `#note` — jot a memory, like CC. Writes to the memory index (created if absent).\n if (line.startsWith('#')) {\n const note = line.slice(1).trim();\n if (note) { const where = await appendMemoryNote(agent.options.fs!, primaryMemDir(agent.options.memoryDir, adot('memory')), note); err(green(` ✎ remembered → ${where}\\n`)); }\n return;\n }\n\n if (line.startsWith('/')) {\n const [name, ...a] = line.slice(1).split(/\\s+/);\n if (!name) { err(red(' / needs a command name\\n') + dim(' (try /help)\\n')); return; } // bare \"/\" or \"/ \"\n const b = builtins[name];\n if (b) { if (await b.run(a)) return 'quit'; return; }\n // not a builtin → pick up any skill/command created mid-session before resolving, so a\n // freshly-authored /<name> dispatches without needing a model turn or /reload first.\n await refreshCatalogs().catch((e) => { log.debug('catalog refresh failed', e); });\n // …user-defined custom command?\n const c = cmds.find((x) => x.name === name);\n if (c) { await runCommand(c, a.join(' ')); return; }\n // …or a skill? invoke it by feeding its SKILL.md (plus any args) as the turn's prompt.\n const sk = skills.find((x) => x.name === name);\n if (sk) { await runSkill(sk, a.join(' ')); return; }\n // unknown → enumerate what IS available\n const known = Object.keys(builtins).filter((k) => k !== 'quit').map((k) => '/' + k);\n const custom = [...cmds.map((x) => x.name), ...skills.map((x) => x.name)].map((n) => '/' + n);\n err(red(` unknown command /${name}\\n`) + dim(' builtins: ' + known.join(' ') + '\\n') + (custom.length ? dim(' custom: ' + custom.join(' ') + '\\n') : '') + dim(' (or /help)\\n'));\n return;\n }\n\n // Attach any clipboard images grabbed via /paste to this message (reuses the @ref pipeline).\n const task = pendingImages.length ? `${line} ${pendingImages.map((p) => '@' + p).join(' ')}` : line;\n pendingImages.length = 0;\n await turn(task);\n if (goalCondition && !aborting && !exitRequested) { goalTurns++; persistGoal(); await goalLoop(); }\n if (exitRequested) return 'quit';\n };\n\n // ── Voice I/O (`--voice` + SONIOX/CARTESIA keys on a TTY): spoken utterances enter the SAME\n // dispatch as typed lines (the dx.send mutex serializes); the voice's text_delta stream is\n // spoken via the host tap above. Missing keys → conversational text mode, one-line note.\n let voicePartial = ''; // live partial transcript, rendered in the prompt footer\n let partialRedraw: ReturnType<typeof setTimeout> | null = null;\n // Spin VoiceIO up live (launch with --voice, or /voice mid-session). `greet` opens with a spoken\n // greeting turn (launch only); a manual toggle just turns the mic on quietly. Returns true if voice\n // is now live. Duplex + TTY only — bound to `toggleVoice` below so /voice can flip it off again.\n const startVoice = async (greet: boolean): Promise<boolean> => {\n if (voiceIO) return true;\n if (!duplex || !process.stdin.isTTY) { err(dim(' (voice needs --duplex on a TTY)\\n')); return false; }\n if (!VoiceIO.available()) {\n err(dim(' (voice I/O off — set SONIOX_API_KEY, CARTESIA_API_KEY, CARTESIA_VOICE_ID to talk)\\n'));\n return false;\n }\n voiceIO = new VoiceIO({\n // No ack phrase by default: a fixed \"Mm-hm,\" every turn reads robotic, Haiku's TTFT doesn't\n // need masking (~0.7-1.2s full turns), and the conversational register already opens with a\n // natural reaction. The mechanism (+ echo-leak guard) stays for slower voice models.\n onState: () => editorRef?.redrawNow(),\n // Throttled: each redraw clears the screen below the prompt — a partial-per-token storm\n // (fast speech, or echo bleed if AEC degrades) would continuously erase streamed text.\n onPartial: (text) => {\n if (text === voicePartial) return; // Soniox emits frequent no-change partials — repainting on them flickers the idle prompt\n voicePartial = text;\n if (!partialRedraw) partialRedraw = setTimeout(() => { partialRedraw = null; editorRef?.redrawNow(); }, 250);\n },\n // voiceEchoEnd closes the open echo line; '\\r\\x1b[0J' wipes the stale prompt/footer before the\n // notice — every other async-chrome writer does this, and without it \"✋ interrupted\" overprints\n // the footer's leading chars (the \"interrupted% ctx\" glue).\n onBargeIn: (phase) => { activeTurn?.abort(); voiceEchoEnd(); if (phase === 'speaking') err('\\r\\x1b[0J' + yellow(' ✋ interrupted\\n')); },\n onUtterance: (text) => {\n voicePartial = '';\n if (!text.trim()) return;\n // Spoken \"voice off\": deterministic keyword match BEFORE the reflex (no inference, no TTS\n // context leak). Speak a short ack, let it drain, then tear voice down via the /voice toggle.\n if (matchVoiceCommand(text) === 'off') {\n err(`\\r\\x1b[K ${bold(cyan('🎤 ›'))} ${text}\\n`);\n // Capture the instance: /voice during the ~1s ack drain swaps voiceIO — a blind toggle\n // would then flip the user's NEW choice (off→on inversion). Only tear down OUR instance.\n const v = voiceIO!;\n void (async () => { v.speakFiller('Voice off.'); await v.awaitIdle(); if (voiceIO === v) await toggleVoice?.(); })();\n return;\n }\n // Barge-in context: the cut-off reply is in the transcript but the user never HEARD its\n // tail — tell the model, so it can recap what was missed instead of assuming it landed.\n const cut = voiceIO!.takeInterruptedReply();\n const note = cut && cut.full.length - cut.heard.length > 40\n ? `\\n[the user interrupted you mid-speech — they only heard up to: \"…${cut.heard.slice(-80)}\". Work any unheard essentials into your reply naturally, only if still relevant.]`\n : '';\n // Only model-bound turns open a TTS context — a `!`/`#`/`/` line produces no deltas and\n // would leak an open context (state stuck in 'thinking', ack spoken into silence).\n if (!/^[!#/]/.test(text.trim())) voiceIO!.beginSpeech(true); // context + micro-ack NOW (LLM deltas continue it)\n err(`\\r\\x1b[K ${bold(cyan('🎤 ›'))} ${text}\\n`);\n void dispatchLine(text + note).then(async (r) => { if (r === 'quit') { await voiceIO?.awaitIdle(); editorRef?.abort(); } }).finally(() => editorRef?.redrawNow());\n },\n });\n try {\n await voiceIO.start();\n // Only the AEC path captures the macOS default input verbatim; the ffmpeg fallback name-picks a real\n // mic (skips BlackHole), so reporting the system default there would be misleading.\n const inDev = voiceIO.usingAec ? detectedInputDevice() : null;\n const inNote = inDev ? `, in: ${inDev.name}` : '';\n err(dim(` 🎤 voice on (${voiceIO.usingAec ? 'echo-cancelled' : 'heuristic echo — headphones recommended'}${inNote}) — just talk; speak over it to interrupt; say \"voice off\" to stop\\n`));\n // A virtual/loopback default input (BlackHole, Aggregate, Teams…) carries no mic signal → STT hears silence.\n if (inDev?.virtual) err(yellow(` ⚠ default input \"${inDev.name}\" looks like a virtual device — if it can't hear you, switch your Mac input to a real mic\\n`));\n if (greet) {\n // Greeting: the agent makes the first turn — spoken, personalized from what it can see.\n // Straight to turn() (not dispatchLine): the synthetic prompt must not enter ↑-history.\n const where = cwd.split('/').pop();\n const resumed = session.messages.length > 0;\n // Resume ≠ cold start: the prior conversation (incl. the memory QuickLook result) is already in\n // context, so DON'T re-fetch memory and DON'T re-open with \"what would you like to do\" — that\n // resets the thread and reads as a brand-new session. Continue where it left off instead.\n const prompt = resumed\n ? `[session resumed] You're rejoining a live voice conversation already in progress — the full history, including the user's memory/preferences, is already in context, so do NOT call QuickLook again. ` +\n `In one short spoken line, welcome the user back and pick the thread up where it left off: if your last turn ended on an open question or offer, continue it naturally rather than asking what they'd like to do.`\n : `[session started] First call QuickLook with what:\"memory\" — if it knows the user's name or preferences, use them. ` +\n `Then greet the user warmly in one or two short sentences, as the opener of a live voice conversation. ` +\n `Context: working directory \"${where}\". Personalize from whatever you learned (memory). Then ask what they'd like to do.`;\n void turn(prompt).finally(() => editorRef?.redrawNow());\n }\n return true;\n } catch (e: any) {\n err(yellow(` ⚠ voice I/O failed to start: ${e?.message ?? e} — continuing text-only\\n`));\n voiceIO = undefined;\n return false;\n }\n };\n // Child cleanup, registered ONCE (not per start — toggling on/off must not stack listeners). They\n // close over the live `voiceIO`, so they cover whichever instance is up. SIGHUP/SIGTERM (terminal\n // closed, kill) bypass 'exit' handlers by default — without these the mic/player children outlive\n // the CLI and hold the microphone (verified leak in PTY testing).\n if (duplex && process.stdin.isTTY) {\n process.on('exit', () => voiceIO?.stop());\n for (const sig of ['SIGHUP', 'SIGTERM'] as const) process.on(sig, () => { voiceIO?.stop(); process.exit(0); });\n }\n // /voice toggle: flip the mic on or off without leaving the session (kills STT/TTS children on off).\n if (duplex && process.stdin.isTTY) toggleVoice = async () => {\n if (voiceIO) { voiceIO.stop(); voiceIO = undefined; voicePartial = ''; err(dim(' 🔇 voice off — /voice to turn back on\\n')); editorRef?.redrawNow(); return; }\n await startVoice(false);\n editorRef?.redrawNow();\n };\n // Launch with --voice: start now, with the spoken greeting.\n if (args.voice && duplex && process.stdin.isTTY) await startVoice(true);\n\n let ctxWarned = 0; // highest context-pressure threshold (80/90) already warned about\n while (true) {\n // Double-Esc fired during the just-finished turn → open the jump-back picker now (turn has unwound).\n if (pendingRewind) { pendingRewind = false; const t = await rewindToMessage(); if (t !== undefined) prefill = t; }\n aborting = false;\n const carry = stashText() ? stashEd!.expand() : ''; stashEd?.reset(); // type-ahead typed (not Enter'd) during the turn → carry it forward\n err('\\n'); // blank line before the prompt (the editor renders on one line)\n // Consume the pending jump-back text (once); else fall back to un-submitted type-ahead so a line\n // typed while the turn ran isn't lost — it lands editable in the fresh prompt (CC parity).\n const initial = prefill ?? (carry || undefined); prefill = undefined;\n // Dim status footer under the prompt (context% · cost). Constant while typing one line (transcript is\n // fixed until submit), so compute once per iteration. Hidden on a fresh REPL (no usage yet) to stay clean.\n const ctxTok = estimateTranscriptTokens(face.transcript); // expensive: compute once per iteration (not per keystroke)\n const ctxCap = face.options.maxTokens || 200_000;\n // One-shot threshold warnings at 80% and 90% (CC parity: warn BEFORE the silent auto-trim bites).\n {\n const pct = Math.round((ctxTok / ctxCap) * 100);\n const step = pct >= 90 ? 90 : pct >= 80 ? 80 : 0;\n if (step > ctxWarned) { ctxWarned = step; err(yellow(` ⚠ context ${pct}% full`) + dim(' — /compact folds older messages (oldest are auto-trimmed at the cap)\\n')); }\n else if (!step) ctxWarned = 0; // dropped back under 80% (e.g. /compact) → re-arm\n\n }\n const usd = session.meta.costUsd ?? 0;\n // Cheap, mutable bits (posture/reasoning/tasks) are read LIVE so Shift+Tab/Alt+T update the footer instantly.\n const computeFooter = () => {\n const parts: string[] = [];\n if (voiceIO) {\n const glyph = { listening: '🎤', thinking: '💭', speaking: '🔊', idle: '·' }[voiceIO.state];\n parts.push(voicePartial && voiceIO.state === 'listening' ? `🎤 ${voicePartial.slice(-60)}` : `${glyph} ${voiceIO.state}`);\n }\n if (ctxTok > 400) parts.push(`${Math.round((ctxTok / ctxCap) * 100)}% ctx (~${(ctxTok / 1000).toFixed(1)}k/${Math.round(ctxCap / 1000)}k)`);\n if (usd > 0) parts.push(`${session.meta.costEstimated ? '~' : ''}${fmtUsd(usd)}`);\n if (posture !== 'default') parts.push(postureLabel());\n const r = work.reasoning; if (r && r !== 'off') parts.push(`reasoning:${r}`);\n if (verboseOutput) parts.push('verbose');\n if (goalCondition) parts.push(`◎ goal (${goalTurns} turns)`);\n if (latestTodos.length) { // compact TodoWrite panel: done-count + the current step (CC Ctrl-T-style)\n const done = latestTodos.filter((t) => t.status === 'completed').length;\n const cur = latestTodos.find((t) => t.status === 'in_progress')?.content;\n if (done < latestTodos.length) parts.push(`☑ ${done}/${latestTodos.length}${cur ? ` · ${cur.slice(0, 48)}` : ''}`);\n }\n if (scheduler.size) parts.push(`⏰ ${scheduler.size} scheduled`);\n if (inputStash.length) parts.push(`${inputStash.length} stashed (⌃S to pop)`);\n // Running background tasks: one STACKED line each, pinned to the prompt block, with an animated\n // spinner frame (statusTickMs re-renders this footer every second) — a slow worker is visibly\n // alive and visibly THERE. Finished tasks drop out (their ⦿ result lands in the flow).\n const taskLines: string[] = [];\n if (dx) {\n const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n for (const t of dx.tasks.values()) if (t.status === 'running') taskLines.push(`◔ ${frames[tick % frames.length]} ${t.id} ${t.label} — working in background…`);\n if (taskLines.length) tick++;\n }\n return [...taskLines, parts.join(' · ')].filter(Boolean).join('\\n');\n };\n // LIVE prompt: while a worker question is pending, the prompt itself becomes the question\n // (CC-parity for permission asks) — duplexAsk's redrawNow() flips it the moment an ask parks.\n const livePrompt = () => {\n const ask = dx?.pendingAsks.size ? dx.pendingAsks.values().next().value : undefined;\n if (!ask) return promptStr;\n const q = ask.question.replace(/\\s+/g, ' ').slice(0, 64);\n return bold(yellow(`? ${q}${ask.question.length > 64 ? '…' : ''} ‹yes/no› `));\n };\n const result = await readMultiline((cont) => editor.readLine({\n prompt: cont ? contPrompt : livePrompt, suggest, history, classifyPaste, onEmptyPaste: grabClipboardAttachment,\n onSubmit: () => { dispatchPending = true; }, // claim keys buffered behind the Enter (turn isn't active yet)\n initial: cont ? undefined : initial, status: computeFooter, vimMode: cfg.editorMode === 'vim',\n statusTickMs: dx ? 1000 : undefined, // duplex: animate the running-task footer while idle at the prompt\n // Esc at the idle prompt with workers running → cancel them (CC-style: Esc stops the work).\n onEscapeIdle: dx ? () => {\n const running = [...dx.tasks.values()].filter((t) => t.status === 'running');\n if (!running.length) return false;\n for (const t of running) err('\\r\\x1b[0J' + yellow(` ⊘ ${dx.cancelTask(t.id)}`) + '\\n');\n return true;\n } : undefined,\n onCyclePosture: cyclePosture,\n onToggleThinking: toggleReasoning,\n onToggleVerbose: toggleVerbose,\n onPickModel: async () => { const picked = await pickModel(work.model); if (picked) setModel(picked); return picked; },\n onStash: (text) => { inputStash.push(text); err(`${green(' ✓ stashed')} ${dim(`#${inputStash.length}: ${text.slice(0, 50)}${text.length > 50 ? '…' : ''}`)}\\n`); },\n onUnstash: () => { if (!inputStash.length) return undefined; const t = inputStash.pop()!; err(dim(` ↑ unstashed${inputStash.length ? ` (${inputStash.length} left)` : ''}\\n`)); return t; },\n }));\n if (result === null) break; // Ctrl-D / Ctrl-C at an empty prompt → exit\n if (result === REWIND) { prefill = await rewindToMessage(); continue; } // double-Esc → jump-back picker\n const line = result.trim();\n if (!line) continue;\n // Typed answer to a pending worker question: resolve it DIRECTLY (deterministic, no LLM hop) —\n // same UX as approving in a normal session. Anything else falls through to the conversation.\n if (dx?.pendingAsks.size && /^(y(es|ep|eah)?|n(o|ope)?|sure|ok(ay)?|allow|deny|go( ahead)?)[.!]?$/i.test(line)) {\n const [id, ask] = dx.pendingAsks.entries().next().value!;\n ask.resolve(line);\n err(dim(` ↳ answered ${id}: ${line}\\n`));\n continue;\n }\n let quit = await dispatchLine(line) === 'quit';\n // Drain stashed input (typed while a turn was running) — but ONLY after a real conversational\n // turn. A local meta-command (/cmd, !bash, #note) must not auto-fire the queue: it isn't a turn,\n // and /paste would even fold its just-grabbed clipboard image into the drained message. Queue waits.\n const wasLocal = /^[!#/]/.test(line);\n while (!quit && !wasLocal && inputStash.length) {\n const next = inputStash.shift()!;\n const nview = next.replace(/\\n+/g, ' ⏎ ');\n err(dim(` ⏎ stashed › ${nview.slice(0, 60)}${nview.length > 60 ? '…' : ''}\\n`));\n quit = await dispatchLine(next) === 'quit';\n }\n // Drain scheduled prompts that fired while the last turn was running (or idle at the prompt).\n while (!quit && scheduleQueue.length) {\n const prompt = scheduleQueue.shift()!;\n err(dim(` ⏰ scheduled › ${prompt.slice(0, 60)}${prompt.length > 60 ? '…' : ''}\\n`));\n await turn(prompt);\n }\n dispatchPending = false; // dispatch + drains settled — back to the editor owning the keys\n // Persist scheduler state into session (survives --resume).\n (session.meta as any).scheduledJobs = scheduler.snapshot();\n try { store.save(session); } catch { /* non-fatal */ }\n if (quit) break;\n }\n scheduler.destroy();\n triggerServer.stop(); // unlink this session's trigger socket (a stale one would mislead tier-1 routing)\n voiceIO?.stop(); // kill mic/player children + close STT/TTS sockets (they outlive the process otherwise)\n // Duplex: let in-flight workers finish (their re-voice persists the transcript) before tearing down.\n // ExitSession: the user said goodbye — kill workers immediately instead of draining.\n if (dx) {\n const running = [...dx.tasks.values()].filter((t) => t.status === 'running');\n if (exitRequested && running.length) {\n for (const t of running) { t.status = 'cancelled'; t.controller.abort(); }\n err(dim(` … cancelled ${running.length} background task(s)\\n`));\n } else if (running.length) {\n err(dim(` … waiting for ${running.length} background task(s) (Ctrl-C to force quit)\\n`));\n // stdin is still in raw mode here, so Ctrl-C arrives as a 0x03 byte (no SIGINT).\n // Race the drain against a raw Ctrl-C: on press, abort all workers and bail.\n let forced = false;\n let onCtrlC = () => {};\n const onByte = (b: Buffer) => {\n if (!b.includes(0x03)) return; // Ctrl-C\n forced = true;\n for (const t of running) { t.status = 'cancelled'; t.controller.abort(); }\n err(dim(`\\n … force-quit — cancelled ${running.length} background task(s)\\n`));\n onCtrlC();\n };\n keyInput.on('data', onByte);\n await Promise.race([dx.idle(), new Promise<void>((res) => { onCtrlC = res; })]);\n keyInput.off('data', onByte);\n if (forced) {\n // User force-quit: tear down and hard-exit — don't trust the event loop to drain\n // (voice children / sockets / MCP handles can keep the process alive otherwise).\n voiceIO?.stop();\n releaseStdin();\n disposeCursorSessions();\n await closeMcp(mounted);\n process.exit(130);\n }\n (face.options.host as { flushText?: () => void } | undefined)?.flushText?.();\n duplexPersist();\n }\n }\n releaseStdin();\n disposeCursorSessions(); // reap any warm cursor helper (its stdout pipe would otherwise keep the loop alive → hang on exit)\n await closeMcp(mounted);\n}\n\n/** Read all of stdin to EOF (for `echo \"prompt\" | agentx -p`). */\nfunction readAllStdin(): Promise<string> {\n return new Promise((res) => {\n let data = '';\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', (c) => (data += c));\n process.stdin.on('end', () => res(data));\n process.stdin.resume();\n });\n}\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2));\n if (args.version) { console.log('agentx ' + VERSION); return; }\n if (args.help) { console.log(HELP); return; }\n if (args.debug) process.env.DEBUG ||= '*'; // --debug/--verbose → enable gated debug/verbose logs (libx forComponent)\n // bare `-p` with piped input → read the whole prompt from stdin (CC parity for `echo \"…\" | agentx -p`)\n if (args.print && !args.task && !process.stdin.isTTY) args.task = (await readAllStdin()).trim();\n const cwd = resolve(args.cwd ?? process.cwd());\n const cfg = await loadConfig(cwd);\n // fold in rules the user \"Always allowed/denied\" in earlier sessions (.agent/permissions.json)\n // fold in CC-compatible .claude/settings.json rules, our persisted \"Always\" rules, and the config block\n // (all merged — deny>allow>ask is decided per-call, not per-source, so concatenation is correct).\n cfg.permissions = mergePerms(loadClaudeSettings(cwd), mergePerms(loadPersistedRules(cwd), cfg.permissions));\n // directory-trust gate (CC-style): on first interactive use of a new dir, confirm once.\n if (canPrompt && !args.yes && !isTrusted(cwd)) {\n const ok = await makeHost().confirm?.(`Trust this directory? agent.libx will read and edit files in:\\n ${cwd}`);\n if (!ok) { console.error(red(' not trusted — exiting (re-run with --yes to skip this prompt).')); process.exit(1); }\n trustDir(cwd);\n }\n // bare `--resume`/`-r` (no id) → interactive session picker, like CC (needs a TTY + an id when piped).\n if (args.resume === '') {\n const picker = new SessionStore(cwd).list();\n if (!picker.length) { console.error(yellow(' no saved sessions in this directory.')); process.exit(1); }\n if (!canPrompt) { console.error(red(' --resume needs an id when not interactive: --resume <id> (latest: ' + picker[0].id + ')')); process.exit(1); }\n const id = await selectMenu(process.stderr, { title: 'Resume a session', items: picker.slice(0, 50).map((m) => ({ label: `${m.id} ${m.title || '(untitled)'}`, value: m.id, desc: `${m.turns} turn${m.turns === 1 ? '' : 's'}` })) });\n if (!id) process.exit(0); // cancelled\n args.resume = id;\n }\n loadInstallEnv(); // fallback: pick up keys from agentx's own .env when launched elsewhere (won't override CWD/shell)\n const apiKeys = { ...cfg.apiKeys, ...apiKeysFromEnv() }; // env wins\n if (!Object.keys(apiKeys).length) {\n console.error(red('No provider key found. Set ANTHROPIC_API_KEY (or OPENAI_API_KEY / GOOGLE_API_KEY / GROQ_API_KEY), e.g. in .env.'));\n process.exit(1);\n }\n // AIClient is the concrete impl of the runtime's `ChatLike` seam (the CLI only needs that seam).\n // retry: transient 429/5xx blips auto-recover with backoff; surface it so a pause isn't a mystery.\n const ai = new AIClient({\n apiKeys,\n ...(cfg.baseUrls ? { baseUrls: cfg.baseUrls } : {}),\n retry: {\n onRetry: ({ attempt, delayMs, error }: { attempt: number; delayMs: number; error: any }) => {\n const why = error?.name === 'RateLimitError' || error?.status === 429 ? 'rate-limited' : 'service busy';\n err(yellow(`\\n ⟳ ${why} — retrying (#${attempt}) in ~${Math.max(1, Math.round(delayMs / 1000))}s…\\n`));\n },\n },\n }) as unknown as ChatLike;\n\n if (args.task) {\n // one-shot / headless — still persisted so it can be --continue'd later. OAuth refresh works here\n // (no browser); only attended registration needs the REPL `/mcp login`.\n const mounted = await mountMcp(cfg, new McpOAuth({ storePath: join(cwd, '.agent', 'mcp-auth.json') }));\n const agent = await makeAgent(args, ai, cfg, mcpAgentTools(mounted));\n const store = new SessionStore(cwd);\n const session = startSession(args, store, agent, cwd);\n process.once('SIGINT', () => activeTurn?.abort()); // Ctrl-C cancels the run; it still persists + exits cleanly\n const { ok, res } = await runTurn(agent, store, session, args.task, undefined, cwd);\n // opt-in: on a bad outcome, reflect once and persist a novel lesson for next session\n if (cfg.reflectOnFailure && !ok && res && agent.options.memoryDir) {\n const _fsBase = agent.options.fs!.getCwd() === '/' ? '' : agent.options.fs!.getCwd();\n const slug = await reflectOnRun({ ai, model: agent.options.model, fs: agent.options.fs!, dir: primaryMemDir(agent.options.memoryDir, `${_fsBase}/.agent/memory`), result: res });\n if (slug) err(dim(` ✎ learned a lesson → ${slug}\\n`));\n }\n await closeMcp(mounted); // kill MCP child processes after the run (and any reflection)\n if (args.outputFormat === 'json' || args.outputFormat === 'stream-json') {\n const obj = res ? jsonResult(res, session) : { ok: false, finishReason: 'error', sessionId: session.meta.id };\n // json → the single result object; stream-json → a final {type:'result',…} line closing the NDJSON stream\n process.stdout.write(JSON.stringify(args.outputFormat === 'stream-json' ? { type: 'result', ...obj } : obj) + '\\n');\n }\n process.exit(ok ? 0 : 1);\n }\n\n await repl(args, ai, cfg, cwd); // --duplex is a mode of the same REPL (fast voice + delegated workers)\n}\n\n// Only auto-run when invoked as the entry point — keeps the module importable in tests.\nif (import.meta.main) main().catch((e) => { console.error(e?.message ?? e); process.exit(1); });\n","import { execFileSync } from 'node:child_process';\nimport { statSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/**\n * Read an image off the OS clipboard and save it to disk — the \"paste a screenshot\" path that\n * bracketed paste can't carry (image bytes never reach stdin as text). macOS via osascript (+ sips\n * for TIFF→PNG, since screenshots are often TIFF); Linux via wl-paste (Wayland) or xclip (X11).\n * Other platforms / missing tools / empty clipboard → null. `run`/`platform` are injectable for tests.\n */\n\nexport interface ClipboardImage { path: string; mime: string; }\n/** Runs a command; for the macOS path the side effect (a written file) matters, for Linux the returned stdout Buffer does. */\nexport type RunFn = (cmd: string, args: string[], opts?: { maxBuffer?: number; stdio?: any }) => unknown;\n\n// macOS: osascript/sips write the file as a side effect — discard all stdio (ImageIO prints benign\n// warnings like \"Error creating a JP2 color space: falling back to sRGB\" to stderr; we don't want those).\nconst SILENT = { stdio: ['ignore', 'ignore', 'ignore'] as const };\n// Linux: capture stdout (the PNG bytes), discard stderr.\nconst CAPTURE = { stdio: ['ignore', 'pipe', 'ignore'] as const, maxBuffer: 64 * 1024 * 1024 };\n\n/** AppleScript double-quoted POSIX path. */\nconst q = (s: string): string => '\"' + s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"') + '\"';\nconst nonEmpty = (p: string): boolean => { try { return statSync(p).size > 0; } catch { return false; } };\n\n/** Save the clipboard image to `dir/clip-<id>.png`. Returns null when the clipboard holds no image. */\nexport function grabClipboardImage(\n dir: string,\n id: string,\n run: RunFn = execFileSync,\n platform: NodeJS.Platform = process.platform,\n): ClipboardImage | null {\n const png = join(dir, `clip-${id}.png`);\n if (platform === 'linux') {\n // wl-paste (Wayland) / xclip (X11) write the PNG bytes to stdout; each throws if absent or no image.\n for (const [cmd, args] of [['wl-paste', ['--type', 'image/png']], ['xclip', ['-selection', 'clipboard', '-t', 'image/png', '-o']]] as const) {\n try {\n const buf = run(cmd, [...args], CAPTURE); // spread: `as const` makes args readonly; run wants string[]\n if (Buffer.isBuffer(buf) && buf.length) { writeFileSync(png, buf); return { path: png, mime: 'image/png' }; }\n } catch { /* tool missing or no image — try the next */ }\n }\n return null;\n }\n if (platform !== 'darwin') return null;\n // `set d` runs first → throws cleanly (before any file is opened) if the clipboard lacks that class.\n const osa = (klass: string, out: string) =>\n `set d to (the clipboard as «class ${klass}»)\\n` +\n `set f to open for access POSIX file ${q(out)} with write permission\\n` +\n `try\\n\\twrite d to f\\nend try\\nclose access f`;\n try { run('osascript', ['-e', osa('PNGf', png)], SILENT); if (nonEmpty(png)) return { path: png, mime: 'image/png' }; } catch { /* no PNG on clipboard */ }\n try {\n const tiff = join(dir, `clip-${id}.tiff`);\n run('osascript', ['-e', osa('TIFF', tiff)], SILENT);\n if (nonEmpty(tiff)) { run('sips', ['-s', 'format', 'png', tiff, '--out', png], SILENT); if (nonEmpty(png)) return { path: png, mime: 'image/png' }; }\n } catch { /* no image on clipboard */ }\n return null;\n}\n\n/** Put `text` on the OS clipboard (for `/copy`). pbcopy (macOS), wl-copy/xclip (Linux).\n * Returns false when no clipboard tool is available. */\nexport function copyTextToClipboard(text: string, platform: NodeJS.Platform = process.platform): boolean {\n const candidates: Array<[string, string[]]> =\n platform === 'darwin' ? [['pbcopy', []]] :\n platform === 'linux' ? [['wl-copy', []], ['xclip', ['-selection', 'clipboard']]] : [];\n for (const [cmd, args] of candidates) {\n try { execFileSync(cmd, args, { input: text, stdio: ['pipe', 'ignore', 'ignore'] }); return true; }\n catch { /* tool missing — try the next */ }\n }\n return false;\n}\n","/**\n * Wire types mirroring ai.libx.js (OpenAI-style chat). We type the transport\n * structurally via `ChatLike`, so an ai.libx.js `AIClient` is a drop-in — and a\n * `FakeAIClient` works in tests — with no hard runtime dependency on ai.libx.js.\n */\n\nexport type Role = 'system' | 'user' | 'assistant' | 'tool';\n\nexport interface ToolCall {\n id: string;\n type: 'function';\n function: { name: string; arguments: string }; // arguments is a JSON string\n}\n\n/** One part of a multimodal message (mirrors ai.libx.js ContentPart) — text or an image URL/data-URI. */\nexport interface ContentPart {\n type: 'text' | 'image_url';\n text?: string;\n image_url?: { url: string };\n}\n\n/** A message's content is either plain text or an array of multimodal parts (images + text). */\nexport type MessageContent = string | ContentPart[];\n\nexport interface Message {\n role: Role;\n content: MessageContent;\n name?: string;\n tool_call_id?: string;\n tool_calls?: ToolCall[];\n}\n\n/** Flatten any message content to its text (string as-is; parts → concatenated text) — for length\n * estimation, summaries, and display. Non-text parts (images) contribute a short placeholder. */\nexport function contentText(content: MessageContent | undefined): string {\n if (content == null) return '';\n if (typeof content === 'string') return content;\n return content.map((p) => (p.type === 'text' ? (p.text ?? '') : '[image]')).join(p_sep(content));\n}\nconst p_sep = (parts: ContentPart[]): string => (parts.length > 1 ? '\\n' : '');\n\n/** Build an image content part from a data-URI or http(s) URL. */\nexport function imagePart(url: string): ContentPart {\n return { type: 'image_url', image_url: { url } };\n}\n\nexport interface Tool {\n type: 'function';\n function: { name: string; description?: string; parameters: object };\n}\n\nexport interface ChatResponse {\n content: string;\n finishReason?: string;\n toolCalls?: ToolCall[];\n model?: string;\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number };\n}\n\n/**\n * One incremental event from a streamed `chat({stream:true})` call — mirrors\n * ai.libx.js's `StreamChunk` (OpenAI-style): each chunk carries a `content`\n * text delta; the terminal chunk carries `finishReason` and the accumulated\n * `toolCalls`. Consuming the stream and folding the deltas reconstructs the\n * same `ChatResponse` the non-stream path returns.\n */\nexport interface StreamChunk {\n content: string;\n finishReason?: string;\n index?: number;\n toolCalls?: ToolCall[]; // accumulated tool calls (typically on the final chunk)\n reasoningContent?: string;\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number }; // on the terminal chunk, when the provider reports it\n}\n\nexport interface ChatOptions {\n model: string;\n messages: Message[];\n tools?: Tool[];\n toolChoice?: unknown;\n stream?: boolean;\n /** Cancel the request/stream. Forwarded to providers that honor it; the Agent also stops consuming on abort. */\n signal?: AbortSignal;\n [k: string]: unknown;\n}\n\n/** Minimal shape of an ai.libx.js AIClient that the Agent drives. */\nexport interface ChatLike {\n chat(options: ChatOptions): Promise<ChatResponse | AsyncIterable<StreamChunk>>;\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\nimport type { ChatLike, ChatResponse, Message, StreamChunk, ToolCall, MessageContent, ContentPart } from './llm';\nimport { contentText, imagePart } from './llm';\nimport { type AgentTool, type ToolContext, type HostBridge, defaultTools, makeContext, toWireTools, truncateOutput } from './tools';\nimport { SandboxJobRegistry, makeJobTools } from './tools.jobs';\nimport { askUserQuestionTool } from './host';\nimport { loadSkills, scanSkills } from './skills';\nimport { loadCommands, scanCommands } from './commands';\nimport { loadMemory } from './memory';\nimport { loadInstructions } from './instructions';\nimport { makeTaskTool, makeTaskBatchTool } from './subagent';\nimport { loadAgents } from './agents';\nimport { checkpointTools } from './OverlayFilesystem';\nimport type { Hooks } from './hooks';\nimport { PermissionPolicy, planMode, composeHooks } from './permissions';\nimport { forComponent } from './logging';\nimport { checkSyntax } from './lint';\nimport { reasoningToChatFragment, type ReasoningEffort } from './reasoning';\n\nconst log = forComponent('Agent');\n\n/** A thrown provider error that is really a cancel (barge-in / Ctrl-C), not a crash. The abort flag can\n * lag the throw under a race, so we message-match across providers: fetch AbortError, Node ABORT_ERR,\n * groq/SDK \"operation was aborted\", ConnectError [canceled]. Mirrors the CLI's cursor-abort guard. */\nfunction isAbortError(err: unknown): boolean {\n const e = err as any;\n const blob = `${e?.message ?? ''} ${e?.name ?? ''} ${e?.code ?? ''} ${e?.cause?.name ?? ''}`;\n return /operation was aborted|\\bAbortError\\b|ABORT_ERR|\\[canceled\\]/i.test(blob);\n}\n\nexport interface RunResult {\n text: string;\n steps: number;\n /** Why the loop ended. The middle group are automatic kill-switches (budget/abuse guards). */\n finishReason: 'stop' | 'max_steps' | 'budget' | 'timeout' | 'loop' | 'max_tool_calls' | 'aborted' | 'error';\n messages: Message[];\n /** Accumulated token usage across all turns (non-stream path). With prompt caching,\n * promptTokens includes cached reads/writes; the cache splits ride along for exact pricing. */\n usage?: { promptTokens: number; completionTokens: number; totalTokens: number; cacheCreationTokens?: number; cacheReadTokens?: number };\n /** True if ANY turn's usage was estimated (provider gave none) rather than exact — lets the UI mark cost `~`. */\n usageEstimated?: boolean;\n error?: unknown;\n}\n\nexport class AgentOptions {\n /** Any ai.libx.js AIClient (or a FakeAIClient). */\n ai!: ChatLike;\n /** Filesystem backend — MemFilesystem, NodeDiskFilesystem, IndexedDbFilesystem, …\n * OPTIONAL: if omitted, the agent lazily defaults to a JAILED real disk rooted at `process.cwd()`\n * (secrets hidden by DEFAULT_DENY) — resolved via a dynamic node import at first run, so the edge/\n * browser build (which always passes its own fs) never pulls in `node:fs`. Pass `fs` explicitly to\n * use any other backend (and to keep full control of the jail). */\n fs?: IFilesystem;\n model = 'anthropic/claude-sonnet-4-6';\n systemPrompt =\n 'You are a coding agent operating on a virtual filesystem. Use the `bash` tool to explore (ls, grep, find, cat) and the `Read`/`Edit` tools to view and modify files. Always Read a file before Editing it — and before overwriting it with `Write` or a whole-file `ApplyEdits`: Write replaces the ENTIRE file, so blindly writing over an existing one destroys its unseen contents. If a file already exists, Read it first, then merge your changes (or Edit the specific part). When multiple tool calls are independent (e.g. several Reads or Greps with no dependency between them), issue them together in a single turn rather than one at a time. When the task is complete, reply with a short summary and make no further tool calls.\\n' +\n 'Recovery: every turn\\'s file changes are checkpointed. If the user asks to undo/revert/recover edits (including a file you overwrote), tell them to run `/rewind` (or `/undo` for the last turn) to restore the working tree — checkpoints cover files you edited even in .gitignored dirs. You cannot run `/rewind` yourself; surface it as the recovery path.\\n' +\n 'When working with a knowledge base or document workspace: use `RepoMap` with scope \"docs\" to see all document headings and summaries (orient first); use `MemorySearch` to find memories by content when you don\\'t know the exact slug; use `Recall` with multiple slugs to batch-load related facts in one call. Prefer targeted loads over reading everything — orient → search → load → act.';\n tools: AgentTool[] = defaultTools();\n maxSteps = 25;\n // --- automatic kill-switches (always on; protect the API budget against runaway loops/abuse) ---\n /** Hard ceiling on accumulated tokens (prompt+completion) across the run; cache READS count at 0.1×\n * (their real price) so a fat cached context doesn't trip the guard on healthy turns. 0 = unbounded. */\n maxTokens = 200_000;\n /** Wall-clock ceiling in ms for the whole run. 0 = unbounded. */\n timeoutMs = 120_000;\n /** Stop if the identical tool-call batch (name+args) repeats this many times in a row. 0 = off. */\n maxRepeats = 3;\n /** Cumulative cap on tool calls dispatched across the run. 0 = unbounded. */\n maxToolCalls = 100;\n /** External cancellation — abort the loop between steps (e.g. a UI \"Cancel\" button). */\n signal?: AbortSignal;\n /** 0 = never trim. Otherwise cap the messages sent per turn (system + most recent). */\n maxContextMessages = 0;\n /** Note-taking: keep the most-recent N tool-result outputs verbatim; collapse OLDER ones to a one-line\n * stub in the sent context (the model already consumed them — it can re-Read/re-run). The stored\n * transcript is never mutated. 0 = keep all verbatim. */\n keepToolOutputs = 0;\n /** Token-aware backstop (~4 chars/token estimate). After note-taking, drop oldest messages from the\n * sent context until the estimate is under this ceiling (pairing-safe). 0 = off. */\n maxContextTokens = 0;\n /** Pagination ceiling for a SINGLE tool result (bytes). A result over this is cropped to page 1 with\n * a marker telling the model it was cropped (refine the query, or page further). Guards against one\n * Grep/Read/MCP call blowing the whole context window. 0 = off. Default 60k (~15k tokens). */\n maxToolResultBytes = 60_000;\n /** Hook to handle an oversized tool result instead of the default lossy crop: receives the FULL output\n * and returns the (cropped) string to put in context — e.g. spill to scratch and return a recoverable,\n * paginated stub. Called only when a result exceeds `maxToolResultBytes`. */\n capToolResult?: (full: string, info: { tool: string; args: any }) => string | Promise<string>;\n /** VFS dir(s) of skills (`<dir>/<id>/SKILL.md`). If set: inject a catalog + add the `Skill` tool. Multiple dirs are merged (first wins on name collisions). */\n skillsDir?: string | string[];\n /** VFS dir(s) of slash-command templates (`<dir>/<name>.md`). If set: inject a catalog + add the `SlashCommand` tool. Multiple dirs are merged (first wins). */\n commandsDir?: string | string[];\n /** VFS dir(s) of memory (`<dir>/MEMORY.md`). If set: inject the index at run start (persistence = backend).\n * Multiple dirs are merged (reads search all; writes go to first). */\n memoryDir?: string | string[];\n /** User-scope memory dir for global facts (type=user/feedback). Remember routes by type when set. */\n memoryUserDir?: string;\n /** Filenames to discover as project instructions (e.g. `AGENT.md`, `AGENTS.md`, `CLAUDE.md`).\n * Walks the VFS tree and merges all found files (general → specific, like Claude Code).\n * `true` (default) = auto-discover standard names. `string[]` = custom names. `false` = skip. */\n instructionFiles: boolean | string[] = true;\n /** Host interaction channel (human-in-the-loop). If set: adds the `AskUserQuestion` tool. */\n host?: HostBridge;\n /** Add the `AskUserQuestion` tool when a host is present (default true). Set false for an agent that\n * must never block a turn on a structured question — e.g. a voice reflex that confirms inline. */\n askUserQuestion = true;\n /** Deterministic interception points around tool execution (pre/post/stop). */\n hooks?: Hooks;\n /** If true: add the `Task` tool so the agent can spawn depth-limited child agents over the VFS. */\n subagents = false;\n /** VFS dir of typed-subagent defs (`<dir>/<name>.md`). If set with `subagents`: inject a catalog + enable the `Task` `agentType` param. */\n agentsDir?: string;\n /** Current recursion depth (0 = top-level); spawned children run at depth+1. */\n depth = 0;\n /** Hard ceiling on subagent nesting (beyond it the `Task` tool refuses to spawn). */\n maxDepth = 2;\n /** Stream tokens from the model. Takes effect only with a `host.notify`; off => current (non-stream) behavior. */\n stream = false;\n /** Fold the dropped middle of an over-long transcript into a synthetic summary (edge-safe, no LLM). Off => drop-oldest. */\n compaction?: { maxMessages: number };\n /** Add `Checkpoint`/`Rollback` tools (requires the fs to be an OverlayFilesystem). */\n checkpoints = false;\n /** Enable `bash({background:true})` + JobOutput/JobStatus/JobKill — sandbox background jobs (overlay-isolated,\n * committed on completion, drained at turn end). Useful when the VFS backend is slow (remote) or for sub-agents. */\n backgroundJobs = false;\n /** Plan mode: block mutating tools until the agent calls `ExitPlanMode` (host-approved). */\n planMode = false;\n /** Permission policy gating each tool call (allow / ask / deny). */\n permissions?: PermissionPolicy;\n /** Opt-in syntax guardrail: refuse to persist a syntactically-broken code-file write/edit. Default off. */\n lintOnWrite?: boolean;\n /** Optional PDF text extraction for Read on .pdf files (node hosts wire pdftotext); absent => Read explains. */\n pdfText?: (path: string) => Promise<string>;\n /** Opt-in: after a write-class tool runs, run `command` over the VFS and append any failure to the tool result.\n * `tools` defaults to ['Write','Edit','MultiEdit','ApplyEdits']. */\n autoTest?: { command: string; tools?: string[] };\n /** Provider-specific options forwarded to ai.chat() (e.g. cursor mcpServers, cwd). */\n providerOptions?: Record<string, unknown>;\n /** Prompt caching (providers that support it, e.g. Anthropic): cache tools/system/conversation\n * prefix across the loop's steps — reads cost 0.1x, writes 1.25x. A multi-step agent loop\n * re-sends its whole prefix every step, so this is a large net cost cut. Default on. */\n promptCache = true;\n /** Tool selection mode: 'auto' = model decides (needed for Groq); undefined = provider default. */\n toolChoice?: 'auto' | 'required' | 'none';\n /** Extended-thinking / reasoning effort, normalized across providers (anthropic, openai).\n * `'off'`/undefined = none; `'low'|'medium'|'high'` or a raw token budget. Mapped to the\n * provider-specific request shape via {@link reasoningToChatFragment}; explicit `providerOptions` wins. */\n reasoning?: ReasoningEffort;\n}\n\n/**\n * The agentic loop: chat() -> dispatch tool_calls over the VFS -> thread results\n * back -> repeat until the model stops (no tool calls) or maxSteps is hit.\n */\nexport class Agent {\n public options: AgentOptions;\n public transcript: Message[] = [];\n private ctx!: ToolContext; // built in the ctor when `fs` is provided, else lazily in ensureFs()\n private lastTrimNotified = 0; // last auto-trim drop count surfaced via host.notify (dedup)\n private activeTools: AgentTool[] = [];\n private activeHooks?: Hooks; // composed: user hooks + plan-mode + permissions\n private prepared = false; // memo guard: prompt/tools/plan-state built once per conversation\n private systemPromptCache = ''; // the assembled system prompt from the last prepare()\n private started = false; // session-start lifecycle hook fires once per conversation\n private parkedMs = 0; // cumulative time blocked on the HUMAN (permission/plan prompts) — excluded from the timeout\n\n /** Time a human-blocking await (a permission/plan prompt) and bank it in `parkedMs` so idle prompt\n * time never trips the wall-clock kill-switch. The agent did no work while parked on the user. */\n private async park<T>(p: Promise<T>): Promise<T> {\n const t = Date.now();\n try { return await p; } finally { this.parkedMs += Date.now() - t; }\n }\n\n /** Force the next `send()`/`run()` to rebuild the system prompt, tools, plan-mode and permission hooks\n * from `options` — apply mid-conversation changes to `planMode`/`permissions`/`model` etc. (prepare()\n * is otherwise memoized per conversation). */\n reprepare(): void { this.prepared = false; }\n\n /** Tools injected via addTools(); kept separate from options.tools so prepare() rebuilds don't drop them. */\n private injectedTools: AgentTool[] = [];\n\n /** Current tool surface for hosts/UIs (configured + injected, deduped by name) — options.tools\n * alone misses addTools()-injected ones (e.g. MCP servers mounted after startup). */\n get toolNames(): string[] {\n return [...new Set([...(this.options.tools ?? []), ...this.injectedTools].map((t) => t.name))];\n }\n\n /** Inject tools into a running agent (e.g. dynamically mounted MCP servers). Takes effect on the next turn\n * and survives prepare() rebuilds (reprepare(), new conversations). */\n addTools(tools: AgentTool[]): void {\n this.injectedTools.push(...tools);\n this.activeTools.push(...tools);\n }\n\n /** Remove tools by name from a running agent. Returns the count removed. Also filters\n * `options.tools` — otherwise a constructor-passed tool resurrects on the next prepare()\n * rebuild (and re-adding it via addTools() would then DUPLICATE it in the wire schema). */\n removeTools(names: Set<string> | string[]): number {\n const s = names instanceof Set ? names : new Set(names);\n const before = this.activeTools.length;\n this.activeTools = this.activeTools.filter((t) => !s.has(t.name));\n this.injectedTools = this.injectedTools.filter((t) => !s.has(t.name));\n if (this.options.tools) this.options.tools = this.options.tools.filter((t) => !s.has(t.name));\n return before - this.activeTools.length;\n }\n\n constructor(options?: Partial<AgentOptions>) {\n this.options = { ...new AgentOptions(), ...options } as AgentOptions;\n if (this.options.fs) this.buildCtx(); // fs provided → build the tool context now (sync, unchanged behavior)\n }\n\n /** Build the tool context from the resolved fs + options. Idempotent-safe: called once (ctor or ensureFs). */\n private buildCtx(): void {\n this.ctx = makeContext(this.options.fs!, this.options.host);\n this.ctx.signal = this.options.signal; // expose run-cancellation to abort-aware tools (e.g. real shell)\n if (this.options.lintOnWrite) this.ctx.lint = checkSyntax; // opt-in syntax guardrail\n if (this.options.pdfText) this.ctx.pdfText = this.options.pdfText; // host-wired PDF text extraction (Read on .pdf)\n this.ctx.ai = this.options.ai; // expose model to tools that run their own LLM pass (e.g. Review)\n this.ctx.model = this.options.model;\n this.ctx.parkHuman = (p) => this.park(p); // route interactive tools' human-waits into the parked-time accumulator\n if (this.options.backgroundJobs) this.ctx.jobs = new SandboxJobRegistry(); // enables bash({background:true})\n }\n\n /**\n * Resolve the filesystem + build the tool context if the ctor couldn't (no `fs` was passed). The disk\n * default lives HERE, not in the ctor: the ctor can't await, and we must avoid a STATIC `node:fs` import\n * in the core (edge/browser would break). The dynamic import only fires when `fs` is omitted — edge code\n * always passes its own `MemFilesystem`, so the node module is never reached. Default = jailed disk @ cwd.\n */\n private async ensureFs(): Promise<void> {\n if (this.ctx) return; // already built (fs was provided to the ctor, or a prior run resolved it)\n if (!this.options.fs) {\n const { NodeDiskFilesystem } = await import('./NodeDiskFilesystem');\n const { JailedFilesystem } = await import('./JailedFilesystem');\n const disk = new NodeDiskFilesystem(process.cwd());\n await disk.init();\n this.options.fs = new JailedFilesystem(disk); // DEFAULT_DENY hides secrets out of the box\n log.info(`no fs provided — defaulting to jailed real disk at ${process.cwd()}`);\n }\n this.buildCtx();\n }\n\n /**\n * Assemble the system prompt + active tools/hooks ONCE per conversation (memoized).\n * `run()` resets the memo to start fresh; `send()` reuses it, so multi-turn state —\n * plan-mode approval, the tool set, the skills/commands/memory snapshot — stays stable\n * across turns (and the frozen prompt pairs well with prompt caching). Does NOT touch\n * the transcript; `run`/`send` own that.\n */\n private async prepare(taskHint?: string): Promise<string> {\n if (this.prepared) return this.systemPromptCache;\n const o = this.options;\n const fs = o.fs!; // resolved by ensureFs() before any run()/send() reaches prepare()\n let systemPrompt = o.systemPrompt;\n let tools = o.tools;\n if (o.instructionFiles !== false) {\n const names = Array.isArray(o.instructionFiles) ? o.instructionFiles : undefined;\n const ins = await loadInstructions(fs, names);\n if (ins) systemPrompt += '\\n\\n' + ins;\n }\n if (o.memoryDir) {\n // taskHint floats the most task-relevant learnings to the top of a large index; the rest\n // collapse to slugs (still Recall-able) — bounds tokens as learnings accumulate over time.\n const { index, tools: memTools } = await loadMemory(fs, o.memoryDir, { relevanceHint: taskHint, userDir: o.memoryUserDir });\n if (index) systemPrompt += '\\n\\n' + index; // hot: compact (ranked) index always injected\n tools = [...tools, ...memTools]; // cold: Recall (pull fact) + Remember (persist fact)\n }\n // Merged slash namespace (CC parity): each tool cross-resolves into the other registry on a\n // miss, so `/x` works whether x is a command or a skill regardless of which tool the model picks.\n const skillsDir = o.skillsDir, commandsDir = o.commandsDir;\n if (skillsDir) {\n // taskHint floats the most relevant skills to the top of a large catalog; full set stays loadable by name.\n const sibling = commandsDir\n ? async (name: string) => {\n const c = (await scanCommands(fs, commandsDir)).find((x) => x.name === name);\n return c ? { path: c.path, stripFrontmatter: true } : undefined;\n }\n : undefined;\n const { catalog, tool } = await loadSkills(fs, skillsDir, { relevanceHint: taskHint, sibling });\n if (catalog) systemPrompt += '\\n\\n' + catalog;\n if (tool) tools = [...tools, tool];\n }\n if (commandsDir) {\n const sibling = skillsDir\n ? async (name: string) => {\n const s = (await scanSkills(fs, skillsDir)).find((x) => x.name === name);\n return s ? { path: s.path, stripFrontmatter: false } : undefined;\n }\n : undefined;\n const { catalog, tool } = await loadCommands(fs, commandsDir, { relevanceHint: taskHint, sibling });\n if (catalog) systemPrompt += '\\n\\n' + catalog;\n if (tool) tools = [...tools, tool];\n }\n if (o.host && o.askUserQuestion) tools = [...tools, askUserQuestionTool];\n if (o.subagents) {\n let agents: Awaited<ReturnType<typeof loadAgents>>['agents'] | undefined;\n if (o.agentsDir) {\n const loaded = await loadAgents(fs, o.agentsDir);\n agents = loaded.agents;\n if (loaded.catalog) systemPrompt += '\\n\\n' + loaded.catalog;\n }\n const taskOpts = { ai: o.ai, model: o.model, fs, depth: o.depth, maxDepth: o.maxDepth, agents, hooks: o.hooks };\n tools = [...tools, makeTaskTool(taskOpts), makeTaskBatchTool(taskOpts)];\n }\n if (o.checkpoints) tools = [...tools, ...checkpointTools()];\n if (this.ctx.jobs) tools = [...tools, ...makeJobTools(this.ctx.jobs)]; // JobOutput/JobStatus/JobKill\n const plan = o.planMode ? planMode({ host: o.host }) : undefined; // gates mutating tools until approved\n if (plan) tools = [...tools, plan.tool];\n this.activeHooks = composeHooks(o.hooks, plan?.hooks, o.permissions?.hooks());\n this.activeTools = [...tools, ...this.injectedTools]; // injected (addTools) survive the rebuild\n this.systemPromptCache = systemPrompt;\n this.prepared = true;\n return systemPrompt;\n }\n\n /** Single-shot: reset all per-conversation state and run `task` to completion. `task` may be plain\n * text or multimodal content parts (text + images). */\n async run(task: MessageContent): Promise<RunResult> {\n await this.ensureFs(); // resolve the disk default (if no fs was passed) before prepare reads o.fs\n this.prepared = false; // fresh conversation → rebuild prompt + tools + plan-mode state\n this.started = false;\n const systemPrompt = await this.prepare(contentText(task)); // task text hints catalog relevance\n const startCtx = await this.fireSessionStart(); // [lifecycle] once-per-session context injection\n const userContent = await this.applyPromptSubmit(task); // [lifecycle] per-turn prompt rewrite (text only)\n this.transcript = [\n { role: 'system', content: systemPrompt + (startCtx ? '\\n\\n' + startCtx : '') },\n { role: 'user', content: userContent },\n ];\n return this.runLoop();\n }\n\n /** Apply onUserPromptSubmit to a turn: rewrite plain text; pass multimodal content through untouched. */\n private async applyPromptSubmit(task: MessageContent): Promise<MessageContent> {\n return typeof task === 'string' ? await this.fireUserPromptSubmit(task) : task;\n }\n\n /** Fire onSessionStart once per conversation; returns any injected context. */\n private async fireSessionStart(): Promise<string | undefined> {\n if (this.started) return undefined;\n this.started = true;\n const ctx = await this.activeHooks?.onSessionStart?.();\n return typeof ctx === 'string' && ctx ? ctx : undefined;\n }\n\n /** Fire onUserPromptSubmit; returns the (possibly rewritten) prompt text. */\n private async fireUserPromptSubmit(task: string): Promise<string> {\n const r = await this.activeHooks?.onUserPromptSubmit?.(task);\n return typeof r === 'string' ? r : task;\n }\n\n /**\n * Multi-turn: continue the existing conversation by appending a user turn instead of\n * resetting — this is what makes an interactive REPL feel like one conversation. The\n * leading system message is (re)synced to the current prompt, so a resumed session whose\n * tools were rebuilt gets a matching catalog rather than a stale one.\n */\n async send(task: MessageContent): Promise<RunResult> {\n await this.ensureFs(); // resolve the disk default (if no fs was passed) before prepare reads o.fs\n const systemPrompt = await this.prepare(contentText(task)); // first turn's task hints catalog relevance; frozen thereafter (memoized → cache-stable)\n const startCtx = await this.fireSessionStart(); // [lifecycle] first send() of a fresh agent counts as session start\n const userContent = await this.applyPromptSubmit(task);\n const sys = systemPrompt + (startCtx ? '\\n\\n' + startCtx : '');\n if (this.transcript[0]?.role === 'system') this.transcript[0] = { role: 'system', content: sys };\n else this.transcript.unshift({ role: 'system', content: sys });\n this.transcript.push({ role: 'user', content: userContent });\n return this.runLoop();\n }\n\n /**\n * Fold the conversation in place (manual `/compact`): keep the system message + the\n * most-recent window, summarizing the dropped middle (deterministic, no LLM call).\n * No-op when the transcript already fits. Returns the number of messages removed.\n * `focus` (e.g. from `/compact keep the API details`) preserves matching lines from the\n * dropped span verbatim in the summary, instead of losing them to the generic recap.\n */\n compactNow(maxMessages = 12, focus?: string): number {\n const max = Math.max(2, maxMessages);\n if (this.transcript.length <= max) return 0;\n void this.activeHooks?.onPreCompact?.(this.transcript); // [lifecycle] observe before folding (fire-and-forget)\n const before = this.transcript.length;\n this.transcript = compact(this.transcript, max, focus);\n return before - this.transcript.length;\n }\n\n private async runLoop(): Promise<RunResult> {\n const o = this.options;\n const wireTools = toWireTools(this.activeTools);\n // Stream only when explicitly requested AND a host can render deltas; else stay on the non-stream path.\n const useStream = o.stream === true && typeof o.host?.notify === 'function';\n let steps = 0;\n const usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0 };\n let usageEstimated = false; // flips true the first turn a provider returns no usage and we estimate\n const start = Date.now();\n this.parkedMs = 0; // reset per run: only THIS run's human-wait is excluded from the timeout\n let toolCallsTotal = 0; // cumulative tool calls dispatched\n let lastFp = ''; // fingerprint of the previous tool-call batch\n let repeats = 0; // consecutive identical batches\n // Single exit for every kill-switch: warn + return a result carrying the reason.\n const kill = (finishReason: RunResult['finishReason']): RunResult => {\n log.warn(`kill-switch: ${finishReason} (steps=${steps}, tokens=${usage.totalTokens}, budgetTokens=${Math.round(usage.totalTokens - 0.9 * usage.cacheReadTokens)}, ms=${Date.now() - start - this.parkedMs}${this.parkedMs ? ` +${this.parkedMs} parked` : ''})`);\n this.ctx.jobs?.killAll(); // abort background jobs (don't commit) — a budget/timeout kill shouldn't leak writes\n return { text: lastAssistantText(this.transcript), steps, finishReason, messages: this.transcript, usage, usageEstimated };\n };\n\n while (true) {\n if (o.signal?.aborted) return kill('aborted');\n if (steps >= o.maxSteps) return kill('max_steps');\n if (o.timeoutMs && Date.now() - start - this.parkedMs >= o.timeoutMs) return kill('timeout'); // active wall-clock: idle prompt time excluded\n // Budget = cost proxy, not raw volume: cache reads are ~10% of fresh-token price, and a fat cached\n // context (MCP schemas + big tool results) re-counts every step — at full weight a healthy ~25k-ctx\n // session dies near step 8. Weighting reads at 0.1 keeps runaway protection (fresh tokens count full).\n const budgetTokens = usage.totalTokens - 0.9 * usage.cacheReadTokens;\n if (o.maxTokens && budgetTokens >= o.maxTokens) return kill('budget');\n steps++;\n this.options.host?.notify?.({ kind: 'turn_start', message: `step ${steps}` });\n\n let res: ChatResponse;\n const sent = this.trimContext(); // the exact context sent this turn (reused for usage estimation)\n // Normalized reasoning → provider request shape; explicit providerOptions overrides the derived one.\n const frag = reasoningToChatFragment(o.model, o.reasoning);\n // Cursor is an agent runtime — bridge host tools via IPC-based toolExecutor callback.\n const isCursorWithTools = o.model.startsWith('cursor/') && wireTools.length > 0;\n const cursorPo = isCursorWithTools ? {\n toolExecutor: async (name: string, args: Record<string, any>) => {\n const tc = { id: `cursor-${Date.now()}`, type: 'function' as const, function: { name, arguments: JSON.stringify(args) } };\n const raw = await this.dispatch(tc);\n return typeof raw === 'string' ? raw : raw.text;\n },\n } : undefined;\n const reasonOpts = {\n ...frag,\n ...(o.promptCache ? { promptCache: true } : {}),\n ...(o.providerOptions || cursorPo ? { providerOptions: { ...frag.providerOptions, ...o.providerOptions, ...cursorPo } } : {}),\n };\n try {\n // One step = one model call; a TRANSIENT network drop (mid-stream or pre-flight) retries the\n // step from the last committed transcript state instead of failing the whole turn. Server-side\n // transient HTTP errors (5xx/408/overloaded) retry too; 4xx like rate limits are NOT retried\n // here — the AIClient's own rate-limit retry handles those.\n for (let attempt = 0; ; attempt++) {\n try {\n if (useStream) {\n const r = await o.ai.chat({ model: o.model, messages: sent, tools: wireTools, stream: true, signal: o.signal, ...(o.toolChoice ? { toolChoice: o.toolChoice } : {}), ...reasonOpts });\n res = await this.consumeStream(r as AsyncIterable<StreamChunk>);\n } else {\n const r = await o.ai.chat({ model: o.model, messages: sent, tools: wireTools, stream: false, signal: o.signal, ...(o.toolChoice ? { toolChoice: o.toolChoice } : {}), ...reasonOpts });\n res = r as ChatResponse;\n }\n break;\n } catch (err) {\n const sc = (err as any)?.statusCode;\n const serverSide = sc >= 500 || sc === 408 || /Service Unavailable|overloaded|Internal server error|Bad gateway|Gateway time/i.test(String((err as any)?.message ?? ''));\n const network = !sc && /ECONNRESET|ECONNREFUSED|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|EPIPE|socket hang up|fetch failed|network|terminated|UND_ERR/i.test(String((err as any)?.message ?? (err as any)?.code ?? err));\n const transient = !o.signal?.aborted && !isAbortError(err) && attempt < 2 && (network || serverSide);\n if (!transient) throw err;\n const waitMs = 1000 * (attempt + 1);\n log.warn(`network drop mid-step (${(err as any)?.message ?? err}) — retrying in ${waitMs}ms`);\n o.host?.notify?.({ kind: 'retry', message: `connection dropped — retrying step (#${attempt + 1})` });\n await new Promise((r) => setTimeout(r, waitMs));\n }\n }\n } catch (err) {\n // A budget-exhausted signal (e.g. proxy 429) is a clean stop, not a crash:\n // preserve the transcript so the run can be resumed once the cap is raised.\n if ((err as any)?.code === 'budget') return kill('budget');\n // An aborted fetch surfaces as a thrown provider error. The signal flag can LAG the throw under\n // a barge-in race (the controller fires, the provider rejects, but o.signal.aborted hasn't\n // settled yet), so match the provider's abort message too — else a clean cancel is logged as a\n // crash AND its \"operation was aborted\" string leaks onto the spoken/utterance line.\n if (o.signal?.aborted || isAbortError(err)) return kill('aborted');\n // surface the provider's human message (non-enumerable → lost by JSON.stringify); the bare\n // {code,statusCode} alone reads as a malformed request when it's often billing/quota (e.g. a 400\n // whose body is \"credit balance is too low\"). The raw response body carries that detail —\n // extract it onto the error so hosts/logs see WHY, not just the status code.\n const body = (err as any)?.body ?? (err as any)?.response?.data ?? (err as any)?.error;\n // try/catch: a circular body must not crash the error handler itself\n let bodyStr: string | undefined;\n try { bodyStr = body && typeof body !== 'string' ? JSON.stringify(body).slice(0, 2000) : (body as string | undefined); } catch { bodyStr = undefined; }\n if (bodyStr && err instanceof Error && !err.message.includes(bodyStr)) (err as any).detail = bodyStr;\n log.error(`chat() failed: ${(err as any)?.message ?? err}${bodyStr ? ` — ${bodyStr}` : ''}`, err);\n return { text: '', steps, finishReason: 'error', messages: this.transcript, usage, usageEstimated, error: err };\n }\n // Cancelled mid-response → end the turn as 'aborted', not as a clean 'stop' on the partial reply.\n if (o.signal?.aborted) return kill('aborted');\n\n // ai.libx.js streaming doesn't surface token usage — estimate (~4 chars/token) so cost reporting\n // AND the maxTokens budget kill-switch still work when streaming (the CLI default). Non-stream\n // responses carry exact usage and are left untouched.\n if (!res.usage) {\n const promptTokens = estimateTokens(sent);\n const completionTokens = Math.ceil((contentText(res.content).length + (res.toolCalls ? JSON.stringify(res.toolCalls).length : 0)) / 4);\n res.usage = { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens };\n usageEstimated = true;\n }\n if (res.usage) {\n usage.promptTokens += res.usage.promptTokens ?? 0; usage.completionTokens += res.usage.completionTokens ?? 0; usage.totalTokens += res.usage.totalTokens ?? 0;\n usage.cacheCreationTokens += (res.usage as any).cacheCreationTokens ?? 0; usage.cacheReadTokens += (res.usage as any).cacheReadTokens ?? 0;\n }\n const toolCalls = res.toolCalls ?? [];\n // A turn with no tool calls AND no text is dead air — don't commit it to the transcript or count\n // it as a real response (it bills tokens but says/does nothing). The voice layer repairs the silence.\n const emptyTurn = toolCalls.length === 0 && contentText(res.content ?? '').trim() === '';\n if (!emptyTurn) {\n this.transcript.push({\n role: 'assistant',\n content: res.content ?? '',\n ...(toolCalls.length ? { tool_calls: toolCalls } : {}),\n });\n }\n\n if (toolCalls.length === 0) {\n log.verbose(`completed in ${steps} step(s)`);\n await this.ctx.jobs?.drain(); // let background jobs finish + commit before we call the run done (no lost writes)\n await this.activeHooks?.onStop?.(res.content ?? ''); // [hooks] fire once on clean stop\n return { text: res.content ?? '', steps, finishReason: 'stop', messages: this.transcript, usage, usageEstimated };\n }\n\n // loop detection: the model emitting the same tool-call batch over and over.\n const fp = toolCalls.map((tc) => tc.function.name + ':' + (tc.function.arguments ?? '')).join('|');\n repeats = fp === lastFp ? repeats + 1 : 1;\n lastFp = fp;\n if (o.maxRepeats && repeats >= o.maxRepeats) return kill('loop');\n\n toolCallsTotal += toolCalls.length;\n if (o.maxToolCalls && toolCallsTotal > o.maxToolCalls) return kill('max_tool_calls');\n\n for (const tc of toolCalls) {\n if (o.signal?.aborted) return kill('aborted'); // cancelled mid-batch → don't run the rest\n const raw = await this.dispatch(tc);\n let content: MessageContent;\n if (typeof raw === 'string') { content = raw; }\n else {\n const parts: ContentPart[] = [{ type: 'text', text: raw.text }];\n for (const img of raw.images ?? []) parts.push(imagePart(`data:${img.mimeType};base64,${img.data}`));\n content = parts;\n }\n this.transcript.push({ role: 'tool', tool_call_id: tc.id, name: tc.function.name, content });\n }\n }\n }\n\n /**\n * Drain a streamed chat() response: emit each text delta to the host\n * (`{kind:'text_delta'}`) and fold all chunks back into the single\n * ChatResponse the non-stream path would have returned.\n */\n private async consumeStream(stream: AsyncIterable<StreamChunk>): Promise<ChatResponse> {\n let content = '';\n let finishReason: string | undefined;\n let toolCalls: ToolCall[] | undefined;\n let usage: ChatResponse['usage'];\n for await (const chunk of stream) {\n if (this.options.signal?.aborted) break; // cancelled → stop emitting now; breaking also closes the stream\n // [G3] surface extended-thinking as a distinct channel (never folded into `content` or the\n // persisted transcript — it's a transient UI stream, not history). Provider-dependent field.\n if (chunk.reasoningContent) this.options.host!.notify!({ kind: 'thinking_delta', message: chunk.reasoningContent });\n if (chunk.content) {\n content += chunk.content;\n this.options.host!.notify!({ kind: 'text_delta', message: chunk.content });\n }\n if (chunk.finishReason) finishReason = chunk.finishReason;\n if (chunk.toolCalls?.length) toolCalls = chunk.toolCalls; // accumulated, latest wins\n if (chunk.usage) usage = chunk.usage; // exact usage on the terminal chunk (providers that report it; else runLoop estimates)\n }\n return { content, ...(finishReason ? { finishReason } : {}), ...(toolCalls ? { toolCalls } : {}), ...(usage ? { usage } : {}) };\n }\n\n private async dispatch(tc: ToolCall): Promise<string | { text: string; images?: { mimeType: string; data: string }[] }> {\n const tool = this.activeTools.find((t) => t.name === tc.function.name);\n // [render] Parse args first but DON'T early-return on failure. An unknown-tool or bad-args call\n // (e.g. a model hallucinating a `task` tool) must still flow through the same preToolUse/notify/\n // postToolUse path as a real call — otherwise the host draws no `⚙` line and the UI looks silently\n // stuck. On parse failure keep the raw string as `args` so it still renders, and fail below.\n let args: any = {};\n let earlyError: string | undefined;\n if (!tool) earlyError = `Error: unknown tool '${tc.function.name}'`;\n try {\n args = tc.function.arguments ? JSON.parse(tc.function.arguments) : {};\n } catch (e) {\n args = tc.function.arguments;\n earlyError ??= `Error: invalid JSON arguments for ${tc.function.name}: ${String(e)}`;\n }\n const hooks = this.activeHooks; // [hooks] composed: user + plan-mode + permissions\n const call = { name: tc.function.name, args };\n const meta = { id: tc.id }; // [G4] stable per-call id so a host can correlate result↔call without serial-order assumptions\n // preToolUse is where a permission policy blocks on the user's Yes/No/Always answer — park that wait\n // so a long-standing approval prompt doesn't accrue toward the timeout kill-switch.\n const decision = await this.park(Promise.resolve(hooks?.preToolUse?.(call, meta))); // [hooks] guard before run\n if (decision?.block) {\n const blocked = `Blocked by hook: ${decision.reason ?? 'no reason given'}`;\n log.debug(`${tc.function.name} -> ${blocked}`);\n await hooks?.postToolUse?.(call, blocked, meta); // [hooks] observe the block too\n return blocked;\n }\n this.options.host?.notify?.({ kind: 'tool_use', id: tc.id ?? '', name: tc.function.name, input: args });\n // [render] surface the unknown-tool / bad-args failure through the normal result path (postToolUse\n // renders the body; notify carries isError) so it's visible instead of vanishing.\n if (earlyError) {\n log.debug(`${tc.function.name} -> ${earlyError}`);\n await hooks?.postToolUse?.(call, earlyError, meta);\n this.options.host?.notify?.({ kind: 'tool_result', id: tc.id ?? '', output: earlyError, isError: true });\n return earlyError;\n }\n let result: string;\n let images: { mimeType: string; data: string }[] | undefined;\n let threw = false;\n try {\n log.debug(`${tc.function.name}(${tc.function.arguments})`);\n // [hooks] per-call incremental-output channel: streaming tools (real Shell) push chunks via\n // ctx.emit → onToolOutput. Dispatch is serial, so binding on the shared ctx is safe; cleared\n // in finally so a straggler emit after the call settles is a silent no-op.\n this.ctx.emit = hooks?.onToolOutput ? (chunk: string) => { try { hooks.onToolOutput!(call, chunk, meta); } catch (e) { log.debug(`onToolOutput hook error: ${e}`); } } : undefined;\n const raw = await tool!.run(args, this.ctx);\n if (typeof raw === 'string') { result = raw; }\n else { result = raw.text; images = raw.images; }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n log.debug(`${tc.function.name} -> error: ${msg}`);\n result = `Error: ${msg}`;\n threw = true;\n } finally {\n this.ctx.emit = undefined; // the call settled — late emits (stray timers) go nowhere\n }\n // autoTest (opt-in): after a successful write-class tool, run a VFS test command and surface any failure\n // to the model in-band — so it never burns a turn re-running tests itself. Skipped on block/throw.\n if (!threw) result = await this.maybeAutoTest(tc.function.name, result);\n // Image-only result (e.g. a screenshot tool): give it a text marker so hosts don't render\n // \"(no output)\" and the model has a text anchor next to the image part.\n if (images?.length && !result) result = `[${images.length} image${images.length > 1 ? 's' : ''} attached]`;\n // Pagination ceiling: a single oversized result (a 1MB Grep, a huge Read/MCP payload) would otherwise\n // blow the context window. Crop to page 1 with a marker; a capToolResult hook can spill it losslessly.\n const cap = this.options.maxToolResultBytes ?? 0;\n if (!threw && cap > 0 && result.length > cap) {\n const info = { tool: tc.function.name, args };\n result = this.options.capToolResult ? await this.options.capToolResult(result, info) : cropResult(result, cap);\n }\n await hooks?.postToolUse?.(call, result, meta); // [hooks] observe the result\n this.options.host?.notify?.({ kind: 'tool_result', id: tc.id ?? '', output: result, isError: threw });\n if (images?.length) {\n for (const img of images) {\n this.options.host?.notify?.({ kind: 'tool_result_image', id: tc.id ?? '', dataUrl: `data:${img.mimeType};base64,${img.data}` });\n }\n }\n return images?.length ? { text: result, images } : result;\n }\n\n private static readonly WRITE_CLASS = ['Write', 'Edit', 'MultiEdit', 'ApplyEdits'];\n\n /** Append an autoTest failure section to a write-class tool result, if configured. */\n private async maybeAutoTest(toolName: string, result: string): Promise<string> {\n const at = this.options.autoTest;\n if (!at?.command) return result;\n const set = at.tools ?? Agent.WRITE_CLASS;\n if (!set.includes(toolName)) return result;\n const r = await this.ctx.exec.execute(at.command);\n if (r.exitCode === 0) return result; // silent on pass — avoid noise\n const out = truncateOutput(((r.output ?? '') + (r.error ?? '')).replace(/\\n+$/, ''));\n return `${result}\\n\\n[autoTest] \\`${at.command}\\` FAILED (exit ${r.exitCode}):\\n${out}`;\n }\n\n /**\n * Shape the per-turn context (a VIEW — the stored transcript is never mutated). Layered, each off by default:\n * 1. coarse reduction — `compaction` (fold the dropped middle into a synthetic summary) OR\n * `maxContextMessages` (pure drop-oldest), keeping the system message + most-recent window.\n * 2. note-taking (`keepToolOutputs`) — collapse all-but-the-recent-N tool-result bodies to one-line stubs\n * (kills \"immortal tool results\": a big Read/Grep stops costing its full weight once it's old).\n * 3. token-aware backstop (`maxContextTokens`) — drop oldest messages until under an estimated token ceiling.\n * With every knob off, returns the transcript unchanged (same reference).\n */\n trimContext(): Message[] {\n const o = this.options;\n const m = this.transcript;\n let out: Message[] | null = null;\n if (o.compaction?.maxMessages && m.length > o.compaction.maxMessages) out = compact(m, o.compaction.maxMessages);\n else if (o.maxContextMessages && m.length > o.maxContextMessages) out = dropOldest(m, o.maxContextMessages);\n if (o.keepToolOutputs) out = stubOldToolResults(out ?? m, o.keepToolOutputs);\n if (o.maxContextTokens) {\n const pre = (out ?? m).length;\n out = fitTokenBudget(out ?? m, o.maxContextTokens);\n // Token-cap trims used to be SILENT — surface a one-line notice (deduped per drop count)\n // so the user knows context was auto-compacted, not mysteriously forgotten.\n const dropped = pre - out.length;\n if (dropped > 0 && dropped !== this.lastTrimNotified) {\n this.lastTrimNotified = dropped;\n o.host?.notify?.({ kind: 'compaction', message: `context full — auto-trimmed ${dropped} oldest message(s) to fit ~${Math.round(o.maxContextTokens / 1000)}k tokens` });\n }\n }\n // Unconditional correctness net: a tool_result whose tool_call parent isn't in the sent set is a\n // hard API 400 (INVALID_REQUEST). Orphans arise from compaction boundaries OR a resumed transcript\n // that was folded in a prior session — strip them no matter which knobs are on. Same ref if clean.\n return dropOrphanToolResults(out ?? m);\n }\n}\n\n/** system (if any) + the most-recent (max - head) messages — pure drop-oldest. */\nfunction dropOldest(m: Message[], max: number): Message[] {\n const head = m[0]?.role === 'system' ? [m[0]] : [];\n return [...head, ...m.slice(-(max - head.length))];\n}\n\n/** ~4 chars/token estimate over content + serialized tool_calls. */\nfunction estimateTokens(m: Message[]): number {\n let chars = 0;\n for (const x of m) chars += contentText(x.content).length + (x.tool_calls ? JSON.stringify(x.tool_calls).length : 0);\n return Math.ceil(chars / 4);\n}\n\n/**\n * Note-taking: keep the most-recent `keep` tool-result messages verbatim; collapse older, bulky ones to a\n * one-line stub that still names the tool + its file (so the model can re-pull). Structure (role/tool_call_id/\n * name) is preserved so tool_use↔tool_result pairing stays valid; only `content` is replaced, on COPIES.\n */\n/** Crop an oversized tool result to page 1 (cut at a line boundary) with a marker telling the model it\n * was cropped and how to proceed. The default (lossy) handler when no capToolResult hook spills it. */\nexport function cropResult(result: string, cap: number): string {\n const head = result.slice(0, cap);\n const nl = head.lastIndexOf('\\n');\n const page = nl > cap * 0.5 ? head.slice(0, nl) : head; // prefer a clean line cut if not too early\n const omitted = result.length - page.length;\n return `${page}\\n\\n[output cropped — showing ${page.length} of ${result.length} bytes; ${omitted} omitted. ` +\n `This is page 1. Refine your query/command to narrow it, or call the tool again with a tighter scope to see more.]`;\n}\n\nfunction stubOldToolResults(messages: Message[], keep: number): Message[] {\n const meta = new Map<string, string | undefined>(); // tool_call_id -> path arg (for the pointer)\n for (const msg of messages)\n for (const tc of msg.tool_calls ?? []) {\n let path: string | undefined;\n try { const a = tc.function.arguments ? JSON.parse(tc.function.arguments) : {}; if (typeof a.path === 'string') path = a.path; } catch { /* args not JSON */ }\n meta.set(tc.id, path);\n }\n const toolIdx = messages.map((x, i) => (x.role === 'tool' ? i : -1)).filter((i) => i >= 0);\n const stub = new Set(toolIdx.slice(0, Math.max(0, toolIdx.length - keep)));\n if (stub.size === 0) return messages;\n return messages.map((x, i) => {\n const text = contentText(x.content);\n if (!stub.has(i) || text.length <= 120) return x; // small results aren't worth stubbing\n const where = meta.get(x.tool_call_id ?? '');\n const lines = text.split('\\n').length;\n return { ...x, content: `[${x.name ?? 'tool'}${where ? ` ${where}` : ''} output elided — ${lines} lines; re-run the tool to view]` };\n });\n}\n\n/** All tool_call ids present on assistant messages — one O(n) pass instead of a scan per result. */\nconst callIdSet = (msgs: Message[]): Set<string> => {\n const ids = new Set<string>();\n for (const m of msgs) if (m.role === 'assistant') for (const tc of m.tool_calls ?? []) ids.add(tc.id);\n return ids;\n};\n\n/** Drop every orphan tool_result (one whose tool_call isn't in the set) — sending one is a hard API\n * 400. Anywhere in the sequence, not just the head. Returns the same array reference when clean. */\nfunction dropOrphanToolResults(messages: Message[]): Message[] {\n const ids = callIdSet(messages);\n const ok = (m: Message) => m.role !== 'tool' || ids.has(m.tool_call_id ?? '');\n return messages.every(ok) ? messages : messages.filter(ok);\n}\n\n/**\n * Token-aware backstop: keep the system head, drop oldest body messages until under `maxTokens`.\n * The window may empty entirely (a single message can exceed the whole budget), and it is never\n * left starting on an ORPHAN tool_result (one whose tool_call isn't in the window) — that would\n * break tool_use↔tool_result pairing and get rejected by the API. If even [system] is over budget\n * (e.g. a huge memory index), we can't trim further — warn; the hard `maxTokens` kill-switch is the real guard.\n */\nfunction fitTokenBudget(messages: Message[], maxTokens: number): Message[] {\n // Incremental accounting: estimate each message once, subtract as we drop — O(n), not O(n²)\n // (re-estimating the whole window per dropped message walks every char repeatedly).\n const per = messages.map((x) => estimateTokens([x]));\n let total = per.reduce((a, b) => a + b, 0);\n if (total <= maxTokens) return messages;\n const head = messages[0]?.role === 'system' ? [messages[0]] : [];\n let from = head.length; // body = messages[from..]\n while (from < messages.length && total > maxTokens) total -= per[from++];\n const ids = callIdSet(messages.slice(from));\n while (from < messages.length && messages[from].role === 'tool' && !ids.has(messages[from].tool_call_id ?? '')) total -= per[from++];\n if (total > maxTokens)\n log.warn(`context ~${total} tok still over maxContextTokens=${maxTokens} after trimming (system head can't be dropped)`);\n return [...head, ...messages.slice(from)];\n}\n\n/** system (if any) + synthetic summary of the dropped middle + most-recent window; fits within `max`. */\nfunction compact(m: Message[], max: number, focus?: string): Message[] {\n const hasSystem = m[0]?.role === 'system';\n const head = hasSystem ? [m[0]] : [];\n // Reserve one slot for the summary, the rest for the most-recent window. Bound the tail\n // to the post-head slice so a short transcript (max >= length) can't re-include the head.\n const tailCount = Math.max(1, max - head.length - 1);\n const tail = m.slice(head.length).slice(-tailCount);\n const dropped = m.slice(head.length, m.length - tail.length);\n if (dropped.length === 0) return [...head, ...tail];\n return [...head, { role: 'system', content: summarize(dropped, focus) }, ...tail];\n}\n\n/** Lightweight, deterministic, LLM-free recap of a span of messages. */\nfunction summarize(messages: Message[], focus?: string): string {\n const tools = new Set<string>();\n const files = new Set<string>();\n let lastAssistant = '';\n for (const msg of messages) {\n for (const tc of msg.tool_calls ?? []) {\n tools.add(tc.function.name);\n try {\n const args = tc.function.arguments ? JSON.parse(tc.function.arguments) : {};\n if (typeof args.path === 'string') files.add(args.path);\n } catch {\n /* arguments not JSON — skip file extraction */\n }\n }\n if (msg.role === 'assistant' && msg.content) lastAssistant = contentText(msg.content);\n }\n const lines = [`[summary of ${messages.length} earlier message(s)]`];\n if (tools.size) lines.push(`tools used: ${[...tools].join(', ')}`);\n if (files.size) lines.push(`files touched: ${[...files].join(', ')}`);\n if (lastAssistant) lines.push(`last assistant: ${lastAssistant}`);\n // Focused compaction: keep lines from the dropped span that mention any focus keyword,\n // verbatim (bounded), so \"/compact keep the API details\" doesn't lose them to the recap.\n if (focus?.trim()) {\n const words = focus.toLowerCase().split(/\\s+/).filter((w) => w.length > 2);\n const kept: string[] = [];\n outer: for (const msg of messages) {\n if (msg.role === 'tool') continue; // tool bodies are bulk noise; user/assistant text carries the decisions\n for (const line of contentText(msg.content).split('\\n')) {\n const l = line.toLowerCase();\n if (line.trim() && words.some((w) => l.includes(w))) {\n kept.push(line.trim().slice(0, 200));\n if (kept.length >= 12) break outer;\n }\n }\n }\n if (kept.length) lines.push(`preserved (re: ${focus.trim()}):`, ...kept.map((l) => ` ${l}`));\n }\n return lines.join('\\n');\n}\n\nfunction lastAssistantText(messages: Message[]): string {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === 'assistant') return contentText(messages[i].content);\n }\n return '';\n}\n","/**\n * Sandbox background jobs — the in-process twin of `ShellJobRegistry` (src/tools.shell.ts), but for work\n * that runs *inside* the sandbox rather than as an OS child process. Backs `bash({background:true})` and\n * (later) background sub-agents.\n *\n * IMPORTANT — this is concurrency via async-I/O interleaving, NOT parallelism. The runtime is single\n * threaded: a CPU-bound JS command still blocks. Real overlap only happens when a job *awaits* — i.e. a\n * remote VFS backend (BodDbFilesystem, network per read) or a sub-agent (model calls). Over a pure in-mem\n * MemFilesystem, backgrounding a fast command buys nothing (the tool description says so).\n *\n * The registry is kind-AGNOSTIC: it tracks any async producer's lifecycle + tail output. Overlay isolation\n * and commit-on-success are the *producer's* responsibility (IoC), so the registry stays a pure tracker.\n */\nexport type JobStatus = 'running' | 'done' | 'error' | 'killed';\n\n/** A producer: does the actual work, may stream progress via `onChunk`, returns its final text. */\nexport interface JobFn {\n (ctx: { signal: AbortSignal; onChunk: (s: string) => void }): Promise<string>;\n}\n\ninterface Job {\n kind: string;\n label: string;\n status: JobStatus;\n buf: string;\n ctl: AbortController;\n promise: Promise<void>;\n}\n\n/** Per-session registry of in-process background jobs. Bounded tail buffer; abortable; drainable at turn end. */\nexport class SandboxJobRegistry {\n private jobs = new Map<string, Job>();\n private seq = 0;\n constructor(private maxBuffer = 256 * 1024) {}\n\n /** Start `fn` in the background and return a job id immediately (does not await completion). */\n start(fn: JobFn, opts: { kind?: string; label?: string } = {}): string {\n const id = `job-${++this.seq}`;\n const ctl = new AbortController();\n const onChunk = (s: string) => { job.buf = (job.buf + s).slice(-this.maxBuffer); }; // ring: keep the tail\n const job: Job = { kind: opts.kind ?? 'task', label: opts.label ?? '', status: 'running', buf: '', ctl, promise: Promise.resolve() };\n job.promise = fn({ signal: ctl.signal, onChunk }).then(\n (res) => { if (job.status === 'running') { job.status = 'done'; if (res) onChunk(res); } },\n (e: any) => { if (job.status === 'running') { job.status = 'error'; onChunk(`\\n[error] ${e?.message ?? e}`); } },\n );\n this.jobs.set(id, job);\n return id;\n }\n\n /** Tail output for a job (null = no such job, '' = job exists but no output yet). */\n output(id: string): string | null { return this.jobs.get(id)?.buf ?? (this.jobs.has(id) ? '' : null); }\n\n status(id: string): { status: JobStatus; bytes: number } | null {\n const j = this.jobs.get(id);\n return j ? { status: j.status, bytes: j.buf.length } : null;\n }\n\n list(): Array<{ id: string; kind: string; label: string; status: JobStatus }> {\n return [...this.jobs].map(([id, j]) => ({ id, kind: j.kind, label: j.label, status: j.status }));\n }\n\n /** Signal cancel (the producer decides what abort means — e.g. skip the overlay commit). */\n kill(id: string): boolean {\n const j = this.jobs.get(id);\n if (!j) return false;\n if (j.status === 'running') { j.ctl.abort(); j.status = 'killed'; }\n return true;\n }\n\n killAll(): void { for (const id of this.jobs.keys()) this.kill(id); }\n\n /** Await every still-running job. Called at turn end so a job's committed writes aren't lost from view\n * just because the model didn't poll it. Returns the ids that were still running when drain began. */\n async drain(): Promise<string[]> {\n const pending = [...this.jobs].filter(([, j]) => j.status === 'running').map(([id]) => id);\n await Promise.all([...this.jobs.values()].map((j) => j.promise));\n return pending;\n }\n}\n\nconst NO_JOB = (id: string) =>\n `Error: no background job '${id}'. Use JobStatus with no id to list jobs, or start one with bash({background:true}).`;\n\n/** Companion tools (JobOutput / JobStatus / JobKill) over a SandboxJobRegistry. */\nexport function makeJobTools(registry: SandboxJobRegistry): import('./tools').AgentTool[] {\n return [\n {\n name: 'JobOutput',\n description: 'Read the accumulated output (tail) of a background job by id (from bash({background:true})).',\n parameters: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } },\n async run({ id }) {\n const out = registry.output(String(id));\n if (out == null) return NO_JOB(String(id));\n const st = registry.status(String(id))!;\n return `[${st.status}]\\n${out.replace(/\\n+$/, '') || '(no output yet)'}`;\n },\n },\n {\n name: 'JobStatus',\n description: 'Status of a background job (running/done/killed/error). Omit `id` to list all jobs.',\n parameters: { type: 'object', properties: { id: { type: 'string' } } },\n async run({ id }) {\n if (!id) {\n const jobs = registry.list();\n return jobs.length ? jobs.map((j) => `${j.id} ${j.status} ${j.kind}${j.label ? ' ' + j.label : ''}`).join('\\n') : '(no background jobs)';\n }\n const st = registry.status(String(id));\n return st ? `${st.status} · ${st.bytes} byte(s) buffered` : NO_JOB(String(id));\n },\n },\n {\n name: 'JobKill',\n description: 'Stop a running background job by id (the job is cancelled; its overlay writes are NOT committed).',\n parameters: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } },\n async run({ id }) {\n return registry.kill(String(id)) ? `Killed job ${id}.` : NO_JOB(String(id));\n },\n },\n ];\n}\n","import type { AgentTool, ToolContext, HostBridge, UserQuestion } from './tools';\n\nexport type { HostBridge, UserQuestion } from './tools';\n\n/**\n * `AskUserQuestion` tool — lets the model pose a structured choice to a human.\n * Delegates to `ctx.host.ask`. Registered only when a HostBridge is provided\n * (autonomous runs don't see it), so it never dead-ends a headless agent.\n */\nexport const askUserQuestionTool: AgentTool = {\n name: 'AskUserQuestion',\n description:\n 'Ask the user a multiple-choice question when a decision is genuinely theirs to make (ambiguous requirement, a fork you cannot resolve from context). Returns their selection.',\n parameters: {\n type: 'object',\n required: ['question', 'options'],\n properties: {\n question: { type: 'string' },\n header: { type: 'string', description: 'short label for the question' },\n options: {\n type: 'array',\n items: { type: 'object', required: ['label'], properties: { label: { type: 'string' }, description: { type: 'string' } } },\n },\n multiSelect: { type: 'boolean' },\n },\n },\n async run(args: UserQuestion, ctx: ToolContext) {\n if (!ctx.host?.ask) {\n const fallback = args.options?.[0]?.label ?? '';\n return `No interactive user is available — proceed using your best judgment.${fallback ? ` (Closest default: \"${fallback}\")` : ''}`;\n }\n const answer = ctx.host.ask(args); // human-blocking — park it so the wait doesn't count toward the timeout\n return ctx.parkHuman ? ctx.parkHuman(answer) : answer;\n },\n};\n\n/** Deterministic HostBridge for tests/dev: scripts answers + records what was asked. */\nexport class ScriptedHostBridge implements HostBridge {\n public asked: UserQuestion[] = [];\n public confirms: string[] = [];\n public events: Array<{ kind: string; message: string; data?: unknown }> = [];\n constructor(private answers: string[] = [], private confirmDefault = true) {}\n async ask(q: UserQuestion): Promise<string> {\n this.asked.push(q);\n return this.answers.shift() ?? q.options[0]?.label ?? '';\n }\n async confirm(prompt: string): Promise<boolean> {\n this.confirms.push(prompt);\n return this.confirmDefault;\n }\n notify(event: { kind: string; message: string; data?: unknown }): void {\n this.events.push(event);\n }\n}\n\n/** Node CLI HostBridge: prompts on stdin. (node-only host adapter; not edge-safe by design.) */\nexport class ConsoleHostBridge implements HostBridge {\n async ask(q: UserQuestion): Promise<string> {\n const rl = await import('node:readline/promises');\n const io = rl.createInterface({ input: process.stdin, output: process.stdout });\n try {\n const lines = [q.header ? `\\n[${q.header}] ${q.question}` : `\\n${q.question}`];\n q.options.forEach((o, i) => lines.push(` ${i + 1}) ${o.label}${o.description ? ' — ' + o.description : ''}`));\n const ans = await io.question(lines.join('\\n') + '\\n> ');\n const n = Number(ans.trim());\n return Number.isInteger(n) && q.options[n - 1] ? q.options[n - 1].label : ans.trim();\n } finally {\n io.close();\n }\n }\n async confirm(prompt: string): Promise<boolean> {\n const rl = await import('node:readline/promises');\n const io = rl.createInterface({ input: process.stdin, output: process.stdout });\n try {\n const ans = await io.question(`\\n${prompt} [y/N] `);\n return /^y(es)?$/i.test(ans.trim());\n } finally {\n io.close();\n }\n }\n notify(event: { kind: string; message: string }): void {\n console.error(`[${event.kind}] ${event.message}`);\n }\n}\n","/**\n * Lexical relevance — no deps, deterministic, edge-safe. Ranks catalog entries (skills,\n * commands, memories, docs) by a task hint so a LARGE catalog doesn't dump every entry into\n * the prompt. TF-IDF weighted: rare terms in the corpus score higher than common ones.\n */\n\nconst STOP = new Set([\n 'the', 'and', 'for', 'with', 'that', 'this', 'from', 'into', 'your', 'you', 'are', 'was', 'will',\n 'use', 'using', 'run', 'add', 'fix', 'make', 'file', 'files', 'code', 'please', 'need', 'want', 'should', 'all',\n]);\n\n/** Lowercased alphanumeric tokens of length ≥ 3, minus a few stopwords. */\nexport function tokenize(s: string): Set<string> {\n const out = new Set<string>();\n for (const w of String(s ?? '').toLowerCase().match(/[a-z0-9]+/g) ?? []) {\n if (w.length >= 3 && !STOP.has(w)) out.add(w);\n }\n return out;\n}\n\n/** Build IDF weights from a corpus of texts. Rare terms get higher weight. */\nexport function idfWeights(corpus: string[]): Map<string, number> {\n const N = corpus.length;\n if (N === 0) return new Map();\n const df = new Map<string, number>();\n for (const doc of corpus) for (const t of tokenize(doc)) df.set(t, (df.get(t) ?? 0) + 1);\n const idf = new Map<string, number>();\n for (const [t, n] of df) idf.set(t, Math.log((N + 1) / (n + 1)) + 1); // smooth IDF\n return idf;\n}\n\n/** TF-IDF weighted relevance score. Without IDF, falls back to flat token overlap (backward-compatible). */\nexport function relevanceScore(text: string, queryTokens: Set<string>, idf?: Map<string, number>): number {\n if (queryTokens.size === 0) return 0;\n const t = tokenize(text);\n let score = 0;\n for (const q of queryTokens) if (t.has(q)) score += idf?.get(q) ?? 1;\n return score;\n}\n\n/**\n * Split `items` into the `k` most relevant to `query` (by TF-IDF overlap with `text(item)`)\n * and the rest, preserving each item's original order within its group. Returns everything in\n * `kept` (empty `rest`) when `items.length <= k` or `query` is blank — so it's a no-op for\n * small lists. When `corpus` is provided, builds IDF weights for better ranking.\n */\nexport function topByRelevance<T>(items: T[], query: string, text: (x: T) => string, k: number, corpus?: string[]): { kept: T[]; rest: T[] } {\n if (!Number.isInteger(k) || k < 1) return { kept: items, rest: [] }; // invalid k → no-op (keep all), never hide\n if (items.length <= k || !query.trim()) return { kept: items, rest: [] };\n const q = tokenize(query);\n if (q.size === 0) return { kept: items.slice(0, k), rest: items.slice(k) };\n const idf = corpus?.length ? idfWeights(corpus) : undefined;\n const scored = items.map((x, i) => ({ i, s: relevanceScore(text(x), q, idf) }));\n scored.sort((a, b) => b.s - a.s || a.i - b.i); // best score first; stable by original index\n const keep = new Set(scored.slice(0, k).map((e) => e.i));\n return { kept: items.filter((_, i) => keep.has(i)), rest: items.filter((_, i) => !keep.has(i)) };\n}\n","/**\n * Lean YAML-frontmatter parsing (no YAML dependency) shared by skills + commands.\n * Handles single-line values AND block scalars (`>`, `>-`, `|`, `|-`, …) — CC skills\n * often fold long descriptions across indented lines, which a single-line regex truncates.\n */\n\n/** Extract the `---`-delimited frontmatter block + the body that follows it. */\nexport function splitFrontmatter(md: string): { block: string; body: string } {\n const m = md.match(/^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n?/);\n return { block: m ? m[1] : '', body: (m ? md.slice(m[0].length) : md).trim() };\n}\n\n/** Grab a scalar field from a frontmatter block by key (case-insensitive). Folds block scalars to one line. */\nexport function grabField(block: string, key: string): string | undefined {\n const lines = block.split('\\n');\n const i = lines.findIndex((l) => new RegExp(`^${key}\\\\s*:`, 'i').test(l));\n if (i < 0) return undefined;\n const inline = lines[i].replace(new RegExp(`^${key}\\\\s*:\\\\s*`, 'i'), '');\n // Block scalar (`>`/`|` with optional chomping `-`/`+`): gather the following more-indented lines.\n if (/^[>|][+-]?\\s*$/.test(inline)) {\n const folded: string[] = [];\n for (let j = i + 1; j < lines.length && /^\\s+\\S/.test(lines[j]); j++) folded.push(lines[j].trim());\n return folded.join(' ').trim() || undefined; // fold to one line (catalog descriptions are single-line)\n }\n return inline.trim().replace(/^[\"']|[\"']$/g, '') || undefined;\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\nimport type { AgentTool, ToolContext } from './tools';\nimport { topByRelevance } from './relevance';\nimport { splitFrontmatter, grabField } from './frontmatter';\n\n/** Above this many commands, the catalog shows full entries only for the most task-relevant; the rest list as names. */\nconst MAX_CATALOG = 25;\n\nexport interface CommandInfo {\n name: string;\n description: string;\n path: string;\n}\n\n/**\n * Resolves a name in the *other* half of the merged slash namespace (CC parity: `/x` is one\n * namespace whether `x` is a `commands/x.md` or a `skills/x/SKILL.md`). On a miss in its own\n * registry, a tool calls this to find the sibling and learn how to expand it. Injected by the\n * caller (Agent.prepare) so commands.ts and skills.ts stay mutually decoupled (no circular import).\n */\nexport type SiblingResolver = (name: string) => Promise<{ path: string; stripFrontmatter: boolean } | undefined>;\n\n/** Parse a command template's `description:` frontmatter + return the body that follows. */\nfunction parseFrontmatter(md: string): { description?: string; body: string } {\n const { block, body } = splitFrontmatter(md);\n return { description: grabField(block, 'description'), body };\n}\n\n/**\n * Expand a command template's argument placeholders:\n * - `$ARGUMENTS` → all args (every occurrence)\n * - `$1`…`$9` → positional args (whitespace-split; missing → empty)\n * If the body has neither placeholder, `args` is appended as a trailing block (back-compat).\n */\nexport function expandTemplate(body: string, args: string): string {\n if (!/\\$ARGUMENTS|\\$[1-9]/.test(body)) return args ? `${body}\\n\\n${args}` : body;\n const toks = args.trim() ? args.trim().split(/\\s+/) : [];\n return body.split('$ARGUMENTS').join(args).replace(/\\$([1-9])/g, (_m, n) => toks[Number(n) - 1] ?? '');\n}\n\n/** Inline `@path` references (CC-style) with the file's contents, fenced. Non-existent paths stay literal. */\nasync function embedFiles(text: string, fs: IFilesystem): Promise<string> {\n const refs = [...new Set([...text.matchAll(/(?:^|\\s)@(\\S+)/g)].map((m) => m[1]))];\n let out = text;\n for (const ref of refs) {\n try {\n const content = await fs.readFile(ref);\n out = out.split('@' + ref).join(`\\n\\n--- @${ref} ---\\n${content}\\n--- end @${ref} ---\\n`);\n } catch { /* not a readable file — leave the literal @ref (could be an email, decorator, etc.) */ }\n }\n return out;\n}\n\n/**\n * Read a slash entry's file and return its expanded text: arg placeholders filled, then `@file`\n * refs embedded. `stripFrontmatter` drops the YAML head (commands feed only their body); skills\n * feed the whole SKILL.md (frontmatter is part of the instructions). Shared by commands + skills\n * so both halves of the merged namespace expand identically (CC parity).\n */\nexport async function expandEntry(\n fs: IFilesystem,\n path: string,\n args: string,\n opts: { stripFrontmatter?: boolean } = {},\n): Promise<string> {\n const raw = await fs.readFile(path);\n const text = opts.stripFrontmatter ? parseFrontmatter(raw).body : raw;\n return embedFiles(expandTemplate(text, args), fs);\n}\n\n/** Read a command file and return its expanded body: arg placeholders filled, then `@file` refs embedded. */\nexport async function expandCommand(fs: IFilesystem, cmd: CommandInfo, args: string): Promise<string> {\n return expandEntry(fs, cmd.path, args, { stripFrontmatter: true });\n}\n\n/**\n * Discover slash commands under `dir` (each `<dir>/<name>.md`) and produce:\n * - `catalog`: a names+descriptions block for the system prompt,\n * - `tool`: a `SlashCommand` tool that returns a command's expanded template body.\n *\n * Commands are reusable prompt templates (like Claude Code slash commands) — just\n * VFS files. The template body is returned (user args appended, and `$ARGUMENTS`\n * substituted if present) so the model can act on it. Mirrors loadSkills.\n */\n/** Scan `dir`(s) for `<dir>/<name>.md` command templates (first dir wins on duplicate names). */\nexport async function scanCommands(fs: IFilesystem, dir: string | string[]): Promise<CommandInfo[]> {\n const commands: CommandInfo[] = [];\n const seen = new Set<string>();\n for (const d of Array.isArray(dir) ? dir : [dir]) {\n if (!await fs.exists(d)) continue;\n for (const entry of await fs.readDir(d)) {\n if (!entry.endsWith('.md')) continue;\n const name = entry.replace(/\\.md$/, '');\n if (seen.has(name)) continue; // first dir wins\n seen.add(name);\n const path = `${d}/${entry}`;\n const fm = parseFrontmatter(await fs.readFile(path));\n commands.push({ name, description: fm.description || '', path });\n }\n }\n return commands;\n}\n\nexport async function loadCommands(\n fs: IFilesystem,\n dir: string | string[],\n opts: { relevanceHint?: string; max?: number; sibling?: SiblingResolver } = {},\n): Promise<{ commands: CommandInfo[]; catalog: string; tool?: AgentTool }> {\n const commands = await scanCommands(fs, dir);\n if (commands.length === 0) return { commands, catalog: '' };\n\n // At scale, show full entries only for the most task-relevant; the rest list as names (still\n // runnable by name). No-op for small catalogs (≤ max) or no hint, so the prefix stays stable.\n const { kept, rest } = topByRelevance(commands, opts.relevanceHint ?? '', (c) => `${c.name} ${c.description}`, opts.max ?? MAX_CATALOG);\n const catalog =\n '## Slash commands (reusable prompt templates)\\n' +\n kept.map((c) => `- **/${c.name}** — ${c.description} (\\`${c.path}\\`)`).join('\\n') +\n (rest.length ? `\\n- (${rest.length} more, names only — call \\`SlashCommand\\` to run): ${rest.map((c) => c.name).join(', ')}` : '') +\n '\\nTo run one, call the `SlashCommand` tool with its name (and optional `args`); it returns the expanded template to act on.';\n\n const tool: AgentTool = {\n name: 'SlashCommand',\n description: 'Run a slash command (or skill) by name — returns its expanded prompt template/instructions (with your `args` substituted/appended). Resolves both the command and skill namespaces. Use when a task matches a listed command or skill.',\n parameters: {\n type: 'object',\n required: ['name'],\n properties: { name: { type: 'string' }, args: { type: 'string', description: 'arguments to fill the template' } },\n },\n async run({ name, args }, ctx: ToolContext) {\n const slug = String(name ?? '').replace(/^\\//, '');\n let c = commands.find((x) => x.name === slug);\n let fresh: CommandInfo[] | undefined;\n if (!c) { // miss → rescan: commands created mid-conversation are runnable without a reprepare\n fresh = await scanCommands(ctx.fs, dir);\n c = fresh.find((x) => x.name === slug);\n if (c) commands.push(c);\n }\n if (c) return expandCommand(ctx.fs, c, String(args ?? ''));\n // still a miss → merged namespace: try the sibling (skills) registry before failing.\n const sib = await opts.sibling?.(slug);\n if (sib) return expandEntry(ctx.fs, sib.path, String(args ?? ''), { stripFrontmatter: sib.stripFrontmatter });\n return `Error: no command or skill named '${slug}'. Available commands: ${(fresh ?? []).map((x) => x.name).join(', ') || '(none)'}`;\n },\n };\n return { commands, catalog, tool };\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\nimport type { AgentTool, ToolContext } from './tools';\nimport { topByRelevance } from './relevance';\nimport { splitFrontmatter, grabField } from './frontmatter';\nimport { expandEntry, type SiblingResolver } from './commands';\n\n/** Above this many skills, the catalog shows full entries only for the most task-relevant; the rest list as names. */\nconst MAX_CATALOG = 25;\n\nexport interface SkillInfo {\n name: string;\n description: string;\n path: string;\n}\n\n/** Parse a SKILL.md's `name:` / `description:` frontmatter (falls back to scanning the head if undelimited). */\nfunction parseFrontmatter(md: string): { name?: string; description?: string } {\n const { block } = splitFrontmatter(md);\n const b = block || md.slice(0, 600);\n return { name: grabField(b, 'name'), description: grabField(b, 'description') };\n}\n\n/**\n * Discover skills under `dir` (each `<dir>/<id>/SKILL.md`) and produce:\n * - `catalog`: a names+descriptions block for the system prompt,\n * - `tool`: a `Skill` tool that returns a skill's full SKILL.md (progressive disclosure).\n *\n * Skills are just VFS files — the Read tool already gives progressive disclosure; this\n * adds the catalog + a convenience tool. (Executable skills can be `bash`-exec'd: wcli\n * runs JS files from the VFS as commands.)\n */\n/** Scan `dir`(s) for `<dir>/<id>/SKILL.md` entries (first dir wins on duplicate ids). */\nexport async function scanSkills(fs: IFilesystem, dir: string | string[]): Promise<SkillInfo[]> {\n const skills: SkillInfo[] = [];\n const seen = new Set<string>();\n for (const d of Array.isArray(dir) ? dir : [dir]) {\n if (!await fs.exists(d)) continue;\n for (const entry of await fs.readDir(d)) {\n if (seen.has(entry)) continue; // first dir wins (our .agent/ before .claude/)\n const skillMd = `${d}/${entry}/SKILL.md`;\n if (await fs.exists(skillMd)) {\n seen.add(entry);\n const fm = parseFrontmatter(await fs.readFile(skillMd));\n skills.push({ name: fm.name || entry, description: fm.description || '', path: skillMd });\n }\n }\n }\n return skills;\n}\n\nexport async function loadSkills(\n fs: IFilesystem,\n dir: string | string[],\n opts: { relevanceHint?: string; max?: number; sibling?: SiblingResolver } = {},\n): Promise<{ skills: SkillInfo[]; catalog: string; tool?: AgentTool }> {\n const skills = await scanSkills(fs, dir);\n if (skills.length === 0) return { skills, catalog: '' };\n\n // At scale, show full entries only for the most task-relevant; the rest list as names (still\n // loadable by name). No-op for small catalogs (≤ max) or no hint, so the prefix stays stable.\n const { kept, rest } = topByRelevance(skills, opts.relevanceHint ?? '', (s) => `${s.name} ${s.description}`, opts.max ?? MAX_CATALOG);\n const catalog =\n '## Skills (load one before acting on a matching task)\\n' +\n kept.map((s) => `- **${s.name}** — ${s.description} (\\`${s.path}\\`)`).join('\\n') +\n (rest.length ? `\\n- (${rest.length} more, names only — call \\`Skill\\` to load): ${rest.map((s) => s.name).join(', ')}` : '') +\n '\\nWhen a task matches a skill, call the `Skill` tool with its name to load its full instructions.';\n\n const tool: AgentTool = {\n name: 'Skill',\n description: 'Load a skill (or slash command) by name — returns its full instructions (SKILL.md / expanded template), with any `args` substituted/appended. Resolves both the skill and command namespaces. Use when a task matches a listed skill or command.',\n parameters: { type: 'object', required: ['name'], properties: { name: { type: 'string' }, args: { type: 'string', description: 'arguments to fill the template' } } },\n async run({ name, args }, ctx: ToolContext) {\n const slug = String(name ?? '').replace(/^\\//, '');\n let s = skills.find((x) => x.name === slug);\n let fresh: SkillInfo[] | undefined;\n if (!s) { // miss → rescan: skills created mid-conversation are loadable without a reprepare\n fresh = await scanSkills(ctx.fs, dir);\n s = fresh.find((x) => x.name === slug);\n if (s) skills.push(s);\n }\n if (s) return expandEntry(ctx.fs, s.path, String(args ?? '')); // skill: whole SKILL.md (frontmatter kept)\n // still a miss → merged namespace: try the sibling (commands) registry before failing.\n const sib = await opts.sibling?.(slug);\n if (sib) return expandEntry(ctx.fs, sib.path, String(args ?? ''), { stripFrontmatter: sib.stripFrontmatter });\n return `Error: no skill or command named '${slug}'. Available skills: ${(fresh ?? []).map((x) => x.name).join(', ') || '(none)'}`;\n },\n };\n return { skills, catalog, tool };\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\nimport type { AgentTool, ToolContext } from './tools';\nimport { mkdirp } from './tools.structured';\nimport { topByRelevance, tokenize, relevanceScore, idfWeights } from './relevance';\nimport { splitFrontmatter } from './frontmatter';\n\nconst MAX_INDEX = 25;\nconst MAX_INDEX_LINES = 200;\nconst MAX_INDEX_BYTES = 25_000;\n\n/** Behavioral guidance injected alongside the memory index — adapted from CC's battle-tuned prose, for our tool-based workflow. */\nexport const MEMORY_PROMPT =\n '## Memory guidelines\\n' +\n '**When to Remember:** user corrections (\"no, do X instead\"), preferences (\"I prefer Y\"), project constraints, recurring gotchas, ' +\n 'role/context (\"I\\'m a data scientist\"), workflow patterns confirmed by the user. Capture the WHY, not just the what.\\n' +\n '**When NOT to Remember:** task-specific scratch, transient state, things derivable from code/git, conversation filler, ' +\n 'anything already in instruction files. If removing the memory wouldn\\'t change future behavior, don\\'t save it.\\n' +\n '**Types** (pass to Remember — this determines where the memory is stored):\\n' +\n '- `user` — role, preferences, knowledge level, collaboration style (GLOBAL — follows you across projects)\\n' +\n '- `feedback` — corrections, what to avoid/repeat, with WHY (GLOBAL)\\n' +\n '- `project` — ongoing work, goals, constraints, deadlines (LOCAL to this project; convert relative dates to absolute)\\n' +\n '- `reference` — pointers to external resources, URLs, vendor docs (LOCAL to this project)\\n' +\n '**Before acting on a recalled memory:** verify it\\'s still true — a memory naming a file/function/flag is a claim ' +\n 'from when it was written. Grep/read to confirm before recommending. Stale memory → update via Remember (same slug overwrites).\\n' +\n '**Dedup:** before writing, check if a similar memory exists (Recall or MemorySearch). Update the existing one rather than creating duplicates.\\n' +\n 'Call `Recall` with a slug (or multiple slugs/a pattern) to load full bodies when relevant.\\n' +\n 'Call `MemorySearch` with a query to find memories by content when you don\\'t know the slug.\\n' +\n 'Call `Remember` to persist a durable fact for future sessions.';\n\n/** Voice-specific memory guidance — shorter, spoken-interaction tuned. */\nexport const VOICE_MEMORY_PROMPT =\n 'You have Remember and Recall tools — use them directly, no delegation needed.\\n' +\n 'IMPLICIT CAPTURE: when the user shares their name, role, a preference, a correction (\"no, do X instead\"), ' +\n 'or a project constraint — call Remember immediately without announcing it. Natural memory, not a ceremony.\\n' +\n 'For explicit \"remember X\" requests, also call Remember directly and confirm briefly (\"got it\").\\n' +\n 'Do NOT remember: transient task details, conversation filler, things you\\'d forget in a real conversation.\\n' +\n 'Keep it invisible: never announce \"saving to memory\" or list what you remembered unless asked.\\n' +\n 'For anything requiring files, shell, or web — still Act.';\n\n/**\n * Load memory for injection at run start (the recall step), with progressive disclosure:\n * - `index`: the compact `<dir>/MEMORY.md` index, injected into the system prompt — cheap,\n * always-hot. Each line points at a fact file the agent can pull on demand.\n * - `tools`: `Recall` (load one fact body on demand — keeps facts COLD until needed) and\n * `Remember` (persist a durable fact + index pointer mid-run — the WRITE half that closes\n * the learning loop: what the agent learns now steers future sessions).\n *\n * Persistence is the BACKEND's job, for free: NodeDiskFilesystem → disk,\n * IndexedDbFilesystem → browser, (planned) BodDbFilesystem → database. The same\n * memory mechanism therefore works in node, a browser tab, or on edge.\n */\nexport interface LoadMemoryOpts {\n relevanceHint?: string;\n max?: number;\n /** Max Remember calls per session (default 25). Prevents runaway memory writes. */\n maxWritesPerSession?: number;\n /** Called after each successful memory write (auditing, UI indicators). */\n onMemorySaved?: (slug: string, type?: string) => void;\n /** User-scope dir for global memories (type=user/feedback). If set, Remember routes by type:\n * user/feedback → userDir (global, survives across projects), project/reference → writeDir. */\n userDir?: string;\n}\n\nexport async function loadMemory(\n fs: IFilesystem,\n dir: string | string[],\n opts: LoadMemoryOpts = {},\n): Promise<{ index: string; tools: AgentTool[] }> {\n const dirs = (Array.isArray(dir) ? dir : [dir]).filter(Boolean);\n const writeDir = dirs[0]; // writes go to first (project) scope\n const tools = [recallTool(fs, dirs), rememberTool(fs, writeDir, opts), memorySearchTool(fs, dirs)];\n\n // Merge pointers from all dirs' MEMORY.md files (dedup by slug, first wins).\n const allPointers: string[] = [];\n const seenSlugs = new Set<string>();\n let header = '';\n let hasContent = false;\n for (const d of dirs) {\n const indexPath = `${d}/MEMORY.md`;\n const md = (await fs.exists(indexPath)) ? (await fs.readFile(indexPath)).trim() : '';\n if (!md) continue;\n hasContent = true;\n const lines = md.split('\\n');\n if (!header) header = lines.filter((l) => !/^\\s*-\\s*\\[.+\\]\\(.+\\.md\\)/.test(l)).join('\\n').trim();\n for (const l of lines.filter((l) => /^\\s*-\\s*\\[.+\\]\\(.+\\.md\\)/.test(l))) {\n const slug = l.match(/\\]\\(([^)]+)\\.md\\)/)?.[1];\n if (slug && !seenSlugs.has(slug)) { seenSlugs.add(slug); allPointers.push(l); }\n }\n }\n\n // Always inject behavioral guidance — even for empty dirs, so the model knows HOW to create memories.\n if (!hasContent) return { index: MEMORY_PROMPT, tools };\n\n const { kept, rest } = topByRelevance(allPointers, opts.relevanceHint ?? '', (l) => l, opts.max ?? MAX_INDEX);\n const restSlugs = rest.map((l) => l.match(/\\]\\(([^)]+)\\.md\\)/)?.[1] ?? l.match(/\\[([^\\]]+)\\]/)?.[1] ?? '').filter(Boolean);\n\n const index =\n MEMORY_PROMPT + '\\n\\n' +\n '## Memory index (persistent context — recalled across sessions)\\n' +\n (header ? header + '\\n' : '') +\n kept.join('\\n') +\n (restSlugs.length ? `\\n- (${restSlugs.length} more learnings, slugs only — call \\`Recall\\` if relevant): ${restSlugs.join(', ')}` : '');\n return { index, tools };\n}\n\n/** Slugify free text into a safe kebab filename stem (no separators, bounded). */\nexport function slugify(s: string, fallback = 'note'): string {\n const base = String(s ?? '')\n .trim()\n .toLowerCase()\n .replace(/\\.md$/i, '')\n .replace(/[^\\w\\s-]/g, '')\n .replace(/[\\s_]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 48);\n return base || fallback;\n}\n\n/**\n * Persist a durable fact: write `<dir>/<slug>.md` and ensure a one-line pointer exists in\n * `<dir>/MEMORY.md` (created if missing). Idempotent on the index (won't duplicate a pointer).\n * This is the shared write path behind the `Remember` tool and automatic lesson capture.\n */\nexport async function writeFact(fs: IFilesystem, dir: string, slug: string, body: string, opts?: { type?: string; description?: string }): Promise<void> {\n await mkdirp(fs, dir);\n const content = opts?.type ? `---\\ntype: ${opts.type}\\n---\\n\\n${body}` : body;\n await fs.writeFile(`${dir}/${slug}.md`, content.endsWith('\\n') ? content : content + '\\n');\n const indexPath = `${dir}/MEMORY.md`;\n const idx = (await fs.exists(indexPath)) ? await fs.readFile(indexPath) : '# Memory Index\\n';\n const summary = opts?.description || body.split('\\n')[0].slice(0, 80);\n const line = `- [${slug}](${slug}.md) — ${summary}`;\n const lines = idx.split('\\n');\n const at = lines.findIndex((l) => l.includes(`(${slug}.md)`));\n if (at >= 0) {\n if (lines[at] !== line) { lines[at] = line; await fs.writeFile(indexPath, lines.join('\\n')); }\n } else {\n await fs.writeFile(indexPath, idx.replace(/\\s*$/, '') + `\\n${line}\\n`);\n }\n // Enforce index cap: drop oldest pointers when over limit (fact files survive — still Recall-able/searchable).\n await truncateIndex(fs, indexPath);\n}\n\nasync function truncateIndex(fs: IFilesystem, path: string): Promise<void> {\n const raw = await fs.readFile(path);\n if (raw.length <= MAX_INDEX_BYTES) {\n const count = raw.split('\\n').filter((l) => /^\\s*-\\s*\\[.+\\]\\(.+\\.md\\)/.test(l)).length;\n if (count <= MAX_INDEX_LINES) return;\n }\n const lines = raw.split('\\n');\n const pointerIdxs: number[] = [];\n for (let i = 0; i < lines.length; i++) if (/^\\s*-\\s*\\[.+\\]\\(.+\\.md\\)/.test(lines[i])) pointerIdxs.push(i);\n // Drop oldest (topmost) pointers until under both caps.\n const drop = new Set<number>();\n for (const pi of pointerIdxs) {\n const candidate = lines.filter((_, i) => !drop.has(i)).join('\\n');\n if (candidate.length <= MAX_INDEX_BYTES && pointerIdxs.length - drop.size <= MAX_INDEX_LINES) break;\n drop.add(pi);\n }\n if (drop.size) await fs.writeFile(path, lines.filter((_, i) => !drop.has(i)).join('\\n'));\n}\n\n/** Sanitize a slug: strip .md suffix, normalize path separators, block traversal. */\nfunction cleanSlug(raw: string): string {\n let s = String(raw ?? '').trim().replace(/\\.md$/i, '').replace(/\\\\/g, '/').replace(/\\/+/g, '/').replace(/^\\/|\\/$/g, '');\n while (s.includes('..')) s = s.replace(/\\.\\./g, '');\n return s;\n}\n\n/** Recursively list all fact slugs in the memory dir (relative paths without .md, excluding MEMORY.md). */\nasync function listSlugs(fs: IFilesystem, dir: string, prefix = ''): Promise<string[]> {\n let entries: string[];\n try { entries = await fs.readDir(dir); } catch { return []; }\n const out: string[] = [];\n for (const e of entries.sort()) {\n const full = dir === '/' ? `/${e}` : `${dir}/${e}`;\n const rel = prefix ? `${prefix}/${e}` : e;\n if (await fs.isDirectory(full)) out.push(...await listSlugs(fs, full, rel));\n else if (e.endsWith('.md') && e !== 'MEMORY.md') out.push(rel.replace(/\\.md$/, ''));\n }\n return out;\n}\n\n/** Load a single fact by slug; strips YAML frontmatter before returning. Returns null if not found. */\nasync function loadFact(fs: IFilesystem, dir: string, slug: string): Promise<string | null> {\n const path = `${dir}/${slug}.md`;\n try {\n const raw = await fs.readFile(path);\n const { body } = splitFrontmatter(raw);\n return body || raw;\n } catch { return null; }\n}\n\n/** Try loading a fact from multiple dirs (first hit wins). */\nasync function loadFactMulti(fs: IFilesystem, dirs: string[], slug: string): Promise<string | null> {\n for (const d of dirs) { const r = await loadFact(fs, d, slug); if (r != null) return r; }\n return null;\n}\n\n/** List all slugs across multiple dirs (deduped, first wins). */\nasync function listSlugsMulti(fs: IFilesystem, dirs: string[]): Promise<string[]> {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const d of dirs) for (const s of await listSlugs(fs, d)) if (!seen.has(s)) { seen.add(s); out.push(s); }\n return out;\n}\n\n/** A `Recall` tool that loads memory facts by slug — single, batch, or pattern. */\nfunction recallTool(fs: IFilesystem, dirs: string[]): AgentTool {\n return {\n name: 'Recall',\n description: 'Load memory facts by slug. Pass `slug` for one, `slugs` for several, or `pattern` (glob like \"auth*\") to match. Returns full bodies, separated by `--- slug ---` headers.',\n parameters: {\n type: 'object',\n properties: {\n slug: { type: 'string', description: 'single fact slug (filename without .md)' },\n slugs: { type: 'array', items: { type: 'string' }, description: 'multiple slugs to load at once' },\n pattern: { type: 'string', description: 'glob pattern to match against slugs (e.g. \"auth*\", \"*database*\")' },\n },\n },\n async run({ slug, slugs, pattern }, ctx: ToolContext) {\n let targets: string[] = [];\n if (slug) targets = [cleanSlug(slug)];\n else if (Array.isArray(slugs)) targets = slugs.map(cleanSlug).filter(Boolean);\n else if (pattern) {\n const escaped = String(pattern).replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&');\n const re = new RegExp('^' + escaped.replace(/\\*/g, '.*').replace(/\\?/g, '.') + '$', 'i');\n targets = (await listSlugsMulti(fs, dirs)).filter((s) => re.test(s));\n }\n if (!targets.length) return `Error: no slugs resolved. Pass slug, slugs, or pattern.`;\n const parts: string[] = [];\n for (const s of targets.slice(0, 20)) {\n const body = await loadFactMulti(fs, dirs, s);\n if (body != null) parts.push(targets.length > 1 ? `--- ${s} ---\\n${body}` : body);\n else parts.push(targets.length > 1 ? `--- ${s} ---\\n[not found]` : `Error: no memory fact '${s}'.`);\n }\n if (targets.length > 20) parts.push(`(${targets.length - 20} more matched — narrow the pattern)`);\n return parts.join('\\n\\n');\n },\n };\n}\n\n/** Search across all memory fact files by content. Returns slug + matching snippet pairs, ranked by relevance. */\nfunction memorySearchTool(fs: IFilesystem, dirs: string[]): AgentTool {\n return {\n name: 'MemorySearch',\n description:\n 'Search memory facts by content — find relevant memories when you don\\'t know the exact slug. Returns up to 10 matching slug + snippet pairs, ranked by relevance. Use `regex: true` for regex patterns.',\n parameters: {\n type: 'object',\n required: ['query'],\n properties: {\n query: { type: 'string', description: 'search query (keywords or regex pattern)' },\n regex: { type: 'boolean', description: 'treat query as a regex pattern (default: false)' },\n },\n },\n async run({ query, regex }, ctx: ToolContext) {\n const q = String(query ?? '').trim();\n if (!q) return 'Error: empty query.';\n const slugs = await listSlugsMulti(fs, dirs);\n if (!slugs.length) return '(no memory facts found)';\n let matcher: (line: string) => boolean;\n if (regex) {\n try { const re = new RegExp(q, 'i'); matcher = (l) => re.test(l); } catch (e) { return `Error: invalid regex: ${e}`; }\n } else {\n const lower = q.toLowerCase();\n matcher = (l) => l.toLowerCase().includes(lower);\n }\n const loaded: { slug: string; body: string }[] = [];\n for (const slug of slugs) {\n const body = await loadFactMulti(fs, dirs, slug);\n if (body) loaded.push({ slug, body });\n }\n const idf = idfWeights(loaded.map((l) => l.body));\n const qTokens = tokenize(q);\n const hits: { slug: string; snippet: string; score: number }[] = [];\n for (const { slug, body } of loaded) {\n const lines = body.split('\\n');\n const matchLine = lines.find(matcher);\n if (!matchLine && !relevanceScore(body, qTokens, idf)) continue;\n const snippet = matchLine?.trim().slice(0, 120) || lines.find((l) => l.trim())?.trim().slice(0, 120) || '';\n hits.push({ slug, snippet, score: relevanceScore(body, qTokens, idf) });\n }\n if (!hits.length) return '(no matches)';\n hits.sort((a, b) => b.score - a.score);\n return hits.slice(0, 10).map((h) => `${h.slug}: ${h.snippet}`).join('\\n');\n },\n };\n}\n\n/** A `Remember` tool: persist a durable fact + index pointer so it's recalled in future sessions. */\nfunction rememberTool(fs: IFilesystem, dir: string, memOpts: LoadMemoryOpts = {}): AgentTool {\n const maxWrites = memOpts.maxWritesPerSession ?? 25;\n let writes = 0;\n return {\n name: 'Remember',\n description:\n 'Persist a durable fact for future sessions (a fix you found, a gotcha, a project constraint). Adds a pointer to the Memory index and stores the body. Use sparingly — only genuinely reusable knowledge, not task-specific scratch.',\n parameters: {\n type: 'object',\n required: ['fact'],\n properties: {\n fact: { type: 'string', description: 'the durable fact to remember (one or more lines)' },\n slug: { type: 'string', description: 'optional kebab-case id; derived from the fact if omitted' },\n type: { type: 'string', enum: ['user', 'feedback', 'project', 'reference'], description: 'memory category (user/feedback/project/reference)' },\n description: { type: 'string', description: 'one-line summary for the memory index (≤80 chars)' },\n },\n },\n async run({ fact, slug, type, description }, ctx: ToolContext) {\n const body = String(fact ?? '').trim();\n if (!body) return `Error: nothing to remember (empty fact).`;\n if (++writes > maxWrites) return `Rate limit: too many memories this session (${maxWrites}). Only persist genuinely durable facts.`;\n const name = slugify(slug || body.split('\\n')[0]);\n // Route by type: user/feedback → user scope (global); project/reference → project scope.\n const isGlobal = (type === 'user' || type === 'feedback') && memOpts.userDir;\n const targetDir = isGlobal ? memOpts.userDir! : dir;\n await writeFact(fs, targetDir, name, body, { type, description });\n memOpts.onMemorySaved?.(name, type);\n return `Remembered '${name}' (recallable in future sessions).`;\n },\n };\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\n\nconst DEFAULT_NAMES = ['AGENT.md', 'AGENTS.md', 'CLAUDE.md'];\n\n/**\n * Walk the VFS directory tree from `/` down, collecting instruction files\n * (AGENT.md, AGENTS.md, CLAUDE.md, .claude/<name>) at each level.\n * Merges all found files general-first → specific-last (mirrors Claude Code's\n * hierarchical CLAUDE.md discovery). First matching filename per directory wins\n * (no duplicates from the same level). Edge-portable: works over any IFilesystem.\n */\nexport async function loadInstructions(\n fs: IFilesystem,\n names: string[] = DEFAULT_NAMES,\n): Promise<string> {\n // First matching name wins (AGENT.md > AGENTS.md > CLAUDE.md).\n // Both root and .claude/ locations are checked for the winning name — anchored at the FS\n // working dir (in CC-parity disk mode root '/' is the real machine, so instructions live\n // under the launch dir, not '/'). With cwd '/' this is the original behavior.\n const cwd = fs.getCwd();\n const base = cwd === '/' ? '' : cwd;\n for (const name of names) {\n const sections: string[] = [];\n for (const path of [`${base}/${name}`, `${base}/.claude/${name}`]) {\n if (!(await fs.exists(path))) continue;\n const md = (await fs.readFile(path)).trim();\n if (md) sections.push(`<!-- ${path} -->\\n${md}`);\n }\n if (sections.length) {\n return `## Project instructions\\nRepository-specific instructions — follow them.\\n\\n${sections.join('\\n\\n---\\n\\n')}`;\n }\n }\n return '';\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\nimport type { ChatLike } from './llm';\nimport type { AgentTool, ToolContext } from './tools';\nimport { toolsByName } from './tools';\nimport type { AgentDef } from './agents';\nimport type { Hooks } from './hooks';\nimport { Agent } from './Agent';\nimport { OverlayFilesystem } from './OverlayFilesystem';\n\n/** Run items through `fn` with at most `limit` in flight, preserving result order. */\nasync function boundedPool<T, R>(items: T[], limit: number, fn: (item: T, i: number) => Promise<R>): Promise<R[]> {\n const out = new Array<R>(items.length);\n let next = 0;\n const worker = async () => { while (next < items.length) { const i = next++; out[i] = await fn(items[i], i); } };\n await Promise.all(Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, worker));\n return out;\n}\n\nexport interface TaskToolOptions {\n /** The same ai.libx.js client the parent uses — the child shares it. */\n ai: ChatLike;\n model: string;\n /** The filesystem the child operates over (jail/scope it before passing, if desired). */\n fs: IFilesystem;\n /** Step budget for the child run (independent of the parent's). */\n maxSteps?: number;\n /** Recursion depth of the child this tool would spawn (0 = first level). */\n depth?: number;\n /** Hard ceiling on nesting — beyond this the tool refuses to spawn. */\n maxDepth?: number;\n /** Named subagent types selectable via the `agentType` param (persona + model + scoped tools). */\n agents?: AgentDef[];\n /** Max children running concurrently in a `TaskBatch` (default 4). */\n maxParallel?: number;\n /** Parent hooks — `onSubagentStop` fires with each child's summary when it finishes. */\n hooks?: Hooks;\n}\n\n/** Resolve the constructor opts for one child agent (persona/model/tool scoping). Returns an error string on bad agentType. */\nfunction childOptionsFor(opts: TaskToolOptions, fs: IFilesystem, depth: number, maxDepth: number, agentType?: string): ConstructorParameters<typeof Agent>[0] | string {\n let def: AgentDef | undefined;\n if (agentType) {\n def = (opts.agents ?? []).find((a) => a.name === agentType);\n if (!def) return `no subagent type '${agentType}'. Available: ${(opts.agents ?? []).map((a) => a.name).join(', ') || '(none defined)'}`;\n }\n const childOpts: ConstructorParameters<typeof Agent>[0] = { ai: opts.ai, fs, model: def?.model ?? opts.model, subagents: true, depth: depth + 1, maxDepth };\n if (opts.maxSteps != null) childOpts.maxSteps = opts.maxSteps;\n if (def?.systemPrompt) childOpts.systemPrompt = def.systemPrompt;\n if (def?.tools?.length) {\n try { childOpts.tools = toolsByName(def.tools); }\n catch (e) { return `subagent '${agentType}' declares an unknown tool — ${(e as Error).message}`; }\n }\n return childOpts;\n}\n\n/**\n * `Task` tool — spawn a CHILD agent over the same VFS with its own step budget,\n * returning only its final summary to the parent. Use to fan out a self-contained\n * sub-task (search, refactor a subtree) without polluting the parent's context.\n * @returns the child's final text, or an error string if the depth limit is reached.\n */\nexport function makeTaskTool(opts: TaskToolOptions): AgentTool {\n const depth = opts.depth ?? 0;\n const maxDepth = opts.maxDepth ?? 2;\n return {\n name: 'Task',\n description:\n 'Delegate a self-contained sub-task to a child agent over the same filesystem. It runs autonomously with its own step budget and returns a concise summary — use to isolate context-heavy work (broad search, a scoped refactor). Provide a short `description` and a full `prompt`. Set `background: true` to run it detached (returns a job id to poll with JobOutput while you keep working); its file edits are overlay-isolated and commit when it finishes.',\n parameters: {\n type: 'object',\n required: ['description', 'prompt'],\n properties: {\n description: { type: 'string', description: 'a short (3-5 word) label for the sub-task' },\n prompt: { type: 'string', description: 'the full instructions the child agent should carry out' },\n agentType: { type: 'string', description: 'optional named subagent type (its persona, model, and scoped tools) — see the catalog' },\n background: { type: 'boolean', description: 'run detached (overlay-isolated, commits on finish); returns a job id to poll with JobOutput instead of blocking' },\n },\n },\n async run({ description, prompt, agentType, background }, ctx: ToolContext) {\n if (depth >= maxDepth) {\n return `Error: Task depth limit reached (maxDepth ${maxDepth}). Cannot spawn another child agent — do this work directly instead.`;\n }\n const label = String(description ?? agentType ?? 'sub-task');\n\n // Background: run the child detached over an isolated overlay via the job registry. This is where\n // sandbox backgrounding actually pays off — a child does real model calls, so it overlaps the parent.\n if (background && ctx.jobs) {\n const id = ctx.jobs.start(async ({ signal }) => {\n const overlay = new OverlayFilesystem(opts.fs); // write-isolation: parent VFS untouched until commit\n const childOpts = childOptionsFor(opts, overlay, depth, maxDepth, agentType);\n if (typeof childOpts === 'string') throw new Error(childOpts);\n childOpts!.signal = signal; // killing the job aborts the child's run loop\n const res = await new Agent(childOpts).run(String(prompt ?? ''));\n if (signal.aborted) return '[killed before commit]';\n await overlay.commit(); // flush the child's edits down into the parent VFS\n const summary = res.text || `(child '${label}' finished with no summary; finishReason=${res.finishReason})`;\n await opts.hooks?.onSubagentStop?.(summary, { label, agentType });\n return summary;\n }, { kind: 'agent', label });\n return `Started background sub-task ${id} ('${label}') — poll with JobOutput({id:\"${id}\"}).`;\n }\n\n // The child gets subagents enabled but one level deeper, so it can recurse\n // up to maxDepth; at the ceiling its own Task tool refuses (see guard above).\n const childOpts = childOptionsFor(opts, opts.fs, depth, maxDepth, agentType);\n if (typeof childOpts === 'string') return `Error: ${childOpts}`;\n const child = new Agent(childOpts);\n const res = await child.run(String(prompt ?? ''));\n const summary = res.text || `(child agent finished '${label}' with no summary; finishReason=${res.finishReason})`;\n await opts.hooks?.onSubagentStop?.(summary, { label, agentType });\n return summary;\n },\n };\n}\n\n/**\n * `TaskBatch` tool — fan out several self-contained sub-tasks to child agents that run\n * **concurrently** (bounded pool), returning all their summaries together. Each child runs over its\n * OWN `OverlayFilesystem` (write-isolated from siblings), and successful children's edits are\n * committed **in array order** afterward — so concurrent writes resolve deterministically\n * (last index wins) instead of racing. Use to parallelize independent work (review N files, search M\n * subtrees, scoped refactors). For a single sub-task, use `Task`.\n */\nexport function makeTaskBatchTool(opts: TaskToolOptions): AgentTool {\n const depth = opts.depth ?? 0;\n const maxDepth = opts.maxDepth ?? 2;\n const maxParallel = opts.maxParallel ?? 4;\n return {\n name: 'TaskBatch',\n description:\n 'Delegate SEVERAL independent sub-tasks to child agents that run concurrently; returns all their summaries. Each child is write-isolated (its file edits are merged back in array order). Use for parallel fan-out (review/search/scoped refactors across files). Provide `tasks: [{ description, prompt, agentType? }]`.',\n parameters: {\n type: 'object',\n required: ['tasks'],\n properties: {\n tasks: {\n type: 'array',\n description: 'the sub-tasks to run in parallel',\n items: {\n type: 'object',\n required: ['description', 'prompt'],\n properties: {\n description: { type: 'string', description: 'a short (3-5 word) label' },\n prompt: { type: 'string', description: 'the full instructions for this child' },\n agentType: { type: 'string', description: 'optional named subagent type' },\n },\n },\n },\n },\n },\n async run({ tasks }, _ctx: ToolContext) {\n if (depth >= maxDepth) return `Error: Task depth limit reached (maxDepth ${maxDepth}). Cannot spawn child agents — do this work directly instead.`;\n const list = Array.isArray(tasks) ? tasks : [];\n if (!list.length) return 'Error: TaskBatch needs a non-empty `tasks` array.';\n\n type Outcome = { label: string; text?: string; error?: string; overlay?: OverlayFilesystem; ok: boolean };\n const results = await boundedPool<any, Outcome>(list, maxParallel, async (t, i) => {\n const label = String(t?.description ?? t?.agentType ?? `task ${i + 1}`);\n const overlay = new OverlayFilesystem(opts.fs); // write-isolation: siblings can't see each other's edits\n const childOpts = childOptionsFor(opts, overlay, depth, maxDepth, t?.agentType);\n if (typeof childOpts === 'string') return { label, error: childOpts, ok: false };\n try {\n const res = await new Agent(childOpts).run(String(t?.prompt ?? ''));\n await opts.hooks?.onSubagentStop?.(res.text, { label, agentType: t?.agentType });\n return { label, text: res.text, overlay, ok: res.finishReason !== 'error' };\n } catch (e) { return { label, error: e instanceof Error ? e.message : String(e), ok: false }; }\n });\n\n // Merge successful children's edits into the shared fs, in array order (deterministic last-writer-wins).\n for (const r of results) if (r.ok && r.overlay) await r.overlay.commit().catch(() => {});\n\n return results\n .map((r, i) => `### ${i + 1}. ${r.label}\\n${r.error ? `ERROR: ${r.error}` : (r.text || '(no summary)')}`)\n .join('\\n\\n');\n },\n };\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\n\n/**\n * Typed subagents — named child-agent definitions from `<dir>/<name>.md`, each with a\n * description, an optional model + tool allowlist (frontmatter), and a system prompt (the\n * body). The `Task` tool's `agentType` selects one, so a delegated sub-task runs with its\n * own persona, model, and scoped tools — the Claude-Code `.claude/agents` model.\n * VFS-backed (edge-portable), mirroring loadSkills / loadCommands.\n */\nexport interface AgentDef {\n name: string;\n description: string;\n /** The .md body — used as the child's system prompt (overrides the default). */\n systemPrompt?: string;\n /** Optional model override for this subagent type. */\n model?: string;\n /** Optional tool-name allowlist (scopes the child's tools). */\n tools?: string[];\n}\n\n/** Lean frontmatter parse for `description`/`model`/`tools` (no YAML dependency). */\nfunction parseAgentFrontmatter(md: string): { description?: string; model?: string; tools?: string[]; body: string } {\n const m = md.match(/^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n?/);\n const block = m ? m[1] : '';\n const get = (k: string) => {\n const r = new RegExp(`^${k}\\\\s*:\\\\s*(.+)$`, 'im').exec(block);\n return r ? r[1].trim().replace(/^[\"']|[\"']$/g, '') : undefined;\n };\n const toolsRaw = get('tools');\n const tools = toolsRaw\n ? toolsRaw.replace(/^\\[|\\]$/g, '').split(',').map((s) => s.trim().replace(/^[\"']|[\"']$/g, '')).filter(Boolean)\n : undefined;\n return { description: get('description'), model: get('model'), tools, body: (m ? md.slice(m[0].length) : md).trim() };\n}\n\n/** Discover subagent definitions under `dir` and a catalog block for the system prompt. */\nexport async function loadAgents(fs: IFilesystem, dir: string): Promise<{ agents: AgentDef[]; catalog: string }> {\n const agents: AgentDef[] = [];\n if (await fs.exists(dir)) {\n for (const entry of await fs.readDir(dir)) {\n if (!entry.endsWith('.md')) continue;\n const fm = parseAgentFrontmatter(await fs.readFile(`${dir}/${entry}`));\n agents.push({\n name: entry.replace(/\\.md$/, ''),\n description: fm.description || '',\n systemPrompt: fm.body || undefined,\n model: fm.model,\n tools: fm.tools,\n });\n }\n }\n if (!agents.length) return { agents, catalog: '' };\n const catalog =\n '## Subagent types (pass as the `Task` tool `agentType`)\\n' +\n agents.map((a) => `- **${a.name}** — ${a.description}`).join('\\n');\n return { agents, catalog };\n}\n","import type { Hooks, ToolUse } from './hooks';\nimport type { HostBridge, AgentTool } from './tools';\nimport { globToRegExp } from './tools.structured';\n\n/**\n * Permissions & plan-mode — safe-autonomy controls built ENTIRELY on the hooks +\n * host seams (no Agent-core changes needed). Two pieces:\n * - PermissionPolicy → Hooks: allow / ask (host.confirm) / deny a tool call by tool\n * name + path glob. First matching rule wins; default decision otherwise.\n * - planMode(): blocks mutating tools until the agent presents a plan via `ExitPlanMode`\n * and the host approves — Claude-Code-style plan gating.\n */\nexport type Decision = 'allow' | 'ask' | 'deny';\n\n/** Match a shell command against a rule glob where `*` spans anything (including spaces and `/`),\n * e.g. `git *` → any git subcommand, `rm *` → any rm invocation. Literals are regex-escaped. */\nfunction commandMatches(glob: string, cmd: string): boolean {\n const pattern = glob.split('*').map((s) => s.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('.*');\n return new RegExp('^' + pattern + '$').test(cmd);\n}\n\nexport interface PermissionRule {\n /** tool name to match (omit = any tool). */\n tool?: string;\n /** glob on the call's `path` arg to match (omit = any/none). */\n pathGlob?: string;\n decision: Decision;\n}\n\nexport class PermissionOptions {\n rules: PermissionRule[] = [];\n /** decision when no rule matches. */\n default: Decision = 'allow';\n /** host channel for `ask` (confirm). If absent, `ask` is treated as `deny` (fail-closed). */\n host?: HostBridge;\n /** Richer ask resolver (CLI surfaces a Yes/No/Always menu). Returns the decision + whether to\n * remember it — on remember, the policy adds a session rule so the same tool isn't re-asked.\n * If unset, falls back to `host.confirm` (plain yes/no). */\n ask?(call: ToolUse): Promise<{ decision: 'allow' | 'deny'; remember?: boolean } | undefined>;\n}\n\nexport class PermissionPolicy {\n public options: PermissionOptions;\n constructor(options?: Partial<PermissionOptions>) {\n this.options = { ...new PermissionOptions(), ...options };\n }\n\n /** Resolve the decision for a tool call (first matching rule, else default). */\n decide(call: ToolUse): Decision {\n // Deferred MCP (`McpCall({name})`) routes many tools through ONE agent tool — rules written\n // against the underlying `mcp__server__tool` name must still match (deny rules especially).\n const names = call.name === 'McpCall' && typeof call.args?.name === 'string' ? [call.name, call.args.name] : [call.name];\n for (const r of this.options.rules) {\n if (r.tool && !names.includes(r.tool)) continue;\n if (r.pathGlob) {\n // The glob matches a file `path` (path-glob semantics, slash-normalized) OR a `command`\n // string (`Shell(git *)`/`bash(rm *)`) — commands use *=anything (slashes included).\n const path = typeof call.args?.path === 'string' ? call.args.path : null;\n const cmd = typeof call.args?.command === 'string' ? call.args.command : null;\n if (path != null) {\n if (!globToRegExp(r.pathGlob).test(path.startsWith('/') ? path : `/${path}`)) continue;\n } else if (cmd != null) {\n if (!commandMatches(r.pathGlob, cmd)) continue;\n } else continue; // rule has a glob but the call exposes neither path nor command\n }\n return r.decision;\n }\n return this.options.default;\n }\n\n /** A preToolUse hook enforcing this policy (deny/ask → block; allow → proceed). */\n hooks(): Hooks {\n return {\n preToolUse: async (call) => {\n const d = this.decide(call);\n if (d === 'allow') return;\n if (d === 'deny') return { block: true, reason: `denied by permission policy (${call.name})` };\n // ask — prefer the richer resolver (Yes/No/Always); fall back to a plain confirm.\n if (this.options.ask) {\n const r = await this.options.ask(call);\n const decision = r?.decision ?? 'deny';\n // Remember the UNDERLYING tool for deferred MCP — remembering 'McpCall' itself would\n // blanket-approve every MCP tool from one answer. decide() aliases it back on match.\n const rememberTool = call.name === 'McpCall' && typeof call.args?.name === 'string' ? call.args.name : call.name;\n if (r?.remember) this.options.rules.unshift({ tool: rememberTool, decision }); // session-remember (wins next time)\n return decision === 'allow' ? undefined : { block: true, reason: `not approved (${call.name})` };\n }\n const ok = await this.options.host?.confirm?.(`Allow ${call.name}${call.args?.path ? ' on ' + call.args.path : ''}?`);\n return ok ? undefined : { block: true, reason: `not approved (${call.name})` };\n },\n };\n }\n}\n\n/** Tools the agent must not run before the plan is approved (sensible default). */\nexport const DEFAULT_MUTATING = ['Write', 'Edit', 'MultiEdit', 'deleteFile', 'bash'];\n\n/**\n * Plan-mode: mutating tools are BLOCKED until the agent calls `ExitPlanMode` with a plan\n * and (if a host is present) the user approves it. Returns the gating hook + the tool to\n * add to the agent. Compose the hook with others via composeHooks().\n */\nexport function planMode(opts?: { mutating?: string[]; host?: HostBridge }): { hooks: Hooks; tool: AgentTool } {\n const mutating = new Set(opts?.mutating ?? DEFAULT_MUTATING);\n let approved = false;\n const tool: AgentTool = {\n name: 'ExitPlanMode',\n description: 'Call when your plan is ready and you want to start making changes. Provide the `plan`. Until this is approved, edits/writes are blocked.',\n parameters: { type: 'object', required: ['plan'], properties: { plan: { type: 'string', description: 'the concrete steps you will take' } } },\n async run({ plan }, _ctx) {\n if (opts?.host?.confirm) {\n const confirm = opts.host.confirm(`Approve this plan?\\n\\n${String(plan ?? '')}`);\n const ok = await (_ctx?.parkHuman ? _ctx.parkHuman(confirm) : confirm); // exclude approval wait from the timeout\n if (!ok) return 'Plan not approved. Revise it and call ExitPlanMode again.';\n }\n approved = true;\n return 'Plan approved — you may now make changes.';\n },\n };\n const hooks: Hooks = {\n preToolUse: (call) =>\n !approved && mutating.has(call.name)\n ? { block: true, reason: 'plan mode: present a plan and call ExitPlanMode (approved) before editing.' }\n : undefined,\n };\n return { hooks, tool };\n}\n\n/** Run several Hooks as one: preToolUse stops at the first block; post/stop all fire. */\nexport function composeHooks(...list: (Hooks | undefined)[]): Hooks {\n const hooks = list.filter(Boolean) as Hooks[];\n return {\n async preToolUse(call, meta) {\n for (const h of hooks) {\n const d = await h.preToolUse?.(call, meta);\n if (d?.block) return d;\n }\n },\n async postToolUse(call, result, meta) { for (const h of hooks) await h.postToolUse?.(call, result, meta); },\n onToolOutput(call, chunk, meta) { for (const h of hooks) h.onToolOutput?.(call, chunk, meta); },\n onStop(text) { for (const h of hooks) h.onStop?.(text); },\n // lifecycle: concatenate session-start context; chain prompt-submit transforms; fan out pre-compact.\n async onSessionStart() {\n let ctx = '';\n for (const h of hooks) { const r = await h.onSessionStart?.(); if (r) ctx += (ctx ? '\\n\\n' : '') + r; }\n return ctx || undefined;\n },\n async onUserPromptSubmit(text) {\n let t = text;\n for (const h of hooks) { const r = await h.onUserPromptSubmit?.(t); if (typeof r === 'string') t = r; }\n return t;\n },\n async onPreCompact(messages) { for (const h of hooks) await h.onPreCompact?.(messages); },\n async onSubagentStop(summary, info) { for (const h of hooks) await h.onSubagentStop?.(summary, info); },\n };\n}\n","/**\n * Conservative, dependency-free syntax sanity check for code files (edge-safe pure JS).\n * Goal: catch an unambiguously-broken write (unbalanced/mis-nested delimiters) BEFORE it\n * lands, so the model doesn't later waste a turn re-reading + re-editing. Deliberately narrow:\n * it ONLY checks balanced ()/[]/{} after skipping string literals and comments, and ONLY\n * reports when delimiters are clearly wrong. Never throws.\n */\n\nconst CODE_RE = /\\.(ts|tsx|js|jsx|mjs|cjs)$/;\n\n/** Returns an error message if `content` is clearly broken for a code file, else null. */\nexport function checkSyntax(path: string, content: string): string | null {\n if (!CODE_RE.test(path)) return null; // only code files\n try {\n const open: Record<string, string> = { ')': '(', ']': '[', '}': '{' };\n const names: Record<string, string> = { '(': \"'('\", '[': \"'['\", '{': \"'{'\" };\n const stack: string[] = [];\n const n = content.length;\n for (let i = 0; i < n; i++) {\n const c = content[i];\n // line comment\n if (c === '/' && content[i + 1] === '/') {\n while (i < n && content[i] !== '\\n') i++;\n continue;\n }\n // block comment\n if (c === '/' && content[i + 1] === '*') {\n i += 2;\n while (i < n && !(content[i] === '*' && content[i + 1] === '/')) i++;\n i++; // skip the closing '/' (loop's i++ skips '*')\n continue;\n }\n // string / template literals — skip with escape handling\n if (c === '\"' || c === \"'\" || c === '`') {\n const quote = c;\n i++;\n while (i < n) {\n if (content[i] === '\\\\') { i += 2; continue; }\n if (content[i] === quote) break;\n i++;\n }\n continue;\n }\n if (c === '(' || c === '[' || c === '{') stack.push(c);\n else if (c === ')' || c === ']' || c === '}') {\n const want = open[c];\n if (stack.length === 0) return `Syntax check failed for ${path}: unexpected closing '${c}'. Fix before writing.`;\n const top = stack.pop()!;\n if (top !== want) return `Syntax check failed for ${path}: mismatched '${c}' (expected to close ${names[top]}). Fix before writing.`;\n }\n }\n if (stack.length > 0) {\n const ch = stack[stack.length - 1];\n return `Syntax check failed for ${path}: unbalanced ${names[ch]} (${stack.length} unclosed). Fix before writing.`;\n }\n return null;\n } catch {\n return null; // never throw — lint is a guard, not a gate that can crash a write\n }\n}\n","/**\n * Normalized reasoning/thinking control → provider-specific request fragment.\n *\n * Pure & dependency-free (no `ai.libx.js` import — provider is detected from the\n * `provider/model` prefix), so it stays inside the Agent's structural-typing boundary.\n * The returned fragment is spread into `ai.chat()`; callers never hand-craft the\n * per-provider encoding (Anthropic `thinking.budget_tokens`, OpenAI `reasoning_effort`).\n */\n\n/** `'off'`/undefined = no reasoning; named buckets; or a raw token budget (budget-based providers). */\nexport type ReasoningEffort = 'off' | 'low' | 'medium' | 'high' | number;\n\nexport interface ChatFragment {\n providerOptions?: Record<string, unknown>;\n /** Request `max_tokens`. Raised for budget-based providers so `budget_tokens < max_tokens` holds. */\n maxTokens?: number;\n}\n\n/** Named effort → thinking-token budget (budget-based providers, e.g. Anthropic). */\nconst BUDGET: Record<'low' | 'medium' | 'high', number> = { low: 2048, medium: 8192, high: 24576 };\n\n/** Bucket a raw token budget back to the nearest named effort (for providers that take a label). */\nfunction toLabel(effort: ReasoningEffort): 'low' | 'medium' | 'high' {\n if (typeof effort !== 'number') return effort === 'off' ? 'low' : effort;\n return effort <= BUDGET.low ? 'low' : effort < BUDGET.high ? 'medium' : 'high';\n}\n\n/** Resolve an effort to a concrete token budget. */\nfunction toBudget(effort: ReasoningEffort): number {\n return typeof effort === 'number' ? effort : BUDGET[effort as 'low' | 'medium' | 'high'];\n}\n\n/**\n * Map a normalized effort to a partial `ChatOptions` fragment for `model`'s provider.\n * Returns `{}` (safe no-op) for `'off'`, undefined, or an unsupported provider.\n *\n * Supported: `anthropic/*` (extended thinking), `openai/*` (reasoning_effort).\n * `google/*` is intentionally NOT mapped here — its adapter `Object.assign`s\n * providerOptions over the built `generationConfig`, clobbering it; pass an\n * explicit `providerOptions` if you need Gemini thinking.\n */\nexport function reasoningToChatFragment(model: string, effort?: ReasoningEffort): ChatFragment {\n if (effort == null || effort === 'off') return {};\n const provider = model.split('/')[0];\n switch (provider) {\n case 'anthropic': {\n const budget = toBudget(effort);\n return { providerOptions: { thinking: { type: 'enabled', budget_tokens: budget } }, maxTokens: budget + 8192 };\n }\n case 'openai':\n return { providerOptions: { reasoning_effort: toLabel(effort) } };\n default:\n return {};\n }\n}\n","// agentx — edge-native AI agent runtime over a virtual filesystem.\n\nexport { Agent, AgentOptions } from './Agent';\nexport type { RunResult } from './Agent';\n\nexport { NodeDiskFilesystem } from './NodeDiskFilesystem';\nexport { BodDbFilesystem } from './BodDbFilesystem';\nexport { JailedFilesystem, JailOptions, DEFAULT_DENY } from './JailedFilesystem';\nexport { OverlayFilesystem, checkpointTool, rollbackTool, checkpointTools } from './OverlayFilesystem';\nexport { MountFilesystem } from './MountFilesystem';\nexport type { Mount } from './MountFilesystem';\nexport { raceAttempts } from './speculate';\nexport type { Attempt } from './speculate';\nexport { validateToolCode, compileSynthesizedTool } from './synthesize';\nexport type { ToolSpec } from './synthesize';\nexport { PermissionPolicy, PermissionOptions, planMode, composeHooks, DEFAULT_MUTATING } from './permissions';\nexport type { Decision, PermissionRule } from './permissions';\n\nexport { FakeAIClient, toolCall } from './FakeAIClient';\n\nexport { bashTool, readTool, editTool, defaultTools, exitSessionTool, makeContext, toWireTools, toolRegistry, toolsByName } from './tools';\nexport { SandboxJobRegistry, makeJobTools } from './tools.jobs';\nexport { Scheduler, makeScheduleTools, parseCron, cronMatches, nextCronAfter } from './scheduler';\nexport type { ScheduledJob, ScheduledJobSnapshot, Trigger, TriggerOneOff, TriggerInterval, TriggerCron, SchedulerOptions } from './scheduler';\nexport { sandboxAgentOptions, diskAgentOptions, fullAgentOptions } from './presets';\nexport { grepTool, globTool, writeTool, multiEditTool, applyEditsTool, repoMapTool, repoIndex, mkdirp } from './tools.structured';\nexport { todoWriteTool } from './todo';\nexport { webFetchTool, webSearchTool, makeWebFetchTool, makeWebSearchTool, htmlToText, parseDdgHtml, decodeDdgUrl } from './tools.web';\nexport { Scratch, makeAskTool, SCRATCH_DIR } from './scratch';\nexport type { ScratchOptions, AskOptions } from './scratch';\nexport type { WebFetchOptions, WebSearchOptions } from './tools.web';\nexport type { TodoItem } from './todo';\nexport type { AgentTool, ToolContext, HostBridge, HostEvent, UserQuestion } from './tools';\n\nexport { askUserQuestionTool, ScriptedHostBridge, ConsoleHostBridge } from './host';\n\nexport { loadSkills, scanSkills } from './skills';\nexport type { SkillInfo } from './skills';\nexport { tokenize, relevanceScore, topByRelevance, idfWeights } from './relevance';\nexport { loadCommands, scanCommands, expandCommand, expandTemplate, expandEntry } from './commands';\nexport type { CommandInfo, SiblingResolver } from './commands';\nexport { loadMemory, writeFact, slugify, MEMORY_PROMPT, VOICE_MEMORY_PROMPT } from './memory';\nexport type { LoadMemoryOpts } from './memory';\nexport { lessonCapture, LessonOptionsDefaults } from './lessons';\nexport type { LessonOptions } from './lessons';\nexport { reflectOnRun } from './reflect';\nexport type { ReflectOptions } from './reflect';\nexport { loadInstructions } from './instructions';\n\nexport { DuplexAgent, DuplexAgentOptions, VOICE_SYSTEM_PROMPT } from './duplex';\nexport type { TaskRecord, DuplexTaskStatus, WorkerTier } from './duplex';\n\nexport { makeTaskTool, makeTaskBatchTool } from './subagent';\nexport type { TaskToolOptions } from './subagent';\nexport { loadAgents } from './agents';\nexport type { AgentDef } from './agents';\nexport { mcpToolsToAgentTools, mcpToolToAgentTool, makeMcpToolSearch, makeMcpToolSearchFromMounted, makeLazyMcpToolSearch, buildMcpCatalog } from './mcp';\nexport type { McpToolSpec, McpCall, McpToolSearchOptions, McpImage, McpToolResult, MountedMcpLike, McpRoute, McpRouteResolver } from './mcp';\nexport { RecordingHooks, RecordingLifecycle } from './hooks';\nexport type { Hooks, ToolUse, ToolUseMeta, PreToolUseDecision } from './hooks';\n\nexport { forComponent, log } from './logging';\n\n// Voice I/O (portable core — CLI/server/browser; platform backends live in cli/voice.ts).\nexport { VoiceEngine, VoiceEngineOptions } from './voice/engine';\nexport type { SttLike, TtsLike } from './voice/engine';\nexport { SonioxSTT, SonioxSTTOptions } from './voice/soniox';\nexport { CartesiaTTS, CartesiaTTSOptions } from './voice/cartesia';\nexport { resolveAuth, STT_SAMPLE_RATE, TTS_SAMPLE_RATE } from './voice/types';\nexport type { AudioSource, AudioSink, AuthProvider, VoiceState } from './voice/types';\n\nexport type { Message, Tool, ToolCall, ChatResponse, ChatOptions, ChatLike, Role, StreamChunk, ContentPart, MessageContent } from './llm';\nexport { contentText, imagePart } from './llm';\nexport { reasoningToChatFragment } from './reasoning';\nexport type { ReasoningEffort, ChatFragment } from './reasoning';\n\n// Re-export the wcli-core filesystem backends so embedders get everything from one place.\nexport { MemFilesystem, IndexedDbFilesystem, CommandExecutor, registerHeadlessCommands } from '@livx.cc/wcli/core';\nexport type { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';\n","import type { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';\nimport { PathResolver } from '@livx.cc/wcli/core';\nimport { BodDB } from '@bod.ee/db';\nimport type { VFSBackend } from '@bod.ee/db';\n\n/** Pure in-memory byte store for the default (no-arg) constructor — keeps it truly in-memory\n * (bod-db's default backend writes bytes to disk under `storageRoot`). Keyed by fileId. */\nclass MemBackend implements VFSBackend {\n private store = new Map<string, Uint8Array>();\n async read(id: string): Promise<Uint8Array> {\n const d = this.store.get(id);\n if (!d) throw new Error(`fileId not found: ${id}`);\n return d;\n }\n async write(id: string, data: Uint8Array): Promise<void> { this.store.set(id, data); }\n async delete(id: string): Promise<void> { this.store.delete(id); }\n async exists(id: string): Promise<boolean> { return this.store.has(id); }\n}\n\n/**\n * Database-backed `IFilesystem` over bod-db's VFS — the normalization thesis realized: the agent\n * operates on a file tree that lives in a database, yet the same tools/commands run unchanged\n * (semantics mirror MemFilesystem/NodeDiskFilesystem: throw on missing parent / existing dir /\n * non-empty dir / missing file). bod-db's VFS is path-based and async, so the adapter is thin.\n *\n * Construct with no args for an in-memory DB (great for tests), or pass a configured `BodDB`\n * (with VFS enabled) backed by real/cloud storage for persistence. Call `close()` when done to\n * release the DB's timers (the in-memory default uses `sweepInterval: 0`, so there's nothing to sweep).\n */\nexport class BodDbFilesystem implements IFilesystem {\n private cwd = '/';\n private db: BodDB;\n private vfs: NonNullable<BodDB['vfs']>;\n private owns: boolean;\n\n constructor(db?: BodDB) {\n this.owns = !db;\n // default: metadata DB in-memory (path ':memory:'), file bytes in a Map backend → no disk, no sweep timer.\n this.db = db ?? new BodDB({ path: ':memory:', sweepInterval: 0, vfs: { storageRoot: ':memory:', backend: new MemBackend() } });\n if (!this.db.vfs) throw new Error('BodDbFilesystem: the BodDB must have VFS enabled (construct it with { vfs: { … } }).');\n this.vfs = this.db.vfs;\n }\n\n /** Release the underlying DB's timers/handles. Closes only a DB we created (a passed-in DB is the caller's). */\n close(): void {\n if (this.owns) this.db.close();\n }\n\n resolvePath(path: string, cwd?: string): string {\n return PathResolver.resolve(path, cwd || this.cwd);\n }\n getCwd(): string { return this.cwd; }\n setCwd(path: string): void { this.cwd = PathResolver.normalize(path); }\n\n /** Parent dir of an absolute VFS path ('/a/b.txt' -> '/a'; '/a' -> '/'). */\n private parentOf(p: string): string {\n const i = p.lastIndexOf('/');\n return i <= 0 ? '/' : p.slice(0, i);\n }\n /** Throw (matching the other backends) unless the parent directory exists. Root is always a dir. */\n private assertParentDir(p: string, path: string): void {\n const parent = this.parentOf(p);\n if (parent === '/') return;\n const s = this.vfs.stat(parent);\n if (!s || !s.isDir) throw new Error(`Parent directory does not exist: ${path}`);\n }\n\n async readFile(path: string): Promise<string> {\n const p = this.resolvePath(path);\n const s = this.vfs.stat(p);\n if (!s) throw new Error(`File not found: ${path}`);\n if (s.isDir) throw new Error(`Not a file: ${path}`);\n return new TextDecoder().decode(await this.vfs.read(p));\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n const p = this.resolvePath(path);\n this.assertParentDir(p, path);\n if (this.vfs.stat(p)?.isDir) throw new Error(`Is a directory: ${path}`);\n await this.vfs.write(p, new TextEncoder().encode(content), 'text/plain');\n }\n\n async deleteFile(path: string): Promise<void> {\n const p = this.resolvePath(path);\n const s = this.vfs.stat(p);\n if (!s) throw new Error(`File not found: ${path}`);\n if (s.isDir && this.vfs.list(p).length > 0) throw new Error(`Directory not empty: ${path}`);\n await this.vfs.remove(p);\n }\n\n async readDir(path: string): Promise<string[]> {\n const p = this.resolvePath(path);\n if (p !== '/') {\n const s = this.vfs.stat(p);\n if (!s) throw new Error(`Directory not found: ${path}`); // missing vs…\n if (!s.isDir) throw new Error(`Not a directory: ${path}`); // …a file (match MemFilesystem semantics)\n }\n return this.vfs.list(p).map((e: { name: string }) => e.name);\n }\n\n async createDir(path: string): Promise<void> {\n const p = this.resolvePath(path);\n if (p === '/' || this.vfs.stat(p)) throw new Error(`File or directory already exists: ${path}`);\n this.assertParentDir(p, path);\n this.vfs.mkdir(p);\n }\n\n async exists(path: string): Promise<boolean> {\n const p = this.resolvePath(path);\n return p === '/' || this.vfs.stat(p) !== null;\n }\n\n async stat(path: string): Promise<FileMetadata> {\n const p = this.resolvePath(path);\n const s = this.vfs.stat(p);\n if (!s) {\n if (p === '/') return { created: new Date(0), modified: new Date(0), size: 0, permissions: 'drwxr-xr-x', isExecutable: false };\n throw new Error(`File not found: ${path}`);\n }\n const when = new Date(s.mtime); // bod-db tracks a single mtime; reuse for created+modified\n return {\n created: when,\n modified: when,\n size: s.size,\n permissions: s.isDir ? 'drwxr-xr-x' : '-rw-r--r--',\n isExecutable: false,\n };\n }\n\n async isDirectory(path: string): Promise<boolean> {\n const p = this.resolvePath(path);\n return p === '/' || this.vfs.stat(p)?.isDir === true;\n }\n async isFile(path: string): Promise<boolean> {\n const s = this.vfs.stat(this.resolvePath(path));\n return !!s && !s.isDir;\n }\n}\n","import type { IFilesystem, FileMetadata } from '@livx.cc/wcli/core';\n\n/**\n * Hybrid / composite VFS — a root backend with other IFilesystems mounted at path\n * prefixes. Each op routes to the longest-matching mount and is translated into that\n * backend's OWN root space (`/skills/x.md` → the /skills mount's `/x.md`); everything\n * else falls through to the root backend. `readDir` merges the routed listing with\n * mount-point names at that level, and intermediate mount-ancestor dirs (e.g. `/vendor`\n * when only `/vendor/lib` is mounted) are synthesized.\n *\n * This is what lets you mix sources: edit a real project on disk at `/` while reading\n * skills/tools/docs from a bundled in-memory VFS or another disk folder — one filesystem\n * to the agent. Pure IFilesystem composition: edge-safe.\n */\nconst DIR_META: FileMetadata = { created: new Date(0), modified: new Date(0), size: 0, permissions: 'drwxr-xr-x', isExecutable: false };\nconst norm = (p: string) => '/' + p.split('/').filter(Boolean).join('/'); // leading slash, no trailing\n\nexport interface Mount { prefix: string; fs: IFilesystem }\n\nexport class MountFilesystem implements IFilesystem {\n private mounts: Mount[];\n\n constructor(private root: IFilesystem, mounts: Mount[] = []) {\n this.mounts = mounts\n .map((m) => ({ prefix: norm(m.prefix), fs: m.fs }))\n .sort((a, b) => b.prefix.length - a.prefix.length); // longest prefix wins\n }\n\n resolvePath(path: string, cwd?: string): string { return this.root.resolvePath(path, cwd ?? this.root.getCwd()); }\n getCwd(): string { return this.root.getCwd(); }\n setCwd(path: string): void { this.root.setCwd(path); }\n private abs(p: string): string { return this.resolvePath(p); }\n\n /** Route an absolute VFS path to a backend + its path within that backend. */\n private route(abs: string): { fs: IFilesystem; sub: string } {\n for (const m of this.mounts) {\n if (abs === m.prefix || abs.startsWith(m.prefix + '/')) return { fs: m.fs, sub: abs.slice(m.prefix.length) || '/' };\n }\n return { fs: this.root, sub: abs };\n }\n\n /** Is `abs` strictly ABOVE a mount point (a synthesized dir the root may not have)? */\n private isMountAncestor(abs: string): boolean {\n const base = abs === '/' ? '/' : abs + '/';\n return this.mounts.some((m) => m.prefix.startsWith(base));\n }\n\n /** Immediate child segment names of `abs` that come from mounts (for readDir merge). */\n private mountChildrenOf(abs: string): string[] {\n const base = abs === '/' ? '/' : abs + '/';\n const out = new Set<string>();\n for (const m of this.mounts) if (m.prefix.startsWith(base)) out.add(m.prefix.slice(base.length).split('/')[0]);\n return [...out];\n }\n\n async readFile(path: string): Promise<string> { const { fs, sub } = this.route(this.abs(path)); return fs.readFile(sub); }\n async writeFile(path: string, content: string): Promise<void> { const { fs, sub } = this.route(this.abs(path)); return fs.writeFile(sub, content); }\n async deleteFile(path: string): Promise<void> { const { fs, sub } = this.route(this.abs(path)); return fs.deleteFile(sub); }\n async createDir(path: string): Promise<void> { const { fs, sub } = this.route(this.abs(path)); return fs.createDir(sub); }\n\n async exists(path: string): Promise<boolean> {\n const a = this.abs(path);\n if (this.isMountAncestor(a)) return true;\n const { fs, sub } = this.route(a);\n return fs.exists(sub);\n }\n async isDirectory(path: string): Promise<boolean> {\n const a = this.abs(path);\n if (this.isMountAncestor(a)) return true; // synthesized ancestor dir\n const { fs, sub } = this.route(a);\n return fs.isDirectory(sub);\n }\n async isFile(path: string): Promise<boolean> {\n const a = this.abs(path);\n if (this.isMountAncestor(a)) return false;\n const { fs, sub } = this.route(a);\n return fs.isFile(sub);\n }\n async stat(path: string): Promise<FileMetadata> {\n const a = this.abs(path);\n if (this.isMountAncestor(a)) return DIR_META;\n const { fs, sub } = this.route(a);\n return fs.stat(sub);\n }\n\n async readDir(path: string): Promise<string[]> {\n const a = this.abs(path);\n const { fs, sub } = this.route(a);\n const names = new Set<string>();\n let routedOk = false;\n try { for (const n of await fs.readDir(sub)) names.add(n); routedOk = true; } catch { /* may be a pure synthetic ancestor */ }\n for (const n of this.mountChildrenOf(a)) names.add(n);\n if (!routedOk && !this.isMountAncestor(a)) throw new Error(`Directory not found: ${path}`);\n return [...names].sort();\n }\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\nimport { OverlayFilesystem } from './OverlayFilesystem';\n\n/**\n * Speculative parallel attempts — a primitive uniquely cheap on a SWAPPABLE VFS.\n *\n * Fork the workspace into N copy-on-write overlays of the same `base`, run an attempt in\n * each (independently — writes stay in each overlay, the base is untouched), score them,\n * then COMMIT the best overlay into the base and DISCARD the losers (they leave no trace).\n * Use it to race several approaches/seeds for a flaky or multi-path task and keep only the\n * winner — something agents on a real, non-forkable filesystem can't do without copying the\n * whole tree. Pairs naturally with subagents (each attempt is a child Agent over its overlay).\n *\n * `score` returns a higher-is-better number, or null to disqualify (e.g. failed grading).\n */\nexport interface Attempt<R> {\n index: number;\n fs: OverlayFilesystem;\n result: R;\n score: number | null;\n}\n\nexport async function raceAttempts<R>(\n base: IFilesystem,\n n: number,\n run: (fs: IFilesystem, index: number) => Promise<R>,\n score: (a: { fs: OverlayFilesystem; result: R; index: number }) => Promise<number | null> | number | null,\n): Promise<{ winner: Attempt<R> | null; attempts: Attempt<R>[] }> {\n const attempts: Attempt<R>[] = await Promise.all(\n Array.from({ length: Math.max(1, n) }, async (_, index) => {\n const fs = new OverlayFilesystem(base);\n const result = await run(fs, index);\n const s = await score({ fs, result, index });\n return { index, fs, result, score: s };\n }),\n );\n // Best non-disqualified score wins; ties broken by earliest index (stable).\n const ranked = attempts.filter((a) => a.score != null).sort((a, b) => b.score! - a.score! || a.index - b.index);\n const winner = ranked[0] ?? null;\n if (winner) await winner.fs.commit(); // apply ONLY the winner to the base; losers are discarded\n return { winner, attempts };\n}\n","/**\n * In-process scheduler — timers that fire prompts into the agent loop while the session is alive.\n * Three trigger modes: one-off ({at}), interval ({everyMs}), cron ({cron}).\n * The scheduler never calls `turn()` itself — it invokes an IoC `fire` callback with due jobs,\n * keeping it testable and host-agnostic. Persistence is the host's responsibility (serialize jobs\n * into the session and re-arm on resume).\n *\n * Survives --resume (host reloads); does NOT survive process exit (no daemon, no launchd).\n */\n\nexport type TriggerOneOff = { at: number };\nexport type TriggerInterval = { everyMs: number };\nexport type TriggerCron = { cron: string };\nexport type Trigger = TriggerOneOff | TriggerInterval | TriggerCron;\n\nexport type ScheduledJobStatus = 'active' | 'done';\n\nexport interface ScheduledJob {\n id: string;\n prompt: string;\n trigger: Trigger;\n status: ScheduledJobStatus;\n created: number;\n lastRun?: number;\n runs: number;\n /** Optional label for display (e.g. footer, /schedule list). */\n label?: string;\n}\n\n/** Serializable snapshot for session persistence (same shape — kept as an alias for clarity at call sites). */\nexport type ScheduledJobSnapshot = ScheduledJob;\n\nexport interface SchedulerOptions {\n /** Called when a job is due. Must not throw — the scheduler logs errors and continues. */\n fire: (job: ScheduledJob) => Promise<void> | void;\n /** Monotonic clock override for testing (default: Date.now). */\n now?: () => number;\n /** Tick interval in ms (default: 15_000 — 15s). */\n tickMs?: number;\n /** If true, suppress the setInterval (for unit tests that call tick() manually). */\n manual?: boolean;\n}\n\n// ── Cron mini-parser (minute hour dom month dow) ──────────────────────────\n// Supports: *, N, N-M, */N, N-M/N, comma-separated lists. No named days/months.\n// Enough for real scheduling; not a full vixie-cron (no @yearly etc).\n\ninterface CronFields { minute: number[]; hour: number[]; dom: number[]; month: number[]; dow: number[] }\n\nfunction parseCronField(field: string, min: number, max: number): number[] {\n const vals = new Set<number>();\n for (const part of field.split(',')) {\n const [rangeStr, stepStr] = part.split('/');\n const step = stepStr ? parseInt(stepStr, 10) : 1;\n if (isNaN(step) || step < 1) throw new Error(`invalid cron step: ${part}`);\n let lo: number, hi: number;\n if (rangeStr === '*') { lo = min; hi = max; }\n else if (rangeStr!.includes('-')) {\n const [a, b] = rangeStr!.split('-').map(Number);\n if (isNaN(a!) || isNaN(b!)) throw new Error(`invalid cron range: ${part}`);\n lo = a!; hi = b!;\n } else {\n const n = parseInt(rangeStr!, 10);\n if (isNaN(n)) throw new Error(`invalid cron value: ${part}`);\n lo = n; hi = stepStr ? max : n;\n }\n for (let i = lo; i <= hi; i += step) vals.add(i);\n }\n return [...vals].sort((a, b) => a - b);\n}\n\nexport function parseCron(expr: string): CronFields {\n const parts = expr.trim().split(/\\s+/);\n if (parts.length !== 5) throw new Error(`cron expression must have 5 fields (minute hour dom month dow), got ${parts.length}: \"${expr}\"`);\n return {\n minute: parseCronField(parts[0]!, 0, 59),\n hour: parseCronField(parts[1]!, 0, 23),\n dom: parseCronField(parts[2]!, 1, 31),\n month: parseCronField(parts[3]!, 1, 12),\n dow: parseCronField(parts[4]!, 0, 6),\n };\n}\n\nexport function cronMatches(fields: CronFields, date: Date): boolean {\n return fields.minute.includes(date.getMinutes())\n && fields.hour.includes(date.getHours())\n && fields.dom.includes(date.getDate())\n && fields.month.includes(date.getMonth() + 1)\n && fields.dow.includes(date.getDay());\n}\n\n/** Next occurrence of `cron` after `after` (epoch ms). Returns epoch ms, or null if >366 days out (guard). */\nexport function nextCronAfter(cron: string, after: number): number | null {\n const fields = parseCron(cron);\n const d = new Date(after);\n d.setSeconds(0, 0);\n d.setMinutes(d.getMinutes() + 1); // always at least 1 minute in the future\n const limit = after + 366 * 86400_000;\n while (d.getTime() <= limit) {\n if (cronMatches(fields, d)) return d.getTime();\n d.setMinutes(d.getMinutes() + 1);\n }\n return null;\n}\n\n// ── Scheduler ─────────────────────────────────────────────────────────────\n\nexport class Scheduler {\n private jobs = new Map<string, ScheduledJob>();\n private seq = 0;\n private timer: ReturnType<typeof setInterval> | null = null;\n private firing = false;\n private readonly fire: SchedulerOptions['fire'];\n private readonly now: () => number;\n private readonly tickMs: number;\n\n constructor(opts: SchedulerOptions) {\n this.fire = opts.fire;\n this.now = opts.now ?? Date.now;\n this.tickMs = opts.tickMs ?? 15_000;\n if (!opts.manual) this.start();\n }\n\n /** Start the tick timer. Idempotent. */\n start(): void {\n if (this.timer) return;\n this.timer = setInterval(() => this.tick(), this.tickMs);\n if (typeof this.timer === 'object' && 'unref' in this.timer) (this.timer as any).unref();\n }\n\n /** Stop the tick timer. Does not clear jobs. */\n stop(): void {\n if (this.timer) { clearInterval(this.timer); this.timer = null; }\n }\n\n /** Add a scheduled job. Returns the job id. */\n add(opts: { prompt: string; trigger: Trigger; label?: string }): string {\n // Validate trigger\n if ('cron' in opts.trigger) parseCron(opts.trigger.cron); // throws on bad expr\n if ('at' in opts.trigger && opts.trigger.at < this.now()) {\n // Allow slightly-past timestamps (clock skew); just fire on next tick.\n }\n if ('everyMs' in opts.trigger && opts.trigger.everyMs < 1000) {\n throw new Error('interval must be >= 1000ms');\n }\n const id = `sched-${++this.seq}`;\n this.jobs.set(id, {\n id, prompt: opts.prompt, trigger: opts.trigger, status: 'active',\n created: this.now(), runs: 0, label: opts.label,\n });\n return id;\n }\n\n /** Cancel a job. Returns false if not found. */\n cancel(id: string): boolean {\n const j = this.jobs.get(id);\n if (!j) return false;\n j.status = 'done';\n return true;\n }\n\n get(id: string): ScheduledJob | undefined { return this.jobs.get(id); }\n\n list(): ScheduledJob[] { return [...this.jobs.values()]; }\n\n active(): ScheduledJob[] { return this.list().filter(j => j.status === 'active'); }\n\n /** Compute when a job next fires (epoch ms), or null if done/unknown. */\n nextFire(job: ScheduledJob): number | null {\n if (job.status !== 'active') return null;\n const t = job.trigger;\n if ('at' in t) return t.at;\n if ('everyMs' in t) return (job.lastRun ?? job.created) + t.everyMs;\n if ('cron' in t) return nextCronAfter(t.cron, job.lastRun ?? job.created);\n return null;\n }\n\n /** Check all active jobs and fire any that are due. Reentrant-safe. */\n async tick(): Promise<void> {\n if (this.firing) return; // guard: never overlap\n this.firing = true;\n try {\n const now = this.now();\n for (const job of this.jobs.values()) {\n if (job.status !== 'active') continue;\n const due = this.nextFire(job);\n if (due == null || due > now) continue;\n job.lastRun = now;\n job.runs++;\n // One-off: mark done immediately (before firing — fire is async, cancel must stick).\n if ('at' in job.trigger) job.status = 'done';\n try { await this.fire(job); } catch { /* fire contract: must not throw; belt-and-suspenders */ }\n }\n } finally {\n this.firing = false;\n }\n }\n\n /** Export all jobs for session persistence. */\n snapshot(): ScheduledJobSnapshot[] {\n return this.list().filter(j => j.status === 'active').map(j => ({ ...j }));\n }\n\n /** Restore jobs from a snapshot (e.g. on --resume). Clears existing jobs first. */\n restore(snapshots: ScheduledJobSnapshot[]): void {\n this.jobs.clear();\n for (const s of snapshots) {\n this.seq = Math.max(this.seq, parseInt(s.id.replace('sched-', ''), 10) || 0);\n this.jobs.set(s.id, { ...s });\n }\n }\n\n /** Number of active jobs. */\n get size(): number { return this.active().length; }\n\n destroy(): void { this.stop(); this.jobs.clear(); }\n}\n\n// ── Agent tools ───────────────────────────────────────────────────────────\n\nimport type { AgentTool } from './tools';\n\n/** Narrow seam to an OS-level scheduler backend (jobs that survive quit/reboot). Node hosts wire\n * the CLI's `OsScheduler` (launchd/cron/at); absent => everything stays in-process. Edge-safe:\n * this module only sees the interface. */\nexport interface OsBackend {\n sessionId: string;\n cwd: string;\n /** 'os' when the trigger should outlive the session (per hint/heuristic). */\n route(trigger: Trigger, backendHint?: string): 'session' | 'os';\n /** Register with the OS. Returns a mechanism description (e.g. 'launchd:…'). Throws on failure. */\n schedule(spec: { id: string; prompt: string; sessionId: string; cwd: string; trigger: Trigger; label?: string }): string;\n cancel(id: string): boolean;\n list(): Array<{ id: string; label?: string; mechanism: string; trigger: Trigger }>;\n}\n\nexport function makeScheduleTools(scheduler: Scheduler, os?: OsBackend): AgentTool[] {\n return [\n {\n name: 'ScheduleTask',\n description:\n 'Schedule a prompt to fire automatically.\\n' +\n 'Modes:\\n' +\n ' • One-off: {at: <epoch_ms>} — fires once at that time, then done.\\n' +\n ' • Interval: {everyMs: <ms>} — fires repeatedly (≥1s).\\n' +\n ' • Cron: {cron: \"min hr dom mon dow\"} — standard 5-field cron.\\n' +\n 'Backend: \"session\" fires while this CLI session is alive (default for recurring + near one-offs); ' +\n '\"os\" registers with the OS scheduler so the job survives quitting — it headless-resumes this session ' +\n 'when it fires (auto-chosen for one-offs ≥30min out when available). Pass backend:\"os\" explicitly for ' +\n 'recurring jobs that must outlive the session.',\n parameters: {\n type: 'object',\n required: ['prompt', 'trigger'],\n properties: {\n prompt: { type: 'string', description: 'The prompt to inject when the job fires.' },\n trigger: {\n type: 'object',\n description: 'One of: {at: epoch_ms}, {everyMs: ms}, {cron: \"5-field expr\"}.',\n properties: {\n at: { type: 'number' },\n everyMs: { type: 'number' },\n cron: { type: 'string' },\n },\n },\n label: { type: 'string', description: 'Short label for display (optional).' },\n backend: { type: 'string', enum: ['auto', 'session', 'os'], description: 'Where the job lives (default auto).' },\n },\n },\n async run({ prompt, trigger, label, backend }) {\n try {\n if (os && os.route(trigger, backend) === 'os') {\n const id = `os-${Date.now().toString(36)}`;\n const mechanism = os.schedule({ id, prompt, sessionId: os.sessionId, cwd: os.cwd, trigger, label });\n return `Scheduled ${id}${label ? ` (${label})` : ''} on the OS scheduler (${mechanism}) — survives quitting; fires \\`agentx --resume ${os.sessionId}\\` headless.`;\n }\n if (backend === 'os') return 'Error: no OS scheduler available on this platform — job not created (use the default in-session backend).';\n const id = scheduler.add({ prompt, trigger, label });\n const job = scheduler.get(id)!;\n const next = scheduler.nextFire(job);\n return `Scheduled ${id}${label ? ` (${label})` : ''}. Next fire: ${next ? new Date(next).toLocaleString() : 'now'}. (In-session: does not survive quitting.)`;\n } catch (e: any) {\n return `Error: ${e?.message ?? e}`;\n }\n },\n },\n {\n name: 'ScheduleList',\n description: 'List all scheduled jobs (in-session + OS-backed) and their next fire time.',\n parameters: { type: 'object', properties: {} },\n async run() {\n const osJobs = os?.list() ?? [];\n const osLines = osJobs.map((j) => `${j.id} os ${j.mechanism}${j.label ? ' ' + j.label : ''}`);\n const jobs = scheduler.list();\n if (!jobs.length && !osLines.length) return '(no scheduled jobs)';\n return [...osLines, ...jobs.map(j => {\n const next = scheduler.nextFire(j);\n const trig = 'at' in j.trigger ? `once @ ${new Date(j.trigger.at).toLocaleString()}`\n : 'everyMs' in j.trigger ? `every ${(j.trigger.everyMs / 1000).toFixed(0)}s`\n : `cron: ${(j.trigger as TriggerCron).cron}`;\n return `${j.id} ${j.status} ${trig} runs:${j.runs} next:${next ? new Date(next).toLocaleTimeString() : '—'}${j.label ? ' ' + j.label : ''}`;\n })].join('\\n');\n },\n },\n {\n name: 'ScheduleCancel',\n description: 'Cancel a scheduled job by id (in-session or OS-backed).',\n parameters: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } },\n async run({ id }) {\n const key = String(id);\n if (key.startsWith('os-')) return os?.cancel(key) ? `Cancelled ${key} (OS job removed).` : `Error: no OS job '${key}'.`;\n return scheduler.cancel(key) ? `Cancelled ${key}.` : `Error: no scheduled job '${key}'. Use ScheduleList to see jobs.`;\n },\n },\n {\n name: 'Wakeup',\n description:\n 'Self-pacing: schedule a one-off re-invocation of the agent after a delay.\\n' +\n 'Use this to resume work later in the session (e.g. \"check back in 5 minutes\").\\n' +\n 'The prompt fires once, while the session is alive. Equivalent to ScheduleTask with {at: now + delayMs}.',\n parameters: {\n type: 'object',\n required: ['delayMs', 'prompt'],\n properties: {\n delayMs: { type: 'number', description: 'Delay in milliseconds (minimum 5000).' },\n prompt: { type: 'string', description: 'The prompt to inject when waking up.' },\n label: { type: 'string' },\n },\n },\n async run({ delayMs, prompt, label }) {\n const delay = Math.max(5000, Number(delayMs) || 5000);\n try {\n const id = scheduler.add({ prompt, trigger: { at: Date.now() + delay }, label: label ?? 'wakeup' });\n return `Wakeup ${id} in ${(delay / 1000).toFixed(0)}s.`;\n } catch (e: any) {\n return `Error: ${e?.message ?? e}`;\n }\n },\n },\n ];\n}\n","/**\n * Named filesystem-mode presets (G-B) — thin factories that compose existing primitives into a\n * `Partial<AgentOptions>`, so a consumer can pick a posture without hand-wiring the fs/tools:\n *\n * new Agent(sandboxAgentOptions({ ai })) // in-memory VFS — real disk untouched\n * new Agent(diskAgentOptions({ ai })) // jailed real disk @ cwd (the default)\n * new Agent(await fullAgentOptions({ ai })) // disk + a real /bin/sh tool (run binaries)\n *\n * The core stays unopinionated (IoC): these just preset `fs`/`tools`. `sandbox`/`disk` are edge-safe to\n * import; `full` is node-only (real shell) and DYNAMIC-imports it, so importing this module never pulls\n * `node:child_process` into an edge/browser bundle.\n */\nimport { MemFilesystem } from '@livx.cc/wcli/core';\nimport type { AgentOptions } from './Agent';\nimport { defaultTools, type AgentTool } from './tools';\n\n/** Sandbox mode: an in-memory VFS — the real disk is never read or written. Edge/browser/test/dry-run. */\nexport function sandboxAgentOptions(opts: Partial<AgentOptions> = {}): Partial<AgentOptions> {\n return { fs: new MemFilesystem(), ...opts };\n}\n\n/** Disk mode (the default): operate on the real filesystem, jailed to cwd (secrets hidden by DEFAULT_DENY).\n * Omitting `fs` lets the Agent lazily resolve the jailed disk — this preset just makes the intent explicit\n * (and is where you'd thread overrides). Pass an explicit `fs` to use a different backend. */\nexport function diskAgentOptions(opts: Partial<AgentOptions> = {}): Partial<AgentOptions> {\n return { ...opts }; // fs omitted → Agent.ensureFs() resolves Jailed(NodeDisk(cwd))\n}\n\n/** Full mode: disk + a real `/bin/sh` tool (run installed binaries — git, bun, node, …) plus its\n * background-job companions. NODE-ONLY: the real-shell module is dynamic-imported so this file stays\n * edge-safe to import. `cwd` defaults to `process.cwd()`; secret env is scrubbed from spawned children. */\nexport async function fullAgentOptions(opts: Partial<AgentOptions> & { cwd?: string } = {}): Promise<Partial<AgentOptions>> {\n const { makeRealShellTool, makeShellJobTools, ShellJobRegistry } = await import('./tools.shell');\n const { cwd = process.cwd(), tools, ...rest } = opts;\n const registry = new ShellJobRegistry({ cwd, killOnExit: true });\n const shell: AgentTool[] = [makeRealShellTool({ cwd, registry }), ...makeShellJobTools(registry)];\n return { ...rest, tools: [...(tools ?? defaultTools()), ...shell] };\n}\n","/**\n * Scratch — keep large tool/subagent outputs OUT of the main context, but queryable AS FILES.\n *\n * Pattern: many-tool / many-subagent engines bloat context with raw outputs (search results, big\n * file reads, subagent reports) that are mostly noise once a gist is taken. Here, a tool wrapped with\n * `Scratch.capture` writes any oversized result to an ephemeral scratch filesystem (a real VFS) and\n * returns a compact stub (path + preview) to context. To recover a buried detail later you do NOT\n * re-bloat context — you peek with the FILE tools already on hand:\n * • Grep/Glob/Read over the scratch dir — returns matching lines, not the blob (a free, light peek).\n * • Ask({question, over?}) — a CHEAP child agent over the scratch FS that greps/reads and returns\n * just the answer; its reasoning tokens never touch the caller's context.\n * Two-tier division of labour: cheap RETRIEVE/EXTRACT, strong caller SYNTHESIZE.\n *\n * The scratch FS is injected (IoC): pass a MemFilesystem for ephemeral, or a disk-backed one under the\n * session dir to persist across resume (CC's lesson: the filesystem is the durable store). Segregated\n * module — zero Agent-core changes.\n */\nimport type { IFilesystem } from '@livx.cc/wcli/core';\nimport type { ChatLike } from './llm';\nimport type { AgentTool } from './tools';\nimport { toolsByName } from './tools';\nimport { Agent } from './Agent';\nimport { mkdirp } from './tools.structured';\nimport { forComponent } from './logging';\n\nconst log = forComponent('scratch');\n\n/** Default scratch dir (a path in the injected scratch FS). */\nexport const SCRATCH_DIR = '/scratch';\n\nfunction shortArgs(args: any): string {\n try { const s = JSON.stringify(args ?? {}); return s.length > 50 ? s.slice(0, 47) + '…' : s; } catch { return ''; }\n}\nconst slug = (s: string) => s.replace(/[^a-z0-9]+/gi, '-').replace(/^-+|-+$/g, '').toLowerCase().slice(0, 32) || 'out';\n\nexport interface ScratchOptions {\n /** Min result length (chars) to capture; smaller results pass through untouched. Default 1500. */\n threshold?: number;\n /** Dir within the scratch FS to write captures. Default SCRATCH_DIR. */\n dir?: string;\n /** Chars of the captured output to preview in the stub. Default 320. */\n previewChars?: number;\n}\n\n/**\n * Owns an (injected) scratch filesystem + a capture counter. `capture(tool)` wraps a tool so its\n * oversized string results spill to a scratch file and are replaced in context with a stub.\n */\nexport class Scratch {\n public options: Required<ScratchOptions>;\n private seq = 0;\n private dirReady?: Promise<void>;\n constructor(public fs: IFilesystem, options: ScratchOptions = {}) {\n this.options = { threshold: 1500, dir: SCRATCH_DIR, previewChars: 320, ...options };\n }\n\n /** Number of captures so far. */\n get count(): number { return this.seq; }\n\n /** Wrap a tool: oversized STRING results spill to a scratch file; everything else passes through. */\n capture(tool: AgentTool): AgentTool {\n const { threshold, dir, previewChars } = this.options;\n return {\n ...tool,\n run: async (args, ctx) => {\n const raw = await tool.run(args, ctx);\n if (typeof raw !== 'string' || raw.length <= threshold) return raw;\n const id = 'a' + ++this.seq;\n const path = `${dir}/${id}-${slug(tool.name)}.txt`;\n const header = `# ${tool.name}(${shortArgs(args)}) — ${raw.length} bytes\\n`;\n try { await (this.dirReady ??= mkdirp(this.fs, dir)); await this.fs.writeFile(path, header + raw); }\n catch (e) { log.debug('scratch write failed; returning raw', e); return raw; } // never lose data on FS error\n const preview = raw.slice(0, previewChars).replace(/\\s+/g, ' ').trim();\n return `[scratch ${path} · ${tool.name} · ${raw.length} bytes — full output saved out of context to keep it clean]\\n` +\n `preview: ${preview}…\\n` +\n `To pull a specific detail, Grep/Read ${path}, or call Ask({ question: \"…\", over: \"${path}\" }). Do NOT guess at what the preview cuts off.`;\n },\n };\n }\n\n /** Wrap many tools at once. */\n captureAll(tools: AgentTool[]): AgentTool[] { return tools.map((t) => this.capture(t)); }\n\n /**\n * Spill an oversized tool result to a scratch file and return PAGE 1 + a recoverable, paginated stub.\n * Drop-in for `Agent.capToolResult`: the agent sees usable content immediately and knows how to get\n * the rest (refine the query, Read the file in pages with offset/limit, or Ask to extract specifics).\n * Lossless — unlike a plain crop, the full output stays available on the scratch FS.\n */\n async spill(full: string, info: { tool: string; args: any }, pageBytes = 8000): Promise<string> {\n const { dir } = this.options;\n const id = 'a' + ++this.seq;\n const path = `${dir}/${id}-${slug(info.tool)}.txt`;\n const header = `# ${info.tool}(${shortArgs(info.args)}) — ${full.length} bytes\\n`;\n try { await (this.dirReady ??= mkdirp(this.fs, dir)); await this.fs.writeFile(path, header + full); }\n catch (e) { log.debug('scratch spill failed; cropping lossy', e); return full.slice(0, pageBytes) + `\\n\\n[output cropped to ${pageBytes} of ${full.length} bytes; full output unavailable (scratch write failed) — refine your query]`; }\n const head = full.slice(0, pageBytes);\n const nl = head.lastIndexOf('\\n');\n const page = nl > pageBytes * 0.5 ? head.slice(0, nl) : head;\n return `${page}\\n\\n[output cropped — page 1 (${page.length} of ${full.length} bytes). Full output saved to ${path}. ` +\n `To see more: refine your query/command to narrow it, or Read ${path} with offset/limit to page through it, or Ask({ question: \"…\", over: \"${path}\" }) to extract specifics.]`;\n }\n}\n\nexport interface AskOptions {\n /** The scratch filesystem to peek into (dedicated VFS holding only scratch files). */\n fs: IFilesystem;\n ai: ChatLike;\n /** Model for the peek — intentionally a CHEAP model; the caller synthesizes. */\n model: string;\n /** Step budget for the peek child (default 6). */\n maxSteps?: number;\n /** Scratch dir to search when `over` is omitted. Default SCRATCH_DIR. */\n dir?: string;\n}\n\nconst ASK_PROMPT =\n 'You are a retrieval-extraction step with Read, Grep and Glob over a scratch filesystem holding raw ' +\n 'outputs from earlier tools. Find the information that answers the question and return it concisely, ' +\n 'quoting values/facts verbatim. Do NOT add analysis or anything not grounded in the files. ' +\n 'If the answer is not present, say so plainly.';\n\n/**\n * `Ask` — peek into the scratch FS to answer a question WITHOUT loading raw data into the caller's\n * context. Spawns a cheap child agent (Read/Grep/Glob over scratch) that greps/reads and returns just\n * the answer. Pass `over` (a path) for a targeted peek, or omit to grep-discover.\n */\nexport function makeAskTool(o: AskOptions): AgentTool {\n const dir = o.dir ?? SCRATCH_DIR;\n return {\n name: 'Ask',\n description:\n 'Answer a question by peeking into the scratch files — large earlier outputs (web search, big reads, subagent reports) kept out of your context. ' +\n 'Pass `over` with a scratch path for a targeted lookup, or omit it to search the scratch dir. ' +\n 'Returns only the extracted answer; the full data never enters your context.',\n parameters: {\n type: 'object',\n required: ['question'],\n properties: {\n question: { type: 'string', description: 'what you need from the scratch files' },\n over: { type: 'string', description: 'scratch path to read, e.g. \"/scratch/a3-websearch.txt\"; omit to search' },\n },\n },\n async run({ question, over }) {\n const q = String(question ?? '').trim();\n if (!q) return 'Error: empty question';\n const child = new Agent({\n ai: o.ai,\n model: o.model,\n fs: o.fs,\n tools: toolsByName(['Read', 'Grep', 'Glob']),\n maxSteps: o.maxSteps ?? 6,\n systemPrompt: ASK_PROMPT,\n });\n const hint = over ? `Start by reading: ${over}.` : `Grep/Glob ${dir} to find the relevant file(s) first.`;\n try {\n const res = await child.run(`${hint}\\n\\nQuestion: ${q}`);\n const answer = (res.text ?? '').trim();\n return answer || '(no answer found in scratch)';\n } catch (e: any) {\n log.debug('Ask peek failed', e);\n return `Error querying scratch: ${e?.message ?? e}`;\n }\n },\n };\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\nimport type { Hooks, ToolUse } from './hooks';\nimport { writeFact } from './memory';\nimport { forComponent } from './logging';\n\nconst log = forComponent('Lessons');\n\n/**\n * Automatic mistake → lesson → steer loop. Closes the within-run learning gap: the agent\n * reacting to an error string is transient, but a RECURRING failure is a signal worth keeping.\n * This hook watches tool results for known failure patterns; once the SAME pattern recurs\n * `minRepeats` times in a run, it persists a corrective lesson to memory (deduped) — so the\n * NEXT session's `loadMemory` injects it as steering. Deterministic, edge-safe, no LLM call.\n *\n * Writes immediately on crossing the threshold (not on a clean stop), so a loop/budget kill —\n * exactly the runs that wasted effort — still leaves a lesson behind.\n */\nexport interface LessonOptions {\n fs: IFilesystem;\n /** Memory dir to persist lessons into (same dir loadMemory reads). */\n dir: string;\n /** How many times a pattern must recur before it's worth remembering. */\n minRepeats: number;\n}\n\nexport class LessonOptionsDefaults implements Partial<LessonOptions> {\n minRepeats = 2;\n}\n\n/** Known failure substring → the corrective lesson to persist. Maps OUR own tool errors to fixes. */\nconst LESSONS: { match: RegExp; slug: string; body: string }[] = [\n { match: /changed since it was read|stale/i, slug: 'lesson-stale-edit', body: 'Edit kept failing because the file changed since it was read (stale). Re-Read a file immediately before Editing it — do not Read far ahead of the Edit.' },\n { match: /is not unique|\\(\\d+ matches\\)/i, slug: 'lesson-edit-ambiguous', body: 'Edit kept failing because old_string was not unique. Include more surrounding lines to disambiguate, or batch with MultiEdit.' },\n { match: /has not been read yet/i, slug: 'lesson-read-before-edit', body: 'Edit was attempted before Reading the file. Always Read a file before Editing it.' },\n { match: /not found in/i, slug: 'lesson-edit-not-found', body: 'Edit old_string was not found. Re-Read the current file and copy the exact text (whitespace included) before Editing.' },\n { match: /unknown tool/i, slug: 'lesson-unknown-tool', body: 'A non-existent tool was called. Only call tools that are advertised in the current tool set.' },\n];\n\nconst isFailure = (result: string): boolean => /^Error:|^Blocked by hook:|^\\[exit [1-9]/.test(result);\n\n/**\n * Build a Hooks object that auto-captures recurring failures as memory lessons.\n * Compose it with the host's own hooks via `composeHooks`.\n */\nexport function lessonCapture(options: LessonOptions): Hooks {\n const o = { ...new LessonOptionsDefaults(), ...options } as LessonOptions;\n const counts = new Map<string, number>();\n const written = new Set<string>();\n return {\n async postToolUse(_call: ToolUse, result: string) {\n if (!isFailure(result)) return;\n const lesson = LESSONS.find((l) => l.match.test(result));\n if (!lesson || written.has(lesson.slug)) return;\n const n = (counts.get(lesson.slug) ?? 0) + 1;\n counts.set(lesson.slug, n);\n if (n < o.minRepeats) return;\n written.add(lesson.slug); // write-once per run, on crossing the threshold\n await writeFact(o.fs, o.dir, lesson.slug, lesson.body).catch((e) => log.warn(`could not persist ${lesson.slug}: ${e?.message ?? e}`));\n log.debug(`captured lesson ${lesson.slug} (recurred ${n}×)`);\n },\n };\n}\n","import type { IFilesystem } from '@livx.cc/wcli/core';\nimport type { ChatLike, ChatResponse, Message } from './llm';\nimport { contentText } from './llm';\nimport type { RunResult } from './Agent';\nimport { writeFact, slugify } from './memory';\nimport { forComponent } from './logging';\n\nconst log = forComponent('Reflect');\n\n/**\n * One-shot LLM reflection on a finished run. The deterministic `lessonCapture` hook only\n * knows OUR pre-mapped failure patterns; reflection catches NOVEL mistakes — it reads a digest\n * of what the run actually did and, if there's a durable lesson, persists it to memory so the\n * next session is steered. Costs exactly ONE model call, so it's meant for runs that went badly\n * (loop / budget / max_steps), not every run. Opt-in. Returns the slug written, or null.\n */\nexport interface ReflectOptions {\n ai: ChatLike;\n model: string;\n /** Filesystem + memory dir to persist the lesson into (same dir loadMemory reads). */\n fs: IFilesystem;\n dir: string;\n /** The finished run to reflect on. */\n result: RunResult;\n /** Bound the reflection prompt (chars of run digest). */\n maxDigestChars?: number;\n}\n\nexport async function reflectOnRun(o: ReflectOptions): Promise<string | null> {\n const digest = digestRun(o.result.messages, o.maxDigestChars ?? 6000);\n if (!digest.trim()) return null;\n const prompt =\n `A coding agent just finished a task with outcome \"${o.result.finishReason}\". Here is a digest of what it did:\\n\\n${digest}\\n\\n` +\n `If there is a DURABLE, reusable lesson that would help a FUTURE session avoid a mistake seen here, reply with exactly one line:\\n` +\n `LESSON: <imperative, specific, ≤200 chars>\\n` +\n `If the run was fine or the issue was purely task-specific (not generalizable), reply exactly: NONE`;\n\n let text = '';\n try {\n const r = (await o.ai.chat({ model: o.model, messages: [{ role: 'user', content: prompt }], stream: false })) as ChatResponse;\n text = r?.content ?? '';\n } catch (e: any) {\n log.warn(`reflection call failed: ${e?.message ?? e}`);\n return null;\n }\n\n const m = text.match(/LESSON:\\s*(.+)/i);\n const lesson = m?.[1]?.trim().slice(0, 200) ?? '';\n if (!lesson || /^none\\b/i.test(lesson)) return null;\n\n const slug = ('lesson-' + slugify(lesson)).slice(0, 56);\n try {\n await writeFact(o.fs, o.dir, slug, lesson);\n } catch (e: any) {\n log.warn(`could not persist lesson: ${e?.message ?? e}`);\n return null;\n }\n log.debug(`reflection persisted ${slug}`);\n return slug;\n}\n\n/** Compact, bounded digest of a run: assistant intents + tool calls + their results (errors included). */\nfunction digestRun(messages: Message[], maxChars: number): string {\n const lines: string[] = [];\n for (const m of messages) {\n if (m.role === 'assistant' && m.content) lines.push(`assistant: ${contentText(m.content).slice(0, 200)}`);\n for (const tc of m.tool_calls ?? []) lines.push(`tool ${tc.function.name}(${(tc.function.arguments ?? '').slice(0, 120)})`);\n if (m.role === 'tool' && m.content) lines.push(` → ${contentText(m.content).split('\\n')[0].slice(0, 200)}`);\n }\n // defense-in-depth: untrusted run content (file bodies, tool output) is DATA, not instructions —\n // neutralize a literal `LESSON:` so a crafted file can't spoof the reply format we parse below.\n const out = lines.join('\\n').replace(/LESSON:/gi, 'lesson(reported):');\n return out.length > maxChars ? out.slice(0, maxChars) + '\\n… (truncated)' : out;\n}\n","/**\n * DuplexAgent — voice-optimized three-tier conversational engine, composed on top of `Agent`.\n *\n * Three cognitive tiers (like a human brain):\n * REFLEX — fast voice agent (streams instant replies, owns THE transcript, the only voice the\n * user hears). Handles simple questions, routes complex work to Act or Think.\n * ACT — standard worker (Sonnet-class). Full tools, file access, shell. The hands.\n * THINK — premium reasoning (Opus-class). Deep analysis, architecture, hard problems. The brain.\n *\n * Workers are spawned per escalation via `Act`/`Think` tools. Results are pushed back as\n * `[task <id> completed] …` events and re-voiced by the reflex — push, not poll.\n *\n * Host events (via the open HostEvent union): the voice agent's standard `text_delta` stream,\n * plus `task_started` / `task_progress` / `task_done` / `task_error` / `task_cancelled`.\n */\nimport type { IFilesystem } from '@livx.cc/wcli/core';\nimport { MemFilesystem } from '@livx.cc/wcli/core';\nimport { Agent, AgentOptions, type RunResult } from './Agent';\nimport type { ChatLike, MessageContent } from './llm';\nimport { contentText } from './llm';\nimport type { AgentTool, HostBridge } from './tools';\nimport type { ToolUse, Hooks } from './hooks';\nimport { composeHooks } from './permissions';\nimport { forComponent } from './logging';\nimport { loadMemory, VOICE_MEMORY_PROMPT } from './memory';\n\nconst log = forComponent('DuplexAgent');\n\n/** One speakable line for a tool call: name + a short hint from its first string arg. */\nfunction describeCall(call: ToolUse): string {\n const v = call.args && Object.values(call.args).find((x) => typeof x === 'string' && (x as string).trim());\n const hint = v ? ` (${String(v).replace(/\\s+/g, ' ').trim().slice(0, 48)})` : '';\n return `${call.name}${hint}`;\n}\n\nexport type DuplexTaskStatus = 'running' | 'done' | 'error' | 'cancelled';\n\nexport interface TaskRecord {\n id: string;\n label: string;\n status: DuplexTaskStatus;\n controller: AbortController;\n /** Settles when the worker finished AND its completion was processed. Never rejects. */\n promise: Promise<void>;\n /** Rolling activity tail (tool calls + last-result previews, capped) — feeds task inspection UIs. */\n tail: string[];\n /** Final report text (or error message) once the task settled. */\n result?: string;\n}\n\nexport type WorkerTier = 'act' | 'think';\n\nexport class DuplexAgentOptions {\n /** Any ai.libx.js AIClient — shared by all tiers (routed by model). */\n ai!: ChatLike;\n /** The WORKER's filesystem (act + think). If omitted the worker keeps Agent's jailed-disk-at-cwd default. */\n fs?: IFilesystem;\n // The reflex IS the voice. 120b (not 20b) for channel discipline + instruction-following: the 20b\n // mislabels gpt-oss harmony channels under load, leaking raw analysis into the spoken `final` channel\n // (and misfiring Hold). 120b is the same price tier (~$0.15/$0.60) — the quality/cost trade is free.\n reflexModel = 'groq/openai/gpt-oss-120b';\n actModel = 'anthropic/claude-sonnet-4-6';\n /** Premium reasoning model. Set to `false` to disable the Think tier entirely. */\n thinkModel: string | false = 'anthropic/claude-opus-4-8';\n /** Per-worker providerOptions, derived from the worker's actual model at spawn time (IoC — keeps duplex\n * provider-agnostic). Workers override the reflex/main model, so provider-specific options (e.g. cursor's\n * cwd/cursorSession) must be recomputed for the worker's model, never inherited from the main template —\n * leaking cursor options to an anthropic worker is a hard 400. Returns undefined → no providerOptions. */\n providerOptionsFor?: (model: string) => Record<string, unknown> | undefined;\n /** Escape hatches merged over the derived per-agent options. */\n reflexOptions?: Partial<AgentOptions>;\n actOptions?: Partial<AgentOptions>;\n thinkOptions?: Partial<AgentOptions>;\n /** Fresh-context check on each successful Act task: a NEW agent (no self-confirmation bias) re-reads\n * the file state against the brief and fixes any gap before the result is re-voiced. Bounded to one\n * pass; ~2x Act cost so default OFF. The self-verify FOOTER (same context) was measured ineffective —\n * this is the structural fix (see mind/10). Think tasks are pure reasoning, never checked. */\n verifyActTasks = false;\n /** Receives the voice text_delta stream + task lifecycle events. */\n host?: HostBridge;\n /** How many recent transcript messages are rendered into a worker's brief. */\n excerptTurns = 6;\n /** Voice register: 'neutral' = clean spoken style; 'conversational' = human-like — fillers,\n * backchannels, impulsive first reactions before content (mimics real duplex conversation). */\n voiceStyle: 'neutral' | 'conversational' = 'neutral';\n /** Awaited BEFORE a worker spawns — open a per-task checkpoint frame, audit, etc.\n * (post-spawn would race the worker's first edits). */\n onTaskStart?: (id: string, label: string) => void | Promise<void>;\n /** Re-voice throttled worker progress asides ('[task t1 progress] …') so long tasks aren't dead\n * air. Off by default — each update costs a voice turn (LLM call + speech). */\n progressUpdates = false;\n /** Min ms between progress re-voices per task. */\n progressIntervalMs = 25_000;\n /** Relay worker questions (AskUserQuestion + permission asks via parkQuestion) through the VOICE:\n * the question re-voices as '[task <id> asks] …', the user answers conversationally, and the\n * voice model resolves it with the AnswerTask tool. Off → host.ask passthrough (text menus). */\n askRelay = false;\n /** Parked questions auto-resolve empty after this long (callers map '' to deny/best-judgment). */\n askTimeoutMs = 120_000;\n /** Max retained task records: oldest SETTLED tasks (and their activity tails) are evicted past this,\n * bounding memory over a long-lived session. Running tasks are never evicted. */\n maxTaskRecords = 50;\n /** Host overrides for QuickLook lookups (keyed by `what`). The engine's defaults go through the\n * (possibly jailed) fs — e.g. `.git/**` is deny-listed, so the CLI supplies 'branch' itself. */\n quickLook?: Record<string, (path?: string) => string | Promise<string>>;\n /** Memory directory/directories on the WORKER fs. If set, the voice agent gets Remember + Recall\n * tools directly (no delegation needed) and implicit capture guidance. */\n memoryDir?: string | string[];\n /** User-scope memory dir for global facts (type=user/feedback). Forwarded to Remember's routing. */\n memoryUserDir?: string;\n}\n\n/** `[task t1 completed]` / `… failed` / `… progress` / `… asks` are HOST event markers — they may\n * only ever reach the user from a real task lifecycle event, never from the reflex's own stream. A\n * weak reflex sometimes fabricates one and continues with a made-up answer while the real task is\n * still running (it imitates the event syntax). This finds the first such marker so the spoken text\n * can be cut there — the legit ack before it survives, the fabricated tail is dropped. */\nexport const RESERVED_EVENT_MARKER = /\\[task\\b[^\\]\\n]*\\b(?:completed|failed|progress|asks)\\b/i;\n\nexport const VOICE_SYSTEM_PROMPT =\n 'You are a spoken voice assistant — the user HEARS everything you say. Use short sentences. One idea per sentence. ' +\n 'No markdown, no bullet lists, no code blocks, no headings, no emoji.\\n' +\n 'This holds even when asked to \"print\", \"list\", \"show\", or \"make a table\" — there is no screen for the spoken channel. Speak it as flowing prose (\"Tuesday is half a meter, Wednesday a bit less…\"), or if they truly need it on screen, route it to Act to render. Never emit dashes or pipes into speech.\\n' +\n 'Keep turns SHORT — one to three sentences, then stop. Never lecture, enumerate cases, or add caveats unprompted. ' +\n 'Conversation is a fast exchange: give the one thing asked, and let the user pull more if they want it.\\n' +\n 'You have three cognitive tiers — like a human brain:\\n' +\n '• YOU (reflex) — instant, lightweight. Handle greetings, simple questions, status checks, QuickLook.\\n' +\n '• `Act` — your hands. A background worker with its own configured tools and access to the user\\'s environment (files and shell{{WORKER_WEB}}). Use for reading, editing, searching, running tasks, building — any real work.\\n' +\n '{{THINK_SLOT}}\\n' +\n 'When you are unsure whether you can do or access something, do NOT assume and do NOT claim a capability you have not confirmed. To check what you can do, QuickLook `capabilities` (instant — it lists your worker\\'s real tools) and answer from that. Never promise an ability that is not in your capabilities; if it is not there, tell the user plainly you can\\'t. To actually DO real work, call `Act`. ' +\n 'When the user mentions their project, folder, files, or environment (\"this project\", \"the current folder\", \"my code\"), call `Act` IMMEDIATELY — do not ask for paths or details the worker can discover itself. ' +\n 'Never pretend to have done the work or invent results — the worker\\'s report is your only source.\\n' +\n 'You cannot mute the microphone or stop voice capture yourself — no tool does it. If the user asks you to stop listening or turn the voice off, never claim you did: tell them to say exactly \"voice off\" (handled by the app directly), or type /voice.\\n' +\n 'You are NOT a knowledge base. For any question whose answer needs SPECIFIC verifiable facts you do not already have in hand — how to build/configure/implement something, exact API, library, entitlement, command or option names, current events, or particular numbers, dates, or names — do NOT answer from your own memory: you will confidently make things up (a fake API, a wrong entitlement, an event that did not happen). Route it to `Act`, which can search and verify, and speak only what its report says. Answer inline ONLY for general conversation, chit-chat, and trivia you are sure of, or facts you can see via QuickLook. When elaborating on a completed task (\"tell me more\", \"the gist\"), stay strictly within what that result actually said — if the user asks for something the result did not cover, that is NEW information: dispatch `Act`, do not improvise.\\n' +\n 'ALWAYS react before you work: the FIRST thing in your turn is a brief spoken acknowledgement of what you heard and what you are about to do (\"got it — opening that now\", \"sure, let me pull it up\", \"okay, checking\"). NEVER call a tool (Act, Think, QuickLook) silently — the user must hear you react before you go quiet to work. After dispatching Act or Think, that same one short sentence IS your turn — end it and do not wait for the result.\\n' +\n 'Results arrive later as events like \"[task t1 completed] …\" or \"[task t1 failed] …\". When one arrives, speak the USEFUL gist in one or two short sentences — the actual answer the user wanted (the headline finding, the key numbers), not the thinnest possible \"it\\'s done\". A forecast → say it\\'s calm AND that it\\'s good for swimming but not surf; a count → say the number. Be brief, but do not drop the substance. ' +\n 'If the result is a LIST (search results, multiple files/matches), the user CANNOT see it — there is no screen and no numbered menu to point at. Speak the gist: say what you found and name the top one or two by NAME (the source, not \"the first one\" or a number), then ask plainly if they want more. Never ask them to \"pick which one\" or reference items by position. ' +\n 'The completed result stays in YOUR context — it is yours to draw on. When the user follows up (\"tell me more\", \"what else\", \"and?\"), answer FROM that result first: you already have the detail, so elaborate on what you have. Do NOT spawn a fresh worker to re-search or re-gather what you were just handed. Re-dispatch ONLY when genuinely new information is needed — e.g. the user wants the full contents of a SPECIFIC source, which is one WebFetch of that URL, not a brand-new search. ' +\n '\"[task t1 progress] …\" events are interim status, NOT results — give at most a half-sentence aside (\"still on it — running tests now\") and end your turn. Never present progress as a finished result.\\n' +\n 'CRITICAL: while a task is still running you have NO answer yet — never state a specific result of any kind (a number, size, count, name, path, or value). The real answer arrives ONLY in the \"[task … completed]\" event; inventing one meanwhile (a made-up disk size, commit count, etc.) is a serious error. Until then, only acknowledge and wait.\\n' +\n 'Never read raw file paths, diffs, or code aloud verbatim.\\n' +\n 'Do NOT end every turn with the same canned offer (\"want a rundown?\", \"want the steps?\"). Offer once at most; if the user pushes back, repeats themselves, or sounds unsatisfied (\"you know what I mean?\", \"think deeper\", \"are you sure?\"), do NOT re-offer the same thing — change approach: dispatch `Act`/`Think` to actually dig in, or ask one concrete clarifying question. Repeating a non-answer is worse than silence.\\n' +\n '\"[task t1 asks] …\" events are QUESTIONS from a background task — relay to the user in your own words, short, then end your turn. When the user answers, call `AnswerTask` with that id and their answer. NEVER answer on the user\\'s behalf for permissions or risky operations; if their reply is ambiguous, confirm first.\\n' +\n 'If the user\\'s message sounds INCOMPLETE — trailing off mid-sentence, a fragment that needs more context (\"and then we\", \"but the problem is\"), hesitation fillers (\"uh\", \"um\") — call `Hold` instead of answering. This keeps listening for the rest of their thought. Only respond with substance when you have a complete question or request.\\n' +\n 'Dispatch discipline: send ONE self-contained task per request — a single worker with the full brief beats several workers with fragments (each worker starts fresh and re-discovers context). ' +\n 'NEVER dispatch a worker just to read files or gather information — workers explore and discover context themselves; pass on what you already know and let one worker do the whole job. ' +\n 'Split into parallel tasks only when the user asks for genuinely independent things. ' +\n 'When a task completes, report its result and stop — do NOT dispatch follow-up work (verification, polish, extras) the user did not ask for, unless the report itself signals failure or doubt.\\n' +\n 'Do not fire a second Act/Think for work already in flight, and NEVER spawn a second task to re-count, cross-check, or verify a result a worker already gave you — trust its answer; a single question gets ONE task. ' +\n 'Call `TaskStatus` at most ONCE per turn; if a task is still running, just say \"still on it\" and end the turn — never poll it again and again in a loop. Use `CancelTask` when the user asks to stop something.\\n' +\n 'PRIORITY: when the user says goodbye or wants to end/finish/wrap up the session (\"ok bye\", \"that\\'s all\", \"let\\'s finish\", \"let\\'s end\", \"goodnight\", \"exit\", \"wrap up\"), call `ExitSession` IMMEDIATELY — do not act, do not check status, just exit.\\n' +\n 'For TRIVIAL instant lookups only — current time, git branch, listing a folder, peeking at a small file, or checking your own `capabilities`/tools — use `QuickLook` (instant, no task). Whenever the user asks what you can do or whether you have some ability, QuickLook `capabilities` and answer from that — never guess. Anything requiring searching, reasoning, running commands, or editing goes through `Act`.\\n' +\n '{{MEMORY_SLOT}}\\n' +\n 'User messages may arrive via speech-to-text and can carry transcription artifacts — odd words, cut-offs, homophones (\"for you\" vs \"folder\"). Read for INTENT, not surface text. If a message seems garbled or surprising, briefly confirm what they meant (\"did you mean…?\") instead of answering the literal words.';\n\nconst THINK_GUIDANCE =\n '• `Think` — your brain. A premium reasoning model, FAR more expensive than Act. Reserve it for open-ended architecture/design questions, or a problem Act already FAILED at. ' +\n 'ALL implementation work — coding, refactoring, debugging, edge cases, tests — goes to Act; Act is highly capable. Never send the same work to both.';\nconst THINK_DISABLED_GUIDANCE =\n '(Think tier is not available — use Act for all escalations.)';\n\n/** Appended for `voiceStyle: 'conversational'` — a human conversational register over the base rules. */\nexport const VOICE_STYLE_CONVERSATIONAL =\n 'Speak like a person in a live conversation, not an assistant reading a script. ' +\n 'React first, then deliver: a quick impulsive beat (\"oh nice\", \"hmm, hold on\", \"ah, got it\") before the substance. ' +\n 'Use contractions always. Vary sentence length — some very short. ' +\n 'Light fillers and backchannels are fine (\"mm-hm\", \"right\", \"let\\'s see\") but at most one per reply — never stack them. ' +\n 'When you escalate to Act or Think, say it like a human would (\"hang on, let me actually dig into that — gimme a minute\") instead of announcing a task. ' +\n 'When a result comes back, react to it like you just found out (\"okay so — turns out…\"). ' +\n 'Match the user\\'s energy: a quick question gets a quick answer — a few words is a perfectly good turn. ' +\n 'Prefer a short answer plus an offer (\"want the details?\") over covering everything. ' +\n 'Never narrate your own mechanics (no \"I will now act\", no task ids out loud).';\n\n/**\n * The duplex orchestrator. `send()` enqueues a user turn on the reflex agent; `Act`/`Think`\n * spawn detached workers whose completions enqueue re-voice turns. A promise-chain\n * mutex serializes all voice turns so streams never interleave, and completions that\n * pile up while the voice is busy are coalesced into a single re-voice turn.\n */\nexport class DuplexAgent {\n public options: DuplexAgentOptions;\n public readonly voice: Agent;\n public readonly tasks = new Map<string, TaskRecord>();\n private queue: Promise<unknown> = Promise.resolve();\n private seq = 0;\n private pendingEvents: string[] = [];\n private flushQueued = false;\n /** Per-voice-turn guards (reset by resetTurn at each turn's start). The reflex is a weak model:\n * left unguarded it polls TaskStatus after a dispatch and/or dispatches silently (dead air).\n * Like CC's Task tool, a dispatch is \"said my piece, now wait for the push\" — these enforce that. */\n private turnDispatched = false; // an Act/Think fired this turn\n private turnBriefs = new Set<string>(); // briefs dispatched this turn (detect identical re-dispatch)\n private spokeThisTurn = false; // any non-empty text_delta streamed this turn\n private nudging = false; // re-ack pass in flight: block ALL tools, prevent recursion\n private reflexBuf = ''; // accumulated reflex text this turn (fabricated-event detection)\n private reflexForwarded = 0; // chars of reflexBuf already forwarded to the host/TTS\n private fabricationCut = false; // reflex emitted a reserved [task …] marker → suppress its tail\n /** Parked worker questions awaiting a (voice-relayed) user answer, keyed by ask id. */\n public readonly pendingAsks = new Map<string, { question: string; resolve: (answer: string) => void }>();\n\n /** Lazily resolved memory tools (async loadMemory runs in initMemory). */\n private memoryReady: Promise<{ tools: AgentTool[]; index: string }> | undefined;\n\n constructor(options?: Partial<DuplexAgentOptions>) {\n this.options = { ...new DuplexAgentOptions(), ...options };\n const o = this.options;\n // Kick off async memory load early (resolves before first send via initMemory guard).\n if (o.memoryDir && o.fs) {\n this.memoryReady = loadMemory(o.fs, o.memoryDir, { maxWritesPerSession: 10, userDir: o.memoryUserDir });\n }\n // Resolve template slots in the voice prompt.\n const memSlot = o.memoryDir && o.fs\n ? VOICE_MEMORY_PROMPT\n : 'NEVER claim to have stored, saved, or remembered something durably — you cannot. Anything the user wants persisted (their name, preferences, notes) must go through Act so a worker writes it to memory.';\n const thinkSlot = o.thinkModel !== false ? THINK_GUIDANCE : THINK_DISABLED_GUIDANCE;\n // Tell the reflex up-front whether its worker can reach the web, so it dispatches web lookups to\n // Act instead of declining from priors (the weak reflex defaults to \"I can't search\" otherwise).\n const workerToolNames = (o.actOptions?.tools ?? []).map((t) => t.name);\n const canSearch = workerToolNames.some((n) => /WebSearch/i.test(n));\n const canFetch = workerToolNames.some((n) => /WebFetch/i.test(n));\n const workerWeb = canSearch\n ? ', and it CAN search the web and read web pages — so when the user gives you something specific to look up (\"search for X\", \"find me…\", \"what\\'s the latest on…\"), route it to Act. But a bare capability QUESTION like \"can you search the web?\" just gets a short spoken \"yes, I can\" — do NOT dispatch and NEVER invent a query the user did not give you'\n : canFetch\n ? ', and it can fetch a specific web page URL (but cannot search the web)'\n : '';\n // MCP servers reach the worker via providerOptions (cursor/*) or as mcp__ tools — inject them so the\n // reflex KNOWS its real reach without a QuickLook (the weak reflex won't reliably look before it\n // answers \"can you…?\", and was FALSELY DENYING browser control it actually has).\n const mcpNames = [\n ...Object.keys((o.actOptions?.providerOptions as any)?.mcpServers ?? {}),\n ...new Set(workerToolNames.filter((n) => n.startsWith('mcp__')).map((n) => n.slice(5).split('__')[0])),\n ];\n const workerMcp = mcpNames.length\n ? `, and it can use these MCP servers: ${[...new Set(mcpNames)].join(', ')}` +\n (mcpNames.some((n) => /browser/i.test(n)) ? ' — including driving a REAL browser (open tabs, navigate, click, screenshot), so answer \"yes\" if asked whether you can control/drive a browser and route an actual browse to Act' : '')\n : '';\n const prompt = VOICE_SYSTEM_PROMPT\n .replace('{{MEMORY_SLOT}}', memSlot)\n .replace('{{THINK_SLOT}}', thinkSlot)\n .replace('{{WORKER_WEB}}', workerWeb + workerMcp)\n + (o.voiceStyle === 'conversational' ? '\\n' + VOICE_STYLE_CONVERSATIONAL : '')\n + `\\nToday's date: ${new Date().toDateString()}.`;\n const tools: AgentTool[] = [\n ...(o.reflexOptions?.tools ?? []),\n this.actTool(),\n ...(o.thinkModel !== false ? [this.thinkTool()] : []),\n this.taskStatusTool(), this.cancelTaskTool(), this.quickLookTool(), this.answerTaskTool(), this.holdTool(),\n ];\n // Tap the voice stream so we know whether the model actually SPOKE this turn (drives the\n // dead-air re-ack). Delegates the real host transparently — ask/confirm pass straight through.\n // (Explicit forwarding, not `{...o.host}`: spreading a class instance drops its prototype methods.)\n const host = o.host;\n const voiceHost: HostBridge | undefined = host && {\n ask: host.ask ? (q) => host.ask!(q) : undefined,\n confirm: host.confirm ? (p, m) => host.confirm!(p, m) : undefined,\n notify: (ev) => {\n // Sanitize the reflex's spoken stream: it must never emit a reserved [task …] event marker.\n // If it does, it's fabricating a result while the real task is still in flight — cut the\n // spoken text at the marker (keeping the legit ack) and suppress the rest of the turn so the\n // hallucinated report never reaches TTS. See RESERVED_EVENT_MARKER + mind/10.\n if (ev?.kind === 'text_delta' && typeof (ev as any).message === 'string') {\n if (this.fabricationCut) return; // already cut this turn → drop the tail\n const msg = (ev as any).message as string;\n this.reflexBuf += msg;\n const m = this.reflexBuf.match(RESERVED_EVENT_MARKER);\n if (m) {\n this.fabricationCut = true;\n log.warn(`reflex fabricated a [task …] event in its spoken stream — cutting it (kept ${m.index} chars)`);\n const safe = this.reflexBuf.slice(this.reflexForwarded, m.index); // unforwarded text before the marker\n if (!safe) return;\n if (safe.trim()) this.spokeThisTurn = true;\n host.notify?.({ ...ev, message: safe } as any);\n return;\n }\n this.reflexForwarded = this.reflexBuf.length;\n if (msg.trim()) this.spokeThisTurn = true;\n }\n host.notify?.(ev);\n },\n };\n this.voice = new Agent({\n ai: o.ai,\n fs: new MemFilesystem(),\n model: o.reflexModel,\n stream: true,\n host: voiceHost,\n // The reflex IS the conversational channel — it confirms ambiguity inline (\"did you mean…?\"),\n // never via the blocking AskUserQuestion tool (Agent auto-adds it whenever a host is set). Left in,\n // it stalls a voice turn until the kill-switch. Worker questions still reach the user via parkQuestion.\n askUserQuestion: false,\n systemPrompt: prompt,\n instructionFiles: false,\n maxSteps: 8,\n timeoutMs: 30_000,\n ...o.reflexOptions,\n tools,\n // Composed AFTER the spread so the dispatch guard can't be dropped by reflexOptions.\n hooks: composeHooks(this.dispatchGuard(), o.reflexOptions?.hooks),\n });\n }\n\n /** Resolve memory tools + inject index into voice system prompt (once). */\n private async initMemory(): Promise<void> {\n if (!this.memoryReady) return;\n const mem = await this.memoryReady;\n this.memoryReady = undefined; // one-shot\n // Append memory tools to the voice agent's active set.\n (this.voice.options.tools as AgentTool[]).push(...mem.tools);\n // Inject memory index into the system prompt.\n if (mem.index) this.voice.options.systemPrompt += '\\n\\n' + mem.index;\n }\n\n /** Clear the per-turn guards. Called at the head of every voice turn (user send + re-voice flush). */\n private resetTurn(): void {\n this.turnDispatched = false;\n this.turnBriefs.clear();\n this.spokeThisTurn = false;\n this.reflexBuf = '';\n this.reflexForwarded = 0;\n this.fabricationCut = false;\n this.voice.options.toolChoice = undefined; // clear any post-dispatch tool lock from the previous turn\n }\n\n /** preToolUse guard on the reflex: once it has dispatched this turn, a dispatch is \"said my piece,\n * now wait for the push\" (CC's Task model). Block the temptations — TaskStatus polling and identical\n * re-dispatch — so the only remaining move is to voice a short ack and end. A genuinely NEW Act is\n * still allowed (parallel independent work). During a re-ack pass, block every tool. */\n private dispatchGuard(): Hooks {\n return {\n preToolUse: (call: ToolUse) => {\n if (this.nudging) return { block: true, reason: 'Just say one short spoken acknowledgement — no tools this turn.' };\n if (!this.turnDispatched) return;\n if (call.name === 'TaskStatus')\n return { block: true, reason: 'You just dispatched a task this turn — do NOT poll. Give one short spoken acknowledgement and end your turn; the result arrives later as a [task …] event.' };\n if ((call.name === 'Act' || call.name === 'Think') && this.turnBriefs.has(String(call.args?.brief ?? '')))\n return { block: true, reason: 'You already dispatched this exact task — acknowledge briefly and end your turn.' };\n },\n };\n }\n\n /** True when the just-finished turn dispatched a task but voiced nothing — dead air to repair.\n * Requires a host: without one there's no stream to detect speech on (and no one to speak to). */\n private get silentDispatch(): boolean {\n return !!this.options.host && this.turnDispatched && !this.spokeThisTurn;\n }\n\n /** A dispatch with no spoken text is dead air. Re-prompt the reflex ONCE so the LLM itself voices a\n * short ack (no template). If it STILL says nothing, fall back to a minimal line so silence never ships. */\n private async ackIfSilent(): Promise<void> {\n this.nudging = true;\n try {\n await this.voice.send('[reminder] You dispatched a task but said nothing to the user. Say ONE short spoken acknowledgement now — no tools.');\n } catch (e) {\n log.warn(`ack nudge failed: ${e instanceof Error ? e.message : e}`);\n } finally {\n this.nudging = false;\n }\n if (!this.spokeThisTurn) this.options.host?.notify?.({ kind: 'text_delta', message: 'Okay, on it.' });\n }\n\n /** One user turn: the voice agent streams the reply (and may Act/Think). Serialized with re-voice turns. */\n send(content: MessageContent): Promise<RunResult> {\n return this.enqueue(async () => {\n await this.initMemory();\n this.resetTurn();\n const res = await this.voice.send(content);\n if (this.silentDispatch) await this.ackIfSilent();\n return res;\n });\n }\n\n /** Cancel a running background task — shared by the CancelTask tool and the CLI /tasks picker. */\n cancelTask(id: string): string {\n const rec = this.tasks.get(id);\n if (!rec) return `No task '${id}'.`;\n if (rec.status !== 'running') return `Task ${rec.id} is already ${rec.status}.`;\n rec.status = 'cancelled';\n rec.controller.abort();\n return `Task ${rec.id} (${rec.label}) cancelled.`;\n }\n\n /** Resolve when all queued voice turns AND all in-flight worker tasks have settled (tests, graceful shutdown). */\n async idle(): Promise<void> {\n while (true) {\n const q = this.queue;\n await q.catch(() => {});\n await Promise.all([...this.tasks.values()].map((t) => t.promise));\n // a worker completion may have enqueued a re-voice turn meanwhile — loop until quiescent\n if (this.queue === q && ![...this.tasks.values()].some((t) => t.status === 'running')) return;\n }\n }\n\n /** Promise-chain mutex: turns run strictly one at a time; a failed turn doesn't poison the chain. */\n private enqueue<T>(fn: () => Promise<T>): Promise<T> {\n const run = this.queue.then(fn, fn);\n this.queue = run.then(() => {}, () => {});\n return run;\n }\n\n private notify(kind: string, message: string, data?: unknown): void {\n this.options.host?.notify?.({ kind, message, data });\n }\n\n /** Queue a `[task …]` event for re-voicing. Events arriving while the voice is busy coalesce into ONE turn. */\n private queueRevoice(event: string): void {\n this.pendingEvents.push(event);\n if (this.flushQueued) return;\n this.flushQueued = true;\n void this.enqueue(async () => {\n this.flushQueued = false; // events landing during this send() get their own flush turn\n const events = this.pendingEvents.splice(0);\n if (!events.length) return;\n this.resetTurn();\n await this.voice.send(events.join('\\n'));\n if (this.silentDispatch) await this.ackIfSilent();\n // A re-voice turn ends OUTSIDE any host send() callsite — signal it so a line-buffered\n // renderer (CLI MarkdownStream) can flush its tail (else the last partial line is swallowed).\n this.notify('revoice_done', '');\n });\n }\n\n /** The worker's brief: the Act/Think args + a STATIC text snapshot of the recent conversation.\n * Act briefs get a self-verify footer — the worker's report is trusted without review, so it\n * must check its own work before reporting (nearly free under prompt caching; measured honest:\n * it does NOT fix one-shot logic bugs — see mind/10). Think tasks are pure reasoning — no footer. */\n private buildBrief(brief: string, tier: WorkerTier = 'act'): string {\n const recent = this.voice.transcript\n .filter((m) => (m.role === 'user' || m.role === 'assistant') && contentText(m.content).trim())\n .slice(-this.options.excerptTurns)\n .map((m) => `${m.role}: ${contentText(m.content)}`)\n .join('\\n');\n const verify = tier === 'act'\n ? '\\n\\nBefore reporting done: re-read what you changed and check it against EVERY requirement above — fix any gap first. Your report is trusted without review.'\n : '';\n return (recent ? `${brief}\\n\\n## Recent conversation (for context)\\n${recent}` : brief) + verify;\n }\n\n /** Spawn a detached worker for task `id`; its settlement notifies + enqueues the re-voice turn. */\n private spawnWorker(id: string, label: string, briefText: string, tier: WorkerTier = 'act'): void {\n const o = this.options;\n const tierOpts = tier === 'think' ? o.thinkOptions : o.actOptions;\n const tierModel = tier === 'think' ? (o.thinkModel as string) : o.actModel;\n const controller = new AbortController();\n const base = tierOpts?.hooks ?? o.actOptions?.hooks;\n const report = o.progressUpdates ? this.progressReporter(id) : undefined;\n // Rolling activity tail (always on, unlike the gated progress re-voicer) — backs /tasks inspection.\n const tail: string[] = [];\n const pushTail = (line: string) => { tail.push(line.slice(0, 200)); if (tail.length > 120) tail.splice(0, tail.length - 120); };\n const hooks = {\n ...base,\n preToolUse: async (call: ToolUse, meta?: any) => { const d = await base?.preToolUse?.(call, meta); pushTail(`⚙ ${describeCall(call)}`); report?.pre(call); return d; },\n postToolUse: async (call: ToolUse, result: string, meta?: any) => {\n await base?.postToolUse?.(call, result, meta);\n const last = result?.trim().split('\\n').filter(Boolean).pop();\n if (last) pushTail(` ↳ ${last}`);\n report?.post(call);\n },\n onToolOutput: (call: ToolUse, chunk: string, meta?: any) => { base?.onToolOutput?.(call, chunk, meta); report?.output(chunk); },\n };\n const relayAsk = async (q: { question: string; options?: Array<{ label: string }> }): Promise<string> => {\n const opts = q.options?.length ? ` Options: ${q.options.map((x) => x.label).join(', ')}.` : '';\n const a = await this.parkQuestion(id, `${q.question}${opts}`);\n return a || '(no answer from the user — use your best judgment and note the assumption)';\n };\n const workerHost: HostBridge | undefined = o.askRelay ? { ask: relayAsk } : o.host?.ask ? { ask: (q) => o.host!.ask!(q) } : undefined;\n const agentOpts: Partial<AgentOptions> = {\n ai: o.ai,\n fs: o.fs,\n model: tierModel,\n ...(tier === 'think' ? { reasoning: tierOpts?.reasoning ?? 'high' } : {}),\n ...tierOpts,\n // Recompute providerOptions for THIS worker's model (after tierOpts so it wins over any inherited\n // main-template value) — prevents cursor-only cwd/cursorSession leaking onto an anthropic worker.\n providerOptions: o.providerOptionsFor?.(tierModel),\n ...(workerHost ? { host: workerHost } : {}),\n ...(hooks ? { hooks } : {}),\n signal: controller.signal, // shared with the checker so a cancel tears down both\n };\n const promise = new Agent(agentOpts)\n .run(briefText)\n .then((res) => this.maybeVerify(id, briefText, res, tier, agentOpts))\n .then((res) => this.onWorkerSettled(id, res))\n .catch((err) => this.onWorkerFailed(id, err));\n this.tasks.set(id, { id, label, status: 'running', controller, promise, tail });\n // Evict oldest settled records past the cap (Map preserves insertion order) — running tasks stay.\n if (this.tasks.size > this.options.maxTaskRecords)\n for (const [tid, rec] of this.tasks) {\n if (this.tasks.size <= this.options.maxTaskRecords) break;\n if (rec.status !== 'running') this.tasks.delete(tid);\n }\n }\n\n /** Fresh-context check of a successful Act task: a NEW agent (same model/fs/tools, but NO shared\n * conversation context) re-reads the file state against the brief and fixes any gap. The fix lands\n * on the shared fs automatically (workers write fs directly, no overlay), so grading sees the\n * corrected state. Bounded to ONE pass. Off unless `verifyActTasks`; never runs for think/failed/\n * cancelled tasks. Usage is merged so /cost reflects the real (worker + checker) spend. */\n private async maybeVerify(id: string, briefText: string, res: RunResult, tier: WorkerTier, agentOpts: Partial<AgentOptions>): Promise<RunResult> {\n if (!this.options.verifyActTasks || tier !== 'act' || res.finishReason !== 'stop') return res;\n if (this.tasks.get(id)?.status === 'cancelled') return res; // user stopped it — don't spend on a check\n const checkBrief = `${briefText}\\n\\n## VERIFY MODE\\nAnother agent just implemented the above. Independently check the CURRENT state of the files against EVERY requirement. Fix any gap you find. If everything is already correct, make NO changes — do not refactor or improve — and report \"verified\".`;\n this.notify('task_verify', `task ${id}: verifying`, { id });\n const cres = await new Agent(agentOpts).run(checkBrief);\n // Surface an inconclusive check (errored / hit a kill-switch) — don't let a failed verification\n // masquerade as a passed one. The worker's work still stands, so the task still completes with\n // the worker's report; we just flag that the check didn't cleanly finish.\n if (cres.finishReason !== 'stop') {\n log.warn(`task ${id}: verify inconclusive (${cres.finishReason})`);\n this.notify('task_verify', `task ${id}: verify inconclusive (${cres.finishReason})`, { id, finishReason: cres.finishReason });\n }\n const sum = (a = 0, b = 0) => a + b;\n return {\n ...res,\n steps: res.steps + cres.steps,\n // Merge the checker's messages so downstream tool-call/step accounting includes BOTH agents\n // (else a verified task's toolCalls would undercount vs its steps/usage).\n messages: [...res.messages, ...cres.messages],\n usageEstimated: res.usageEstimated || cres.usageEstimated,\n usage: res.usage && cres.usage ? {\n promptTokens: sum(res.usage.promptTokens, cres.usage.promptTokens),\n completionTokens: sum(res.usage.completionTokens, cres.usage.completionTokens),\n totalTokens: sum(res.usage.totalTokens, cres.usage.totalTokens),\n cacheCreationTokens: sum(res.usage.cacheCreationTokens, cres.usage.cacheCreationTokens),\n cacheReadTokens: sum(res.usage.cacheReadTokens, cres.usage.cacheReadTokens),\n } : (res.usage ?? cres.usage),\n };\n }\n\n /** Throttled per-task progress: worker tool calls → at most one progress re-voice per interval.\n * Two sources, one throttle: completed steps (post) and a heartbeat for a SINGLE long tool call\n * (pre records the in-flight call; a self-cleaning timer narrates \"still inside Bash — 70s\").\n * Completion supersedes: nothing is emitted once the task has settled. */\n private progressReporter(id: string): { pre: (call: ToolUse) => void; post: (call: ToolUse) => void; output: (chunk: string) => void } {\n let lastAt = Date.now();\n let steps = 0;\n let inflight: { call: ToolUse; at: number; tail: string } | null = null;\n const due = () => {\n if (this.pendingAsks.size) return undefined; // a question is pending — \"still working\" asides are noise (and wrong: it's WAITING)\n const rec = this.tasks.get(id);\n return rec && rec.status === 'running' && Date.now() - lastAt >= this.options.progressIntervalMs ? rec : undefined;\n };\n const emit = (rec: TaskRecord, line: string, call: ToolUse) => {\n lastAt = Date.now();\n this.notify('task_progress', `task ${id} (${rec.label}): ${line}`, { id, steps, call: call.name });\n this.queueRevoice(`[task ${id} progress] ${line}`);\n };\n const timer = setInterval(() => {\n const rec = this.tasks.get(id);\n if (!rec || rec.status !== 'running') return clearInterval(timer); // task settled — self-clean\n if (!inflight || !due()) return;\n // content-aware when the tool streams (ctx.emit → rolling tail): \"last output: 12 pass, 0 fail\"\n const last = inflight.tail.trim().split('\\n').filter(Boolean).pop()?.slice(-80);\n emit(rec, `still inside ${describeCall(inflight.call)} — ${Math.round((Date.now() - inflight.at) / 1000)}s on this step${last ? `, last output: ${last}` : ''}`, inflight.call);\n }, Math.max(this.options.progressIntervalMs, 250));\n (timer as any).unref?.(); // never hold the process open\n return {\n pre: (call) => { inflight = { call, at: Date.now(), tail: '' }; },\n output: (chunk) => { if (inflight) inflight.tail = (inflight.tail + chunk).slice(-500); }, // digest only — NEVER re-voices directly\n post: (call) => {\n steps++;\n inflight = null;\n const rec = due();\n if (rec) emit(rec, `still running — ${steps} steps so far, now: ${describeCall(call)}`, call);\n },\n };\n }\n\n /** Park a question under `askId` (a task id, or any unique key for permission asks): re-voices\n * '[task <id> asks] …' and resolves with the user's answer via AnswerTask — or '' on timeout/\n * task settle (callers map '' to deny / best-judgment). Workers never block forever. */\n parkQuestion(askId: string, question: string): Promise<string> {\n return new Promise((resolve) => {\n let settled = false;\n const finish = (answer: string) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n this.pendingAsks.delete(askId);\n resolve(answer);\n };\n const timer = setTimeout(() => {\n this.notify('task_ask_timeout', `task ${askId}: question timed out — proceeding without an answer`);\n finish('');\n }, this.options.askTimeoutMs);\n this.pendingAsks.set(askId, { question, resolve: finish });\n this.notify('task_ask', `task ${askId} asks: ${question}`, { id: askId, question });\n this.queueRevoice(`[task ${askId} asks] ${question}\\n(Relay this to the user in your own words. When they answer, call AnswerTask with id \"${askId}\" and their answer.)`);\n });\n }\n\n /** Resolve any question a settling/cancelled task left parked (its answer can no longer matter). */\n private dropAsk(id: string): void {\n this.pendingAsks.get(id)?.resolve('');\n }\n\n private onWorkerSettled(id: string, res: RunResult): void {\n this.dropAsk(id);\n const rec = this.tasks.get(id)!;\n if (res.finishReason === 'aborted' || rec.status === 'cancelled') {\n rec.status = 'cancelled';\n this.notify('task_cancelled', `task ${id} (${rec.label}) cancelled`);\n return; // the user asked to stop — don't narrate cancelled work\n }\n if (res.finishReason === 'error') {\n const msg = res.error instanceof Error ? res.error.message : String(res.error ?? 'unknown error');\n return this.failTask(rec, msg);\n }\n rec.status = 'done';\n rec.result = res.text;\n log.verbose(`task ${id} done (${res.steps} steps)`);\n // toolCalls = the worker's REAL tool-call count (a dispatch is not a tool call — consumers\n // comparing efficiency across agents need the worker's actual work, not the escalation count).\n this.notify('task_done', `task ${id} (${rec.label}) completed`, {\n id, text: res.text, usage: res.usage, usageEstimated: res.usageEstimated,\n steps: res.steps, toolCalls: res.messages.filter((m) => m.role === 'tool').length,\n });\n this.queueRevoice(`[task ${id} completed] ${res.text}`);\n }\n\n private onWorkerFailed(id: string, err: unknown): void {\n this.failTask(this.tasks.get(id)!, err instanceof Error ? err.message : String(err));\n }\n\n private failTask(rec: TaskRecord, msg: string): void {\n this.dropAsk(rec.id);\n rec.status = 'error';\n rec.result = msg;\n log.warn(`task ${rec.id} failed: ${msg}`);\n this.notify('task_error', `task ${rec.id} (${rec.label}) failed: ${msg}`);\n this.queueRevoice(`[task ${rec.id} failed] ${msg}`);\n }\n\n // --- voice tools (closures over this instance) ---\n\n /** Live-switch the think tier: `false` disables (removes the Think tool from the voice agent),\n * a model id enables (adds the tool if missing). The system-prompt THINK_SLOT text is frozen at\n * construction — the tool's own description carries the routing guidance, so a live enable works;\n * dispatch()'s think→act fallback covers any straggler calls after a live disable. */\n setThinkModel(model: string | false): void {\n this.options.thinkModel = model;\n const tools = this.voice.options.tools as AgentTool[];\n const i = tools.findIndex((t) => t.name === 'Think');\n if (model === false && i >= 0) tools.splice(i, 1);\n else if (model !== false && i < 0) tools.push(this.thinkTool());\n }\n\n /** User/programmatic spawn: the CLI's /act and /think commands. Returns the task id. */\n async dispatch(brief: string, tier: WorkerTier = 'act', label?: string): Promise<string> {\n if (tier === 'think' && this.options.thinkModel === false) tier = 'act';\n const id = `t${++this.seq}`;\n const lbl = label ?? tier;\n await this.options.onTaskStart?.(id, lbl);\n this.spawnWorker(id, lbl, this.buildBrief(brief, tier), tier);\n this.notify('task_started', `task ${id} (${lbl}) started`, { id, brief, tier });\n return id;\n }\n\n private actTool(): AgentTool {\n return {\n name: 'Act',\n description:\n 'Escalate real work (reading/editing files, searching, running tasks, building) to a standard background worker. ' +\n 'Returns immediately with a task id; the result arrives later as a \"[task <id> completed]\" event. ' +\n 'Provide a clear, self-contained `brief` (the worker does not hear the live conversation).',\n parameters: {\n type: 'object',\n required: ['brief'],\n properties: {\n brief: { type: 'string', description: 'full, self-contained instructions for the worker' },\n label: { type: 'string', description: 'a short (2-4 word) label for the task' },\n },\n },\n run: async ({ brief, label }) => {\n this.turnDispatched = true;\n this.turnBriefs.add(String(brief ?? ''));\n // Turn-terminal: force the NEXT reflex step to be text-only (the spoken ack), so a weak model\n // can't keep polling TaskStatus and emit a redundant ack each step. Cleared by resetTurn.\n this.voice.options.toolChoice = 'none';\n const id = await this.dispatch(String(brief ?? ''), 'act', label ? String(label) : undefined);\n return `Acting on task ${id}. Acknowledge briefly; the result will arrive as a [task ${id} completed] event.`;\n },\n };\n }\n\n private thinkTool(): AgentTool {\n return {\n name: 'Think',\n description:\n 'Escalate to a premium deep-reasoning agent for complex analysis, architecture decisions, hard debugging, or planning. ' +\n 'Same async pattern as Act — returns a task id. Use when the problem needs careful thought before (or instead of) action. ' +\n 'Do not use Think for simple tasks — Act is cheaper and faster.',\n parameters: {\n type: 'object',\n required: ['brief'],\n properties: {\n brief: { type: 'string', description: 'the question or problem to reason about deeply' },\n label: { type: 'string', description: 'a short (2-4 word) label for the task' },\n },\n },\n run: async ({ brief, label }) => {\n this.turnDispatched = true;\n this.turnBriefs.add(String(brief ?? ''));\n // Turn-terminal: force the NEXT reflex step to be text-only (the spoken ack), so a weak model\n // can't keep polling TaskStatus and emit a redundant ack each step. Cleared by resetTurn.\n this.voice.options.toolChoice = 'none';\n const id = await this.dispatch(String(brief ?? ''), 'think', label ? String(label) : undefined);\n return `Thinking on task ${id}. Acknowledge briefly; the result will arrive as a [task ${id} completed] event.`;\n },\n };\n }\n\n private taskStatusTool(): AgentTool {\n return {\n name: 'TaskStatus',\n description: 'Status of background tasks. Pass `id` for one task, or omit it to list all.',\n parameters: { type: 'object', properties: { id: { type: 'string' } } },\n run: async ({ id }) => {\n const list = id ? [this.tasks.get(String(id))].filter(Boolean) as TaskRecord[] : [...this.tasks.values()];\n if (!list.length) return id ? `No task '${id}'.` : 'No background tasks.';\n return list.map((t) => `${t.id} (${t.label}): ${t.status}`).join('\\n');\n },\n };\n }\n\n /** Sub-100ms read-only lookups the voice may do itself — everything else stays Act-only.\n * fs-only (no shell; the engine is VFS-abstracted): time, git branch (.git/HEAD read), ls, file\n * head. Output is hard-capped so a lookup can never bloat the skinny voice context. */\n private quickLookTool(): AgentTool {\n const CAP = 2000; // chars — a \"peek\", not a Read\n const kinds = [...new Set(['time', 'branch', 'ls', 'file', 'capabilities', ...Object.keys(this.options.quickLook ?? {})])];\n return {\n name: 'QuickLook',\n description:\n `Instant read-only lookup — one of: ${kinds.join(', ')}. ` +\n 'For trivial facts only; anything needing search, commands, or reasoning goes through Act.',\n parameters: {\n type: 'object',\n required: ['what'],\n properties: {\n what: { type: 'string', enum: kinds, description: 'what to look up' },\n path: { type: 'string', description: 'for ls/file: the path to look at' },\n },\n },\n run: async ({ what, path }) => {\n const fs = this.options.fs;\n try {\n const over = this.options.quickLook?.[String(what)];\n if (over) return await over(path ? String(path) : undefined);\n switch (String(what)) {\n case 'capabilities': {\n // CC-style self-introspection: report the worker's REAL tools so the reflex can\n // answer \"can you…?\" by looking, not guessing. Generalized — no capability hard-coded.\n const actTools = (this.options.actOptions?.tools ?? []) as AgentTool[];\n const names = actTools.map((t) => t.name);\n // MCP servers reach an autonomous worker (cursor/*) via providerOptions, NOT as actTools —\n // so without this the reflex underreports (e.g. denies browser control it actually has).\n const mcpServers = Object.keys((this.options.actOptions?.providerOptions as any)?.mcpServers ?? {});\n const mcpNote = mcpServers.length\n ? ` Plus MCP servers your worker can use: ${mcpServers.join(', ')} (e.g. browser-bridge → drive a real browser: open tabs, navigate, click, screenshot).`\n : '';\n if (!names.length)\n return 'Your worker uses Act\\'s default local toolset (reading/editing files, running shell ' +\n 'commands). No extra tools (e.g. web/internet) are configured; if a request is not a ' +\n 'basic file or shell operation, assume you can\\'t do it and say so.' + mcpNote;\n // Each tool stands on its own — the reflex must resolve a request to the RIGHT one.\n // The trap: it conflates three distinct web capabilities. Spell them apart so it neither\n // overclaims (WebFetch ≠ search) nor underclaims (a browser CAN reach a search engine).\n const hasFetch = names.some((n) => /WebFetch/i.test(n));\n const hasBrowser = names.some((n) => /browser.*(navigate|click|page|type)/i.test(n));\n const hasSearch = names.some((n) => /(^|_)WebSearch$|search/i.test(n) && !/WebFetch|browser/i.test(n));\n const notes: string[] = [];\n if (hasFetch) notes.push('WebFetch retrieves ONE specific URL you are given — it is not a search engine.');\n if (hasBrowser) notes.push('The browser tools drive a real browser: you CAN open a site and, if needed, navigate to a search engine and search there — but it is manual and takes a moment, not an instant lookup.');\n else if (!hasSearch && hasFetch) notes.push('You have no general web-search tool, so for an instant \"search the web\" you can only fetch a URL they provide.');\n const webNote = notes.length ? ' NOTE: ' + notes.join(' ') : '';\n return `Tools your background worker (Act) can actually use: ${names.join(', ')}. ` +\n 'Read each name literally and match the request to a SPECIFIC tool; if none fits, you do NOT have ' +\n 'that ability — say so honestly.' + webNote + mcpNote;\n }\n case 'time':\n return new Date().toString();\n case 'branch': {\n if (!fs) return 'unavailable (no filesystem)';\n const head = (await fs.readFile('.git/HEAD')).trim();\n return head.startsWith('ref: refs/heads/') ? `branch: ${head.slice('ref: refs/heads/'.length)}` : `detached HEAD at ${head.slice(0, 12)}`;\n }\n case 'ls': {\n if (!fs) return 'unavailable (no filesystem)';\n const names = await fs.readDir(String(path ?? '.'));\n return names.slice(0, 50).join('\\n') + (names.length > 50 ? `\\n… (+${names.length - 50} more)` : '');\n }\n case 'file': {\n if (!fs) return 'unavailable (no filesystem)';\n if (!path) return 'file lookup needs a path';\n const text = await fs.readFile(String(path));\n return text.length > CAP ? text.slice(0, CAP) + `\\n… (truncated — ${text.length} chars total; Act for the full file)` : text;\n }\n default:\n return `unknown lookup '${what}'`;\n }\n } catch (e: any) {\n return `lookup failed: ${e?.message ?? e}`;\n }\n },\n };\n }\n\n private answerTaskTool(): AgentTool {\n return {\n name: 'AnswerTask',\n description: 'Relay the user\\'s answer to a pending question from a background task (the \"[task <id> asks]\" events). Pass the id from the event and the user\\'s answer.',\n parameters: {\n type: 'object',\n required: ['id', 'answer'],\n properties: { id: { type: 'string' }, answer: { type: 'string', description: \"the user's answer, verbatim or faithfully summarized\" } },\n },\n run: async ({ id, answer }) => {\n const ask = this.pendingAsks.get(String(id));\n if (!ask) return `No pending question for '${id}' — it may have been answered already or timed out.`;\n ask.resolve(String(answer ?? ''));\n return `Answer relayed — task ${id} resumes.`;\n },\n };\n }\n\n private holdTool(): AgentTool {\n return {\n name: 'Hold',\n description:\n 'The user seems mid-thought — hold the turn (stay listening) instead of answering. ' +\n 'Optionally pass a short filler (\"mhm\", \"go on\") to speak while waiting. Use when the ' +\n 'message sounds incomplete, trailing off, or like they paused to think.',\n parameters: {\n type: 'object',\n properties: {\n filler: { type: 'string', description: 'optional short filler to speak (\"mhm\", \"go on\", \"mm-hm\")' },\n },\n },\n run: async ({ filler }) => {\n if (filler) this.notify('hold_filler', String(filler));\n return 'Holding — listening for the rest of the user\\'s thought. Do not respond further this turn.';\n },\n };\n }\n\n private cancelTaskTool(): AgentTool {\n return {\n name: 'CancelTask',\n description: 'Cancel a running background task by id.',\n parameters: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } },\n run: async ({ id }) => this.cancelTask(String(id)),\n };\n }\n}\n","import type { AgentTool } from './tools';\nimport { topByRelevance } from './relevance';\n\n/**\n * MCP bridge — adapt a Model Context Protocol tool list into the agent's AgentTool[],\n * so any MCP server's tools become first-class agent tools (edge-safe: you supply the\n * transport via `callTool`; this module has no node/network dependency of its own).\n *\n * Pass the server's advertised tools + a `callTool(name, args)` that performs the call\n * (over stdio/HTTP/whatever you wire up); each becomes an AgentTool the Agent can use.\n */\nexport interface McpToolSpec {\n name: string;\n description?: string;\n /** JSON Schema for the tool's arguments (MCP's `inputSchema`). */\n inputSchema?: object;\n}\n\n/** Perform an MCP tool call; return its textual result. Throw to surface an error to the model. */\nexport type McpCall = (name: string, args: any) => Promise<unknown>;\n\nexport interface McpImage { mimeType: string; data: string }\nexport interface McpToolResult { text: string; images?: McpImage[] }\n\n/** Normalize an MCP call result into text + optional image blocks. */\nfunction toResult(result: unknown): McpToolResult {\n if (result == null) return { text: '' };\n if (typeof result === 'string') return { text: result };\n const content = (result as any).content;\n if (Array.isArray(content)) {\n const texts: string[] = [];\n const images: McpImage[] = [];\n for (const c of content) {\n if (c?.type === 'image' && typeof c.data === 'string' && c.mimeType) {\n images.push({ mimeType: c.mimeType, data: c.data });\n } else if (typeof c?.text === 'string') {\n texts.push(c.text);\n } else {\n texts.push(JSON.stringify(c));\n }\n }\n const text = texts.join('\\n');\n if (text || images.length) return { text, ...(images.length ? { images } : {}) };\n }\n return { text: JSON.stringify(result) };\n}\n\nfunction toText(result: unknown): string { return toResult(result).text; }\n\n/** Adapt one MCP tool spec into an AgentTool backed by `callTool`. */\nexport function mcpToolToAgentTool(spec: McpToolSpec, callTool: McpCall, prefix = 'mcp__'): AgentTool {\n return {\n name: `${prefix}${spec.name}`,\n description: spec.description ?? `MCP tool ${spec.name}`,\n parameters: spec.inputSchema ?? { type: 'object', properties: {} },\n async run(args, _ctx) {\n const r = toResult(await callTool(spec.name, args ?? {}));\n return r.images?.length ? r : r.text;\n },\n };\n}\n\n/** Adapt a whole MCP tool list into AgentTool[] (names prefixed to avoid collisions).\n * Optional `filter` pre-narrows the set at mount time (host allowlist), so a server with\n * hundreds of tools needn't mount them all eagerly. */\nexport function mcpToolsToAgentTools(specs: McpToolSpec[], callTool: McpCall, prefix = 'mcp__', filter?: (spec: McpToolSpec) => boolean): AgentTool[] {\n return (filter ? specs.filter(filter) : specs).map((s) => mcpToolToAgentTool(s, callTool, prefix));\n}\n\nexport interface McpToolSearchOptions {\n /** Prefix stripped from / shown on tool names (cosmetic; mirrors the adapter prefix). Default 'mcp__'. */\n prefix?: string;\n /** Max tools returned per `ToolSearch` query. Default 10. */\n maxResults?: number;\n}\n\n/** Render one spec for the search result: name, description, and its argument schema (so the\n * model knows how to call it via `McpCall`). */\nfunction describeSpec(s: McpToolSpec): string {\n const schema = s.inputSchema ? `\\n args: ${JSON.stringify(s.inputSchema)}` : '';\n return `${s.name} — ${s.description ?? '(no description)'}${schema}`;\n}\n\n/**\n * Deferred-mount mode (ToolSearch-equivalent) for large MCP tool sets. Instead of mounting N\n * tools into the wire schema (cost + latency + model confusion past a few dozen), mount exactly\n * TWO bounded tools regardless of N:\n * - `ToolSearch({ query })` — ranks the catalog by relevance and returns the top matches with\n * their argument schemas, so the model discovers what's available on demand.\n * - `McpCall({ name, args })` — invokes any catalog tool by name through the same transport.\n * Keep `mcpToolsToAgentTools` (eager) as the default for small sets.\n */\nexport function makeMcpToolSearch(specs: McpToolSpec[], callTool: McpCall, options: McpToolSearchOptions = {}): AgentTool[] {\n const maxResults = options.maxResults ?? 10;\n const byName = new Map(specs.map((s) => [s.name, s]));\n const catalogLine = `${specs.length} MCP tool(s) available — search by keyword, then call by exact name.`;\n\n const searchTool: AgentTool = {\n name: 'ToolSearch',\n description: `Search the available MCP tools by keyword (${catalogLine}). Returns matching tool names + their argument schemas; call one with \\`McpCall\\`.`,\n parameters: { type: 'object', required: ['query'], properties: { query: { type: 'string', description: 'keywords to match against tool name + description' } } },\n async run({ query }) {\n const q = String(query ?? '').trim();\n if (!q) return catalogLine;\n const { kept } = topByRelevance(specs, q, (s) => `${s.name} ${s.description ?? ''}`, maxResults);\n if (!kept.length) return `(no MCP tool matches \"${q}\" — try broader keywords)`;\n return kept.map(describeSpec).join('\\n');\n },\n };\n\n const callMcpTool: AgentTool = {\n name: 'McpCall',\n description: 'Call an MCP tool discovered via `ToolSearch`, by its exact name. Pass its arguments as `args`.',\n parameters: {\n type: 'object',\n required: ['name'],\n properties: {\n name: { type: 'string', description: 'exact tool name from ToolSearch' },\n args: { type: 'object', description: 'arguments object for the tool (per its schema)' },\n },\n },\n async run({ name, args }) {\n const n = String(name ?? '');\n if (!byName.has(n)) return `Error: unknown MCP tool '${n}'. Use ToolSearch to find valid names.`;\n const r = toResult(await callTool(n, args ?? {}));\n return r.images?.length ? r : r.text;\n },\n };\n\n return [searchTool, callMcpTool];\n}\n\n/** Minimal shape of a mounted MCP server this module needs — structurally satisfied by\n * `MountedMcp` from `mcp.client.ts`, kept local so `mcp.ts` stays node-free/edge-safe. */\nexport interface MountedMcpLike {\n name: string;\n specs: McpToolSpec[];\n client: { callTool(name: string, args: unknown): Promise<unknown> };\n}\n\n/** A flattened catalog entry's origin: which server owns it + the un-prefixed raw tool name. */\nexport interface McpRoute { server: string; rawName: string }\n\n/** Flatten servers' specs into one `mcp__<server>__<tool>` namespace + a display→origin map.\n * Sanitizing/truncating to provider name rules can MERGE distinct names (`a/b` & `a:b` → `a_b`),\n * so dedupe with a numeric suffix — a silent overwrite would orphan a tool. */\nexport function buildMcpCatalog(servers: { name: string; specs: McpToolSpec[] }[]): { specs: McpToolSpec[]; routes: Map<string, McpRoute> } {\n const specs: McpToolSpec[] = [];\n const routes = new Map<string, McpRoute>();\n for (const m of servers) {\n for (const s of m.specs) {\n const base = `mcp__${m.name}__${s.name}`.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 128);\n let display = base;\n for (let i = 2; routes.has(display); i++) display = `${base.slice(0, 128 - String(i).length - 1)}_${i}`;\n specs.push({ name: display, description: s.description, inputSchema: s.inputSchema });\n routes.set(display, { server: m.name, rawName: s.name });\n }\n }\n return { specs, routes };\n}\n\n/** Resolve a routed MCP call to its result. Throw to surface an error to the model. */\nexport type McpRouteResolver = (server: string, rawName: string, args: any) => Promise<unknown>;\n\n/** Shared core: wire the `ToolSearch`/`McpCall` pair over a prebuilt catalog, dispatching each\n * call through `resolve(server, rawName, args)` (eager → a mounted client; lazy → connect-on-call). */\nfunction searchOverCatalog(servers: string[], specs: McpToolSpec[], routes: Map<string, McpRoute>, resolve: McpRouteResolver, options?: McpToolSearchOptions) {\n const tools = specs.length\n ? makeMcpToolSearch(specs, (name, args) => {\n const r = routes.get(name);\n if (!r) throw new Error(`unknown MCP tool '${name}' — use ToolSearch to find valid names`);\n return resolve(r.server, r.rawName, args ?? {});\n }, options)\n : [];\n return { tools, serverNames: servers, toolCount: specs.length };\n}\n\n/**\n * Ergonomic deferred-mount over already-mounted MCP servers: flattens their specs into one\n * `mcp__<server>__<tool>` namespace and wires a single `ToolSearch`/`McpCall` pair that routes\n * each call to the owning server's RAW `callTool` (so result normalization happens exactly once —\n * double-normalizing corrupts image blocks).\n */\nexport function makeMcpToolSearchFromMounted(\n mounted: MountedMcpLike[],\n options?: McpToolSearchOptions,\n): { tools: AgentTool[]; serverNames: string[]; toolCount: number } {\n const { specs, routes } = buildMcpCatalog(mounted);\n const byName = new Map(mounted.map((m) => [m.name, m]));\n return searchOverCatalog(mounted.map((m) => m.name), specs, routes, (server, rawName, args) => byName.get(server)!.client.callTool(rawName, args), options);\n}\n\n/**\n * Lazy variant: same `ToolSearch`/`McpCall` surface, but the server isn't required to be connected.\n * Each `McpCall` resolves the owning server from the catalog and `resolve(server, rawName, args)`\n * connects-on-demand — so a turn that calls no MCP tool opens ZERO connections. Edge-safe: the\n * caller (`mountMcpCatalog` in `mcp.client.ts`) supplies the node-side connect/pool logic.\n */\nexport function makeLazyMcpToolSearch(\n servers: { name: string; specs: McpToolSpec[] }[],\n resolve: McpRouteResolver,\n options?: McpToolSearchOptions,\n): { tools: AgentTool[]; serverNames: string[]; toolCount: number } {\n const { specs, routes } = buildMcpCatalog(servers);\n return searchOverCatalog(servers.map((s) => s.name), specs, routes, resolve, options);\n}\n","/**\n * VoiceEngine — the portable voice-conversation brain: state machine (idle|listening|thinking|\n * speaking), barge-in policy (AEC-trivial + heuristic echo tier), gapless TTS turn handoff,\n * utterance merge window, interrupted-reply tracking, ack echo-leak guard.\n *\n * Pure logic over three injected seams (STT, TTS, AudioSink) — runs in CLI, server, or browser.\n * Hosts wire `onUtterance` to their dispatch and feed `beginSpeech()/speakDelta()/endSpeech()`;\n * `interrupt()` is the barge-in primitive. Behavior validated live; see mind/11-voice.md.\n */\nimport { forComponent } from '../logging';\nimport type { AudioSink, VoiceState } from './types';\n\nconst log = forComponent('VoiceEngine');\nconst now = () => performance.now();\n\n/** Sanitize text for the spoken channel (and its on-screen echo). Drops markdown punctuation TTS would\n * read aloud (\"star\"/\"hash\"), turns em/en dashes and table pipes into spoken pauses, normalizes \"30 %\"\n * → \"30%\", and collapses filler dot-runs (\"now.....\" → \"now.\"). Per-delta safe: every map is local to\n * the chunk (single chars / line-anchored), so chunk boundaries never split a multi-char span. */\nexport const forSpeech = (t: string): string =>\n t.replace(/[*_`#]+/g, '')\n .replace(/^[ \\t]*[-•]\\s+/gm, '') // leading list marker\n .replace(/\\s*[\\u2013\\u2014]\\s*/g, ', ') // en/em dash → spoken pause (prompt forbids dashes in speech)\n .replace(/[\\u2010\\u2011]/g, '-') // (non-breaking) hyphen → plain hyphen (TTS reads \"8-12\" fine)\n .replace(/\\s*\\|\\s*/g, ', ') // table pipe → pause\n .replace(/(\\d)\\s+%/g, '$1%') // \"30 %\" → \"30%\" (else \"thirty space percent\")\n .replace(/\\.{3,}/g, '.'); // filler dot-run → single period\n\n/** Structural contracts (satisfied by SonioxSTT/CartesiaTTS or test fakes). */\nexport interface SttLike {\n usingAec: boolean;\n onPartial: (text: string) => void;\n onUtterance: (text: string, endpointAt: number) => void;\n onLevel: (rms: number) => void;\n start(): Promise<void> | void;\n reset(): void;\n stop(): void;\n}\nexport interface TtsLike {\n onAudio: (chunk: Uint8Array) => void;\n onDone: () => void;\n connect(): Promise<void> | void;\n newContext(): string;\n speak(text: string, cont: boolean): void;\n end(): void;\n cancel(): void;\n close(): void;\n}\n\nexport class VoiceEngineOptions {\n stt!: SttLike;\n tts!: TtsLike;\n player!: AudioSink;\n /** a final utterance arrived (endpoint) — host dispatches it as a turn */\n onUtterance: (text: string) => void = () => {};\n /** live partial transcript while listening (host renders the 🎤 line) */\n onPartial: (text: string) => void = () => {};\n onState: (s: VoiceState) => void = () => {};\n /** user spoke/acted over playback — host aborts the in-flight turn (called AFTER audio is killed).\n * phase: 'speaking' = cut mid-speech (real interruption); 'drain' = in the final audio tail\n * (normal turn-taking — hosts shouldn't alarm). */\n onBargeIn: (phase: 'speaking' | 'drain') => void = () => {};\n /** spoken micro-ack on utterance endpoint (masks LLM TTFT); '' disables */\n ackPhrase = '';\n /** Endpoint merge window (ms): hold an endpointed utterance briefly — if speech resumes (spelled\n * letters, mid-thought pauses), the next utterance MERGES instead of dispatching a truncated one\n * (\"E-L-Y.\" / \"A.\"). Costs this much latency per turn; 0 disables. */\n utteranceMergeMs = 350;\n /** Extended merge window (ms) for utterances that look incomplete (trailing conjunction/filler).\n * Gives the user time to finish their thought without triggering a model call. */\n incompleteMergeMs = 1500;\n /** Filler phrase spoken when holding for an incomplete utterance ('' disables). */\n holdFiller = '';\n /** Called when the engine holds an incomplete utterance (host can render a visual cue). */\n onHold: () => void = () => {};\n /** heuristic (non-AEC) energy barge-in tuning */\n bargeRmsMult = 2;\n bargeRmsFloor = 500;\n /** Overlap turn-taking (AEC tier, needs player.pause/resume) — human phone-call model, driven by\n * the STT ITSELF (a trained speech classifier) instead of energy thresholds (energy could not\n * separate residue bursts from speech in every room — hiccup whack-a-mole): partial text while\n * speaking → PAUSE (exact-sample hold); partial grows into dominant-novel ≥2 words → cede\n * (interrupt; the LLM re-enters); partial stalls/endpoints without ceding (backchannel by\n * DURATION, not vocabulary) → resume + drop. false disables. */\n overlapPause = true;\n /** no new partial activity for this long while paused → resume, drop the interjection */\n overlapResumeMs = 700;\n /** A genuine barge over a LONG reply is defeated by the dominant-novel gate: Meet echoes our own\n * speech back, so the partial is mostly our words + a few of hers → never \"dominant novel\" → it\n * resumes (replaying old audio — the audible \"completes the buffer\" blip) instead of ceding.\n * Mechanism-based discriminator: a re-PAUSE this soon after a resume = a persistent human, not an\n * echo blip (which pauses once and stalls). Cede on the re-pause regardless of the novel gate. */\n overlapRepauseCedeMs = 1500;\n}\n\nexport class VoiceEngine {\n public options: VoiceEngineOptions;\n public state: VoiceState = 'idle';\n protected stt: SttLike;\n protected tts: TtsLike;\n protected player: AudioSink;\n private speaking = false; // audible (deltas flowing OR audio draining)\n private ctxOpen = false; // the current TTS context still accepts deltas (false once end-frame sent)\n private interrupted = false; // barge-in latch: drop in-flight deltas until the next legitimate turn\n private spokeDeltas = false; // a TTS context is open for the current spoken turn\n private drainTimer: ReturnType<typeof setTimeout> | null = null;\n // heuristic tier state (inert under AEC) — frozen as validated in the experiment\n private echoWords = new Set<string>();\n private prevReply = '';\n private reply = '';\n private echoUntil = 0;\n private baseline = 0;\n private hot = 0;\n private suspectUntil = 0;\n private ackAt = 0; // when the micro-ack was spoken — its echo can leak before the AEC filter converges\n private pendingUtt = ''; // endpointed text held for the merge window\n private pendingTimer: ReturnType<typeof setTimeout> | null = null;\n private lastInterrupted: { full: string; heard: string } | null = null;\n // overlap (pause) tier state — AEC + pause-capable sinks only\n private pausedAt = 0;\n private lastResumeAt = 0; // when the overlap last resumed from a false alarm — a quick re-pause cedes\n private lastOverlapPartial = ''; // change-detection: only NEW partial text counts as activity\n private resumeTimer: ReturnType<typeof setTimeout> | null = null;\n private turnStartAt = 0; // timestamp when the current turn began (for TTFT logging)\n\n constructor(options?: Partial<VoiceEngineOptions>) {\n this.options = { ...new VoiceEngineOptions(), ...options };\n const o = this.options;\n if (!o.stt || !o.tts || !o.player) throw new Error('VoiceEngine needs stt, tts and player (see cli/voice.ts VoiceIO for platform defaults)');\n this.stt = o.stt;\n this.tts = o.tts;\n this.player = o.player;\n }\n\n async start(): Promise<void> {\n this.tts.onAudio = (c) => { if (this.speaking) this.player.write(c); };\n this.stt.onPartial = (text) => this.handlePartial(text);\n this.stt.onUtterance = (text) => this.handleUtterance(text);\n this.stt.onLevel = (rms) => this.handleLevel(rms);\n await Promise.all([this.tts.connect(), this.stt.start()]);\n this.setState('listening');\n log.debug(`voice I/O up (${this.stt.usingAec ? 'AEC' : 'heuristic echo'} capture)`);\n }\n\n get usingAec(): boolean {\n return this.stt.usingAec;\n }\n\n private idleWaiters: (() => void)[] = [];\n private setState(s: VoiceState): void {\n if (this.state === s) return;\n this.state = s;\n this.options.onState(s);\n if (s !== 'speaking' && s !== 'thinking') {\n for (const r of this.idleWaiters.splice(0)) r();\n }\n }\n\n /** Resolve when the engine is no longer speaking (immediate if already idle). */\n awaitIdle(): Promise<void> {\n if (this.state !== 'speaking' && this.state !== 'thinking') return Promise.resolve();\n return new Promise((r) => this.idleWaiters.push(r));\n }\n\n // --- speaking side (host-driven) ---\n\n /** open a spoken turn (idempotent — safe from both onUtterance and first-delta paths).\n * `ack` speaks the configured micro-ack as the context opener (utterance path only —\n * masks LLM TTFT; re-voice turns begun by their first delta skip it). */\n beginSpeech(ack = false): void {\n if (this.speaking && this.ctxOpen) return;\n if (this.drainTimer) { clearTimeout(this.drainTimer); this.drainTimer = null; }\n this.interrupted = false; // a new turn re-arms speech\n // gapless handoff: a new turn while the previous one's audio drains keeps the SAME player\n // (markTurn would cut the tail) and just opens a fresh TTS context — Cartesia rejects deltas\n // on an ended context (\"Context closed\" 400, narration silently lost).\n this.resetOverlap(true); // a held pause must release — gapless handoff keeps the same player (no FLUSH)\n if (!this.speaking) this.player.markTurn();\n this.speaking = true;\n this.ctxOpen = true;\n this.spokeDeltas = false;\n this.reply = '';\n this.echoWords = new Set(this.words(this.prevReply)); // previous reply's echo may still be in flight\n this.tts.newContext();\n if (ack && this.options.ackPhrase) { this.tts.speak(this.options.ackPhrase + ' ', true); this.spokeDeltas = true; this.ackAt = now(); }\n // TTFT is stamped at the real turn start (flushUtterance, when the user's utterance dispatches);\n // only fall back to here for a re-voice turn that has no preceding utterance.\n if (!this.turnStartAt) this.turnStartAt = now();\n this.setState('thinking');\n }\n speakDelta(text: string): void {\n // After a barge-in the aborted turn's stream may keep delivering (re-voice turns have no abort\n // signal) — those deltas must NOT re-open speech. endSpeech()/beginSpeech() clear the latch.\n if (this.interrupted) return;\n if (!this.speaking || !this.ctxOpen) this.beginSpeech();\n this.reply += text;\n for (const w of this.words(this.reply)) this.echoWords.add(w);\n this.tts.speak(forSpeech(text), true); // strip markdown punctuation so TTS doesn't read \"dash\"/\"star\"/\"hash\" aloud\n if (!this.spokeDeltas && this.turnStartAt) log.debug(`ttft: ${Math.round(now() - this.turnStartAt)}ms`);\n this.spokeDeltas = true;\n this.setState('speaking');\n }\n /** close the spoken turn (idempotent); stays audible until ALL audio arrived AND playback drains */\n endSpeech(): void {\n this.interrupted = false; // the interrupted turn is over — next turn may speak\n if (!this.speaking) return;\n this.ctxOpen = false; // context ends now; audio keeps draining\n if (this.reply) this.prevReply = this.reply;\n // remain 'speaking' (barge-in armed, echo discrimination active) until audio actually finishes\n const settle = () => {\n if (this.ctxOpen) { this.drainTimer = null; return; } // a newer turn took over the player — it settles\n if (this.pausedAt) { this.drainTimer = setTimeout(settle, 250); return; } // held by an overlap — not finished audibly\n this.drainTimer = null;\n this.speaking = false;\n if (this.turnStartAt) log.debug(`turn: ${Math.round(now() - this.turnStartAt)}ms (incl. playback)`);\n this.echoUntil = now() + 2500; // tail echo (capture+network+finalization) outlives playback\n if (!this.usingAec) this.stt.reset(); // drop echo residue (AEC: keep — it can only be the user)\n this.setState('listening');\n };\n const drainThenSettle = () => {\n if (this.drainTimer) clearTimeout(this.drainTimer);\n this.drainTimer = setTimeout(settle, this.player.drainMs() + 300);\n };\n if (this.spokeDeltas) {\n // the LLM turn is over but the TTS is still synthesizing — wait for ALL chunks (onDone)\n // before the drain countdown, else drainMs() undercounts and the reply's tail is dropped.\n this.tts.onDone = drainThenSettle;\n this.tts.end();\n // safety net: if 'done' never arrives (ws drop), settle after a generous ceiling\n if (this.drainTimer) clearTimeout(this.drainTimer);\n this.drainTimer = setTimeout(drainThenSettle, 15_000);\n } else drainThenSettle();\n }\n /** text of the reply cut by the last barge-in — consumed by the host to tell the model what\n * the user did NOT hear. Cleared on read. */\n takeInterruptedReply(): { full: string; heard: string } | null {\n const r = this.lastInterrupted;\n this.lastInterrupted = null;\n return r;\n }\n\n /** Speak a short filler phrase without starting a model turn (stays in listening mode after). */\n speakFiller(text: string): void {\n if (!text || this.speaking) return;\n this.beginSpeech();\n this.speakDelta(text);\n this.endSpeech();\n }\n\n /** barge-in: stop audio NOW, cancel generation, reset for the user's utterance */\n interrupt(): void {\n if (!this.speaking && !this.drainTimer) return;\n if (this.drainTimer) { clearTimeout(this.drainTimer); this.drainTimer = null; }\n // estimate how much of the reply was actually heard: played-audio seconds ≈ spoken chars\n // (~15 chars/s of TTS speech) — coarse, but enough for \"the user missed most of it\".\n this.resetOverlap(false); // ceding — the flush below discards the held tape, don't resume it\n this.lastResumeAt = 0; // consume the re-pause signal: the next reply starts fresh\n const heardChars = Math.round((Math.max(0, this.player.playedMs()) / 1000) * 15); // paused time excluded by the sink\n if (this.reply) this.lastInterrupted = { full: this.reply, heard: this.reply.slice(0, heardChars) };\n this.speaking = false;\n this.ctxOpen = false;\n this.interrupted = true; // stragglers from the aborted stream stay silent\n this.suspectUntil = 0;\n // Meet's WebRTC echoes our audio back with ~1-2s network delay. The echo window must cover\n // the full playback duration + round-trip, not just a fixed tail. Without this, long responses\n // (stories, explanations) leak their echo tail past the window → false barge-in → cascade.\n this.echoUntil = now() + Math.max(2500, this.player.drainMs() + 3000);\n this.tts.cancel();\n this.player.kill();\n if (!this.usingAec) this.stt.reset(); // heuristic: drop the mixed echo/user buffer\n if (this.reply) this.prevReply = this.reply;\n this.setState('listening');\n }\n stop(): void {\n if (this.resumeTimer) clearTimeout(this.resumeTimer);\n if (this.pendingTimer) clearTimeout(this.pendingTimer);\n if (this.drainTimer) clearTimeout(this.drainTimer);\n this.stt.stop();\n this.player.kill();\n this.tts.close();\n this.setState('idle');\n }\n\n // --- listening side (STT-driven) ---\n\n private words(s: string): string[] {\n return s.toLowerCase().replace(/[^a-z0-9\\s]/g, '').split(/\\s+/).filter((w) => w.length >= 2);\n }\n private novelWords(text: string): string[] {\n return this.words(text).filter((w) => !this.echoWords.has(w));\n }\n private echoActive(): boolean {\n return this.speaking || now() < this.echoUntil;\n }\n /** Genuine user speech vs our own bleed (AEC tier): novel words must DOMINATE, not merely exist.\n * Degraded AEC + an STT mis-hearing manufactures a single novel word out of pure echo (a name or\n * rare word in our own reply comes back transcribed slightly differently — 1 novel / N words).\n * A real interjection is mostly novel (\"stop\", \"wait what\") — short utterances pass on ratio,\n * longer ones on count. */\n private genuine(text: string): boolean {\n const total = this.words(text).length;\n const novel = this.novelWords(text).length;\n // ratio, not count: a long mis-heard echo sentence yields 2-3 \"novel\" words out of a dozen\n // (live trace: \"…latest email from you\" from our \"…latest news for you\") — an absolute >=2\n // pass let those through. Real user speech is MOSTLY novel.\n return novel > 0 && novel / Math.max(1, total) > 0.5;\n }\n\n private handlePartial(text: string): void {\n if (this.speaking) {\n if (this.overlapCapable) {\n // STT-driven overlap: Soniox saying \"this is speech\" is the discriminator (energy could not\n // separate residue from speech across rooms). New partial text → pause (trail-off); growing\n // into dominant-novel ≥2 words → cede; stalling → the resume timer releases the hold.\n const txt = text.trim();\n if (!txt || txt === this.lastOverlapPartial) return; // no NEW speech activity\n this.lastOverlapPartial = txt;\n if (!this.pausedAt) {\n this.pausedAt = now();\n this.player.pause!();\n // Re-pause right after a false-alarm resume → persistent human, not an echo blip. Cede now,\n // before the resume replays old audio again, and without waiting for the dominant-novel gate.\n if (this.lastResumeAt && now() - this.lastResumeAt < this.options.overlapRepauseCedeMs) {\n this.interrupt();\n this.options.onBargeIn(this.ctxOpen ? 'speaking' : 'drain');\n return;\n }\n }\n if (this.genuine(txt) && this.words(txt).length >= 2) {\n const phase = this.ctxOpen ? 'speaking' as const : 'drain' as const;\n this.interrupt();\n this.options.onBargeIn(phase);\n return;\n }\n this.armResume(); // single word / not-yet-genuine: hold; quiet releases\n return;\n }\n // Barge-in = NOVEL words (not in our own recent reply) — even with AEC. Cancellation quality\n // is a spectrum (VPIO convergence varies run to run); when it degrades, the assistant's own\n // bleed must not self-interrupt. User speech is novel by definition → still triggers fast.\n const barge = this.usingAec ? this.genuine(text) : this.novelWords(text).length >= (this.suspectUntil ? 1 : 2);\n if (barge) {\n const phase = this.ctxOpen ? 'speaking' as const : 'drain' as const;\n this.interrupt();\n this.options.onBargeIn(phase);\n }\n return;\n }\n if (this.pendingUtt && text.trim()) { // user kept talking during the merge window — wait for the next endpoint\n // RE-ARM (long fallback), never just clear: Soniox emits trailing partial frames after <end> —\n // clearing left the pending utterance parked forever (the user's barge words were LOST).\n if (this.pendingTimer) clearTimeout(this.pendingTimer);\n this.pendingTimer = setTimeout(() => this.flushUtterance(), Math.max(800, this.options.utteranceMergeMs));\n }\n // display partials unless they're echo-shaped during/after our own speech (degraded-AEC bleed)\n if (!this.echoActive() || (this.usingAec ? this.genuine(text) : this.novelWords(text).length >= 1)) this.options.onPartial(text);\n }\n\n private static readonly TRAIL_RE = /(?:^|\\s)(?:and|but|or|so|to|the|a|an|of|in|for|with|that|if|uh|um|like|about|from|into|on|is|are|was|were|,)$/i;\n /** The utterance sounds like the user paused mid-thought (trailing conjunction/filler/comma). */\n private looksIncomplete(text: string): boolean {\n return VoiceEngine.TRAIL_RE.test(text.trim());\n }\n\n private handleUtterance(text: string): void {\n // Overlap that never grabbed the turn: duration said backchannel/noise → drop it. Real grabs\n // interrupted already (speaking=false). Applies while content flows (ctxOpen) AND while we are\n // holding a pause for THIS overlap (a drain-tail \"yeah\" leaked as a real turn otherwise). A\n // clean early answer during the drain — no hold in progress — still falls through (turn-taking).\n if (this.speaking && (this.ctxOpen || this.pausedAt) && this.overlapCapable) { this.stt.reset(); return; }\n // Echo-shaped utterances (no/few novel words while we are or just were audible) are dropped in\n // BOTH tiers — degraded AEC bleed otherwise becomes fake user turns (\"🎤 › Friday.\").\n if (this.echoActive() && (this.usingAec ? !this.genuine(text) : this.novelWords(text).length < 2)) { this.stt.reset(); return; }\n // AEC converges over ~100ms at audio onset — the ack (first audio after silence) can leak back\n // as a transcript. Drop backchannel-shaped utterances shortly after we spoke it.\n const squash = (t: string) => t.toLowerCase().replace(/[^a-z]/g, '').replace(/(.)\\1+/g, '$1');\n if (this.ackAt && now() - this.ackAt < 6000 && squash(text) === squash(this.options.ackPhrase)) { this.ackAt = 0; return; }\n // Merge window: semantic endpointing fires mid-spelling (\"E-L-Y.\" … \"A.\") and mid-thought.\n // Hold briefly; speech resuming in the window appends to the SAME utterance. Substantial\n // utterances (≥4 words) skip the hold — they are never spelled fragments, and the saved 350ms\n // is the difference between ping-pong and lag in quick exchanges.\n this.pendingUtt = this.pendingUtt ? `${this.pendingUtt} ${text}` : text;\n if (this.pendingTimer) clearTimeout(this.pendingTimer);\n // Incomplete utterance hold: trailing conjunctions/fillers get an extended merge window + optional\n // filler phrase, letting the user finish their thought without triggering a model call.\n if (this.options.incompleteMergeMs && this.looksIncomplete(this.pendingUtt)) {\n log.verbose(`hold: incomplete utterance \"${this.pendingUtt.slice(-40)}\"`);\n this.options.onHold();\n if (this.options.holdFiller && !this.speaking) {\n this.beginSpeech();\n this.speakDelta(this.options.holdFiller);\n this.endSpeech();\n }\n this.pendingTimer = setTimeout(() => this.flushUtterance(), this.options.incompleteMergeMs);\n return;\n }\n if (!this.options.utteranceMergeMs || this.words(this.pendingUtt).length >= 4) return this.flushUtterance();\n this.pendingTimer = setTimeout(() => this.flushUtterance(), this.options.utteranceMergeMs);\n }\n private flushUtterance(): void {\n if (this.pendingTimer) { clearTimeout(this.pendingTimer); this.pendingTimer = null; }\n const text = this.pendingUtt;\n this.pendingUtt = '';\n if (text) { this.turnStartAt = now(); this.options.onUtterance(text); } // stamp the real turn start for TTFT\n }\n\n private get overlapCapable(): boolean {\n return this.usingAec && this.options.overlapPause && !!this.player.pause && !!this.player.resume;\n }\n private armResume(): void {\n if (this.resumeTimer) clearTimeout(this.resumeTimer);\n this.resumeTimer = setTimeout(() => {\n this.resumeTimer = null;\n if (!this.pausedAt) return; // (no speaking guard: a held pause must ALWAYS release, else the tape wedges)\n this.stt.reset(); // drop the stalled residue/backchannel buffer — it is not the next utterance\n this.resetOverlap(true); // the overlap died out (backchannel/noise) — pick up exactly where she left off\n }, this.options.overlapResumeMs);\n }\n private resetOverlap(resume: boolean): void {\n if (this.resumeTimer) { clearTimeout(this.resumeTimer); this.resumeTimer = null; }\n if (this.pausedAt && resume) { this.player.resume?.(); this.lastResumeAt = now(); }\n this.pausedAt = 0;\n this.lastOverlapPartial = '';\n this.gatePassTimes = [];\n }\n\n /** energy two-stage barge-in (heuristic tier only): spike over echo baseline → pause + confirm via STT */\n private gatePassTimes: number[] = []; // recent gate-PASSING chunks (helper zeroes residue — nonzero = vetted)\n private handleLevel(rms: number): void {\n if (this.usingAec) {\n // Fast hold trigger: a nonzero level while we are audible means the helper's gate PASSED it\n // (≥2× expected residue). Two passes within 350ms = speech onset → pause NOW (~300ms), without\n // waiting for STT tokens (which lag whenever the onset straddles the gate). The STT still owns\n // the DECISION: cede on genuine ≥2 words, or the resume timer releases the hold.\n if (!this.speaking || !this.overlapCapable || this.pausedAt || rms < 50) return;\n const t = now();\n this.gatePassTimes = this.gatePassTimes.filter((x) => t - x < 350);\n this.gatePassTimes.push(t);\n if (this.gatePassTimes.length < 2) return;\n this.gatePassTimes = [];\n this.pausedAt = t;\n this.player.pause!();\n this.armResume();\n return;\n }\n if (!this.speaking) { this.baseline = 0; this.hot = 0; return; }\n // warm-up: let the EMA learn the echo level before triggers (else her own onset reads as a spike)\n if (!this.baseline) { this.baseline = rms; return; }\n this.baseline = this.baseline * 0.9 + rms * 0.1;\n if (rms > Math.max(this.baseline * this.options.bargeRmsMult, this.options.bargeRmsFloor)) this.hot++;\n else this.hot = 0;\n if (this.hot >= 2 && !this.suspectUntil) {\n this.suspectUntil = now() + 1300;\n setTimeout(() => { this.suspectUntil = 0; }, 1350);\n }\n }\n}\n","/**\n * Soniox streaming STT over WebSocket — token partials, semantic `<end>` endpointing,\n * auto-reconnect (re-minting auth — temp tokens expire). Portable: the microphone is an\n * injected AudioSource, not spawned here.\n *\n * Browser auth: NEVER ship the real key — your backend mints a short-lived key via\n * `POST https://api.soniox.com/v1/auth/temporary-api-key` (sent with the real key) and the\n * client passes `auth: () => fetch('/your-be/soniox-token').then(r => r.text())`.\n */\nimport { forComponent } from '../logging';\nimport { type AudioSource, type AuthProvider, resolveAuth, STT_SAMPLE_RATE } from './types';\n\nconst log = forComponent('SonioxSTT');\nconst now = () => performance.now();\n\nexport class SonioxSTTOptions {\n auth: AuthProvider = '';\n source!: AudioSource;\n model = 'stt-rt-preview';\n languageHints = ['en'];\n /** Client-side endpoint: finalized text + no new tokens for this long = utterance (don't wait for\n * Soniox's semantic <end>, which adds 0.5-1.5s — the difference between ping-pong and lag). */\n silenceEndpointMs = 500;\n}\n\nexport class SonioxSTT {\n public options: SonioxSTTOptions;\n private ws!: WebSocket;\n private stopped = false;\n private sourceStarted = false;\n public onPartial: (text: string) => void = () => {};\n public onUtterance: (text: string, endpointAt: number) => void = () => {};\n /** mic energy (RMS) per chunk — drives the energy-based heuristic barge-in tier */\n public onLevel: (rms: number) => void = () => {};\n private finalText = '';\n private partialText = '';\n private lastChangeAt = 0;\n private lastCombined = '';\n private endpointTimer: ReturnType<typeof setInterval> | null = null;\n private firstTokenAt = 0; // first speech token in current utterance\n\n constructor(options?: Partial<SonioxSTTOptions>) {\n this.options = { ...new SonioxSTTOptions(), ...options };\n }\n\n get usingAec(): boolean {\n return this.options.source?.aec ?? false;\n }\n\n private async connectWs(): Promise<void> {\n const apiKey = await resolveAuth(this.options.auth); // per-connect: temp tokens expire\n this.ws = new WebSocket('wss://stt-rt.soniox.com/transcribe-websocket');\n await new Promise<void>((res, rej) => {\n this.ws.onopen = () => res();\n this.ws.onerror = (e: any) => rej(new Error(`soniox ws: ${e.message || 'connect failed'}`));\n });\n this.ws.send(\n JSON.stringify({\n api_key: apiKey,\n model: this.options.model,\n audio_format: 'pcm_s16le',\n sample_rate: STT_SAMPLE_RATE,\n num_channels: 1,\n language_hints: this.options.languageHints,\n enable_endpoint_detection: true,\n }),\n );\n this.ws.onmessage = (ev) => this.handle(JSON.parse(String(ev.data)));\n this.ws.onclose = (ev: any) => {\n if (this.stopped) return;\n log.warn(`soniox ws closed (${ev.code} ${ev.reason || ''}) — reconnecting`);\n this.reset();\n this.connectWs().catch((e) => log.error(`soniox reconnect failed: ${e.message}`));\n };\n }\n\n async start(): Promise<void> {\n await this.connectWs();\n if (this.sourceStarted) return; // reconnect path — source keeps running\n this.sourceStarted = true;\n // client-side stability endpoint (faster than Soniox's semantic <end> AND its finalization lag:\n // finals trail partials by ~1s — text that has stopped CHANGING is the utterance)\n this.endpointTimer = setInterval(() => {\n const combined = (this.finalText + this.partialText).trim();\n if (!combined || now() - this.lastChangeAt < this.options.silenceEndpointMs) return;\n if (this.firstTokenAt) log.debug(`stt: ${Math.round(now() - this.firstTokenAt)}ms first-token→silence-endpoint, \"${combined.slice(0, 60)}\"`);\n this.reset();\n this.onUtterance(combined, now());\n }, 120);\n (this.endpointTimer as any).unref?.();\n await this.options.source.start((chunk) => {\n let sum = 0;\n const view = new DataView(chunk.buffer, chunk.byteOffset, chunk.byteLength);\n for (let i = 0; i + 1 < chunk.byteLength; i += 2) { const v = view.getInt16(i, true); sum += v * v; }\n this.onLevel(Math.sqrt(sum / (chunk.byteLength / 2)));\n if (this.ws.readyState === WebSocket.OPEN) this.ws.send(chunk);\n });\n }\n private handle(m: any): void {\n if (m.error_message) return log.error(`soniox: ${m.error_message}`);\n let endpoint = false;\n for (const t of m.tokens ?? []) {\n if (t.text === '<end>') endpoint = true;\n else if (t.is_final) this.finalText += t.text;\n }\n this.partialText = (m.tokens ?? []).filter((t: any) => !t.is_final && t.text !== '<end>').map((t: any) => t.text).join('');\n const combined = this.finalText + this.partialText;\n if (combined !== this.lastCombined) {\n this.lastCombined = combined; this.lastChangeAt = now();\n if (!this.firstTokenAt && combined.trim()) this.firstTokenAt = now();\n }\n this.onPartial(combined);\n if (endpoint && this.finalText.trim()) {\n const utterance = this.finalText.trim();\n if (this.firstTokenAt) log.debug(`stt: ${Math.round(now() - this.firstTokenAt)}ms first-token→endpoint, \"${utterance.slice(0, 60)}\"`);\n this.reset();\n this.onUtterance(utterance, now());\n }\n }\n reset(): void {\n this.finalText = '';\n this.partialText = '';\n this.lastCombined = '';\n this.firstTokenAt = 0;\n }\n stop(): void {\n this.stopped = true;\n if (this.endpointTimer) clearInterval(this.endpointTimer);\n this.options.source?.stop();\n if (this.ws) this.ws.onclose = null as any;\n this.ws?.close();\n }\n}\n","/**\n * Portable voice I/O contracts — zero platform imports. The engine, STT and TTS clients in this\n * directory run anywhere with a `WebSocket` global (Bun, Node, browser); platform backends\n * (mic capture, audio playback) plug in through these seams.\n */\n\nexport type VoiceState = 'idle' | 'listening' | 'thinking' | 'speaking';\n\n/** STT input sample format — sources MUST deliver this (downsample/convert in the adapter). */\nexport const STT_SAMPLE_RATE = 16000; // Hz, mono, s16le\n/** Playback format the TTS requests and sinks must play. */\nexport const TTS_SAMPLE_RATE = 44100; // Hz, mono, s16le\n\n/** A microphone (or any PCM) source. Emits s16le mono 16kHz chunks.\n * Node: mic-aec/ffmpeg child process. Web: getUserMedia({ echoCancellation: true }) + worklet. */\nexport interface AudioSource {\n /** `aec` = the source is echo-cancelled (assistant's own TTS never reaches the chunks) —\n * selects the engine's trivial barge-in path vs the heuristic echo tier. */\n readonly aec: boolean;\n start(onChunk: (pcm: Uint8Array) => void): void | Promise<void>;\n stop(): void;\n}\n\n/** An audio playback sink for s16le mono 44.1kHz PCM.\n * Node: per-turn ffplay. Web: AudioContext/worklet ring buffer. */\nexport interface AudioSink {\n /** start a new spoken turn (may recycle or recreate the underlying player) */\n markTurn(): void;\n write(pcm: Uint8Array): void;\n /** estimated ms until queued audio finishes playing */\n drainMs(): number;\n /** ms of audio actually played this turn */\n playedMs(): number;\n /** stop playback NOW (barge-in primitive) */\n kill(): void;\n /** optional exact-sample pause/resume — enables the overlap trail-off tier (web: AudioContext\n * suspend/resume; CLI AEC helper: control frames). Sinks without it degrade to interrupt-only\n * turn-taking. Nothing is lost across a pause; playedMs/drainMs must exclude paused time. */\n pause?(): void;\n resume?(): void;\n}\n\n/** Static key (server/CLI) or an async getter (browser: fetch a short-lived token from YOUR\n * backend). Getters are invoked on EVERY (re)connect — temp tokens expire, so a reconnect\n * must re-mint, never reuse the boot-time token. */\nexport type AuthProvider = string | (() => string | Promise<string>);\n\nexport async function resolveAuth(auth: AuthProvider): Promise<string> {\n return typeof auth === 'function' ? await auth() : auth;\n}\n","/**\n * Cartesia streaming TTS over a warm WebSocket — raw-delta continuations (prosody stitched\n * server-side, no sentence chunker), per-context cancel (barge-in), stale-context filtering.\n * Portable: browser/Bun/Node. Auth: static key (server) or BE-minted access token (browser).\n *\n * Browser auth: NEVER ship the real key — your backend mints a short-lived access token\n * (Cartesia `POST /access-tokens`, sent with the real X-API-Key) and the client uses\n * `auth: () => fetch('/your-be/cartesia-token').then(r => r.text())` + `authMode: 'token'`.\n */\nimport { forComponent } from '../logging';\nimport { type AuthProvider, resolveAuth, TTS_SAMPLE_RATE } from './types';\n\nconst log = forComponent('CartesiaTTS');\nconst now = () => performance.now();\n\nexport class CartesiaTTSOptions {\n auth: AuthProvider = '';\n voiceId = '';\n model = 'sonic-3.5';\n /** 'apiKey' (server/CLI) → `api_key=` URL param; 'token' (browser, BE-minted) → `access_token=`. */\n authMode: 'apiKey' | 'token' = 'apiKey';\n}\n\nexport class CartesiaTTS {\n public options: CartesiaTTSOptions;\n private ws!: WebSocket;\n private ctxSeq = 0;\n public ctxId = '';\n public onAudio: (chunk: Uint8Array) => void = () => {};\n public onDone: () => void = () => {};\n public firstAudioAt = 0;\n /** Circuit breaker: consecutive error count + down flag. */\n private consecutiveErrors = 0;\n private consecutiveOk = 0;\n private down = false;\n private downAt = 0;\n private probeTimer: ReturnType<typeof setInterval> | null = null;\n private static readonly CB_THRESHOLD = 3; // open after 3 consecutive errors\n private static readonly CB_RECOVER_OK = 2; // close only after 2 consecutive good frames (no single-frame flap)\n private static readonly CB_PROBE_MS = 30_000;\n\n constructor(options?: Partial<CartesiaTTSOptions>) {\n this.options = { ...new CartesiaTTSOptions(), ...options };\n }\n\n private closed = false;\n private connecting: Promise<void> | null = null;\n\n async connect(): Promise<void> {\n this.closed = false;\n this.connecting = this.doConnect();\n await this.connecting;\n this.connecting = null;\n }\n\n private async doConnect(): Promise<void> {\n const key = await resolveAuth(this.options.auth); // per-connect: temp tokens expire\n const param = this.options.authMode === 'token' ? 'access_token' : 'api_key';\n this.ws = new WebSocket(`wss://api.cartesia.ai/tts/websocket?cartesia_version=2026-03-01&${param}=${key}`);\n await new Promise<void>((res, rej) => {\n this.ws.onopen = () => res();\n this.ws.onerror = (e: any) => rej(new Error(`cartesia ws: ${e.message || 'connect failed'}`));\n });\n this.ws.onclose = (ev: any) => {\n log.warn(`cartesia ws closed (${ev.code} ${ev.reason || ''})`);\n if (!this.closed) { this.connecting = this.doConnect().catch((e) => log.error(`cartesia reconnect failed: ${e.message}`)); }\n };\n this.ws.onmessage = (ev) => {\n const m = JSON.parse(String(ev.data));\n if (m.context_id && m.context_id !== this.ctxId) return; // stale context (post-cancel stragglers)\n if (m.type === 'chunk' && m.data) {\n this.consecutiveErrors = 0;\n this.markRecovered();\n if (!this.firstAudioAt) this.firstAudioAt = now();\n this.onAudio(base64ToBytes(m.data));\n } else if (m.type === 'done') {\n this.consecutiveErrors = 0;\n this.markRecovered();\n this.onDone();\n }\n else if (m.type === 'error') {\n if (/already been cancelled|does not exist/.test(m.message || '')) return;\n this.consecutiveErrors++;\n if (!this.down && this.consecutiveErrors >= CartesiaTTS.CB_THRESHOLD) {\n this.down = true;\n this.downAt = now();\n this.consecutiveOk = 0;\n log.warn(`TTS circuit breaker open — ${this.consecutiveErrors} consecutive errors, switching to text-only`);\n this.onDone(); // release any pending drain\n this.startProbe();\n } else if (!this.down) {\n log.warn(`cartesia: ${JSON.stringify(m)}`);\n }\n }\n };\n }\n\n /** Close the breaker only after CB_RECOVER_OK consecutive good frames, so a single straggler chunk\n * after a 503 burst doesn't flap open→recover in <1s. A sub-2s down-window is a transient blip → debug. */\n private markRecovered(): void {\n if (!this.down) return;\n if (++this.consecutiveOk < CartesiaTTS.CB_RECOVER_OK) return;\n this.down = false;\n this.consecutiveOk = 0;\n this.stopProbe();\n const downMs = this.downAt ? now() - this.downAt : 0;\n (downMs < 2000 ? log.debug : log.info)(`TTS recovered${downMs ? ` (down ${downMs}ms)` : ''}`);\n }\n\n /** Ensure the WS is open before sending — reconnects if idle-closed. */\n private async ensureConnected(): Promise<void> {\n if (this.connecting) await this.connecting;\n if (this.ws?.readyState !== WebSocket.OPEN) await this.connect();\n }\n newContext(): string {\n this.ctxId = `ctx-${++this.ctxSeq}`;\n this.firstAudioAt = 0;\n return this.ctxId;\n }\n private frame(transcript: string, cont: boolean): string {\n return JSON.stringify({\n model_id: this.options.model,\n transcript,\n voice: { mode: 'id', id: this.options.voiceId },\n output_format: { container: 'raw', encoding: 'pcm_s16le', sample_rate: TTS_SAMPLE_RATE },\n context_id: this.ctxId,\n continue: cont,\n });\n }\n speak(text: string, cont: boolean): void {\n if (this.down) return;\n // An empty continuation has nothing to synthesize and Cartesia hard-400s on it (\"transcript must\n // not be empty when continue is true unless flushing\"). Deltas that sanitize to nothing (a chunk of\n // pure markdown/whitespace via forSpeech) hit this — drop them. The real flush is end()'s cont=false.\n if (cont && !text) return;\n if (this.ws?.readyState === WebSocket.OPEN) this.ws.send(this.frame(text, cont));\n else void this.ensureConnected().then(() => this.ws?.readyState === WebSocket.OPEN && this.ws.send(this.frame(text, cont)));\n }\n end(): void {\n if (this.down) { this.onDone(); return; }\n if (this.ws?.readyState === WebSocket.OPEN) this.ws.send(this.frame('', false));\n }\n cancel(): void {\n if (this.ws?.readyState === WebSocket.OPEN) this.ws.send(JSON.stringify({ context_id: this.ctxId, cancel: true }));\n }\n private startProbe(): void {\n if (this.probeTimer) return;\n this.probeTimer = setInterval(() => {\n if (!this.down) { this.stopProbe(); return; }\n this.consecutiveErrors = 0;\n // bypass the `down` guard in speak() — send a probe frame directly\n this.newContext();\n if (this.ws?.readyState === WebSocket.OPEN) this.ws.send(this.frame('.', false));\n }, CartesiaTTS.CB_PROBE_MS);\n (this.probeTimer as any).unref?.();\n }\n private stopProbe(): void {\n if (this.probeTimer) { clearInterval(this.probeTimer); this.probeTimer = null; }\n }\n close(): void {\n this.closed = true;\n this.stopProbe();\n if (this.ws) this.ws.onclose = null as any;\n this.ws?.close();\n }\n}\n\n/** atob-based for browsers, Buffer for Bun/Node — both produce a Uint8Array. */\nfunction base64ToBytes(b64: string): Uint8Array {\n if (typeof Buffer !== 'undefined') return Buffer.from(b64, 'base64');\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport { forComponent } from './logging';\nimport { mcpToolsToAgentTools, makeMcpToolSearchFromMounted, makeLazyMcpToolSearch, type McpToolSpec, type McpToolSearchOptions } from './mcp';\nimport type { AgentTool } from './tools';\n\nconst log = forComponent('mcp');\n\n/**\n * Real MCP (Model Context Protocol) client — node-only, deliberately kept OUT of the edge-safe\n * `src/index.ts` entry. It speaks JSON-RPC 2.0 over a transport (stdio child process or HTTP),\n * performs the `initialize` handshake + `tools/list` discovery, then hands `(specs, callTool)` to\n * the pure `src/mcp.ts` adapter — so the browser/edge build keeps working without importing this.\n */\n\nconst PROTOCOL_VERSION = '2025-06-18';\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** A JSON-RPC 2.0 transport: request (awaits a result), notify (fire-and-forget), close. */\nexport interface McpTransport {\n start(): Promise<void>;\n request(method: string, params?: unknown): Promise<any>;\n notify(method: string, params?: unknown): Promise<void>;\n close(): Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// stdio transport — newline-delimited JSON-RPC over a spawned child's stdin/stdout.\n// ---------------------------------------------------------------------------\nexport interface StdioServerSpec {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n timeoutMs?: number;\n}\n\nexport class StdioTransport implements McpTransport {\n private proc?: ChildProcess;\n private buf = '';\n private nextId = 1;\n private pending = new Map<number, { resolve: (v: any) => void; reject: (e: any) => void; timer: ReturnType<typeof setTimeout> }>();\n\n constructor(private spec: StdioServerSpec) {}\n\n async start(): Promise<void> {\n const { command, args = [], env, cwd } = this.spec;\n const proc = spawn(command, args, { stdio: ['pipe', 'pipe', 'pipe'], env: { ...process.env, ...env }, cwd });\n this.proc = proc;\n proc.stdout!.setEncoding('utf8');\n proc.stdout!.on('data', (chunk: string) => this.onData(chunk));\n proc.stderr!.setEncoding('utf8');\n proc.stderr!.on('data', (chunk: string) => log.debug(`[${command}] stderr:`, chunk.trimEnd())); // server diagnostics\n proc.on('exit', (code) => this.failAll(new Error(`MCP server \"${command}\" exited (code ${code})`)));\n proc.on('error', (e) => this.failAll(e instanceof Error ? e : new Error(String(e))));\n }\n\n private onData(chunk: string): void {\n this.buf += chunk;\n let nl: number;\n while ((nl = this.buf.indexOf('\\n')) >= 0) {\n const line = this.buf.slice(0, nl).trim();\n this.buf = this.buf.slice(nl + 1);\n if (!line) continue;\n try { this.dispatch(JSON.parse(line)); }\n catch (e) { log.debug('dropping non-JSON line from MCP server:', line, e); } // never throw out of the stream handler\n }\n }\n\n private dispatch(msg: any): void {\n // We're a minimal client: only correlate responses to our requests; ignore server→client calls.\n if (msg?.id == null || !this.pending.has(msg.id)) return;\n const p = this.pending.get(msg.id)!;\n this.pending.delete(msg.id);\n clearTimeout(p.timer);\n if (msg.error) p.reject(new Error(msg.error?.message ?? JSON.stringify(msg.error)));\n else p.resolve(msg.result);\n }\n\n private failAll(e: Error): void {\n for (const p of this.pending.values()) { clearTimeout(p.timer); p.reject(e); }\n this.pending.clear();\n }\n\n private write(msg: unknown): void {\n if (!this.proc?.stdin) throw new Error('MCP stdio transport not started');\n this.proc.stdin.write(JSON.stringify(msg) + '\\n');\n }\n\n request(method: string, params?: unknown): Promise<any> {\n const id = this.nextId++;\n const timeoutMs = this.spec.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error(`MCP request \"${method}\" timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n this.pending.set(id, { resolve, reject, timer });\n try { this.write({ jsonrpc: '2.0', id, method, params }); }\n catch (e) { clearTimeout(timer); this.pending.delete(id); reject(e); }\n });\n }\n\n async notify(method: string, params?: unknown): Promise<void> {\n this.write({ jsonrpc: '2.0', method, params });\n }\n\n async close(): Promise<void> {\n this.failAll(new Error('MCP transport closed'));\n try { this.proc?.stdin?.end(); } catch (e) { log.debug('stdin end failed', e); }\n this.proc?.kill();\n }\n}\n\n// ---------------------------------------------------------------------------\n// HTTP transport — Streamable HTTP: POST JSON-RPC, parse JSON or an SSE response.\n// ---------------------------------------------------------------------------\nexport interface HttpServerSpec {\n url: string;\n headers?: Record<string, string>;\n /** Sugar over `headers` → `Authorization: Bearer <token>`. The headless-friendly path (no OAuth loopback);\n * inject a static token (from env / VFS secret) per our CLAUDE.md rule preferring API keys for cron/edge. */\n bearerToken?: string;\n timeoutMs?: number;\n}\n\n/** Thrown when an HTTP MCP server rejects auth (401/403). Carries `needsAuth` so callers can surface a hint\n * (\"set bearerToken / headers\") instead of a generic mount failure — without attempting an interactive flow. */\nexport class McpAuthError extends Error {\n needsAuth = true;\n constructor(public status: number, public serverName?: string) {\n super(`MCP server${serverName ? ` \"${serverName}\"` : ''} requires authentication (HTTP ${status}) — set bearerToken or headers`);\n this.name = 'McpAuthError';\n }\n}\n\nexport class HttpTransport implements McpTransport {\n private nextId = 1;\n private sessionId?: string;\n private fetchImpl: typeof fetch;\n\n constructor(private spec: HttpServerSpec, fetchImpl?: typeof fetch) {\n this.fetchImpl = fetchImpl ?? fetch;\n }\n\n async start(): Promise<void> {}\n\n request(method: string, params?: unknown): Promise<any> {\n return this.post({ jsonrpc: '2.0', id: this.nextId++, method, params }, false);\n }\n\n async notify(method: string, params?: unknown): Promise<void> {\n await this.post({ jsonrpc: '2.0', method, params }, true);\n }\n\n private async post(msg: unknown, isNotify: boolean): Promise<any> {\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n accept: 'application/json, text/event-stream',\n ...(this.spec.bearerToken ? { authorization: `Bearer ${this.spec.bearerToken}` } : {}),\n ...this.spec.headers, // explicit headers win — lets a caller override the bearer sugar if needed\n ...(this.sessionId ? { 'mcp-session-id': this.sessionId } : {}),\n };\n const resp = await this.fetchImpl(this.spec.url, {\n method: 'POST', headers, body: JSON.stringify(msg),\n signal: AbortSignal.timeout(this.spec.timeoutMs ?? DEFAULT_TIMEOUT_MS),\n });\n const sid = resp.headers.get('mcp-session-id');\n if (sid) this.sessionId = sid; // adopt the server-assigned session for subsequent calls\n if (resp.status === 401 || resp.status === 403) throw new McpAuthError(resp.status);\n if (!resp.ok) throw new Error(`MCP HTTP ${resp.status} ${resp.statusText}`);\n if (isNotify) return;\n const ct = resp.headers.get('content-type') ?? '';\n const data = ct.includes('text/event-stream') ? parseSseResponse(await resp.text()) : await resp.json();\n if (data?.error) throw new Error(data.error?.message ?? JSON.stringify(data.error));\n return data?.result;\n }\n\n async close(): Promise<void> {}\n}\n\n/** Pull the JSON-RPC response object out of an SSE body (the first `data:` payload that carries one). */\nfunction parseSseResponse(body: string): any {\n for (const line of body.split('\\n')) {\n const trimmed = line.trimStart();\n if (!trimmed.startsWith('data:')) continue;\n try {\n const obj = JSON.parse(trimmed.slice(5).trim());\n if (obj && (obj.result !== undefined || obj.error !== undefined)) return obj;\n } catch (e) { log.debug('skipping unparseable SSE data line', e); }\n }\n return {};\n}\n\n// ---------------------------------------------------------------------------\n// Client — handshake + discovery on top of a transport.\n// ---------------------------------------------------------------------------\nexport class McpClient {\n constructor(public transport: McpTransport, private clientInfo = { name: 'agentx', version: '0' }) {}\n\n /** `initialize` handshake → `notifications/initialized`. Returns the server's init result. */\n async connect(): Promise<{ serverInfo?: { name?: string; version?: string }; capabilities?: any }> {\n await this.transport.start();\n const result = await this.transport.request('initialize', {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: this.clientInfo,\n });\n await this.transport.notify('notifications/initialized');\n return result ?? {};\n }\n\n async listTools(): Promise<McpToolSpec[]> {\n const r = await this.transport.request('tools/list');\n return Array.isArray(r?.tools) ? r.tools : [];\n }\n\n async callTool(name: string, args: unknown): Promise<unknown> {\n return this.transport.request('tools/call', { name, arguments: args ?? {} });\n }\n\n async listResources(): Promise<Array<{ uri: string; name?: string; mimeType?: string }>> {\n const r = await this.transport.request('resources/list');\n return Array.isArray(r?.resources) ? r.resources : [];\n }\n\n async readResource(uri: string): Promise<any> {\n return this.transport.request('resources/read', { uri });\n }\n\n async close(): Promise<void> {\n await this.transport.close();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Config-driven mounting — Claude-style `mcpServers: { name: {...} }`.\n// ---------------------------------------------------------------------------\n/** One server: stdio (`command`+`args`+`env`) OR http (`url`+`headers`). `disabled` skips it. */\nexport interface McpServerConfig {\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n url?: string;\n headers?: Record<string, string>;\n /** `Authorization: Bearer <token>` sugar for http servers (headless-friendly; no OAuth flow). */\n bearerToken?: string;\n /** Auth strategy for http servers. `'oauth'` → the CLI resolves a token via the attended OAuth flow\n * (cli/mcpOAuth.ts) and injects it as `bearerToken` at mount; the core never runs the flow. Default none. */\n auth?: 'oauth' | 'none';\n timeoutMs?: number;\n disabled?: boolean;\n}\n\nexport interface MountedMcp {\n name: string;\n client: McpClient;\n tools: AgentTool[];\n /** Raw tool specs discovered at mount (already fetched internally) — exposed so deferred-mount\n * glue (`makeMcpToolSearchFromMounted`) needn't re-call `tools/list`. */\n specs: McpToolSpec[];\n serverInfo?: { name?: string; version?: string };\n /** The config this server was mounted with — lets a host remount it (`/mcp reconnect`). */\n config: McpServerConfig;\n}\n\n/** Build the transport for a server config (http when `url`, else stdio). Shared by every mount path. */\nfunction buildTransport(cfg: McpServerConfig): McpTransport {\n return cfg.url\n ? new HttpTransport({ url: cfg.url, headers: cfg.headers, bearerToken: cfg.bearerToken, timeoutMs: cfg.timeoutMs })\n : new StdioTransport({ command: cfg.command!, args: cfg.args, env: cfg.env, cwd: cfg.cwd, timeoutMs: cfg.timeoutMs });\n}\n\n/** Race `p` against `ms` (a per-server mount deadline). `ms` falsy/≤0 → no deadline. The caller\n * closes the half-open client on rejection so a hung server leaks nothing. */\nfunction withTimeout<T>(p: Promise<T>, ms: number | undefined, label: string): Promise<T> {\n if (!ms || ms <= 0) return p;\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`MCP \"${label}\" mount exceeded ${ms}ms`)), ms);\n (timer as any).unref?.();\n p.then((v) => { clearTimeout(timer); resolve(v); }, (e) => { clearTimeout(timer); reject(e); });\n });\n}\n\n/** Connect + discover + adapt, with optional per-server deadline; closes the client if it fails. */\nasync function mountWithDeadline(name: string, cfg: McpServerConfig, mountTimeoutMs?: number): Promise<MountedMcp> {\n const client = new McpClient(buildTransport(cfg));\n try {\n return await withTimeout((async () => {\n const init = await client.connect();\n const specs = await client.listTools();\n const tools = mcpToolsToAgentTools(specs, (tool, a) => client.callTool(tool, a), `mcp__${name}__`);\n return { name, client, tools, specs, serverInfo: init?.serverInfo, config: cfg } as MountedMcp;\n })(), mountTimeoutMs, name);\n } catch (e) {\n await client.close().catch((err) => log.debug(`close after failed mount of \"${name}\": ${err}`));\n throw e;\n }\n}\n\n/** Connect one server, discover its tools, and adapt them to prefixed AgentTools (`mcp__<name>__`). */\nexport function mountMcpServer(name: string, cfg: McpServerConfig): Promise<MountedMcp> {\n return mountWithDeadline(name, cfg);\n}\n\n/** Drop disabled/incomplete entries, warning on the incomplete ones. */\nfunction validEntries(servers: Record<string, McpServerConfig>): Array<[string, McpServerConfig]> {\n return Object.entries(servers).filter(([name, cfg]) => {\n if (!cfg || cfg.disabled) return false;\n if (!cfg.command && !cfg.url) { log.warn(`MCP server \"${name}\" needs a command (stdio) or url (http) — skipping`); return false; }\n return true;\n });\n}\n\n/** Log a mount failure (auth vs generic) without throwing — one broken server never blocks startup. */\nfunction logMountFailure(name: string, e: any): void {\n if (e instanceof McpAuthError) log.warn(`MCP \"${name}\" needs-auth: HTTP ${e.status} — set bearerToken or headers in its config; skipping`);\n else log.error(`MCP server \"${name}\" failed to mount: ${e?.message ?? e}`); // logged, then skipped\n}\n\n/**\n * Mount every configured server in PARALLEL (one slow/dead server no longer serializes the rest);\n * each may carry a `mountTimeoutMs` deadline. A server that fails is logged and skipped.\n */\nexport async function mountMcpServers(servers: Record<string, McpServerConfig> = {}, opts: { mountTimeoutMs?: number } = {}): Promise<MountedMcp[]> {\n const entries = validEntries(servers);\n const settled = await Promise.allSettled(entries.map(([name, cfg]) => mountWithDeadline(name, cfg, opts.mountTimeoutMs)));\n const out: MountedMcp[] = [];\n settled.forEach((r, i) => {\n const name = entries[i][0];\n // debug (not info): the CLI prints its own one-line mount summary — an always-on info here double-prints\n if (r.status === 'fulfilled') { out.push(r.value); log.debug(`MCP \"${name}\" mounted — ${r.value.tools.length} tool(s)${r.value.serverInfo?.name ? ` from ${r.value.serverInfo.name}` : ''}`); }\n else logMountFailure(name, r.reason);\n });\n return out;\n}\n\n/**\n * One-shot deferred MCP mount: connect every entry (failures dropped, never block startup) and\n * fold the survivors into a single `ToolSearch`/`McpCall` pair via `makeMcpToolSearchFromMounted`.\n * The node-only counterpart to that edge-safe helper — returns `mounted` too so callers can close\n * the clients on shutdown. Eager: it connects all servers up front. For lazy connect + a cached\n * catalog (zero connections on a turn that uses no MCP tool), use `mountMcpCatalog`.\n */\nexport async function mountMcpDeferred(\n servers: Record<string, McpServerConfig> = {},\n options?: McpToolSearchOptions & { mountTimeoutMs?: number },\n): Promise<{ tools: AgentTool[]; serverNames: string[]; toolCount: number; mounted: MountedMcp[] }> {\n const mounted = await mountMcpServers(servers, { mountTimeoutMs: options?.mountTimeoutMs });\n return { ...makeMcpToolSearchFromMounted(mounted, options), mounted };\n}\n\n// ---------------------------------------------------------------------------\n// Lazy connect + catalog cache — defer the CONNECTION, not just the schemas.\n// ---------------------------------------------------------------------------\n/** A persistent tool catalog: lets `mountMcpCatalog` build `ToolSearch` WITHOUT connecting when a\n * fresh entry exists. The lib defines the interface; the consumer supplies the store (RAM/disk).\n * Key = a hash of the server's resolved config (see `mcpConfigKey`). TTL/versioning is the store's. */\nexport interface McpCatalogStore {\n get(key: string): McpToolSpec[] | null;\n set(key: string, specs: McpToolSpec[]): void;\n}\n\n/** Stable cache key for a server config — command/args/cwd + env NAMES (not secret values), or\n * url + header names. Changing any of these invalidates the cached catalog; rotating a secret does not. */\nexport function mcpConfigKey(cfg: McpServerConfig): string {\n const parts = cfg.url\n ? ['http', cfg.url, ...Object.keys(cfg.headers ?? {}).sort()]\n : ['stdio', cfg.command ?? '', ...(cfg.args ?? []), cfg.cwd ?? '', ...Object.keys(cfg.env ?? {}).sort()];\n return createHash('sha256').update(parts.join('\\0')).digest('hex').slice(0, 16);\n}\n\n/** Default in-memory catalog: process-lifetime, hash-keyed, TTL-expiring (so a server that gains\n * tools is picked up after the TTL without a restart). Shared module singleton → cross-turn reuse. */\nexport class MemMcpCatalog implements McpCatalogStore {\n private m = new Map<string, { specs: McpToolSpec[]; exp: number }>();\n constructor(private ttlMs = 5 * 60_000) {}\n get(key: string): McpToolSpec[] | null {\n const e = this.m.get(key);\n if (!e) return null;\n if (Date.now() > e.exp) { this.m.delete(key); return null; }\n return e.specs;\n }\n set(key: string, specs: McpToolSpec[]): void { this.m.set(key, { specs, exp: Date.now() + this.ttlMs }); }\n}\n\n/** Opt-in warm pool: keeps stdio MCP clients connected across turns, reaping each after `ttlMs`\n * idle. Most stdio MCPs are per-turn by design, so this is off by default; HTTP servers are\n * stateless and never pooled. */\nexport class McpPool {\n private warm = new Map<string, { client: McpClient; timer: ReturnType<typeof setTimeout> }>();\n constructor(private ttlMs = 5 * 60_000) {}\n get(key: string): McpClient | null { const e = this.warm.get(key); if (!e) return null; this.arm(key, e); return e.client; }\n put(key: string, client: McpClient): void {\n const prev = this.warm.get(key); // overwrite: cancel the stale timer + close the displaced client\n if (prev) { clearTimeout(prev.timer); if (prev.client !== client) void prev.client.close().catch((err) => log.debug(`warm-pool replace close failed: ${err}`)); }\n const e = { client, timer: undefined as any };\n this.warm.set(key, e); this.arm(key, e);\n }\n private arm(key: string, e: { client: McpClient; timer: any }): void {\n clearTimeout(e.timer);\n e.timer = setTimeout(() => { void this.evict(key); }, this.ttlMs);\n (e.timer as any).unref?.();\n }\n private async evict(key: string): Promise<void> {\n const e = this.warm.get(key); if (!e) return;\n this.warm.delete(key);\n await e.client.close().catch((err) => log.debug(`warm-pool evict close failed: ${err}`));\n }\n async closeAll(): Promise<void> { for (const e of this.warm.values()) { clearTimeout(e.timer); await e.client.close().catch(() => {}); } this.warm.clear(); }\n}\n\nconst defaultCatalog = new MemMcpCatalog();\nconst defaultPool = new McpPool();\nconst defaultFailures = new Map<string, number>(); // configKey → cooldown-until epoch ms (negative cache)\nconst bgInflight = new Set<string>(); // configKey → background discovery in flight (dedupe)\nconst DEFAULT_FAILURE_COOLDOWN_MS = 60_000;\n\nexport interface McpCatalogOptions extends McpToolSearchOptions {\n /** Where to read/write discovered specs. Default: a shared process-lifetime `MemMcpCatalog`. */\n catalog?: McpCatalogStore;\n /** Per-server deadline for the connect+list on a cache MISS. A hung server is skipped, not blocking. */\n mountTimeoutMs?: number;\n /** Opt-in: keep stdio clients warm across turns (see `McpPool`). HTTP servers are never pooled. */\n keepWarm?: boolean;\n /** Warm-client pool. Default: a shared process-lifetime `McpPool` (only used when `keepWarm`). */\n pool?: McpPool;\n /** Negative cache: after a server fails/times out discovery, skip it for this long so it never\n * re-floors a turn at the deadline. Default 60s; the server is re-probed once the cooldown lapses. */\n failureCooldownMs?: number;\n /** Shared failure-cooldown map (configKey → until-epoch-ms). Default: a process-lifetime singleton. */\n failures?: Map<string, number>;\n /** Discovery policy on a cache MISS:\n * - `'connect'` (default): synchronously connect+list (deadline-bounded) — blocks until ready.\n * - `'cache-only'`: NEVER block the turn — serve only cached servers, and kick uncached discovery\n * to the background (so it's warm next turn). Pair with a boot/timer `warmMcpCatalog` so the\n * first turn is already a cache hit. */\n discover?: 'connect' | 'cache-only';\n}\n\ninterface Discovered { name: string; cfg: McpServerConfig; key: string; specs: McpToolSpec[] }\n\n/** Connect+list one server (deadline-bounded), populate the catalog on success / negative-cache on\n * failure. Closes the client unless `keepWarm` keeps it for the lazy-call phase. */\nasync function connectAndList(name: string, cfg: McpServerConfig, key: string, opts: McpCatalogOptions): Promise<Discovered | null> {\n const catalog = opts.catalog ?? defaultCatalog;\n const pool = opts.pool ?? defaultPool;\n const failures = opts.failures ?? defaultFailures;\n const client = new McpClient(buildTransport(cfg));\n try {\n const specs = await withTimeout((async () => { await client.connect(); return client.listTools(); })(), opts.mountTimeoutMs, name);\n catalog.set(key, specs);\n failures.delete(key); // recovered\n if (opts.keepWarm && !cfg.url) pool.put(key, client); // reuse this connection for the lazy-call phase\n else await client.close().catch(() => {});\n return { name, cfg, key, specs };\n } catch (e: any) {\n await client.close().catch(() => {});\n failures.set(key, Date.now() + (opts.failureCooldownMs ?? DEFAULT_FAILURE_COOLDOWN_MS));\n logMountFailure(name, e);\n return null;\n }\n}\n\n/** Resolve one server to its specs: cache hit → no connection; in failure-cooldown → skip;\n * otherwise connect (or, in `cache-only` mode, kick background discovery and skip for now). */\nasync function discoverOne(name: string, cfg: McpServerConfig, opts: McpCatalogOptions): Promise<Discovered | null> {\n const catalog = opts.catalog ?? defaultCatalog;\n const failures = opts.failures ?? defaultFailures;\n const key = mcpConfigKey(cfg);\n const cached = catalog.get(key);\n if (cached) return { name, cfg, key, specs: cached };\n const until = failures.get(key);\n if (until && until > Date.now()) return null; // negative cache → known-down, skip\n if (opts.discover === 'cache-only') {\n if (!bgInflight.has(key)) { bgInflight.add(key); void connectAndList(name, cfg, key, opts).finally(() => bgInflight.delete(key)); }\n return null; // not available THIS turn; warms for the next one\n }\n return connectAndList(name, cfg, key, opts);\n}\n\n/**\n * Lazy + cached MCP mount. Builds the `ToolSearch`/`McpCall` pair from the CACHED catalog when one\n * exists — connecting NOTHING. On a cache miss it (by default) connects once (parallel, deadline-\n * bounded), lists, caches, then disconnects (or keeps warm if `keepWarm`). A server is connected only\n * when one of its tools is actually invoked via `McpCall` (memoized per turn; reused from the warm\n * pool if enabled). A server that fails/times out is negative-cached (`failureCooldownMs`) so it\n * never re-floors a later turn.\n *\n * For zero turn-path latency even on a cold process, set `discover: 'cache-only'` and call\n * `warmMcpCatalog` at boot + on a timer: the turn then NEVER synchronously connects — it serves\n * cached servers and warms the rest in the background.\n *\n * Per-turn cost: a turn using NO MCP tool → 0 connections; a turn using one → exactly one.\n */\nexport async function mountMcpCatalog(\n servers: Record<string, McpServerConfig> = {},\n opts: McpCatalogOptions = {},\n): Promise<{ tools: AgentTool[]; serverNames: string[]; toolCount: number; connect(name: string): Promise<McpClient>; close(): Promise<void> }> {\n const pool = opts.pool ?? defaultPool;\n const discovered = (await Promise.all(validEntries(servers).map(([name, cfg]) => discoverOne(name, cfg, opts)))).filter(Boolean) as Discovered[];\n\n const byName = new Map(discovered.map((d) => [d.name, d]));\n const inflight = new Map<string, Promise<McpClient>>(); // memoize per server → concurrent calls share one connect\n const live: McpClient[] = []; // non-warm clients opened this turn (closed on close())\n\n const connect = (name: string): Promise<McpClient> => {\n let p = inflight.get(name);\n if (p) return p;\n p = (async () => {\n const d = byName.get(name);\n if (!d) throw new Error(`MCP server '${name}' is not in the catalog`);\n const warmable = opts.keepWarm && !d.cfg.url;\n if (warmable) { const w = pool.get(d.key); if (w) return w; }\n const client = new McpClient(buildTransport(d.cfg));\n await client.connect();\n if (warmable) pool.put(d.key, client); else live.push(client);\n return client;\n })();\n inflight.set(name, p);\n return p;\n };\n\n const search = makeLazyMcpToolSearch(\n discovered.map((d) => ({ name: d.name, specs: d.specs })),\n async (server, rawName, args) => (await connect(server)).callTool(rawName, args),\n opts,\n );\n const close = async (): Promise<void> => { for (const c of live) await c.close().catch(() => {}); live.length = 0; inflight.clear(); };\n return { ...search, connect, close };\n}\n\n/**\n * Off-turn catalog warm-up: do the one cold discovery pass (connect + list, parallel, deadline-\n * bounded) so a later `mountMcpCatalog(..., { discover: 'cache-only' })` is a cache HIT. Call at\n * server boot and on a timer (cadence < the catalog TTL). Cache hits cost nothing; down servers are\n * negative-cached so turns never touch them. Returns which servers warmed vs failed.\n */\nexport async function warmMcpCatalog(\n servers: Record<string, McpServerConfig> = {},\n opts: McpCatalogOptions = {},\n): Promise<{ warmed: string[]; failed: string[]; toolCount: number }> {\n const entries = validEntries(servers);\n const discovered = (await Promise.all(entries.map(([name, cfg]) => discoverOne(name, cfg, { ...opts, discover: 'connect' })))).filter(Boolean) as Discovered[];\n const warmedNames = new Set(discovered.map((d) => d.name));\n return {\n warmed: discovered.map((d) => d.name),\n failed: entries.map(([n]) => n).filter((n) => !warmedNames.has(n)),\n toolCount: discovered.reduce((s, d) => s + d.specs.length, 0),\n };\n}\n","/**\n * MCP OAuth — node-only, CLI-gated token acquisition for hosted (OAuth-only) MCP servers.\n *\n * NOT a transport: it produces a bearer token that feeds the existing `HttpServerSpec.bearerToken`\n * path in `src/mcp.client.ts` (which stays edge-safe and untouched). The model the user asked for:\n * - register() = ATTENDED, one-time — PKCE + loopback callback + browser; persists {access,refresh}.\n * - tokenFor() = UNATTENDED — returns the cached access token; refreshes via refresh_token grant\n * (a plain HTTP POST, no browser) when expired; throws McpAuthError when re-auth is\n * genuinely required, so the CLI can prompt `--mcp-login` again.\n *\n * All side-effectful deps (fetch, browser opener, clock, store path) are injectable for headless tests.\n */\nimport { createServer } from 'node:http';\nimport { randomBytes, createHash } from 'node:crypto';\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { McpAuthError } from '../src/mcp.client';\n\nexport interface TokenBundle {\n access_token: string;\n refresh_token?: string;\n expires_at?: number; // epoch ms; absent = never expires\n client_id?: string;\n token_endpoint: string;\n}\ntype Store = Record<string, TokenBundle>; // keyed by server URL\n\n/** OAuth Authorization Server metadata (the subset we use). */\ninterface AsMetadata {\n authorization_endpoint: string;\n token_endpoint: string;\n registration_endpoint?: string;\n}\n\nexport class McpOAuthOptions {\n /** Where to persist tokens. Mode 0600. */\n storePath = '.agent/mcp-auth.json';\n /** Injectable fetch (tests pass a fake authorization server). */\n fetchImpl: typeof fetch = fetch;\n /** Open the user's browser to the authorize URL (attended). Tests inject an auto-approver. */\n openBrowser: (url: string) => void | Promise<void> = defaultOpenBrowser;\n /** Clock (epoch ms) — injectable so token-expiry tests are deterministic. */\n now: () => number = () => Date.now();\n /** Seconds of slack before `expires_at` at which we proactively refresh. */\n skewSeconds = 60;\n /** Pre-registered client_id (used when the server doesn't support Dynamic Client Registration). */\n clientId?: string;\n /** OAuth scopes to request. */\n scope?: string;\n /** How long register() waits for the browser callback before giving up. */\n callbackTimeoutMs = 180_000;\n}\n\nexport class McpOAuth {\n public options: McpOAuthOptions;\n constructor(options?: Partial<McpOAuthOptions>) {\n this.options = { ...new McpOAuthOptions(), ...options };\n }\n\n // -- store I/O ----------------------------------------------------------------\n private load(): Store {\n try { return existsSync(this.options.storePath) ? JSON.parse(readFileSync(this.options.storePath, 'utf8')) : {}; }\n catch { return {}; } // a corrupt store should not wedge auth — start fresh\n }\n private save(store: Store): void {\n mkdirSync(dirname(this.options.storePath), { recursive: true });\n writeFileSync(this.options.storePath, JSON.stringify(store, null, 2), { mode: 0o600 });\n }\n\n // -- ATTENDED: one-time authorization ----------------------------------------\n /** Run the authorization-code + PKCE flow and persist the resulting tokens for `serverUrl`. */\n async register(serverUrl: string): Promise<TokenBundle> {\n const meta = await this.discover(serverUrl);\n const clientId = this.options.clientId ?? (await this.registerClient(meta, serverUrl));\n const verifier = b64url(randomBytes(32));\n const challenge = b64url(createHash('sha256').update(verifier).digest());\n const state = b64url(randomBytes(16));\n\n const { code, redirectUri } = await this.captureCode(meta.authorization_endpoint, clientId, challenge, state);\n const tok = await this.exchange(meta.token_endpoint, {\n grant_type: 'authorization_code', code, redirect_uri: redirectUri, client_id: clientId, code_verifier: verifier,\n });\n\n const bundle: TokenBundle = {\n access_token: tok.access_token,\n refresh_token: tok.refresh_token,\n expires_at: tok.expires_in ? this.options.now() + tok.expires_in * 1000 : undefined,\n client_id: clientId,\n token_endpoint: meta.token_endpoint,\n };\n const store = this.load();\n store[serverUrl] = bundle;\n this.save(store);\n return bundle;\n }\n\n // -- UNATTENDED: cached token, refreshed on demand ---------------------------\n /** Return a valid access token for `serverUrl`, refreshing if expired. Throws McpAuthError if re-login is needed. */\n async tokenFor(serverUrl: string): Promise<string> {\n const store = this.load();\n const b = store[serverUrl];\n if (!b) throw new McpAuthError(401, serverUrl); // never registered → needs attended login\n const skew = this.options.skewSeconds * 1000;\n if (b.expires_at == null || b.expires_at - skew > this.options.now()) return b.access_token; // still fresh\n if (!b.refresh_token) throw new McpAuthError(401, serverUrl); // expired, nothing to refresh with\n\n try {\n const tok = await this.exchange(b.token_endpoint, {\n grant_type: 'refresh_token', refresh_token: b.refresh_token, client_id: b.client_id ?? '',\n });\n b.access_token = tok.access_token;\n if (tok.refresh_token) b.refresh_token = tok.refresh_token; // rotation\n b.expires_at = tok.expires_in ? this.options.now() + tok.expires_in * 1000 : undefined;\n this.save(store);\n return b.access_token;\n } catch (e) {\n throw new McpAuthError(401, serverUrl); // refresh token dead/revoked → attended re-login\n }\n }\n\n /** True if we hold any (even expired) credentials for `serverUrl`. */\n has(serverUrl: string): boolean { return !!this.load()[serverUrl]; }\n\n // -- internals ----------------------------------------------------------------\n /** Discover the Authorization Server metadata from the server's origin (RFC 8414 well-known endpoints). */\n private async discover(serverUrl: string): Promise<AsMetadata> {\n const origin = new URL(serverUrl).origin;\n const candidates = [`${origin}/.well-known/oauth-authorization-server`, `${origin}/.well-known/openid-configuration`];\n for (const u of candidates) {\n try {\n const r = await this.options.fetchImpl(u);\n if (!r.ok) continue;\n const m = await r.json();\n if (m?.authorization_endpoint && m?.token_endpoint) return m as AsMetadata;\n } catch { /* try the next candidate */ }\n }\n throw new Error(`could not discover OAuth metadata for ${serverUrl} (tried ${candidates.join(', ')})`);\n }\n\n /** Dynamic Client Registration (RFC 7591) when no client_id was configured and the server supports it. */\n private async registerClient(meta: AsMetadata, serverUrl: string): Promise<string> {\n if (!meta.registration_endpoint) {\n throw new Error(`${serverUrl} needs a client_id (no Dynamic Client Registration); pass clientId in options`);\n }\n const r = await this.options.fetchImpl(meta.registration_endpoint, {\n method: 'POST', headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ client_name: 'agentx', grant_types: ['authorization_code', 'refresh_token'], token_endpoint_auth_method: 'none', redirect_uris: ['http://127.0.0.1/callback'] }),\n });\n if (!r.ok) throw new Error(`dynamic client registration failed (${r.status})`);\n const j = await r.json();\n if (!j?.client_id) throw new Error('registration response missing client_id');\n return j.client_id as string;\n }\n\n /** Start a one-route loopback server, open the browser, and resolve with the returned auth code. */\n private captureCode(authEndpoint: string, clientId: string, challenge: string, state: string): Promise<{ code: string; redirectUri: string }> {\n return new Promise((resolve, reject) => {\n const server = createServer((req, res) => {\n const url = new URL(req.url ?? '/', 'http://127.0.0.1');\n if (url.pathname !== '/callback') { res.writeHead(404).end(); return; }\n const code = url.searchParams.get('code');\n const gotState = url.searchParams.get('state');\n res.writeHead(200, { 'content-type': 'text/html' }).end('<h3>Authorized — you can close this tab.</h3>');\n server.close();\n clearTimeout(timer);\n if (gotState !== state) return reject(new Error('OAuth state mismatch (possible CSRF) — aborting'));\n if (!code) return reject(new Error(`authorization failed: ${url.searchParams.get('error') ?? 'no code'}`));\n resolve({ code, redirectUri });\n });\n let redirectUri = '';\n const timer = setTimeout(() => { server.close(); reject(new Error('timed out waiting for browser authorization')); }, this.options.callbackTimeoutMs);\n server.listen(0, '127.0.0.1', async () => {\n const port = (server.address() as { port: number }).port;\n redirectUri = `http://127.0.0.1:${port}/callback`;\n const auth = new URL(authEndpoint);\n auth.searchParams.set('response_type', 'code');\n auth.searchParams.set('client_id', clientId);\n auth.searchParams.set('redirect_uri', redirectUri);\n auth.searchParams.set('code_challenge', challenge);\n auth.searchParams.set('code_challenge_method', 'S256');\n auth.searchParams.set('state', state);\n if (this.options.scope) auth.searchParams.set('scope', this.options.scope);\n try { await this.options.openBrowser(auth.toString()); }\n catch (e) { server.close(); clearTimeout(timer); reject(e instanceof Error ? e : new Error(String(e))); }\n });\n });\n }\n\n /** POST an x-www-form-urlencoded token request and return the parsed token response. */\n private async exchange(tokenEndpoint: string, params: Record<string, string>): Promise<{ access_token: string; refresh_token?: string; expires_in?: number }> {\n const r = await this.options.fetchImpl(tokenEndpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' },\n body: new URLSearchParams(params).toString(),\n });\n if (!r.ok) throw new Error(`token endpoint returned ${r.status}`);\n const j = await r.json();\n if (!j?.access_token) throw new Error('token response missing access_token');\n return j;\n }\n}\n\n/** base64url with no padding (PKCE + state). */\nfunction b64url(buf: Buffer): string {\n return buf.toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Best-effort cross-platform browser open (macOS `open`, Linux `xdg-open`, Windows `start`). */\nfunction defaultOpenBrowser(url: string): void {\n const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'cmd' : 'xdg-open';\n const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];\n import('node:child_process').then(({ spawn }) => spawn(cmd, args, { stdio: 'ignore', detached: true }).unref());\n}\n","import { randomUUID } from 'node:crypto';\nimport { execFile } from 'node:child_process';\nimport { resolve, basename, join } from 'node:path';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { platform, arch, release, userInfo, homedir, tmpdir } from 'node:os';\nimport { Agent, AgentOptions, NodeDiskFilesystem, JailedFilesystem, MemFilesystem, MountFilesystem, BodDbFilesystem, toolsByName, composeHooks, lessonCapture, mkdirp, Scratch, makeAskTool } from '../src/index';\nimport type { ChatLike, Hooks, HostBridge, RunResult, PermissionPolicy, AgentTool, IFilesystem } from '../src/index';\nimport { makeRealShellTool, makeShellJobTools, ShellJobRegistry } from '../src/tools.shell'; // node-only; imported directly (not via index — keeps index edge-safe)\nimport { makeNotifyTool } from '../src/tools.notify'; // node-only, same policy\nimport type { OsSandboxOptions } from '../src/shell.sandbox';\nimport type { McpServerConfig } from '../src/mcp.client';\nimport { BodDB } from '@bod.ee/db'; // node-only DB backing the `--boddb` workspace mode\nimport { dotDirs } from './util';\n\n/**\n * The CLI's testable core: build an Agent rooted at a real-disk cwd (jailed so secrets\n * like .env stay invisible) with the full tool set, streaming, and the hooks/host seams\n * the terminal UI uses for live display. Auto-loads .agent/{skills,commands,memory}.\n */\nexport interface CliOptions {\n ai: ChatLike;\n model?: string;\n cwd?: string;\n tools?: string[];\n stream?: boolean;\n host?: HostBridge;\n hooks?: Hooks;\n planMode?: boolean;\n permissions?: PermissionPolicy;\n maxSteps?: number;\n /** Normalized reasoning/thinking effort: 'off'|'low'|'medium'|'high' or a raw token budget. */\n reasoning?: import('../src/index').ReasoningEffort;\n subagents?: boolean;\n /** Enable sandbox background jobs (`bash({background:true})` + Job tools). Defaults ON in `--sandbox`\n * (where there's no real shell to background); the disk path already has the real ShellJobRegistry. */\n backgroundJobs?: boolean;\n /** Root filenames loaded as project instructions (default AGENTS.md, CLAUDE.md). */\n instructionFiles?: string[];\n /** Extra tools appended to the resolved set (e.g. tools discovered from mounted MCP servers). */\n extraTools?: AgentTool[];\n /** REQUIRED — the filesystem access mode, chosen explicitly (no silent default; buildAgent THROWS\n * if omitted). `false` = disk: the REAL filesystem with full reach, like Claude Code (root '/' is the\n * machine root, cwd is the working dir; secrets are still hidden by the jail). `true` = sandbox: an\n * in-memory COPY of cwd — the real disk is never modified and nothing outside cwd exists. Forcing the\n * choice ensures a programmatic consumer always knows whether its run is sandboxed. The CLI always\n * passes it (`--sandbox` → true, else false), so the CLI never throws. */\n sandbox: boolean;\n /** Database-backed filesystem mode: the agent's file tree lives in a persistent bod-db workspace\n * at this directory path (a `meta.db` SQLite tree + a `files/` byte store), surviving across runs.\n * The real disk is never touched. DB-native by default (starts with whatever the DB holds); pair\n * with `seed` to hydrate it from cwd on the first run. Mutually exclusive with `sandbox`. */\n boddb?: string;\n /** Only with `boddb`: on the first run (empty DB), copy the cwd subtree into the DB to seed it. */\n seed?: boolean;\n /** `full` mode: add the opt-in real-shell tool (spawns /bin/sh; gated by permissions). */\n realShell?: boolean;\n /** Tier-1 hardening: OS-sandbox the real shell (sandbox-exec/bwrap) — writes confined to cwd+tmp,\n * network deniable. Fails closed when no wrapper exists. Ignored when the real shell is off. */\n osSandbox?: boolean | Partial<OsSandboxOptions>;\n /** Extra instructions appended to the system prompt for this run (CC's --append-system-prompt). */\n appendSystemPrompt?: string;\n /** Additional real directories to mount into the VFS beyond cwd (CC's --add-dir). Ignored in sandbox. */\n addDirs?: string[];\n // kill-switches (undefined => use the Agent's built-in safety defaults)\n maxTokens?: number;\n timeoutMs?: number;\n maxRepeats?: number;\n maxToolCalls?: number;\n // context shaping (undefined => CLI default below / Agent default)\n keepToolOutputs?: number;\n maxContextTokens?: number;\n /** Auto-capture recurring tool failures as memory lessons (needs .agent/memory). Default off — it writes files. */\n learnFromMistakes?: boolean;\n /** Configured MCP servers, forwarded to autonomous runtimes (cursor/*) for environment parity — the\n * delegated agent sees the same MCP servers as this host. Note: env/tokens cross into the cursor\n * subprocess (same machine/user). Ignored for chat-model providers. */\n mcpServers?: Record<string, McpServerConfig>;\n /** Enable scratch context-offload: oversized web outputs spill to files (kept out of context,\n * queryable via Grep/Read or the `Ask` tool). Lives in the agent's own fs, so it's ephemeral in\n * sandbox/boddb (MemFilesystem) and persists on disk otherwise. Default off. */\n scratch?: boolean;\n /** Dir for scratch files (default `<cwd>/.agent/scratch`). The CLI passes a session-specific subdir\n * so captures persist across resume and don't bleed between sessions. */\n scratchDir?: string;\n /** Model for the `Ask` peek (the cheap retrieve/extract tier). Default: the main model. */\n scratchAskModel?: string;\n}\n\n/** Default CLI tool set — the structured tools the self-evolution found most efficient.\n * ApplyEdits (cross-file atomic batch, no prior Read) + RepoMap (signature digest) were the\n * primitives the evolve arc adopted to collapse multi-file refactors; duplex workers inherit them. */\nexport const DEFAULT_TOOLS = ['bash', 'Read', 'Edit', 'Write', 'Grep', 'Glob', 'MultiEdit', 'ApplyEdits', 'RepoMap', 'TodoWrite'];\n\n/** Web tools — both keyless by default (WebSearch uses DuckDuckGo, auto-upgrades to Tavily when TAVILY_API_KEY is set). */\nfunction autoWebTools(): string[] {\n return ['WebFetch', 'WebSearch'];\n}\n\n/** PDF text extraction for Read on .pdf — poppler's `pdftotext <file> -` (no JS dep). Throws a\n * readable message when poppler isn't installed; the Read tool surfaces it to the model. */\nfunction pdfTextViaPoppler(path: string): Promise<string> {\n return new Promise((res, rej) => {\n execFile('pdftotext', [path, '-'], { maxBuffer: 32 * 1024 * 1024, timeout: 30_000 }, (e, stdout) => {\n if (e) rej(new Error(/ENOENT/.test(String((e as any).code ?? e.message)) ? 'pdftotext not installed (brew/apt install poppler)' : e.message));\n else res(stdout);\n });\n });\n}\n\n/** Directory names never copied into the sandbox VFS (heavy/derived/VCS) — keeps hydration bounded. */\nconst SANDBOX_SKIP = new Set(['node_modules', '.git', 'dist', 'build', '.next', 'coverage', '.cache']);\n\n/** Copy a disk tree into another FS (bounded: skips heavy dirs). The source is jailed, so\n * secrets are already invisible and never enter the target (in-mem sandbox or a bod-db store).\n * Returns the file count copied. */\nasync function hydrate(from: IFilesystem, to: IFilesystem, dir = '/'): Promise<number> {\n let n = 0;\n for (const name of await from.readDir(dir).catch(() => [])) {\n if (SANDBOX_SKIP.has(name)) continue;\n const p = dir === '/' ? '/' + name : dir + '/' + name;\n if (await from.isDirectory(p)) { await to.createDir(p).catch(() => {}); n += await hydrate(from, to, p); }\n else { const c = await from.readFile(p).catch(() => null); if (c != null) { await to.writeFile(p, c).catch(() => {}); n++; } }\n }\n return n;\n}\n\n/**\n * Map agentx MCP config to the @cursor/sdk shape (`AgentOptions.mcpServers`) for environment parity in\n * cursor delegations. SDK accepts `{type?:'stdio',command,args,env,cwd} | {type?:'http'|'sse',url,headers}`\n * — near-identical to ours; `bearerToken` becomes an `Authorization` header. Skips disabled servers and\n * http servers whose oauth token wasn't resolved (cursor can't run the attended flow). Returns the\n * `{ mcpServers }` fragment only when non-empty, so an empty map never clobbers cursor's own ambient\n * config layers (~/.cursor/mcp.json).\n */\nexport function toCursorMcp(servers?: Record<string, McpServerConfig>): { mcpServers: Record<string, unknown> } | undefined {\n if (!servers) return undefined;\n const out: Record<string, unknown> = {};\n for (const [name, s] of Object.entries(servers)) {\n if (!s || s.disabled) continue;\n if (s.command) {\n out[name] = { type: 'stdio', command: s.command, ...(s.args ? { args: s.args } : {}), ...(s.env ? { env: s.env } : {}), ...(s.cwd ? { cwd: s.cwd } : {}) };\n } else if (s.url) {\n if (s.auth === 'oauth' && !s.bearerToken) continue; // unresolved oauth — cursor can't complete the flow\n const headers = { ...(s.headers ?? {}), ...(s.bearerToken ? { Authorization: `Bearer ${s.bearerToken}` } : {}) };\n out[name] = { url: s.url, ...(Object.keys(headers).length ? { headers } : {}) };\n }\n }\n return Object.keys(out).length ? { mcpServers: out } : undefined;\n}\n\n/**\n * Cursor-only providerOptions for a given model: anchors cursor to `cwd`, forwards MCP servers, and (unless\n * CURSOR_WARM=0) mints a FRESH warm-session id. Returns undefined for non-cursor models — critical because\n * the Anthropic/OpenAI adapters Object.assign providerOptions straight into the request body, so leaking\n * `cwd`/`cursorSession` to them is a hard 400 (\"cwd: Extra inputs are not permitted\"). Each caller (main\n * agent + every duplex worker) gets its OWN session id — sharing one across concurrent agents collides.\n */\nexport function cursorProviderOptions(model: string | undefined, cwd: string, mcpServers?: Record<string, McpServerConfig>): Record<string, unknown> | undefined {\n if (!(model ?? '').startsWith('cursor/')) return undefined;\n return { cwd, ...(toCursorMcp(mcpServers) ?? {}), ...(process.env.CURSOR_WARM === '0' ? {} : { cursorSession: randomUUID() }) };\n}\n\nexport async function buildAgent(o: CliOptions): Promise<Agent> {\n // No silent default: a consumer must consciously choose disk (full real-FS reach) vs sandbox.\n if (typeof o.sandbox !== 'boolean')\n throw new Error(\n \"buildAgent: explicit `sandbox` required — false = disk (the REAL filesystem, full reach like Claude Code; secrets still hidden) or true = sandbox (an in-memory copy of cwd; the real disk is never modified). This forces a conscious sandboxing decision.\");\n const cwd = resolve(o.cwd ?? process.cwd());\n // Claude-Code parity: root the disk backend at the REAL filesystem root and set the working dir to\n // cwd, so absolute host paths (/Users/…) and reaching above cwd both work like a normal shell.\n // denySymlinks is OFF — at root '/', system dirs (/tmp,/var,/etc on macOS) are symlinks; the\n // escape-defense only matters for a *confined* root (evolve/library keep their own jailed cwd-root).\n // The jail still hides secrets machine-wide by name (DEFAULT_DENY: .env, .ssh, .aws, .git, keys…).\n const disk = new NodeDiskFilesystem('/', { denySymlinks: false });\n await disk.init();\n const jailedDisk = new JailedFilesystem(disk); // boundary A: hide secrets even on the real disk\n jailedDisk.setCwd(cwd); // working dir = launch dir (root '/' = real machine)\n // sandbox mode: agent operates over an in-memory COPY of the cwd subtree → real disk is never\n // written, and nothing outside cwd exists. Same real-path namespace as disk mode (cwd mirrored at\n // its absolute path), so paths behave identically in both modes.\n // \"virtual\" = a non-disk filesystem (sandbox copy or bod-db store): no real /bin/sh (it would escape\n // to disk), VFS bash + background jobs instead, and the real disk is never modified.\n const virtual = o.sandbox || !!o.boddb;\n // cursor/* is an autonomous runtime that runs its OWN tools on the real disk via @cursor/sdk\n // (Agent.create({ local: { cwd } })) — so it needs the launch cwd, and it can't honor a VFS jail.\n const isCursor = (o.model ?? '').startsWith('cursor/');\n // Refuse sandbox/boddb for cursor rather than silently let the agent escape the VFS the flags promise.\n if (virtual && isCursor)\n throw new Error(\n 'cursor/* models cannot run in --sandbox/--boddb: the Cursor agent runs its own real-disk tools and bypasses the VFS jail. Use disk mode (default).');\n let fs: IFilesystem = jailedDisk;\n if (o.sandbox) {\n const mem = new MemFilesystem();\n await mkdirp(mem, cwd); // materialize the cwd path chain so the copy sits at its real path\n await hydrate(jailedDisk, mem, cwd); // copy only the cwd subtree (secrets already filtered by the jail)\n mem.setCwd(cwd);\n fs = mem;\n } else if (o.boddb) {\n // Database-backed workspace: the file tree lives in a persistent bod-db store under `o.boddb/`\n // (meta.db = the path tree, files/ = the bytes), surviving across runs. The real disk is never\n // written. DB-native by default; `--seed` hydrates the cwd subtree into the DB on the first run only.\n const root = resolve(o.boddb);\n mkdirSync(root, { recursive: true }); // parent for meta.db (storageRoot is auto-created by the VFS engine)\n const db = new BodDB({ path: join(root, 'meta.db'), sweepInterval: 0, vfs: { storageRoot: join(root, 'files') } });\n const bod = new BodDbFilesystem(db);\n const firstRun = (await bod.readDir('/').catch(() => [])).length === 0; // empty DB ⇒ never seeded\n await mkdirp(bod, cwd); // materialize the cwd path chain so paths sit at their real namespace\n if (o.seed && firstRun) await hydrate(jailedDisk, bod, cwd); // one-time seed (secrets filtered by the jail)\n bod.setCwd(cwd);\n fs = bod;\n }\n // --add-dir: mount extra real directories into the VFS at collision-free prefixes (disk mode only —\n // a sandbox copy can't contain writes to a real mounted dir). Each is jailed like the root.\n let mountNote = '';\n if (o.addDirs?.length && !virtual) {\n const used = new Set<string>();\n const mounts = [];\n const notes: string[] = [];\n for (const d of o.addDirs) {\n const abs = resolve(d);\n let name = basename(abs) || 'dir', prefix = `/${name}`, n = 2;\n while (used.has(prefix)) prefix = `/${name}-${n++}`;\n used.add(prefix);\n const md = new NodeDiskFilesystem(abs);\n await md.init();\n mounts.push({ prefix, fs: new JailedFilesystem(md) });\n notes.push(`${prefix} → ${abs}`);\n }\n fs = new MountFilesystem(fs, mounts);\n mountNote = `Additional directories are mounted into the filesystem (read/write):\\n${notes.join('\\n')}\\nReference files in them by their mount path (the left side).`;\n }\n // .agent dirs live under the launch dir; the FS path is cwd-anchored (root '/' = real machine\n // in disk mode; mirrored under cwd in sandbox mode). Both modes resolve to the same place.\n const dot = (sub: string) => (existsSync(`${cwd}/.agent/${sub}`) ? `${cwd}/.agent/${sub}` : undefined);\n // Search order lives in dotDirs() — shared with the REPL's catalog resolution (cli.ts adots()).\n const dots = (sub: string): string[] | undefined => {\n const dirs = dotDirs(cwd, sub, { existing: true });\n return dirs.length ? dirs : undefined;\n };\n // Memory: merged across scopes. Project dir is always first (write target, created on demand).\n // User-scope dirs are read-only fallbacks for global memories.\n const memoryDir = (() => {\n const home = homedir();\n const projectDir = `${cwd}/.agent/memory`;\n const readDirs = [\n existsSync(projectDir) ? projectDir : undefined,\n existsSync(`${cwd}/.claude/memory`) ? `${cwd}/.claude/memory` : undefined,\n existsSync(`${home}/.agent/memory`) ? `${home}/.agent/memory` : undefined,\n existsSync(`${home}/.claude/memory`) ? `${home}/.claude/memory` : undefined,\n ].filter(Boolean) as string[];\n return readDirs[0] === projectDir ? readDirs : [projectDir, ...readDirs];\n })();\n // User-scope dir for global memories (user/feedback types). First existing user-level dir wins.\n const memoryUserDir = (() => {\n const home = homedir();\n return [\n existsSync(`${home}/.agent/memory`) ? `${home}/.agent/memory` : undefined,\n existsSync(`${home}/.claude/memory`) ? `${home}/.claude/memory` : undefined,\n ].find(Boolean) ?? `${home}/.agent/memory`; // fallback: create on first write\n })();\n // opt-in: auto-capture recurring failures as persisted lessons (needs a memory dir to write to).\n const memoryWriteDir = memoryDir[0];\n const hooks = o.learnFromMistakes && memoryWriteDir ? composeHooks(o.hooks, lessonCapture({ fs, dir: memoryWriteDir, minRepeats: 2 })) : o.hooks;\n // Disk mode: real shell ON by default (CC parity — the agent should be able to run git, bun, etc).\n // Sandbox mode: real shell OFF (a real /bin/sh would escape the VFS). Explicit `realShell` overrides.\n let realShell: AgentTool[] = [];\n const useRealShell = o.realShell ?? !virtual;\n if (useRealShell && !virtual) {\n const jobs = new ShellJobRegistry({ cwd, killOnExit: true, osSandbox: o.osSandbox });\n realShell = [makeRealShellTool({ cwd, registry: jobs, osSandbox: o.osSandbox }), ...makeShellJobTools(jobs)];\n }\n // Scratch context-offload (on by default): an oversized tool result spills to a scratch file + a\n // recoverable paginated stub instead of a lossy crop; the caller peeks with Grep/Read or Ask. Lives\n // in the agent's own fs. Disk mode → OS tmpdir (per-process, OS-reclaimed, no project litter, still\n // reachable by Read/Grep since disk fs is rooted at '/'); virtual modes → in the in-mem/db fs (ephemeral).\n const scratchDir = o.scratch ? (o.scratchDir ?? (virtual ? `${cwd}/.agent/scratch` : `${tmpdir()}/agentx-scratch-${process.pid}`)) : undefined;\n const scratch = scratchDir ? new Scratch(fs, { dir: scratchDir }) : undefined;\n return new Agent({\n ai: o.ai,\n fs,\n model: o.model ?? 'anthropic/claude-sonnet-4-6',\n // PDF reads (disk mode only — VFS paths aren't real files): poppler's pdftotext when installed.\n ...(!virtual ? { pdfText: pdfTextViaPoppler } : {}),\n // Anchor cursor to the launch dir (its adapter defaults to TMPDIR otherwise) and forward the\n // host's MCP servers so the delegated cursor agent runs in the same environment. Gated to cursor:\n // openai/google adapters Object.assign providerOptions into the request body, so a blanket cwd\n // would corrupt those calls.\n // Warm cursor session (default on; CURSOR_WARM=0 to disable): one long-lived agent reused across\n // turns, amortising the ~2s Agent.create + h2 handshake. Keyed per agentx launch.\n ...(() => { const po = cursorProviderOptions(o.model, cwd, o.mcpServers); return po ? { providerOptions: po } : {}; })(),\n ...(() => {\n // Anchor the model to its working dir + tell it how the path space behaves (the fix for the\n // \"host path → silently empty\" trap: the model now knows whether '/' is the real machine).\n const now = new Date();\n const platformNames: Record<string, string> = { darwin: 'macOS', linux: 'Linux', win32: 'Windows' };\n const envNote = `Current date: ${now.toLocaleDateString('en-CA')} ${now.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })} (${Intl.DateTimeFormat().resolvedOptions().timeZone})\\nPlatform: ${platformNames[platform()] ?? platform()} ${arch()} (${release()})\\nUser: ${userInfo().username}\\nShell: ${process.env.SHELL ?? 'unknown'}`;\n const cwdNote = o.boddb\n ? `Working directory: ${cwd}\\nDATABASE WORKSPACE: your files live in a database (bod-db), not on the real disk — the real disk is never modified and nothing outside this tree exists. Use paths relative to the working directory, or absolute paths under it.`\n : o.sandbox\n ? `Working directory: ${cwd}\\nSANDBOX: you operate on an in-memory COPY of this directory — the real disk is never modified and nothing outside it exists. Use paths relative to the working directory, or absolute paths under it.`\n : `Working directory: ${cwd}\\nThe filesystem root '/' is the real machine root — you have full filesystem access, like a normal shell. Use paths relative to the working directory, or absolute paths. Secret files (.env, .ssh, keys, .git) are hidden for safety.`;\n const shellNote = useRealShell && !virtual\n ? 'The `Shell` tool runs /bin/sh — you can run any installed binary (git, bun, node, curl, etc). Use `Shell` for all shell commands.'\n : undefined;\n const toneNote = 'Be concise. Do not use emojis unless the user asks. Do not explain what you are about to do — just do it.';\n // Self-awareness: agentx is its own runtime, NOT Claude Code/Desktop. Its MCP servers come from\n // .agent config (project or ~/.agent) and their tools are already mounted as `mcp__<server>__*`.\n // Without this note the model answers \"what MCPs do you have?\" by shelling out to read CC's\n // ~/.claude.json / claude_desktop_config.json — confusing itself with a different agent.\n const mcpNote = (() => {\n const names = new Set<string>(Object.keys(o.mcpServers ?? {}));\n for (const t of o.extraTools ?? []) if (t.name.startsWith('mcp__')) names.add(t.name.slice(5).split('__')[0]);\n const list = [...names];\n return `You are agentx (an agent runtime) — NOT Claude Code or Claude Desktop, which are separate agents with their own config. Your MCP servers are configured in .agent/settings.json or .agent/config.* (this project's .agent/ or ~/.agent/), and their tools are already in your tool list as \\`mcp__<server>__<tool>\\`.${list.length ? ` Configured MCP servers: ${list.join(', ')}.` : ' No MCP servers are currently configured.'} When asked which MCPs/tools you have, answer from your own tool list — never read Claude Code/Desktop config (e.g. ~/.claude.json, claude_desktop_config.json) to answer; those belong to a different agent.`;\n })();\n const extra = [o.appendSystemPrompt, envNote, cwdNote, shellNote, toneNote, mountNote, mcpNote].filter(Boolean).join('\\n\\n');\n // Override the base prompt's wording when running on the real disk with a real shell.\n const basePrompt = (() => {\n let p = new AgentOptions().systemPrompt;\n if (!virtual) p = p.replace('operating on a virtual filesystem', 'operating on the host filesystem');\n if (useRealShell && !virtual) p = p.replace('Use the `bash` tool to explore (ls, grep, find, cat)', 'Use the `Shell` tool to run commands (ls, grep, find, git, etc)');\n return p;\n })();\n return { systemPrompt: basePrompt + '\\n\\n' + extra };\n })(),\n tools: (() => {\n const base = toolsByName([...(o.tools ?? DEFAULT_TOOLS), ...autoWebTools()]);\n const tail: AgentTool[] = [...(o.extraTools ?? [])];\n // Scratch adds the Ask peek tool; the oversized-result spill is wired via Agent.capToolResult\n // below (one chokepoint covering EVERY tool — Grep/Read/MCP/web — not per-tool wrapping).\n if (scratch) tail.push(makeAskTool({ fs, ai: o.ai, model: o.scratchAskModel ?? o.model ?? 'anthropic/claude-sonnet-4-6', dir: scratchDir }));\n tail.push(makeNotifyTool()); // OS desktop notifications (CC PushNotification parity); degrades gracefully off macOS/Linux\n if (!realShell.length) return [...base, ...tail];\n // Real shell replaces VFS bash (having both is confusing — the model would use the wrong one).\n // The real Shell tool covers everything VFS bash does and more; structured tools (Grep/Glob/Read)\n // still operate via the VFS for consistency.\n const filtered = base.filter((t) => t.name !== 'bash');\n return [...filtered, ...realShell, ...tail];\n })(),\n maxSteps: o.maxSteps ?? 30,\n ...(o.reasoning != null ? { reasoning: o.reasoning } : {}),\n stream: o.stream ?? false,\n host: o.host,\n hooks,\n planMode: o.planMode ?? false,\n permissions: o.permissions,\n subagents: o.subagents ?? false,\n // When scratch is on, an oversized tool result spills to a scratch file + recoverable paginated stub\n // (lossless). Without scratch, the Agent's default crop (lossy) still guards the context window.\n ...(scratch ? { capToolResult: (full: string, info: { tool: string; args: any }) => scratch.spill(full, info) } : {}),\n backgroundJobs: o.backgroundJobs ?? virtual, // default ON in virtual modes (no real shell there); disk uses ShellJobRegistry\n skillsDir: dots('skills'),\n commandsDir: dots('commands'),\n memoryDir,\n memoryUserDir,\n agentsDir: dot('agents'),\n instructionFiles: o.instructionFiles ?? ['AGENTS.md', 'CLAUDE.md'],\n // Only override the Agent's safety defaults when explicitly configured.\n ...(o.maxTokens != null ? { maxTokens: o.maxTokens } : {}),\n ...(o.timeoutMs != null ? { timeoutMs: o.timeoutMs } : {}),\n ...(o.maxRepeats != null ? { maxRepeats: o.maxRepeats } : {}),\n ...(o.maxToolCalls != null ? { maxToolCalls: o.maxToolCalls } : {}),\n // Context-v2: by default, note-take over a long session (stub tool outputs older than the last 8).\n keepToolOutputs: o.keepToolOutputs ?? 8,\n ...(o.maxContextTokens != null ? { maxContextTokens: o.maxContextTokens } : {}),\n });\n}\n\n/** Build + run a single task (fresh transcript; the cwd filesystem persists across calls). */\nexport async function runOnce(o: CliOptions, task: string): Promise<RunResult> {\n const agent = await buildAgent(o);\n return agent.run(task);\n}\n\n/** One-line human summary of a tool call for the terminal (path / command / pattern). */\nexport function summarizeCall(name: string, args: any): string {\n if (!args) return '';\n if (args.path) {\n // Edit: just the path — the colorized diff that follows tells the story (a 20-char «old»→«new»\n // truncates both sides to the same prefix and conveys nothing)\n if (Array.isArray(args.edits)) return `${args.path} (${args.edits.length} edits)`;\n return String(args.path);\n }\n if (args.command) return String(args.command);\n // regex slashes only where the pattern IS a regex (Grep); Glob patterns are literal\n if (args.pattern) return name === 'Glob' ? String(args.pattern) : `/${args.pattern}/${args.glob ? ' in ' + args.glob : ''}`;\n if (args.prompt) return trunc(String(args.description ?? args.prompt), 50);\n if (args.brief) return trunc(String(args.label ? `${args.label}: ${args.brief}` : args.brief), 70); // duplex Act/Think\n return trunc(JSON.stringify(args), 60);\n}\nconst trunc = (s: string, n: number) => (s == null ? '' : String(s).length > n ? String(s).slice(0, n) + '…' : String(s)).replace(/\\n/g, '⏎');\n","import { execFile } from 'node:child_process';\nimport type { AgentTool } from './tools';\nimport { forComponent } from './logging';\n\nconst log = forComponent('notify');\n\n/**\n * PushNotification — node-only, OPT-IN OS desktop notification (CC parity: alert the user\n * out-of-band when a long task finishes or needs attention). Kept out of `defaultTools()` and\n * the edge-safe index (same policy as tools.shell.ts); the CLI mounts it explicitly.\n *\n * macOS: osascript `display notification` (no extra deps; terminal-notifier not required).\n * Linux: notify-send (libnotify). Other platforms / missing tools → tool reports unavailability\n * to the model instead of throwing (the task itself should not fail because a toast couldn't show).\n */\nexport function makeNotifyTool(opts: { platform?: NodeJS.Platform; exec?: typeof execFile } = {}): AgentTool {\n const platform = opts.platform ?? process.platform;\n const run = opts.exec ?? execFile;\n return {\n name: 'PushNotification',\n description:\n 'Show an OS desktop notification to the user (out-of-band alert — e.g. a long task finished, input is needed). ' +\n 'Use sparingly: only for events the user would want to be interrupted for.',\n parameters: {\n type: 'object',\n required: ['message'],\n properties: {\n message: { type: 'string', description: 'notification body' },\n title: { type: 'string', description: 'notification title (default \"agentx\")' },\n },\n },\n async run({ message, title }) {\n const msg = String(message ?? '').slice(0, 256);\n const head = String(title ?? 'agentx').slice(0, 64);\n if (!msg) return 'Error: empty message';\n const argv: [string, string[]] | null =\n platform === 'darwin'\n ? ['osascript', ['-e', `display notification ${JSON.stringify(msg)} with title ${JSON.stringify(head)}`]]\n : platform === 'linux'\n ? ['notify-send', [head, msg]]\n : null;\n if (!argv) return `Notifications unavailable on ${platform}.`;\n return new Promise<string>((resolve) => {\n run(argv[0], argv[1], { timeout: 5000 }, (e) => {\n if (e) { log.debug('notification failed', e); resolve(`Notification failed: ${e.message}`); }\n else resolve('Notification shown.');\n });\n });\n },\n };\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { forComponent } from '../src/logging';\n\nconst log = forComponent('cli-util');\n\n/**\n * Shared CLI helpers — dot-dir resolution, text truncation, safe JSON. One home for the\n * patterns that were previously re-implemented per call site (core.ts dots() vs cli.ts adots(),\n * ad-hoc slice(0,N) labels, bare try/JSON.parse).\n */\n\n/** The `.agent`/`.claude` config-dir search order for `sub` (first wins on name collision):\n * project .agent → project .claude → user ~/.agent → user ~/.claude. Home-level dirs are what\n * surface a GLOBAL skill/command everywhere. `existing` filters to dirs present on the real disk\n * (use only when `base` is a real path — VFS callers pass the unfiltered list). */\nexport function dotDirs(base: string, sub: string, opts: { existing?: boolean; home?: string } = {}): string[] {\n const home = opts.home ?? homedir();\n const dirs = [`${base}/.agent/${sub}`, `${base}/.claude/${sub}`, `${home}/.agent/${sub}`, `${home}/.claude/${sub}`];\n return opts.existing ? dirs.filter((d) => existsSync(d)) : dirs;\n}\n\n/** Cap `s` at `n` chars with a suffix marker. Null-safe. */\nexport function truncate(s: string | null | undefined, n: number, suffix = '…'): string {\n const t = s ?? '';\n return t.length > n ? t.slice(0, n) + suffix : t;\n}\n\n/** One-line label: collapse whitespace/newlines, trim, cap at `max` (checkpoint labels, commit subjects). */\nexport function sanitizeLabel(s: string, max = 60): string {\n return truncate(s.replace(/\\s+/g, ' ').trim(), max, '');\n}\n\n/** JSON.parse that returns `fallback` instead of throwing — and LOGS the failure (never silently\n * swallow: a corrupt settings/session file should leave a trace). */\nexport function parseJson<T = any>(text: string, fallback: T, what = 'json'): T {\n try { return JSON.parse(text); } catch (e) {\n log.debug(`parseJson(${what}) failed: ${(e as Error).message}`);\n return fallback;\n }\n}\n\n/** Read + parse a JSON file from the real disk; `fallback` when absent or malformed (logged). */\nexport function readJsonFile<T = any>(path: string, fallback: T): T {\n if (!existsSync(path)) return fallback;\n let text: string;\n try { text = readFileSync(path, 'utf8'); } catch (e) {\n log.debug(`readJsonFile(${path}) unreadable: ${(e as Error).message}`);\n return fallback;\n }\n return parseJson(text, fallback, path);\n}\n","/**\n * Node/macOS voice I/O backends + VoiceIO composition for the CLI.\n *\n * The portable brain (state machine, barge-in, merge window, echo policy) and the WS protocol\n * clients live in src/voice/ — reusable on web (getUserMedia source + AudioContext sink + BE-minted\n * temp tokens). This file owns only what is platform-bound:\n * - mic capture: cli/native/mic-aec.swift (Apple VPIO echo cancellation, compile-on-first-use)\n * with raw-ffmpeg fallback (heuristic echo tier; MIC_AEC=0 forces it)\n * - playback: per-turn ffplay fed raw PCM (persistent players drop post-gap audio)\n *\n * Design + measured numbers: mind/11-voice.md.\n */\nimport { spawn, spawnSync, type ChildProcess } from 'node:child_process';\nimport { existsSync, mkdirSync, statSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { forComponent } from '../src/logging';\nimport { VoiceEngine, VoiceEngineOptions } from '../src/voice/engine';\nimport { CartesiaTTS } from '../src/voice/cartesia';\nimport { SonioxSTT } from '../src/voice/soniox';\nimport { type AudioSink, type AudioSource, STT_SAMPLE_RATE, TTS_SAMPLE_RATE } from '../src/voice/types';\n\nexport { CartesiaTTS, SonioxSTT, VoiceEngine };\n\nconst log = forComponent('VoiceIO');\nconst now = () => performance.now();\n\n// ---------- Player: fresh ffplay per turn (a persistent one drops \"late\" audio after stream\n// gaps — its realtime clock keeps advancing through underruns). kill() = barge-in primitive. ----------\nexport class Player implements AudioSink {\n private proc: ChildProcess | null = null;\n private bytesWritten = 0;\n private startedAt = 0;\n\n /** start a new spoken turn: kill any previous player, spawn a fresh one */\n markTurn(): void {\n this.kill();\n this.proc = spawn(\n 'ffplay',\n ['-loglevel', 'quiet', '-nodisp', '-fflags', 'nobuffer', '-flags', 'low_delay', '-probesize', '32', '-f', 's16le', '-ar', String(TTS_SAMPLE_RATE), '-ch_layout', 'mono', '-i', '-'],\n { stdio: ['pipe', 'ignore', 'ignore'] },\n );\n this.proc.on('error', (e) => log.warn(`ffplay error: ${e.message}`));\n this.proc.stdin!.on('error', () => {}); // EPIPE on kill is fine\n this.bytesWritten = 0;\n this.startedAt = 0;\n }\n write(chunk: Uint8Array): void {\n if (!this.proc) this.markTurn();\n if (!this.startedAt) this.startedAt = now();\n this.bytesWritten += chunk.length;\n this.proc!.stdin!.write(chunk);\n }\n /** ms of audio actually played so far this turn */\n playedMs(): number {\n return this.startedAt ? now() - this.startedAt : 0;\n }\n /** estimated ms until queued audio finishes playing */\n drainMs(): number {\n if (!this.startedAt) return 0;\n const queuedMs = (this.bytesWritten / (TTS_SAMPLE_RATE * 2)) * 1000;\n return Math.max(0, queuedMs - (now() - this.startedAt));\n }\n kill(): void {\n this.proc?.kill('SIGKILL');\n this.proc = null;\n }\n}\n\n// ---------- mic capture: AEC helper (compile-on-first-use) → ffmpeg fallback ----------\nconst nativeDir = () => join(dirname(fileURLToPath(import.meta.url)), 'native');\n\n/** avfoundation device \":0\" is often a virtual loopback (BlackHole etc.) — pick a real mic by name */\nfunction detectFfmpegMic(): string {\n if (process.env.MIC_DEVICE) return process.env.MIC_DEVICE;\n const out = spawnSync('ffmpeg', ['-f', 'avfoundation', '-list_devices', 'true', '-i', ''], { encoding: 'utf8' }).stderr as string;\n const audio = out.slice(out.indexOf('audio devices'));\n const devices = [...audio.matchAll(/\\[(\\d+)\\] (.+)/g)].map(([, idx, name]) => ({ idx, name: name.trim() }));\n const mic = devices.find((d) => /microphone|built-in/i.test(d.name) && !/teams|blackhole|loopback/i.test(d.name)) ?? devices[0];\n if (!mic) throw new Error('no audio input device found');\n log.debug(`ffmpeg mic: [${mic.idx}] ${mic.name}`);\n return `:${mic.idx}`;\n}\n\n/** Short name of the macOS default input device (what the AEC path actually captures) + a virtual/loopback\n * flag — so voice startup can surface \"in: BlackHole 2ch ⚠\" when the default isn't a real mic (silent STT). */\nexport function detectedInputDevice(): { name: string; virtual: boolean } | null {\n if (process.platform !== 'darwin') return null;\n let name = '';\n if (spawnSync('which', ['SwitchAudioSource']).status === 0) {\n name = (spawnSync('SwitchAudioSource', ['-c', '-t', 'input'], { encoding: 'utf8' }).stdout || '').trim();\n } else {\n const out = spawnSync('system_profiler', ['SPAudioDataType'], { encoding: 'utf8' }).stdout || '';\n // walk lines, tracking the last device-header (\" Name:\" — colon, no value), and return the\n // header that owns the \"Default Input Device: Yes\" property line (a single regex picks the wrong block).\n let last = '';\n for (const ln of out.split('\\n')) {\n const hdr = ln.match(/^\\s{6,}(\\S.*?):\\s*$/);\n if (hdr) { last = hdr[1].trim(); continue; }\n if (/Default Input Device:\\s*Yes/.test(ln)) { name = last; break; }\n }\n }\n if (!name) return null;\n return { name, virtual: /blackhole|loopback|aggregate|virtual|soundflower|multi-output|teams|zoom/i.test(name) };\n}\n\n/** Resolve (building if needed) the AEC capture binary; null → caller falls back to ffmpeg. */\nexport function resolveAecBinary(): string | null {\n if (process.env.MIC_AEC === '0' || process.platform !== 'darwin') return null;\n const src = join(nativeDir(), 'mic-aec.swift');\n const plist = join(nativeDir(), 'Info.plist');\n if (!existsSync(src)) return null;\n const cacheDir = join(homedir(), '.agent', 'cache');\n const bin = join(cacheDir, 'mic-aec');\n // rebuild when the source is newer than the cached binary\n if (existsSync(bin) && statSync(bin).mtimeMs >= statSync(src).mtimeMs) return bin;\n if (spawnSync('which', ['swiftc']).status !== 0) return null;\n mkdirSync(cacheDir, { recursive: true });\n log.info('compiling AEC mic helper (first run)…');\n const build = spawnSync('swiftc', ['-O', '-o', bin, src, '-Xlinker', '-sectcreate', '-Xlinker', '__TEXT', '-Xlinker', '__info_plist', '-Xlinker', plist], { encoding: 'utf8' });\n if (build.status !== 0) { log.warn(`AEC build failed: ${build.stderr?.slice(0, 400)}`); return null; }\n const sign = spawnSync('codesign', ['-fs', '-', bin], { encoding: 'utf8' });\n if (sign.status !== 0) { log.warn(`codesign failed: ${sign.stderr?.slice(0, 200)}`); return null; }\n return bin;\n}\n\n/** Node AudioSource: AEC helper when available, else raw ffmpeg (heuristic echo tier). */\nexport class NodeMicSource implements AudioSource {\n public readonly aec: boolean;\n private bin: string | null;\n private proc: ChildProcess | null = null;\n private stopped = false;\n\n constructor() {\n this.bin = resolveAecBinary();\n this.aec = !!this.bin;\n }\n start(onChunk: (pcm: Uint8Array) => void): void {\n if (this.bin) {\n this.proc = spawn(this.bin, [], { stdio: ['ignore', 'pipe', 'ignore'] });\n } else {\n if (spawnSync('which', ['ffmpeg']).status !== 0) throw new Error('voice I/O unavailable: no AEC helper and no ffmpeg on PATH');\n log.info('mic: raw capture (no AEC) — echo handled heuristically; headphones recommended');\n this.proc = spawn(\n 'ffmpeg',\n ['-loglevel', 'error', '-f', 'avfoundation', '-i', detectFfmpegMic(), '-ar', String(STT_SAMPLE_RATE), '-ac', '1', '-f', 's16le', '-'],\n { stdio: ['ignore', 'pipe', 'pipe'] },\n );\n this.proc.stderr!.on('data', (d: Buffer) => log.warn(`ffmpeg: ${String(d).trim()}`));\n }\n this.proc.on('exit', (c) => { if (c && !this.stopped) log.error(`mic capture exited (${c}) — check mic permission / MIC_DEVICE / MIC_AEC=0`); });\n this.proc.stdout!.on('data', (chunk: Buffer) => onChunk(chunk));\n }\n stop(): void {\n this.stopped = true;\n const p = this.proc;\n this.proc = null;\n if (!p) return;\n p.kill('SIGTERM'); // graceful: mic-aec stops its audio engine (SIGKILL wedges VPIO in coreaudiod)\n setTimeout(() => { try { p.kill('SIGKILL'); } catch { /* already gone */ } }, 500).unref?.();\n }\n}\n\n// ---------- AecDuplexAudio: ONE helper process = mic source + TTS sink ----------\n// The root echo fix (mind/11-voice.md): TTS rendered through the SAME AVAudioEngine as capture\n// gives VPIO a sample-accurate reference for exactly what we emit — near-deterministic\n// cancellation vs. the per-run spectrum of cancelling a separate ffplay via system loopback.\n// Playback protocol: [u32le len][s16le 44.1k mono PCM] frames on stdin; len==0 = FLUSH (in-band,\n// so stale frames already in the pipe are consumed-and-dropped — no post-barge audio race).\nexport class AecDuplexAudio implements AudioSource, AudioSink {\n public readonly aec = true;\n private proc: ChildProcess | null = null;\n private stopped = false;\n private bytesWritten = 0;\n private startedAt = 0;\n\n constructor(private bin: string) {}\n\n // --- AudioSource ---\n start(onChunk: (pcm: Uint8Array) => void): void {\n this.proc = spawn(this.bin, [], { stdio: ['pipe', 'pipe', 'pipe'] });\n this.proc.stdin!.on('error', () => {}); // EPIPE on teardown is fine\n this.proc.on('exit', (c) => { if (c && !this.stopped) log.error(`aec duplex audio exited (${c}) — check mic permission / MIC_AEC=0`); });\n this.proc.stdout!.on('data', (chunk: Buffer) => onChunk(chunk));\n this.proc.stderr!.on('data', (d: Buffer) => { for (const ln of String(d).split('\\n')) if (ln.trim()) log.debug(`mic-aec: ${ln.trim()}`); });\n }\n stop(): void {\n this.stopped = true;\n const p = this.proc;\n this.proc = null;\n if (!p) return;\n p.kill('SIGTERM'); // graceful: stop the audio engine first (SIGKILL wedges VPIO in coreaudiod)\n setTimeout(() => { try { p.kill('SIGKILL'); } catch { /* already gone */ } }, 500).unref?.();\n }\n\n // --- AudioSink (frame writer; same played/drain byte-math as the ffplay Player) ---\n private frame(payload: Uint8Array | null): void {\n const stdin = this.proc?.stdin;\n if (!stdin || stdin.destroyed) return;\n const hdr = Buffer.alloc(4);\n hdr.writeUInt32LE(payload ? payload.length : 0);\n stdin.write(hdr);\n if (payload?.length) stdin.write(payload);\n }\n markTurn(): void {\n this.frame(null); // FLUSH any previous turn's tail (also clears a held pause helper-side)\n this.bytesWritten = 0;\n this.startedAt = 0;\n this.pausedSince = 0;\n this.pausedAccum = 0;\n }\n write(chunk: Uint8Array): void {\n if (!this.startedAt) this.startedAt = now();\n this.bytesWritten += chunk.length;\n this.frame(chunk);\n }\n playedMs(): number {\n return this.startedAt ? now() - this.startedAt - this.pausedMs() : 0;\n }\n drainMs(): number {\n if (!this.startedAt) return 0;\n const queuedMs = (this.bytesWritten / (TTS_SAMPLE_RATE * 2)) * 1000;\n return Math.max(0, queuedMs - (now() - this.startedAt - this.pausedMs()));\n }\n /** barge-in: silence NOW (in-band flush) — the capture side keeps running */\n kill(): void {\n this.frame(null);\n this.bytesWritten = 0;\n this.startedAt = 0;\n this.pausedSince = 0;\n this.pausedAccum = 0;\n }\n /** overlap trail-off: exact-sample PAUSE (len==0xFFFFFFFF) / RESUME (len==0xFFFFFFFE) frames */\n private pausedSince = 0;\n private pausedAccum = 0;\n private ctl(code: number): void {\n const stdin = this.proc?.stdin;\n if (!stdin || stdin.destroyed) return;\n const f = Buffer.alloc(4);\n f.writeUInt32LE(code, 0);\n stdin.write(f);\n }\n pause(): void {\n if (this.pausedSince) return;\n this.pausedSince = now();\n this.ctl(0xffffffff);\n }\n resume(): void {\n if (!this.pausedSince) return;\n this.pausedAccum += now() - this.pausedSince;\n this.pausedSince = 0;\n this.ctl(0xfffffffe);\n }\n /** total paused time this turn — excluded from played/drain math (the tape held still) */\n private pausedMs(): number {\n return this.pausedAccum + (this.pausedSince ? now() - this.pausedSince : 0);\n }\n /** TEST HARNESS: queue simulated user speech (s16le 16k mono) — the helper mixes it into the real\n * mic stream pre-gate, so the full live pipeline runs while a script plays the human. */\n inject(pcm16k: Uint8Array): void {\n const stdin = this.proc?.stdin;\n if (!stdin || stdin.destroyed) return;\n const hdr = Buffer.alloc(8);\n hdr.writeUInt32LE(0xfffffffd, 0);\n hdr.writeUInt32LE(pcm16k.length, 4);\n stdin.write(hdr);\n stdin.write(pcm16k);\n }\n}\n\n/** Spoken voice-control command, matched on the whole normalized utterance (\"Voice off.\" → \"voice off\").\n * Deterministic and pre-reflex: zero inference cost, works even if the model misbehaves. Standalone\n * phrases only — \"turn the voice off later\" must NOT match. Tolerates spoken politeness (\"okay…\",\n * \"…please\") and the merge window gluing a repeated command (\"voice off voice off\"). */\nexport const matchVoiceCommand = (text: string): 'off' | null => {\n const t = text.toLowerCase().replace(/[^a-z ]/g, ' ').replace(/\\s+/g, ' ').trim()\n .replace(/^(?:hey|ok|okay|please) /, '').replace(/ (?:please|now)$/, '');\n return /^(voice off|mute|stop listening)( \\1)*$/.test(t) ? 'off' : null;\n};\n\n// ---------- VoiceIO: the engine + Node defaults (env keys, AEC duplex audio, ffplay fallback) ----------\nexport class VoiceIOOptions extends VoiceEngineOptions {\n sonioxApiKey = process.env.SONIOX_API_KEY ?? '';\n cartesiaApiKey = process.env.CARTESIA_API_KEY ?? '';\n cartesiaVoiceId = process.env.CARTESIA_VOICE_ID ?? '';\n}\n\nexport class VoiceIO extends VoiceEngine {\n constructor(options?: Partial<VoiceIOOptions>) {\n const o = { ...new VoiceIOOptions(), ...options };\n // One duplex helper = mic + playback (root echo fix); without it: ffmpeg mic + ffplay sink.\n const bin = (!o.stt || !o.player) ? resolveAecBinary() : null;\n const duplex = bin ? new AecDuplexAudio(bin) : null;\n super({\n ...o,\n stt: o.stt ?? new SonioxSTT({ auth: o.sonioxApiKey, source: duplex ?? new NodeMicSource() }),\n tts: o.tts ?? new CartesiaTTS({ auth: o.cartesiaApiKey, voiceId: o.cartesiaVoiceId }),\n player: o.player ?? duplex ?? new Player(),\n bargeRmsMult: Number(process.env.BARGE_RMS_MULT || o.bargeRmsMult),\n bargeRmsFloor: Number(process.env.BARGE_RMS_FLOOR || o.bargeRmsFloor),\n });\n }\n\n /** ready = keys present (AEC vs heuristic is decided at start()) */\n static available(env = process.env): boolean {\n return !!(env.SONIOX_API_KEY && env.CARTESIA_API_KEY && env.CARTESIA_VOICE_ID);\n }\n}\n","import { homedir } from 'node:os';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type { HooksConfig } from './hooks-config';\nimport type { McpServerConfig } from '../src/mcp.client';\n\n/**\n * File-based agent config. Resolved with precedence:\n * CLI flags > ./.agent/config.* (project) > ~/.agent/config.* (user) > built-in defaults.\n * Authored as a TS/JS module (`export default {…}`) or plain JSON. Malformed files are\n * warned about and ignored — config never crashes a run.\n */\nexport interface AgentConfig {\n model?: string;\n /** Duplex reflex (fast voice) model — used by --duplex/--voice; --voice-model flag wins. */\n reflexModel?: string;\n /** Duplex think (premium reasoning) model. Set to `false` to disable the Think tier. */\n thinkModel?: string | false;\n /** Duplex worker UI chrome: 'full' = per-step ⚙ tool activity, 'minimal' = task events only.\n * Default 'full' (text duplex) / 'minimal' (--voice); /workers toggles it live. */\n workerChrome?: 'full' | 'minimal';\n /** --voice permission asks: 'menu' (default — interactive Allow once/always/Deny picker, like a\n * non-voice session) | 'relay' (spoken through the conversation, answer by voice or typing). */\n voiceAskUi?: 'relay' | 'menu';\n maxSteps?: number;\n /** Reasoning/thinking effort: 'off'|'low'|'medium'|'high' or a raw token budget (anthropic/openai). */\n reasoning?: import('../src/index').ReasoningEffort;\n /** Initial permission posture (Shift+Tab cycles it live): default (ask) | acceptEdits | plan. */\n permissionMode?: 'default' | 'acceptEdits' | 'plan';\n /** Line-editor keymap: 'normal' (emacs/readline, default) | 'vim' (modal). */\n editorMode?: 'normal' | 'vim';\n tools?: string[];\n stream?: boolean;\n subagents?: boolean;\n planMode?: boolean;\n // --- providers (merged with env keys; env wins) ---\n /** Per-provider API keys, e.g. `{ openai: 'sk-…', anthropic: 'sk-ant-…' }`. */\n apiKeys?: Record<string, string>;\n /** Per-provider custom base URLs (proxies / self-hosted gateways). */\n baseUrls?: Record<string, string>;\n /** Declarative shell hooks (preToolUse/postToolUse/onStop) — gate or audit tool calls. */\n hooks?: HooksConfig;\n /** Persisted permission rules (CC-style). Each entry is `Tool` or `Tool(pathGlob)`, e.g.\n * `Edit(src/**)`, `Read(./.env)`, `Shell`. `deny` wins over `allow` wins over `ask`; unmatched\n * tools fall through to the run's default posture (ask when interactive, allow when unattended). */\n permissions?: { allow?: string[]; ask?: string[]; deny?: string[] };\n /** MCP servers to auto-mount (Claude-style): `{ name: { command, args } | { url } }`. */\n mcpServers?: Record<string, McpServerConfig>;\n // --- kill-switches (raise/lower the always-on safety ceilings) ---\n maxTokens?: number;\n timeoutMs?: number;\n maxRepeats?: number;\n maxToolCalls?: number;\n // --- context shaping (hot/cold) ---\n /** Keep the most-recent N tool-result outputs verbatim; stub older ones (default 8). 0 = keep all. */\n keepToolOutputs?: number;\n /** Token-aware per-turn context ceiling (~4 chars/token). 0/undefined = off. */\n maxContextTokens?: number;\n /** Auto-capture recurring tool failures as memory lessons (needs .agent/memory). Default off — writes files. */\n learnFromMistakes?: boolean;\n /** On a failed/wasteful headless run (loop/budget/max_steps), reflect once via the model and persist a novel lesson. Default off — costs one model call. */\n reflectOnFailure?: boolean;\n /** Server-side proxy budget caps (USD). Consumed by web/server.ts. */\n budget?: { perSession?: number; global?: number; windowMs?: number };\n}\n\nconst FILES = ['config.ts', 'config.js', 'config.mjs', 'config.json'];\n\n/** Load the first matching `.agent/config.*` under `dir` (returns {} if none/unreadable). */\nasync function loadFrom(dir: string): Promise<Partial<AgentConfig>> {\n for (const f of FILES) {\n const p = join(dir, '.agent', f);\n if (!existsSync(p)) continue;\n try {\n const mod = await import(pathToFileURL(p).href, f.endsWith('.json') ? { with: { type: 'json' } } : undefined);\n return (mod.default ?? mod.config ?? mod) as AgentConfig;\n } catch (e: any) {\n console.error(`agentx: ignoring ${p} — ${e?.message ?? e}`);\n }\n return {};\n }\n return {};\n}\n\n/**\n * Load `.agent/settings.json` (CC-compatible format). Maps CC fields to AgentConfig:\n * mcpServers, permissions, env (→ apiKeys where recognized).\n * Returns {} if missing/unreadable.\n */\nfunction loadSettings(dir: string): Partial<AgentConfig> {\n const p = join(dir, '.agent', 'settings.json');\n if (!existsSync(p)) return {};\n try {\n const raw = JSON.parse(readFileSync(p, 'utf8'));\n const cfg: Partial<AgentConfig> = {};\n if (raw.mcpServers && typeof raw.mcpServers === 'object') cfg.mcpServers = raw.mcpServers;\n if (raw.permissions && typeof raw.permissions === 'object') cfg.permissions = raw.permissions;\n if (raw.model && typeof raw.model === 'string') cfg.model = raw.model;\n if (raw.reasoning != null) cfg.reasoning = raw.reasoning;\n if (raw.permissionMode === 'default' || raw.permissionMode === 'acceptEdits' || raw.permissionMode === 'plan') cfg.permissionMode = raw.permissionMode;\n if (raw.editorMode === 'normal' || raw.editorMode === 'vim') cfg.editorMode = raw.editorMode;\n if (typeof raw.stream === 'boolean') cfg.stream = raw.stream;\n if (raw.env && typeof raw.env === 'object') {\n for (const [k, v] of Object.entries(raw.env)) {\n if (typeof v === 'string' && !process.env[k]) process.env[k] = v;\n }\n }\n return cfg;\n } catch (e: any) {\n console.error(`agent: ignoring ${p} — ${e?.message ?? e}`);\n return {};\n }\n}\n\n/**\n * Merge config layers (later wins):\n * ~/.agent/settings.json → ~/.agent/config.* → ./.agent/settings.json → ./.agent/config.*\n */\nexport async function loadConfig(cwd: string): Promise<Partial<AgentConfig>> {\n const userSettings = loadSettings(homedir());\n const user = await loadFrom(homedir());\n const projectSettings = loadSettings(cwd);\n const project = await loadFrom(cwd);\n const merged = { ...userSettings, ...user, ...projectSettings, ...project };\n // deep-merge mcpServers (all layers contribute servers, not just the last one with the key)\n if (userSettings.mcpServers || user.mcpServers || projectSettings.mcpServers || project.mcpServers) {\n merged.mcpServers = { ...userSettings.mcpServers, ...user.mcpServers, ...projectSettings.mcpServers, ...project.mcpServers };\n }\n return merged;\n}\n","import { spawnSync } from 'node:child_process';\nimport { forComponent, type Hooks } from '../src/index';\n\n/**\n * Config-driven shell hooks for the CLI. Turns a declarative `hooks` block in\n * `.agent/config.*` into the runtime's `Hooks` seam — so a user can gate or audit\n * tool calls without embedding TypeScript (the Claude-Code `settings.json` model).\n * Node-only by design (runs shell commands): the pure hook engine stays in `src/`.\n *\n * Each matched rule runs `command` via the shell with the event payload in env:\n * AGENTLIBX_EVENT, AGENTLIBX_TOOL, AGENTLIBX_ARGS (JSON), AGENTLIBX_RESULT, AGENTLIBX_TEXT.\n * For preToolUse with `block: true`, a non-zero exit BLOCKS the call (stdout/stderr → reason).\n */\nconst log = forComponent('hooks');\n\nexport interface HookRule {\n /** Match the tool name. `*` wildcards (e.g. \"Web*\"); omit / \"*\" matches any tool. */\n tool?: string;\n /** Shell command to run. */\n command: string;\n /** preToolUse only: block the tool call if the command exits non-zero. */\n block?: boolean;\n /** Per-command timeout (ms, default 10000). */\n timeoutMs?: number;\n}\nexport interface HooksConfig {\n preToolUse?: HookRule[];\n postToolUse?: HookRule[];\n onStop?: HookRule[];\n}\n\nconst escapeRegex = (s: string) => s.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/** Does a rule apply to a tool name? Supports `*` wildcards; missing/\"*\" tool matches all. */\nexport function ruleMatches(rule: HookRule, toolName: string): boolean {\n if (!rule.tool || rule.tool === '*') return true;\n const re = new RegExp('^' + rule.tool.split('*').map(escapeRegex).join('.*') + '$');\n return re.test(toolName);\n}\n\nfunction runCmd(rule: HookRule, env: Record<string, string>): { code: number; out: string } {\n try {\n const r = spawnSync(rule.command, {\n shell: true,\n encoding: 'utf8',\n timeout: rule.timeoutMs ?? 10_000,\n env: { ...process.env, ...env },\n });\n return { code: r.status ?? 1, out: ((r.stdout ?? '') + (r.stderr ?? '')).trim() };\n } catch (e) {\n log.debug(`hook command failed: ${rule.command}`, e);\n return { code: 1, out: String((e as any)?.message ?? e) };\n }\n}\n\nconst CAP = 8192; // bound payload env vars\n\n/** Build a runtime `Hooks` object from a declarative config block. */\nexport function hooksFromConfig(cfg: HooksConfig): Hooks {\n return {\n async preToolUse(call) {\n for (const rule of cfg.preToolUse ?? []) {\n if (!ruleMatches(rule, call.name)) continue;\n const { code, out } = runCmd(rule, {\n AGENTLIBX_EVENT: 'preToolUse',\n AGENTLIBX_TOOL: call.name,\n AGENTLIBX_ARGS: JSON.stringify(call.args ?? {}).slice(0, CAP),\n });\n if (rule.block && code !== 0) return { block: true, reason: out || `blocked by hook (exit ${code})` };\n }\n },\n async postToolUse(call, result) {\n for (const rule of cfg.postToolUse ?? []) {\n if (!ruleMatches(rule, call.name)) continue;\n runCmd(rule, {\n AGENTLIBX_EVENT: 'postToolUse',\n AGENTLIBX_TOOL: call.name,\n AGENTLIBX_ARGS: JSON.stringify(call.args ?? {}).slice(0, CAP),\n AGENTLIBX_RESULT: String(result).slice(0, CAP),\n });\n }\n },\n onStop(text) {\n for (const rule of cfg.onStop ?? []) {\n runCmd(rule, { AGENTLIBX_EVENT: 'onStop', AGENTLIBX_TEXT: String(text ?? '').slice(0, CAP) });\n }\n },\n };\n}\n","/**\n * Minimal, dependency-free unified line-diff for the CLI — renders Edit/Write/MultiEdit\n * changes as +/- lines with limited context. Colorizers are injected so all TTY-gating\n * stays in cli.ts. Pure functions: equally usable in tests or a browser build.\n */\nexport interface DiffStyle {\n add?: (s: string) => string; // colorizer for added (+) lines\n del?: (s: string) => string; // colorizer for removed (-) lines\n dim?: (s: string) => string; // colorizer for context / hunk separators\n}\nexport interface DiffOptions extends DiffStyle {\n context?: number; // unchanged lines kept around each change (default 3)\n maxLines?: number; // cap rendered lines (default 160)\n}\n\nexport type DiffOp = { t: ' ' | '+' | '-'; line: string };\n\n/** LCS-based line diff → an ordered op list. O(n·m); guard very large inputs upstream. */\nexport function diffLines(before: string, after: string): DiffOp[] {\n const a = before ? before.split('\\n') : [];\n const b = after ? after.split('\\n') : [];\n const n = a.length, m = b.length;\n const dp: number[][] = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));\n for (let i = n - 1; i >= 0; i--)\n for (let j = m - 1; j >= 0; j--)\n dp[i][j] = a[i] === b[j] ? dp[i + 1][j + 1] + 1 : Math.max(dp[i + 1][j], dp[i][j + 1]);\n const ops: DiffOp[] = [];\n let i = 0, j = 0;\n while (i < n && j < m) {\n if (a[i] === b[j]) { ops.push({ t: ' ', line: a[i] }); i++; j++; }\n else if (dp[i + 1][j] >= dp[i][j + 1]) { ops.push({ t: '-', line: a[i] }); i++; }\n else { ops.push({ t: '+', line: b[j] }); j++; }\n }\n while (i < n) ops.push({ t: '-', line: a[i++] });\n while (j < m) ops.push({ t: '+', line: b[j++] });\n return ops;\n}\n\n/** Count added / removed lines from a precomputed op list — for the `+N -M` header. */\nexport function statOf(ops: DiffOp[]): { added: number; removed: number } {\n let added = 0, removed = 0;\n for (const op of ops) { if (op.t === '+') added++; else if (op.t === '-') removed++; }\n return { added, removed };\n}\n\n/** Convenience: count added / removed lines between two strings (runs the diff). */\nexport function diffStat(before: string, after: string): { added: number; removed: number } {\n return statOf(diffLines(before, after));\n}\n\n/** Convenience: diff two strings and render. Returns '' if nothing changed. */\nexport function renderDiff(before: string, after: string, opts: DiffOptions = {}): string {\n if (before === after) return '';\n return formatDiff(diffLines(before, after), opts);\n}\n\n/** Render a precomputed op list as a compact, context-limited, capped unified diff. */\nexport function formatDiff(ops: DiffOp[], opts: DiffOptions = {}): string {\n const { context = 3, maxLines = 160 } = opts;\n const id = (s: string) => s;\n const add = opts.add ?? id, del = opts.del ?? id, dim = opts.dim ?? id;\n const keep = new Array(ops.length).fill(false);\n ops.forEach((op, k) => {\n if (op.t === ' ') return;\n for (let d = -context; d <= context; d++) if (k + d >= 0 && k + d < ops.length) keep[k + d] = true;\n });\n const out: string[] = [];\n let elided = false;\n for (let k = 0; k < ops.length; k++) {\n if (!keep[k]) { if (!elided && out.length) { out.push(dim(' ⋯')); elided = true; } continue; }\n elided = false;\n const op = ops[k];\n out.push(op.t === '+' ? add(' +' + op.line) : op.t === '-' ? del(' -' + op.line) : dim(' ' + op.line));\n if (out.length >= maxLines) { out.push(dim(' … diff truncated')); break; }\n }\n return out.join('\\n');\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, renameSync, symlinkSync, unlinkSync, readlinkSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { forComponent, contentText, type Message } from '../src/index';\n\nconst log = forComponent('session');\n\n/** Global symlink index: `~/.agent/sessions/<id>.json` → per-project session file. */\nconst globalDir = () => join(homedir(), '.agent', 'sessions');\n\n/**\n * On-disk session store for the CLI: each conversation is one JSON file at\n * `<cwd>/.agent/sessions/<id>.json`. Writes are atomic (temp + rename) so a crash\n * mid-write never corrupts a prior session. This is what gives the REPL memory across\n * turns and powers `--continue` / `--resume`.\n */\nexport interface SessionMeta {\n id: string;\n created: number;\n updated: number;\n cwd: string;\n model?: string;\n turns: number;\n title: string;\n /** Cumulative tokens across all turns in this session (for `/cost`). */\n tokens?: number;\n /** Cumulative USD cost across all turns (per-turn model pricing; for `/cost`). */\n costUsd?: number;\n /** Sticky: true if any turn's usage was estimated (streamed without provider usage) → cost is approximate. */\n costEstimated?: boolean;\n /** Per-turn forensic log: timing, outcome, usage, and provider error per turn — for investigating a reported issue. */\n events?: TurnEvent[];\n}\n/** One turn's diagnostics, captured for offline forensics (mirrors what the footer prints, but persisted). */\nexport interface TurnEvent {\n ts: number; // turn start (epoch ms)\n durationMs: number;\n model: string;\n finishReason: string; // 'stop' | 'error' | 'length' | aborted, etc.\n steps: number;\n tools: number; // tool messages in this turn\n tokens?: number; // res.usage.totalTokens\n costUsd?: number;\n estimated?: boolean; // usage was estimated (no provider-reported usage)\n error?: { message: string; statusCode?: number; code?: string };\n}\nexport interface SessionData {\n meta: SessionMeta;\n messages: Message[];\n}\n\nexport class SessionStore {\n readonly dir: string;\n constructor(cwd: string) {\n this.dir = join(cwd, '.agent', 'sessions');\n }\n\n /** Sortable, human-readable id: `YYYYMMDD-HHMMSS-<folder>`. */\n newId(now = Date.now(), cwd?: string): string {\n const d = new Date(now);\n const p = (n: number, w = 2) => String(n).padStart(w, '0');\n const slug = (cwd ?? process.cwd()).split('/').pop()?.replace(/[^A-Za-z0-9_-]/g, '') || 'session';\n let id = `${d.getFullYear()}${p(d.getMonth() + 1)}${p(d.getDate())}-${p(d.getHours())}${p(d.getMinutes())}${p(d.getSeconds())}-${slug}`;\n // Disambiguate same-second collisions (concurrent launches / rapid --fork)\n if (existsSync(this.dir) && existsSync(join(this.dir, `${id}.json`))) {\n for (let i = 2; i <= 99; i++) { const c = `${id}-${i}`; if (!existsSync(join(this.dir, `${c}.json`))) { id = c; break; } }\n }\n return id;\n }\n\n /** A session id must be one safe path segment — blocks `../`-style traversal via --resume/load/save. */\n private safeId(id: string): boolean { return /^[A-Za-z0-9._-]+$/.test(id) && !id.includes('..'); }\n\n save(data: SessionData): void {\n if (!this.safeId(data.meta.id)) throw new Error(`unsafe session id: ${data.meta.id}`);\n if (!existsSync(this.dir)) mkdirSync(this.dir, { recursive: true });\n const path = join(this.dir, `${data.meta.id}.json`);\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, JSON.stringify(data));\n renameSync(tmp, path); // atomic swap\n // Global symlink index: ~/.agent/sessions/<id>.json → this file (zero-cost cross-project lookup)\n try {\n const gd = globalDir();\n if (!existsSync(gd)) mkdirSync(gd, { recursive: true });\n const link = join(gd, `${data.meta.id}.json`);\n if (!existsSync(link)) symlinkSync(path, link);\n } catch { /* non-fatal: best-effort index */ }\n }\n\n load(id: string): SessionData | undefined {\n if (!this.safeId(id)) { log.debug(`rejecting unsafe session id: ${id}`); return undefined; }\n const path = join(this.dir, `${id}.json`);\n if (!existsSync(path)) return undefined;\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as SessionData;\n } catch (e) {\n log.debug(`unreadable session ${id} — ignoring`, e); // corrupt file → caller treats as \"no session\"\n return undefined;\n }\n }\n\n /** All sessions' metadata, most-recently-updated first. */\n list(): SessionMeta[] {\n if (!existsSync(this.dir)) return [];\n const metas: SessionMeta[] = [];\n for (const f of readdirSync(this.dir)) {\n if (!f.endsWith('.json')) continue;\n try {\n metas.push((JSON.parse(readFileSync(join(this.dir, f), 'utf8')) as SessionData).meta);\n } catch (e) {\n log.debug(`skipping unreadable session file ${f}`, e);\n }\n }\n return metas.sort((a, b) => b.updated - a.updated);\n }\n\n latest(): SessionMeta | undefined {\n return this.list()[0];\n }\n\n /** The most-recently-updated session's full data (single listing pass). */\n latestData(): SessionData | undefined {\n const m = this.latest();\n return m ? this.load(m.id) : undefined;\n }\n}\n\n/** Global session lookup: resolve a (partial) session ID across all projects via the symlink index. */\nexport function globalSessionLoad(idOrPrefix: string): SessionData | undefined {\n const gd = globalDir();\n if (!existsSync(gd)) return undefined;\n // Exact match first\n const exact = join(gd, `${idOrPrefix}.json`);\n if (existsSync(exact)) {\n try {\n const target = readlinkSync(exact);\n return JSON.parse(readFileSync(target, 'utf8')) as SessionData;\n } catch { return undefined; }\n }\n // Prefix/suffix match (user typed a shortId like \"090715-335\" = last 10 chars)\n try {\n for (const f of readdirSync(gd)) {\n if (!f.endsWith('.json')) continue;\n const base = f.slice(0, -5);\n if (base.includes(idOrPrefix) || base.endsWith(idOrPrefix)) {\n const target = readlinkSync(join(gd, f));\n return JSON.parse(readFileSync(target, 'utf8')) as SessionData;\n }\n }\n } catch { /* best effort */ }\n return undefined;\n}\n\n/** List all sessions globally (from symlink index), most-recently-updated first. */\nexport function globalSessionList(): SessionMeta[] {\n const gd = globalDir();\n if (!existsSync(gd)) return [];\n const metas: SessionMeta[] = [];\n for (const f of readdirSync(gd)) {\n if (!f.endsWith('.json')) continue;\n try {\n const target = readlinkSync(join(gd, f));\n if (!existsSync(target)) { try { unlinkSync(join(gd, f)); } catch {} continue; } // stale symlink → prune\n metas.push((JSON.parse(readFileSync(target, 'utf8')) as SessionData).meta);\n } catch { /* skip corrupt */ }\n }\n return metas.sort((a, b) => b.updated - a.updated);\n}\n\n/** A short, single-line title derived from the first user message. */\nexport function titleOf(messages: Message[]): string {\n const u = messages.find((m) => m.role === 'user');\n const t = contentText(u?.content).replace(/\\s+/g, ' ').trim();\n return t.length > 60 ? t.slice(0, 57) + '…' : t || '(empty)';\n}\n","import type { IFilesystem, Hooks, ToolUse } from '../src/index';\nimport { sanitizeLabel } from './util';\nimport { diffLines, formatDiff } from './diff';\n\n/**\n * Within-session checkpoint/rewind for the CLI. The undo primitive (`OverlayFilesystem`) commits\n * one-way, so instead of buffering we capture, per turn, the **pre-mutation content** of every file\n * a structured mutator (Write/Edit/MultiEdit/ApplyEdits) is about to change — via a `preToolUse` hook — and can\n * restore the working tree to before any earlier turn.\n *\n * Scope (v1): structured FS edits only. `bash`/`Shell` side-effects are NOT checkpointed (we can't\n * know what an arbitrary process touched) — same edit-focused boundary as CC's rewind. History is\n * bounded and in-memory: it's gone when the session ends (git is the cross-session net).\n */\nexport const MUTATORS = new Set(['Write', 'Edit', 'MultiEdit', 'ApplyEdits']);\n\n/** Paths a mutator tool call is about to change. Covers single-file tools (`args.path`: Write/Edit/\n * MultiEdit) AND the multi-file `ApplyEdits` (`args.edits[].path`). Shared by both checkpoint backends\n * so a new write-class tool only has to be added to MUTATORS once. */\nexport function mutatedPaths(call: ToolUse): string[] {\n if (!MUTATORS.has(call.name)) return [];\n const out: string[] = [];\n if (typeof call.args?.path === 'string') out.push(call.args.path);\n if (Array.isArray(call.args?.edits)) for (const e of call.args.edits) if (typeof e?.path === 'string') out.push(e.path);\n return [...new Set(out)];\n}\n\n/**\n * Common contract for the CLI's two checkpoint backends: the in-memory {@link CheckpointStack}\n * (sandbox mode) and the durable git-backed `GitCheckpoints` (disk mode). Both expose the same\n * begin/list/rewindTo/size surface consumed by the REPL (`/rewind`, `/undo`, double-Esc rewind).\n */\nexport interface Checkpoints {\n /** Open a restore point for the turn about to run (label = the user's message). */\n begin(label: string): void | Promise<void>;\n /** Restore points, newest-first, for an interactive picker. */\n list(): { index: number; label: string; at: number; files: number }[];\n /** Restore the working tree to BEFORE restore point `index` (undo it and every later one). */\n rewindTo(index: number): Promise<{ restored: number; deleted: number }>;\n /** Number of restore points currently held. */\n readonly size: number;\n /** Optional pre-mutation hook (in-memory backend only; git captures at the turn boundary). */\n hooks?(): Hooks;\n /** Re-bind to a different conversation (resume/switch); no-op for the in-memory backend. */\n use?(sessionId: string): void;\n /** Sync `list()`/`size` with the durable backend before a read (git backend only). */\n refresh?(): Promise<void>;\n /** Unified diff of everything this session changed (oldest restore point → current tree), for `/diff`. */\n diff?(): Promise<string>;\n}\n\ninterface Frame {\n label: string;\n at: number;\n /** path -> content BEFORE this turn first touched it (null = file did not exist yet). */\n saved: Map<string, string | null>;\n}\n\nexport class CheckpointStack implements Checkpoints {\n private frames: Frame[] = [];\n private current?: Frame;\n\n constructor(private fs: IFilesystem, private max = 50) {}\n\n /** Open a new turn frame (call right before sending a user turn). */\n begin(label: string): void {\n this.current = { label: sanitizeLabel(label) || '(turn)', at: Date.now(), saved: new Map() };\n this.frames.push(this.current);\n if (this.frames.length > this.max) this.frames.shift(); // bounded history\n }\n\n /** Hook that snapshots a file's prior content before a mutating tool overwrites it. */\n hooks(): Hooks {\n return {\n preToolUse: async (call: ToolUse) => {\n if (!this.current) return;\n for (const path of mutatedPaths(call)) {\n if (this.current.saved.has(path)) continue; // only the FIRST touch in a turn matters\n let prior: string | null = null;\n try { prior = await this.fs.readFile(path); } catch { prior = null; } // absent → created this turn\n this.current.saved.set(path, prior);\n }\n },\n };\n }\n\n get size(): number { return this.frames.length; }\n\n /** Frames newest-first, for an interactive picker. */\n list(): { index: number; label: string; at: number; files: number }[] {\n return this.frames.map((f, i) => ({ index: i, label: f.label, at: f.at, files: f.saved.size })).reverse();\n }\n\n /** Unified-style diff of all session edits: each file's OLDEST saved content vs its current content. */\n async diff(): Promise<string> {\n const base = new Map<string, string | null>(); // oldest frame wins = true pre-session content\n for (const f of this.frames) for (const [path, prior] of f.saved) if (!base.has(path)) base.set(path, prior);\n const parts: string[] = [];\n for (const [path, prior] of base) {\n let now: string | null = null;\n try { now = await this.fs.readFile(path); } catch { /* deleted since */ }\n if ((prior ?? '') === (now ?? '')) continue;\n const ops = diffLines(prior ?? '', now ?? '');\n parts.push(`--- ${path}${prior == null ? ' (new)' : now == null ? ' (deleted)' : ''}\\n${formatDiff(ops)}`);\n }\n return parts.join('\\n');\n }\n\n /**\n * Restore the working tree to BEFORE frame `index` — undo that frame and every later one.\n * Frames are replayed newest→oldest so the OLDEST saved content for a path wins (its true\n * pre-edit state). A file that was created in an undone frame is deleted.\n */\n async rewindTo(index: number): Promise<{ restored: number; deleted: number }> {\n if (index < 0 || index >= this.frames.length) throw new Error('no such checkpoint');\n let restored = 0, deleted = 0;\n for (let i = this.frames.length - 1; i >= index; i--) {\n for (const [path, prior] of this.frames[i].saved) {\n if (prior == null) { try { await this.fs.deleteFile(path); deleted++; } catch { /* already gone */ } }\n else { await this.fs.writeFile(path, prior); restored++; }\n }\n }\n this.frames.length = index; // drop the undone frames\n this.current = undefined;\n return { restored, deleted };\n }\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { writeFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { join, resolve, sep } from 'node:path';\nimport { forComponent } from '../src/index';\nimport type { Hooks, ToolUse } from '../src/index';\nimport type { Checkpoints } from './checkpoints';\nimport { mutatedPaths } from './checkpoints';\nimport { sanitizeLabel } from './util';\n\nconst log = forComponent('checkpoints');\nconst exec = promisify(execFile);\n\n/**\n * Durable, CC-parity file checkpoints for the CLI's **disk mode**. Each checkpointed root (the launch\n * cwd, plus any `--add-dir` mounts outside it) gets a *shadow* git repo with its own `GIT_DIR` over the\n * real tree — so a turn's WHOLE-tree state is snapshotted (capturing bash side-effects too, unlike the\n * structured-edit-only in-memory stack) and survives across sessions. The separate git-dir means the\n * user's real `.git` is never touched.\n *\n * One commit per turn per root on a per-session ref (`refs/heads/<sessionId>`), so each conversation has\n * its own restore-point history and the roots stay in lockstep. Rewinding `reset --hard`s every root back\n * and `clean -fd`s untracked-new files (never `-x`, so ignored dirs like node_modules are preserved).\n * Old conversations' refs are pruned past a retention window and objects reclaimed via `gc --auto`.\n */\nconst DEFAULT_EXCLUDE = ['.agent/', '.git/', 'node_modules/', 'dist/', 'build/', '.next/', 'target/', '.venv/', '__pycache__/', '*.log'];\n\ninterface Commit { sha: string; at: number; label: string; files?: number }\n\n/** One shadow git repo over a single real work-tree. Low-level git plumbing; index space is oldest-first. */\nclass ShadowRepo {\n ready?: boolean; // undefined = unprobed; false = git/this root unusable\n constructor(private workTree: string, private gitDir: string, private exclude: string[], private git: string) {}\n\n /** Absolute work-tree root — used to route force-tracked paths to the repo that contains them. */\n get root(): string { return this.workTree; }\n\n private async run(...args: string[]): Promise<string> {\n const { stdout } = await exec(this.git, ['-c', 'core.hooksPath=/dev/null', ...args], {\n env: { ...process.env, GIT_DIR: this.gitDir, GIT_WORK_TREE: this.workTree },\n maxBuffer: 64 * 1024 * 1024,\n });\n return stdout;\n }\n\n async init(): Promise<boolean> {\n if (this.ready !== undefined) return this.ready;\n try {\n await exec(this.git, ['--version']);\n if (!existsSync(this.gitDir)) { mkdirSync(this.gitDir, { recursive: true }); await this.run('init', '-q'); }\n // (Re)write excludes every init so an existing shadow repo picks up changes to the default list.\n writeFileSync(join(this.gitDir, 'info', 'exclude'), this.exclude.join('\\n') + '\\n');\n this.ready = true;\n } catch (e) { log.debug(`git checkpoints unavailable for ${this.workTree}`, e); this.ready = false; }\n return this.ready;\n }\n\n /** Point HEAD at the session ref without touching the work-tree. */\n async point(ref: string): Promise<void> { await this.run('symbolic-ref', 'HEAD', ref); }\n\n async commit(label: string, forced: string[] = []): Promise<void> {\n await this.run('add', '-A'); // honors .gitignore (keeps node_modules etc. out)\n // …then force-add the paths the agent itself touched, so its work is snapshotted even when it\n // lives in a .gitignored dir (e.g. .tmp/tasks/). Bounded to agent-edited files — never the tree.\n for (const p of forced) await this.run('add', '-f', '--', p).catch((e) => log.debug(`force-add failed: ${p}`, e));\n await this.run('commit', '--allow-empty', '-q', '-m', label);\n }\n\n /** Inject the CURRENT (pre-edit) content of `paths` into the turn-open restore point by amending it.\n * Lets a rewind recover the ORIGINAL of a .gitignored file the agent is about to overwrite — the\n * turn-boundary `add -A` would never have captured it. Amend (vs a new commit) keeps one restore\n * point per turn, so the REPL's turn↔frame mapping stays intact. */\n async amendForced(paths: string[]): Promise<void> {\n for (const p of paths) await this.run('add', '-f', '--', p).catch((e) => log.debug(`force-capture failed: ${p}`, e));\n await this.run('commit', '--amend', '--no-edit', '-q', '--allow-empty').catch((e) => log.debug('amend failed', e));\n }\n\n /** Commits on `ref`, oldest-first (canonical index space). */\n async log(ref: string): Promise<Commit[]> {\n try {\n const out = await this.run('log', '--format=%H%x00%ct%x00%s', ref);\n return out.split('\\n').filter(Boolean).map((l) => {\n const [sha, ct, ...rest] = l.split('\\x00');\n return { sha, at: Number(ct) * 1000, label: rest.join('\\x00') };\n }).reverse();\n } catch { return []; } // unborn ref / no commits\n }\n\n /** How many tracked files differ between `sha` and the current work-tree (= rewind impact preview). */\n async filesVsWorktree(sha: string): Promise<number> {\n try { return (await this.run('diff', '--name-only', sha)).split('\\n').filter(Boolean).length; } catch { return 0; }\n }\n\n /** Unified diff between `sha` and the current work-tree (for `/diff`). */\n async diffSince(sha: string): Promise<string> {\n try { return await this.run('diff', sha); } catch { return ''; }\n }\n\n /** Restore the tree to `sha`; returns counts of reverted tracked files + removed untracked-new. */\n async resetTo(sha: string): Promise<{ restored: number; deleted: number }> {\n let restored = 0, deleted = 0;\n try { restored = (await this.run('diff', '--name-status', sha)).split('\\n').filter(Boolean).length; } catch (e) { void e; }\n try { deleted = (await this.run('clean', '-nd')).split('\\n').filter(Boolean).length; } catch (e) { void e; }\n await this.run('reset', '--hard', '-q', sha);\n await this.run('clean', '-fd'); // NOT -x: keep ignored dirs (node_modules, …)\n return { restored, deleted };\n }\n\n /** Delete session refs whose tip is older than `cutoffSec` (keep `keepRef`), then reclaim objects. */\n async prune(cutoffSec: number, keepRef: string): Promise<void> {\n try {\n // for-each-ref has no %x00 escape (unlike git log); refnames can't contain spaces, so split on one.\n const out = await this.run('for-each-ref', '--format=%(committerdate:unix) %(refname)', 'refs/heads/');\n for (const l of out.split('\\n').filter(Boolean)) {\n const sp = l.indexOf(' ');\n const ts = Number(l.slice(0, sp)), ref = l.slice(sp + 1);\n if (ref !== keepRef && ts < cutoffSec) await this.run('update-ref', '-d', ref).catch(() => {});\n }\n await this.run('gc', '--auto', '-q').catch(() => {});\n } catch (e) { log.debug('checkpoint prune failed', e); }\n }\n}\n\nexport class GitCheckpoints implements Checkpoints {\n public options: GitCheckpointsOptions;\n private session: string;\n private repos: ShadowRepo[];\n private started = false;\n private snapshotted = false; // false until the first (potentially slow) full-tree commit lands\n private caches: Commit[][] = []; // per-repo, oldest-first; repos stay in lockstep\n private forced = new Set<string>(); // absolute paths the agent touched → force-tracked despite .gitignore\n\n public constructor(options?: Partial<GitCheckpointsOptions>) {\n this.options = { ...new GitCheckpointsOptions(), ...options };\n this.session = this.options.sessionId;\n this.repos = this.roots().map((r) => new ShadowRepo(r.workTree, r.gitDir, this.options.exclude, this.options.git));\n this.caches = this.repos.map(() => []);\n }\n\n private ref(): string { return `refs/heads/${this.session}`; }\n\n /** cwd + any add-dir mounts that live OUTSIDE cwd (in-cwd mounts are already covered by the cwd root). */\n private roots(): { workTree: string; gitDir: string }[] {\n const cwd = resolve(this.options.workTree);\n const out = [{ workTree: cwd, gitDir: this.options.gitDir }];\n for (const d of this.options.addDirs ?? []) {\n const abs = resolve(d);\n if (abs === cwd || abs.startsWith(cwd + sep)) continue; // inside cwd → already snapshotted\n if (cwd.startsWith(abs + sep)) continue; // ancestor of cwd → avoid nesting + huge snapshot\n out.push({ workTree: abs, gitDir: join(abs, '.agent', 'checkpoints.git') });\n }\n return out;\n }\n\n /** Init every usable root once, point HEAD at the session ref, and prune stale history. Drops dead roots. */\n private async start(): Promise<boolean> {\n if (this.started) return this.repos.length > 0;\n this.started = true;\n const usable: ShadowRepo[] = [];\n const caches: Commit[][] = [];\n const cutoff = Math.floor(Date.now() / 1000) - this.options.retainDays * 86400;\n for (const r of this.repos) {\n if (!(await r.init())) continue;\n await r.point(this.ref());\n await r.prune(cutoff, this.ref());\n usable.push(r); caches.push([]);\n }\n if (!usable.length && this.repos.length) // git present but every root failed, or git missing\n process.stderr.write('\\x1b[2m checkpoints: git unavailable — file rewind disabled (conversation rewind still works)\\x1b[0m\\n');\n this.repos = usable; this.caches = caches;\n return usable.length > 0;\n }\n\n use(sessionId: string): void {\n if (sessionId === this.session) return;\n this.session = sessionId;\n if (this.started) for (const r of this.repos) void r.point(this.ref()).catch((e) => log.debug('re-point failed', e));\n }\n\n async begin(label: string): Promise<void> {\n if (!(await this.start())) return;\n const msg = sanitizeLabel(label, 72) || '(turn)';\n // The first commit hashes the whole tree — warn (once) only if it's actually slow on a big workspace.\n let slow: ReturnType<typeof setTimeout> | undefined;\n if (!this.snapshotted) slow = setTimeout(() => process.stderr.write('\\x1b[2m checkpointing initial workspace snapshot…\\x1b[0m\\n'), 1500);\n for (let i = 0; i < this.repos.length; i++) {\n const forced = [...this.forced].filter((p) => this.repoIndexFor(p) === i); // this repo's touched paths\n try { await this.repos[i].commit(msg, forced); } catch (e) { log.debug('checkpoint commit failed', e); } // never block a turn\n }\n if (slow) clearTimeout(slow);\n this.snapshotted = true;\n }\n\n /** Index of the repo whose work-tree contains `abs` (longest-prefix wins for nested roots); -1 if none. */\n private repoIndexFor(abs: string): number {\n let best = -1, bestLen = -1;\n this.repos.forEach((r, i) => {\n const wt = r.root.endsWith(sep) ? r.root.slice(0, -1) : r.root;\n if ((abs === wt || abs.startsWith(wt + sep)) && wt.length > bestLen) { best = i; bestLen = wt.length; }\n });\n return best;\n }\n\n /** Pre-mutation hook: the FIRST time the agent touches a path in a turn, force-capture its current\n * content into the turn-open restore point — so even a .gitignored or bash-untracked file the agent\n * overwrites stays recoverable via /rewind. Best-effort: never throws, never blocks a turn. */\n hooks(): Hooks {\n return {\n preToolUse: async (call: ToolUse) => {\n if (!this.snapshotted || !this.repos.length) return; // no restore point to amend into yet\n for (const rel of mutatedPaths(call)) {\n const abs = resolve(this.options.workTree, rel);\n if (this.forced.has(abs)) continue; // only the first touch matters\n this.forced.add(abs);\n const i = this.repoIndexFor(abs);\n if (i >= 0) await this.repos[i].amendForced([abs]).catch((e) => log.debug('amendForced failed', e));\n }\n },\n };\n }\n\n async refresh(): Promise<void> {\n if (!(await this.start())) { this.caches = []; return; }\n this.caches = await Promise.all(this.repos.map((r) => r.log(this.ref())));\n // Annotate the primary root's rows with rewind impact (files that would change) for the picker.\n const primary = this.caches[0];\n if (primary?.length) await Promise.all(primary.map(async (c) => { c.files = await this.repos[0].filesVsWorktree(c.sha); }));\n }\n\n /** Newest-first display rows carrying their oldest-first `index` (mirrors CheckpointStack.list()). */\n list(): { index: number; label: string; at: number; files: number }[] {\n return (this.caches[0] ?? []).map((f, i) => ({ index: i, label: f.label, at: f.at, files: f.files ?? 0 })).reverse();\n }\n\n get size(): number { return this.caches[0]?.length ?? 0; }\n\n /** Unified diff of everything this session changed: oldest session checkpoint → current tree, across all roots. */\n async diff(): Promise<string> {\n if (!this.caches[0]?.length) await this.refresh();\n const parts: string[] = [];\n for (let i = 0; i < this.repos.length; i++) {\n const base = this.caches[i]?.[0];\n if (base) parts.push(await this.repos[i].diffSince(base.sha));\n }\n return parts.filter(Boolean).join('\\n');\n }\n\n async rewindTo(index: number): Promise<{ restored: number; deleted: number }> {\n if (!this.caches[0]?.length) await this.refresh();\n if (index < 0 || index >= (this.caches[0]?.length ?? 0)) throw new Error('no such checkpoint');\n let restored = 0, deleted = 0;\n for (let i = 0; i < this.repos.length; i++) {\n const c = this.caches[i];\n if (index >= c.length) continue; // a root added later than this point — nothing to undo there\n const r = await this.repos[i].resetTo(c[index].sha);\n restored += r.restored; deleted += r.deleted;\n this.caches[i] = c.slice(0, index + 1); // commits after the target are gone; target is now HEAD\n }\n return { restored, deleted };\n }\n}\n\nexport class GitCheckpointsOptions {\n /** Real working tree to snapshot (the launch cwd). */\n workTree = process.cwd();\n /** Isolated git dir for the cwd shadow repo (kept out of the user's real .git). */\n gitDir = join(process.cwd(), '.agent', 'checkpoints.git');\n /** Extra mounted dirs (`--add-dir`); those outside cwd each get their own shadow repo. */\n addDirs: string[] = [];\n /** Conversation id → per-session restore-point ref. */\n sessionId = 'default';\n /** Drop restore-point history for conversations untouched for this many days (then `gc --auto`). */\n retainDays = 30;\n /** Paths the shadow repos always ignore (heavy/derived/VCS), beyond the user's own .gitignore. */\n exclude: string[] = [...DEFAULT_EXCLUDE];\n /** git executable. */\n git = 'git';\n}\n","import { writeFileSync, mkdirSync } from 'node:fs';\nimport { readJsonFile } from './util';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { PermissionRule, Decision } from '../src/index';\n\nexport type PermConfig = { allow?: string[]; ask?: string[]; deny?: string[] };\n\n/**\n * Parse CC-style permission rule strings from config into `PermissionRule`s.\n *\n * Grammar: `Tool` (whole tool) or `Tool(pathGlob)` (file-path-bearing tools). Precedence is encoded\n * by ORDER — `deny` first, then `allow`, then `ask` — because `PermissionPolicy.decide` is first-match.\n * So a `deny` always beats an `allow`/`ask` for the same call.\n *\n * The glob matches the call's `path` arg (file tools) OR its `command` arg (`bash`/`Shell`), so\n * `Edit(src/**)` gates edits under src and `Shell(git *)` / `bash(rm *)` gate by command pattern.\n */\nconst RULE_RE = /^(\\w+)(?:\\((.+)\\))?$/;\n\nfunction parseOne(raw: string, decision: Decision): PermissionRule | null {\n const m = RULE_RE.exec(raw.trim());\n if (!m) return null;\n const [, tool, pathGlob] = m;\n return pathGlob ? { tool, pathGlob, decision } : { tool, decision };\n}\n\n/** Build ordered rules (deny → allow → ask) from a config `permissions` block. Bad entries are skipped. */\nexport function parsePermRules(perms?: { allow?: string[]; ask?: string[]; deny?: string[] }): PermissionRule[] {\n if (!perms) return [];\n const out: PermissionRule[] = [];\n for (const [decision, list] of [['deny', perms.deny], ['allow', perms.allow], ['ask', perms.ask]] as const) {\n for (const raw of list ?? []) { const r = parseOne(raw, decision); if (r) out.push(r); }\n }\n return out;\n}\n\n/** One-line human summary of a rule (for `/permissions`). */\nexport function describeRule(r: PermissionRule): string {\n return `${r.decision.padEnd(5)} ${r.tool ?? '*'}${r.pathGlob ? `(${r.pathGlob})` : ''}`;\n}\n\n// --- persisted rules (.agent/permissions.json) — written by \"Always allow/deny\" prompts ---\nconst PERM_FILE = (cwd: string) => join(cwd, '.agent', 'permissions.json');\n\n/** Read persisted project rules (returns {} if absent/unreadable — never throws). */\nexport function loadPersistedRules(cwd: string): PermConfig {\n const j = readJsonFile<any>(PERM_FILE(cwd), null);\n return j ? { allow: j.allow ?? [], ask: j.ask ?? [], deny: j.deny ?? [] } : {};\n}\n\n/**\n * Read CC-compatible `.claude/settings.json` permission rules and merge them (user → project → project-local).\n * Same `Tool(arg)` string format as our own `permissions` block, so a Claude Code user's existing rules apply\n * as-is (e.g. `Read(./.env)`, `Edit(src/**)`). Malformed/absent files are ignored — never crashes a run.\n * (Tool-name caveat: CC's shell tool is `Bash`; ours are `bash`/`Shell` — shell rules may need renaming.)\n */\nexport function loadClaudeSettings(cwd: string, home: string = homedir()): PermConfig {\n const files = [join(home, '.claude', 'settings.json'), join(cwd, '.claude', 'settings.json'), join(cwd, '.claude', 'settings.local.json')];\n let out: PermConfig = {};\n for (const p of files) {\n // malformed/absent files fall back to null (logged) — config never crashes a run\n const perms = readJsonFile<any>(p, null)?.permissions;\n if (perms) out = mergePerms(out, { allow: perms.allow, ask: perms.ask, deny: perms.deny }) ?? out;\n }\n return out;\n}\n\n/** Append a rule string under a decision bucket and persist (idempotent — no duplicates). */\nexport function persistRule(cwd: string, decision: Decision, ruleStr: string): void {\n const cur = loadPersistedRules(cwd);\n const list = (cur[decision] ??= []);\n if (!list.includes(ruleStr)) list.push(ruleStr);\n try { mkdirSync(join(cwd, '.agent'), { recursive: true }); writeFileSync(PERM_FILE(cwd), JSON.stringify(cur, null, 2) + '\\n'); }\n catch { /* best-effort; a remembered rule still applies for this session via the policy */ }\n}\n\n/** Merge two permission configs (later wins on duplicates; arrays concatenated + deduped). */\nexport function mergePerms(a?: PermConfig, b?: PermConfig): PermConfig | undefined {\n if (!a && !b) return undefined;\n const out: PermConfig = {};\n for (const k of ['allow', 'ask', 'deny'] as const) {\n const merged = [...(a?.[k] ?? []), ...(b?.[k] ?? [])];\n if (merged.length) out[k] = [...new Set(merged)];\n }\n return Object.keys(out).length ? out : undefined;\n}\n\n// --- directory trust ledger (~/.agent/trusted.json; path injectable for tests) ---\nconst TRUST_FILE = join(homedir(), '.agent', 'trusted.json');\n\n/** Has the user previously trusted this working directory? */\nexport function isTrusted(cwd: string, file = TRUST_FILE): boolean {\n const list = readJsonFile<string[]>(file, []);\n return Array.isArray(list) && list.includes(cwd);\n}\n\n/** Record `cwd` as trusted (so future runs don't re-prompt). */\nexport function trustDir(cwd: string, file = TRUST_FILE): void {\n let list = readJsonFile<string[]>(file, []); // corrupt file resets (logged in readJsonFile)\n if (!Array.isArray(list)) list = [];\n if (!list.includes(cwd)) list.push(cwd);\n try { mkdirSync(join(file, '..'), { recursive: true }); writeFileSync(file, JSON.stringify(list, null, 2) + '\\n'); }\n catch { /* best-effort */ }\n}\n","/**\n * Tab-completion for the REPL line editor (readline `completer`). Two modes:\n * - `/cmd` — when it's the whole line → complete slash-command names (builtins + custom).\n * - `@path` — the token under the cursor → complete file/dir paths (dirs get a trailing `/`).\n * Returns readline's `[hits, token]`: `hits` replace the trailing `token`. No match → `[[], line]`.\n *\n * Synchronous by necessity: Bun/Node readline destructure the completer's return value inline,\n * so an async completer crashes. Directory access is injected as a sync `DirLister` — the CLI\n * backs it with `readdirSync`; tests pass an in-memory map.\n */\n\n/** List an absolute dir's immediate entries for completion; return `null` if it isn't a directory. */\nexport type DirLister = (absDir: string) => Array<{ name: string; dir: boolean }> | null;\n\nexport interface CompleteContext {\n /** Slash-command names WITHOUT the leading `/` (builtins + user-defined). */\n commands: string[];\n listDir: DirLister;\n /** Past `!`-prefixed shell lines (most-recent-first) — completes `!<partial>` from history (CC parity). */\n bangHistory?: string[];\n}\n\n/** The trailing whitespace-free token under the cursor — what we try to complete. */\nexport function lastToken(line: string): string {\n const m = line.match(/(\\S*)$/);\n return m ? m[1] : '';\n}\n\nexport function completeLine(line: string, ctx: CompleteContext): [string[], string] {\n const token = lastToken(line);\n\n // /slash-command — only when it's the whole line (commands aren't valid mid-sentence).\n if (token.startsWith('/') && line.trimStart() === token) {\n const want = token.slice(1);\n const hits = rank(ctx.commands.filter((c) => fuzzy(want, c)), want).map((c) => '/' + c);\n return [hits, token];\n }\n\n // !shell — complete the WHOLE line from past `!` commands (needs ≥1 char so a bare `!` stays quiet).\n if (line.startsWith('!') && line.length > 1 && ctx.bangHistory?.length) {\n const want = line.slice(1);\n const seen = new Set<string>();\n const hits = ctx.bangHistory.filter((h) => h.startsWith('!') && h.length > 1 && fuzzy(want, h.slice(1)) && !seen.has(h) && !!seen.add(h));\n return [rank(hits, line), line]; // token = the whole line → accept replaces it entirely\n }\n\n // @file mention — complete a path.\n if (token.startsWith('@')) return [completePath(ctx.listDir, token.slice(1)), token];\n\n return [[], line];\n}\n\n/** Case-insensitive subsequence match (`cr` matches `code-review`) — empty needle matches all. */\nexport function fuzzy(needle: string, hay: string): boolean {\n if (!needle) return true;\n const n = needle.toLowerCase(), h = hay.toLowerCase();\n let i = 0;\n for (let j = 0; j < h.length && i < n.length; j++) if (h[j] === n[i]) i++;\n return i === n.length;\n}\n\n/** Sort fuzzy hits: exact-prefix matches first, then alphabetical — so the obvious match leads. */\nfunction rank(hits: string[], needle: string): string[] {\n const n = needle.toLowerCase();\n return hits.slice().sort((a, b) => {\n const pa = a.toLowerCase().startsWith(n) ? 0 : 1, pb = b.toLowerCase().startsWith(n) ? 0 : 1;\n return pa - pb || a.localeCompare(b);\n });\n}\n\n/** Path completion: `@`-prefixed matches under `ref`'s dir (fuzzy basename), dirs suffixed with `/`. */\nfunction completePath(listDir: DirLister, ref: string): string[] {\n const slash = ref.lastIndexOf('/');\n const dir = slash >= 0 ? ref.slice(0, slash) : '';\n const base = slash >= 0 ? ref.slice(slash + 1) : ref;\n const abs = '/' + dir.split('/').filter(Boolean).join('/'); // '/' when dir is empty\n const entries = listDir(abs);\n if (!entries) return [];\n const matched: string[] = [];\n for (const e of entries) {\n if (!fuzzy(base, e.name)) continue;\n if (e.name.startsWith('.') && !base.startsWith('.')) continue; // hide dotfiles unless explicitly typed\n const rel = (dir ? `${dir}/${e.name}` : e.name) + (e.dir ? '/' : '');\n // spaced names ride the quoted-mention form (@\"a b.png\") — an unquoted space breaks @\\S+ parsing\n matched.push(/\\s/.test(rel) ? `@\"${rel}\"` : '@' + rel);\n }\n return rank(matched, '@' + (dir ? dir + '/' : '') + base); // prefix-first within the dir\n}\n","import { emitKeypressEvents } from 'node:readline';\nimport { spawnSync } from 'node:child_process';\nimport { writeFileSync, readFileSync, unlinkSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { applyBidi, appBidi } from './bidi';\nimport { wrapAnsi } from './markdown';\nimport { keyInput } from './stdinSource';\n\n/**\n * A dependency-free raw-mode line editor with a LIVE autocomplete menu — the Claude-Code DX:\n * the moment you type `/` or `@`, suggestions appear under the prompt and filter as you type;\n * ↑/↓ select, Tab/Enter accept, Esc dismisses. Falls back to a plain read when stdin isn't a TTY.\n *\n * The state machine (EditorState + applyKey) is pure and unit-tested; createLineEditor wires it to\n * stdin keypress events + an ANSI renderer. The REPL keeps raw mode on for its whole session and\n * swaps keypress handlers between \"reading a line\" (this) and \"running a turn\" (Esc-to-cancel).\n */\n\n/** A suggestion provider: given the line up to the cursor, return full-replacement hits + the token they replace. */\nexport type Suggest = (lineToCursor: string) => { hits: string[]; token: string; describe?: (hit: string) => string | undefined };\n\n/** Classify a pasted blob (e.g. a drag-dropped file path) into an attachment: `display` is shown in the\n * in-buffer placeholder, `ref` is what the placeholder expands to on submit (e.g. an `@/abs/path` mention). */\nexport type PasteClassifier = (text: string) => { display: string; ref: string } | null;\n\nexport interface KeyEvent { name?: string; ctrl?: boolean; meta?: boolean; shift?: boolean; sequence?: string; }\n\n/** Terminal column width of one code point: 2 for East-Asian wide/emoji, 0 for joiners/combining marks. */\nexport const cpWidth = (cp: number): number => {\n if (cp === 0x200d || cp === 0xfe0f || (cp >= 0x0300 && cp <= 0x036f)) return 0; // ZWJ / VS16 / combining\n return (cp >= 0x1100 && (cp <= 0x115f || cp === 0x2329 || cp === 0x232a ||\n (cp >= 0x2e80 && cp <= 0xa4cf && cp !== 0x303f) ||\n (cp >= 0xac00 && cp <= 0xd7a3) || (cp >= 0xf900 && cp <= 0xfaff) ||\n (cp >= 0xfe30 && cp <= 0xfe4f) || (cp >= 0xff00 && cp <= 0xff60) ||\n (cp >= 0xffe0 && cp <= 0xffe6) ||\n (cp >= 0x1f000 && cp <= 0x1faff) || (cp >= 0x20000 && cp <= 0x3fffd))) ? 2 : 1;\n};\n\n/** Visible width of a string in terminal COLUMNS (ANSI SGR codes occupy none; CJK/emoji occupy two). */\nexport const visibleWidth = (s: string): number => {\n let w = 0;\n for (const ch of s.replace(/\\x1b\\[[0-9;]*m/g, '')) w += cpWidth(ch.codePointAt(0)!);\n return w;\n};\n\n/** A typed printable character (incl. Hebrew/Unicode): non-empty and free of control bytes.\n * Rejects escape sequences (arrow keys etc. arrive as multi-char `str` containing \\x1b/control bytes). */\nexport const isPrintable = (str?: string): str is string => !!str && !/[\\x00-\\x1f\\x7f]/.test(str);\n\nexport class EditorState {\n buf = '';\n cursor = 0; // index into buf\n hits: string[] = [];\n token = '';\n sel = 0; // highlighted hit\n menuOpen = false;\n prevEsc = false; // last key was Esc on an empty buffer → next Esc triggers double-Esc (jump-back)\n describe?: (hit: string) => string | undefined;\n private histIdx = -1; // -1 = editing fresh; ≥0 = browsing history[histIdx]\n private stash = ''; // the fresh buffer, saved while browsing history\n // Bracketed paste: content between ESC[200~/ESC[201~ is buffered as ONE unit, then either typed\n // verbatim (small, single-line) or collapsed to a `[Pasted text …]` placeholder that expands on submit.\n pasting = false;\n private pasteBuf = '';\n private pasteSeq = 0;\n readonly pastes = new Map<string, string>(); // placeholder → full pasted content\n\n // Vim modal editing (opt-in): undefined = emacs/readline keymap; else 'insert'|'normal'.\n vim?: 'insert' | 'normal';\n vimOp?: 'd' | 'c'; // pending operator awaiting a motion (dd/dw/cc)\n\n constructor(\n private suggest: Suggest,\n private history: string[] = [],\n private classifyPaste?: PasteClassifier,\n /** Called when a paste arrives with NO text — the image-Cmd-V signature (terminal fires an empty paste). */\n private onEmptyPaste?: () => { display: string; ref: string } | null,\n vimEnabled = false,\n ) { if (vimEnabled) this.vim = 'insert'; }\n\n /** The most-recent history entry that EXTENDS the current buffer — the inline ghost-suggestion suffix.\n * Empty unless the buffer is a single non-empty line with the cursor at its end and no menu/search open. */\n ghost(): string {\n if (!this.buf || this.cursor !== this.buf.length || this.menuOpen || this.searching || this.buf.includes('\\n')) return '';\n for (const h of this.history) if (h.length > this.buf.length && h.startsWith(this.buf)) return h.slice(this.buf.length);\n return '';\n }\n /** Accept the ghost suggestion (append its remainder). Returns false when there's nothing to accept. */\n acceptGhost(): boolean { const g = this.ghost(); if (!g) return false; this.insert(g); return true; }\n\n /** Collapse pastes that would break the single-line editor (multi-line) or flood it (≥ this many chars). */\n static readonly PASTE_INLINE_MAX = 800;\n\n beginPaste(): void { this.pasting = true; this.pasteBuf = ''; }\n /** Accumulate one character of an in-progress paste (no render/refresh per char — that's the whole point). */\n pasteChar(c: string): void { this.pasteBuf += c; }\n /** Actively grab a clipboard image and attach it (Ctrl-V; same hook as the empty-paste path). */\n grabClipboard(): boolean { const att = this.onEmptyPaste?.(); if (att) this.attach(att.display, att.ref); return !!att; }\n endPaste(): void {\n this.pasting = false;\n const text = this.pasteBuf;\n this.pasteBuf = '';\n // Empty paste = Cmd-V of an IMAGE (the terminal fires a paste event but has no text to send) → grab the clipboard image.\n if (!text) {\n const att = this.onEmptyPaste?.();\n if (att) this.attach(att.display, att.ref);\n return;\n }\n // Drag-dropped / pasted file path → attach (image/file). High-signal because it's a paste, not typed.\n const cls = this.classifyPaste?.(text);\n if (cls) { this.attach(cls.display, cls.ref); return; }\n const multiline = text.includes('\\n');\n if (multiline || text.length > EditorState.PASTE_INLINE_MAX) {\n const lines = text.split('\\n').length;\n const id = ++this.pasteSeq;\n const measure = multiline ? `+${lines} line${lines === 1 ? '' : 's'}` : `+${text.length} chars`;\n const placeholder = `[Pasted text #${id} ${measure}]`;\n this.pastes.set(placeholder, text);\n this.insert(placeholder); // a single safe, single-line token the user sees + can delete\n } else {\n this.insert(text); // small single-line paste: just type it in\n }\n }\n /** Insert an attachment placeholder (`[Image #N]` / `[File … #N]`) that expands to `ref` on submit. */\n attach(display: string, ref: string): void {\n const placeholder = `[${display} #${++this.pasteSeq}]`;\n this.pastes.set(placeholder, ref); // expands to an @ref the existing pipeline attaches/inlines\n this.insert(placeholder);\n }\n /** The line as the model should see it: paste placeholders expanded back to their full content. */\n expand(): string {\n let out = this.buf;\n for (const [ph, full] of this.pastes) if (out.includes(ph)) out = out.split(ph).join(full);\n return out;\n }\n\n /** Recompute suggestions from the line up to the cursor. */\n refresh(): void {\n const r = this.suggest(this.buf.slice(0, this.cursor));\n this.hits = r.hits;\n this.token = r.token;\n this.describe = r.describe;\n // Open the menu when there's something to choose — but not when the sole hit is already typed\n // in full (nothing left to complete), so Enter submits instead of re-accepting. EXCEPTION:\n // a fully-typed slash command keeps its row visible as confirmation it exists (CC parity) —\n // safe because Enter on an exact slash match accepts (a no-op) and submits in one press.\n const exact = r.hits.length === 1 && r.hits[0] === r.token;\n this.menuOpen = r.hits.length > 0 && (!exact || r.token.startsWith('/'));\n if (this.sel >= r.hits.length) this.sel = 0;\n }\n\n // ── Editor undo (Ctrl-_): snapshot before every mutation, pop to restore ──\n private undoStack: { buf: string; cursor: number }[] = [];\n private snapshot(): void {\n const top = this.undoStack[this.undoStack.length - 1];\n if (top?.buf === this.buf) return; // coalesce no-op states (e.g. cursor-only moves)\n this.undoStack.push({ buf: this.buf, cursor: this.cursor });\n if (this.undoStack.length > 200) this.undoStack.shift();\n }\n undo(): void {\n const p = this.undoStack.pop();\n if (!p) return;\n this.buf = p.buf;\n this.cursor = Math.min(p.cursor, p.buf.length);\n this.histIdx = -1;\n this.refresh();\n }\n\n // Code-point boundaries: cursor/delete ops must never split a surrogate pair (emoji = 2 code units;\n // a half-pair in the buffer reaches the model as mojibake). Steps are by code POINT (lean — ZWJ\n // families delete component-wise, which even many terminals do).\n private prevCp(i: number): number {\n if (i >= 2 && /[\\uDC00-\\uDFFF]/.test(this.buf[i - 1]) && /[\\uD800-\\uDBFF]/.test(this.buf[i - 2])) return i - 2;\n return Math.max(0, i - 1);\n }\n private nextCp(i: number): number {\n if (i <= this.buf.length - 2 && /[\\uD800-\\uDBFF]/.test(this.buf[i]) && /[\\uDC00-\\uDFFF]/.test(this.buf[i + 1])) return i + 2;\n return Math.min(this.buf.length, i + 1);\n }\n\n insert(s: string): void {\n this.snapshot();\n this.buf = this.buf.slice(0, this.cursor) + s + this.buf.slice(this.cursor);\n this.cursor += s.length;\n this.histIdx = -1;\n this.refresh();\n }\n backspace(): void {\n if (this.cursor === 0) return;\n this.snapshot();\n const start = this.prevCp(this.cursor);\n this.buf = this.buf.slice(0, start) + this.buf.slice(this.cursor);\n this.cursor = start;\n this.histIdx = -1;\n this.refresh();\n }\n del(): void {\n if (this.cursor >= this.buf.length) return;\n this.snapshot();\n this.buf = this.buf.slice(0, this.cursor) + this.buf.slice(this.nextCp(this.cursor));\n this.refresh();\n }\n left(): void { if (this.cursor > 0) this.cursor = this.prevCp(this.cursor); }\n right(): void { if (this.cursor < this.buf.length) this.cursor = this.nextCp(this.cursor); }\n home(): void { this.cursor = 0; }\n end(): void { this.cursor = this.buf.length; }\n\n // ── Word motion + kill ring (emacs/readline parity: Ctrl-W/U/K, Alt-B/F/D, Alt/Ctrl-arrows, Ctrl-Y) ──\n killed = ''; // last-killed text, re-inserted by Ctrl-Y (yank)\n private isWordChar(i: number): boolean { return i >= 0 && i < this.buf.length && !/\\s/.test(this.buf[i]); }\n /** Start of the whitespace-delimited word at/just before `i` (skip spaces, then the word). */\n private prevWord(i: number): number { let j = i; while (j > 0 && !this.isWordChar(j - 1)) j--; while (j > 0 && this.isWordChar(j - 1)) j--; return j; }\n /** End of the whitespace-delimited word at/just after `i` (skip spaces, then the word). */\n private nextWord(i: number): number { let j = i; while (j < this.buf.length && !this.isWordChar(j)) j++; while (j < this.buf.length && this.isWordChar(j)) j++; return j; }\n private cut(from: number, to: number): void { this.snapshot(); this.killed = this.buf.slice(from, to); this.buf = this.buf.slice(0, from) + this.buf.slice(to); this.cursor = from; this.histIdx = -1; this.refresh(); }\n\n wordLeft(): void { this.cursor = this.prevWord(this.cursor); }\n wordRight(): void { this.cursor = this.nextWord(this.cursor); }\n killWordBack(): void { if (this.cursor > 0) this.cut(this.prevWord(this.cursor), this.cursor); } // Ctrl-W / Alt-⌫\n killWordForward(): void { const e = this.nextWord(this.cursor); if (e > this.cursor) { const at = this.cursor; this.cut(this.cursor, e); this.cursor = at; } } // Alt-D\n killToStart(): void { if (this.cursor > 0) this.cut(0, this.cursor); } // Ctrl-U\n killToEnd(): void { if (this.cursor < this.buf.length) { const at = this.cursor; this.cut(this.cursor, this.buf.length); this.cursor = at; } } // Ctrl-K\n yank(): void { if (this.killed) this.insert(this.killed); } // Ctrl-Y\n\n // ── Reverse incremental history search (Ctrl-R) ──\n searching = false;\n searchQuery = '';\n searchMiss = false; // current query matches nothing (render shows \"failing\")\n private searchStash = ''; // buffer to restore if the search is cancelled\n private searchFrom = 0; // history index the next match scans from\n startSearch(): void { this.searching = true; this.searchQuery = ''; this.searchMiss = false; this.searchStash = this.buf; this.searchFrom = 0; this.closeMenu(); this.locate(); }\n /** Load the first history entry at/after `searchFrom` containing the query into the buffer (a live preview). */\n private locate(): void {\n const q = this.searchQuery.toLowerCase();\n for (let i = this.searchFrom; i < this.history.length; i++) {\n if (this.history[i].toLowerCase().includes(q)) { this.buf = this.history[i]; this.cursor = this.buf.length; this.searchFrom = i; this.searchMiss = false; return; }\n }\n this.searchMiss = this.searchQuery.length > 0; // nothing older matched — keep showing the last hit\n }\n searchType(c: string): void { this.searchQuery += c; this.searchFrom = 0; this.locate(); }\n searchBack(): void { this.searchQuery = this.searchQuery.slice(0, -1); this.searchFrom = 0; this.locate(); }\n searchOlder(): void { this.searchFrom += 1; this.locate(); } // Ctrl-R again → next older match\n endSearch(accept: boolean): void {\n this.searching = false; this.searchQuery = ''; this.searchMiss = false;\n if (!accept) { this.buf = this.searchStash; this.cursor = this.buf.length; } // cancel → restore the pre-search line\n this.histIdx = -1; this.refresh();\n }\n\n menuUp(): void { if (this.menuOpen && this.hits.length) this.sel = (this.sel - 1 + this.hits.length) % this.hits.length; }\n menuDown(): void { if (this.menuOpen && this.hits.length) this.sel = (this.sel + 1) % this.hits.length; }\n closeMenu(): void { this.menuOpen = false; this.hits = []; this.sel = 0; }\n\n /** Replace the trailing token with the highlighted hit; re-suggest (e.g. `@src/` opens its children). */\n accept(): boolean {\n if (!this.menuOpen || !this.hits.length) return false;\n const hit = this.hits[this.sel] ?? this.hits[0];\n const start = this.cursor - this.token.length;\n this.buf = this.buf.slice(0, start) + hit + this.buf.slice(this.cursor);\n this.cursor = start + hit.length;\n this.refresh();\n return true;\n }\n\n historyPrev(): void { // older\n if (!this.history.length) return;\n if (this.histIdx === -1) this.stash = this.buf;\n this.histIdx = Math.min(this.histIdx + 1, this.history.length - 1);\n this.buf = this.history[this.histIdx] ?? '';\n this.cursor = this.buf.length;\n this.closeMenu();\n }\n historyNext(): void { // newer\n if (this.histIdx === -1) return;\n this.histIdx--;\n this.buf = this.histIdx === -1 ? this.stash : (this.history[this.histIdx] ?? '');\n this.cursor = this.buf.length;\n this.closeMenu();\n }\n reset(): void { this.buf = ''; this.cursor = 0; this.histIdx = -1; this.pasting = false; this.pasteBuf = ''; this.searching = false; this.searchQuery = ''; this.pastes.clear(); this.closeMenu(); this.vimOp = undefined; if (this.vim) this.vim = 'insert'; }\n}\n\n/** Sentinel resolved by readLine on double-Esc (empty buffer): the REPL shows a jump-back picker.\n * A NUL-prefixed string so it can never collide with typed input. */\nexport const REWIND = '\\x00REWIND';\n\n/**\n * Vim NORMAL-mode keymap (baseline subset — CC-style modal editing). Handles motions/edits and returns\n * the REPL action; returns 'pass' to let the caller fall through to the shared keymap (Enter, Ctrl-C, …).\n * Scope (documented, not silently partial): motions h l 0 $ w b e · enter-insert i a A I o ·\n * edits x D C dd dw cc · Esc stays normal. No visual mode, no yank/put register, no counts, no `u` undo.\n */\nfunction applyVimNormal(s: EditorState, key: KeyEvent, str?: string): 'submit' | 'cancel' | 'eof' | 'none' | 'pass' {\n const k = key?.name;\n if (key?.ctrl || key?.meta) return 'pass'; // control/meta chords use the shared keymap\n if (k === 'return' || k === 'enter') return 'pass'; // submit/newline handled by shared keymap\n if (k === 'escape') { s.vimOp = undefined; return 'pass'; } // Esc → menu dismiss / clear / double-Esc\n const op = s.vimOp; s.vimOp = undefined;\n if (op) { // operator pending (d/c) → expect a motion\n if (str === 'd' && op === 'd') s.killToStart(), s.killToEnd(); // dd → kill whole line\n else if (str === 'c' && op === 'c') { s.killToStart(); s.killToEnd(); s.vim = 'insert'; } // cc → change line\n else if (str === 'w') { // dw / cw → kill the word + trailing spaces (vim-ish)\n s.killWordForward();\n while (s.buf[s.cursor] === ' ') s.del();\n if (op === 'c') s.vim = 'insert';\n }\n return 'none';\n }\n switch (str) {\n case 'i': s.vim = 'insert'; return 'none';\n case 'a': s.right(); s.vim = 'insert'; return 'none';\n case 'A': s.end(); s.vim = 'insert'; return 'none';\n case 'I': s.home(); s.vim = 'insert'; return 'none';\n case 'o': s.end(); s.insert('\\n'); s.vim = 'insert'; return 'none';\n case 'h': s.left(); return 'none';\n case 'l': s.right(); return 'none';\n case '0': s.home(); return 'none';\n case '$': s.end(); return 'none';\n case 'w': case 'e': s.wordRight(); return 'none';\n case 'b': s.wordLeft(); return 'none';\n case 'x': s.del(); return 'none';\n case 'D': s.killToEnd(); return 'none';\n case 'C': s.killToEnd(); s.vim = 'insert'; return 'none';\n case 'd': s.vimOp = 'd'; return 'none';\n case 'c': s.vimOp = 'c'; return 'none';\n }\n if (k === 'left') { s.left(); return 'none'; }\n if (k === 'right') { s.right(); return 'none'; }\n if (k === 'up') { s.historyPrev(); return 'none'; }\n if (k === 'down') { s.historyNext(); return 'none'; }\n if (k === 'backspace') { s.left(); return 'none'; } // normal-mode backspace just moves left (vim)\n return 'none'; // swallow other printables in normal mode\n}\n\n/** Apply one keypress to the state. Returns the resulting REPL action. */\nexport function applyKey(s: EditorState, key: KeyEvent, str?: string): 'submit' | 'cancel' | 'eof' | 'rewind' | 'none' {\n const k = key?.name;\n // Vim normal mode intercepts first (unless mid-paste/search, handled below). 'pass' falls through.\n if (s.vim === 'normal' && !s.pasting && !s.searching) {\n const r = applyVimNormal(s, key ?? {}, str);\n if (r !== 'pass') return r;\n }\n // Bracketed paste: swallow everything between the markers into one unit (Enter is a newline here, not submit).\n if (k === 'paste-start') { s.beginPaste(); return 'none'; }\n if (s.pasting) {\n if (k === 'paste-end') { s.endPaste(); return 'none'; }\n const c = (k === 'enter' || k === 'return') ? '\\n' : k === 'tab' ? '\\t' : (str ?? '');\n if (c) s.pasteChar(c);\n return 'none';\n }\n // Reverse incremental search (Ctrl-R) captures input until accepted (Enter/arrow) or cancelled (Esc/Ctrl-G/Ctrl-C).\n if (s.searching) {\n if (key?.ctrl && k === 'r') { s.searchOlder(); return 'none'; } // next older match\n if (key?.ctrl && k === 'c') { s.endSearch(false); return 'cancel'; }\n if ((key?.ctrl && k === 'g') || k === 'escape') { s.endSearch(false); return 'none'; } // cancel → restore line\n if (k === 'return' || k === 'enter') { s.endSearch(true); return 'none'; } // accept → keep editing (Enter again submits)\n if (k === 'backspace') { s.searchBack(); return 'none'; }\n if (!key?.ctrl && !key?.meta && isPrintable(str)) { s.searchType(str); return 'none'; }\n s.endSearch(true); // any other key (arrows, etc.) accepts the match, then falls through to act normally\n }\n if (key?.ctrl && k === 'r') return (s.startSearch(), 'none');\n const wasEsc = s.prevEsc; s.prevEsc = false; // any key clears the double-Esc arming; the escape case re-arms\n if (key?.ctrl && k === 'c') return 'cancel';\n if (key?.ctrl && k === 'd') return s.buf.length === 0 ? 'eof' : (s.del(), 'none');\n if (key?.ctrl && k === 'a') return (s.home(), 'none'); // line start\n if (key?.ctrl && k === 'e') return (s.end(), 'none'); // line end\n if (key?.ctrl && k === 'b') return (s.left(), 'none'); // char back (emacs)\n if (key?.ctrl && k === 'f') return (s.right(), 'none'); // char fwd (emacs)\n if (key?.ctrl && k === 'w') return (s.killWordBack(), 'none'); // kill word back\n if (key?.ctrl && k === 'u') return (s.killToStart(), 'none'); // kill to line start\n if (key?.ctrl && k === 'k') return (s.killToEnd(), 'none'); // kill to line end\n if (key?.ctrl && k === 'y') return (s.yank(), 'none'); // yank (paste last kill)\n // Ctrl-V: actively grab a clipboard image (CC parity). The Cmd-V empty-paste path only works on\n // terminals that fire a bracketed paste for an image-only clipboard — many fire nothing at all.\n if (key?.ctrl && k === 'v') { s.grabClipboard(); return 'none'; }\n if (str === '\\x1f') return (s.undo(), 'none'); // Ctrl-_ / Ctrl-7 → undo last edit\n // Alt/Meta word ops (also Ctrl+arrow on most terminals) — word motion + word kill.\n if (key?.meta && k === 'b') return (s.wordLeft(), 'none');\n if (key?.meta && k === 'f') return (s.wordRight(), 'none');\n if (key?.meta && k === 'd') return (s.killWordForward(), 'none');\n if (key?.meta && k === 'backspace') return (s.killWordBack(), 'none');\n if ((key?.meta || key?.ctrl) && k === 'left') return (s.wordLeft(), 'none');\n if ((key?.meta || key?.ctrl) && k === 'right') return (s.wordRight(), 'none');\n // Option/Alt+Enter (meta) or an ESC-prefixed CR/LF → newline, not submit (multi-line authoring, CC parity).\n if ((key?.meta && (k === 'return' || k === 'enter')) || str === '\\x1b\\r' || str === '\\x1b\\n') { s.insert('\\n'); return 'none'; }\n switch (k) {\n case 'return': case 'enter':\n if (s.menuOpen) {\n const isCmd = s.token.startsWith('/'); // slash-command → accept + run in one press (CC parity)\n s.accept();\n return isCmd ? 'submit' : 'none'; // @paths: accept + keep editing (Enter again submits)\n }\n // `\\` immediately before the cursor + Enter → continuation newline (works on every terminal, no meta needed).\n if (s.buf.slice(0, s.cursor).endsWith('\\\\')) { s.backspace(); s.insert('\\n'); return 'none'; }\n return 'submit';\n case 'tab': if (s.menuOpen) { s.accept(); return 'none'; } if (s.acceptGhost()) return 'none'; return 'none'; // menu accept, else accept history ghost\n case 'escape':\n if (s.menuOpen) { s.closeMenu(); return 'none'; } // open menu → dismiss it first\n if (s.vim === 'insert') { s.vim = 'normal'; return 'none'; } // vim: insert → normal (don't clear)\n if (s.vim === 'normal' && s.buf.length) return 'none'; // vim: Esc in normal is a no-op (never clears)\n if (s.buf.length) return 'cancel'; // non-empty line → clear it (Esc never exits the REPL)\n // A FAST double-tap arrives as ONE merged keypress (node holds a lone ESC for escapeCodeTimeout\n // waiting for a CSI tail). meta:true can't discriminate (a lone ESC sets it too) — the sequence can.\n if (wasEsc || key?.sequence === '\\x1b\\x1b') return 'rewind'; // double-Esc on an empty line → jump-back picker (CC parity)\n s.prevEsc = true; return 'none'; // first Esc on empty → arm double-Esc\n case 'up': s.menuOpen ? s.menuUp() : s.historyPrev(); return 'none';\n case 'down': s.menuOpen ? s.menuDown() : s.historyNext(); return 'none';\n case 'left': s.left(); return 'none';\n case 'right': if (s.cursor === s.buf.length && s.acceptGhost()) return 'none'; s.right(); return 'none'; // at EOL → accept ghost\n case 'home': s.home(); return 'none';\n case 'end': s.end(); return 'none';\n case 'backspace': s.backspace(); return 'none';\n case 'delete': s.del(); return 'none';\n }\n // printable input (ignore control/meta-prefixed keys)\n if (!key?.ctrl && !key?.meta && isPrintable(str)) { s.insert(str); return 'none'; }\n return 'none';\n}\n\nexport interface ReadOptions {\n /** May contain ANSI; its visible width sets the cursor column. A function makes the prompt LIVE —\n * re-evaluated on every repaint (e.g. flip to a '? yes/no' question prompt while an ask is pending;\n * pair with redrawNow() so the flip paints immediately). */\n prompt: string | (() => string);\n suggest: Suggest;\n history?: string[]; // most-recent-first\n maxVisible?: number; // menu rows shown at once (default 8)\n classifyPaste?: PasteClassifier; // turn pasted file paths into attachments (optional)\n /** Grab a clipboard image when a paste arrives empty (Cmd-V of an image fires a text-less paste). */\n onEmptyPaste?: () => { display: string; ref: string } | null;\n /** Pre-fill the buffer (e.g. a message recalled by double-Esc jump-back), ready to edit + resend. */\n initial?: string;\n /** Optional dim status footer (e.g. context% · cost) drawn under the input while typing; cleared on submit. */\n status?: () => string;\n /** Re-render the footer every N ms while waiting for input — lets `status()` animate live activity\n * (e.g. a duplex background task spinner) so a long-running worker never looks like a hang. */\n statusTickMs?: number;\n /** Modal editing: start the line in vim mode (insert, Esc→normal). Default emacs/readline keymap. */\n vimMode?: boolean;\n /** First Esc on an empty idle line — host-level claim (e.g. cancel running background tasks).\n * Return true if handled (prints its own notice); false falls through to double-Esc arming. */\n onEscapeIdle?: () => boolean;\n /** Shift+Tab → cycle permission posture; returns a label to surface (footer re-renders). */\n onCyclePosture?: () => string;\n /** Alt+T → cycle reasoning effort; returns a label to surface. */\n onToggleThinking?: () => string;\n /** Ctrl+O → toggle verbose output (full tool results vs preview); returns a label to surface. */\n onToggleVerbose?: () => string;\n /** Alt+P → open the model picker inline (buffer preserved); returns the new model id or null. */\n onPickModel?: () => Promise<string | null>;\n /** Called SYNCHRONOUSLY the instant a line submits, before the promise resolves — keys buffered\n * behind the Enter in the same input burst dispatch after this, so the host can claim them. */\n onSubmit?: () => void;\n /** Ctrl+S with text → push current input to stash queue. */\n onStash?: (text: string) => void;\n /** Ctrl+S on an empty buffer → pop the next stashed input into the editor. */\n onUnstash?: () => string | undefined;\n}\n\nexport interface LineEditor {\n /** Read one line. Resolves to the text, or null on EOF/Ctrl-D (or Ctrl-C at an empty prompt). */\n readLine(opts: ReadOptions): Promise<string | null>;\n /** Repaint the active prompt block at the CURRENT cursor position. For async writers (background\n * task results landing mid-prompt): clear your line, print your content, then call this — the\n * prompt + buffer + footer re-render cleanly below it. No-op when no read is active. */\n redrawNow(): void;\n /** Pause all prompt rendering (streamed stdout owns the terminal); clears the prompt block.\n * resume() repaints it fresh at the current cursor position. */\n suspend(): void;\n resume(): void;\n /** Externally resolve the pending readLine with null (same effect as Ctrl-D). No-op when idle. */\n abort(): void;\n}\n\n/** Build a line editor bound to a TTY output stream (stderr in the REPL). */\nexport function createLineEditor(out: NodeJS.WriteStream & { columns?: number }): LineEditor {\n const isTTY = !!out.isTTY && !!process.stdin.isTTY;\n const dim = (x: string) => `\\x1b[2m${x}\\x1b[0m`;\n const inverse = (x: string) => `\\x1b[7m${x}\\x1b[0m`;\n const COLOR: Record<InputMode['name'], (x: string) => string> = {\n bash: (x) => `\\x1b[31m${x}\\x1b[0m`, // red\n memory: (x) => `\\x1b[36m${x}\\x1b[0m`, // cyan\n };\n\n let curRow = 0; // rows the terminal cursor sits below the input's first line (multi-line redraws climb back up)\n let suspended = false; // streamed stdout owns the terminal; all renders no-op until resume()\n let activeRedraw: (() => void) | undefined; // set while a readLine is live (see LineEditor.redrawNow)\n let activeAbort: (() => void) | undefined; // set while a readLine is live; called by abort() to resolve with null\n\n // Multi-line aware: buf may hold real newlines (Opt-Enter / `\\`-continuation). The prompt sits on row 0;\n // each further buf line renders at col 0. We climb back to row 0 before clearing, then re-place the cursor.\n function render(s: EditorState, promptArg: string, maxVisible: number, status?: () => string): void {\n if (suspended) return; // a streaming writer owns the terminal — resume() repaints\n const cols = out.columns ?? 80;\n // In reverse-search the prompt becomes the search indicator (bash-style); the matched line follows it.\n // Else, if the buffer opens with a mode prefix (`!` bash / `#` memory), the prompt morphs to that mode's\n // colored indicator live as you type (CC parity) — cleared the instant the prefix is deleted.\n const mode = !s.searching ? inputMode(s.buf) : undefined;\n const vimTag = s.vim === 'normal' && !s.searching && !mode ? inverse(' N ') + ' ' : '';\n const prompt = s.searching\n ? dim(`(${s.searchMiss ? 'failing ' : ''}reverse-i-search)\\`${s.searchQuery}': `)\n : mode ? COLOR[mode.name](`${mode.pfx} ${mode.name} › `) : vimTag + promptArg;\n if (curRow > 0) out.write(`\\x1b[${curRow}A`); // climb to physical row 0 of the previous draw\n out.write('\\r\\x1b[J'); // …then clear it + everything below\n // Hard-wrap into physical rows so a line wider than the terminal can't desync the cursor (we own the\n // wrap points instead of trusting auto-wrap / the magic margin). Row 0 is prefixed by the prompt.\n // In a typed mode the prefix char lives in the indicator, so hide it from the editable buffer view\n // (cursor shifts left by the prefix width to stay aligned). The real s.buf is untouched — submit sees the `!`.\n const rawBuf = mode ? s.buf.slice(mode.pfx.length) : s.buf;\n const rawCursor = mode ? Math.max(0, s.cursor - mode.pfx.length) : s.cursor;\n // Bidi: reorder mixed Hebrew/Arabic+LTR into visual order for the TTY (no-op fast path for pure LTR).\n // OFF unless AGENTX_BIDI=1 — most terminals reorder RTL themselves, so app-side reorder double-flips it.\n const { text: viewBuf, cursor: viewCursor } = appBidi() ? applyBidi(rawBuf, rawCursor) : { text: rawBuf, cursor: rawCursor };\n const { rows, cursorRow, cursorCol } = wrapLayout(visibleWidth(prompt), viewBuf, viewCursor, cols);\n // Inline ghost-suggestion (history autocomplete): drawn dim AFTER the buffer on a single-row line that\n // still has room; the cursor is repositioned to its real column below, so the ghost trails the cursor.\n const ghost = !mode && !s.searching ? s.ghost() : '';\n const ghostFits = ghost && rows.length === 1 && visibleWidth(prompt) + viewBuf.length + ghost.length < cols;\n out.write(prompt + (rows[0] ?? '') + (ghostFits ? dim(ghost) : ''));\n for (let i = 1; i < rows.length; i++) out.write('\\r\\n' + rows[i]);\n const inputRows = rows.length - 1;\n let menuRows = 0;\n if (s.menuOpen && s.hits.length) {\n const win = windowAround(s.hits.length, s.sel, maxVisible);\n for (let i = win.start; i < win.end; i++) {\n const hit = s.hits[i];\n const d = s.describe?.(hit);\n let label = ` ${hit}${d ? ' ' + d : ''}`;\n if (visibleWidth(label) > cols - 1) label = label.slice(0, cols - 2) + '…'; // keep each label to one physical row\n out.write('\\r\\n' + (i === s.sel ? inverse(label) : dim(label)));\n menuRows++;\n }\n }\n // Status footer (context/cost) — dim, below everything; multi-line capable (`\\n`-separated, e.g. one\n // stacked row per running background task). Never drawn on the commit render (finish passes no\n // `status`), so it doesn't freeze into the scrollback after the line is submitted.\n let footerRows = 0;\n const footer = status?.();\n if (footer) {\n for (const line of footer.split('\\n')) {\n const f = visibleWidth(line) > cols - 1 ? line.slice(0, cols - 2) + '…' : line;\n out.write('\\r\\n' + dim(f));\n footerRows++;\n }\n }\n const up = inputRows + menuRows + footerRows - cursorRow; // climb from the bottom of the draw to the cursor's physical row\n if (up > 0) out.write(`\\x1b[${up}A`);\n out.write('\\r'); // col 0\n if (cursorCol > 0) out.write(`\\x1b[${cursorCol}C`); // → cursor column\n curRow = cursorRow;\n }\n\n /** Ctrl-X Ctrl-E: hand the buffer to $VISUAL/$EDITOR on a temp file, reload it on a clean exit.\n * Raw mode + bracketed paste are suspended around the child so the editor owns the terminal. */\n function externalEdit(s: EditorState): void {\n const spec = process.env.VISUAL || process.env.EDITOR || 'vi';\n const [cmd, ...cargs] = spec.split(' ').filter(Boolean); // honor EDITOR=\"code -w\" style values\n const file = join(tmpdir(), `agentx-edit-${process.pid}-${Date.now()}.md`);\n try {\n writeFileSync(file, s.buf);\n process.stdin.setRawMode(false);\n out.write('\\x1b[?2004l');\n const r = spawnSync(cmd, [...cargs, file], { stdio: 'inherit' });\n if (r.status === 0) {\n const text = readFileSync(file, 'utf8').replace(/\\n$/, '');\n s.reset();\n if (text) s.insert(text);\n }\n } catch { /* editor missing/failed — keep the buffer untouched */ }\n finally {\n try { unlinkSync(file); } catch { /* already gone */ }\n process.stdin.setRawMode(true);\n out.write('\\x1b[?2004h');\n }\n }\n\n async function readLine(opts: ReadOptions): Promise<string | null> {\n const maxVisible = opts.maxVisible ?? 8;\n // Non-TTY (piped/headless): plain line read, no menu.\n if (!isTTY) return readPlainLine();\n\n const s = new EditorState(opts.suggest, opts.history ?? [], opts.classifyPaste, opts.onEmptyPaste, opts.vimMode);\n curRow = 0; // fresh draw for this read\n if (opts.initial) s.insert(opts.initial); // recalled message — newlines preserved (multi-line editor)\n s.refresh();\n emitKeypressEvents(keyInput);\n keyInput.setRawMode(true);\n keyInput.resume();\n out.write('\\x1b[?2004h'); // enable bracketed paste — terminal wraps pasted bytes in ESC[200~ … ESC[201~\n const promptOf = () => (typeof opts.prompt === 'function' ? opts.prompt() : opts.prompt);\n render(s, promptOf(), maxVisible, opts.status);\n\n // Terminal resized: our cached row count (curRow) is now stale vs the new width. Reset it and redraw —\n // render() re-reads out.columns live, so the new wrap layout is correct; clearing from row 0 avoids garbage.\n const onResize = () => { curRow = 0; render(s, promptOf(), maxVisible, opts.status); };\n // Async interjection support: an external writer cleared its line and printed content — the old\n // draw is gone, so repaint the whole block fresh from wherever the cursor now sits.\n activeRedraw = () => { curRow = 0; render(s, promptOf(), maxVisible, opts.status); };\n process.on('SIGWINCH', onResize);\n\n return new Promise<string | null>((resolve) => {\n activeAbort = () => { finish(); resolve(null); };\n const redraw = () => render(s, promptOf(), maxVisible, opts.status);\n // Live footer ticker: animates status() (e.g. duplex task spinner) while idle at the prompt.\n // Paused mid-paste (no per-chunk repaints); cleared in finish().\n // Tick re-renders ONLY when the footer text actually changed — a full prompt-block repaint\n // every second reads as flicker (climb + clear + redraw) for a static footer.\n let lastStatus = opts.status?.() ?? '';\n const ticker = opts.statusTickMs && opts.status ? setInterval(() => {\n if (s.pasting) return;\n const cur = opts.status!();\n if (cur === lastStatus) return;\n lastStatus = cur;\n redraw();\n }, opts.statusTickMs) : undefined;\n let chordCtrlX = false; // Ctrl-X arms a readline-style chord (Ctrl-X Ctrl-E → external editor)\n const onKey = (str: string | undefined, key: KeyEvent) => {\n // Ctrl-L: clear the scrollback + screen and redraw the current line at the top (handled here — it writes to the TTY).\n if (key?.ctrl && key.name === 'l') { out.write('\\x1b[2J\\x1b[3J\\x1b[H'); curRow = 0; redraw(); return; }\n // Ctrl-X Ctrl-E: edit the buffer in $VISUAL/$EDITOR (readline parity); any other key disarms.\n // Never arms mid-paste: a literal 0x18 byte inside pasted content must pass through verbatim.\n if (key?.ctrl && key.name === 'x' && !s.pasting) { chordCtrlX = true; return; }\n if (chordCtrlX) {\n chordCtrlX = false;\n if (key?.ctrl && key.name === 'e') { externalEdit(s); curRow = 0; redraw(); return; }\n }\n // Global meta-key shortcuts (CC parity) — act immediately, buffer preserved, no submit:\n if (key?.name === 'tab' && key.shift && opts.onCyclePosture) { opts.onCyclePosture(); redraw(); return; } // Shift+Tab → permission posture\n if (key?.meta && key.name === 't' && opts.onToggleThinking) { opts.onToggleThinking(); redraw(); return; } // Alt+T → reasoning effort\n if (key?.ctrl && key.name === 'o' && opts.onToggleVerbose) { opts.onToggleVerbose(); redraw(); return; } // Ctrl+O → verbose output (CC parity)\n if ((key?.ctrl && key.name === 's') || (key?.meta && key.name === 's')) { // Ctrl+S / Alt+S → stash current / pop stashed\n if (s.buf.trim() && opts.onStash) { opts.onStash(s.expand()); s.reset(); s.refresh(); redraw(); }\n else if (!s.buf.length && opts.onUnstash) { const text = opts.onUnstash(); if (text) { s.insert(text); redraw(); } }\n return;\n }\n // Esc on an empty idle line: let the host claim it first (duplex: cancel running background\n // tasks) — returns true when handled, so it doesn't arm the double-Esc rewind.\n if (key?.name === 'escape' && !s.buf.length && !s.menuOpen && !s.searching && !s.prevEsc && opts.onEscapeIdle?.()) { curRow = 0; redraw(); return; }\n if (key?.meta && key.name === 'p' && opts.onPickModel) { // Alt+P → model picker (inline)\n keyInput.off('keypress', onKey); // hand stdin to selectMenu, then take it back + redraw in place\n void opts.onPickModel().finally(() => { keyInput.on('keypress', onKey); curRow = 0; redraw(); });\n return;\n }\n const action = applyKey(s, key ?? {}, str);\n if (action === 'submit') { finish(); opts.onSubmit?.(); return resolve(s.expand()); } // expand paste placeholders for the model\n if (action === 'eof') { finish(); return resolve(null); }\n if (action === 'rewind') { finish(); return resolve(REWIND); } // double-Esc → REPL shows the jump-back picker\n if (action === 'cancel') {\n if (s.buf.length === 0) { finish(); return resolve(null); }\n s.reset(); s.refresh(); render(s, promptOf(), maxVisible, opts.status); return; // clear the line, keep going\n }\n if (s.pasting) return; // mid-paste: accumulate silently, then render once on paste-end (no per-char flood)\n render(s, promptOf(), maxVisible, opts.status);\n };\n const finish = () => {\n activeRedraw = undefined;\n activeAbort = undefined;\n if (ticker) clearInterval(ticker);\n keyInput.off('keypress', onKey);\n process.removeListener('SIGWINCH', onResize);\n // bracketed paste stays ON between reads — a paste landing MID-TURN must still arrive as one\n // unit (raw \\r fragments would auto-queue as separate turns). The REPL disables it on exit.\n s.closeMenu();\n if (suspended) { out.write('\\r\\n'); return; } // a stream owns the terminal — no commit paint\n // Commit paint: replace the hard-wrapped editing block with a WORD-wrapped echo for the\n // scrollback. The live editor wraps at the raw column edge (it owns the cursor math); the\n // submitted line shouldn't read mid-word in the transcript forever.\n if (curRow > 0) out.write(`\\x1b[${curRow}A`);\n out.write('\\r\\x1b[J');\n const cols = out.columns ?? 80;\n const mode = inputMode(s.buf);\n const prompt = mode ? COLOR[mode.name](`${mode.pfx} ${mode.name} › `) : promptOf();\n const raw = mode ? s.buf.slice(mode.pfx.length) : s.buf;\n const lines = appBidi() ? raw.split('\\n').map((l) => applyBidi(l, 0).text) : raw.split('\\n');\n out.write([prompt + lines[0], ...lines.slice(1)].map((l) => wrapAnsi(l, cols, ' ')).join('\\r\\n') + '\\r\\n');\n curRow = 0;\n };\n keyInput.on('keypress', onKey);\n });\n }\n\n return {\n readLine,\n redrawNow: () => activeRedraw?.(),\n suspend: () => {\n if (suspended) return;\n suspended = true;\n if (curRow > 0) out.write(`\\x1b[${curRow}A`);\n out.write('\\r\\x1b[J'); // clear the prompt block — the stream renders into a clean area\n curRow = 0;\n },\n resume: () => {\n if (!suspended) return;\n suspended = false;\n curRow = 0;\n activeRedraw?.();\n },\n abort: () => activeAbort?.(),\n };\n}\n\nexport interface SelectItem { label: string; value: string; desc?: string; children?: SelectItem[] }\nexport interface SelectOptions { title?: string; items: SelectItem[]; current?: string; maxVisible?: number; filterable?: boolean }\n\n/**\n * Standalone single-choice picker (raw-mode): renders a scrollable list, ↑/↓ to move, ⏎ to choose,\n * Esc/Ctrl-C to cancel. Items with `children` support drill-down: → expands, ← / Esc collapses.\n * When `filterable`, typing narrows the list (fuzzy match on label+value). Backspace shrinks the filter.\n */\nlet menusOpen = 0;\n/** True while a selectMenu picker owns the keyboard (the in-turn type-ahead handler must yield). */\nexport const isMenuActive = (): boolean => menusOpen > 0;\n\nexport function selectMenu(out: NodeJS.WriteStream & { columns?: number }, opts: SelectOptions): Promise<string | null> {\n if (!out.isTTY || !process.stdin.isTTY || !opts.items.length) return Promise.resolve(null);\n const maxVisible = opts.maxVisible ?? 10;\n const dim = (x: string) => `\\x1b[2m${x}\\x1b[0m`;\n const inverse = (x: string) => `\\x1b[7m${x}\\x1b[0m`;\n const cyan = (x: string) => `\\x1b[36m${x}\\x1b[0m`;\n const yellow = (x: string) => `\\x1b[33m${x}\\x1b[0m`;\n\n let items = opts.items;\n let unfiltered = items; // current level's full list (before filtering)\n let sel = Math.max(0, items.findIndex((i) => i.value === opts.current));\n const stack: { unfiltered: SelectItem[]; sel: number; title?: string; filter: string }[] = [];\n let title = opts.title;\n let filter = '';\n let prevLines = 0;\n\n const applyFilter = () => {\n if (!filter) { items = unfiltered; }\n else {\n const lc = filter.toLowerCase();\n items = unfiltered.filter((it) => {\n const hay = (it.label + ' ' + it.value + ' ' + (it.desc ?? '')).toLowerCase();\n return lc.split('').every((ch) => hay.includes(ch)) && hay.includes(lc[0]);\n });\n }\n sel = Math.min(sel, Math.max(0, items.length - 1));\n };\n\n const draw = () => {\n if (prevLines > 1) out.write(`\\x1b[${prevLines - 1}A`);\n out.write('\\r\\x1b[J');\n prevLines = 0;\n const cols = (out.columns ?? 80) - 1;\n const line = (s: string) => (visibleWidth(s) > cols ? s.slice(0, cols - 1) + '…' : s);\n const heading = (title ?? '') + (filter ? ' ' + yellow('/' + filter) : '');\n if (heading) { const rows = heading.split('\\n'); out.write(rows.map((h) => dim(line(h))).join('\\n') + '\\n'); prevLines += rows.length; }\n if (!items.length) {\n out.write(dim(' (no matches)') + '\\n'); prevLines++;\n } else {\n const win = windowAround(items.length, sel, maxVisible);\n for (let i = win.start; i < win.end; i++) {\n const it = items[i];\n const arrow = it.children?.length ? cyan(' →') : '';\n const txt = line(` ${it.value === opts.current ? '●' : ' '} ${it.label}${arrow}${it.desc ? ' ' + dim(it.desc) : ''}`);\n out.write((i === sel ? inverse(txt) : txt) + '\\n');\n prevLines++;\n }\n }\n const more = items.length > maxVisible ? ` · ${sel + 1}/${items.length}` : '';\n const back = stack.length ? '← back · ' : '';\n const filterHint = opts.filterable && !filter ? 'type to filter · ' : '';\n out.write(dim(` ${filterHint}↑/↓ select · ${back}⏎ choose · esc cancel${more}`));\n prevLines++;\n };\n\n return new Promise<string | null>((resolve) => {\n const wasRaw = !!keyInput.isRaw;\n menusOpen++;\n emitKeypressEvents(keyInput);\n keyInput.setRawMode(true);\n keyInput.resume();\n draw();\n const finish = (val: string | null) => {\n menusOpen--;\n keyInput.off('keypress', onKey);\n if (prevLines > 1) out.write(`\\x1b[${prevLines - 1}A`);\n out.write('\\r\\x1b[J');\n if (!wasRaw) { try { keyInput.setRawMode(false); } catch { /* not a tty */ } }\n resolve(val);\n };\n const drillIn = () => {\n const it = items[sel];\n if (!it.children?.length) return;\n stack.push({ unfiltered, sel, title, filter });\n title = it.label;\n filter = '';\n const isGroup = it.value.startsWith('__');\n unfiltered = isGroup ? it.children : [{ label: it.label, value: it.value, desc: 'latest' }, ...it.children];\n items = unfiltered;\n sel = Math.max(0, items.findIndex((i) => i.value === opts.current));\n draw();\n };\n const drillOut = () => {\n if (filter) { filter = ''; applyFilter(); draw(); return true; }\n if (!stack.length) return false;\n const prev = stack.pop()!;\n unfiltered = prev.unfiltered; sel = prev.sel; title = prev.title; filter = prev.filter;\n applyFilter();\n draw();\n return true;\n };\n const onKey = (_s: string | undefined, key: KeyEvent) => {\n const k = key?.name;\n if (k === 'up') { sel = (sel - 1 + items.length) % items.length; draw(); }\n else if (k === 'down') { sel = (sel + 1) % items.length; draw(); }\n else if (k === 'right') drillIn();\n else if (k === 'left') drillOut();\n else if (k === 'return' || k === 'enter') { if (items.length) { const it = items[sel]; if (it.children?.length) drillIn(); else finish(it.value); } }\n else if (k === 'escape' || (key?.ctrl && (k === 'c' || k === 'd'))) { if (!drillOut()) finish(null); }\n else if (k === 'backspace' && opts.filterable && filter) { filter = filter.slice(0, -1); applyFilter(); draw(); }\n else if (opts.filterable && !key?.ctrl && !key?.meta && isPrintable(_s)) { filter += _s; applyFilter(); draw(); }\n };\n keyInput.on('keypress', onKey);\n });\n}\n\n/**\n * Lay a buffer out into PHYSICAL terminal rows, hard-wrapping any logical line wider than `cols` so the\n * editor controls the wrap points (auto-wrap + the \"magic margin\" at exactly `cols` would otherwise desync\n * the cursor math). `promptW` = visible columns the prompt occupies on row 0; wrapped/continuation rows start\n * at col 0. Returns the plain-text rows (caller prefixes row 0 with the real prompt) + the cursor's physical\n * (row, col). buf is plain text (no ANSI); `\\n` starts a new logical line.\n */\n/** A live input mode entered by a buffer prefix (CC parity): `!`→bash, `#`→memory. */\nexport interface InputMode { pfx: string; name: 'bash' | 'memory' }\nconst INPUT_MODES: InputMode[] = [\n { pfx: '!', name: 'bash' },\n { pfx: '#', name: 'memory' },\n];\n/** The input mode a buffer is in by its leading prefix, or undefined for a normal prompt. */\nexport function inputMode(buf: string): InputMode | undefined {\n return INPUT_MODES.find((m) => buf.startsWith(m.pfx));\n}\n\nexport function wrapLayout(promptW: number, buf: string, cursor: number, cols: number): { rows: string[]; cursorRow: number; cursorCol: number } {\n const width = Math.max(1, cols);\n const rows: string[] = [];\n let line = ''; // chars accumulated for the current physical row\n let r = 0, col = promptW; // current physical row index + column as we lay chars out\n let cursorRow = 0, cursorCol = promptW;\n const pushRow = () => { rows.push(line); line = ''; };\n // Iterate by code point; col advances by DISPLAY width (CJK/emoji = 2) so the cursor math matches\n // what the terminal actually renders. `i` stays a code-unit index (what EditorState.cursor uses).\n for (let i = 0; i <= buf.length;) {\n const cp = i < buf.length ? buf.codePointAt(i)! : -1;\n const ch = cp >= 0 ? String.fromCodePoint(cp) : '';\n const w = ch && ch !== '\\n' ? cpWidth(cp) : 0;\n if (w === 2 && col + w > width && col > 0) { pushRow(); r++; col = 0; } // wide char would straddle the edge → wrap BEFORE it (and before placing the cursor on it)\n if (i === cursor) { cursorRow = r; cursorCol = col; } // where char `i` lands = the cursor position\n if (i === buf.length) break;\n if (ch === '\\n') { pushRow(); r++; col = 0; i++; continue; }\n line += ch; col += w;\n if (col >= width) { pushRow(); r++; col = 0; } // row full → wrap to the next physical row at col 0\n i += ch.length;\n }\n pushRow(); // final (possibly empty) row\n return { rows, cursorRow, cursorCol };\n}\n\n/** Visible window [start,end) of `count` items centered enough to keep `sel` in view. */\nexport function windowAround(count: number, sel: number, max: number): { start: number; end: number } {\n if (count <= max) return { start: 0, end: count };\n let start = Math.max(0, sel - Math.floor(max / 2));\n if (start + max > count) start = count - max;\n return { start, end: start + max };\n}\n\n/** Fallback line read for non-TTY stdin (pipes): one line, resolves null on EOF. */\n// Leftover bytes survive across calls so a single piped chunk (`a\\nb\\nc\\n`) yields one line per call\n// instead of dropping everything after the first newline. This is what makes pipe-driven e2e work.\nlet plainBuf = '';\nlet plainEnded = false;\nfunction readPlainLine(): Promise<string | null> {\n return new Promise((resolve) => {\n const emit = (): boolean => {\n const nl = plainBuf.indexOf('\\n');\n if (nl >= 0) { const line = plainBuf.slice(0, nl); plainBuf = plainBuf.slice(nl + 1); resolve(line); return true; }\n if (plainEnded) { const rest = plainBuf; plainBuf = ''; resolve(rest.length ? rest : null); return true; }\n return false;\n };\n const onData = (d: Buffer) => { plainBuf += d.toString('utf8'); if (emit()) cleanup(); };\n const onEnd = () => { plainEnded = true; emit(); cleanup(); };\n const cleanup = () => { process.stdin.off('data', onData); process.stdin.off('end', onEnd); process.stdin.pause(); };\n if (emit()) return; // a full line was already buffered from a prior chunk — no need to read more\n process.stdin.resume();\n process.stdin.on('data', onData);\n process.stdin.on('end', onEnd);\n });\n}\n","/**\n * Minimal Unicode Bidirectional Algorithm (UAX #9) for terminal display of mixed LTR/RTL text.\n *\n * The line editor stores text in LOGICAL order (first-typed char first) — correct for submit. But a raw-mode\n * TTY paints code units left-to-right, so a Hebrew/Arabic run shows reversed (\"backwards\"). This module\n * reorders a logical line into VISUAL order for rendering and returns a logical→visual caret map so the\n * cursor still lands at the right column.\n *\n * Scope: the IMPLICIT algorithm (rules W1–W7, N1–N2, I1–I2, L2) over a single embedding level — i.e. real\n * mixed Hebrew/Arabic/Latin/number input. Explicit embedding/override/isolate format chars (RLE/LRO/RLI…)\n * are essentially never typed into a chat CLI, so they're treated as neutral. Indices are UTF-16 code units\n * to match the editor's cursor space (BMP scripts like Hebrew are one unit each).\n */\n\ntype T = 'L' | 'R' | 'AL' | 'EN' | 'AN' | 'ES' | 'ET' | 'CS' | 'NSM' | 'WS' | 'ON';\n\n/** Quick test: does the string contain any strong-RTL character? If not, skip bidi entirely (LTR fast path).\n * Ranges mirror the R/AL set in classify() exactly: Hebrew, Arabic (+ supplements), and their presentation forms. */\nconst RTL_RE = /[\\u0590-\\u05ff\\u0600-\\u06ff\\u0750-\\u077f\\u08a0-\\u08ff\\ufb1d-\\ufdff\\ufe70-\\ufeff]/;\nexport const needsBidi = (s: string): boolean => RTL_RE.test(s);\n\n/** Whether the APP should reorder RTL into visual order before writing to the TTY.\n *\n * Terminal bidi support is inconsistent: Apple's Terminal.app reorders RTL itself, so app-side reordering\n * would DOUBLE-flip it (Hebrew shows reversed). But iTerm2, VS Code's terminal, and most Linux terminals\n * (gnome-terminal, xterm, alacritty, kitty) do NOT reorder — there the app MUST reorder or RTL shows\n * reversed. So the default is auto: OFF on a terminal known to do its own bidi, ON everywhere else.\n * `AGENTX_BIDI=1|0` (or true/false) forces it for terminals we guess wrong. */\nconst BIDI_TERMINALS = new Set(['Apple_Terminal']); // TERM_PROGRAM values that do their own RTL reordering\nexport const appBidi = (): boolean => {\n const env = process.env.AGENTX_BIDI?.toLowerCase();\n if (env === '1' || env === 'true' || env === 'on') return true;\n if (env === '0' || env === 'false' || env === 'off') return false;\n return !BIDI_TERMINALS.has(process.env.TERM_PROGRAM ?? '');\n};\n\n/** Bidi class of a single UTF-16 code unit (subset sufficient for typed input). */\nfunction classify(c: number): T {\n if (c >= 0x0591 && c <= 0x05bd) return 'NSM'; // Hebrew points (niqqud / cantillation)\n if (c === 0x05bf || c === 0x05c1 || c === 0x05c2 || c === 0x05c4 || c === 0x05c5 || c === 0x05c7) return 'NSM';\n if ((c >= 0x0590 && c <= 0x05ff) || (c >= 0xfb1d && c <= 0xfb4f)) return 'R'; // Hebrew letters + presentation\n if ((c >= 0x0660 && c <= 0x0669) || (c >= 0x06f0 && c <= 0x06f9)) return 'AN'; // Arabic-Indic digits\n if ((c >= 0x0600 && c <= 0x06ff) || (c >= 0x0750 && c <= 0x077f) || (c >= 0x08a0 && c <= 0x08ff) ||\n (c >= 0xfb50 && c <= 0xfdff) || (c >= 0xfe70 && c <= 0xfeff)) return 'AL'; // Arabic letters\n if (c >= 0x0030 && c <= 0x0039) return 'EN'; // ASCII digits\n if (c === 0x002b || c === 0x002d) return 'ES'; // + -\n if (c === 0x0023 || c === 0x0024 || c === 0x0025 || (c >= 0x00a2 && c <= 0x00a5)) return 'ET'; // # $ % ¢£¤¥\n if (c === 0x002c || c === 0x002e || c === 0x003a || c === 0x002f || c === 0x00a0) return 'CS'; // , . : / NBSP\n if (c === 0x0020 || c === 0x0009 || c === 0x000b || c === 0x000c) return 'WS';\n if ((c >= 0x0021 && c <= 0x002f) || (c >= 0x003a && c <= 0x0040) ||\n (c >= 0x005b && c <= 0x0060) || (c >= 0x007b && c <= 0x007e)) return 'ON'; // ASCII punctuation/brackets\n return 'L'; // Latin & everything else → strong LTR\n}\n\n/** P2/P3: paragraph base level from the first strong (L → 0, R/AL → 1; default LTR). */\nfunction baseLevel(types: T[]): number {\n for (const t of types) { if (t === 'L') return 0; if (t === 'R' || t === 'AL') return 1; }\n return 0;\n}\n\n/** Rules W1–W7: resolve weak types within the single base-level run (sos = eos = base direction). */\nfunction resolveWeak(t: T[], baseDir: 'L' | 'R'): T[] {\n const n = t.length;\n for (let i = 0; i < n; i++) if (t[i] === 'NSM') t[i] = i > 0 ? t[i - 1] : baseDir; // W1\n for (let i = 0; i < n; i++) if (t[i] === 'EN') { // W2\n for (let j = i - 1; j >= 0; j--) if (t[j] === 'L' || t[j] === 'R' || t[j] === 'AL') { if (t[j] === 'AL') t[i] = 'AN'; break; }\n }\n for (let i = 0; i < n; i++) if (t[i] === 'AL') t[i] = 'R'; // W3\n for (let i = 1; i < n - 1; i++) { // W4\n if (t[i] === 'ES' && t[i - 1] === 'EN' && t[i + 1] === 'EN') t[i] = 'EN';\n else if (t[i] === 'CS' && t[i - 1] === 'EN' && t[i + 1] === 'EN') t[i] = 'EN';\n else if (t[i] === 'CS' && t[i - 1] === 'AN' && t[i + 1] === 'AN') t[i] = 'AN';\n }\n for (let i = 0; i < n; i++) if (t[i] === 'ET') { // W5\n let j = i; while (j < n && t[j] === 'ET') j++;\n if ((i > 0 && t[i - 1] === 'EN') || (j < n && t[j] === 'EN')) for (let k = i; k < j; k++) t[k] = 'EN';\n i = j - 1;\n }\n for (let i = 0; i < n; i++) if (t[i] === 'ES' || t[i] === 'ET' || t[i] === 'CS') t[i] = 'ON'; // W6\n for (let i = 0; i < n; i++) if (t[i] === 'EN') { // W7\n let strong: T = baseDir;\n for (let j = i - 1; j >= 0; j--) if (t[j] === 'L' || t[j] === 'R') { strong = t[j]; break; }\n if (strong === 'L') t[i] = 'L';\n }\n return t;\n}\n\n/** Rules N1–N2: resolve neutrals (NI) — same-direction surround → that direction (EN/AN count as R), else base. */\nfunction resolveNeutral(t: T[], baseDir: 'L' | 'R'): T[] {\n const n = t.length;\n const strong = (x: T): 'L' | 'R' | undefined => (x === 'L' ? 'L' : x === 'R' || x === 'EN' || x === 'AN' ? 'R' : undefined);\n for (let i = 0; i < n; i++) if (t[i] === 'ON' || t[i] === 'WS') {\n let j = i; while (j < n && (t[j] === 'ON' || t[j] === 'WS')) j++;\n const prev = i > 0 ? strong(t[i - 1]) : baseDir;\n const next = j < n ? strong(t[j]) : baseDir;\n const dir = prev && next && prev === next ? prev : baseDir; // N1 else N2\n for (let k = i; k < j; k++) t[k] = dir;\n i = j - 1;\n }\n return t;\n}\n\n/** Rules I1–I2: implicit embedding level per resolved type. */\nfunction implicitLevels(t: T[], e: number): number[] {\n return t.map((x) => e % 2 === 0\n ? (x === 'R' ? e + 1 : x === 'EN' || x === 'AN' ? e + 2 : e) // even base\n : (x === 'L' || x === 'EN' || x === 'AN' ? e + 1 : e)); // odd base\n}\n\n/** Rule L2: reverse contiguous runs from the highest level down to the lowest odd level. */\nfunction reorder(levels: number[]): number[] {\n const n = levels.length;\n const order = Array.from({ length: n }, (_, i) => i); // order[visualPos] = logicalIndex\n let highest = 0, lowestOdd = Infinity;\n for (const l of levels) { if (l > highest) highest = l; if (l % 2 && l < lowestOdd) lowestOdd = l; }\n for (let lvl = highest; lvl >= lowestOdd; lvl--) {\n let i = 0;\n while (i < n) {\n if (levels[i] >= lvl) {\n let j = i; while (j < n && levels[j] >= lvl) j++;\n for (let a = i, b = j - 1; a < b; a++, b--) { const tmp = order[a]; order[a] = order[b]; order[b] = tmp; }\n i = j;\n } else i++;\n }\n }\n return order;\n}\n\nexport interface BidiLine {\n visual: string; // the line reordered into visual (display) order\n caret: number[]; // caret[logicalIndex] = visual column (length len+1, includes end-of-line)\n}\n\n/** Reorder ONE logical line (no newlines) into visual order + a logical→visual caret map. */\nexport function bidiLine(line: string): BidiLine {\n const n = line.length;\n if (n === 0) return { visual: '', caret: [0] };\n const types = Array.from({ length: n }, (_, i) => classify(line.charCodeAt(i)));\n const e = baseLevel(types);\n const baseDir: 'L' | 'R' = e % 2 ? 'R' : 'L';\n const levels = implicitLevels(resolveNeutral(resolveWeak(types, baseDir), baseDir), e);\n const order = reorder(levels);\n const logToVis = new Array<number>(n);\n for (let v = 0; v < n; v++) logToVis[order[v]] = v;\n // Caret sits on the leading visual edge of a char whose run is LTR, the trailing edge if RTL.\n const caret = new Array<number>(n + 1);\n for (let c = 0; c < n; c++) caret[c] = levels[c] % 2 === 0 ? logToVis[c] : logToVis[c] + 1;\n caret[n] = levels[n - 1] % 2 === 0 ? logToVis[n - 1] + 1 : logToVis[n - 1];\n const visual = order.map((li) => line[li]).join('');\n return { visual, caret };\n}\n\n/**\n * Reorder a (possibly multi-line) logical buffer into visual order for display, mapping the logical cursor\n * to its visual column. Newlines are paragraph separators (each line reordered independently). Pure-LTR\n * buffers are returned untouched (fast path) so non-RTL behavior is byte-for-byte unchanged.\n */\nexport function applyBidi(buf: string, cursor: number): { text: string; cursor: number } {\n if (!needsBidi(buf)) return { text: buf, cursor };\n const lines = buf.split('\\n');\n const out: string[] = [];\n let visCursor = cursor, logBase = 0, visBase = 0;\n for (const line of lines) {\n const { visual, caret } = bidiLine(line);\n out.push(visual);\n if (cursor >= logBase && cursor <= logBase + line.length) visCursor = visBase + caret[cursor - logBase];\n logBase += line.length + 1; // + '\\n'\n visBase += visual.length + 1;\n }\n return { text: out.join('\\n'), cursor: visCursor };\n}\n","/**\n * Conservative terminal markdown rendering for streamed assistant text. It is LINE-BUFFERED: deltas are\n * accumulated until a newline, then each COMPLETE line is rendered — so an inline span (`**bold**`,\n * `` `code` ``, `[link](url)`) can never be mangled by a chunk boundary that splits it. A safe subset is\n * transformed: headings, **bold**, `code`, `[links](url)`, fenced code blocks, `---` rules, and GFM tables.\n *\n * Tables need every row before columns can be aligned, which the per-line commit model can't do mid-stream.\n * The CHEAP strategy: BUFFER a contiguous table block (rows held, not committed raw) and emit it aligned once\n * the block ends (first non-table line, or `flush()`). Rows therefore \"snap\" into alignment at block end\n * rather than rendering live. A future full-streaming upgrade only changes WHEN `flushTable()` fires (e.g.\n * re-render the partial block on every feed) — the parsing/alignment in `flushTable()` stays as-is.\n *\n * The caller gates all of this to a color-capable TTY — piped / NO_COLOR output never reaches here, stays raw.\n */\n\nimport { needsBidi, bidiLine, appBidi } from './bidi';\n\nexport type Paint = (s: string) => string;\n\n/** Reorder a logical text segment into visual (display) order for the TTY — same path the line editor uses on\n * input (cli/bidi.ts). Applied to PLAIN text BEFORE ANSI styling: within a same-direction run character order\n * is preserved, so markdown markers (`**`, `` ` ``, `[]()`) stay adjacent to their content and the later\n * styling pass still matches. Pure-LTR text is returned untouched (fast path). */\nconst vis = (s: string): string => (appBidi() && needsBidi(s) ? bidiLine(s).visual : s);\nexport interface MdPalette {\n bold: Paint;\n dim: Paint;\n cyan: Paint;\n italic?: Paint; // *x* / _x_ — falls back to no styling (text kept, markers dropped)\n strike?: Paint; // ~~x~~ — falls back to no styling\n green?: Paint; // string literals in highlighted code fences — falls back to cyan\n /** Render `text` as a hyperlink to `url` (e.g. OSC 8). Optional — falls back to cyan link text. */\n link?: (text: string, url: string) => string;\n}\n\n// ── Fenced-code syntax highlighting (lean, regex-token based — not a real parser) ──\nconst C_KW = new Set('const let var function return if else for while do switch case break continue class new async await try catch finally throw import export from default type interface extends implements public private protected readonly static void null undefined true false this super yield typeof instanceof in of enum namespace struct fn pub mut match impl use go defer chan func package var range nil'.split(' '));\nconst PY_KW = new Set('def return if elif else for while class import from as with try except finally raise lambda pass break continue global nonlocal yield async await None True False not and or in is del assert print self'.split(' '));\nconst SH_KW = new Set('if then else elif fi for while do done case esac function local export return echo exit set source in'.split(' '));\nconst HASH_COMMENT = /^(sh|bash|zsh|shell|py|python|rb|ruby|yaml|yml|toml|ini|make|makefile|dockerfile|r)$/;\n/** Keyword set for a fence language tag; null → no highlighting (unknown/absent lang keeps legacy all-cyan). */\nfunction kwFor(lang?: string): Set<string> | null {\n if (!lang) return null;\n const l = lang.toLowerCase();\n if (/^(js|jsx|ts|tsx|javascript|typescript|java|c|h|cpp|cc|cs|go|rust|rs|swift|kotlin|kt|php|scala|dart)$/.test(l)) return C_KW;\n if (/^(py|python)$/.test(l)) return PY_KW;\n if (/^(sh|bash|zsh|shell|console)$/.test(l)) return SH_KW;\n if (/^(json|yaml|yml|toml|sql|html|xml|css)$/.test(l)) return new Set(); // strings/numbers/comments only\n return null;\n}\n/** Color one code line: comments dim, strings green, numbers cyan, keywords bold — rest plain.\n * Unknown language → the whole line in cyan (the pre-highlighting behavior). Best-effort by design:\n * a `#`/`//` inside a string may be taken for a comment; acceptable for terminal display. */\nexport function highlightCode(line: string, lang: string | undefined, p: MdPalette): string {\n const kws = kwFor(lang);\n if (!kws) return p.cyan(line);\n const cm = (HASH_COMMENT.test(lang!.toLowerCase()) ? /(^|\\s)#.*$/ : /\\/\\/.*$|\\/\\*.*$/).exec(line);\n let code = line, comment = '';\n if (cm) { const at = cm.index + (cm[1]?.length ?? 0); comment = line.slice(at); code = line.slice(0, at); }\n const str = p.green ?? p.cyan;\n const re = /(\"(?:[^\"\\\\]|\\\\.)*\"?|'(?:[^'\\\\]|\\\\.)*'?|`[^`]*`?)|\\b(\\d+(?:\\.\\d+)?)\\b|\\b([A-Za-z_]\\w*)\\b/g;\n const out = code.replace(re, (m, s, num, word) => {\n if (s) return str(s);\n if (num) return p.cyan(num);\n if (word && kws.has(word)) return p.bold(word);\n return m;\n });\n return out + (comment ? p.dim(comment) : '');\n}\n\n/** Strip INLINE markdown markers to recover the VISIBLE text — used for table column-width math (where the\n * ANSI-styled form has a different byte length than what the eye sees) and for dim preview panels that\n * show raw text without a full render. Inline-only: leading block markers (#, -) are NOT touched here so\n * table-cell widths stay exact; the panel callsite handles those separately via `plainLine`. */\nexport function displayText(s: string): string {\n return s\n .replace(/`([^`]+)`/g, '$1')\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1')\n .replace(/\\*\\*([^*]+)\\*\\*/g, '$1')\n .replace(/~~([^~]+)~~/g, '$1')\n .replace(/(?<![\\w*])[*_]([^*_\\s][^*_]*?)[*_](?![\\w*])/g, '$1');\n}\n\n/** Strip a whole line of markdown for a plain dim preview (no styling): inline markers + leading heading\n * hashes / list markers. For panels like the duplex task-result preview — NOT for width-sensitive math. */\nexport function plainLine(s: string): string {\n return displayText(s).replace(/^\\s{0,3}#{1,6}\\s+/, '').replace(/^(\\s*)[-*+]\\s+/, '$1');\n}\n\n/** Render inline spans in one already-complete line. A single alternation pass so a `code` span is consumed\n * as one unit — its inner `**` is never seen by the **bold** branch (a two-pass approach would re-bold it).\n * Order: code → link → bold, so a `[**x**](u)` link text isn't pre-eaten by the bold branch. */\nexport function mdInline(line: string, p: MdPalette): string {\n const re = /(`[^`]+`)|(\\[[^\\]]+\\]\\([^)]+\\))|(\\*\\*[^*]+\\*\\*)|(~~[^~]+~~)|((?<![\\w*])[*_][^*_\\s][^*_]*?[*_](?![\\w*]))/g;\n return line.replace(re, (_m, code, link, bold, strike, italic) => {\n if (code) return p.cyan(code.slice(1, -1));\n if (link) {\n const m = /^\\[([^\\]]+)\\]\\(([^)]+)\\)$/.exec(link)!;\n return p.link ? p.link(m[1], m[2]) : p.cyan(m[1]);\n }\n if (bold) return p.bold(bold.slice(2, -2));\n if (strike) return (p.strike ?? ((s) => s))(strike.slice(2, -2));\n return (p.italic ?? ((s) => s))(italic.slice(1, -1)); // markers dropped even without a paint\n });\n}\n\n/** Render one COMPLETE non-table line to ANSI, threading fenced-code-block state across lines. `cols` widths\n * the `---` horizontal rule (falls back to 80 when unknown). Table rows never reach here — the stream holds\n * them for `flushTable()`. */\nexport function renderMdLine(line: string, inFence: boolean, p: MdPalette, cols = 80, fenceLang?: string): { out: string; inFence: boolean; fenceLang?: string } {\n if (/^\\s*```/.test(line)) { // fence marker: dim, toggle state, capture the language tag on open\n const lang = inFence ? undefined : /^\\s*```\\s*(\\w+)/.exec(line)?.[1];\n return { out: p.dim(line), inFence: !inFence, fenceLang: lang };\n }\n if (inFence) return { out: highlightCode(line, fenceLang, p), inFence, fenceLang }; // code body: lang-aware highlight (cyan when unknown)\n if (/^\\s*([-*_])(\\s*\\1){2,}\\s*$/.test(line)) return { out: p.dim('─'.repeat(cols)), inFence }; // --- → full rule\n const h = line.match(/^(#{1,6})\\s+(.*)$/);\n if (h) return { out: p.bold(vis(h[2])), inFence }; // heading → bold, drop the leading #'s\n const q = line.match(/^(\\s*)>\\s?(.*)$/);\n if (q) return { out: q[1] + p.dim('▎ ') + p.dim(mdInline(vis(q[2]), p)), inFence }; // blockquote → dim bar + dim text\n const b = line.match(/^(\\s*)[-*+]\\s+(.*)$/);\n if (b) return { out: b[1] + p.cyan('•') + ' ' + mdInline(vis(b[2]), p), inFence }; // bullet → • (keeps indent)\n return { out: mdInline(vis(line), p), inFence };\n}\n\n/** A `| a | b |` row — header, separator, or body. Prose rarely opens a line with `|`, so this is safe. */\nfunction isTableRow(line: string): boolean {\n return /^\\s*\\|.*\\|\\s*$/.test(line);\n}\n\n// SGR color codes + OSC-8 hyperlink wrappers: present in styled output, zero display width.\nconst ANSI_TOKEN = /\\x1b\\[[0-9;]*m|\\x1b\\]8;;[^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)/;\nconst WRAP_TOKENS = new RegExp(`${ANSI_TOKEN.source}|[ \\\\t]+|[^\\\\s\\\\x1b]+`, 'g');\n\n/** Wrap one styled (ANSI-bearing) line at WORD boundaries to `cols` visible chars; continuation rows get\n * `indent` (hanging indent for bullets/quotes). Escapes are zero-width and never split; the terminal\n * carries SGR attributes across the inserted newlines, so codes need no close/reopen. A single word wider\n * than the row is hard-sliced (can't do better). Lines are joined with \\r\\n (raw-mode stream convention). */\nexport function wrapAnsi(s: string, cols: number, indent = ''): string {\n if (cols <= 1 || s.replace(new RegExp(ANSI_TOKEN.source, 'g'), '').length <= cols) return s;\n if (indent.length >= cols) indent = ''; // degenerate: indent eats the whole row → wrap flush (also guards the slice loop below)\n const tokens = s.match(WRAP_TOKENS) ?? [];\n const lines: string[] = [];\n let line = '', w = 0;\n const commit = () => { lines.push(line.replace(/[ \\t]+$/, '')); line = indent; w = indent.length; };\n for (const t of tokens) {\n if (t.startsWith('\\x1b')) { line += t; continue; }\n if (/^[ \\t]+$/.test(t)) { // spaces never open a wrapped row — swallow them at a break\n if (w + t.length <= cols) { line += t; w += t.length; }\n else commit();\n continue;\n }\n let word = t;\n while (word && w + word.length > cols) { // `word &&`: a drained word must exit even if w is over (degenerate widths)\n if (w > indent.length) { commit(); continue; } // push the word to the next row\n const take = Math.max(1, cols - w); // word alone exceeds the width → hard-slice\n line += word.slice(0, take); word = word.slice(take); commit();\n }\n line += word; w += word.length;\n }\n if (line !== indent || !lines.length) lines.push(line.replace(/[ \\t]+$/, ''));\n return lines.join('\\r\\n');\n}\n\n/** Continuation-row indent for a wrapped SOURCE line: bullets and blockquotes hang under their text\n * (marker width = 2), plain paragraphs wrap flush. */\nexport function hangIndent(line: string): string {\n const m = line.match(/^(\\s*)(?:[-*+]|>)\\s/);\n return m ? m[1] + ' ' : '';\n}\n\n/**\n * PROGRESSIVE streaming renderer. Text appears as it arrives (char-by-char): every `feed()` re-renders the\n * current in-progress line in place, so an inline `**bold**` / `` `code` `` shows literally while open and\n * \"snaps\" to its styled form the instant its closer arrives — and headings bold as you type. Complete lines\n * (ending in `\\n`) are committed permanently. The in-progress line may wrap, so we clear ALL its physical rows\n * (not just the last) before re-drawing — no long-line corruption. `flush()` commits + resets (any in-progress\n * tail is already on screen; a buffered table block is emitted here). `cols` = terminal width for the wrap math.\n */\nexport class MarkdownStream {\n private buf = ''; // the current (uncommitted) logical line's text\n private inFence = false;\n private fenceLang?: string; // language tag of the open fence (drives syntax highlighting)\n private lineRows = 0; // physical rows the in-progress line occupied last draw (for the next clear)\n private tableBuf: string[] = []; // contiguous GFM table rows held until the block ends, then aligned\n constructor(private p: MdPalette, private cols = 80) {}\n /** Update the wrap width (terminal resized). Recompute how many physical rows the in-progress line now spans\n * so the next feed()'s clear-math matches the new width (the terminal reflows the drawn text on resize too). */\n resize(cols: number): void {\n this.cols = Math.max(1, cols);\n if (this.buf) this.lineRows = Math.max(1, Math.ceil(this.buf.length / this.cols));\n }\n /** Render the held table block as aligned columns and reset the buffer. If the block lacks a `|---|`\n * separator row it isn't a real table — emit the rows verbatim (rendered as normal lines) instead. */\n private flushTable(): string {\n const rows = this.tableBuf;\n this.tableBuf = [];\n const sepIdx = rows.findIndex((r, i) => i > 0 && r.includes('-') && /^\\s*\\|[\\s:|-]+\\|\\s*$/.test(r));\n if (sepIdx < 0) return rows.map((r) => renderMdLine(r, false, this.p, this.cols).out + '\\r\\n').join('');\n const cells = (r: string) => r.trim().replace(/^\\||\\|$/g, '').split('|').map((c) => c.trim());\n const data = rows.filter((_, i) => i !== sepIdx).map(cells); // header + body (drop the separator row)\n const ncol = Math.max(...data.map((r) => r.length));\n const widths = Array.from({ length: ncol }, (_, i) => Math.max(...data.map((r) => displayText(r[i] ?? '').length)));\n const out: string[] = [];\n data.forEach((row, ri) => {\n const header = ri === 0;\n const line = ' ' + widths.map((w, ci) => {\n const c = row[ci] ?? '';\n const styled = header ? this.p.bold(displayText(vis(c))) : mdInline(vis(c), this.p);\n return styled + ' '.repeat(Math.max(0, w - displayText(c).length)); // reorder is length-invariant → width ok\n }).join(' ').replace(/\\s+$/, '');\n out.push(line);\n if (header) out.push(' ' + this.p.dim('─'.repeat(widths.reduce((a, b) => a + b, 0) + 3 * (ncol - 1))));\n });\n return out.map((l) => l + '\\r\\n').join('');\n }\n feed(text: string): string {\n this.buf += text;\n let out = '';\n // 1. wipe the previously-drawn in-progress line (cursor is sitting at its end, possibly wrapped).\n if (this.lineRows > 1) out += `\\x1b[${this.lineRows - 1}A\\r\\x1b[J`; // climb to its first row, clear down\n else if (this.lineRows === 1) out += '\\r\\x1b[K';\n this.lineRows = 0;\n // 2. commit every COMPLETE line (ending in \\n). Table rows are HELD (block buffered, aligned at block end);\n // any other line first flushes a pending table, then scrolls up and is never touched again.\n let nl: number;\n while ((nl = this.buf.indexOf('\\n')) >= 0) {\n const line = this.buf.slice(0, nl);\n this.buf = this.buf.slice(nl + 1);\n if (!this.inFence && isTableRow(line)) { this.tableBuf.push(line); continue; }\n if (this.tableBuf.length) out += this.flushTable();\n const wasFence = this.inFence;\n const r = renderMdLine(line, this.inFence, this.p, this.cols, this.fenceLang);\n this.inFence = r.inFence;\n this.fenceLang = r.fenceLang;\n // word-wrap committed PROSE at the terminal width (code bodies + fence markers stay verbatim —\n // wrapping code would corrupt it; the terminal hard-wraps those rare overlong lines itself)\n out += (wasFence || r.inFence ? r.out : wrapAnsi(r.out, this.cols, hangIndent(line))) + '\\r\\n';\n }\n // 3. (re)draw the in-progress tail (no newline). A tail that STARTS with `|` while a table block is open is a\n // partial table row still arriving — HOLD it (don't draw raw, it would glue onto the aligned table); it\n // snaps in when its `\\n` commits it or at flush(). A non-`|` tail means the table block ended, so emit the\n // aligned table FIRST (correct order, no glue) before drawing the tail.\n const tailIsTableRow = this.tableBuf.length > 0 && !this.inFence && /^\\s*\\|/.test(this.buf);\n if (this.buf && !tailIsTableRow) {\n if (this.tableBuf.length) out += this.flushTable();\n const rendered = renderMdLine(this.buf, this.inFence, this.p, this.cols, this.fenceLang).out;\n if (this.inFence) { // code stays verbatim (terminal soft-wraps); rows from source length\n out += rendered;\n this.lineRows = Math.max(1, Math.ceil(this.buf.length / Math.max(1, this.cols)));\n } else {\n // word-wrap the tail too — a one-paragraph answer with no trailing \\n NEVER commits, so\n // without this it would sit on screen terminal-hard-wrapped mid-word until the turn ends\n const tail = wrapAnsi(rendered, this.cols, hangIndent(this.buf));\n out += tail;\n this.lineRows = tail.split('\\r\\n').length; // rows = our explicit breaks (each row ≤ cols)\n }\n }\n return out;\n }\n /** Commit the in-progress line as-is (already on screen), emit any buffered table, and reset for next turn. */\n flush(): string {\n let out = '';\n // A table's final row usually arrives with no trailing newline — it's held in `buf` (feed step 3 does NOT\n // draw a partial table row, so nothing is on screen to clear). Fold a COMPLETE row into the block; an\n // incomplete partial (no closing `|`) is dropped rather than shown raw.\n if (this.tableBuf.length && this.buf && !this.inFence && isTableRow(this.buf)) {\n this.tableBuf.push(this.buf);\n this.buf = '';\n }\n out += this.tableBuf.length ? this.flushTable() : '';\n this.buf = '';\n this.inFence = false;\n this.fenceLang = undefined;\n this.lineRows = 0;\n return out;\n }\n pending(): boolean { return this.buf.length > 0 || this.tableBuf.length > 0; }\n /** Terminate the stream for external chrome (a tool header, a step notice): if an in-progress tail is\n * drawn on screen, end its line with \\r\\n, then flush + reset. Without this, chrome printed below a\n * pending tail leaves stale clear-math behind — the next feed() climbs the wrong rows and re-draws the\n * old tail glued onto the new text (the classic duplicated/jammed-block artifact). */\n commit(): string {\n // a held partial table row (tailIsTableRow in feed) was never drawn → nothing on screen to terminate\n const open = this.buf.length > 0 && !(this.tableBuf.length > 0 && !this.inFence && /^\\s*\\|/.test(this.buf));\n return (open ? '\\r\\n' : '') + this.flush();\n }\n}\n","import { PassThrough } from 'node:stream';\n\n/**\n * The CLI's single keyboard source.\n *\n * Bun's node-compat `process.stdin` (≤1.3.x, verified on 1.3.10) starves on a single TTY chunk\n * larger than ~37 bytes: the first ~37 bytes are delivered, the remainder sits unread until the\n * NEXT chunk arrives (seconds-to-forever later). Fast typing bursts, any paste, and multi-byte\n * scripts (Hebrew = 2 bytes/char) all trip it — Enter \"doesn't work\" (the `\\r` starves in the\n * tail) and bracketed pastes freeze mid-paste (the ESC[201~ end marker starves).\n * `Bun.stdin.stream()` delivers the same chunks intact and instantly, so under Bun on a TTY we\n * pump it into a PassThrough that mimics the bits of ReadStream the editor uses (isTTY/isRaw/\n * setRawMode). Everything keyboard-shaped MUST read from `keyInput` — a second reader on the\n * real fd would steal bytes from the pump. Repro: .tmp/qa-input-dx-repro/ · spec:\n * .tmp/tasks/input-line-dx.md. Re-check on Bun upgrades.\n */\nexport type KeyInput = NodeJS.ReadStream;\n\nlet cancelPump: (() => void) | undefined;\n\nexport const keyInput: KeyInput = (() => {\n const bun = (globalThis as { Bun?: { stdin: { stream(): ReadableStream<Uint8Array> } } }).Bun;\n if (!bun || !process.stdin.isTTY) return process.stdin;\n const pt = new PassThrough() as unknown as NodeJS.ReadStream & PassThrough;\n pt.isTTY = true;\n pt.setRawMode = (mode: boolean) => { process.stdin.setRawMode(mode); return pt; };\n Object.defineProperty(pt, 'isRaw', { get: () => process.stdin.isRaw });\n // LAZY pump: the pending native read keeps the event loop alive, so starting it at import time\n // would hang one-shot invocations (--help, -p) that never touch the keyboard. First resume()\n // (the editor/menu's \"start reading keys\") starts it; releaseKeyInput() cancels it for exit.\n let pump: (() => void) | undefined = () => {\n pump = undefined;\n const reader = bun.stdin.stream().getReader();\n let stopped = false;\n cancelPump = () => { stopped = true; void reader.cancel().catch(() => { /* already closed */ }); };\n void (async () => {\n try {\n while (!stopped) {\n const { value, done } = await reader.read();\n if (done) break;\n if (value?.length) pt.write(Buffer.from(value));\n }\n } catch { /* cancelled / fd closed */ }\n pt.end();\n })();\n };\n const ptResume = pt.resume.bind(pt);\n pt.resume = () => { pump?.(); return ptResume(); };\n return pt;\n})();\n\n/** Stop the pump so the process can exit (the pending native read keeps the event loop alive). */\nexport function releaseKeyInput(): void { cancelPump?.(); }\n","import { spawnSync } from 'node:child_process';\nimport { writeFileSync, mkdirSync, readdirSync, unlinkSync, chmodSync, existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { forComponent } from '../src/index';\nimport type { Trigger } from '../src/scheduler';\nimport { parseCron, nextCronAfter } from '../src/scheduler';\nimport { readJsonFile } from './util';\n\nconst log = forComponent('os-sched');\n\n/**\n * OS-backend scheduler (mind/12 spec): jobs that survive quit/reboot. Each job is a small shell\n * script under ~/.agent/sched/ running `agentx -p \"<prompt>\" --resume <sessionId> --yes` from the\n * project dir, plus a JSON meta file (the source of truth for list/cancel). Trigger mechanisms:\n *\n * macOS — launchd user agent (~/Library/LaunchAgents/cc.livx.agentx.sched-<id>.plist):\n * {at}/simple-cron → StartCalendarInterval; {everyMs} → StartInterval. One-offs\n * self-remove (the script calls `launchctl remove` + deletes its own files).\n * Linux — recurring → user crontab line tagged `# agentx-sched-<id>`; one-off → `at`.\n *\n * No daemon, no queue: the OS scheduler + session JSON ARE the persistence. Results land in the\n * session transcript (visible on next --resume) + ~/.agent/sched/<id>.log; the agent is told to\n * use PushNotification for out-of-band alerts.\n */\n\nexport interface OsJobSpec { id: string; prompt: string; sessionId: string; cwd: string; trigger: Trigger; label?: string }\ninterface JobMeta extends OsJobSpec { created: number; mechanism: string }\n\nexport class OsScheduler {\n public options: OsSchedulerOptions;\n constructor(options?: Partial<OsSchedulerOptions>) {\n this.options = { ...new OsSchedulerOptions(), ...options };\n }\n\n private get dir(): string { return join(this.options.home, '.agent', 'sched'); }\n private label(id: string): string { return `cc.livx.agentx.sched-${id}`; }\n private plistPath(id: string): string { return join(this.options.home, 'Library', 'LaunchAgents', `${this.label(id)}.plist`); }\n private run(cmd: string, args: string[], input?: string): string {\n return this.options.exec(cmd, args, input);\n }\n\n available(): boolean {\n return this.options.platform === 'darwin' || this.options.platform === 'linux';\n }\n\n /** Register the job with the OS. Returns a human description of the mechanism used. Throws on failure. */\n schedule(spec: OsJobSpec): string {\n if (!this.available()) throw new Error(`no OS scheduler on ${this.options.platform}`);\n mkdirSync(this.dir, { recursive: true });\n const oneOff = 'at' in spec.trigger;\n const script = this.writeScript(spec, oneOff);\n const mechanism = this.options.platform === 'darwin' ? this.scheduleDarwin(spec, script) : this.scheduleLinux(spec, script, oneOff);\n const meta: JobMeta = { ...spec, created: Date.now(), mechanism };\n writeFileSync(join(this.dir, `${spec.id}.json`), JSON.stringify(meta, null, 2));\n return mechanism;\n }\n\n cancel(id: string): boolean {\n const meta = readJsonFile<JobMeta | null>(join(this.dir, `${id}.json`), null);\n if (!meta) return false;\n try {\n if (this.options.platform === 'darwin') {\n try { this.run('launchctl', ['remove', this.label(id)]); } catch { /* not loaded */ }\n try { unlinkSync(this.plistPath(id)); } catch { /* already gone */ }\n } else if (meta.mechanism.startsWith('crontab')) {\n const cur = (() => { try { return this.run('crontab', ['-l']); } catch { return ''; } })();\n const next = cur.split('\\n').filter((l) => !l.includes(`# agentx-sched-${id}`)).join('\\n');\n this.run('crontab', ['-'], next.trim() ? next.trimEnd() + '\\n' : '');\n } else if (meta.mechanism.startsWith('at:')) {\n try { this.run('atrm', [meta.mechanism.slice(3)]); } catch { /* already fired */ }\n }\n } catch (e) { log.debug(`cancel ${id}`, e); }\n for (const f of [`${id}.json`, `${id}.sh`]) { try { unlinkSync(join(this.dir, f)); } catch { /* gone */ } }\n return true;\n }\n\n list(): JobMeta[] {\n if (!existsSync(this.dir)) return [];\n return readdirSync(this.dir)\n .filter((f) => f.endsWith('.json'))\n .map((f) => readJsonFile<JobMeta | null>(join(this.dir, f), null))\n .filter(Boolean) as JobMeta[];\n }\n\n /** The per-job runner script: cd to the project, headless-resume the session, log, notify. */\n private writeScript(spec: OsJobSpec, oneOff: boolean): string {\n const p = join(this.dir, `${spec.id}.sh`);\n const q = (s: string) => `'${s.replace(/'/g, `'\\\\''`)}'`;\n const cleanup = oneOff\n ? this.options.platform === 'darwin'\n ? `launchctl remove ${this.label(spec.id)} 2>/dev/null; rm -f ${q(this.plistPath(spec.id))} ${q(join(this.dir, `${spec.id}.json`))} ${q(p)}\\n`\n : `rm -f ${q(join(this.dir, `${spec.id}.json`))} ${q(p)}\\n`\n : '';\n writeFileSync(p, `#!/bin/sh\n# agentx scheduled job ${spec.id}${spec.label ? ` — ${spec.label}` : ''}\ncd ${q(spec.cwd)} || exit 1\n${this.options.agentx} -p ${q(spec.prompt)} --resume ${q(spec.sessionId)} --yes >> ${q(join(this.dir, `${spec.id}.log`))} 2>&1\n${cleanup}`);\n chmodSync(p, 0o755);\n return p;\n }\n\n private scheduleDarwin(spec: OsJobSpec, script: string): string {\n const t = spec.trigger;\n let trigger: string;\n if ('everyMs' in t) {\n trigger = `<key>StartInterval</key><integer>${Math.max(60, Math.round(t.everyMs / 1000))}</integer>`;\n } else if ('at' in t) {\n const d = new Date(t.at);\n trigger = `<key>StartCalendarInterval</key><dict><key>Minute</key><integer>${d.getMinutes()}</integer><key>Hour</key><integer>${d.getHours()}</integer><key>Day</key><integer>${d.getDate()}</integer><key>Month</key><integer>${d.getMonth() + 1}</integer></dict>`;\n } else {\n // cron → StartCalendarInterval supports one value per field; ranges/lists/steps would explode\n // into dict products — keep it honest and reject those (use {everyMs} or simple crons).\n const f = parseCron(t.cron);\n const dict: string[] = [];\n const put = (key: string, vals: number[], full: number) => {\n if (vals.length === full) return; // '*' — omit (launchd wildcard)\n if (vals.length !== 1) throw new Error(`macOS launchd supports only single-value cron fields (got \"${t.cron}\") — use {everyMs} or a simpler cron`);\n dict.push(`<key>${key}</key><integer>${vals[0]}</integer>`);\n };\n put('Minute', f.minute, 60); put('Hour', f.hour, 24); put('Day', f.dom, 31); put('Month', f.month, 12); put('Weekday', f.dow, 7);\n trigger = `<key>StartCalendarInterval</key><dict>${dict.join('')}</dict>`;\n }\n const plist = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\"><dict>\n<key>Label</key><string>${this.label(spec.id)}</string>\n<key>ProgramArguments</key><array><string>/bin/sh</string><string>${script}</string></array>\n${trigger}\n<key>RunAtLoad</key><false/>\n</dict></plist>\n`;\n mkdirSync(join(this.options.home, 'Library', 'LaunchAgents'), { recursive: true });\n writeFileSync(this.plistPath(spec.id), plist);\n this.run('launchctl', ['load', this.plistPath(spec.id)]);\n return `launchd:${this.label(spec.id)}`;\n }\n\n private scheduleLinux(spec: OsJobSpec, script: string, oneOff: boolean): string {\n const t = spec.trigger;\n if (oneOff) {\n // `at` prints \"job N at <date>\" on stderr\n const d = new Date(('at' in t ? t.at : Date.now()));\n const stamp = `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')} ${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;\n const out = this.run('at', [stamp], `/bin/sh ${script}\\n`);\n const jobId = /job (\\d+)/.exec(out)?.[1] ?? '';\n return `at:${jobId}`;\n }\n const expr = 'cron' in t ? t.cron : `*/${Math.max(1, Math.round((t as { everyMs: number }).everyMs / 60_000))} * * * *`;\n parseCron(expr); // validate before touching the crontab\n const cur = (() => { try { return this.run('crontab', ['-l']); } catch { return ''; } })();\n this.run('crontab', ['-'], `${cur.trimEnd()}\\n${expr} /bin/sh ${script} # agentx-sched-${spec.id}\\n`.replace(/^\\n/, ''));\n return `crontab:${expr}`;\n }\n}\n\nexport class OsSchedulerOptions {\n platform: NodeJS.Platform = process.platform;\n home = homedir();\n /** How the fired job invokes the CLI — a RAW shell snippet (may be `bun /path/cli.ts`). Default: `agentx` on PATH. */\n agentx = 'agentx';\n /** Injectable executor for tests. Returns stdout+stderr merged — `at` reports \"job N\" on STDERR,\n * and the job id is what atrm needs for cancel. Throws on non-zero exit. */\n exec: (cmd: string, args: string[], input?: string) => string = (cmd, args, input) => {\n const r = spawnSync(cmd, args, { input, encoding: 'utf8' });\n if (r.error) throw r.error;\n if (r.status !== 0) throw new Error(`${cmd} exited ${r.status}: ${r.stderr || r.stdout}`);\n return `${r.stdout ?? ''}${r.stderr ?? ''}`;\n };\n}\n\n/** Spec routing heuristic: one-off ≥30min out → OS (survives quit); near one-offs and ALL\n * recurring triggers stay in-process unless the agent explicitly asks for the OS backend\n * (a recurring OS job spawns repeated headless runs — that should be a deliberate choice). */\nexport function routeTrigger(trigger: Trigger, backendHint: string | undefined, now = Date.now()): 'session' | 'os' {\n if (backendHint === 'os') return 'os';\n if (backendHint === 'session') return 'session';\n return 'at' in trigger && trigger.at - now >= 30 * 60_000 ? 'os' : 'session';\n}\n\n/** Next-fire preview for display (mirrors Scheduler.nextFire for an unsaved trigger). */\nexport function nextFireOf(trigger: Trigger, now = Date.now()): number | null {\n if ('at' in trigger) return trigger.at;\n if ('everyMs' in trigger) return now + trigger.everyMs;\n return nextCronAfter(trigger.cron, now);\n}\n","import { createServer, createConnection, type Server } from 'node:net';\nimport { spawn } from 'node:child_process';\nimport { existsSync, mkdirSync, unlinkSync, readdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { forComponent } from '../src/index';\nimport type { AgentTool } from '../src/tools';\nimport { globalSessionLoad } from './session';\n\nconst log = forComponent('remote-trigger');\n\n/**\n * RemoteTrigger — invoke ANOTHER agentx session on demand (the event-driven sibling of the\n * scheduler's \"run X at time T\"). Two local tiers, tried in order:\n *\n * 1. LIVE session (same machine): every REPL listens on a per-session unix socket under\n * ~/.agent/triggers/ (same-user only — the dir is 0700). A trigger lands as an injected\n * prompt in the OPEN terminal (same seam as a scheduler fire), so there is no second\n * writer racing the session JSON. The caller gets an ack, not the result — the result\n * belongs to the live session.\n * 2. HEADLESS spawn: no live socket → `agentx -p \"<prompt>\" --resume <id> --yes` from the\n * target session's own cwd (resolved via the global session index). The caller gets the\n * run's final text.\n *\n * Cross-machine triggering is deliberately NOT here — that's the MCP-server direction\n * (mind/13): an agentx exposed as a connectable MCP with real auth.\n */\n\nconst TRIGGER_DIR = () => join(homedir(), '.agent', 'triggers');\nconst sockPath = (sessionId: string, dir = TRIGGER_DIR()) => join(dir, `${sessionId}.sock`);\n\nexport interface TriggerRequest { prompt: string; from?: string }\n\n/** Per-REPL listener: accepts {prompt} JSON lines and injects them into the live session. */\nexport class TriggerServer {\n private server?: Server;\n private path?: string;\n\n constructor(private onTrigger: (req: TriggerRequest) => void) {}\n\n /** Start listening for this session. Never throws — a failed listener just disables tier 1. */\n start(sessionId: string, dir = TRIGGER_DIR()): void {\n this.stop();\n try {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n const p = sockPath(sessionId, dir);\n try { unlinkSync(p); } catch { /* no stale socket */ }\n this.server = createServer((conn) => {\n let buf = '';\n conn.on('data', (d) => {\n buf += d.toString();\n const nl = buf.indexOf('\\n');\n if (nl < 0) return;\n const line = buf.slice(0, nl);\n buf = buf.slice(nl + 1);\n try {\n const req = JSON.parse(line) as TriggerRequest;\n if (typeof req.prompt === 'string' && req.prompt.trim()) {\n this.onTrigger(req);\n conn.end(JSON.stringify({ ok: true, mode: 'live' }) + '\\n');\n } else conn.end(JSON.stringify({ ok: false, error: 'empty prompt' }) + '\\n');\n } catch (e) { conn.end(JSON.stringify({ ok: false, error: String(e) }) + '\\n'); }\n });\n conn.on('error', (e) => log.debug('trigger conn error', e));\n });\n this.server.on('error', (e) => log.debug('trigger server error', e));\n this.server.listen(p);\n this.path = p;\n } catch (e) { log.debug('trigger server unavailable', e); }\n }\n\n /** Re-bind on /resume (the session id changed). */\n use(sessionId: string, dir = TRIGGER_DIR()): void { this.start(sessionId, dir); }\n\n stop(): void {\n this.server?.close();\n this.server = undefined;\n if (this.path) { try { unlinkSync(this.path); } catch { /* gone */ } this.path = undefined; }\n }\n}\n\n/** Tier 1: send {prompt} to a live session's socket. Resolves null when no live listener answers. */\nexport function triggerLive(sessionId: string, req: TriggerRequest, dir = TRIGGER_DIR(), timeoutMs = 3000): Promise<{ ok: boolean } | null> {\n const p = sockPath(sessionId, dir);\n if (!existsSync(p)) return Promise.resolve(null);\n return new Promise((res) => {\n const conn = createConnection(p);\n const done = (v: { ok: boolean } | null) => { conn.destroy(); res(v); };\n const timer = setTimeout(() => done(null), timeoutMs);\n let buf = '';\n conn.on('connect', () => conn.write(JSON.stringify(req) + '\\n'));\n conn.on('data', (d) => {\n buf += d.toString();\n if (!buf.includes('\\n')) return;\n clearTimeout(timer);\n try { done(JSON.parse(buf.slice(0, buf.indexOf('\\n')))); } catch { done(null); }\n });\n conn.on('error', () => { clearTimeout(timer); try { unlinkSync(p); } catch { /* held elsewhere */ } done(null); }); // stale socket → clean + fall through\n });\n}\n\n/** Live sessions visible on this machine (sockets present under the trigger dir). */\nexport function liveSessions(dir = TRIGGER_DIR()): string[] {\n if (!existsSync(dir)) return [];\n return readdirSync(dir).filter((f) => f.endsWith('.sock')).map((f) => f.slice(0, -5));\n}\n\nexport interface RemoteTriggerOptions {\n /** RAW shell-ready interpreter+script (same convention as OsSchedulerOptions.agentx). */\n agentx: string;\n /** This session's id — triggering yourself is rejected (it would deadlock the live seam). */\n selfId?: () => string;\n /** Injectable for tests. */\n spawnFn?: typeof spawn;\n triggerDir?: string;\n /** Headless run hard cap. */\n timeoutMs?: number;\n}\n\n/** The RemoteTrigger agent tool: live-socket first, headless `--resume` spawn as fallback. */\nexport function makeRemoteTriggerTool(opts: RemoteTriggerOptions): AgentTool {\n const dir = opts.triggerDir ?? TRIGGER_DIR();\n const doSpawn = opts.spawnFn ?? spawn;\n return {\n name: 'RemoteTrigger',\n description:\n 'Trigger ANOTHER agentx session (this machine) with a prompt. A session open in a live terminal receives it ' +\n 'as an injected turn (you get an ack; the result shows there). Otherwise the session is resumed headless and ' +\n 'you get its final answer. Find ids via the user or `ls ~/.agent/sessions`. Not for self-delegation — use Task for that.',\n parameters: {\n type: 'object',\n required: ['sessionId', 'prompt'],\n properties: {\n sessionId: { type: 'string', description: 'target session id (or unique prefix/suffix)' },\n prompt: { type: 'string', description: 'the prompt to run in that session' },\n },\n },\n async run({ sessionId, prompt }) {\n const id = String(sessionId ?? '').trim();\n const text = String(prompt ?? '').trim();\n if (!id || !text) return 'Error: sessionId and prompt are required.';\n const target = globalSessionLoad(id);\n if (!target) return `Error: no session matching '${id}' in the global index (~/.agent/sessions).`;\n const full = target.meta.id;\n if (opts.selfId && full === opts.selfId()) return 'Error: that is THIS session — use Task/TaskBatch for self-delegation.';\n // Tier 1: live terminal on this machine\n const live = await triggerLive(full, { prompt: text, from: opts.selfId?.() }, dir);\n if (live?.ok) return `Delivered to live session ${full} — it runs there; the user sees it in that terminal.`;\n // Tier 2: headless resume from the target's own project dir\n if (!target.meta.cwd || !existsSync(target.meta.cwd)) return `Error: session ${full} has no reachable cwd (${target.meta.cwd ?? 'unknown'}).`;\n return new Promise<string>((res) => {\n const child = doSpawn('/bin/sh', ['-c', `${opts.agentx} -p \"$1\" --resume \"$2\" --yes`, 'sh', text, full], {\n cwd: target.meta.cwd, stdio: ['ignore', 'pipe', 'pipe'],\n });\n let out = '', errOut = '';\n child.stdout?.on('data', (d) => { out += d; });\n child.stderr?.on('data', (d) => { errOut += d; });\n const killer = setTimeout(() => { child.kill(); }, opts.timeoutMs ?? 10 * 60_000);\n child.on('close', (code) => {\n clearTimeout(killer);\n const answer = out.trim().slice(-8000);\n res(code === 0\n ? `Headless run of ${full} finished:\\n${answer || '(no output)'}`\n : `Error: headless run of ${full} exited ${code}: ${(errOut || out).trim().slice(-1000)}`);\n });\n child.on('error', (e) => { clearTimeout(killer); res(`Error: could not spawn agentx: ${e.message}`); });\n });\n },\n };\n}\n"],"mappings":"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","names":["norm","i","err","log","q","res","exec","err","fuzzy","now","platform","existsSync","spawn","ctx","resolve","err","log","NO_JOB","existsSync","readFileSync","mkdirSync","writeFileSync","readdirSync","statSync","unlinkSync","homedir","tmpdir","platform","join","resolve","basename","dirname","q","slug","MAX_CATALOG","parseFrontmatter","slug","l","slug","q","childOpts","res","summary","rememberTool","log","err","NodeDiskFilesystem","JailedFilesystem","PathResolver","now","id","log","q","log","log","slug","MemFilesystem","log","q","MemFilesystem","err","resolve","CAP","q","resolve","log","log","now","log","now","MemFilesystem","CommandExecutor","registerHeadlessCommands","log","resolve","err","err","log","createHash","writeFileSync","dirname","dirname","writeFileSync","createHash","resolve","spawn","execFile","join","existsSync","mkdirSync","homedir","log","platform","resolve","BodDB","existsSync","readFileSync","log","execFile","MemFilesystem","mkdirSync","BodDB","join","existsSync","homedir","now","spawn","existsSync","mkdirSync","statSync","homedir","dirname","join","log","now","spawn","join","dirname","existsSync","homedir","statSync","mkdirSync","homedir","existsSync","readFileSync","join","spawnSync","log","spawnSync","i","j","dim","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","join","log","join","homedir","now","slug","existsSync","mkdirSync","writeFileSync","link","readFileSync","now","execFile","writeFileSync","mkdirSync","existsSync","join","resolve","sep","log","execFile","existsSync","mkdirSync","writeFileSync","join","resolve","sep","writeFileSync","mkdirSync","homedir","join","mkdirSync","writeFileSync","spawnSync","writeFileSync","readFileSync","unlinkSync","tmpdir","join","link","bold","strike","italic","q","q","dim","join","tmpdir","writeFileSync","spawnSync","readFileSync","unlinkSync","resolve","cyan","yellow","spawnSync","writeFileSync","mkdirSync","readdirSync","unlinkSync","existsSync","homedir","join","log","join","mkdirSync","writeFileSync","unlinkSync","existsSync","readdirSync","q","homedir","spawnSync","now","createServer","spawn","existsSync","mkdirSync","unlinkSync","readdirSync","homedir","join","log","join","homedir","mkdirSync","unlinkSync","createServer","existsSync","spawn","existsSync","log","readFileSync","dirname","existsSync","join","q","makeRealShellTool","r","exec","CommandExecutor","registerHeadlessCommands","resolve","homedir","statSync","basename","m","now","writeFileSync","mkdirSync","picked","tmpdir","p","spawnSync","unlinkSync","t","fs","cfg","readdirSync","slug"]}