@cryer/star-cli 0.3.9 → 0.3.11

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/tools/fs/edit.ts","../src/tools/fs/glob.ts","../src/tools/fs/grep.ts","../src/tools/fs/outline.ts","../src/tools/fs/read.ts","../src/tools/fs/read-image.ts","../src/tools/fs/write.ts","../src/tools/screenshot.ts","../src/core/screenshot.ts","../src/tools/tasks.ts","../src/tasks/format.ts","../src/tools/web/search.ts","../src/llm/debug.ts","../src/tools/registry.ts","../src/tools/index.ts"],"sourcesContent":["import { readFile, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport {\n MAX_SNAPSHOT_CONTENT_BYTES,\n currentTurnMessageIndex,\n currentTurnSeq,\n nextSnapshotId,\n pushSnapshot,\n} from \"./snapshots\";\n\n// Same heuristic as read_file: a NUL in the first 8KB marks a binary file.\n// edit_file writes back as UTF-8, so an ASCII old_string that happens to\n// match inside a binary file would corrupt it irreversibly (U+FFFD\n// replacement on undecodable bytes), and snapshots cannot restore it.\nconst BINARY_PROBE_BYTES = 8192;\n\nfunction countOccurrences(haystack: string, needle: string): number {\n let count = 0;\n let idx = haystack.indexOf(needle);\n while (idx !== -1) {\n count += 1;\n idx = haystack.indexOf(needle, idx + needle.length);\n }\n return count;\n}\n\nfunction normalizeEol(text: string): string {\n return text.replace(/\\r\\n/g, \"\\n\");\n}\n\nconst schema = z.object({\n path: z.string().describe(\"File path, absolute or relative to the working directory\"),\n old_string: z.string().min(1).describe(\"Exact text to replace\"),\n new_string: z.string().describe(\"Replacement text\"),\n replace_all: z\n .boolean()\n .optional()\n .describe(\"Replace every occurrence instead of requiring a unique match\"),\n});\n\nexport const editFileTool: Tool<typeof schema> = {\n name: \"edit_file\",\n description:\n \"Replace an exact string in a file. Fails if old_string is not found or matches multiple locations unless replace_all is set. Refuses binary files and files over 5MB.\",\n permission: \"write\",\n parameters: schema,\n async execute(args, ctx) {\n const filePath = path.resolve(ctx.cwd, args.path);\n let content: string;\n let readMtimeMs: number;\n try {\n const st = await stat(filePath);\n // Past the snapshot content cap /undo keeps only metadata, so an edit\n // would be unrecoverable — refuse instead of writing blind.\n if (st.size > MAX_SNAPSHOT_CONTENT_BYTES) {\n return {\n content: `Refused to edit ${args.path}: file is ${st.size} bytes, over the 5MB limit (edits past it could not be restored by /undo)`,\n isError: true,\n };\n }\n readMtimeMs = st.mtimeMs;\n const buf = await readFile(filePath);\n if (buf.subarray(0, BINARY_PROBE_BYTES).includes(0)) {\n return { content: `Refused to edit binary file: ${args.path}`, isError: true };\n }\n content = buf.toString(\"utf8\");\n } catch (err) {\n return { content: `Failed to read ${args.path}: ${(err as Error).message}`, isError: true };\n }\n // Dual-path matching: exact first. When that finds nothing, retry in an\n // LF-normalized space — read_file strips \\r for display, so on a CRLF\n // file the model can only phrase a multi-line old_string with \\n, which\n // never matches the raw bytes. Uniqueness/replace_all counts are judged\n // in the normalized space; after replacing there, the text is converted\n // back to the original file's dominant line ending before writing.\n let working = content;\n let oldString = args.old_string;\n let newString = args.new_string;\n let restoreEol: ((text: string) => string) | null = null;\n let count = countOccurrences(working, oldString);\n if (count === 0) {\n const normalizedContent = normalizeEol(content);\n const normalizedOld = normalizeEol(oldString);\n const normalizedCount = countOccurrences(normalizedContent, normalizedOld);\n if (normalizedCount > 0) {\n const crlfCount = countOccurrences(content, \"\\r\\n\");\n const loneLfCount = countOccurrences(content.replace(/\\r\\n/g, \"\"), \"\\n\");\n restoreEol =\n crlfCount > 0 && crlfCount >= loneLfCount ? (text) => text.replace(/\\n/g, \"\\r\\n\") : null;\n working = normalizedContent;\n oldString = normalizedOld;\n newString = normalizeEol(newString);\n count = normalizedCount;\n }\n }\n if (count === 0) {\n return { content: `old_string not found in ${args.path}`, isError: true };\n }\n if (count > 1 && !args.replace_all) {\n return {\n content: `old_string matches ${count} locations in ${args.path}; provide more surrounding context or set replace_all`,\n isError: true,\n };\n }\n let updated = args.replace_all\n ? working.split(oldString).join(newString)\n : working.replace(oldString, () => newString);\n if (restoreEol) {\n updated = restoreEol(updated);\n }\n try {\n // Guard against a silent overwrite when the file changed on disk\n // between our read and our write.\n const now = await stat(filePath).catch(() => null);\n if (!now || now.mtimeMs !== readMtimeMs) {\n return {\n content: `Failed to edit ${args.path}: file changed since it was read; re-read and retry`,\n isError: true,\n };\n }\n await writeFile(filePath, updated, \"utf8\");\n } catch (err) {\n return { content: `Failed to write ${args.path}: ${(err as Error).message}`, isError: true };\n }\n const contentTooLarge = Buffer.byteLength(content, \"utf8\") > MAX_SNAPSHOT_CONTENT_BYTES;\n await pushSnapshot({\n id: nextSnapshotId(),\n path: filePath,\n existed: true,\n content: contentTooLarge ? null : content,\n contentTooLarge: contentTooLarge || undefined,\n toolName: \"edit_file\",\n timestamp: Date.now(),\n turn: ctx.snapshotContext?.turn ?? currentTurnSeq(),\n messageIndex: ctx.snapshotContext?.messageIndex ?? currentTurnMessageIndex(),\n owner: ctx.snapshotContext?.owner ?? \"root\",\n });\n return { content: `Edited ${args.path}: ${count} replacement${count > 1 ? \"s\" : \"\"}` };\n },\n};\n","import path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport { createIgnorePredicate, matchesGlob, walkFiles } from \"./util\";\n\nconst MAX_RESULTS = 100;\n\nconst GLOB_MAGIC = /[*?[{]/;\n\n// Leading directory segments without glob magic (everything before the final\n// segment, which may name a file) let src/**/*.ts walk <root>/src directly\n// instead of descending the whole tree. Matched paths are re-prefixed before\n// matching and display so output stays relative to the requested root.\nfunction literalDirPrefix(pattern: string): string[] {\n const segments = pattern.replace(/\\\\/g, \"/\").split(\"/\").slice(0, -1);\n const out: string[] = [];\n for (const segment of segments) {\n if (segment === \"\" || GLOB_MAGIC.test(segment)) {\n break;\n }\n out.push(segment);\n }\n return out;\n}\n\nconst schema = z.object({\n pattern: z\n .string()\n .describe(\n \"Glob pattern, e.g. 'src/**/*.ts'. Supports **, *, ?, {a,b} braces and [abc] character classes. A bare pattern like '*.ts' matches basenames recursively.\",\n ),\n path: z.string().optional().describe(\"Directory to search, defaults to the working directory\"),\n});\n\n// A \"..\" segment would walk above the requested root (the literal-prefix\n// optimization resolves it against the search root), escaping the cwd\n// boundary the permission gate enforces on the path argument.\nfunction hasParentSegment(pattern: string): boolean {\n return pattern\n .replace(/\\\\/g, \"/\")\n .split(\"/\")\n .some((segment) => segment === \"..\");\n}\n\nexport const globTool: Tool<typeof schema> = {\n name: \"glob\",\n description:\n \"Find files by glob pattern. Skips node_modules, .git and dist. Follows symlinks that stay inside the working directory. Returns paths sorted by modification time, newest first, up to 100 results.\",\n permission: \"read\",\n parameters: schema,\n async execute(args, ctx) {\n if (hasParentSegment(args.pattern)) {\n return {\n content: `Refused glob pattern with '..' segment: ${args.pattern}`,\n isError: true,\n };\n }\n const root = path.resolve(ctx.cwd, args.path ?? \".\");\n const prefixSegments = literalDirPrefix(args.pattern);\n const walkRoot = prefixSegments.length > 0 ? path.join(root, ...prefixSegments) : root;\n const prefix = prefixSegments.length > 0 ? `${prefixSegments.join(\"/\")}/` : \"\";\n const { files, aborted } = await walkFiles(walkRoot, undefined, {\n ignore: createIgnorePredicate(ctx.cwd),\n signal: ctx.abortSignal,\n symlinkBoundary: ctx.cwd,\n nestedIgnore: true,\n });\n const matched = files\n .filter((f) => matchesGlob(args.pattern, `${prefix}${f.rel}`))\n .sort((a, b) => b.mtimeMs - a.mtimeMs)\n .slice(0, MAX_RESULTS);\n if (matched.length === 0) {\n return {\n content: aborted\n ? `Search interrupted before any files matched pattern: ${args.pattern}`\n : `No files matched pattern: ${args.pattern}`,\n };\n }\n const lines = matched.map((f) => `${prefix}${f.rel}`);\n if (aborted) {\n lines.push(\"... (interrupted: partial results)\");\n }\n return { content: lines.join(\"\\n\") };\n },\n};\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport {\n WALK_CONCURRENCY,\n type WalkedFile,\n createIgnorePredicate,\n isSensitivePath,\n matchesGlob,\n walkFiles,\n} from \"./util\";\n\nconst MAX_MATCHES = 250;\nconst MAX_LINE_CHARS = 500;\nconst MAX_PATTERN_CHARS = 200;\nconst MAX_FILE_BYTES = 5 * 1024 * 1024;\n\n// Very long patterns are usually pasted blobs, and a quantified group is the\n// classic catastrophic-backtracking shape — reject both before they hang the\n// process on a large tree.\nfunction isTooComplexPattern(pattern: string): boolean {\n return (\n pattern.length > MAX_PATTERN_CHARS || /\\)[+*]/.test(pattern) || /\\)\\{\\d+(,\\d*)?\\}/.test(pattern)\n );\n}\n\nconst schema = z.object({\n pattern: z.string().describe(\"Regular expression to search for\"),\n path: z\n .string()\n .optional()\n .describe(\"File or directory to search, defaults to the working directory\"),\n glob: z\n .string()\n .optional()\n .describe(\"Glob pattern to filter which files are searched, e.g. '*.ts'\"),\n ignoreCase: z.boolean().optional().describe(\"Case-insensitive matching\"),\n});\n\nexport const grepTool: Tool<typeof schema> = {\n name: \"grep\",\n description:\n \"Search file contents with a regular expression. Outputs 'file:line:content', up to 250 matches. Skips binary files, files over 5MB, sensitive files, node_modules and .git. Follows symlinks that stay inside the working directory.\",\n permission: \"read\",\n parameters: schema,\n async execute(args, ctx) {\n if (isTooComplexPattern(args.pattern)) {\n return {\n content: `pattern too complex: keep it under ${MAX_PATTERN_CHARS} characters and avoid quantified groups like (a+)+`,\n isError: true,\n };\n }\n let re: RegExp;\n try {\n re = new RegExp(args.pattern, args.ignoreCase ? \"i\" : \"\");\n } catch (err) {\n return { content: `Invalid regular expression: ${(err as Error).message}`, isError: true };\n }\n const root = path.resolve(ctx.cwd, args.path ?? \".\");\n let files: WalkedFile[];\n let interrupted = false;\n try {\n const st = await stat(root);\n if (st.isFile()) {\n // Symlink targets are checked too: a link named notes.txt can point\n // at a sensitive file whose resolved basename is on the blocklist.\n const resolved = await realpath(root).catch(() => null);\n if (isSensitivePath(root) || (resolved !== null && isSensitivePath(resolved))) {\n return {\n content: `Refused to grep sensitive file: ${args.path ?? \".\"}`,\n isError: true,\n };\n }\n files = [{ abs: root, rel: path.basename(root), mtimeMs: st.mtimeMs }];\n } else {\n const walked = await walkFiles(root, undefined, {\n ignore: createIgnorePredicate(ctx.cwd),\n withMtime: false,\n signal: ctx.abortSignal,\n symlinkBoundary: ctx.cwd,\n nestedIgnore: true,\n });\n interrupted = walked.aborted;\n // A link named notes.txt can resolve to a sensitive target inside the\n // cwd; check the resolved path as well as the link path.\n files = walked.files.filter(\n (f) =>\n !isSensitivePath(f.abs) && (f.resolved === undefined || !isSensitivePath(f.resolved)),\n );\n }\n } catch {\n return { content: `Path not found: ${args.path ?? \".\"}`, isError: true };\n }\n if (args.glob) {\n const glob = args.glob;\n files = files.filter((f) => matchesGlob(glob, f.rel));\n }\n // Files are scanned in concurrent chunks; matches are appended in file\n // order so output stays deterministic and the 250-match cut is stable.\n const scanFile = async (file: WalkedFile): Promise<string[] | null> => {\n const st = await stat(file.abs).catch(() => null);\n if (!st) {\n return null;\n }\n if (st.size > MAX_FILE_BYTES) {\n skippedLarge += 1;\n return null;\n }\n let buf: Buffer;\n try {\n buf = await readFile(file.abs);\n } catch {\n return null;\n }\n if (buf.includes(0)) {\n return null;\n }\n const hits: string[] = [];\n const lines = buf.toString(\"utf8\").split(\"\\n\");\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n if (re.test(line)) {\n const shown = line.length > MAX_LINE_CHARS ? `${line.slice(0, MAX_LINE_CHARS)}…` : line;\n hits.push(`${file.rel}:${i + 1}:${shown}`);\n }\n }\n return hits;\n };\n const out: string[] = [];\n let truncated = false;\n let skippedLarge = 0;\n outer: for (let i = 0; i < files.length; i += WALK_CONCURRENCY) {\n if (ctx.abortSignal?.aborted) {\n interrupted = true;\n break;\n }\n const chunk = await Promise.all(\n files.slice(i, i + WALK_CONCURRENCY).map((file) => scanFile(file)),\n );\n for (const hits of chunk) {\n if (!hits) {\n continue;\n }\n for (const hit of hits) {\n out.push(hit);\n if (out.length >= MAX_MATCHES) {\n truncated = true;\n break outer;\n }\n }\n }\n }\n const skippedNote =\n skippedLarge > 0 ? `(skipped ${skippedLarge} file(s) larger than 5MB)` : null;\n if (out.length === 0) {\n return {\n content: `No matches for pattern: ${args.pattern}${skippedNote ? ` ${skippedNote}` : \"\"}${interrupted ? \" (search interrupted)\" : \"\"}`,\n };\n }\n if (truncated) {\n out.push(`... (truncated: more than ${MAX_MATCHES} matches)`);\n } else if (interrupted) {\n out.push(\"... (interrupted: partial results)\");\n }\n if (skippedNote) {\n out.push(`... ${skippedNote}`);\n }\n return { content: out.join(\"\\n\") };\n },\n};\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport {\n WALK_CONCURRENCY,\n type WalkedFile,\n createIgnorePredicate,\n isSensitivePath,\n walkFiles,\n} from \"./util\";\n\nconst MAX_DIR_FILES = 60;\nconst MAX_FILE_BYTES = 2 * 1024 * 1024;\nconst MAX_SYMBOLS_PER_FILE = 150;\nconst MAX_LINE_CHARS = 200;\nconst MAX_OUT_CHARS = 30 * 1024;\n// Nesting is shown through original indentation, capped so deep nesting\n// cannot push the signature out of view.\nconst MAX_INDENT_CHARS = 8;\n\n// Declaration-spotting regexes per language family. This is deliberately a\n// lightweight skeleton extractor, not a parser: it misses some declarations\n// (multi-line signatures, macros) and that is fine — the outline exists so\n// the model can navigate to line ranges cheaply; read_file still owns exact\n// content. Patterns are anchored to declaration shapes (leading modifiers,\n// trailing \"{\"/\";\"/end-of-line) so ordinary calls and control flow don't\n// match, and are tested against the raw line because member rules key on\n// indentation (methods are indented, top-level declarations are not).\nconst KEYWORD_EXCLUSION =\n \"(?!if\\\\b|for\\\\b|while\\\\b|switch\\\\b|catch\\\\b|return\\\\b|else\\\\b|do\\\\b|new\\\\b|throw\\\\b)\";\n\nconst TS_MEMBER_MODIFIERS =\n \"(?:public|private|protected|static|async|readonly|get|set|override|abstract)\";\n\nconst TS_LIKE = [\n /^(?:export\\s+)?(?:default\\s+)?(?:async\\s+)?function\\*?\\s+[\\w$]+/,\n /^(?:export\\s+)?(?:abstract\\s+)?class\\s+[\\w$]+/,\n /^(?:export\\s+)?interface\\s+[\\w$]+/,\n /^(?:export\\s+)?type\\s+[\\w$]+\\s*=/,\n /^(?:export\\s+)?(?:const\\s+)?enum\\s+[\\w$]+/,\n // const handler = (a, b) => / const handler = async (a) => — top level\n // only; locals inside functions are navigation noise.\n /^(?:export\\s+)?(?:const|let|var)\\s+[\\w$]+\\s*=\\s*(?:async\\s*)?(?:\\([^)]*\\)|[\\w$]+)\\s*=>/,\n // Indented class/object members with a body: name<T>(args): ReturnType {\n // — control flow excluded by the keyword lookahead, dotted calls\n // (this.x()) fail the anchored name-then-paren shape.\n new RegExp(\n `^\\\\s+(?:${TS_MEMBER_MODIFIERS}\\\\s+)*${KEYWORD_EXCLUSION}[\\\\w$]+(?:<[^>]*>)?\\\\s*\\\\([^)]*\\\\)\\\\s*(?::\\\\s*[^{}=;]+?)?\\\\s*(?:\\\\{\\\\s*)?\\\\}?\\\\s*$`,\n ),\n // Bodyless signatures (interface members, overloads): only when the\n // parens carry type annotations or an explicit return type follows —\n // otherwise indented calls like clearTimeout(timer); or finalize();\n // would leak into the outline.\n new RegExp(\n `^\\\\s+(?:${TS_MEMBER_MODIFIERS}\\\\s+)*${KEYWORD_EXCLUSION}[\\\\w$]+(?:<[^>]*>)?\\\\s*(?:\\\\([^)]*:[^)]*\\\\)\\\\s*(?::\\\\s*[^{}=;]+?)?|\\\\([^)]*\\\\)\\\\s*:\\\\s*[^{}=;]+?)\\\\s*;\\\\s*$`,\n ),\n];\n\nconst LANGUAGE_PATTERNS: Record<string, RegExp[]> = {\n ts: TS_LIKE,\n python: [/^\\s*(?:async\\s+)?def\\s+\\w+\\s*\\(/, /^\\s*class\\s+\\w+/],\n go: [/^func\\s+(?:\\([^)]*\\)\\s*)?\\w+\\s*\\(/, /^type\\s+\\w+\\s+(?:struct|interface)\\b/],\n rust: [\n /^\\s*(?:pub(?:\\([^)]*\\))?\\s+)?(?:async\\s+)?fn\\s+\\w+/,\n /^\\s*(?:pub\\s+)?(?:struct|enum|trait|union)\\s+\\w+/,\n ],\n jvm: [\n /^\\s*(?:(?:public|private|protected|internal|static|final|abstract|sealed|open|suspend|inline|override|async|partial|virtual|extern)\\s+)*(?:class|interface|enum|struct|record|object)\\s+\\w+/,\n /^\\s*(?:(?:public|private|protected|internal|open|suspend|inline|override)\\s+)*fun\\s+\\w+\\s*\\(/,\n new RegExp(\n `^\\\\s+(?:(?:public|private|protected|internal|static|final|abstract|sealed|open|suspend|inline|override|async|partial|virtual)\\\\s+)*[\\\\w<>[\\\\],.?]+\\\\s+${KEYWORD_EXCLUSION}\\\\w+\\\\s*\\\\([^;{}]*\\\\)\\\\s*(?:\\\\{|;|=>|$)`,\n ),\n ],\n cpp: [\n /^\\s*(?:class|struct|enum|union|namespace)\\s+\\w+/,\n new RegExp(\n `^\\\\s*(?:(?:static|inline|virtual|constexpr|extern|friend|explicit)\\\\s+)*[\\\\w:<>,~*&\\\\s]+?\\\\s+${KEYWORD_EXCLUSION}[\\\\w:~]+\\\\s*\\\\([^;]*\\\\)\\\\s*(?:const\\\\s*)?(?:noexcept\\\\s*)?(?:\\\\{|;|$)`,\n ),\n ],\n ruby: [/^\\s*def\\s+[\\w.=!?]+/, /^\\s*(?:class|module)\\s+[\\w:]+/],\n php: [\n /^\\s*(?:(?:public|private|protected|static|abstract|final)\\s+)*function\\s+\\w+\\s*\\(/,\n /^\\s*(?:(?:abstract|final)\\s+)?(?:class|interface|trait|enum)\\s+\\w+/,\n ],\n shell: [/^\\s*(?:function\\s+)?[\\w.-]+\\s*\\(\\s*\\)\\s*(?:\\{|$)/],\n swift: [\n /^\\s*(?:(?:public|private|internal|open|fileprivate|static|class|override|mutating|final)\\s+)*func\\s+\\w+\\s*\\(/,\n /^\\s*(?:(?:public|private|internal|open|final)\\s+)*(?:class|struct|enum|protocol|extension)\\s+\\w+/,\n ],\n scala: [\n /^\\s*(?:(?:private|protected|override|final|abstract|implicit)\\s+)*def\\s+\\w+\\s*[(\\[]/,\n /^\\s*(?:(?:abstract|final|sealed)\\s+)*(?:class|trait|object)\\s+\\w+/,\n ],\n};\n\nconst EXT_TO_LANGUAGE: Record<string, keyof typeof LANGUAGE_PATTERNS> = {\n ts: \"ts\",\n tsx: \"ts\",\n mts: \"ts\",\n cts: \"ts\",\n js: \"ts\",\n jsx: \"ts\",\n mjs: \"ts\",\n cjs: \"ts\",\n py: \"python\",\n pyi: \"python\",\n go: \"go\",\n rs: \"rust\",\n java: \"jvm\",\n kt: \"jvm\",\n kts: \"jvm\",\n cs: \"jvm\",\n c: \"cpp\",\n h: \"cpp\",\n cc: \"cpp\",\n cpp: \"cpp\",\n cxx: \"cpp\",\n hpp: \"cpp\",\n hh: \"cpp\",\n rb: \"ruby\",\n php: \"php\",\n sh: \"shell\",\n bash: \"shell\",\n zsh: \"shell\",\n swift: \"swift\",\n scala: \"scala\",\n sc: \"scala\",\n};\n\nfunction languageOf(filePath: string): RegExp[] | undefined {\n const name = path.basename(filePath);\n // Minified and machine-generated bundles are declaration soup; outlining\n // a bundled dependency is never useful navigation.\n if (/\\.(min|bundle|generated)\\.[^.]+$/.test(name)) return undefined;\n const ext = name.split(\".\").pop()?.toLowerCase() ?? \"\";\n const lang = EXT_TO_LANGUAGE[ext];\n return lang === undefined ? undefined : LANGUAGE_PATTERNS[lang];\n}\n\ninterface SymbolLine {\n line: number;\n indent: string;\n text: string;\n}\n\nfunction extractSymbols(text: string, patterns: RegExp[]): SymbolLine[] {\n const out: SymbolLine[] = [];\n const lines = text.split(\"\\n\");\n for (let i = 0; i < lines.length; i++) {\n const raw = (lines[i] ?? \"\").replace(/\\r$/, \"\");\n const trimmed = raw.trim();\n if (trimmed === \"\") continue;\n if (!patterns.some((re) => re.test(raw))) continue;\n const indent = raw.slice(0, raw.length - raw.trimStart().length).slice(0, MAX_INDENT_CHARS);\n const shown =\n trimmed.length > MAX_LINE_CHARS ? `${trimmed.slice(0, MAX_LINE_CHARS)}…` : trimmed;\n out.push({ line: i + 1, indent, text: shown });\n }\n return out;\n}\n\nasync function outlineFile(\n abs: string,\n): Promise<{ symbols: SymbolLine[]; total: number } | { binary: true } | { unreadable: true }> {\n const st = await stat(abs).catch(() => null);\n if (!st || st.size > MAX_FILE_BYTES) return { unreadable: true };\n const buf = await readFile(abs).catch(() => null);\n if (!buf) return { unreadable: true };\n if (buf.includes(0)) return { binary: true };\n const patterns = languageOf(abs);\n if (!patterns) return { unreadable: true };\n const all = extractSymbols(buf.toString(\"utf8\"), patterns);\n return { symbols: all.slice(0, MAX_SYMBOLS_PER_FILE), total: all.length };\n}\n\nfunction formatSymbols(symbols: SymbolLine[], total: number): string[] {\n const out = symbols.map((s) => `${s.line}\\t${s.indent}${s.text}`);\n if (total > symbols.length) {\n out.push(`... (${total - symbols.length} more declarations)`);\n }\n return out;\n}\n\nconst schema = z.object({\n path: z\n .string()\n .optional()\n .describe(\"Source file or directory to outline (default: the working directory)\"),\n maxFiles: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(`Directory mode: maximum files to include (default ${MAX_DIR_FILES})`),\n});\n\nexport const codeOutlineTool: Tool<typeof schema> = {\n name: \"code_outline\",\n description:\n \"List the declaration skeleton of a source file or directory (functions, classes, methods, types) with line numbers, without reading the bodies. Cheaper than read_file for navigating unfamiliar code: outline first, then read_file the exact line ranges you need. Supports TS/JS, Python, Go, Rust, Java/Kotlin/C#, C/C++, Ruby, PHP, Shell, Swift, Scala.\",\n permission: \"read\",\n parameters: schema,\n async execute(args, ctx) {\n const root = path.resolve(ctx.cwd, args.path ?? \".\");\n const st = await stat(root).catch(() => null);\n if (!st) {\n return { content: `Path not found: ${args.path ?? \".\"}`, isError: true };\n }\n\n if (st.isFile()) {\n // Same refusal as read_file: the raw name and the symlink target both\n // count, so a planted link cannot launder a sensitive basename.\n const resolved = await realpath(root).catch(() => null);\n if (isSensitivePath(root) || (resolved !== null && isSensitivePath(resolved))) {\n return { content: `Refused to outline sensitive file: ${args.path ?? \".\"}`, isError: true };\n }\n if (languageOf(root) === undefined) {\n return {\n content: `No supported source language for: ${args.path ?? \".\"} (supported: TS/JS, Python, Go, Rust, Java/Kotlin/C#, C/C++, Ruby, PHP, Shell, Swift, Scala)`,\n };\n }\n const result = await outlineFile(root);\n if (\"binary\" in result) {\n return { content: `Cannot outline binary file: ${args.path ?? \".\"}`, isError: true };\n }\n if (\"unreadable\" in result) {\n return {\n content: `Cannot outline ${args.path ?? \".\"}: unreadable or larger than 2MB`,\n isError: true,\n };\n }\n if (result.symbols.length === 0) {\n return { content: `(no recognizable declarations in ${args.path ?? \".\"})` };\n }\n return { content: formatSymbols(result.symbols, result.total).join(\"\\n\") };\n }\n\n const walked = await walkFiles(root, undefined, {\n ignore: createIgnorePredicate(ctx.cwd),\n withMtime: false,\n signal: ctx.abortSignal,\n symlinkBoundary: ctx.cwd,\n nestedIgnore: true,\n });\n const candidates = walked.files.filter(\n (f) =>\n languageOf(f.abs) !== undefined &&\n !isSensitivePath(f.abs) &&\n (f.resolved === undefined || !isSensitivePath(f.resolved)),\n );\n const maxFiles = args.maxFiles ?? MAX_DIR_FILES;\n\n const scan = async (\n file: WalkedFile,\n ): Promise<{ rel: string; lines: string[]; chars: number } | null> => {\n const result = await outlineFile(file.abs);\n if (\"symbols\" in result && result.symbols.length > 0) {\n const lines = formatSymbols(result.symbols, result.total);\n const chars = lines.reduce((n, l) => n + l.length + 1, file.rel.length + 2);\n return { rel: file.rel, lines, chars };\n }\n return null;\n };\n\n const out: string[] = [];\n let size = 0;\n let included = 0;\n let hitLimit = false;\n for (let i = 0; i < candidates.length && included < maxFiles; i += WALK_CONCURRENCY) {\n if (ctx.abortSignal?.aborted) break;\n const chunk = await Promise.all(\n candidates.slice(i, i + WALK_CONCURRENCY).map((file) => scan(file)),\n );\n for (const block of chunk) {\n if (!block) continue;\n if (size + block.chars > MAX_OUT_CHARS || included >= maxFiles) {\n hitLimit = true;\n break;\n }\n if (out.length > 0) out.push(\"\");\n out.push(`${block.rel}:`);\n out.push(...block.lines);\n size += block.chars;\n included += 1;\n }\n if (hitLimit) break;\n }\n if (included === 0) {\n return {\n content: `No recognizable declarations under ${args.path ?? \".\"} (${candidates.length} source file(s) scanned)`,\n };\n }\n if (hitLimit) {\n out.push(\"... (truncated: output limit reached, more files not outlined)\");\n } else if (walked.aborted || ctx.abortSignal?.aborted) {\n out.push(\"... (interrupted: partial results)\");\n }\n return { content: out.join(\"\\n\") };\n },\n};\n","import { open, realpath, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport { isSensitivePath } from \"./util\";\n\nconst DEFAULT_LIMIT = 2000;\nconst MAX_CHARS = 100 * 1024;\n// Output is capped at 100KB anyway, so reading past 1MB can never be shown.\nconst MAX_READ_BYTES = 1024 * 1024;\nconst BINARY_PROBE_BYTES = 8192;\n\nfunction decodeUtf16be(buf: Buffer): string {\n const len = buf.length - (buf.length % 2);\n const swapped = Buffer.allocUnsafe(len);\n for (let k = 0; k < len; k += 2) {\n swapped[k] = buf[k + 1] ?? 0;\n swapped[k + 1] = buf[k] ?? 0;\n }\n return swapped.toString(\"utf16le\");\n}\n\n// A UTF-16 BOM means the file is text (its NUL bytes are expected); without a\n// BOM, a NUL in the first 8KB marks a binary file.\nfunction decodeTextBuffer(buf: Buffer): { text: string } | { binary: true } {\n if (buf.length >= 2 && buf[0] === 0xff && buf[1] === 0xfe) {\n return { text: buf.subarray(2).toString(\"utf16le\") };\n }\n if (buf.length >= 2 && buf[0] === 0xfe && buf[1] === 0xff) {\n return { text: decodeUtf16be(buf.subarray(2)) };\n }\n if (buf.subarray(0, BINARY_PROBE_BYTES).includes(0)) {\n return { binary: true };\n }\n return { text: buf.toString(\"utf8\") };\n}\n\nconst schema = z.object({\n path: z.string().describe(\"File path, absolute or relative to the working directory\"),\n offset: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"1-based line number to start reading from\"),\n limit: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Maximum number of lines to read (default 2000)\"),\n});\n\n// Per-tool-instance cache of what was already sent to the model, so a re-read\n// of an unchanged file (same mtime + size) whose requested line range was\n// already returned answers with a one-line note instead of re-billing the\n// full content (aider's read-file dedup). Keyed by realpath when resolvable.\ninterface ReadCacheEntry {\n mtimeMs: number;\n size: number;\n totalLines: number;\n start: number;\n end: number;\n}\nconst READ_CACHE_MAX_ENTRIES = 200;\n\nexport function createReadFileTool(): Tool<typeof schema> {\n const cache = new Map<string, ReadCacheEntry>();\n return {\n name: \"read_file\",\n description:\n \"Read a text file and return its contents with line numbers. Output is truncated to 2000 lines or 100KB by default. Re-reading an unchanged file range returns a short note instead of the content.\",\n permission: \"read\",\n parameters: schema,\n reset: () => cache.clear(),\n async execute(args, ctx) {\n const filePath = path.resolve(ctx.cwd, args.path);\n // Check both the given path and its symlink target: a repo can plant a\n // harmless-looking link (notes.txt -> ~/.ssh/id_rsa) whose resolved name\n // is on the sensitive list. Unresolvable paths keep the raw-path check.\n const resolvedPath = await realpath(filePath).catch(() => null);\n if (isSensitivePath(filePath) || (resolvedPath !== null && isSensitivePath(resolvedPath))) {\n return { content: `Refused to read sensitive file: ${args.path}`, isError: true };\n }\n const st = await stat(filePath).catch(() => null);\n if (!st) {\n return { content: `File not found: ${args.path}`, isError: true };\n }\n if (st.isDirectory()) {\n return { content: `Path is a directory, not a file: ${args.path}`, isError: true };\n }\n const start = args.offset ?? 1;\n const limit = args.limit ?? DEFAULT_LIMIT;\n const cacheKey = resolvedPath ?? filePath;\n const hit = cache.get(cacheKey);\n if (hit && hit.mtimeMs === st.mtimeMs && hit.size === st.size) {\n const requestedEnd = Math.min(hit.totalLines, start - 1 + limit);\n if (start >= hit.start && requestedEnd <= hit.end && start <= hit.totalLines) {\n return {\n content: `[unchanged since last read: ${args.path} — lines ${start}-${requestedEnd} of ${hit.totalLines} are already in context and the file has not changed]`,\n };\n }\n }\n const bytesToRead = Math.min(st.size, MAX_READ_BYTES);\n const fileCapped = st.size > MAX_READ_BYTES;\n const handle = await open(filePath, \"r\").catch(() => null);\n if (!handle) {\n return { content: `Failed to read ${args.path}`, isError: true };\n }\n let buf: Buffer;\n try {\n const { bytesRead, buffer } = await handle.read(\n Buffer.alloc(bytesToRead),\n 0,\n bytesToRead,\n 0,\n );\n buf = buffer.subarray(0, bytesRead);\n } finally {\n await handle.close().catch(() => {});\n }\n const decoded = decodeTextBuffer(buf);\n if (\"binary\" in decoded) {\n return { content: `Cannot read binary file: ${args.path}`, isError: true };\n }\n const lines = decoded.text.split(\"\\n\");\n const totalDesc = fileCapped ? `at least ${lines.length}` : `${lines.length}`;\n if (start > lines.length) {\n return { content: `(offset ${start} beyond end of file; file has ${totalDesc} lines)` };\n }\n const end = Math.min(lines.length, start - 1 + limit);\n const out: string[] = [];\n let size = 0;\n let truncatedBySize = false;\n for (let i = start - 1; i < end; i++) {\n const line = (lines[i] ?? \"\").replace(/\\r$/, \"\");\n const numbered = `${i + 1}\\t${line}`;\n if (size + numbered.length > MAX_CHARS) {\n truncatedBySize = true;\n break;\n }\n out.push(numbered);\n size += numbered.length;\n }\n const lastShown = start - 1 + out.length;\n if (truncatedBySize) {\n out.push(\n `... (truncated: output exceeds 100KB, showing lines ${start}-${lastShown} of ${totalDesc})`,\n );\n } else if (end < lines.length || fileCapped) {\n out.push(`... (truncated: showing lines ${start}-${end} of ${totalDesc})`);\n }\n if (out.length > 0) {\n if (cache.size >= READ_CACHE_MAX_ENTRIES) cache.clear();\n const prev = hit?.mtimeMs === st.mtimeMs && hit.size === st.size ? hit : undefined;\n cache.set(cacheKey, {\n mtimeMs: st.mtimeMs,\n size: st.size,\n totalLines: lines.length,\n // Extend the remembered range when the new read overlaps or abuts\n // the previous one; disjoint ranges replace it.\n start: prev && start <= prev.end + 1 ? Math.min(prev.start, start) : start,\n end: prev && lastShown >= prev.start - 1 ? Math.max(prev.end, lastShown) : lastShown,\n });\n }\n return { content: out.join(\"\\n\") };\n },\n };\n}\n\n// Shared instance for direct consumers (tests); the tool registry creates a\n// fresh one per agent loop so a subagent's cache never claims content that\n// only the parent's context holds.\nexport const readFileTool = createReadFileTool();\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { probeImageDimensions } from \"../../core/image\";\nimport { downsampleImageIfNeeded } from \"../../core/image-resize\";\nimport type { ImageInput } from \"../../core/messages\";\nimport type { Tool } from \"../types\";\nimport { isSensitivePath } from \"./util\";\n\n// Same ceiling as @-mention image reads (src/cli/mentions.ts).\nconst MAX_IMAGE_BYTES = 5 * 1024 * 1024;\n\nconst IMAGE_MIME_TYPES: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n};\n\nconst schema = z.object({\n path: z\n .string()\n .describe(\n \"Image file path (png/jpg/jpeg/gif/webp), absolute or relative to the working directory\",\n ),\n});\n\n// Lets the model pull an image into the conversation mid-session (a screenshot\n// the user mentioned, a generated asset, a UI mock). The image itself is not\n// in the text result — the loop attaches it to the history as a user message\n// with image parts (see ToolResult.images), so every protocol sees it the same\n// way as a pasted image.\nexport const readImageTool: Tool<typeof schema> = {\n name: \"read_image\",\n description:\n \"Read an image file (png, jpg, gif, webp) and show it to the model. Use this whenever the user references a screenshot, diagram, or picture file you need to see. Images larger than 2000px are downsampled automatically.\",\n permission: \"read\",\n parameters: schema,\n async execute(args, ctx) {\n if (ctx.visionEnabled === false) {\n return {\n content:\n \"The active model does not support image input (vision = false), so the image was not read. Work from text instead, or ask the user to describe the image.\",\n isError: true,\n };\n }\n const filePath = path.resolve(ctx.cwd, args.path);\n // Same symlink-aware sensitive check as read_file.\n const resolvedPath = await realpath(filePath).catch(() => null);\n if (isSensitivePath(filePath) || (resolvedPath !== null && isSensitivePath(resolvedPath))) {\n return { content: `Refused to read sensitive file: ${args.path}`, isError: true };\n }\n const mimeType = IMAGE_MIME_TYPES[path.extname(filePath).toLowerCase()];\n if (!mimeType) {\n return {\n content: `Not a supported image (png/jpg/jpeg/gif/webp): ${args.path}`,\n isError: true,\n };\n }\n const st = await stat(filePath).catch(() => null);\n if (!st || !st.isFile()) {\n return { content: `File not found: ${args.path}`, isError: true };\n }\n if (st.size > MAX_IMAGE_BYTES) {\n return {\n content: `Image too large (${Math.round(st.size / 1024)}KB > ${MAX_IMAGE_BYTES / 1024}KB): ${args.path}`,\n isError: true,\n };\n }\n const buf = await readFile(filePath).catch(() => null);\n if (!buf || buf.length === 0) {\n return { content: `Failed to read ${args.path}`, isError: true };\n }\n if (!probeImageDimensions(buf)) {\n return {\n content: `File is not a valid image (unrecognized header): ${args.path}`,\n isError: true,\n };\n }\n const downsampled = await downsampleImageIfNeeded({\n path: args.path,\n mimeType,\n data: buf.toString(\"base64\"),\n });\n if (downsampled.oversized && !downsampled.resized) {\n return {\n content: `Image exceeds 2000px and could not be downsampled on this platform: ${args.path}`,\n isError: true,\n };\n }\n const image: ImageInput = downsampled.image;\n const dims = probeImageDimensions(Buffer.from(image.data, \"base64\"));\n const sizeKB = Math.round(image.data.length / 1024);\n const desc = dims ? `${dims.width}x${dims.height}` : \"unknown dimensions\";\n const resizedNote = downsampled.resized ? \" (downsampled to fit 2000px)\" : \"\";\n return {\n content: `Image loaded: ${args.path} (${desc}, ~${sizeKB}KB)${resizedNote}. The image is attached below — look at it now.`,\n images: [image],\n };\n },\n};\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { Tool } from \"../types\";\nimport { MAX_SNAPSHOT_CONTENT_BYTES, captureSnapshot, pushSnapshot } from \"./snapshots\";\n\nconst schema = z.object({\n path: z.string().describe(\"File path, absolute or relative to the working directory\"),\n content: z.string().describe(\"Full content to write to the file\"),\n});\n\nexport const writeFileTool: Tool<typeof schema> = {\n name: \"write_file\",\n description:\n \"Write content to a file, creating parent directories as needed. Overwrites existing files. Refuses content with NUL bytes (binary) or over 5MB.\",\n permission: \"write\",\n parameters: schema,\n async execute(args, ctx) {\n const filePath = path.resolve(ctx.cwd, args.path);\n // write_file writes UTF-8 text: NUL bytes mean the model is pushing\n // binary content that would land corrupted, and past the snapshot cap\n // /undo keeps only metadata, so the overwritten file would be\n // unrecoverable — same limits as edit_file.\n if (args.content.includes(\"\\0\")) {\n return {\n content: `Refused to write ${args.path}: content contains NUL bytes (write_file is text-only)`,\n isError: true,\n };\n }\n const bytes = Buffer.byteLength(args.content, \"utf8\");\n if (bytes > MAX_SNAPSHOT_CONTENT_BYTES) {\n return {\n content: `Refused to write ${args.path}: content is ${bytes} bytes, over the 5MB limit (writes past it could not be restored by /undo)`,\n isError: true,\n };\n }\n const snapshot = await captureSnapshot(filePath, \"write_file\", ctx.snapshotContext);\n try {\n await mkdir(path.dirname(filePath), { recursive: true });\n await writeFile(filePath, args.content, \"utf8\");\n } catch (err) {\n return { content: `Failed to write ${args.path}: ${(err as Error).message}`, isError: true };\n }\n await pushSnapshot(snapshot);\n return { content: `Wrote ${bytes} bytes to ${args.path}` };\n },\n};\n","import { z } from \"zod\";\nimport { probeImageDimensions } from \"../core/image\";\nimport { type ScreenshotResult, captureScreenshot } from \"../core/screenshot\";\nimport type { Tool } from \"./types\";\n\nconst schema = z.object({});\n\n// Lets the model look at the actual screen mid-session — the visual debugging\n// counterpart of read_image: start a dev server or GUI program, screenshot,\n// then judge the real rendered output instead of guessing from code. The\n// capture function is injectable so tests never touch a real display.\nexport function createScreenshotTool(\n capture: () => Promise<ScreenshotResult> = captureScreenshot,\n): Tool<typeof schema> {\n return {\n name: \"screenshot\",\n description:\n \"Capture a screenshot of the primary display and see it. Use this to check the actual visual result of a running program (web page, GUI) — e.g. after starting a dev server — instead of inferring from code. The capture shows exactly what is visible on screen, including overlapping windows: content hidden behind other windows cannot be seen, so if a specific window matters ask the user to bring it to the front first. Note the capture may include anything else currently on screen.\",\n permission: \"read\",\n parameters: schema,\n async execute(_args, ctx) {\n if (ctx.visionEnabled === false) {\n return {\n content:\n \"The active model does not support image input (vision = false), so no screenshot was taken. Work from text instead, or ask the user to describe what is on screen.\",\n isError: true,\n };\n }\n const result = await capture();\n if (!result.ok) {\n return { content: `Screenshot failed: ${result.error}`, isError: true };\n }\n const image = result.image;\n const dims = probeImageDimensions(Buffer.from(image.data, \"base64\"));\n const sizeKB = Math.round(image.data.length / 1024);\n const desc = dims ? `${dims.width}x${dims.height}` : \"unknown dimensions\";\n return {\n content: `Screenshot captured (${desc}, ~${sizeKB}KB). The image is attached below — look at it now.`,\n images: [image],\n };\n },\n };\n}\n\nexport const screenshotTool = createScreenshotTool();\n","import { execFile } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { readFile, unlink } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { probeImageDimensions } from \"./image\";\nimport { downsampleImageIfNeeded } from \"./image-resize\";\nimport type { ImageInput } from \"./messages\";\n\nexport const SCREENSHOT_TIMEOUT_MS = 20_000;\n\nconst execFileAsync = promisify(execFile);\n\nexport interface ScreenshotCommand {\n command: string;\n args: string[];\n}\n\nexport type ScreenshotResult = { ok: true; image: ImageInput } | { ok: false; error: string };\n\n// Windows capture script: copies the primary screen into a PNG. The position\n// problem on Windows is DPI virtualization — when the process is not truly\n// per-monitor DPI aware, the Bounds Forms reports and the pixels CopyFromScreen\n// reads live in different coordinate spaces, so at 125%/150% scaling the\n// capture comes out offset and wrongly sized. Setting per-monitor-V2 awareness\n// before touching Forms/Drawing makes both sides physical pixels; the call\n// fails harmlessly when the host manifest already pinned awareness (system\n// awareness is still physically correct on the primary display).\nexport function windowsScreenshotScript(outputFile: string): string {\n const output = outputFile.replace(/'/g, \"''\");\n return [\n \"try { Add-Type -MemberDefinition '[DllImport(\\\"user32.dll\\\")] public static extern bool SetProcessDpiAwarenessContext(int v);' -Name Dpi -Namespace StarShot -ErrorAction Stop; [void][StarShot.Dpi]::SetProcessDpiAwarenessContext(-4) } catch { }\",\n \"Add-Type -AssemblyName System.Windows.Forms,System.Drawing\",\n \"$b = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds\",\n \"$bmp = New-Object System.Drawing.Bitmap($b.Width, $b.Height)\",\n \"$g = [System.Drawing.Graphics]::FromImage($bmp)\",\n \"$g.CopyFromScreen($b.Left, $b.Top, 0, 0, $bmp.Size)\",\n `$bmp.Save('${output}', [System.Drawing.Imaging.ImageFormat]::Png)`,\n \"$g.Dispose(); $bmp.Dispose()\",\n ].join(\"; \");\n}\n\n// Platform-native capture command writing a PNG to outputFile, or null when\n// this platform/session cannot take screenshots. Windows/macOS capture the\n// primary display only — one deterministic file and physically exact bounds,\n// even on mixed-DPI multi-monitor setups; Linux tools capture the whole\n// compositor/root window (all monitors composited).\nexport function screenshotPlan(\n platform: NodeJS.Platform,\n outputFile: string,\n env: NodeJS.ProcessEnv = process.env,\n tools: Record<string, boolean> = {},\n): ScreenshotCommand | null {\n if (platform === \"win32\") {\n return {\n command: \"powershell.exe\",\n args: [\"-NoProfile\", \"-NonInteractive\", \"-Command\", windowsScreenshotScript(outputFile)],\n };\n }\n if (platform === \"darwin\") {\n // -x silences the shutter sound; -D 1 pins the main display so a single\n // output file is deterministic no matter how many monitors are attached.\n return { command: \"screencapture\", args: [\"-x\", \"-D\", \"1\", outputFile] };\n }\n if (platform === \"linux\") {\n if (env.WAYLAND_DISPLAY) {\n if (tools.grim) return { command: \"grim\", args: [outputFile] };\n if (tools[\"gnome-screenshot\"]) {\n return { command: \"gnome-screenshot\", args: [\"-f\", outputFile] };\n }\n if (tools.spectacle) {\n return { command: \"spectacle\", args: [\"-b\", \"-n\", \"-o\", outputFile] };\n }\n return null;\n }\n if (env.DISPLAY) {\n if (tools.import) return { command: \"import\", args: [\"-window\", \"root\", outputFile] };\n if (tools.scrot) return { command: \"scrot\", args: [\"--overwrite\", outputFile] };\n if (tools[\"gnome-screenshot\"]) {\n return { command: \"gnome-screenshot\", args: [\"-f\", outputFile] };\n }\n if (tools.spectacle) {\n return { command: \"spectacle\", args: [\"-b\", \"-n\", \"-o\", outputFile] };\n }\n return null;\n }\n return null;\n }\n return null;\n}\n\nexport function noScreenshotToolMessage(\n platform: NodeJS.Platform,\n env: NodeJS.ProcessEnv = process.env,\n): string {\n if (platform === \"linux\") {\n if (!env.WAYLAND_DISPLAY && !env.DISPLAY) {\n return \"no display server (neither DISPLAY nor WAYLAND_DISPLAY is set) — this session is headless (e.g. SSH), there is no screen to capture\";\n }\n return \"no screenshot tool found — install one of: grim or spectacle (Wayland), scrot or ImageMagick's import (X11), or gnome-screenshot\";\n }\n return `screenshots are not supported on this platform (${platform})`;\n}\n\nasync function commandExists(command: string): Promise<boolean> {\n const checker = process.platform === \"win32\" ? \"where\" : \"which\";\n try {\n await execFileAsync(checker, [command], { timeout: SCREENSHOT_TIMEOUT_MS });\n return true;\n } catch {\n return false;\n }\n}\n\nconst LINUX_TOOL_NAMES = [\"grim\", \"gnome-screenshot\", \"spectacle\", \"import\", \"scrot\"];\n\n// Captures the screen into a temp PNG via platform-native tools (no npm image\n// dependency), downsamples past 2000px like read_image, and returns the image\n// for the loop to attach to the history. Failures come back as messages the\n// model can act on instead of exceptions.\nexport async function captureScreenshot(): Promise<ScreenshotResult> {\n const outputFile = path.join(os.tmpdir(), `star-screenshot-${randomUUID()}.png`);\n try {\n const tools: Record<string, boolean> = {};\n if (process.platform === \"linux\") {\n const found = await Promise.all(LINUX_TOOL_NAMES.map(commandExists));\n for (const [i, name] of LINUX_TOOL_NAMES.entries()) {\n tools[name] = found[i] ?? false;\n }\n }\n const plan = screenshotPlan(process.platform, outputFile, process.env, tools);\n if (!plan) {\n return { ok: false, error: noScreenshotToolMessage(process.platform) };\n }\n try {\n await execFileAsync(plan.command, plan.args, { timeout: SCREENSHOT_TIMEOUT_MS });\n } catch (err) {\n const detail = err instanceof Error && err.message ? ` (${err.message})` : \"\";\n return { ok: false, error: `${plan.command} failed to capture the screen${detail}` };\n }\n const buf = await readFile(outputFile).catch(() => null);\n if (!buf || buf.length === 0) {\n return { ok: false, error: `${plan.command} produced no image file` };\n }\n if (!probeImageDimensions(buf)) {\n return { ok: false, error: `${plan.command} produced an unrecognized image file` };\n }\n const downsampled = await downsampleImageIfNeeded({\n path: \"screen\",\n mimeType: \"image/png\",\n data: buf.toString(\"base64\"),\n });\n if (downsampled.oversized && !downsampled.resized) {\n return {\n ok: false,\n error: \"screenshot exceeds 2000px and could not be downsampled on this platform\",\n };\n }\n return { ok: true, image: downsampled.image };\n } finally {\n await unlink(outputFile).catch(() => {});\n }\n}\n","import { z } from \"zod\";\nimport { type AgentTaskSnapshot, defaultAgentTasks } from \"../agent/agent-tasks\";\nimport { formatDuration, formatTaskLine, formatTaskList } from \"../tasks/format\";\nimport { type TaskSnapshot, defaultTaskManager } from \"../tasks/manager\";\nimport { MAX_OUTPUT } from \"./bash\";\nimport type { Tool, ToolContext } from \"./types\";\n\nconst idSchema = z.object({\n id: z.string().describe(\"Task id, e.g. task-1 or agent-1\"),\n});\n\n// Aligns with the foreground bash output cap: keep the tail, note the cut.\nfunction truncateOutput(s: string): string {\n if (s.length <= MAX_OUTPUT) return s;\n return `[... earlier output truncated; showing the last ${MAX_OUTPUT} characters ...]\\n${s.slice(-MAX_OUTPUT)}`;\n}\n\n// Shell tasks are owned by the agent that started them: root sees and\n// controls everything, a subagent only its own tasks — otherwise one\n// subagent could kill the parent's (or a sibling's) background work.\n// Unowned/foreign tasks answer \"Unknown task\" so their existence doesn't\n// leak either. Background subagents (agent-*) always belong to root:\n// subagents can't spawn subagents.\nfunction callerId(ctx: ToolContext): string {\n return ctx.agentId ?? \"root\";\n}\n\nfunction accessibleShellTask(ctx: ToolContext, id: string): TaskSnapshot | undefined {\n const task = defaultTaskManager.get(id);\n if (!task) return undefined;\n const caller = callerId(ctx);\n return caller === \"root\" || task.ownerId === caller ? task : undefined;\n}\n\nfunction formatAgentTaskLine(task: AgentTaskSnapshot): string {\n const duration = formatDuration(task.startedAt, task.endedAt);\n const label = task.description ?? task.prompt.slice(0, 60);\n const status =\n task.status === \"running\" ? `running ${duration}` : `${task.status} after ${duration}`;\n return `${task.id} [${status}] ${label}`;\n}\n\nexport const taskListTool: Tool = {\n name: \"task_list\",\n description: \"List background tasks (shell commands and subagents) with status and runtime.\",\n permission: \"read\",\n parameters: z.object({}),\n execute(_args, ctx) {\n const caller = callerId(ctx);\n const shell = formatTaskList(\n defaultTaskManager.list().filter((t) => caller === \"root\" || t.ownerId === caller),\n );\n const agents = caller === \"root\" ? defaultAgentTasks.list() : [];\n const agentLines =\n agents.length === 0\n ? \"No background subagents.\"\n : `Background subagents:\\n${agents.map(formatAgentTaskLine).join(\"\\n\")}`;\n return Promise.resolve({ content: `${shell}\\n${agentLines}` });\n },\n};\n\nexport const taskOutputTool: Tool<typeof idSchema> = {\n name: \"task_output\",\n description:\n \"Read the current output of a background task (shell command or subagent; works while still running).\",\n permission: \"read\",\n parameters: idSchema,\n execute(args, ctx) {\n const shell = accessibleShellTask(ctx, args.id);\n if (shell) {\n const body = truncateOutput(shell.output.replace(/\\s+$/, \"\") || \"(no output yet)\");\n return Promise.resolve({ content: `${formatTaskLine(shell)}\\n${body}` });\n }\n const agent = callerId(ctx) === \"root\" ? defaultAgentTasks.get(args.id) : undefined;\n if (agent) {\n const body =\n agent.status === \"running\"\n ? \"(still running)\"\n : truncateOutput(agent.result.replace(/\\s+$/, \"\") || \"(no report)\");\n return Promise.resolve({ content: `${formatAgentTaskLine(agent)}\\n${body}` });\n }\n return Promise.resolve({ content: `Unknown task: ${args.id}`, isError: true });\n },\n};\n\nexport const taskKillTool: Tool<typeof idSchema> = {\n name: \"task_kill\",\n description: \"Stop a running background task (shell command process tree or subagent).\",\n permission: \"exec\",\n parameters: idSchema,\n execute(args, ctx) {\n const shell = accessibleShellTask(ctx, args.id);\n const agent = shell || callerId(ctx) !== \"root\" ? undefined : defaultAgentTasks.get(args.id);\n const task = shell ?? agent;\n if (!task) {\n return Promise.resolve({ content: `Unknown task: ${args.id}`, isError: true });\n }\n if (task.status !== \"running\") {\n return Promise.resolve({\n content: `Task ${args.id} is not running (status: ${task.status}).`,\n isError: true,\n });\n }\n if (shell) {\n defaultTaskManager.kill(args.id);\n } else {\n defaultAgentTasks.kill(args.id);\n }\n return Promise.resolve({ content: `Task ${args.id} stopped.` });\n },\n};\n","import type { TaskSnapshot } from \"./manager\";\n\nexport function formatDuration(startedAt: number, endedAt?: number): string {\n const seconds = Math.max(0, Math.round(((endedAt ?? Date.now()) - startedAt) / 1000));\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m${seconds % 60}s`;\n return `${Math.floor(minutes / 60)}h${minutes % 60}m`;\n}\n\nfunction formatStatus(task: TaskSnapshot): string {\n const duration = formatDuration(task.startedAt, task.endedAt);\n if (task.status === \"running\") return `running ${duration}`;\n const exit =\n task.exitCode === null || task.exitCode === undefined ? \"\" : `, exit ${task.exitCode}`;\n return `${task.status}${exit} after ${duration}`;\n}\n\nexport function formatTaskLine(task: TaskSnapshot): string {\n const label = task.description ? `${task.description} (${task.command})` : task.command;\n return `${task.id} [${formatStatus(task)}] ${label}`;\n}\n\nexport function formatTaskList(tasks: TaskSnapshot[]): string {\n if (tasks.length === 0) return \"No background tasks.\";\n return `Background tasks:\\n${tasks.map(formatTaskLine).join(\"\\n\")}`;\n}\n\nexport function formatTaskStarted(task: TaskSnapshot): string {\n const label = task.description ? `${task.description} (${task.command})` : task.command;\n return `Background task ${task.id} started: ${label}`;\n}\n\nexport function formatTaskFinished(task: TaskSnapshot): string {\n const exit =\n task.exitCode === null || task.exitCode === undefined ? \"\" : ` (exit ${task.exitCode})`;\n switch (task.status) {\n case \"completed\":\n return `Background task ${task.id} finished${exit}: ${task.command}`;\n case \"failed\":\n return `Background task ${task.id} failed${exit}: ${task.command}`;\n case \"timed_out\":\n return `Background task ${task.id} timed out: ${task.command}`;\n case \"stopped\":\n return `Background task ${task.id} stopped: ${task.command}`;\n default:\n return `Background task ${task.id}: ${task.command}`;\n }\n}\n","import { z } from \"zod\";\nimport { debugStreamLog } from \"../../llm/debug\";\nimport type { Tool } from \"../types\";\nimport { decodeEntities } from \"./fetch\";\n\nconst TIMEOUT_MS = 15000;\nconst DEFAULT_MAX_RESULTS = 5;\nconst MAX_RESULTS_LIMIT = 10;\nconst USER_AGENT =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36\";\n\nconst schema = z.object({\n query: z.string().min(1).describe(\"The search query\"),\n maxResults: z\n .number()\n .int()\n .min(1)\n .max(MAX_RESULTS_LIMIT)\n .optional()\n .describe(\n `Maximum number of results to return (default ${DEFAULT_MAX_RESULTS}, max ${MAX_RESULTS_LIMIT})`,\n ),\n});\n\nexport interface SearchResult {\n title: string;\n url: string;\n snippet: string;\n}\n\n// A search backend: builds the request URL for a query and parses its HTML\n// into the unified {title, url, snippet} shape. Sources are tried in order;\n// a network error, non-2xx status or zero parsed results falls through to\n// the next one.\ninterface SearchSource {\n name: string;\n buildUrl: (query: string) => string;\n parse: (html: string) => SearchResult[];\n}\n\nfunction stripTags(s: string): string {\n return decodeEntities(s.replace(/<[^>]+>/g, \" \"))\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction normalizeUrl(href: string): string {\n const decoded = decodeEntities(href);\n const uddg = decoded.match(/[?&]uddg=([^&]+)/);\n if (uddg?.[1]) {\n try {\n return decodeURIComponent(uddg[1]);\n } catch {\n return decoded;\n }\n }\n if (decoded.startsWith(\"//\")) {\n return `https:${decoded}`;\n }\n return decoded;\n}\n\nfunction hrefOf(tag: string): string | undefined {\n const match = tag.match(/href\\s*=\\s*\"([^\"]*)\"/i) ?? tag.match(/href\\s*=\\s*'([^']*)'/i);\n return match?.[1];\n}\n\nexport function parseResults(html: string): SearchResult[] {\n const results: SearchResult[] = [];\n const anchorRe = /<a\\b[^>]*\\bclass\\s*=\\s*\"[^\"]*\\bresult__a\\b[^\"]*\"[^>]*>[\\s\\S]*?<\\/a>/gi;\n const anchors = [...html.matchAll(anchorRe)];\n for (const [i, anchor] of anchors.entries()) {\n const full = anchor[0];\n const href = hrefOf(full);\n if (!href) {\n continue;\n }\n const url = normalizeUrl(href);\n const title = stripTags(full.replace(/^<a\\b[^>]*>/i, \"\").replace(/<\\/a>\\s*$/i, \"\"));\n const blockStart = (anchor.index ?? 0) + full.length;\n const blockEnd = i + 1 < anchors.length ? (anchors[i + 1]?.index ?? html.length) : html.length;\n const block = html.slice(blockStart, blockEnd);\n const snippetMatch = block.match(\n /<(?:a|div)\\b[^>]*\\bclass\\s*=\\s*\"[^\"]*\\bresult__snippet\\b[^\"]*\"[^>]*>([\\s\\S]*?)<\\/(?:a|div)>/i,\n );\n const snippet = snippetMatch?.[1] ? stripTags(snippetMatch[1]) : \"\";\n if (title && url) {\n results.push({ title, url, snippet });\n }\n }\n return results;\n}\n\n// lite.duckduckgo.com serves a different (table-based) layout: titles in\n// <a class=\"result-link\">, snippets in the following <td class=\"result-snippet\">.\nexport function parseDdgLiteResults(html: string): SearchResult[] {\n const results: SearchResult[] = [];\n const anchorRe =\n /<a\\b[^>]*\\bclass\\s*=\\s*[\"'][^\"']*\\bresult-link\\b[^\"']*[\"'][^>]*>[\\s\\S]*?<\\/a>/gi;\n const anchors = [...html.matchAll(anchorRe)];\n for (const [i, anchor] of anchors.entries()) {\n const full = anchor[0];\n const href = hrefOf(full);\n if (!href) {\n continue;\n }\n const url = normalizeUrl(href);\n const title = stripTags(full.replace(/^<a\\b[^>]*>/i, \"\").replace(/<\\/a>\\s*$/i, \"\"));\n const blockStart = (anchor.index ?? 0) + full.length;\n const blockEnd = i + 1 < anchors.length ? (anchors[i + 1]?.index ?? html.length) : html.length;\n const block = html.slice(blockStart, blockEnd);\n const snippetMatch = block.match(\n /<td\\b[^>]*\\bclass\\s*=\\s*[\"'][^\"']*\\bresult-snippet\\b[^\"']*[\"'][^>]*>([\\s\\S]*?)<\\/td>/i,\n );\n const snippet = snippetMatch?.[1] ? stripTags(snippetMatch[1]) : \"\";\n if (title && url) {\n results.push({ title, url, snippet });\n }\n }\n return results;\n}\n\n// www.bing.com/search needs no key: results are <li class=\"b_algo\"> blocks\n// with the title link in <h2><a> and the snippet in the block's first <p>.\nexport function parseBingResults(html: string): SearchResult[] {\n const results: SearchResult[] = [];\n const blockRe = /<li\\b[^>]*\\bclass\\s*=\\s*\"[^\"]*\\bb_algo\\b[^\"]*\"[^>]*>/gi;\n const blocks = [...html.matchAll(blockRe)];\n for (const [i, block] of blocks.entries()) {\n const start = block.index ?? 0;\n const end = i + 1 < blocks.length ? (blocks[i + 1]?.index ?? html.length) : html.length;\n const slice = html.slice(start, end);\n const headMatch = slice.match(\n /<h2\\b[^>]*>[\\s\\S]*?<a\\b[^>]*?\\shref\\s*=\\s*\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/a>[\\s\\S]*?<\\/h2>/i,\n );\n if (!headMatch) {\n continue;\n }\n const url = decodeEntities(headMatch[1] ?? \"\").trim();\n const title = stripTags(headMatch[2] ?? \"\");\n const snippetMatch = slice.match(/<p\\b[^>]*>([\\s\\S]*?)<\\/p>/i);\n const snippet = snippetMatch?.[1] ? stripTags(snippetMatch[1]) : \"\";\n if (title && /^https?:\\/\\//.test(url)) {\n results.push({ title, url, snippet });\n }\n }\n return results;\n}\n\nconst SEARCH_SOURCES: SearchSource[] = [\n {\n name: \"duckduckgo-html\",\n buildUrl: (query) => `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`,\n parse: parseResults,\n },\n {\n name: \"duckduckgo-lite\",\n buildUrl: (query) => `https://lite.duckduckgo.com/lite/?q=${encodeURIComponent(query)}`,\n parse: parseDdgLiteResults,\n },\n {\n name: \"bing\",\n buildUrl: (query) => `https://www.bing.com/search?q=${encodeURIComponent(query)}`,\n parse: parseBingResults,\n },\n];\n\nexport const webSearchTool: Tool<typeof schema> = {\n name: \"web_search\",\n description:\n \"Search the web and return a numbered list of results with title, URL and snippet. Uses DuckDuckGo with automatic fallback to DuckDuckGo Lite and Bing when a source fails or returns nothing. No API key required. Use web_fetch to read a result's full page.\",\n permission: \"read\",\n parameters: schema,\n async execute(args, ctx) {\n const maxResults = Math.min(args.maxResults ?? DEFAULT_MAX_RESULTS, MAX_RESULTS_LIMIT);\n const failures: string[] = [];\n for (const source of SEARCH_SOURCES) {\n const timeoutSignal = AbortSignal.timeout(TIMEOUT_MS);\n const signal = ctx.abortSignal\n ? AbortSignal.any([timeoutSignal, ctx.abortSignal])\n : timeoutSignal;\n let res: Response;\n try {\n res = await fetch(source.buildUrl(args.query), {\n signal,\n redirect: \"follow\",\n headers: { \"user-agent\": USER_AGENT, accept: \"text/html\" },\n });\n } catch (err) {\n if (ctx.abortSignal?.aborted) {\n return { content: \"ERROR: request aborted\", isError: true };\n }\n const name = err instanceof Error ? err.name : \"\";\n if (timeoutSignal.aborted || name === \"TimeoutError\") {\n failures.push(`${source.name}: search timed out after ${TIMEOUT_MS / 1000}s`);\n } else {\n const message = err instanceof Error ? err.message : String(err);\n failures.push(`${source.name}: search request failed: ${message}`);\n }\n continue;\n }\n if (!res.ok) {\n await res.body?.cancel().catch(() => {});\n failures.push(`${source.name}: HTTP ${res.status} ${res.statusText}`);\n continue;\n }\n let html: string;\n try {\n html = await res.text();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n failures.push(`${source.name}: failed to read search response: ${message}`);\n continue;\n }\n const results = source.parse(html).slice(0, maxResults);\n if (results.length === 0) {\n failures.push(\n `${source.name}: no results found (the response may have been blocked or the page layout changed)`,\n );\n continue;\n }\n debugStreamLog(\"web_search\", {\n source: source.name,\n query: args.query,\n results: results.length,\n failures,\n });\n const lines = results.map(\n (r, i) => `${i + 1}. ${r.title}\\n ${r.url}${r.snippet ? `\\n ${r.snippet}` : \"\"}`,\n );\n return { content: lines.join(\"\\n\") };\n }\n debugStreamLog(\"web_search_failed\", { query: args.query, failures });\n return {\n content: `ERROR: web search failed for \"${args.query}\" — ${failures.join(\"; \")}`,\n isError: true,\n };\n },\n};\n","import { appendFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { starHome } from \"../config/paths\";\n\n// STAR_DEBUG-gated JSONL log of stream internals (~/.star-cli/debug.log):\n// what the provider actually sent — finish reasons, usage, error details —\n// so a misbehaving relay can be diagnosed from the client side. All write\n// failures are silent; logging must never break a turn.\nexport function debugStreamLog(event: string, data?: Record<string, unknown>): void {\n if (!process.env.STAR_DEBUG) return;\n try {\n const line = `${JSON.stringify({ ts: new Date().toISOString(), event, ...data })}\\n`;\n appendFileSync(path.join(starHome(), \"debug.log\"), line);\n } catch {\n // best-effort only\n }\n}\n","import { bashTool } from \"./bash\";\nimport { editFileTool } from \"./fs/edit\";\nimport { globTool } from \"./fs/glob\";\nimport { grepTool } from \"./fs/grep\";\nimport { codeOutlineTool } from \"./fs/outline\";\nimport { createReadFileTool } from \"./fs/read\";\nimport { readImageTool } from \"./fs/read-image\";\nimport { writeFileTool } from \"./fs/write\";\nimport { screenshotTool } from \"./screenshot\";\nimport { taskKillTool, taskListTool, taskOutputTool } from \"./tasks\";\nimport { type TodoStore, createTodoTools, sharedTodoStore } from \"./todo\";\nimport type { Tool } from \"./types\";\nimport { webFetchTool } from \"./web/fetch\";\nimport { webSearchTool } from \"./web/search\";\n\nexport class ToolRegistry {\n private tools = new Map<string, Tool>();\n\n // todoStore defaults to the module-level shared store; subagent loops pass\n // their own instance so a child's todo_write cannot clobber the parent list.\n // Exposed so the agent loop can watch open items for staleness.\n readonly todos: TodoStore;\n\n constructor(todoStore?: TodoStore) {\n this.todos = todoStore ?? sharedTodoStore();\n for (const tool of [\n // Fresh per registry (i.e. per agent loop): the unchanged-since-last-\n // read cache must not leak across loops, whose contexts differ.\n createReadFileTool(),\n readImageTool,\n screenshotTool,\n writeFileTool,\n editFileTool,\n globTool,\n grepTool,\n codeOutlineTool,\n bashTool,\n webFetchTool,\n webSearchTool,\n taskListTool,\n taskOutputTool,\n taskKillTool,\n ...createTodoTools(this.todos),\n ]) {\n this.register(tool);\n }\n }\n\n register(tool: Tool): void {\n this.tools.set(tool.name, tool);\n }\n\n // Drops every tool the predicate rejects. Used to restrict a read-only\n // subagent loop's tool set; the agent loop reads list() lazily per\n // request, so a retain right after loop construction still shapes the\n // first request. The permission gate stays as backstop for anything\n // attempted outside the model's tool map.\n retain(predicate: (tool: Tool) => boolean): void {\n for (const [name, tool] of this.tools) {\n if (!predicate(tool)) this.tools.delete(name);\n }\n }\n\n // Drops per-session volatile tool state after a wholesale history rewrite\n // (compaction, /undo, resume): anything a tool remembers as \"already sent\n // to the model\" may no longer be in the context.\n resetVolatileState(): void {\n for (const tool of this.tools.values()) tool.reset?.();\n }\n\n get(name: string): Tool | undefined {\n return this.tools.get(name);\n }\n\n list(): Tool[] {\n return [...this.tools.values()];\n }\n\n names(): string[] {\n return [...this.tools.keys()];\n }\n}\n","import { ToolRegistry } from \"./registry\";\nimport type { TodoStore } from \"./todo\";\n\nexport { ToolRegistry } from \"./registry\";\nexport { TodoStore, createTodoTools, setTodoPersistGuard } from \"./todo\";\nexport type { TodoItem } from \"./todo\";\nexport type { PermissionLevel, Tool, ToolContext, ToolResult } from \"./types\";\n\n// The registry constructor registers every built-in tool (todo tools\n// included); this helper only forwards the optional per-loop todo store.\nexport function createDefaultRegistry(todoStore?: TodoStore): ToolRegistry {\n return new ToolRegistry(todoStore);\n}\n"],"mappings":"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","names":["path","z","schema","z","path","readFile","stat","path","z","schema","z","path","stat","readFile","readFile","realpath","stat","path","z","MAX_FILE_BYTES","MAX_LINE_CHARS","path","stat","readFile","schema","z","realpath","realpath","stat","path","z","BINARY_PROBE_BYTES","schema","z","path","realpath","stat","readFile","realpath","stat","path","z","schema","z","path","realpath","stat","readFile","writeFile","path","z","schema","z","path","writeFile","z","readFile","path","path","readFile","schema","z","z","z","z","path","path","schema","z"]}
@@ -3,15 +3,15 @@ import {
3
3
  AgentLoop,
4
4
  PLAN_MODE_PROMPT,
5
5
  attachTurnContext
6
- } from "./chunk-RE3NOULF.js";
7
- import "./chunk-56ZIA57D.js";
6
+ } from "./chunk-63CGUF3F.js";
7
+ import "./chunk-N4MIQSNZ.js";
8
8
  import "./chunk-MVAMPVTA.js";
9
9
  import "./chunk-4IRY44TG.js";
10
- import "./chunk-OIJYNQFZ.js";
11
- import "./chunk-A5PXPWHB.js";
10
+ import "./chunk-Q5FJN4LN.js";
11
+ import "./chunk-LSYGHLRU.js";
12
12
  export {
13
13
  AgentLoop,
14
14
  PLAN_MODE_PROMPT,
15
15
  attachTurnContext
16
16
  };
17
- //# sourceMappingURL=loop-PVOSF6LR.js.map
17
+ //# sourceMappingURL=loop-AY4PXRVP.js.map
package/dist/main.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  resolveMentions,
17
17
  resolveSessionId,
18
18
  summarizeArgs
19
- } from "./chunk-VJFWTXWN.js";
19
+ } from "./chunk-GYXF6NPC.js";
20
20
  import {
21
21
  ConfigSchema,
22
22
  HookConfigSchema,
@@ -24,9 +24,8 @@ import {
24
24
  PermissionsConfigSchema,
25
25
  ProviderConfigSchema,
26
26
  contextWindowTokens,
27
- reconcileStarMessages,
28
- toCoreMessages
29
- } from "./chunk-56ZIA57D.js";
27
+ reconcileStarMessages
28
+ } from "./chunk-N4MIQSNZ.js";
30
29
  import {
31
30
  resolveModelConfig,
32
31
  resolveStartupModel
@@ -42,7 +41,7 @@ import {
42
41
  registerSensitivePatterns,
43
42
  setTodoSession,
44
43
  setWebFetchAllowPrivateHosts
45
- } from "./chunk-A5PXPWHB.js";
44
+ } from "./chunk-LSYGHLRU.js";
46
45
 
47
46
  // src/main.tsx
48
47
  import { Command } from "commander";
@@ -406,7 +405,7 @@ function wireRuntimeSettings(config) {
406
405
 
407
406
  // src/main.tsx
408
407
  async function createLoop(config, modelName, cwd, sessionStore) {
409
- const [{ AgentLoop }, { createModel, reasoningEffortMetadata }, { createDefaultRegistry }] = await Promise.all([import("./loop-PVOSF6LR.js"), import("./provider-EWMUPBLH.js"), import("./tools-JDTACJYX.js")]);
408
+ const [{ AgentLoop }, { createModel, reasoningEffortMetadata }, { createDefaultRegistry }] = await Promise.all([import("./loop-AY4PXRVP.js"), import("./provider-EWMUPBLH.js"), import("./tools-BH55BVIS.js")]);
410
409
  const model = createModel(config, modelName);
411
410
  const registry = createDefaultRegistry();
412
411
  const modelConfig = resolveModelConfig(config, modelName);
@@ -659,14 +658,14 @@ program.name("star").description("Star CLI \u2014 an AI agent command-line inter
659
658
  console.error(ttyError);
660
659
  process.exit(1);
661
660
  }
662
- const { renderRepl } = await import("./repl-OO7C6V7M.js");
661
+ const { renderRepl } = await import("./repl-YBNTJOSB.js");
663
662
  renderRepl(loop, {
664
663
  model: modelName,
665
664
  permissionMode: config.permissionMode,
666
665
  config,
667
666
  cwd,
668
667
  sessionStore,
669
- initialMessages: resumed ? toCoreMessages(resumed.messages) : void 0,
668
+ initialMessages: resumed ? resumed.messages : void 0,
670
669
  initialUsage: resumed?.meta.usage
671
670
  });
672
671
  });
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/main.tsx","../src/cli/print-human.ts","../src/cli/print-json.ts","../src/cli/startup.ts","../src/config/loader.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { defaultAgentTasks } from \"./agent/agent-tasks\";\nimport type { AgentLoop } from \"./agent/loop\";\nimport { formatTokens } from \"./cli/cost\";\nimport { formatStreamError } from \"./cli/format\";\nimport { MAX_IMAGE_BYTES, imageMimeType, readImageInput, resolveMentions } from \"./cli/mentions\";\nimport { printEventLine } from \"./cli/print-human\";\nimport { UsageTracker, eventToJsonLine } from \"./cli/print-json\";\nimport {\n imageRequiresPrintError,\n installStdoutEpipeGuard,\n interactiveRequiresTtyError,\n reportResumeSessions,\n} from \"./cli/startup\";\nimport { SYSTEM_PROMPT } from \"./cli/system-prompt\";\nimport { loadConfigSync } from \"./config/loader\";\nimport { type StarConfig, contextWindowTokens } from \"./config/schema\";\nimport {\n type ImageInput,\n type StarMessage,\n reconcileStarMessages,\n toCoreMessages,\n} from \"./core/messages\";\nimport { resolveModelConfig, resolveStartupModel } from \"./llm/registry\";\nimport { loadSessionSnapshots } from \"./session/checkpoints\";\nimport { clearSessions } from \"./session/clear\";\nimport { findLatestSession, resolveSessionId } from \"./session/list\";\nimport { type SessionMeta, SessionStore } from \"./session/store\";\nimport { defaultTaskManager } from \"./tasks/manager\";\nimport { hydrateSnapshots } from \"./tools/fs/snapshots\";\nimport { loadTodos, setTodoSession } from \"./tools/todo\";\nimport { VERSION } from \"./version\";\n\nasync function createLoop(\n config: StarConfig,\n modelName: string,\n cwd: string,\n sessionStore: SessionStore | null,\n) {\n // Dynamic like the REPL import below: the agent loop pulls in the ai SDK\n // and every @ai-sdk provider (~100ms of module evaluation) that --version,\n // --help, session listing and --clear-sessions never need.\n const [{ AgentLoop }, { createModel, reasoningEffortMetadata }, { createDefaultRegistry }] =\n await Promise.all([import(\"./agent/loop\"), import(\"./llm/provider\"), import(\"./tools\")]);\n const model = createModel(config, modelName);\n const registry = createDefaultRegistry();\n const modelConfig = resolveModelConfig(config, modelName);\n return new AgentLoop({\n model,\n registry,\n config,\n cwd,\n system: SYSTEM_PROMPT,\n sessionStore,\n modelName,\n contextMaxTokens: contextWindowTokens(config, modelName),\n providerMetadata: reasoningEffortMetadata(config, modelName),\n temperature: modelConfig.temperature,\n streamIdleTimeoutSec: modelConfig.streamIdleTimeoutSec,\n streamFirstChunkTimeoutSec: modelConfig.streamFirstChunkTimeoutSec,\n vision: modelConfig.vision,\n });\n}\n\nasync function printMode(\n loop: AgentLoop,\n prompt: string,\n cwd: string,\n json: boolean,\n imagePaths: string[],\n sessionStore: SessionStore | null,\n): Promise<number> {\n const flagImages: ImageInput[] = [];\n for (const imagePath of imagePaths) {\n if (!imageMimeType(imagePath)) {\n process.stderr.write(\n `[error] unsupported image type: ${imagePath} (supported: png, jpg, jpeg, gif, webp)\\n`,\n );\n return 1;\n }\n const image = await readImageInput(imagePath, cwd);\n if (!image) {\n process.stderr.write(\n `[error] cannot read image: ${imagePath} (missing, unreadable, or larger than ${MAX_IMAGE_BYTES / (1024 * 1024)}MB)\\n`,\n );\n return 1;\n }\n flagImages.push(image);\n }\n const controller = new AbortController();\n process.on(\"SIGINT\", () => controller.abort());\n loop.onHookWarning = (message) => {\n process.stderr.write(`[hook] ${message}\\n`);\n };\n const resolved = await resolveMentions(prompt, cwd);\n if (resolved.attached.length > 0) {\n process.stderr.write(`[attached] ${resolved.attached.join(\", \")}\\n`);\n }\n for (const skip of resolved.skipped) {\n process.stderr.write(`[skipped] @${skip.path}: ${skip.reason}\\n`);\n }\n const images = [...flagImages, ...resolved.images];\n const input: string | { text: string; images: ImageInput[] } =\n images.length > 0 ? { text: resolved.input, images } : resolved.input;\n const usage = new UsageTracker();\n let exitCode = 0;\n try {\n for await (const event of loop.stream(input, controller.signal, {\n persistAs: prompt,\n })) {\n if (json) {\n const line = eventToJsonLine(event);\n if (line) process.stdout.write(`${line}\\n`);\n } else {\n // Human-readable path: tool args are the one-line summarizeArgs\n // digest (same as the REPL tool cards), never the full JSON.\n const line = printEventLine(event);\n if (line) {\n (line.stream === \"stdout\" ? process.stdout : process.stderr).write(line.text);\n }\n }\n switch (event.type) {\n case \"finish\":\n usage.add(event.usage);\n // A resumed session (-c/-r -p) must accumulate this turn's usage,\n // same as the REPL does; plain print runs have no store.\n if (event.usage) {\n sessionStore?.addUsage(event.usage).catch(() => {});\n }\n break;\n case \"error\":\n exitCode = 1;\n break;\n }\n if (exitCode !== 0) break;\n }\n } catch (error) {\n if (!(error instanceof DOMException && error.name === \"AbortError\")) {\n const message = error instanceof Error ? formatStreamError(error) : String(error);\n process.stderr.write(`\\n[error] ${message}\\n`);\n exitCode = 1;\n }\n }\n const usageLine = usage.toJsonLine();\n if (usageLine) {\n if (json) {\n process.stdout.write(`${usageLine}\\n`);\n } else {\n const t = usage.totals;\n process.stderr.write(\n `[usage] ${t.requests} requests, ${formatTokens(t.promptTokens)} prompt + ${formatTokens(t.completionTokens)} completion = ${formatTokens(t.totalTokens)} tokens\\n`,\n );\n }\n }\n if (!json) process.stdout.write(\"\\n\");\n const killedShells = defaultTaskManager.cleanup();\n const killedAgents = defaultAgentTasks.cleanup();\n const stopped = killedShells.length + killedAgents.length;\n if (stopped > 0) {\n process.stderr.write(\n `[info] ${stopped} background task(s) were still running and have been stopped.\\n`,\n );\n }\n return exitCode;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"star\")\n .description(\"Star CLI — an AI agent command-line interface\")\n .version(VERSION)\n .option(\"-m, --model <model>\", \"model to use\")\n .option(\"--permission-mode <mode>\", \"permission mode: ask | auto | readonly | yolo | plan\")\n .option(\"-p, --print <prompt>\", \"non-interactive print mode\")\n .option(\"--json\", \"output NDJSON events on stdout (print mode only)\")\n .option(\n \"--image <path>\",\n \"attach an image file (png/jpg/jpeg/gif/webp, max 5MB); repeatable\",\n (value: string, previous: string[]) => [...previous, value],\n [] as string[],\n )\n .option(\"-r, --resume [sessionId]\", \"resume a previous session (lists sessions when no id given)\")\n .option(\"-c, --continue\", \"continue the most recent session for the current directory\")\n .option(\n \"--clear-sessions [scope]\",\n \"delete stored sessions for the current directory ('all' deletes every session) and exit\",\n )\n .action(async (opts) => {\n installStdoutEpipeGuard();\n const cwd = process.cwd();\n\n if (opts.json && opts.print === undefined) {\n console.error(\n '--json requires print mode: use star -p \"...\" --json (the interactive REPL does not support JSON output).',\n );\n process.exit(1);\n }\n\n const imageError = imageRequiresPrintError(opts.print, opts.image ?? []);\n if (imageError) {\n console.error(imageError);\n process.exit(1);\n }\n\n if (opts.resume !== undefined && opts.continue) {\n console.error(\"Options --resume and --continue are mutually exclusive: pick one.\");\n process.exit(1);\n }\n\n if (opts.resume === true) {\n process.exit(await reportResumeSessions(cwd));\n }\n\n if (opts.clearSessions !== undefined) {\n const scope = opts.clearSessions;\n if (scope !== true && scope !== \"all\") {\n console.error(`Invalid scope: ${scope}. Use --clear-sessions or --clear-sessions all.`);\n process.exit(1);\n }\n const all = scope === \"all\";\n const removed = await clearSessions(all ? undefined : cwd);\n console.log(\n all\n ? `Deleted ${removed} session(s) across all directories.`\n : `Deleted ${removed} session(s) for this directory.`,\n );\n process.exit(0);\n }\n\n let config: StarConfig;\n try {\n config = loadConfigSync(cwd, { model: opts.model, permissionMode: opts.permissionMode });\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n let sessionStore: SessionStore | null = null;\n let resumed: { meta: SessionMeta; messages: StarMessage[] } | null = null;\n let resumeId: string | null = null;\n if (typeof opts.resume === \"string\") {\n resumeId = await resolveSessionId(opts.resume);\n if (!resumeId) {\n console.error(`Session not found: ${opts.resume}`);\n process.exit(1);\n }\n } else if (opts.continue) {\n const latest = await findLatestSession(cwd);\n if (latest) {\n resumeId = latest.id;\n } else {\n process.stderr.write(\"No previous session for this directory — starting a new session.\\n\");\n }\n }\n\n if (resumeId) {\n // Open the store once and read through it: resumeSession() would open a\n // second SessionStore instance on the same directory whose independent\n // meta cache could race this instance's writes.\n sessionStore = await SessionStore.open(resumeId);\n if (!sessionStore) {\n console.error(`Session not found: ${resumeId}`);\n process.exit(1);\n }\n const [meta, loaded] = await Promise.all([sessionStore.meta(), sessionStore.starMessages()]);\n const messages = reconcileStarMessages(loaded);\n if (messages.length !== loaded.length) {\n await sessionStore.replaceMessages(messages);\n }\n resumed = { meta, messages };\n setTodoSession(resumeId);\n }\n\n // An explicit --model already landed in config.defaultModel (loader\n // override) and wins; otherwise a resumed session's recorded model is\n // restored when it still resolves in the config.\n const { name: modelName, notice: modelNotice } = resolveStartupModel(\n config,\n opts.model ? undefined : resumed?.meta.model,\n );\n if (modelNotice) {\n process.stderr.write(`${modelNotice}\\n`);\n }\n if (!modelName) {\n console.error(\n \"No model configured. Add one to ~/.star-cli/config.toml or pass --model.\\n\" +\n \"See README.md for configuration examples.\",\n );\n process.exit(1);\n }\n\n if (!resumeId && !opts.print) {\n sessionStore = await SessionStore.create(cwd, modelName);\n setTodoSession(sessionStore.id);\n }\n\n let loop: AgentLoop;\n try {\n loop = await createLoop(config, modelName, cwd, sessionStore);\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n if (resumed) {\n await loop.loadMessages(resumed.messages);\n // Resuming explicitly continues the project: rehydrate its todo list\n // (fresh sessions leave it alone even when .star/todos.json exists, and\n // a list owned by another session is not adopted).\n await loadTodos(cwd, resumeId ?? undefined);\n if (sessionStore) {\n hydrateSnapshots(await loadSessionSnapshots(sessionStore.dir));\n }\n }\n\n if (opts.print) {\n // Let the loop drain instead of process.exit(): force-exiting on Windows\n // can hit a libuv assertion while undici keep-alive handles are closing.\n process.exitCode = await printMode(\n loop,\n opts.print,\n cwd,\n Boolean(opts.json),\n opts.image ?? [],\n sessionStore,\n );\n return;\n }\n\n // The REPL needs a real terminal on both ends; check before paying for\n // the Ink import so a piped launch fails fast with a clear message.\n const ttyError = interactiveRequiresTtyError({\n stdinTTY: Boolean(process.stdin.isTTY),\n stdoutTTY: Boolean(process.stdout.isTTY),\n });\n if (ttyError) {\n console.error(ttyError);\n process.exit(1);\n }\n\n // The REPL pulls in Ink and every interactive component (~0.4s of module\n // evaluation): load it only on the interactive path so -p, --version,\n // --clear-sessions and session listing stay cheap.\n const { renderRepl } = await import(\"./cli/repl\");\n renderRepl(loop, {\n model: modelName,\n permissionMode: config.permissionMode,\n config,\n cwd,\n sessionStore,\n initialMessages: resumed ? toCoreMessages(resumed.messages) : undefined,\n initialUsage: resumed?.meta.usage,\n });\n });\n\nprogram.parse(process.argv);\n","import type { StreamEvent } from \"../core/events\";\nimport { formatStreamError, summarizeArgs } from \"./format\";\n\nexport interface PrintLine {\n stream: \"stdout\" | \"stderr\";\n text: string;\n}\n\n// Human-readable (-p without --json) rendering of one stream event. Tool\n// args go through the same one-line summarizeArgs digest the REPL tool cards\n// use instead of the full JSON; print-json (machine consumption) keeps the\n// complete payload. Returns null for events this path ignores (reasoning,\n// tool-call progress) — finish is accounted separately via UsageTracker and\n// error additionally flips the exit code, both handled by the caller.\nexport function printEventLine(event: StreamEvent): PrintLine | null {\n switch (event.type) {\n case \"text-delta\":\n return { stream: \"stdout\", text: event.text };\n case \"tool-call\":\n return { stream: \"stderr\", text: `\\n[tool] ${event.name} ${summarizeArgs(event.args)}\\n` };\n case \"tool-result\": {\n const preview =\n event.content.length > 500\n ? `${event.content.slice(0, 500)}... (truncated)`\n : event.content;\n return {\n stream: \"stderr\",\n text: `[result] ${event.isError ? \"ERROR: \" : \"\"}${preview}\\n`,\n };\n }\n case \"retry\": {\n const wait =\n event.delayMs !== undefined && event.delayMs >= 1000\n ? ` in ${Math.round(event.delayMs / 1000)}s`\n : \"\";\n return {\n stream: \"stderr\",\n text: `\\n[retry ${event.attempt}/${event.maxAttempts}${wait}] ${event.reason}\\n`,\n };\n }\n case \"notice\":\n return { stream: \"stderr\", text: `\\n[notice] ${event.message}\\n` };\n case \"error\":\n return { stream: \"stderr\", text: `\\n[error] ${formatStreamError(event.error)}\\n` };\n default:\n return null;\n }\n}\n","import type { StreamEvent, TokenUsage } from \"../core/events\";\n\nexport function eventToJsonLine(event: StreamEvent): string | null {\n switch (event.type) {\n case \"finish\":\n return null;\n case \"error\":\n return JSON.stringify({ type: \"error\", error: { message: event.error.message } });\n default:\n return JSON.stringify(event);\n }\n}\n\nexport class UsageTracker {\n private requests = 0;\n private promptTokens = 0;\n private completionTokens = 0;\n private totalTokens = 0;\n\n add(usage?: TokenUsage): void {\n if (!usage) return;\n this.requests += 1;\n this.promptTokens += usage.promptTokens;\n this.completionTokens += usage.completionTokens;\n this.totalTokens += usage.totalTokens;\n }\n\n get totals(): TokenUsage & { requests: number } {\n return {\n requests: this.requests,\n promptTokens: this.promptTokens,\n completionTokens: this.completionTokens,\n totalTokens: this.totalTokens,\n };\n }\n\n toJsonLine(): string | null {\n if (this.requests === 0) return null;\n return JSON.stringify({\n type: \"usage\",\n requests: this.requests,\n promptTokens: this.promptTokens,\n completionTokens: this.completionTokens,\n totalTokens: this.totalTokens,\n });\n }\n}\n","import { formatSessionEntries, listSessionEntries } from \"../session/list\";\n\n// Guards for the CLI entry paths, kept out of main.tsx (which parses argv at\n// module scope) so tests can exercise them without launching commander.\n\nexport interface StartupStreams {\n stdinTTY: boolean;\n stdoutTTY: boolean;\n}\n\n// --image only has a consumer in print mode; without -p the file would be\n// silently dropped when the REPL starts, so fail at startup instead.\nexport function imageRequiresPrintError(\n print: string | undefined,\n images: readonly string[],\n): string | null {\n if (print !== undefined) return null;\n return images.length > 0 ? \"--image requires -p/--print\" : null;\n}\n\n// Ink needs a real terminal on both ends; piped stdin/stdout used to leave a\n// bare stack or a hung process.\nexport function interactiveRequiresTtyError(streams: StartupStreams): string | null {\n return streams.stdinTTY && streams.stdoutTTY\n ? null\n : \"interactive mode requires a TTY; use -p/--print\";\n}\n\n// A downstream pipe that closes early (star -p \"...\" | head -1) turns the next\n// stdout write into an EPIPE \"error\" event; exit quietly instead of dumping a\n// raw stack.\nexport function installStdoutEpipeGuard(stdout: NodeJS.WriteStream = process.stdout): void {\n stdout.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error?.code === \"EPIPE\") process.exit(0);\n else throw error;\n });\n}\n\n// `star -r` without an id prints the session picker list and leaves; a script\n// must be able to tell \"no sessions\" apart from a successful listing, hence\n// the non-zero code.\nexport async function reportResumeSessions(cwd: string): Promise<number> {\n const entries = await listSessionEntries(cwd);\n if (entries.length === 0) {\n console.error(\"No sessions found for this directory.\");\n return 1;\n }\n console.log(formatSessionEntries(entries));\n return 0;\n}\n","import fs from \"node:fs\";\nimport { parse } from \"smol-toml\";\nimport { registerSensitivePatterns } from \"../core/sensitive\";\nimport { setWebFetchAllowPrivateHosts } from \"../tools/web/fetch\";\nimport { loadEnvFile } from \"./env\";\nimport { globalConfigPath, projectConfigPath } from \"./paths\";\nimport {\n type CliOverrides,\n ConfigSchema,\n HookConfigSchema,\n type ModelConfig,\n ModelConfigSchema,\n PermissionsConfigSchema,\n ProviderConfigSchema,\n type StarConfig,\n} from \"./schema\";\n\nconst PartialConfigSchema = ConfigSchema.partial();\n\ntype PartialConfig = ReturnType<typeof PartialConfigSchema.parse>;\n\n// Which file a parsed config came from: project files warn differently —\n// schema-known keys the sandbox strips get sanitizeProjectConfig's \"project\n// config cannot set this key\", so the unknown-key diff only reports keys the\n// schema does not know at all.\ntype ConfigScope = \"global\" | \"project\";\n\nfunction parseTomlFile(content: string, filePath: string, scope: ConfigScope): PartialConfig {\n let raw: unknown;\n try {\n raw = parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to parse TOML in ${filePath}: ${message}`);\n }\n const result = PartialConfigSchema.safeParse(raw);\n if (!result.success) {\n // One readable line per issue instead of zod's single JSON blob.\n const details = result.error.issues\n .map((issue) => {\n const where = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n return ` ${where}: ${issue.message}`;\n })\n .join(\"\\n\");\n throw new Error(`Invalid config in ${filePath}:\\n${details}`);\n }\n warnUnknownKeys(raw, filePath, scope);\n return result.data;\n}\n\n// Keys a project-level .star/config.toml may set. Anything else (providers,\n// permissionMode, permissions, hooks, ...) stays global-only: a checked-out\n// repo must not be able to plant shell hooks, force yolo mode, or redirect\n// provider traffic to a key-harvesting endpoint.\nconst PROJECT_ALLOWED_KEYS = new Set([\n \"defaultModel\",\n \"models\",\n \"maxSteps\",\n \"contextMaxTokens\",\n \"compactThresholdTokens\",\n \"streamIdleTimeoutSec\",\n \"streamFirstChunkTimeoutSec\",\n \"streamMaxRetries\",\n \"maxAutoContinues\",\n \"contextCompaction\",\n \"sessionBudgetUsd\",\n \"notifyBell\",\n \"notifyBellThresholdSec\",\n \"doomLoopThreshold\",\n \"gitSnapshots\",\n]);\n\n// Safe ranges for the project-provided streaming knobs: a repo must not set\n// pathological values (sub-second idle timeouts, thousands of retries).\nconst PROJECT_STREAM_RANGES = {\n streamIdleTimeoutSec: { min: 5, max: 120 },\n streamFirstChunkTimeoutSec: { min: 30, max: 900 },\n streamMaxRetries: { min: 0, max: 10 },\n} as const;\n\n// 0 disables these protections, so a project may only tighten them, never\n// turn them off (handled at merge time via min()).\nconst PROJECT_PROTECTIVE_MIN_KEYS = new Set([\"maxSteps\", \"doomLoopThreshold\"]);\n\n// Known keys per schema-defined section, for the unknown-key diff.\nconst TOP_LEVEL_KEYS = new Set(Object.keys(ConfigSchema.shape));\nconst SECTION_KEYS: Record<string, { keys: Set<string>; array: boolean }> = {\n permissions: { keys: new Set(Object.keys(PermissionsConfigSchema.shape)), array: false },\n providers: { keys: new Set(Object.keys(ProviderConfigSchema.shape)), array: true },\n models: { keys: new Set(Object.keys(ModelConfigSchema.shape)), array: true },\n hooks: { keys: new Set(Object.keys(HookConfigSchema.shape)), array: true },\n};\n\nfunction editDistance(a: string, b: string): number {\n let previous: number[] = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const current: number[] = [i];\n for (let j = 1; j <= b.length; j++) {\n current[j] = Math.min(\n (previous[j] ?? 0) + 1,\n (current[j - 1] ?? 0) + 1,\n (previous[j - 1] ?? 0) + (a[i - 1] === b[j - 1] ? 0 : 1),\n );\n }\n previous = current;\n }\n return previous[b.length] ?? 0;\n}\n\n// Cheap \"did you mean\": case-insensitive Levenshtein against the known keys,\n// accepted when the distance is small relative to the key's length.\nfunction suggestKey(key: string, known: Set<string>): string | undefined {\n const needle = key.toLowerCase();\n let best: string | undefined;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (const candidate of known) {\n const distance = editDistance(needle, candidate.toLowerCase());\n if (distance <= Math.max(1, Math.floor(candidate.length / 4)) && distance < bestDistance) {\n best = candidate;\n bestDistance = distance;\n }\n }\n return best;\n}\n\nfunction warnUnknownKey(keyPath: string, filePath: string, known: Set<string>): void {\n const leaf = keyPath.slice(keyPath.lastIndexOf(\".\") + 1);\n const suggestion = suggestKey(leaf, known);\n const hint = suggestion\n ? `possible typo of \"${suggestion}\"? the key is ignored`\n : \"possible typo? the key is ignored\";\n process.stderr.write(`[star] unknown config key \"${keyPath}\" in ${filePath}: ${hint}\\n`);\n}\n\n// zod object schemas strip unknown keys without a word, so a misspelled\n// option (\"streamMaxRetreis\") would otherwise vanish silently. Diff the raw\n// TOML against the schema shapes and warn once per unknown key — top level\n// plus inside the schema-defined sections ([permissions], [[providers]],\n// [[models]], [[hooks]]). Warnings never block loading. In project files,\n// schema-known sections the sandbox drops wholesale (everything but\n// [[models]]) already get sanitizeProjectConfig's own warning, so their\n// inner keys are not diffed.\nfunction warnUnknownKeys(raw: unknown, filePath: string, scope: ConfigScope): void {\n if (typeof raw !== \"object\" || raw === null) return;\n const table = raw as Record<string, unknown>;\n for (const key of Object.keys(table)) {\n if (!TOP_LEVEL_KEYS.has(key)) warnUnknownKey(key, filePath, TOP_LEVEL_KEYS);\n }\n for (const [section, { keys, array }] of Object.entries(SECTION_KEYS)) {\n if (scope === \"project\" && !PROJECT_ALLOWED_KEYS.has(section)) continue;\n const value = table[section];\n if (array) {\n if (!Array.isArray(value)) continue;\n value.forEach((entry, index) => {\n if (typeof entry !== \"object\" || entry === null) return;\n for (const key of Object.keys(entry)) {\n if (!keys.has(key)) warnUnknownKey(`${section}[${index}].${key}`, filePath, keys);\n }\n });\n continue;\n }\n if (typeof value !== \"object\" || value === null) continue;\n for (const key of Object.keys(value as Record<string, unknown>)) {\n if (!keys.has(key)) warnUnknownKey(`${section}.${key}`, filePath, keys);\n }\n }\n}\n\nfunction warnProject(filePath: string, message: string): void {\n process.stderr.write(`[star] ${message} in ${filePath}\\n`);\n}\n\n// Price fields are stripped from project models: a repo defining $0 prices\n// would silently zero out /cost and defeat sessionBudgetUsd.\nfunction stripModelPrices(models: ModelConfig[], filePath: string): ModelConfig[] {\n let stripped = false;\n const out = models.map((model) => {\n const { promptPrice, completionPrice, cacheReadPrice, ...rest } = model;\n if (\n promptPrice !== undefined ||\n completionPrice !== undefined ||\n cacheReadPrice !== undefined\n ) {\n stripped = true;\n }\n return rest;\n });\n if (stripped) {\n warnProject(filePath, \"ignoring price fields in project [[models]]: pricing stays global-only\");\n }\n return out;\n}\n\nfunction sanitizeProjectConfig(project: PartialConfig, filePath: string): PartialConfig {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(project)) {\n if (value === undefined) continue;\n if (!PROJECT_ALLOWED_KEYS.has(key)) {\n process.stderr.write(\n `[star] ignoring \"${key}\" in ${filePath}: project config cannot set this key\\n`,\n );\n continue;\n }\n if (key === \"gitSnapshots\" && value === false) {\n // Snapshot tracking protects /undo and /redo; a repo may enable but\n // never disable it.\n warnProject(\n filePath,\n 'ignoring \"gitSnapshots = false\": project config cannot disable this protection',\n );\n continue;\n }\n if (PROJECT_PROTECTIVE_MIN_KEYS.has(key) && value === 0) {\n warnProject(filePath, `ignoring \"${key} = 0\": project config cannot disable this protection`);\n continue;\n }\n const range = PROJECT_STREAM_RANGES[key as keyof typeof PROJECT_STREAM_RANGES];\n if (range && typeof value === \"number\") {\n const clamped = Math.min(range.max, Math.max(range.min, value));\n if (clamped !== value) {\n warnProject(\n filePath,\n `clamping \"${key}\" from ${value} to ${clamped}: project config is limited to ${range.min}–${range.max}`,\n );\n }\n sanitized[key] = clamped;\n continue;\n }\n if (key === \"models\" && Array.isArray(value)) {\n sanitized[key] = stripModelPrices(value as ModelConfig[], filePath);\n continue;\n }\n sanitized[key] = value;\n }\n return sanitized as PartialConfig;\n}\n\n// Project [[models]] merge with the global table by name: a project entry\n// replaces the same-named global entry, every other global entry survives.\n// (Shallow-spreading the array would let a repo silently swap the user's\n// whole model table — and orphan a global defaultModel pointing into it.)\nfunction mergeModelsByName(\n globalModels: ModelConfig[],\n projectModels: ModelConfig[],\n): ModelConfig[] {\n const projectByName = new Map(projectModels.map((model) => [model.name, model]));\n const merged = globalModels.map((model) => projectByName.get(model.name) ?? model);\n const globalNames = new Set(globalModels.map((model) => model.name));\n for (const model of projectModels) {\n if (!globalNames.has(model.name)) merged.push(model);\n }\n return merged;\n}\n\n// 0 disables these protections (unlimited), so normalize it to +∞ before the\n// min: a project must be able to tighten a globally-disabled guard (global\n// maxSteps = 0, project 5 → 5), never to relax one.\nfunction protectiveMin(a: number, b: number): number {\n const result = Math.min(\n a === 0 ? Number.POSITIVE_INFINITY : a,\n b === 0 ? Number.POSITIVE_INFINITY : b,\n );\n return result === Number.POSITIVE_INFINITY ? 0 : result;\n}\n\n// Project values merge protectively: a repo can tighten safeguards but never\n// relax them. Budgets take the lower bound; guard thresholds take the lower\n// bound too (a project-side 0 = disabled was already filtered out above, and\n// a global 0 normalizes to +∞ via protectiveMin).\nfunction mergeProjectConfig(\n global: PartialConfig,\n project: PartialConfig,\n projectPath: string,\n): PartialConfig {\n const merged: PartialConfig = { ...global, ...project };\n if (project.models !== undefined) {\n merged.models = mergeModelsByName(global.models ?? [], project.models);\n warnProject(projectPath, `project config overrides ${project.models.length} model(s)`);\n }\n if (project.sessionBudgetUsd !== undefined && global.sessionBudgetUsd !== undefined) {\n merged.sessionBudgetUsd = Math.min(global.sessionBudgetUsd, project.sessionBudgetUsd);\n }\n if (project.maxSteps !== undefined) {\n merged.maxSteps = protectiveMin(global.maxSteps ?? 100, project.maxSteps);\n }\n if (project.doomLoopThreshold !== undefined) {\n merged.doomLoopThreshold = protectiveMin(\n global.doomLoopThreshold ?? 3,\n project.doomLoopThreshold,\n );\n }\n return merged;\n}\n\n// Plaintext keys still work, but config.toml is world-readable by default on\n// some setups and gets committed by accident — point users at apiKeyEnv.\nfunction warnPlaintextApiKey(config: PartialConfig): void {\n const offenders: string[] = [];\n for (const provider of config.providers ?? []) {\n if (provider.apiKey !== undefined) offenders.push(`provider \"${provider.name}\"`);\n }\n for (const model of config.models ?? []) {\n if (\"apiKey\" in model && model.apiKey !== undefined) offenders.push(`model \"${model.name}\"`);\n }\n if (offenders.length === 0) return;\n process.stderr.write(\n `[star] plaintext apiKey in config (${offenders.join(\", \")}) is deprecated: store keys in ~/.star-cli/.env and reference them with apiKeyEnv instead\\n`,\n );\n}\n\nfunction applyOverrides(config: PartialConfig, overrides?: CliOverrides): PartialConfig {\n if (!overrides) return config;\n const merged = { ...config };\n if (overrides.model !== undefined) merged.defaultModel = overrides.model;\n if (overrides.permissionMode !== undefined) merged.permissionMode = overrides.permissionMode;\n return merged;\n}\n\nasync function readTomlFile(filePath: string, scope: ConfigScope): Promise<PartialConfig> {\n let content: string;\n try {\n content = await fs.promises.readFile(filePath, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return {};\n throw error;\n }\n return parseTomlFile(content, filePath, scope);\n}\n\nfunction readTomlFileSync(filePath: string, scope: ConfigScope): PartialConfig {\n if (!fs.existsSync(filePath)) return {};\n const content = fs.readFileSync(filePath, \"utf8\");\n return parseTomlFile(content, filePath, scope);\n}\n\nexport async function loadConfig(cwd: string, overrides?: CliOverrides): Promise<StarConfig> {\n loadEnvFile();\n const global = await readTomlFile(globalConfigPath(), \"global\");\n const projectPath = projectConfigPath(cwd);\n const project = sanitizeProjectConfig(await readTomlFile(projectPath, \"project\"), projectPath);\n const merged = applyOverrides(mergeProjectConfig(global, project, projectPath), overrides);\n warnPlaintextApiKey(merged);\n return wireRuntimeSettings(ConfigSchema.parse(merged));\n}\n\nexport function loadConfigSync(cwd: string, overrides?: CliOverrides): StarConfig {\n loadEnvFile();\n const global = readTomlFileSync(globalConfigPath(), \"global\");\n const projectPath = projectConfigPath(cwd);\n const project = sanitizeProjectConfig(readTomlFileSync(projectPath, \"project\"), projectPath);\n const merged = applyOverrides(mergeProjectConfig(global, project, projectPath), overrides);\n warnPlaintextApiKey(merged);\n return wireRuntimeSettings(ConfigSchema.parse(merged));\n}\n\n// Pushes config-driven security settings into their runtime consumers. The\n// merged permissions table is global-only at this point (the project sandbox\n// dropped any project-side [permissions]), so these can never be planted by\n// a checked-out repo.\nfunction wireRuntimeSettings(config: StarConfig): StarConfig {\n registerSensitivePatterns(config.permissions.sensitive);\n setWebFetchAllowPrivateHosts(config.webFetchAllowPrivateHosts);\n return config;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/main.tsx","../src/cli/print-human.ts","../src/cli/print-json.ts","../src/cli/startup.ts","../src/config/loader.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { defaultAgentTasks } from \"./agent/agent-tasks\";\nimport type { AgentLoop } from \"./agent/loop\";\nimport { formatTokens } from \"./cli/cost\";\nimport { formatStreamError } from \"./cli/format\";\nimport { MAX_IMAGE_BYTES, imageMimeType, readImageInput, resolveMentions } from \"./cli/mentions\";\nimport { printEventLine } from \"./cli/print-human\";\nimport { UsageTracker, eventToJsonLine } from \"./cli/print-json\";\nimport {\n imageRequiresPrintError,\n installStdoutEpipeGuard,\n interactiveRequiresTtyError,\n reportResumeSessions,\n} from \"./cli/startup\";\nimport { SYSTEM_PROMPT } from \"./cli/system-prompt\";\nimport { loadConfigSync } from \"./config/loader\";\nimport { type StarConfig, contextWindowTokens } from \"./config/schema\";\nimport { type ImageInput, type StarMessage, reconcileStarMessages } from \"./core/messages\";\nimport { resolveModelConfig, resolveStartupModel } from \"./llm/registry\";\nimport { loadSessionSnapshots } from \"./session/checkpoints\";\nimport { clearSessions } from \"./session/clear\";\nimport { findLatestSession, resolveSessionId } from \"./session/list\";\nimport { type SessionMeta, SessionStore } from \"./session/store\";\nimport { defaultTaskManager } from \"./tasks/manager\";\nimport { hydrateSnapshots } from \"./tools/fs/snapshots\";\nimport { loadTodos, setTodoSession } from \"./tools/todo\";\nimport { VERSION } from \"./version\";\n\nasync function createLoop(\n config: StarConfig,\n modelName: string,\n cwd: string,\n sessionStore: SessionStore | null,\n) {\n // Dynamic like the REPL import below: the agent loop pulls in the ai SDK\n // and every @ai-sdk provider (~100ms of module evaluation) that --version,\n // --help, session listing and --clear-sessions never need.\n const [{ AgentLoop }, { createModel, reasoningEffortMetadata }, { createDefaultRegistry }] =\n await Promise.all([import(\"./agent/loop\"), import(\"./llm/provider\"), import(\"./tools\")]);\n const model = createModel(config, modelName);\n const registry = createDefaultRegistry();\n const modelConfig = resolveModelConfig(config, modelName);\n return new AgentLoop({\n model,\n registry,\n config,\n cwd,\n system: SYSTEM_PROMPT,\n sessionStore,\n modelName,\n contextMaxTokens: contextWindowTokens(config, modelName),\n providerMetadata: reasoningEffortMetadata(config, modelName),\n temperature: modelConfig.temperature,\n streamIdleTimeoutSec: modelConfig.streamIdleTimeoutSec,\n streamFirstChunkTimeoutSec: modelConfig.streamFirstChunkTimeoutSec,\n vision: modelConfig.vision,\n });\n}\n\nasync function printMode(\n loop: AgentLoop,\n prompt: string,\n cwd: string,\n json: boolean,\n imagePaths: string[],\n sessionStore: SessionStore | null,\n): Promise<number> {\n const flagImages: ImageInput[] = [];\n for (const imagePath of imagePaths) {\n if (!imageMimeType(imagePath)) {\n process.stderr.write(\n `[error] unsupported image type: ${imagePath} (supported: png, jpg, jpeg, gif, webp)\\n`,\n );\n return 1;\n }\n const image = await readImageInput(imagePath, cwd);\n if (!image) {\n process.stderr.write(\n `[error] cannot read image: ${imagePath} (missing, unreadable, or larger than ${MAX_IMAGE_BYTES / (1024 * 1024)}MB)\\n`,\n );\n return 1;\n }\n flagImages.push(image);\n }\n const controller = new AbortController();\n process.on(\"SIGINT\", () => controller.abort());\n loop.onHookWarning = (message) => {\n process.stderr.write(`[hook] ${message}\\n`);\n };\n const resolved = await resolveMentions(prompt, cwd);\n if (resolved.attached.length > 0) {\n process.stderr.write(`[attached] ${resolved.attached.join(\", \")}\\n`);\n }\n for (const skip of resolved.skipped) {\n process.stderr.write(`[skipped] @${skip.path}: ${skip.reason}\\n`);\n }\n const images = [...flagImages, ...resolved.images];\n const input: string | { text: string; images: ImageInput[] } =\n images.length > 0 ? { text: resolved.input, images } : resolved.input;\n const usage = new UsageTracker();\n let exitCode = 0;\n try {\n for await (const event of loop.stream(input, controller.signal, {\n persistAs: prompt,\n })) {\n if (json) {\n const line = eventToJsonLine(event);\n if (line) process.stdout.write(`${line}\\n`);\n } else {\n // Human-readable path: tool args are the one-line summarizeArgs\n // digest (same as the REPL tool cards), never the full JSON.\n const line = printEventLine(event);\n if (line) {\n (line.stream === \"stdout\" ? process.stdout : process.stderr).write(line.text);\n }\n }\n switch (event.type) {\n case \"finish\":\n usage.add(event.usage);\n // A resumed session (-c/-r -p) must accumulate this turn's usage,\n // same as the REPL does; plain print runs have no store.\n if (event.usage) {\n sessionStore?.addUsage(event.usage).catch(() => {});\n }\n break;\n case \"error\":\n exitCode = 1;\n break;\n }\n if (exitCode !== 0) break;\n }\n } catch (error) {\n if (!(error instanceof DOMException && error.name === \"AbortError\")) {\n const message = error instanceof Error ? formatStreamError(error) : String(error);\n process.stderr.write(`\\n[error] ${message}\\n`);\n exitCode = 1;\n }\n }\n const usageLine = usage.toJsonLine();\n if (usageLine) {\n if (json) {\n process.stdout.write(`${usageLine}\\n`);\n } else {\n const t = usage.totals;\n process.stderr.write(\n `[usage] ${t.requests} requests, ${formatTokens(t.promptTokens)} prompt + ${formatTokens(t.completionTokens)} completion = ${formatTokens(t.totalTokens)} tokens\\n`,\n );\n }\n }\n if (!json) process.stdout.write(\"\\n\");\n const killedShells = defaultTaskManager.cleanup();\n const killedAgents = defaultAgentTasks.cleanup();\n const stopped = killedShells.length + killedAgents.length;\n if (stopped > 0) {\n process.stderr.write(\n `[info] ${stopped} background task(s) were still running and have been stopped.\\n`,\n );\n }\n return exitCode;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"star\")\n .description(\"Star CLI — an AI agent command-line interface\")\n .version(VERSION)\n .option(\"-m, --model <model>\", \"model to use\")\n .option(\"--permission-mode <mode>\", \"permission mode: ask | auto | readonly | yolo | plan\")\n .option(\"-p, --print <prompt>\", \"non-interactive print mode\")\n .option(\"--json\", \"output NDJSON events on stdout (print mode only)\")\n .option(\n \"--image <path>\",\n \"attach an image file (png/jpg/jpeg/gif/webp, max 5MB); repeatable\",\n (value: string, previous: string[]) => [...previous, value],\n [] as string[],\n )\n .option(\"-r, --resume [sessionId]\", \"resume a previous session (lists sessions when no id given)\")\n .option(\"-c, --continue\", \"continue the most recent session for the current directory\")\n .option(\n \"--clear-sessions [scope]\",\n \"delete stored sessions for the current directory ('all' deletes every session) and exit\",\n )\n .action(async (opts) => {\n installStdoutEpipeGuard();\n const cwd = process.cwd();\n\n if (opts.json && opts.print === undefined) {\n console.error(\n '--json requires print mode: use star -p \"...\" --json (the interactive REPL does not support JSON output).',\n );\n process.exit(1);\n }\n\n const imageError = imageRequiresPrintError(opts.print, opts.image ?? []);\n if (imageError) {\n console.error(imageError);\n process.exit(1);\n }\n\n if (opts.resume !== undefined && opts.continue) {\n console.error(\"Options --resume and --continue are mutually exclusive: pick one.\");\n process.exit(1);\n }\n\n if (opts.resume === true) {\n process.exit(await reportResumeSessions(cwd));\n }\n\n if (opts.clearSessions !== undefined) {\n const scope = opts.clearSessions;\n if (scope !== true && scope !== \"all\") {\n console.error(`Invalid scope: ${scope}. Use --clear-sessions or --clear-sessions all.`);\n process.exit(1);\n }\n const all = scope === \"all\";\n const removed = await clearSessions(all ? undefined : cwd);\n console.log(\n all\n ? `Deleted ${removed} session(s) across all directories.`\n : `Deleted ${removed} session(s) for this directory.`,\n );\n process.exit(0);\n }\n\n let config: StarConfig;\n try {\n config = loadConfigSync(cwd, { model: opts.model, permissionMode: opts.permissionMode });\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n let sessionStore: SessionStore | null = null;\n let resumed: { meta: SessionMeta; messages: StarMessage[] } | null = null;\n let resumeId: string | null = null;\n if (typeof opts.resume === \"string\") {\n resumeId = await resolveSessionId(opts.resume);\n if (!resumeId) {\n console.error(`Session not found: ${opts.resume}`);\n process.exit(1);\n }\n } else if (opts.continue) {\n const latest = await findLatestSession(cwd);\n if (latest) {\n resumeId = latest.id;\n } else {\n process.stderr.write(\"No previous session for this directory — starting a new session.\\n\");\n }\n }\n\n if (resumeId) {\n // Open the store once and read through it: resumeSession() would open a\n // second SessionStore instance on the same directory whose independent\n // meta cache could race this instance's writes.\n sessionStore = await SessionStore.open(resumeId);\n if (!sessionStore) {\n console.error(`Session not found: ${resumeId}`);\n process.exit(1);\n }\n const [meta, loaded] = await Promise.all([sessionStore.meta(), sessionStore.starMessages()]);\n const messages = reconcileStarMessages(loaded);\n if (messages.length !== loaded.length) {\n await sessionStore.replaceMessages(messages);\n }\n resumed = { meta, messages };\n setTodoSession(resumeId);\n }\n\n // An explicit --model already landed in config.defaultModel (loader\n // override) and wins; otherwise a resumed session's recorded model is\n // restored when it still resolves in the config.\n const { name: modelName, notice: modelNotice } = resolveStartupModel(\n config,\n opts.model ? undefined : resumed?.meta.model,\n );\n if (modelNotice) {\n process.stderr.write(`${modelNotice}\\n`);\n }\n if (!modelName) {\n console.error(\n \"No model configured. Add one to ~/.star-cli/config.toml or pass --model.\\n\" +\n \"See README.md for configuration examples.\",\n );\n process.exit(1);\n }\n\n if (!resumeId && !opts.print) {\n sessionStore = await SessionStore.create(cwd, modelName);\n setTodoSession(sessionStore.id);\n }\n\n let loop: AgentLoop;\n try {\n loop = await createLoop(config, modelName, cwd, sessionStore);\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n if (resumed) {\n await loop.loadMessages(resumed.messages);\n // Resuming explicitly continues the project: rehydrate its todo list\n // (fresh sessions leave it alone even when .star/todos.json exists, and\n // a list owned by another session is not adopted).\n await loadTodos(cwd, resumeId ?? undefined);\n if (sessionStore) {\n hydrateSnapshots(await loadSessionSnapshots(sessionStore.dir));\n }\n }\n\n if (opts.print) {\n // Let the loop drain instead of process.exit(): force-exiting on Windows\n // can hit a libuv assertion while undici keep-alive handles are closing.\n process.exitCode = await printMode(\n loop,\n opts.print,\n cwd,\n Boolean(opts.json),\n opts.image ?? [],\n sessionStore,\n );\n return;\n }\n\n // The REPL needs a real terminal on both ends; check before paying for\n // the Ink import so a piped launch fails fast with a clear message.\n const ttyError = interactiveRequiresTtyError({\n stdinTTY: Boolean(process.stdin.isTTY),\n stdoutTTY: Boolean(process.stdout.isTTY),\n });\n if (ttyError) {\n console.error(ttyError);\n process.exit(1);\n }\n\n // The REPL pulls in Ink and every interactive component (~0.4s of module\n // evaluation): load it only on the interactive path so -p, --version,\n // --clear-sessions and session listing stay cheap.\n const { renderRepl } = await import(\"./cli/repl\");\n renderRepl(loop, {\n model: modelName,\n permissionMode: config.permissionMode,\n config,\n cwd,\n sessionStore,\n initialMessages: resumed ? resumed.messages : undefined,\n initialUsage: resumed?.meta.usage,\n });\n });\n\nprogram.parse(process.argv);\n","import type { StreamEvent } from \"../core/events\";\nimport { formatStreamError, summarizeArgs } from \"./format\";\n\nexport interface PrintLine {\n stream: \"stdout\" | \"stderr\";\n text: string;\n}\n\n// Human-readable (-p without --json) rendering of one stream event. Tool\n// args go through the same one-line summarizeArgs digest the REPL tool cards\n// use instead of the full JSON; print-json (machine consumption) keeps the\n// complete payload. Returns null for events this path ignores (reasoning,\n// tool-call progress) — finish is accounted separately via UsageTracker and\n// error additionally flips the exit code, both handled by the caller.\nexport function printEventLine(event: StreamEvent): PrintLine | null {\n switch (event.type) {\n case \"text-delta\":\n return { stream: \"stdout\", text: event.text };\n case \"tool-call\":\n return { stream: \"stderr\", text: `\\n[tool] ${event.name} ${summarizeArgs(event.args)}\\n` };\n case \"tool-result\": {\n const preview =\n event.content.length > 500\n ? `${event.content.slice(0, 500)}... (truncated)`\n : event.content;\n return {\n stream: \"stderr\",\n text: `[result] ${event.isError ? \"ERROR: \" : \"\"}${preview}\\n`,\n };\n }\n case \"retry\": {\n const wait =\n event.delayMs !== undefined && event.delayMs >= 1000\n ? ` in ${Math.round(event.delayMs / 1000)}s`\n : \"\";\n return {\n stream: \"stderr\",\n text: `\\n[retry ${event.attempt}/${event.maxAttempts}${wait}] ${event.reason}\\n`,\n };\n }\n case \"notice\":\n return { stream: \"stderr\", text: `\\n[notice] ${event.message}\\n` };\n case \"error\":\n return { stream: \"stderr\", text: `\\n[error] ${formatStreamError(event.error)}\\n` };\n default:\n return null;\n }\n}\n","import type { StreamEvent, TokenUsage } from \"../core/events\";\n\nexport function eventToJsonLine(event: StreamEvent): string | null {\n switch (event.type) {\n case \"finish\":\n return null;\n case \"error\":\n return JSON.stringify({ type: \"error\", error: { message: event.error.message } });\n default:\n return JSON.stringify(event);\n }\n}\n\nexport class UsageTracker {\n private requests = 0;\n private promptTokens = 0;\n private completionTokens = 0;\n private totalTokens = 0;\n\n add(usage?: TokenUsage): void {\n if (!usage) return;\n this.requests += 1;\n this.promptTokens += usage.promptTokens;\n this.completionTokens += usage.completionTokens;\n this.totalTokens += usage.totalTokens;\n }\n\n get totals(): TokenUsage & { requests: number } {\n return {\n requests: this.requests,\n promptTokens: this.promptTokens,\n completionTokens: this.completionTokens,\n totalTokens: this.totalTokens,\n };\n }\n\n toJsonLine(): string | null {\n if (this.requests === 0) return null;\n return JSON.stringify({\n type: \"usage\",\n requests: this.requests,\n promptTokens: this.promptTokens,\n completionTokens: this.completionTokens,\n totalTokens: this.totalTokens,\n });\n }\n}\n","import { formatSessionEntries, listSessionEntries } from \"../session/list\";\n\n// Guards for the CLI entry paths, kept out of main.tsx (which parses argv at\n// module scope) so tests can exercise them without launching commander.\n\nexport interface StartupStreams {\n stdinTTY: boolean;\n stdoutTTY: boolean;\n}\n\n// --image only has a consumer in print mode; without -p the file would be\n// silently dropped when the REPL starts, so fail at startup instead.\nexport function imageRequiresPrintError(\n print: string | undefined,\n images: readonly string[],\n): string | null {\n if (print !== undefined) return null;\n return images.length > 0 ? \"--image requires -p/--print\" : null;\n}\n\n// Ink needs a real terminal on both ends; piped stdin/stdout used to leave a\n// bare stack or a hung process.\nexport function interactiveRequiresTtyError(streams: StartupStreams): string | null {\n return streams.stdinTTY && streams.stdoutTTY\n ? null\n : \"interactive mode requires a TTY; use -p/--print\";\n}\n\n// A downstream pipe that closes early (star -p \"...\" | head -1) turns the next\n// stdout write into an EPIPE \"error\" event; exit quietly instead of dumping a\n// raw stack.\nexport function installStdoutEpipeGuard(stdout: NodeJS.WriteStream = process.stdout): void {\n stdout.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (error?.code === \"EPIPE\") process.exit(0);\n else throw error;\n });\n}\n\n// `star -r` without an id prints the session picker list and leaves; a script\n// must be able to tell \"no sessions\" apart from a successful listing, hence\n// the non-zero code.\nexport async function reportResumeSessions(cwd: string): Promise<number> {\n const entries = await listSessionEntries(cwd);\n if (entries.length === 0) {\n console.error(\"No sessions found for this directory.\");\n return 1;\n }\n console.log(formatSessionEntries(entries));\n return 0;\n}\n","import fs from \"node:fs\";\nimport { parse } from \"smol-toml\";\nimport { registerSensitivePatterns } from \"../core/sensitive\";\nimport { setWebFetchAllowPrivateHosts } from \"../tools/web/fetch\";\nimport { loadEnvFile } from \"./env\";\nimport { globalConfigPath, projectConfigPath } from \"./paths\";\nimport {\n type CliOverrides,\n ConfigSchema,\n HookConfigSchema,\n type ModelConfig,\n ModelConfigSchema,\n PermissionsConfigSchema,\n ProviderConfigSchema,\n type StarConfig,\n} from \"./schema\";\n\nconst PartialConfigSchema = ConfigSchema.partial();\n\ntype PartialConfig = ReturnType<typeof PartialConfigSchema.parse>;\n\n// Which file a parsed config came from: project files warn differently —\n// schema-known keys the sandbox strips get sanitizeProjectConfig's \"project\n// config cannot set this key\", so the unknown-key diff only reports keys the\n// schema does not know at all.\ntype ConfigScope = \"global\" | \"project\";\n\nfunction parseTomlFile(content: string, filePath: string, scope: ConfigScope): PartialConfig {\n let raw: unknown;\n try {\n raw = parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to parse TOML in ${filePath}: ${message}`);\n }\n const result = PartialConfigSchema.safeParse(raw);\n if (!result.success) {\n // One readable line per issue instead of zod's single JSON blob.\n const details = result.error.issues\n .map((issue) => {\n const where = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n return ` ${where}: ${issue.message}`;\n })\n .join(\"\\n\");\n throw new Error(`Invalid config in ${filePath}:\\n${details}`);\n }\n warnUnknownKeys(raw, filePath, scope);\n return result.data;\n}\n\n// Keys a project-level .star/config.toml may set. Anything else (providers,\n// permissionMode, permissions, hooks, ...) stays global-only: a checked-out\n// repo must not be able to plant shell hooks, force yolo mode, or redirect\n// provider traffic to a key-harvesting endpoint.\nconst PROJECT_ALLOWED_KEYS = new Set([\n \"defaultModel\",\n \"models\",\n \"maxSteps\",\n \"contextMaxTokens\",\n \"compactThresholdTokens\",\n \"streamIdleTimeoutSec\",\n \"streamFirstChunkTimeoutSec\",\n \"streamMaxRetries\",\n \"maxAutoContinues\",\n \"contextCompaction\",\n \"sessionBudgetUsd\",\n \"notifyBell\",\n \"notifyBellThresholdSec\",\n \"doomLoopThreshold\",\n \"gitSnapshots\",\n]);\n\n// Safe ranges for the project-provided streaming knobs: a repo must not set\n// pathological values (sub-second idle timeouts, thousands of retries).\nconst PROJECT_STREAM_RANGES = {\n streamIdleTimeoutSec: { min: 5, max: 120 },\n streamFirstChunkTimeoutSec: { min: 30, max: 900 },\n streamMaxRetries: { min: 0, max: 10 },\n} as const;\n\n// 0 disables these protections, so a project may only tighten them, never\n// turn them off (handled at merge time via min()).\nconst PROJECT_PROTECTIVE_MIN_KEYS = new Set([\"maxSteps\", \"doomLoopThreshold\"]);\n\n// Known keys per schema-defined section, for the unknown-key diff.\nconst TOP_LEVEL_KEYS = new Set(Object.keys(ConfigSchema.shape));\nconst SECTION_KEYS: Record<string, { keys: Set<string>; array: boolean }> = {\n permissions: { keys: new Set(Object.keys(PermissionsConfigSchema.shape)), array: false },\n providers: { keys: new Set(Object.keys(ProviderConfigSchema.shape)), array: true },\n models: { keys: new Set(Object.keys(ModelConfigSchema.shape)), array: true },\n hooks: { keys: new Set(Object.keys(HookConfigSchema.shape)), array: true },\n};\n\nfunction editDistance(a: string, b: string): number {\n let previous: number[] = Array.from({ length: b.length + 1 }, (_, i) => i);\n for (let i = 1; i <= a.length; i++) {\n const current: number[] = [i];\n for (let j = 1; j <= b.length; j++) {\n current[j] = Math.min(\n (previous[j] ?? 0) + 1,\n (current[j - 1] ?? 0) + 1,\n (previous[j - 1] ?? 0) + (a[i - 1] === b[j - 1] ? 0 : 1),\n );\n }\n previous = current;\n }\n return previous[b.length] ?? 0;\n}\n\n// Cheap \"did you mean\": case-insensitive Levenshtein against the known keys,\n// accepted when the distance is small relative to the key's length.\nfunction suggestKey(key: string, known: Set<string>): string | undefined {\n const needle = key.toLowerCase();\n let best: string | undefined;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (const candidate of known) {\n const distance = editDistance(needle, candidate.toLowerCase());\n if (distance <= Math.max(1, Math.floor(candidate.length / 4)) && distance < bestDistance) {\n best = candidate;\n bestDistance = distance;\n }\n }\n return best;\n}\n\nfunction warnUnknownKey(keyPath: string, filePath: string, known: Set<string>): void {\n const leaf = keyPath.slice(keyPath.lastIndexOf(\".\") + 1);\n const suggestion = suggestKey(leaf, known);\n const hint = suggestion\n ? `possible typo of \"${suggestion}\"? the key is ignored`\n : \"possible typo? the key is ignored\";\n process.stderr.write(`[star] unknown config key \"${keyPath}\" in ${filePath}: ${hint}\\n`);\n}\n\n// zod object schemas strip unknown keys without a word, so a misspelled\n// option (\"streamMaxRetreis\") would otherwise vanish silently. Diff the raw\n// TOML against the schema shapes and warn once per unknown key — top level\n// plus inside the schema-defined sections ([permissions], [[providers]],\n// [[models]], [[hooks]]). Warnings never block loading. In project files,\n// schema-known sections the sandbox drops wholesale (everything but\n// [[models]]) already get sanitizeProjectConfig's own warning, so their\n// inner keys are not diffed.\nfunction warnUnknownKeys(raw: unknown, filePath: string, scope: ConfigScope): void {\n if (typeof raw !== \"object\" || raw === null) return;\n const table = raw as Record<string, unknown>;\n for (const key of Object.keys(table)) {\n if (!TOP_LEVEL_KEYS.has(key)) warnUnknownKey(key, filePath, TOP_LEVEL_KEYS);\n }\n for (const [section, { keys, array }] of Object.entries(SECTION_KEYS)) {\n if (scope === \"project\" && !PROJECT_ALLOWED_KEYS.has(section)) continue;\n const value = table[section];\n if (array) {\n if (!Array.isArray(value)) continue;\n value.forEach((entry, index) => {\n if (typeof entry !== \"object\" || entry === null) return;\n for (const key of Object.keys(entry)) {\n if (!keys.has(key)) warnUnknownKey(`${section}[${index}].${key}`, filePath, keys);\n }\n });\n continue;\n }\n if (typeof value !== \"object\" || value === null) continue;\n for (const key of Object.keys(value as Record<string, unknown>)) {\n if (!keys.has(key)) warnUnknownKey(`${section}.${key}`, filePath, keys);\n }\n }\n}\n\nfunction warnProject(filePath: string, message: string): void {\n process.stderr.write(`[star] ${message} in ${filePath}\\n`);\n}\n\n// Price fields are stripped from project models: a repo defining $0 prices\n// would silently zero out /cost and defeat sessionBudgetUsd.\nfunction stripModelPrices(models: ModelConfig[], filePath: string): ModelConfig[] {\n let stripped = false;\n const out = models.map((model) => {\n const { promptPrice, completionPrice, cacheReadPrice, ...rest } = model;\n if (\n promptPrice !== undefined ||\n completionPrice !== undefined ||\n cacheReadPrice !== undefined\n ) {\n stripped = true;\n }\n return rest;\n });\n if (stripped) {\n warnProject(filePath, \"ignoring price fields in project [[models]]: pricing stays global-only\");\n }\n return out;\n}\n\nfunction sanitizeProjectConfig(project: PartialConfig, filePath: string): PartialConfig {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(project)) {\n if (value === undefined) continue;\n if (!PROJECT_ALLOWED_KEYS.has(key)) {\n process.stderr.write(\n `[star] ignoring \"${key}\" in ${filePath}: project config cannot set this key\\n`,\n );\n continue;\n }\n if (key === \"gitSnapshots\" && value === false) {\n // Snapshot tracking protects /undo and /redo; a repo may enable but\n // never disable it.\n warnProject(\n filePath,\n 'ignoring \"gitSnapshots = false\": project config cannot disable this protection',\n );\n continue;\n }\n if (PROJECT_PROTECTIVE_MIN_KEYS.has(key) && value === 0) {\n warnProject(filePath, `ignoring \"${key} = 0\": project config cannot disable this protection`);\n continue;\n }\n const range = PROJECT_STREAM_RANGES[key as keyof typeof PROJECT_STREAM_RANGES];\n if (range && typeof value === \"number\") {\n const clamped = Math.min(range.max, Math.max(range.min, value));\n if (clamped !== value) {\n warnProject(\n filePath,\n `clamping \"${key}\" from ${value} to ${clamped}: project config is limited to ${range.min}–${range.max}`,\n );\n }\n sanitized[key] = clamped;\n continue;\n }\n if (key === \"models\" && Array.isArray(value)) {\n sanitized[key] = stripModelPrices(value as ModelConfig[], filePath);\n continue;\n }\n sanitized[key] = value;\n }\n return sanitized as PartialConfig;\n}\n\n// Project [[models]] merge with the global table by name: a project entry\n// replaces the same-named global entry, every other global entry survives.\n// (Shallow-spreading the array would let a repo silently swap the user's\n// whole model table — and orphan a global defaultModel pointing into it.)\nfunction mergeModelsByName(\n globalModels: ModelConfig[],\n projectModels: ModelConfig[],\n): ModelConfig[] {\n const projectByName = new Map(projectModels.map((model) => [model.name, model]));\n const merged = globalModels.map((model) => projectByName.get(model.name) ?? model);\n const globalNames = new Set(globalModels.map((model) => model.name));\n for (const model of projectModels) {\n if (!globalNames.has(model.name)) merged.push(model);\n }\n return merged;\n}\n\n// 0 disables these protections (unlimited), so normalize it to +∞ before the\n// min: a project must be able to tighten a globally-disabled guard (global\n// maxSteps = 0, project 5 → 5), never to relax one.\nfunction protectiveMin(a: number, b: number): number {\n const result = Math.min(\n a === 0 ? Number.POSITIVE_INFINITY : a,\n b === 0 ? Number.POSITIVE_INFINITY : b,\n );\n return result === Number.POSITIVE_INFINITY ? 0 : result;\n}\n\n// Project values merge protectively: a repo can tighten safeguards but never\n// relax them. Budgets take the lower bound; guard thresholds take the lower\n// bound too (a project-side 0 = disabled was already filtered out above, and\n// a global 0 normalizes to +∞ via protectiveMin).\nfunction mergeProjectConfig(\n global: PartialConfig,\n project: PartialConfig,\n projectPath: string,\n): PartialConfig {\n const merged: PartialConfig = { ...global, ...project };\n if (project.models !== undefined) {\n merged.models = mergeModelsByName(global.models ?? [], project.models);\n warnProject(projectPath, `project config overrides ${project.models.length} model(s)`);\n }\n if (project.sessionBudgetUsd !== undefined && global.sessionBudgetUsd !== undefined) {\n merged.sessionBudgetUsd = Math.min(global.sessionBudgetUsd, project.sessionBudgetUsd);\n }\n if (project.maxSteps !== undefined) {\n merged.maxSteps = protectiveMin(global.maxSteps ?? 100, project.maxSteps);\n }\n if (project.doomLoopThreshold !== undefined) {\n merged.doomLoopThreshold = protectiveMin(\n global.doomLoopThreshold ?? 3,\n project.doomLoopThreshold,\n );\n }\n return merged;\n}\n\n// Plaintext keys still work, but config.toml is world-readable by default on\n// some setups and gets committed by accident — point users at apiKeyEnv.\nfunction warnPlaintextApiKey(config: PartialConfig): void {\n const offenders: string[] = [];\n for (const provider of config.providers ?? []) {\n if (provider.apiKey !== undefined) offenders.push(`provider \"${provider.name}\"`);\n }\n for (const model of config.models ?? []) {\n if (\"apiKey\" in model && model.apiKey !== undefined) offenders.push(`model \"${model.name}\"`);\n }\n if (offenders.length === 0) return;\n process.stderr.write(\n `[star] plaintext apiKey in config (${offenders.join(\", \")}) is deprecated: store keys in ~/.star-cli/.env and reference them with apiKeyEnv instead\\n`,\n );\n}\n\nfunction applyOverrides(config: PartialConfig, overrides?: CliOverrides): PartialConfig {\n if (!overrides) return config;\n const merged = { ...config };\n if (overrides.model !== undefined) merged.defaultModel = overrides.model;\n if (overrides.permissionMode !== undefined) merged.permissionMode = overrides.permissionMode;\n return merged;\n}\n\nasync function readTomlFile(filePath: string, scope: ConfigScope): Promise<PartialConfig> {\n let content: string;\n try {\n content = await fs.promises.readFile(filePath, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return {};\n throw error;\n }\n return parseTomlFile(content, filePath, scope);\n}\n\nfunction readTomlFileSync(filePath: string, scope: ConfigScope): PartialConfig {\n if (!fs.existsSync(filePath)) return {};\n const content = fs.readFileSync(filePath, \"utf8\");\n return parseTomlFile(content, filePath, scope);\n}\n\nexport async function loadConfig(cwd: string, overrides?: CliOverrides): Promise<StarConfig> {\n loadEnvFile();\n const global = await readTomlFile(globalConfigPath(), \"global\");\n const projectPath = projectConfigPath(cwd);\n const project = sanitizeProjectConfig(await readTomlFile(projectPath, \"project\"), projectPath);\n const merged = applyOverrides(mergeProjectConfig(global, project, projectPath), overrides);\n warnPlaintextApiKey(merged);\n return wireRuntimeSettings(ConfigSchema.parse(merged));\n}\n\nexport function loadConfigSync(cwd: string, overrides?: CliOverrides): StarConfig {\n loadEnvFile();\n const global = readTomlFileSync(globalConfigPath(), \"global\");\n const projectPath = projectConfigPath(cwd);\n const project = sanitizeProjectConfig(readTomlFileSync(projectPath, \"project\"), projectPath);\n const merged = applyOverrides(mergeProjectConfig(global, project, projectPath), overrides);\n warnPlaintextApiKey(merged);\n return wireRuntimeSettings(ConfigSchema.parse(merged));\n}\n\n// Pushes config-driven security settings into their runtime consumers. The\n// merged permissions table is global-only at this point (the project sandbox\n// dropped any project-side [permissions]), so these can never be planted by\n// a checked-out repo.\nfunction wireRuntimeSettings(config: StarConfig): StarConfig {\n registerSensitivePatterns(config.permissions.sensitive);\n setWebFetchAllowPrivateHosts(config.webFetchAllowPrivateHosts);\n return config;\n}\n"],"mappings":"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","names":[]}