topchester-ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +64 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +2986 -0
- package/dist/cli.mjs.map +1 -0
- package/package.json +51 -0
package/dist/cli.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":["#config","parseYaml","hashFile","isNodeError","formatPathStatus","stripAnsi","formatPathStatus","resolveWorkspaceScopedPath","runCommand","findExecutable","getExitCode","isRecord","isRecord","formatPathStatus"],"sources":["../src/model/index.ts","../src/config/index.ts","../src/app/paths.ts","../src/logging/index.ts","../src/app/context.ts","../src/cli/ui.ts","../src/knowledge/status.ts","../src/knowledge/compiler/inventory.ts","../src/knowledge/compiler/l1-entry.ts","../src/knowledge/compiler/l1.ts","../src/knowledge/progress.ts","../src/knowledge/compiler/path-encoding.ts","../src/knowledge/compiler/l1-processor.ts","../src/knowledge/compiler/index.ts","../src/knowledge/init.ts","../src/knowledge/reset.ts","../src/tui/busy.ts","../src/agent/commands.ts","../src/tui/messages.ts","../src/tui/keys.ts","../src/tui/status.ts","../src/tui/text.ts","../src/tui/layout.ts","../src/agent/conversation.ts","../src/agent/events.ts","../src/agent/health.ts","../src/agent/tools/types.ts","../src/agent/tools/find-file.ts","../src/agent/tools/grep.ts","../src/agent/tools/read-file.ts","../src/agent/tools/registry.ts","../src/agent/tools/executor.ts","../src/agent/tools/parser.ts","../src/agent/prompts.ts","../src/agent/runtime.ts","../src/tui/runtime-events.ts","../src/tui/terminal.ts","../src/tui/shell.ts","../src/cli.ts"],"sourcesContent":["import { createOpenAICompatible } from \"@ai-sdk/openai-compatible\";\nimport { generateText, streamText, type LanguageModel } from \"ai\";\n\nexport type ModelPurpose =\n | \"agent.primary\"\n | \"agent.fast\"\n | \"kb.scan\"\n | \"kb.summarize\"\n | \"kb.extract\"\n | \"kb.embed\"\n | \"fallback\";\n\nexport interface OpenAICompatibleProviderConfig {\n type: \"openai-compatible\";\n baseURL: string;\n apiKey?: string;\n apiKeyEnv?: string;\n headers?: Record<string, string>;\n supportsStructuredOutputs?: boolean;\n}\n\nexport interface ModelConfig {\n name: string;\n provider?: string;\n}\n\nexport interface ModelGatewayConfig {\n defaultPurpose: ModelPurpose;\n models: Partial<Record<ModelPurpose, ModelConfig>>;\n defaultProvider?: string;\n providers: Record<string, OpenAICompatibleProviderConfig>;\n}\n\nexport interface ModelRequest {\n purpose?: ModelPurpose;\n system?: string;\n prompt: string;\n abortSignal?: AbortSignal;\n}\n\nexport interface ModelTextResult {\n text: string;\n providerId: string;\n modelId: string;\n purpose: ModelPurpose;\n}\n\nexport class ModelGateway {\n readonly #config: ModelGatewayConfig;\n\n constructor(config: ModelGatewayConfig) {\n this.#config = config;\n }\n\n resolveModel(purpose = this.#config.defaultPurpose): {\n model: LanguageModel;\n providerId: string;\n modelId: string;\n purpose: ModelPurpose;\n } {\n const modelConfig = this.#config.models[purpose] ?? this.#config.models.fallback;\n\n if (!modelConfig) {\n throw new Error(`No model configured for purpose \"${purpose}\".`);\n }\n\n const providerId = modelConfig.provider ?? this.#config.defaultProvider;\n\n if (!providerId) {\n throw new Error(`No provider configured for model \"${modelConfig.name}\".`);\n }\n\n const modelId = modelConfig.name;\n const providerConfig = this.#config.providers[providerId];\n\n if (!providerConfig) {\n throw new Error(`No provider configured for model provider \"${providerId}\".`);\n }\n\n const provider = createOpenAICompatible({\n name: providerId,\n baseURL: providerConfig.baseURL,\n apiKey: resolveApiKey(providerConfig),\n headers: providerConfig.headers,\n supportsStructuredOutputs: providerConfig.supportsStructuredOutputs,\n });\n\n return {\n model: provider.chatModel(modelId),\n providerId,\n modelId,\n purpose,\n };\n }\n\n async generateText(request: ModelRequest): Promise<ModelTextResult> {\n const resolved = this.resolveModel(request.purpose);\n const result = await generateText({\n model: resolved.model,\n system: request.system,\n prompt: request.prompt,\n abortSignal: request.abortSignal,\n });\n\n return {\n text: result.text,\n providerId: resolved.providerId,\n modelId: resolved.modelId,\n purpose: resolved.purpose,\n };\n }\n\n async *streamText(request: ModelRequest): AsyncIterable<string> {\n const resolved = this.resolveModel(request.purpose);\n const result = streamText({\n model: resolved.model,\n system: request.system,\n prompt: request.prompt,\n abortSignal: request.abortSignal,\n });\n\n yield* result.textStream;\n }\n}\n\nfunction resolveApiKey(config: OpenAICompatibleProviderConfig): string | undefined {\n if (config.apiKey !== undefined) {\n return config.apiKey;\n }\n\n if (config.apiKeyEnv === undefined) {\n return undefined;\n }\n\n return process.env[config.apiKeyEnv];\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { z } from \"zod\";\n\nconst modelPurposeSchema = z.enum([\n \"agent.primary\",\n \"agent.fast\",\n \"kb.scan\",\n \"kb.summarize\",\n \"kb.extract\",\n \"kb.embed\",\n \"fallback\",\n]);\n\nconst providerSchema = z.object({\n type: z.literal(\"openai-compatible\"),\n baseURL: z.string().url(),\n apiKeyEnv: z.string().optional(),\n apiKey: z.string().optional(),\n headers: z.record(z.string(), z.string()).optional(),\n supportsStructuredOutputs: z.boolean().optional(),\n});\n\nconst modelAssignmentSchema = z.object({\n name: z.string(),\n provider: z.string().optional(),\n});\n\nconst providersSchema = z\n .object({\n default: z.string().optional(),\n })\n .catchall(providerSchema.or(z.string()));\n\nexport const topchesterConfigSchema = z.object({\n models: z\n .object({\n defaultPurpose: modelPurposeSchema.optional(),\n assignments: z.partialRecord(modelPurposeSchema, modelAssignmentSchema).optional(),\n providers: providersSchema.optional(),\n })\n .optional(),\n});\n\nexport type TopchesterConfig = z.infer<typeof topchesterConfigSchema>;\n\nexport interface ConfigLoadOptions {\n workspaceRoot: string;\n configPath?: string;\n}\n\nexport function loadTopchesterConfig(options: ConfigLoadOptions): TopchesterConfig {\n const paths = [\n join(homedir(), \".config/topchester/config.yaml\"),\n join(options.workspaceRoot, \"topchester.yaml\"),\n join(options.workspaceRoot, \".topchester/config.local.yaml\"),\n process.env.TOPCHESTER_CONFIG,\n options.configPath,\n ].filter((path): path is string => Boolean(path));\n\n let merged: TopchesterConfig = {};\n\n for (const path of paths) {\n const resolvedPath = isAbsolute(path) ? path : resolve(options.workspaceRoot, path);\n\n if (!existsSync(resolvedPath)) {\n continue;\n }\n\n const parsed = parseYaml(readFileSync(resolvedPath, \"utf8\")) as unknown;\n merged = deepMerge(merged, topchesterConfigSchema.parse(parsed));\n }\n\n return topchesterConfigSchema.parse(merged);\n}\n\nfunction deepMerge<T>(base: T, override: T): T {\n if (!isPlainObject(base) || !isPlainObject(override)) {\n return override;\n }\n\n const result: Record<string, unknown> = { ...base };\n\n for (const [key, value] of Object.entries(override)) {\n result[key] = key in result ? deepMerge(result[key], value) : value;\n }\n\n return result as T;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { isAbsolute, join, resolve } from \"node:path\";\n\nexport const TOPCHESTER_STATE_DIR = \".agents/topchester\";\nexport const TOPCHESTER_SESSIONS_DIR = `${TOPCHESTER_STATE_DIR}/sessions`;\nexport const TOPCHESTER_LOGS_DIR = `${TOPCHESTER_STATE_DIR}/logs`;\nexport const TOPCHESTER_DEFAULT_LOG_FILE = `${TOPCHESTER_LOGS_DIR}/topchester.log`;\n\nexport function resolveWorkspacePath(workspaceRoot: string, path: string): string {\n return isAbsolute(path) ? path : resolve(workspaceRoot, path);\n}\n\nexport function getTopchesterStatePath(workspaceRoot: string): string {\n return resolveWorkspacePath(workspaceRoot, TOPCHESTER_STATE_DIR);\n}\n\nexport function getTopchesterSessionsPath(workspaceRoot: string): string {\n return resolveWorkspacePath(workspaceRoot, TOPCHESTER_SESSIONS_DIR);\n}\n\nexport function getTopchesterLogsPath(workspaceRoot: string): string {\n return resolveWorkspacePath(workspaceRoot, TOPCHESTER_LOGS_DIR);\n}\n\nexport function getTopchesterLogFilePath(workspaceRoot: string, logFile = process.env.TOPCHESTER_LOG_FILE): string {\n return logFile\n ? resolveWorkspacePath(workspaceRoot, logFile)\n : join(getTopchesterLogsPath(workspaceRoot), \"topchester.log\");\n}\n","import { mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport pino, { type Logger } from \"pino\";\nimport { getTopchesterLogFilePath } from \"../app/paths.js\";\n\nconst LOG_LEVELS = new Set([\"fatal\", \"error\", \"warn\", \"info\", \"debug\", \"trace\", \"silent\"]);\n\nexport interface TopchesterLoggerInfo {\n logger: Logger;\n level: string;\n logFilePath?: string;\n}\n\nexport function createTopchesterLogger(workspaceRoot: string): TopchesterLoggerInfo {\n const level = normalizeLogLevel(process.env.TOPCHESTER_LOG_LEVEL);\n\n if (level === \"silent\") {\n return {\n logger: pino({ enabled: false }),\n level,\n };\n }\n\n const logFilePath = getTopchesterLogFilePath(workspaceRoot);\n mkdirSync(dirname(logFilePath), { recursive: true });\n\n const logger = pino(\n {\n base: undefined,\n level,\n timestamp: pino.stdTimeFunctions.isoTime,\n },\n pino.destination({ dest: logFilePath, sync: true })\n );\n\n logger.debug({ event: \"logger_ready\", logFilePath, level }, \"logger ready\");\n\n return {\n logger,\n level,\n logFilePath,\n };\n}\n\nfunction normalizeLogLevel(level: string | undefined): string {\n const normalized = level?.trim().toLowerCase();\n\n if (!normalized || normalized === \"off\") {\n return \"silent\";\n }\n\n return LOG_LEVELS.has(normalized) ? normalized : \"info\";\n}\n","import { ModelGateway, type ModelGatewayConfig } from \"../model/index.js\";\nimport { loadTopchesterConfig, type TopchesterConfig } from \"../config/index.js\";\nimport { createTopchesterLogger } from \"../logging/index.js\";\nimport { type Logger } from \"pino\";\n\nexport interface AppContext {\n workspaceRoot: string;\n config: TopchesterConfig;\n modelGateway: ModelGateway;\n devFlags: Set<string>;\n logger: Logger;\n logFilePath?: string;\n}\n\nexport interface CreateAppContextOptions {\n workspaceRoot: string;\n configPath?: string;\n devFlags?: string[];\n}\n\nexport function createAppContext(options: CreateAppContextOptions): AppContext {\n const config = loadTopchesterConfig(options);\n const modelGateway = new ModelGateway(normalizeModelGatewayConfig(config));\n const loggerInfo = createTopchesterLogger(options.workspaceRoot);\n\n return {\n workspaceRoot: options.workspaceRoot,\n config,\n modelGateway,\n devFlags: new Set(options.devFlags ?? []),\n logger: loggerInfo.logger,\n logFilePath: loggerInfo.logFilePath,\n };\n}\n\nfunction normalizeModelGatewayConfig(config: TopchesterConfig): ModelGatewayConfig {\n const providers = config.models?.providers ?? {};\n const { default: defaultProvider, ...namedProviders } = providers;\n\n return {\n defaultPurpose: config.models?.defaultPurpose ?? \"agent.primary\",\n models: config.models?.assignments ?? {},\n defaultProvider: typeof defaultProvider === \"string\" ? defaultProvider : undefined,\n providers: Object.fromEntries(\n Object.entries(namedProviders).filter((entry): entry is [string, Exclude<(typeof entry)[1], string>] => {\n return typeof entry[1] !== \"string\";\n })\n ),\n };\n}\n","import { stderr, stdout } from \"node:process\";\n\nconst colors = {\n bgSoftGray: \"\\u001b[48;5;236m\",\n cyan: \"\\u001b[36m\",\n dim: \"\\u001b[2m\",\n green: \"\\u001b[32m\",\n red: \"\\u001b[31m\",\n reset: \"\\u001b[0m\",\n yellow: \"\\u001b[33m\",\n};\n\nexport const ui = {\n heading(text: string): string {\n return color(`Topchester ${text}`, \"cyan\");\n },\n label(text: string): string {\n return color(text, \"dim\");\n },\n ok(text: string): string {\n return color(text, \"green\");\n },\n warn(text: string): string {\n return color(text, \"yellow\");\n },\n error(text: string): string {\n return color(text, \"red\");\n },\n softBackground(text: string): string {\n return color(text, \"bgSoftGray\");\n },\n async spinner<T>(text: string, action: () => T | Promise<T>): Promise<T> {\n return withStatusLine(text, action, undefined, 80, false);\n },\n async progress<T>(text: string, action: (report: (message: string) => void) => T | Promise<T>): Promise<T> {\n let latest = text;\n\n return withStatusLine(\n text,\n () =>\n action((message) => {\n latest = message;\n }),\n () => latest,\n 80,\n true\n );\n },\n};\n\nasync function withStatusLine<T>(\n text: string,\n action: () => T | Promise<T>,\n getText: () => string = () => text,\n progressEveryMs = 80,\n emitPlainProgress = false\n): Promise<T> {\n if (!shouldUseColor()) {\n if (!emitPlainProgress) {\n return action();\n }\n\n const timer = setInterval(\n () => {\n stderr.write(`${getText()}\\n`);\n },\n Math.max(progressEveryMs, 5000)\n );\n\n try {\n return await action();\n } finally {\n clearInterval(timer);\n }\n }\n\n const frames = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n let index = 0;\n\n stderr.write(`${color(frames[index], \"cyan\")} ${getText()}`);\n const timer = setInterval(() => {\n index = (index + 1) % frames.length;\n stderr.write(`\\r\\u001b[2K${color(frames[index], \"cyan\")} ${getText()}`);\n }, progressEveryMs);\n\n try {\n return await action();\n } finally {\n clearInterval(timer);\n stderr.write(`\\r\\u001b[2K`);\n }\n}\n\nexport function color(text: string, colorName: keyof typeof colors): string {\n if (!shouldUseColor()) {\n return text;\n }\n\n return `${colors[colorName]}${text}${colors.reset}`;\n}\n\nfunction shouldUseColor(): boolean {\n if (process.env.NO_COLOR) {\n return false;\n }\n\n if (process.env.FORCE_COLOR && process.env.FORCE_COLOR !== \"0\") {\n return true;\n }\n\n return stdout.isTTY === true;\n}\n","import { existsSync, statSync } from \"node:fs\";\nimport { resolveWorkspacePath } from \"../app/paths.js\";\n\nexport interface KnowledgeStatus {\n workspaceRoot: string;\n kbPath: string;\n cachePath: string;\n kbExists: boolean;\n kbIsDirectory: boolean;\n cacheExists: boolean;\n cacheIsDirectory: boolean;\n kbPathSource: \"default\" | \"env\";\n cachePathSource: \"default\" | \"env\";\n}\n\nexport function getKnowledgeStatus(workspaceRoot: string): KnowledgeStatus {\n const kbPathSource = process.env.TOPCHESTER_KB_DIR ? \"env\" : \"default\";\n const cachePathSource = process.env.TOPCHESTER_KB_CACHE_DIR ? \"env\" : \"default\";\n const kbPath = resolveWorkspacePath(workspaceRoot, process.env.TOPCHESTER_KB_DIR ?? \"topchester-kb\");\n const cachePath = resolveWorkspacePath(\n workspaceRoot,\n process.env.TOPCHESTER_KB_CACHE_DIR ?? \".agents/topchester-kb-cache\"\n );\n const kbStat = safeStat(kbPath);\n const cacheStat = safeStat(cachePath);\n\n return {\n workspaceRoot,\n kbPath,\n cachePath,\n kbExists: Boolean(kbStat),\n kbIsDirectory: kbStat?.isDirectory() ?? false,\n cacheExists: Boolean(cacheStat),\n cacheIsDirectory: cacheStat?.isDirectory() ?? false,\n kbPathSource,\n cachePathSource,\n };\n}\n\nfunction safeStat(path: string) {\n if (!existsSync(path)) {\n return undefined;\n }\n\n return statSync(path);\n}\n","import { createHash } from \"node:crypto\";\nimport { open, readdir, readFile, stat } from \"node:fs/promises\";\nimport { dirname, extname, join, relative, sep } from \"node:path\";\n\nexport interface InventoryFile {\n path: string;\n sizeBytes: number;\n hash: string;\n}\n\nexport interface InventoryResult {\n workspaceRoot: string;\n gitignoreFiles: string[];\n files: InventoryFile[];\n}\n\nexport interface InventoryOptions {\n excludedPaths?: string[];\n}\n\ninterface IgnoreRule {\n baseDir: string;\n pattern: string;\n negated: boolean;\n directoryOnly: boolean;\n}\n\nconst DEFAULT_EXCLUDED_DIRS = new Set([\n \".git\",\n \"node_modules\",\n \"dist\",\n \"coverage\",\n \".agents/topchester\",\n \".agents/topchester-kb-cache\",\n \"topchester-kb\",\n]);\n\nconst BINARY_FILE_EXTENSIONS = new Set([\n \".avif\",\n \".bmp\",\n \".class\",\n \".db\",\n \".dll\",\n \".dmg\",\n \".doc\",\n \".docx\",\n \".dylib\",\n \".eot\",\n \".exe\",\n \".gif\",\n \".gz\",\n \".ico\",\n \".jar\",\n \".jpeg\",\n \".jpg\",\n \".mov\",\n \".mp3\",\n \".mp4\",\n \".otf\",\n \".pdf\",\n \".png\",\n \".sqlite\",\n \".tar\",\n \".tgz\",\n \".ttf\",\n \".wasm\",\n \".webm\",\n \".webp\",\n \".woff\",\n \".woff2\",\n \".zip\",\n]);\n\nconst BINARY_FILE_NAMES = new Set([\".ds_store\"]);\n\nconst BINARY_SNIFF_BYTES = 4096;\nconst BINARY_CONTROL_BYTE_RATIO_THRESHOLD = 0.3;\n\nexport async function listProjectFilesForL1(\n workspaceRoot: string,\n options: InventoryOptions = {}\n): Promise<InventoryResult> {\n const excludedDirs = buildExcludedDirs(workspaceRoot, options.excludedPaths ?? []);\n const rules = await loadGitignoreRules(workspaceRoot, excludedDirs);\n const files: InventoryFile[] = [];\n\n await walkDirectory(workspaceRoot, workspaceRoot, rules, files, excludedDirs);\n\n files.sort((a, b) => a.path.localeCompare(b.path));\n\n return {\n workspaceRoot,\n gitignoreFiles: rules\n .map((rule) => join(rule.baseDir, \".gitignore\"))\n .filter(unique)\n .sort(),\n files,\n };\n}\n\nasync function loadGitignoreRules(workspaceRoot: string, excludedDirs: Set<string>): Promise<IgnoreRule[]> {\n const gitignorePaths: string[] = [];\n await collectGitignorePaths(workspaceRoot, workspaceRoot, gitignorePaths, excludedDirs);\n\n const rules: IgnoreRule[] = [];\n for (const gitignorePath of gitignorePaths.sort()) {\n const content = await readFile(gitignorePath, \"utf8\");\n const baseDir = dirname(gitignorePath);\n for (const rawLine of content.split(/\\r?\\n/)) {\n const rule = parseGitignoreLine(baseDir, rawLine);\n if (rule) {\n rules.push(rule);\n }\n }\n }\n\n return rules;\n}\n\nasync function collectGitignorePaths(\n workspaceRoot: string,\n dir: string,\n gitignorePaths: string[],\n excludedDirs: Set<string>\n): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const absolutePath = join(dir, entry.name);\n const relativePath = toPosixPath(relative(workspaceRoot, absolutePath));\n\n if (entry.name === \".gitignore\") {\n gitignorePaths.push(absolutePath);\n continue;\n }\n\n if (!entry.isDirectory() || shouldSkipDirectoryByDefault(relativePath, excludedDirs)) {\n continue;\n }\n\n await collectGitignorePaths(workspaceRoot, absolutePath, gitignorePaths, excludedDirs);\n }\n}\n\nasync function walkDirectory(\n workspaceRoot: string,\n dir: string,\n rules: IgnoreRule[],\n files: InventoryFile[],\n excludedDirs: Set<string>\n): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const absolutePath = join(dir, entry.name);\n const relativePath = toPosixPath(relative(workspaceRoot, absolutePath));\n\n if (entry.isDirectory()) {\n if (\n !shouldSkipDirectoryByDefault(relativePath, excludedDirs) &&\n !isIgnored(workspaceRoot, absolutePath, true, rules, excludedDirs)\n ) {\n await walkDirectory(workspaceRoot, absolutePath, rules, files, excludedDirs);\n }\n continue;\n }\n\n if (!entry.isFile() || isIgnored(workspaceRoot, absolutePath, false, rules, excludedDirs)) {\n continue;\n }\n\n const fileStat = await stat(absolutePath);\n if (await isBinaryFile(absolutePath, relativePath)) {\n continue;\n }\n\n files.push({ path: relativePath, sizeBytes: fileStat.size, hash: await hashFile(absolutePath) });\n }\n}\n\nasync function isBinaryFile(absolutePath: string, relativePath: string): Promise<boolean> {\n const lowerRelativePath = relativePath.toLowerCase();\n const fileName = lowerRelativePath.split(\"/\").at(-1) ?? lowerRelativePath;\n\n if (BINARY_FILE_NAMES.has(fileName) || BINARY_FILE_EXTENSIONS.has(extname(lowerRelativePath))) {\n return true;\n }\n\n const fileHandle = await open(absolutePath, \"r\");\n try {\n const buffer = Buffer.alloc(BINARY_SNIFF_BYTES);\n const { bytesRead } = await fileHandle.read(buffer, 0, BINARY_SNIFF_BYTES, 0);\n return looksBinary(buffer.subarray(0, bytesRead));\n } finally {\n await fileHandle.close();\n }\n}\n\nfunction looksBinary(buffer: Buffer): boolean {\n if (buffer.length === 0) {\n return false;\n }\n\n let suspiciousControlBytes = 0;\n for (const byte of buffer) {\n if (byte === 0) {\n return true;\n }\n\n const isAllowedTextControl =\n byte === 7 || byte === 8 || byte === 9 || byte === 10 || byte === 12 || byte === 13 || byte === 27;\n if (byte < 32 && !isAllowedTextControl) {\n suspiciousControlBytes += 1;\n }\n }\n\n return suspiciousControlBytes / buffer.length > BINARY_CONTROL_BYTE_RATIO_THRESHOLD;\n}\n\nasync function hashFile(absolutePath: string): Promise<string> {\n const fileHandle = await open(absolutePath, \"r\");\n try {\n const hash = createHash(\"sha256\");\n const stream = fileHandle.createReadStream();\n for await (const chunk of stream) {\n hash.update(chunk);\n }\n return `sha256:${hash.digest(\"hex\")}`;\n } finally {\n await fileHandle.close();\n }\n}\n\nfunction parseGitignoreLine(baseDir: string, rawLine: string): IgnoreRule | undefined {\n let line = rawLine.trim();\n\n if (!line || line.startsWith(\"#\")) {\n return undefined;\n }\n\n const negated = line.startsWith(\"!\");\n if (negated) {\n line = line.slice(1);\n }\n\n if (!line) {\n return undefined;\n }\n\n const directoryOnly = line.endsWith(\"/\");\n line = line.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n\n if (!line) {\n return undefined;\n }\n\n return { baseDir, pattern: line, negated, directoryOnly };\n}\n\nfunction isIgnored(\n workspaceRoot: string,\n absolutePath: string,\n isDirectory: boolean,\n rules: IgnoreRule[],\n excludedDirs: Set<string>\n): boolean {\n let ignored = false;\n\n for (const rule of rules) {\n const relativeToRule = toPosixPath(relative(rule.baseDir, absolutePath));\n if (relativeToRule.startsWith(\"../\") || relativeToRule === \"..\") {\n continue;\n }\n if (rule.directoryOnly && !isDirectory) {\n continue;\n }\n if (matchesRule(relativeToRule, rule.pattern)) {\n ignored = !rule.negated;\n }\n }\n\n if (ignored) {\n return true;\n }\n\n const workspaceRelativePath = toPosixPath(relative(workspaceRoot, absolutePath));\n return shouldSkipDirectoryByDefault(workspaceRelativePath, excludedDirs) && isDirectory;\n}\n\nfunction matchesRule(relativePath: string, pattern: string): boolean {\n if (pattern.includes(\"/\")) {\n return matchGlob(relativePath, pattern) || relativePath.startsWith(`${pattern}/`);\n }\n\n return relativePath.split(\"/\").some((part) => matchGlob(part, pattern));\n}\n\nfunction matchGlob(value: string, pattern: string): boolean {\n let regex = \"^\";\n\n for (let index = 0; index < pattern.length; index += 1) {\n const char = pattern[index];\n const nextChar = pattern[index + 1];\n\n if (char === \"*\" && nextChar === \"*\") {\n regex += \".*\";\n index += 1;\n continue;\n }\n\n if (char === \"*\") {\n regex += \"[^/]*\";\n continue;\n }\n\n if (char === \"?\") {\n regex += \"[^/]\";\n continue;\n }\n\n regex += escapeRegexChar(char);\n }\n\n regex += \"$\";\n\n return new RegExp(regex).test(value);\n}\n\nfunction escapeRegexChar(value: string): string {\n return /[.+^${}()|[\\]\\\\]/.test(value) ? `\\\\${value}` : value;\n}\n\nfunction shouldSkipDirectoryByDefault(\n relativePath: string,\n excludedDirs: Set<string> = DEFAULT_EXCLUDED_DIRS\n): boolean {\n return excludedDirs.has(relativePath) || [...excludedDirs].some((dir) => relativePath.startsWith(`${dir}/`));\n}\n\nfunction toPosixPath(path: string): string {\n return path.split(sep).join(\"/\");\n}\n\nfunction unique(value: string, index: number, array: string[]): boolean {\n return array.indexOf(value) === index;\n}\n\nfunction buildExcludedDirs(workspaceRoot: string, excludedPaths: string[]): Set<string> {\n const dirs = new Set(DEFAULT_EXCLUDED_DIRS);\n\n for (const excludedPath of excludedPaths) {\n const workspaceRelativePath = toPosixPath(relative(workspaceRoot, excludedPath));\n if (!workspaceRelativePath || workspaceRelativePath === \".\" || workspaceRelativePath.startsWith(\"../\")) {\n continue;\n }\n dirs.add(workspaceRelativePath);\n }\n\n return dirs;\n}\n","import { z } from \"zod\";\n\nexport const l1FileEntrySchemaPath = \"../schema/file-entry.v1.json\";\nexport const l1FileScanStatuses = [\n \"current\",\n \"changed\",\n \"missing_entry\",\n \"missing_file\",\n \"suspect\",\n \"invalid\",\n] as const;\nexport const l1ConfidenceLevels = [\"low\", \"medium\", \"high\"] as const;\n\nconst nonEmptyStringSchema = z.string().min(1);\n\nexport const sha256HashSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/);\nexport const isoUtcTimestampSchema = z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,9})?Z$/)\n .refine((value) => !Number.isNaN(Date.parse(value)), { message: \"Expected a valid UTC ISO timestamp\" });\n\nexport const l1FileIdSchema = nonEmptyStringSchema.refine((value) => value.startsWith(\"file:\"), {\n message: \"Expected a file: id\",\n});\nexport const l1ModuleIdSchema = nonEmptyStringSchema.refine((value) => value.startsWith(\"module:\"), {\n message: \"Expected a module: id\",\n});\nexport const l1FeatureIdSchema = nonEmptyStringSchema.refine((value) => value.startsWith(\"feature:\"), {\n message: \"Expected a feature: id\",\n});\n\nexport const l1FileSymbolSchema = z\n .object({\n id: nonEmptyStringSchema.refine((value) => value.startsWith(\"symbol:\"), { message: \"Expected a symbol: id\" }),\n kind: nonEmptyStringSchema,\n name: nonEmptyStringSchema,\n exported: z.boolean(),\n summary: nonEmptyStringSchema,\n })\n .strict();\n\nexport const l1FileEvidenceSchema = z\n .object({\n kind: nonEmptyStringSchema,\n value: nonEmptyStringSchema,\n })\n .strict();\n\nexport const l1FileEntrySchema = z\n .object({\n $schema: z.literal(l1FileEntrySchemaPath),\n id: l1FileIdSchema,\n layer: z.literal(\"L1\"),\n type: z.literal(\"file\"),\n path: nonEmptyStringSchema,\n language: nonEmptyStringSchema,\n content_hash: sha256HashSchema,\n size_bytes: z.number().int().nonnegative(),\n last_scanned_at: isoUtcTimestampSchema,\n scan_status: z.enum(l1FileScanStatuses),\n summary: nonEmptyStringSchema,\n responsibilities: z.array(nonEmptyStringSchema),\n symbols: z.array(l1FileSymbolSchema),\n imports: z.array(l1FileIdSchema),\n exports: z.array(nonEmptyStringSchema),\n module_ids: z.array(l1ModuleIdSchema),\n feature_ids: z.array(l1FeatureIdSchema),\n test_ids: z.array(l1FileIdSchema),\n evidence: z.array(l1FileEvidenceSchema),\n confidence: z.enum(l1ConfidenceLevels),\n })\n .strict()\n .refine((entry) => entry.id === `file:${entry.path}`, {\n message: \"File entry id must match path\",\n path: [\"id\"],\n });\n\nexport type L1FileScanStatus = (typeof l1FileScanStatuses)[number];\nexport type L1ConfidenceLevel = (typeof l1ConfidenceLevels)[number];\nexport type L1FileSymbol = z.infer<typeof l1FileSymbolSchema>;\nexport type L1FileEvidence = z.infer<typeof l1FileEvidenceSchema>;\nexport type L1FileEntry = z.infer<typeof l1FileEntrySchema>;\n\nexport function parseL1FileEntry(value: unknown): L1FileEntry {\n return l1FileEntrySchema.parse(value);\n}\n","import { z } from \"zod\";\nimport { isoUtcTimestampSchema, l1FileIdSchema, sha256HashSchema } from \"./l1-entry.js\";\nimport { type InventoryFile } from \"./inventory.js\";\n\nexport const l1QueueStatuses = [\"queued\", \"in_progress\", \"completed\", \"failed\", \"changed\", \"missing_file\"] as const;\n\nexport const l1QueueStatusSchema = z.enum(l1QueueStatuses);\n\nexport const l1QueueFailureSchema = z\n .object({\n code: z.string().min(1),\n message: z.string().min(1),\n failedAt: isoUtcTimestampSchema,\n })\n .strict();\n\nexport const l1QueueItemSchema = z\n .object({\n id: l1FileIdSchema,\n path: z.string().min(1),\n sizeBytes: z.number().int().nonnegative(),\n hash: sha256HashSchema,\n status: l1QueueStatusSchema,\n failure: l1QueueFailureSchema.optional(),\n })\n .strict()\n .refine((item) => item.id === `file:${item.path}`, {\n message: \"L1 queue item id must match path\",\n path: [\"id\"],\n });\n\nexport const l1QueueFileSchema = z\n .object({\n layer: z.literal(\"L1\"),\n generatedAt: isoUtcTimestampSchema,\n queuedFiles: z.array(l1QueueItemSchema),\n })\n .strict();\n\nexport type L1QueueStatus = (typeof l1QueueStatuses)[number];\nexport type L1QueueFailure = z.infer<typeof l1QueueFailureSchema>;\nexport type L1QueueItem = z.infer<typeof l1QueueItemSchema>;\nexport type L1QueueFile = z.infer<typeof l1QueueFileSchema>;\n\nexport function createL1QueueItem(file: InventoryFile): L1QueueItem {\n return l1QueueItemSchema.parse({\n ...file,\n id: `file:${file.path}`,\n status: \"queued\",\n });\n}\n\nexport function createL1QueueFile(queuedFiles: L1QueueItem[], generatedAt: string): L1QueueFile {\n return l1QueueFileSchema.parse({\n layer: \"L1\",\n generatedAt,\n queuedFiles,\n });\n}\n","export interface KnowledgeProgressEvent {\n message: string;\n}\n\nexport type KnowledgeProgressReporter = (event: KnowledgeProgressEvent) => void;\n\nexport function formatProgressBar(completed: number, total: number, width = 20): string {\n const safeTotal = Math.max(total, 0);\n const safeCompleted = safeTotal === 0 ? 0 : Math.min(Math.max(completed, 0), safeTotal);\n const filled = safeTotal === 0 ? width : Math.floor((safeCompleted / safeTotal) * width);\n return `${\"█\".repeat(filled)}${\"░\".repeat(width - filled)}`;\n}\n\nexport function formatCountProgress(label: string, completed: number, total: number, detail?: string): string {\n const safeTotal = Math.max(total, 0);\n const safeCompleted = safeTotal === 0 ? 0 : Math.min(Math.max(completed, 0), safeTotal);\n const percent = safeTotal === 0 ? 100 : Math.floor((safeCompleted / safeTotal) * 100);\n const suffix = detail ? ` ${detail}` : \"\";\n return `${label} [${formatProgressBar(safeCompleted, safeTotal)}] ${safeCompleted}/${safeTotal} (${percent}%)${suffix}`;\n}\n","import { join } from \"node:path\";\n\nexport function getL1FileEntryRelativePath(filePath: string): string {\n const normalizedPath = normalizeL1FilePath(filePath);\n return `${normalizedPath}.json`;\n}\n\nexport function getL1FileEntryPath(kbPath: string, filePath: string): string {\n return join(kbPath, \"l1-files\", getL1FileEntryRelativePath(filePath));\n}\n\nexport function mapL1FileEntryRelativePaths(filePaths: string[]): Map<string, string> {\n const entryPathsByPath = new Map<string, string>();\n const pathsByCaseFoldedEntryPath = new Map<string, string>();\n\n for (const filePath of filePaths) {\n const normalizedPath = normalizeL1FilePath(filePath);\n const entryPath = getL1FileEntryRelativePath(normalizedPath);\n const caseFoldedEntryPath = entryPath.toLowerCase();\n const existingPath = pathsByCaseFoldedEntryPath.get(caseFoldedEntryPath);\n\n if (existingPath && existingPath !== normalizedPath) {\n throw new Error(`L1 file entry path collision between ${existingPath} and ${normalizedPath}`);\n }\n\n pathsByCaseFoldedEntryPath.set(caseFoldedEntryPath, normalizedPath);\n entryPathsByPath.set(normalizedPath, entryPath);\n }\n\n return entryPathsByPath;\n}\n\nexport function normalizeL1FilePath(filePath: string): string {\n const normalizedPath = filePath.replace(/^\\.\\//, \"\");\n\n if (\n !normalizedPath ||\n /^[A-Za-z]:/.test(normalizedPath) ||\n normalizedPath.startsWith(\"/\") ||\n normalizedPath.includes(\"\\0\") ||\n normalizedPath.includes(\"\\\\\") ||\n normalizedPath.split(\"/\").some((part) => !part || part === \".\" || part === \"..\")\n ) {\n throw new Error(`Invalid workspace-relative file path: ${filePath}`);\n }\n\n return normalizedPath;\n}\n","import { createHash } from \"node:crypto\";\nimport { mkdir, open, readFile, readdir, realpath, rm, stat, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative } from \"node:path\";\nimport { ZodError } from \"zod\";\nimport { type ModelTextResult } from \"../../model/index.js\";\nimport { formatCountProgress, type KnowledgeProgressReporter } from \"../progress.js\";\nimport { l1FileEntrySchemaPath, parseL1FileEntry, type L1FileEntry } from \"./l1-entry.js\";\nimport { createL1QueueFile, l1QueueFileSchema, type L1QueueFailure, type L1QueueItem } from \"./l1.js\";\nimport { getL1FileEntryPath, normalizeL1FilePath } from \"./path-encoding.js\";\n\nconst MAX_L1_PROMPT_FILE_BYTES = 256 * 1024;\n\nexport interface L1SummaryModel {\n generateText(request: { purpose: \"kb.summarize\"; system: string; prompt: string }): Promise<ModelTextResult>;\n}\n\nexport interface ProcessL1QueueItemOptions {\n workspaceRoot: string;\n kbPath: string;\n item: L1QueueItem;\n model: L1SummaryModel;\n now?: () => Date;\n}\n\nexport interface ProcessL1QueueItemResult {\n item: L1QueueItem;\n entry?: L1FileEntry;\n entryPath?: string;\n}\n\nexport interface ProcessL1QueueOptions {\n workspaceRoot: string;\n kbPath: string;\n queuePath: string;\n manifestPath: string;\n gitignoreFiles: string[];\n model: L1SummaryModel;\n onProgress?: KnowledgeProgressReporter;\n now?: () => Date;\n}\n\nexport interface L1QueueProcessingSummary {\n queued: number;\n completed: number;\n failed: number;\n changed: number;\n missing: number;\n currentEntries: number;\n}\n\nexport interface ProcessL1QueueResult {\n queuedFiles: L1QueueItem[];\n summary: L1QueueProcessingSummary;\n}\n\nexport async function processL1Queue(options: ProcessL1QueueOptions): Promise<ProcessL1QueueResult> {\n const now = options.now ?? (() => new Date());\n const queue = l1QueueFileSchema.parse(JSON.parse(await readFile(options.queuePath, \"utf8\")));\n let queuedFiles = queue.queuedFiles.map(validateQueueItemPath);\n\n await removeOrphanedL1Entries(options.kbPath, new Set(queuedFiles.map((item) => item.path)));\n\n for (const [index, item] of queuedFiles.entries()) {\n options.onProgress?.({\n message: formatL1ProgressMessage(\"Processing L1 files\", index, queuedFiles.length, item.path),\n });\n\n if (item.status === \"completed\" && (await hasCurrentEntry(options.kbPath, item))) {\n options.onProgress?.({\n message: formatL1ProgressMessage(\"Processing L1 files\", index + 1, queuedFiles.length, item.path),\n });\n continue;\n }\n\n queuedFiles[index] = markInProgress(item);\n await persistQueue(options.queuePath, queuedFiles, now().toISOString());\n\n if (await hasCurrentEntry(options.kbPath, item)) {\n queuedFiles[index] = markTerminal(item, \"completed\");\n } else {\n const result = await processL1QueueItem({ ...options, item, now });\n queuedFiles[index] = result.item;\n }\n\n await persistQueue(options.queuePath, queuedFiles, now().toISOString());\n options.onProgress?.({\n message: formatL1ProgressMessage(\"Processing L1 files\", index + 1, queuedFiles.length, item.path),\n });\n }\n\n const summary = await summarizeL1Queue(options.kbPath, queuedFiles);\n await writeManifest(options, summary, now().toISOString());\n return { queuedFiles, summary };\n}\n\nfunction formatL1ProgressMessage(label: string, completed: number, total: number, path: string): string {\n return formatCountProgress(label, completed, total, path);\n}\n\nexport async function processL1QueueItem(options: ProcessL1QueueItemOptions): Promise<ProcessL1QueueItemResult> {\n const now = options.now ?? (() => new Date());\n const failedAt = () => now().toISOString();\n\n try {\n const normalizedPath = normalizeL1FilePath(options.item.path);\n const realWorkspaceRoot = await realpath(options.workspaceRoot);\n const queuedPath = join(realWorkspaceRoot, normalizedPath);\n const absolutePath = await realpath(queuedPath).catch((error: unknown) => {\n if (isNodeErrorCode(error, \"ENOENT\")) {\n return undefined;\n }\n throw error;\n });\n\n if (!absolutePath) {\n return { item: markTerminal(options.item, \"missing_file\") };\n }\n\n if (!isInsideDirectory(realWorkspaceRoot, absolutePath)) {\n return { item: markTerminal(options.item, \"changed\") };\n }\n\n const fileStat = await stat(absolutePath).catch((error: unknown) => {\n if (isNodeErrorCode(error, \"ENOENT\")) {\n return undefined;\n }\n throw error;\n });\n\n if (!fileStat) {\n return { item: markTerminal(options.item, \"missing_file\") };\n }\n\n if (!fileStat.isFile()) {\n return { item: failItem(options.item, \"not_file\", \"Queued path is not a file.\", failedAt()) };\n }\n\n const currentHash = await hashFile(absolutePath);\n if (fileStat.size !== options.item.sizeBytes || currentHash !== options.item.hash) {\n return { item: markTerminal(options.item, \"changed\") };\n }\n\n if (fileStat.size > MAX_L1_PROMPT_FILE_BYTES) {\n return {\n item: failItem(\n options.item,\n \"file_too_large\",\n `File is too large for V0 L1 prompt processing (${fileStat.size} bytes).`,\n failedAt()\n ),\n };\n }\n\n const content = await readFile(absolutePath, \"utf8\");\n const modelResult = await options.model.generateText({\n purpose: \"kb.summarize\",\n system: buildL1FileEntrySystemPrompt(),\n prompt: buildL1FileEntryPrompt({ path: normalizedPath, content }),\n });\n const modelEntry = parseL1ModelJson(modelResult.text);\n const entry = normalizeL1FileEntry(modelEntry, {\n path: normalizedPath,\n hash: currentHash,\n sizeBytes: fileStat.size,\n scannedAt: now().toISOString(),\n });\n const entryPath = getL1FileEntryPath(options.kbPath, normalizedPath);\n\n await mkdir(dirname(entryPath), { recursive: true });\n await writeFile(entryPath, `${JSON.stringify(entry, null, 2)}\\n`);\n\n return { item: markTerminal(options.item, \"completed\"), entry, entryPath };\n } catch (error) {\n return { item: failItem(options.item, classifyFailure(error), sanitizeErrorMessage(error), failedAt()) };\n }\n}\n\nexport function buildL1FileEntrySystemPrompt(): string {\n return [\n \"You summarize one repository file for Topchester's L1 knowledge base.\",\n \"Return exactly one JSON object and no markdown.\",\n \"Do not include secrets, credentials, or raw provider payloads.\",\n ].join(\"\\n\");\n}\n\nexport function buildL1FileEntryPrompt(input: { path: string; content: string }): string {\n return [\n \"Create an L1 file entry for this workspace-relative path.\",\n \"The compiler will overwrite id, path, content_hash, size_bytes, last_scanned_at, and scan_status.\",\n \"Use this JSON shape:\",\n JSON.stringify(\n {\n $schema: l1FileEntrySchemaPath,\n id: \"file:<path>\",\n layer: \"L1\",\n type: \"file\",\n path: \"<path>\",\n language: \"typescript\",\n content_hash: \"sha256:<hash>\",\n size_bytes: 0,\n last_scanned_at: \"2026-05-11T00:00:00Z\",\n scan_status: \"current\",\n summary: \"One clear sentence.\",\n responsibilities: [\"What this file owns or does.\"],\n symbols: [],\n imports: [],\n exports: [],\n module_ids: [],\n feature_ids: [],\n test_ids: [],\n evidence: [{ kind: \"path\", value: \"<path>\" }],\n confidence: \"medium\",\n },\n null,\n 2\n ),\n `Path: ${input.path}`,\n \"File content:\",\n \"```\",\n input.content,\n \"```\",\n ].join(\"\\n\");\n}\n\nexport function parseL1ModelJson(text: string): unknown {\n const trimmed = text.trim();\n if (!trimmed) {\n throw new Error(\"Model returned empty output.\");\n }\n\n const jsonObjects = extractTopLevelJsonObjects(trimmed);\n if (jsonObjects.length !== 1) {\n throw new Error(\n jsonObjects.length === 0 ? \"Model output did not contain a JSON object.\" : \"Model output was ambiguous.\"\n );\n }\n\n return JSON.parse(jsonObjects[0]);\n}\n\nfunction normalizeL1FileEntry(\n value: unknown,\n deterministic: { path: string; hash: string; sizeBytes: number; scannedAt: string }\n): L1FileEntry {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\"Model JSON was not an object.\");\n }\n\n return parseL1FileEntry({\n ...normalizeModelOwnedL1Fields(value, deterministic.path),\n $schema: l1FileEntrySchemaPath,\n id: `file:${deterministic.path}`,\n layer: \"L1\",\n type: \"file\",\n path: deterministic.path,\n content_hash: deterministic.hash,\n size_bytes: deterministic.sizeBytes,\n last_scanned_at: deterministic.scannedAt,\n scan_status: \"current\",\n });\n}\n\nfunction normalizeModelOwnedL1Fields(value: object, path: string): Record<string, unknown> {\n const record = value as Record<string, unknown>;\n return {\n ...record,\n responsibilities: normalizeStringArray(record.responsibilities),\n symbols: normalizeSymbols(record.symbols, path),\n imports: normalizePrefixedIds(record.imports, \"file:\"),\n exports: normalizeStringArray(record.exports),\n module_ids: normalizePrefixedIds(record.module_ids, \"module:\"),\n feature_ids: normalizePrefixedIds(record.feature_ids, \"feature:\"),\n test_ids: normalizePrefixedIds(record.test_ids, \"file:\"),\n evidence: normalizeEvidence(record.evidence),\n };\n}\n\nfunction normalizeStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0);\n}\n\nfunction normalizePrefixedIds(value: unknown, prefix: string): string[] {\n return normalizeStringArray(value).filter((item) => item.startsWith(prefix));\n}\n\nfunction normalizeEvidence(value: unknown): Array<{ kind: string; value: string }> {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.flatMap((item) => {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) {\n return [];\n }\n const record = item as Record<string, unknown>;\n if (typeof record.kind !== \"string\" || record.kind.trim().length === 0) {\n return [];\n }\n if (typeof record.value !== \"string\" || record.value.trim().length === 0) {\n return [];\n }\n return [{ kind: record.kind, value: record.value }];\n });\n}\n\nfunction normalizeSymbols(value: unknown, path: string | undefined): Array<Record<string, unknown>> {\n if (!Array.isArray(value)) {\n return [];\n }\n return value.flatMap((item) => {\n if (typeof item === \"string\") {\n const name = item.trim();\n if (!name || !path) {\n return [];\n }\n return [\n {\n id: `symbol:${path}#${name}`,\n kind: \"symbol\",\n name,\n exported: false,\n summary: `Symbol named ${name}.`,\n },\n ];\n }\n if (!item || typeof item !== \"object\" || Array.isArray(item)) {\n return [];\n }\n const record = item as Record<string, unknown>;\n const rawId = typeof record.id === \"string\" && record.id.startsWith(\"symbol:\") ? record.id : undefined;\n const name =\n typeof record.name === \"string\" && record.name.trim().length > 0\n ? record.name\n : rawId?.slice(rawId.lastIndexOf(\"#\") + 1);\n if (!name || !path) {\n return [];\n }\n return [\n {\n id: rawId ?? `symbol:${path}#${name}`,\n kind: typeof record.kind === \"string\" && record.kind.trim().length > 0 ? record.kind : \"symbol\",\n name,\n exported: typeof record.exported === \"boolean\" ? record.exported : false,\n summary:\n typeof record.summary === \"string\" && record.summary.trim().length > 0\n ? record.summary\n : `Symbol named ${name}.`,\n },\n ];\n });\n}\n\nfunction extractTopLevelJsonObjects(text: string): string[] {\n const objects: string[] = [];\n let depth = 0;\n let start = -1;\n let inString = false;\n let escaped = false;\n\n for (let index = 0; index < text.length; index += 1) {\n const char = text[index];\n\n if (inString) {\n if (escaped) {\n escaped = false;\n } else if (char === \"\\\\\") {\n escaped = true;\n } else if (char === '\"') {\n inString = false;\n }\n continue;\n }\n\n if (char === '\"') {\n inString = true;\n continue;\n }\n\n if (char === \"{\") {\n if (depth === 0) {\n start = index;\n }\n depth += 1;\n continue;\n }\n\n if (char === \"}\" && depth > 0) {\n depth -= 1;\n if (depth === 0 && start >= 0) {\n objects.push(text.slice(start, index + 1));\n start = -1;\n }\n }\n }\n\n return objects.filter((objectText) => {\n try {\n JSON.parse(objectText);\n return true;\n } catch {\n return false;\n }\n });\n}\n\nasync function hashFile(absolutePath: string): Promise<string> {\n const fileHandle = await open(absolutePath, \"r\");\n try {\n const hash = createHash(\"sha256\");\n const stream = fileHandle.createReadStream();\n for await (const chunk of stream) {\n hash.update(chunk);\n }\n return `sha256:${hash.digest(\"hex\")}`;\n } finally {\n await fileHandle.close();\n }\n}\n\nfunction markTerminal(item: L1QueueItem, status: \"completed\" | \"changed\" | \"missing_file\"): L1QueueItem {\n const { failure: _failure, ...rest } = item;\n return { ...rest, status };\n}\n\nfunction markInProgress(item: L1QueueItem): L1QueueItem {\n const { failure: _failure, ...rest } = item;\n return { ...rest, status: \"in_progress\" };\n}\n\nfunction failItem(item: L1QueueItem, code: string, message: string, failedAt: string): L1QueueItem {\n return { ...item, status: \"failed\", failure: sanitizeFailure({ code, message, failedAt }) };\n}\n\nfunction sanitizeFailure(failure: L1QueueFailure): L1QueueFailure {\n return {\n code: failure.code.replace(/[^a-z0-9_]/gi, \"_\").slice(0, 64) || \"failed\",\n message: sanitizeErrorText(failure.message),\n failedAt: failure.failedAt,\n };\n}\n\nfunction sanitizeErrorMessage(error: unknown): string {\n if (error instanceof ZodError) {\n return `L1 entry validation failed: ${error.issues.map((issue) => issue.path.join(\".\") || issue.message).join(\", \")}`;\n }\n if (error instanceof SyntaxError) {\n return \"Model output was not valid JSON.\";\n }\n if (error instanceof Error) {\n return error.message;\n }\n return \"L1 processing failed.\";\n}\n\nfunction sanitizeErrorText(text: string): string {\n return text\n .replace(/sk-[A-Za-z0-9_-]+/g, \"[redacted]\")\n .replace(/SECRET_SENTINEL_[A-Za-z0-9_-]+/g, \"[redacted]\")\n .slice(0, 500);\n}\n\nfunction classifyFailure(error: unknown): string {\n if (error instanceof ZodError) {\n return \"validation_error\";\n }\n if (error instanceof SyntaxError) {\n return \"json_parse_error\";\n }\n return \"processing_error\";\n}\n\nfunction isNodeErrorCode(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === code;\n}\n\nfunction isInsideDirectory(directory: string, target: string): boolean {\n const relativePath = relative(directory, target);\n return (\n relativePath === \"\" || (!relativePath.startsWith(\"..\") && !relativePath.startsWith(\"/\") && relativePath !== \"..\")\n );\n}\n\nfunction validateQueueItemPath(item: L1QueueItem): L1QueueItem {\n const normalizedPath = normalizeL1FilePath(item.path);\n if (item.path !== normalizedPath || item.id !== `file:${normalizedPath}`) {\n throw new Error(`Invalid persisted L1 queue item path: ${item.path}`);\n }\n return item;\n}\n\nasync function persistQueue(queuePath: string, queuedFiles: L1QueueItem[], generatedAt: string): Promise<void> {\n const queue = createL1QueueFile(queuedFiles, generatedAt);\n await writeFile(queuePath, `${JSON.stringify(queue, null, 2)}\\n`);\n}\n\nasync function hasCurrentEntry(kbPath: string, item: L1QueueItem): Promise<boolean> {\n try {\n const entryPath = getL1FileEntryPath(kbPath, item.path);\n const entry = parseL1FileEntry(JSON.parse(await readFile(entryPath, \"utf8\")));\n return entry.scan_status === \"current\" && entry.path === item.path && entry.content_hash === item.hash;\n } catch {\n return false;\n }\n}\n\nasync function removeOrphanedL1Entries(kbPath: string, currentPaths: Set<string>): Promise<void> {\n const entriesDir = join(kbPath, \"l1-files\");\n const entryPaths = await listL1EntryJsonFiles(entriesDir).catch((error: unknown) => {\n if (isNodeErrorCode(error, \"ENOENT\")) {\n return [];\n }\n throw error;\n });\n\n for (const entryPath of entryPaths) {\n try {\n const entry = parseL1FileEntry(JSON.parse(await readFile(entryPath, \"utf8\")));\n if (!currentPaths.has(entry.path)) {\n await rm(entryPath, { force: true });\n }\n } catch {\n await rm(entryPath, { force: true });\n }\n }\n}\n\nasync function listL1EntryJsonFiles(directory: string): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true });\n const filePaths: string[] = [];\n\n for (const entry of entries) {\n const entryPath = join(directory, entry.name);\n if (entry.isDirectory()) {\n filePaths.push(...(await listL1EntryJsonFiles(entryPath)));\n } else if (entry.isFile() && entry.name.endsWith(\".json\")) {\n filePaths.push(entryPath);\n }\n }\n\n return filePaths;\n}\n\nasync function summarizeL1Queue(kbPath: string, queuedFiles: L1QueueItem[]): Promise<L1QueueProcessingSummary> {\n let currentEntries = 0;\n for (const item of queuedFiles) {\n if (await hasCurrentEntry(kbPath, item)) {\n currentEntries += 1;\n }\n }\n\n return {\n queued: queuedFiles.filter((item) => item.status === \"queued\" || item.status === \"in_progress\").length,\n completed: queuedFiles.filter((item) => item.status === \"completed\").length,\n failed: queuedFiles.filter((item) => item.status === \"failed\").length,\n changed: queuedFiles.filter((item) => item.status === \"changed\").length,\n missing: queuedFiles.filter((item) => item.status === \"missing_file\").length,\n currentEntries,\n };\n}\n\nasync function writeManifest(\n options: ProcessL1QueueOptions,\n summary: L1QueueProcessingSummary,\n generatedAt: string\n): Promise<void> {\n await writeFile(\n options.manifestPath,\n `${JSON.stringify(\n {\n name: \"topchester-kb\",\n version: 1,\n generatedAt,\n workspaceRoot: options.workspaceRoot,\n l1QueuePath: options.queuePath,\n queuedFileCount: summary.queued + summary.completed + summary.failed + summary.changed + summary.missing,\n l1: summary,\n gitignoreFiles: options.gitignoreFiles,\n },\n null,\n 2\n )}\\n`\n );\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { getKnowledgeStatus } from \"../status.js\";\nimport { type KnowledgeProgressReporter } from \"../progress.js\";\nimport { listProjectFilesForL1 } from \"./inventory.js\";\nimport { createL1QueueFile, createL1QueueItem, type L1QueueItem } from \"./l1.js\";\nimport { processL1Queue, type L1QueueProcessingSummary, type L1SummaryModel } from \"./l1-processor.js\";\n\nexport interface KnowledgeCompiler {\n compile(): Promise<KnowledgeCompileResult>;\n}\n\nexport interface KnowledgeCompileResult {\n workspaceRoot: string;\n kbPath: string;\n cachePath: string;\n gitignoreFiles: string[];\n queuedFiles: L1QueueItem[];\n queuePath: string;\n manifestPath: string;\n l1?: L1QueueProcessingSummary;\n}\n\nexport async function compileKnowledgeBase(\n workspaceRoot: string,\n options: { onProgress?: KnowledgeProgressReporter; model?: L1SummaryModel; requireModel?: boolean } = {}\n): Promise<KnowledgeCompileResult> {\n options.onProgress?.({ message: \"Checking project knowledge folders...\" });\n const status = getKnowledgeStatus(workspaceRoot);\n\n if (!status.kbExists || !status.kbIsDirectory) {\n throw new Error(\"Run `topchester kb init` before compiling the project knowledge base.\");\n }\n\n if (options.requireModel) {\n assertKbSummarizeModelConfigured(options.model);\n }\n\n await mkdir(status.cachePath, { recursive: true });\n options.onProgress?.({ message: \"Reading .gitignore files and listing project files...\" });\n const inventory = await listProjectFilesForL1(workspaceRoot, { excludedPaths: [status.kbPath, status.cachePath] });\n options.onProgress?.({ message: `Queued ${inventory.files.length} project files for L1...` });\n const queuedFiles = inventory.files.map(createL1QueueItem);\n const queuePath = join(status.cachePath, \"l1-queue.json\");\n const manifestPath = join(status.kbPath, \"manifest.json\");\n const generatedAt = new Date().toISOString();\n const queue = createL1QueueFile(queuedFiles, generatedAt);\n\n options.onProgress?.({ message: \"Writing L1 queue and manifest...\" });\n await writeFile(queuePath, `${JSON.stringify(queue, null, 2)}\\n`);\n const l1 = {\n queued: queuedFiles.length,\n completed: 0,\n failed: 0,\n changed: 0,\n missing: 0,\n currentEntries: 0,\n };\n await writeFile(\n manifestPath,\n `${JSON.stringify(\n {\n name: \"topchester-kb\",\n version: 1,\n generatedAt,\n workspaceRoot,\n l1QueuePath: queuePath,\n queuedFileCount: queuedFiles.length,\n l1,\n gitignoreFiles: inventory.gitignoreFiles,\n },\n null,\n 2\n )}\\n`\n );\n\n options.onProgress?.({ message: \"Processing L1 file entries with the configured model...\" });\n const processed = options.model\n ? await processL1Queue({\n workspaceRoot,\n kbPath: status.kbPath,\n queuePath,\n manifestPath,\n gitignoreFiles: inventory.gitignoreFiles,\n model: options.model,\n onProgress: options.onProgress,\n })\n : undefined;\n\n return {\n workspaceRoot,\n kbPath: status.kbPath,\n cachePath: status.cachePath,\n gitignoreFiles: inventory.gitignoreFiles,\n queuedFiles: processed?.queuedFiles ?? queuedFiles,\n queuePath,\n manifestPath,\n l1: processed?.summary ?? l1,\n };\n}\n\nexport function formatKnowledgeCompileResult(result: KnowledgeCompileResult): string[] {\n const l1 = result.l1 ?? {\n queued: result.queuedFiles.length,\n completed: 0,\n failed: 0,\n changed: 0,\n missing: 0,\n currentEntries: 0,\n };\n const totalQueued = result.queuedFiles.length;\n const hasPartialOutcomes = l1.failed > 0 || l1.changed > 0 || l1.missing > 0;\n const state =\n l1.completed === totalQueued && !hasPartialOutcomes\n ? \"L1 entries are ready and current\"\n : hasPartialOutcomes\n ? \"partial L1 compile; some files need attention\"\n : \"L1 file queue is ready\";\n\n return [\n \"KB compile\",\n `workspace: ${result.workspaceRoot}`,\n `gitignore files read: ${result.gitignoreFiles.length}`,\n `queue: ${result.queuePath}`,\n `manifest: ${result.manifestPath}`,\n `queued: ${totalQueued}`,\n `completed: ${l1.completed}`,\n `failed: ${l1.failed}`,\n `changed: ${l1.changed}`,\n `missing: ${l1.missing}`,\n `current L1 entries: ${l1.currentEntries}`,\n `state: ${state}`,\n ];\n}\n\nexport function isPartialKnowledgeCompileResult(result: KnowledgeCompileResult): boolean {\n const l1 = result.l1;\n return Boolean(\n l1 && (l1.failed > 0 || l1.changed > 0 || l1.missing > 0 || l1.completed !== result.queuedFiles.length)\n );\n}\n\nfunction assertKbSummarizeModelConfigured(model: L1SummaryModel | undefined): void {\n if (!model) {\n throw new Error('No model configured for purpose \"kb.summarize\"; L1 entries were not processed.');\n }\n\n const maybeResolvable = model as L1SummaryModel & { resolveModel?: (purpose: \"kb.summarize\") => unknown };\n if (maybeResolvable.resolveModel) {\n maybeResolvable.resolveModel(\"kb.summarize\");\n }\n}\n","import { mkdir, stat } from \"node:fs/promises\";\nimport { getTopchesterLogsPath, getTopchesterSessionsPath, getTopchesterStatePath } from \"../app/paths.js\";\nimport { type KnowledgeProgressReporter } from \"./progress.js\";\nimport { getKnowledgeStatus } from \"./status.js\";\n\nexport interface KnowledgeInitResult {\n workspaceRoot: string;\n createdPaths: string[];\n existingPaths: string[];\n}\n\nexport async function initializeKnowledgeBase(\n workspaceRoot: string,\n options: { onProgress?: KnowledgeProgressReporter } = {}\n): Promise<KnowledgeInitResult> {\n options.onProgress?.({ message: \"Checking project knowledge folders...\" });\n const status = getKnowledgeStatus(workspaceRoot);\n const paths = [\n getTopchesterStatePath(workspaceRoot),\n getTopchesterSessionsPath(workspaceRoot),\n getTopchesterLogsPath(workspaceRoot),\n status.kbPath,\n `${status.kbPath}/l1-files`,\n `${status.kbPath}/l2-modules`,\n `${status.kbPath}/l3-features`,\n `${status.kbPath}/graph`,\n `${status.kbPath}/reviews`,\n status.cachePath,\n ];\n const createdPaths: string[] = [];\n const existingPaths: string[] = [];\n\n for (const path of paths) {\n options.onProgress?.({ message: `Preparing ${path}...` });\n if (await directoryExists(path)) {\n existingPaths.push(path);\n continue;\n }\n\n await mkdir(path, { recursive: true });\n createdPaths.push(path);\n }\n\n return {\n workspaceRoot,\n createdPaths,\n existingPaths,\n };\n}\n\nexport function formatKnowledgeInitResult(result: KnowledgeInitResult): string[] {\n const lines = [\"KB init\", `workspace: ${result.workspaceRoot}`];\n\n for (const path of result.createdPaths) {\n lines.push(`created: ${path}`);\n }\n\n for (const path of result.existingPaths) {\n lines.push(`already exists: ${path}`);\n }\n\n lines.push(\"state: project knowledge folders are ready\");\n\n return lines;\n}\n\nasync function directoryExists(path: string): Promise<boolean> {\n try {\n const pathStat = await stat(path);\n\n if (!pathStat.isDirectory()) {\n throw new Error(`${path} exists but is not a folder`);\n }\n\n return true;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return false;\n }\n\n throw error;\n }\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n","import { rm } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { type KnowledgeProgressReporter } from \"./progress.js\";\nimport { getKnowledgeStatus } from \"./status.js\";\n\nexport interface KnowledgeResetResult {\n workspaceRoot: string;\n removedPaths: string[];\n missingPaths: string[];\n}\n\nexport async function resetKnowledgeBase(\n workspaceRoot: string,\n options: { onProgress?: KnowledgeProgressReporter } = {}\n): Promise<KnowledgeResetResult> {\n options.onProgress?.({ message: \"Checking project knowledge paths...\" });\n const status = getKnowledgeStatus(workspaceRoot);\n const paths = dedupePaths([status.kbPath, status.cachePath]);\n const removedPaths: string[] = [];\n const missingPaths: string[] = [];\n\n for (const path of paths) {\n assertSafeResetPath(workspaceRoot, path);\n options.onProgress?.({ message: `Removing ${path}...` });\n const removed = await removeIfPresent(path);\n\n if (removed) {\n removedPaths.push(path);\n } else {\n missingPaths.push(path);\n }\n }\n\n return {\n workspaceRoot,\n removedPaths,\n missingPaths,\n };\n}\n\nexport function formatKnowledgeResetResult(result: KnowledgeResetResult): string[] {\n const lines = [\"KB reset\", `workspace: ${result.workspaceRoot}`];\n\n for (const path of result.removedPaths) {\n lines.push(`removed: ${path}`);\n }\n\n for (const path of result.missingPaths) {\n lines.push(`already missing: ${path}`);\n }\n\n lines.push(\"state: project knowledge base was reset\");\n lines.push(\"next: run `topchester kb init` to start clean\");\n\n return lines;\n}\n\nasync function removeIfPresent(path: string): Promise<boolean> {\n try {\n await rm(path, { recursive: true, force: false });\n return true;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return false;\n }\n\n throw error;\n }\n}\n\nfunction dedupePaths(paths: string[]): string[] {\n return [...new Set(paths.map((path) => resolve(path)))];\n}\n\nfunction assertSafeResetPath(workspaceRoot: string, path: string): void {\n const workspace = resolve(workspaceRoot);\n const target = resolve(path);\n\n if (target === workspace) {\n throw new Error(`Refusing to reset KB because the configured KB path is the workspace root: ${target}`);\n }\n\n if (dirname(target) === target) {\n throw new Error(`Refusing to reset KB because the configured KB path is a filesystem root: ${target}`);\n }\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n","import { type ChatLayout } from \"./layout.js\";\n\nexport interface BusyIndicatorOptions {\n status: string;\n promptHint: string;\n activities: string[];\n activityEveryMs?: number;\n}\n\ninterface RenderRequester {\n requestRender(): void;\n}\n\nexport class BusyIndicator {\n private readonly frames = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n private timer: NodeJS.Timeout | undefined;\n private index = 0;\n private ticks = 0;\n private activityOverride: string | undefined;\n\n constructor(\n private readonly app: ChatLayout,\n private readonly tui: RenderRequester,\n private readonly options: BusyIndicatorOptions\n ) {}\n\n start(): void {\n this.app.setStatus(this.options.status);\n this.app.setPromptHint(this.options.promptHint);\n this.render();\n this.timer = setInterval(() => {\n this.index = (this.index + 1) % this.frames.length;\n this.ticks += 1;\n this.render();\n this.tui.requestRender();\n }, 80);\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n\n this.app.setPromptHint(undefined);\n this.app.setEphemeralLine(undefined);\n }\n\n setActivity(activity: string): void {\n this.activityOverride = activity;\n this.render();\n this.tui.requestRender();\n }\n\n private render(): void {\n if (this.activityOverride) {\n this.app.setEphemeralLine(`${this.frames[this.index]} ${this.activityOverride}`);\n return;\n }\n\n const activityEveryMs = this.options.activityEveryMs ?? 1200;\n const activityIndex = Math.floor((this.ticks * 80) / activityEveryMs) % this.options.activities.length;\n this.app.setEphemeralLine(`${this.frames[this.index]} ${this.options.activities[activityIndex]}`);\n }\n}\n","import { compileKnowledgeBase, formatKnowledgeCompileResult } from \"../knowledge/compiler/index.js\";\nimport { type L1SummaryModel } from \"../knowledge/compiler/l1-processor.js\";\nimport { formatKnowledgeInitResult, initializeKnowledgeBase } from \"../knowledge/init.js\";\nimport { type KnowledgeProgressReporter } from \"../knowledge/progress.js\";\nimport { formatKnowledgeResetResult, resetKnowledgeBase } from \"../knowledge/reset.js\";\nimport { getKnowledgeStatus, type KnowledgeStatus } from \"../knowledge/status.js\";\n\nexport interface SlashCommandContext {\n workspaceRoot: string;\n modelGateway?: L1SummaryModel;\n onProgress?: KnowledgeProgressReporter;\n}\n\nexport interface SlashCommandResult {\n messages: string[];\n}\n\nexport interface SlashCommand {\n name: string;\n description: string;\n execute(args: string[], context: SlashCommandContext): SlashCommandResult | Promise<SlashCommandResult>;\n}\n\nexport interface SlashCommandSuggestion {\n value: string;\n description: string;\n}\n\nexport interface ParsedSlashCommand {\n name: string;\n args: string[];\n}\n\nexport const slashCommandSuggestions: SlashCommandSuggestion[] = [\n {\n value: \"/kb status\",\n description: \"show project knowledge base status\",\n },\n {\n value: \"/kb compile\",\n description: \"process project files into L1 entries\",\n },\n {\n value: \"/kb init\",\n description: \"start project knowledge base setup\",\n },\n {\n value: \"/kb reset\",\n description: \"delete the local knowledge base and cache\",\n },\n];\n\nexport const slashCommands: SlashCommand[] = [\n {\n name: \"kb\",\n description: \"knowledge base commands\",\n execute: executeKbCommand,\n },\n];\n\nexport function parseSlashCommand(input: string): ParsedSlashCommand | undefined {\n const trimmed = input.trim();\n\n if (!trimmed.startsWith(\"/\")) {\n return undefined;\n }\n\n const parts = trimmed.slice(1).split(/\\s+/).filter(Boolean);\n const name = parts[0];\n\n if (!name) {\n return undefined;\n }\n\n return {\n name,\n args: parts.slice(1),\n };\n}\n\nexport async function executeSlashCommand(input: string, context: SlashCommandContext): Promise<SlashCommandResult> {\n const parsed = parseSlashCommand(input);\n\n if (!parsed) {\n return { messages: [\"That is not a slash command.\"] };\n }\n\n const command = slashCommands.find((candidate) => candidate.name === parsed.name);\n\n if (!command) {\n return { messages: [`Unknown command: /${parsed.name}`, \"Try /kb status.\"] };\n }\n\n return command.execute(parsed.args, context);\n}\n\nexport function getSlashCommandSuggestions(input: string): SlashCommandSuggestion[] {\n const trimmed = input.trimStart();\n\n if (!trimmed.startsWith(\"/\")) {\n return [];\n }\n\n const query = trimmed.toLowerCase();\n\n return slashCommandSuggestions.filter((suggestion) => suggestion.value.toLowerCase().startsWith(query));\n}\n\nasync function executeKbCommand(args: string[], context: SlashCommandContext): Promise<SlashCommandResult> {\n const subcommand = args[0];\n\n if (subcommand === \"status\") {\n return { messages: formatKnowledgeStatus(getKnowledgeStatus(context.workspaceRoot)) };\n }\n\n if (subcommand === \"init\") {\n return { messages: formatKnowledgeInitResult(await initializeKnowledgeBase(context.workspaceRoot)) };\n }\n\n if (subcommand === \"compile\") {\n if (!context.modelGateway) {\n return { messages: ['No model configured for purpose \"kb.summarize\"; L1 entries were not processed.'] };\n }\n\n try {\n return {\n messages: formatKnowledgeCompileResult(\n await compileKnowledgeBase(context.workspaceRoot, {\n model: context.modelGateway,\n requireModel: true,\n onProgress: context.onProgress,\n })\n ),\n };\n } catch (error) {\n return { messages: [`KB compile failed: ${error instanceof Error ? error.message : \"Unknown error.\"}`] };\n }\n }\n\n if (subcommand === \"reset\") {\n return { messages: formatKnowledgeResetResult(await resetKnowledgeBase(context.workspaceRoot)) };\n }\n\n return { messages: [\"Usage: /kb init, /kb compile, /kb reset, or /kb status\"] };\n}\n\nexport function formatKnowledgeStatus(status: KnowledgeStatus): string[] {\n const lines = [\n \"KB status\",\n `workspace: ${status.workspaceRoot}`,\n `knowledge folder: ${formatPathStatus(status.kbPath, status.kbExists, status.kbIsDirectory)} (${status.kbPathSource})`,\n `local cache folder: ${formatPathStatus(status.cachePath, status.cacheExists, status.cacheIsDirectory)} (${status.cachePathSource})`,\n ];\n\n if (!status.kbExists) {\n lines.push(\"state: no knowledge base found yet\");\n } else if (!status.kbIsDirectory) {\n lines.push(\"state: knowledge base path is not a folder\");\n } else {\n lines.push(\"state: knowledge base found\");\n }\n\n return lines;\n}\n\nfunction formatPathStatus(path: string, exists: boolean, isDirectory: boolean): string {\n if (!exists) {\n return `${path} [missing]`;\n }\n\n if (!isDirectory) {\n return `${path} [not a folder]`;\n }\n\n return `${path} [ok]`;\n}\n","import { ui } from \"../cli/ui.js\";\n\nexport type ChatMessageKind = \"system\" | \"user\" | \"agent\" | \"modal\";\n\ninterface TextChatMessage {\n kind: Exclude<ChatMessageKind, \"modal\">;\n text: string;\n meta?: string;\n}\nexport interface ChatModalAction {\n label: string;\n value?: string;\n}\n\nexport interface ChatModalMessage {\n kind: \"modal\";\n tone: \"info\" | \"warning\";\n title: string;\n body?: string;\n actions: ChatModalAction[];\n}\n\nexport type ChatMessage = TextChatMessage | ChatModalMessage;\n\nexport function systemMessage(text: string): ChatMessage {\n return { kind: \"system\", text };\n}\n\nexport function userMessage(text: string): ChatMessage {\n return { kind: \"user\", text };\n}\n\nexport function agentMessage(text: string, meta?: string): ChatMessage {\n return { kind: \"agent\", text, meta };\n}\n\nexport function modalMessage(message: Omit<ChatModalMessage, \"kind\">): ChatMessage {\n return { kind: \"modal\", ...message };\n}\n\nexport interface RenderChatMessageOptions {\n selectedActionIndex?: number;\n}\n\nexport function renderChatMessage(message: ChatMessage, options: RenderChatMessageOptions = {}): string[] {\n if (message.kind === \"modal\") {\n return renderChatModal(message, options.selectedActionIndex);\n }\n\n if (message.text.length === 0) {\n return [\"\"];\n }\n\n const lines = message.text.split(\"\\n\");\n\n if (message.kind === \"user\") {\n return renderUserMessage(lines);\n }\n\n if (message.kind === \"system\") {\n return renderSystemMessage(lines);\n }\n\n const prefix = getPrefix(message.kind);\n const rendered =\n prefix.length === 0\n ? lines\n : lines.map((line, index) => `${index === 0 ? prefix : \" \".repeat(prefix.length)}${line}`);\n\n if (message.meta) {\n rendered.push(ui.label(message.meta));\n }\n\n return rendered;\n}\n\nfunction renderUserMessage(lines: string[]): string[] {\n const prefix = \"You: \";\n const rendered = lines.map((line, index) => `${index === 0 ? prefix : \" \".repeat(prefix.length)}${line}`);\n\n return [\"\", ...rendered, \"\"];\n}\n\nfunction renderSystemMessage(lines: string[]): string[] {\n const bodyPrefix = \" \";\n\n return [`${ui.ok(\"✦\")} ${ui.label(\"System\")}:`, ...lines.map((line) => `${bodyPrefix}${line}`)];\n}\n\nfunction getPrefix(kind: TextChatMessage[\"kind\"]): string {\n switch (kind) {\n case \"agent\":\n return \"\";\n case \"user\":\n return `${ui.label(\"You\")}: `;\n case \"system\":\n return `${ui.label(\"System\")}: `;\n }\n}\n\nfunction renderChatModal(message: ChatModalMessage, selectedActionIndex?: number): string[] {\n const icon = message.tone === \"warning\" ? \"⚠️\" : \"ℹ️\";\n const title = message.tone === \"warning\" ? ui.warn(message.title) : ui.label(message.title);\n const bodyLines = message.body ? [\"\", ...message.body.split(\"\\n\")] : [];\n const actionLines = message.actions.map((action, index) => {\n const prefix = selectedActionIndex === index ? \">\" : \" \";\n\n return `${prefix} ${index + 1}) ${action.label}`;\n });\n const contentLines = [`${icon} ${title}:`, ...bodyLines, \"\", ...actionLines];\n const contentWidth = Math.max(...contentLines.map(stripAnsi).map((line) => line.length), 1);\n const top = `╭${\"─\".repeat(contentWidth + 2)}╮`;\n const bottom = `╰${\"─\".repeat(contentWidth + 2)}╯`;\n\n return [\n top,\n ...contentLines.map((line) => `│ ${line}${\" \".repeat(contentWidth - stripAnsi(line).length)} │`),\n bottom,\n ];\n}\n\nfunction stripAnsi(text: string): string {\n let plain = \"\";\n for (let index = 0; index < text.length; index += 1) {\n if (text.charCodeAt(index) === 27 && text[index + 1] === \"[\") {\n index += 2;\n while (index < text.length && text[index] !== \"m\") {\n index += 1;\n }\n continue;\n }\n\n plain += text[index];\n }\n\n return plain;\n}\n","import { matchesKey } from \"@earendil-works/pi-tui\";\n\nexport function isUpKey(data: string): boolean {\n return matchesKey(data, \"up\") || data === \"\\u001b[A\";\n}\n\nexport function isDownKey(data: string): boolean {\n return matchesKey(data, \"down\") || data === \"\\u001b[B\";\n}\n\nexport function isEnterKey(data: string): boolean {\n return matchesKey(data, \"enter\") || data === \"\\n\" || data === \"\\r\";\n}\n\nexport function isTabKey(data: string): boolean {\n return matchesKey(data, \"tab\") || data === \"\\t\";\n}\n\nexport function isPageUpKey(data: string): boolean {\n return data === \"\\u001b[5~\";\n}\n\nexport function isPageDownKey(data: string): boolean {\n return data === \"\\u001b[6~\";\n}\n\nexport function isHomeKey(data: string): boolean {\n return matchesKey(data, \"home\") || data === \"\\u001b[H\" || data === \"\\u001b[1~\";\n}\n\nexport function isEndKey(data: string): boolean {\n return matchesKey(data, \"end\") || data === \"\\u001b[F\" || data === \"\\u001b[4~\";\n}\n\nexport function parseMouseWheel(data: string): \"up\" | \"down\" | undefined {\n const sgrMatch = data.match(new RegExp(`^${escapeRegex(\"\\u001b\")}${escapeRegex(\"[<\")}(\\\\d+);\\\\d+;\\\\d+M$`));\n if (sgrMatch) {\n return getWheelDirection(Number(sgrMatch[1]));\n }\n\n if (data.startsWith(\"\\u001b[M\") && data.length >= 6) {\n return getWheelDirection(data.charCodeAt(3) - 32);\n }\n\n return undefined;\n}\n\nfunction getWheelDirection(button: number): \"up\" | \"down\" | undefined {\n if ((button & 64) !== 64) {\n return undefined;\n }\n\n return (button & 1) === 0 ? \"up\" : \"down\";\n}\n\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { basename } from \"node:path\";\nimport { type AppContext } from \"../app/context.js\";\nimport { ui } from \"../cli/ui.js\";\nimport { type ModelPurpose } from \"../model/index.js\";\nimport { renderChatMessage, systemMessage, type ChatMessage } from \"./messages.js\";\n\nexport function getStartupThreadMessages(context: AppContext): ChatMessage[] {\n const assignments = context.config.models?.assignments ?? {};\n const providers = context.config.models?.providers ?? {};\n const lines = [\n ui.heading(\"\"),\n `${ui.label(\"workspace\")}: ${context.workspaceRoot}`,\n `${ui.label(\"default model\")}: ${context.config.models?.defaultPurpose ?? \"agent.primary\"}`,\n ];\n\n if (Object.keys(assignments).length === 0) {\n lines.push(`${ui.label(\"model assignments\")}: none configured`);\n } else {\n lines.push(`${ui.label(\"model assignments\")}:`);\n for (const [purpose, model] of Object.entries(assignments)) {\n const provider = model.provider ? ` [${model.provider}]` : \"\";\n lines.push(` ${purpose}: ${model.name}${provider}`);\n }\n }\n\n const namedProviders = Object.entries(providers).filter(([providerId]) => providerId !== \"default\");\n\n if (namedProviders.length === 0) {\n lines.push(`${ui.label(\"providers\")}: none configured`);\n } else {\n lines.push(`${ui.label(\"providers\")}:`);\n if (typeof providers.default === \"string\") {\n lines.push(` default: ${providers.default}`);\n }\n for (const [providerId, provider] of namedProviders) {\n if (typeof provider === \"string\") {\n continue;\n }\n const auth = provider.apiKeyEnv ? `env:${provider.apiKeyEnv}` : provider.apiKey ? \"inline\" : \"none\";\n lines.push(` ${providerId}: ${provider.type} ${provider.baseURL} auth=${auth}`);\n }\n }\n\n lines.push(\"\");\n lines.push(\"Ask Topchester what you want to change.\");\n\n return [systemMessage(lines.join(\"\\n\"))];\n}\n\nexport function renderStaticLayout(messages: ChatMessage[], folderName = \"\", modelLabel = \"\"): string {\n const threadLines = messages.flatMap((message) => renderChatMessage(message));\n const status = formatStatusLine(folderName, modelLabel);\n\n return [\n ...threadLines,\n \"\",\n \"┌──────────────────────────────────────────────────────────────────────┐\",\n \"│ > │\",\n \"└──────────────────────────────────────────────────────────────────────┘\",\n status,\n ].join(\"\\n\");\n}\n\nexport function getFolderName(path: string): string {\n return basename(path) || path;\n}\n\nexport function formatStatusLine(folderName: string, modelLabel: string, status = \"ready\"): string {\n const folder = folderName ? ` · folder: ${folderName}` : \"\";\n const model = modelLabel ? ` · model: ${modelLabel}` : \"\";\n\n return `${ui.label(\"status\")}: ${status}${folder}${model}`;\n}\n\nexport function formatPathStatus(path: string, exists: boolean, isDirectory: boolean): string {\n if (!exists) {\n return `${path} ${ui.warn(\"[missing]\")}`;\n }\n\n if (!isDirectory) {\n return `${path} ${ui.error(\"[not a folder]\")}`;\n }\n\n return `${path} ${ui.ok(\"[ok]\")}`;\n}\n\nexport function getModelLabel(context: AppContext): string {\n const purpose = context.config.models?.defaultPurpose ?? \"agent.primary\";\n const model =\n context.config.models?.assignments?.[purpose as ModelPurpose] ?? context.config.models?.assignments?.fallback;\n\n if (!model) {\n return \"not set\";\n }\n\n const provider = model.provider ?? context.config.models?.providers?.default;\n\n return typeof provider === \"string\" ? `${model.name} [${provider}]` : model.name;\n}\n","import { truncateToWidth } from \"@earendil-works/pi-tui\";\n\nexport function padLines(lines: string[], height: number, width: number): string[] {\n const padding = Array.from({ length: Math.max(0, height - lines.length) }, () => \"\");\n\n return [...padding, ...lines].map((line) => truncateToWidth(line, width, \"…\", true));\n}\n\nexport function padThreadLine(line: string, innerWidth: number, width: number): string {\n return truncateToWidth(` ${truncateToWidth(line, innerWidth, \"…\", true)} `, width, \"…\", true);\n}\n\nexport function stripAnsi(text: string): string {\n let plain = \"\";\n for (let index = 0; index < text.length; index += 1) {\n if (text.charCodeAt(index) === 27 && text[index + 1] === \"[\") {\n index += 2;\n while (index < text.length && text[index] !== \"m\") {\n index += 1;\n }\n continue;\n }\n\n plain += text[index];\n }\n\n return plain;\n}\n","import {\n Input,\n matchesKey,\n truncateToWidth,\n wrapTextWithAnsi,\n type Component,\n type Focusable,\n type Terminal,\n} from \"@earendil-works/pi-tui\";\nimport { getSlashCommandSuggestions, type SlashCommandSuggestion } from \"../agent/commands.js\";\nimport { type ConversationTurn } from \"../agent/conversation.js\";\nimport { ui } from \"../cli/ui.js\";\nimport { renderChatMessage, userMessage, type ChatMessage } from \"./messages.js\";\nimport {\n isDownKey,\n isEndKey,\n isEnterKey,\n isHomeKey,\n isPageDownKey,\n isPageUpKey,\n isTabKey,\n isUpKey,\n parseMouseWheel,\n} from \"./keys.js\";\nimport { formatStatusLine } from \"./status.js\";\nimport { padLines, padThreadLine, stripAnsi } from \"./text.js\";\n\nexport class ChatLayout implements Component, Focusable {\n private readonly input = new Input();\n private status = \"ready\";\n private ephemeralLine: string | undefined;\n private noticeLine: string | undefined;\n private promptHint: string | undefined;\n private cancelPending: (() => void) | undefined;\n private submitMessage: ((message: string) => void) | undefined;\n private submitCommand: ((command: string) => void) | undefined;\n private activeModalActionIndex = 0;\n private activeSlashSuggestionIndex = 0;\n private threadScrollOffset = 0;\n\n constructor(\n private readonly terminal: Terminal,\n private readonly messages: ChatMessage[],\n private readonly folderName: string,\n private readonly modelLabel: string,\n private readonly exitAgent: () => void = () => {}\n ) {\n this.input.onSubmit = (value) => {\n if (value.trim().length > 0) {\n const message = value.trim();\n this.addMessage(userMessage(message));\n this.input.setValue(\"\");\n this.submitUserInput(message);\n }\n };\n }\n\n addMessage(message: ChatMessage): void {\n this.messages.push(message);\n this.threadScrollOffset = 0;\n if (message.kind === \"modal\") {\n this.activeModalActionIndex = 0;\n }\n }\n\n setStatus(status: string): void {\n this.status = status;\n }\n\n isReady(): boolean {\n return this.status === \"ready\";\n }\n\n setEphemeralLine(line: string | undefined): void {\n this.ephemeralLine = line;\n }\n\n setNoticeLine(line: string | undefined): void {\n this.noticeLine = line;\n }\n\n setPromptHint(hint: string | undefined): void {\n this.promptHint = hint;\n }\n\n setCancelPending(cancel: (() => void) | undefined): void {\n this.cancelPending = cancel;\n }\n\n setSubmitMessage(submit: ((message: string) => void) | undefined): void {\n this.submitMessage = submit;\n }\n\n setSubmitCommand(submit: ((command: string) => void) | undefined): void {\n this.submitCommand = submit;\n }\n\n setInputValue(value: string): void {\n this.input.setValue(value);\n }\n\n getConversationTurns(): ConversationTurn[] {\n return this.messages.flatMap((message): ConversationTurn[] => {\n if (message.kind === \"user\") {\n return [{ role: \"user\", text: message.text }];\n }\n\n if (message.kind === \"agent\" && message.text !== \"ready\") {\n return [{ role: \"assistant\", text: message.text }];\n }\n\n return [];\n });\n }\n\n get focused(): boolean {\n return this.input.focused;\n }\n\n set focused(value: boolean) {\n this.input.focused = value;\n }\n\n handleInput(data: string): void {\n if (this.cancelPending && matchesKey(data, \"escape\")) {\n this.cancelPending();\n return;\n }\n\n if (this.handleModalInput(data)) {\n return;\n }\n\n if (this.handleSlashSuggestionInput(data)) {\n return;\n }\n\n if (this.handleThreadScrollInput(data)) {\n return;\n }\n\n this.input.handleInput(data);\n }\n\n invalidate(): void {\n this.input.invalidate();\n }\n\n render(width: number): string[] {\n const safeWidth = Math.max(20, width);\n const footerLines = this.getActiveModal() ? this.renderModalHelp(safeWidth) : this.renderPrompt(safeWidth);\n const threadHeight = Math.max(1, this.terminal.rows - footerLines.length);\n const allThreadLines = this.renderThread(safeWidth);\n const maxScrollOffset = Math.max(0, allThreadLines.length - threadHeight);\n this.threadScrollOffset = Math.min(this.threadScrollOffset, maxScrollOffset);\n const end = allThreadLines.length - this.threadScrollOffset;\n const start = Math.max(0, end - threadHeight);\n const threadLines = allThreadLines.slice(start, end);\n\n return [...padLines(threadLines, threadHeight, safeWidth), ...footerLines];\n }\n\n private renderThread(width: number): string[] {\n const innerWidth = Math.max(1, width - 2);\n\n const activeModalIndex = this.getActiveModalIndex();\n const lines = this.messages.flatMap((message, index) => {\n const messageLines = renderChatMessage(message, {\n selectedActionIndex: index === activeModalIndex ? this.activeModalActionIndex : undefined,\n });\n const spacer = index === this.messages.length - 1 ? [] : [padThreadLine(\"\", innerWidth, width)];\n\n return [...this.renderThreadMessageLines(messageLines, innerWidth, width, message.kind === \"user\"), ...spacer];\n });\n\n if (this.ephemeralLine) {\n lines.push(...this.renderThreadMessageLines([this.ephemeralLine], innerWidth, width, false));\n }\n\n if (this.noticeLine) {\n lines.push(...this.renderThreadMessageLines([this.noticeLine], innerWidth, width, false));\n }\n\n return lines;\n }\n\n private renderThreadMessageLines(lines: string[], innerWidth: number, width: number, highlight: boolean): string[] {\n return lines.flatMap((line) => {\n const styleLine = (value: string) => (highlight ? ui.softBackground(value) : value);\n\n if (line.length === 0) {\n return [styleLine(padThreadLine(\"\", innerWidth, width))];\n }\n\n return wrapTextWithAnsi(line, innerWidth).map((wrappedLine) =>\n styleLine(padThreadLine(wrappedLine, innerWidth, width))\n );\n });\n }\n\n private renderPrompt(width: number): string[] {\n const top = `┌${\"─\".repeat(Math.max(0, width - 2))}┐`;\n const bottom = `└${\"─\".repeat(Math.max(0, width - 2))}┘`;\n const prefix = \"> \";\n const innerWidth = Math.max(1, width - 4 - prefix.length);\n const inputLine = this.promptHint\n ? truncateToWidth(ui.label(this.promptHint), innerWidth, \"…\", true)\n : truncateToWidth(renderInputWithoutPrompt(this.input, innerWidth), innerWidth, \"…\", true);\n const status = truncateToWidth(formatStatusLine(this.folderName, this.modelLabel, this.status), width, \"…\", true);\n\n return [...this.renderSlashSuggestions(width), top, `│ ${prefix}${inputLine} │`, bottom, status];\n }\n\n private renderSlashSuggestions(width: number): string[] {\n const suggestions = this.getSlashSuggestions();\n\n if (suggestions.length === 0 || this.promptHint) {\n return [];\n }\n\n this.activeSlashSuggestionIndex = Math.min(this.activeSlashSuggestionIndex, suggestions.length - 1);\n\n const innerWidth = Math.max(1, width - 4);\n const visibleSuggestions = suggestions.slice(0, 6);\n const lines = [\n ui.label(\"slash commands\"),\n ...visibleSuggestions.map((suggestion, index) => {\n const marker = index === this.activeSlashSuggestionIndex ? \">\" : \" \";\n const text = `${marker} ${suggestion.value} — ${suggestion.description}`;\n\n return truncateToWidth(text, innerWidth, \"…\", true);\n }),\n ui.label(\"Tab complete · ↑↓ choose\"),\n ];\n const maxLineWidth = Math.max(...lines.map(stripAnsi).map((line) => line.length), 1);\n const boxWidth = Math.min(innerWidth, maxLineWidth);\n const top = `╭${\"─\".repeat(boxWidth + 2)}╮`;\n const bottom = `╰${\"─\".repeat(boxWidth + 2)}╯`;\n\n return [\n top,\n ...lines.map((line) => `│ ${line}${\" \".repeat(Math.max(0, boxWidth - stripAnsi(line).length))} │`),\n bottom,\n ];\n }\n\n private renderModalHelp(width: number): string[] {\n const help = \"↑↓ navigate Enter select Esc cancel\";\n const status = formatStatusLine(this.folderName, this.modelLabel, this.status);\n\n return [truncateToWidth(` ${help}`, width, \"…\", true), truncateToWidth(` ${status}`, width, \"…\", true)];\n }\n\n private handleModalInput(data: string): boolean {\n const activeModal = this.getActiveModal();\n\n if (!activeModal) {\n return false;\n }\n\n if (isUpKey(data)) {\n this.activeModalActionIndex =\n (this.activeModalActionIndex - 1 + activeModal.actions.length) % activeModal.actions.length;\n return true;\n }\n\n if (isDownKey(data)) {\n this.activeModalActionIndex = (this.activeModalActionIndex + 1) % activeModal.actions.length;\n return true;\n }\n\n if (matchesKey(data, \"enter\") || data === \"\\n\" || data === \"\\r\") {\n const action = activeModal.actions[this.activeModalActionIndex];\n if (action.label === \"Exit\") {\n this.exitAgent();\n return true;\n }\n\n this.submitModalAction(action.value ?? action.label);\n return true;\n }\n\n if (matchesKey(data, \"escape\")) {\n this.addMessage(userMessage(\"Cancel\"));\n return true;\n }\n\n return false;\n }\n\n private handleThreadScrollInput(data: string): boolean {\n const pageSize = Math.max(1, Math.floor(this.terminal.rows / 2));\n const wheel = parseMouseWheel(data);\n\n if (isUpKey(data)) {\n this.threadScrollOffset += 3;\n return true;\n }\n\n if (isDownKey(data)) {\n this.threadScrollOffset = Math.max(0, this.threadScrollOffset - 3);\n return true;\n }\n\n if (wheel === \"up\") {\n this.threadScrollOffset += 3;\n return true;\n }\n\n if (wheel === \"down\") {\n this.threadScrollOffset = Math.max(0, this.threadScrollOffset - 3);\n return true;\n }\n\n if (isPageUpKey(data)) {\n this.threadScrollOffset += pageSize;\n return true;\n }\n\n if (isPageDownKey(data)) {\n this.threadScrollOffset = Math.max(0, this.threadScrollOffset - pageSize);\n return true;\n }\n\n if (isHomeKey(data)) {\n this.threadScrollOffset = Number.MAX_SAFE_INTEGER;\n return true;\n }\n\n if (isEndKey(data)) {\n this.threadScrollOffset = 0;\n return true;\n }\n\n return false;\n }\n\n private handleSlashSuggestionInput(data: string): boolean {\n const suggestions = this.getSlashSuggestions();\n\n if (suggestions.length === 0) {\n this.activeSlashSuggestionIndex = 0;\n return false;\n }\n\n if (isUpKey(data)) {\n this.activeSlashSuggestionIndex = (this.activeSlashSuggestionIndex - 1 + suggestions.length) % suggestions.length;\n return true;\n }\n\n if (isDownKey(data)) {\n this.activeSlashSuggestionIndex = (this.activeSlashSuggestionIndex + 1) % suggestions.length;\n return true;\n }\n\n if (isTabKey(data)) {\n this.completeSlashSuggestion(suggestions);\n return true;\n }\n\n if (isEnterKey(data) && this.input.getValue().trim() !== suggestions[this.activeSlashSuggestionIndex]?.value) {\n this.completeSlashSuggestion(suggestions);\n return true;\n }\n\n return false;\n }\n\n private completeSlashSuggestion(suggestions: SlashCommandSuggestion[]): void {\n this.input.setValue(suggestions[this.activeSlashSuggestionIndex]?.value ?? this.input.getValue());\n this.input.handleInput(\"\\u001b[F\");\n }\n\n private getSlashSuggestions(): SlashCommandSuggestion[] {\n return getSlashCommandSuggestions(this.input.getValue());\n }\n\n private getActiveModal(): Extract<ChatMessage, { kind: \"modal\" }> | undefined {\n return this.messages[this.getActiveModalIndex()] as Extract<ChatMessage, { kind: \"modal\" }> | undefined;\n }\n\n private getActiveModalIndex(): number {\n return this.messages[this.messages.length - 1]?.kind === \"modal\" ? this.messages.length - 1 : -1;\n }\n\n private submitModalAction(message: string): void {\n this.addMessage(userMessage(message));\n this.submitUserInput(message);\n }\n\n private submitUserInput(message: string): void {\n if (message.startsWith(\"/\")) {\n this.submitCommand?.(message);\n } else {\n this.submitMessage?.(message);\n }\n }\n}\n\nfunction renderInputWithoutPrompt(input: Input, width: number): string {\n return (input.render(width + 2)[0] ?? \"\").replace(/^> /, \"\");\n}\n","export interface ConversationTurn {\n role: \"user\" | \"assistant\";\n text: string;\n}\n\nexport function buildConversationPrompt(turns: ConversationTurn[], latestMessage: string): string {\n const lines = turns.map((turn) => {\n const label = turn.role === \"user\" ? \"User\" : \"Assistant\";\n\n return `${label}: ${turn.text}`;\n });\n\n if (lines.at(-1) !== `User: ${latestMessage}`) {\n lines.push(`User: ${latestMessage}`);\n }\n\n return lines.join(\"\\n\\n\");\n}\n","import { type KnowledgeStatus } from \"../knowledge/status.js\";\nimport { type ToolCall } from \"./tools.js\";\n\nexport type AgentRuntimeEvent =\n | AgentStatusEvent\n | AgentMessageEvent\n | AgentToolCallEvent\n | AgentKnowledgeStatusEvent\n | AgentChoiceEvent;\n\nexport interface AgentStatusEvent {\n type: \"status\";\n status: string;\n}\n\nexport interface AgentMessageEvent {\n type: \"message\";\n role: \"system\" | \"assistant\";\n text: string;\n meta?: string;\n}\n\nexport interface AgentToolCallEvent {\n type: \"tool_call\";\n call: ToolCall;\n label: string;\n}\n\nexport interface AgentKnowledgeStatusEvent {\n type: \"knowledge_status\";\n status: KnowledgeStatus;\n}\n\nexport interface AgentChoiceEvent {\n type: \"choice\";\n tone: \"info\" | \"warning\";\n title: string;\n body?: string;\n actions: AgentChoiceAction[];\n}\n\nexport interface AgentChoiceAction {\n label: string;\n value?: string;\n}\n\nexport interface AgentChoiceOptions {\n tone: AgentChoiceEvent[\"tone\"];\n title: string;\n body?: string;\n actions: AgentChoiceAction[];\n}\n\nexport const agentEvent = {\n status(status: string): AgentStatusEvent {\n return { type: \"status\", status };\n },\n\n systemMessage(text: string): AgentMessageEvent {\n return { type: \"message\", role: \"system\", text };\n },\n\n assistantMessage(text: string, meta?: string): AgentMessageEvent {\n return meta === undefined\n ? { type: \"message\", role: \"assistant\", text }\n : { type: \"message\", role: \"assistant\", text, meta };\n },\n\n toolCall(call: ToolCall, label: string): AgentToolCallEvent {\n return { type: \"tool_call\", call, label };\n },\n\n knowledgeStatus(status: KnowledgeStatus): AgentKnowledgeStatusEvent {\n return { type: \"knowledge_status\", status };\n },\n\n choice(options: AgentChoiceOptions): AgentChoiceEvent {\n return { type: \"choice\", ...options };\n },\n} as const;\n\nexport function choiceAction(label: string, value?: string): AgentChoiceAction {\n return value === undefined ? { label } : { label, value };\n}\n","import { type ModelGateway } from \"../model/index.js\";\n\nexport type AgentReadyCheckResult = \"ready\" | \"not-ready\" | \"timed-out\";\n\nexport async function checkAgentReady(\n modelGateway: ModelGateway,\n abortSignal?: AbortSignal\n): Promise<AgentReadyCheckResult> {\n const abortController = new AbortController();\n let timedOut = false;\n const timeout = setTimeout(() => {\n timedOut = true;\n abortController.abort();\n }, 30_000);\n const abort = () => abortController.abort();\n\n abortSignal?.addEventListener(\"abort\", abort, { once: true });\n\n try {\n const result = await modelGateway.generateText({\n purpose: \"agent.fast\",\n system: \"You are a startup health check. Reply with exactly one word: ready\",\n prompt: \"Reply with exactly: ready\",\n abortSignal: abortController.signal,\n });\n\n return result.text.trim().toLowerCase().includes(\"ready\") ? \"ready\" : \"not-ready\";\n } catch (error) {\n if (timedOut && isAbortError(error)) {\n return \"timed-out\";\n }\n\n throw error;\n } finally {\n clearTimeout(timeout);\n abortSignal?.removeEventListener(\"abort\", abort);\n }\n}\n\nfunction isAbortError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n\n return error.name === \"AbortError\" || error.message.toLowerCase().includes(\"aborted\");\n}\n","import { type z } from \"zod\";\nimport { type Logger } from \"pino\";\n\nexport interface ToolContext {\n workspaceRoot: string;\n pathEnv?: string;\n logger?: Logger;\n}\n\nexport interface ToolCall<Name extends string = string, Args = unknown> {\n tool: Name;\n args: Args;\n}\n\nexport interface ToolResult<Name extends string = string> {\n tool: Name;\n path?: string;\n content: string;\n command?: string;\n warning?: string;\n}\n\nexport interface ToolDefinition<Name extends string, Args, Result extends ToolResult<Name> = ToolResult<Name>> {\n name: Name;\n description: string;\n prompt: string;\n argsSchema: z.ZodType<Args>;\n execute(context: ToolContext, args: Args): Promise<Result>;\n}\n\nexport type ToolCallForDefinition<Definition> =\n Definition extends ToolDefinition<infer Name, infer Args, infer _Result> ? ToolCall<Name, Args> : never;\n\nexport type ToolResultForDefinition<Definition> =\n Definition extends ToolDefinition<infer _Name, infer _Args, infer Result> ? Result : never;\n\nexport function defineTool<const Name extends string, Args, Result extends ToolResult<Name>>(\n definition: ToolDefinition<Name, Args, Result>\n): ToolDefinition<Name, Args, Result> {\n return definition;\n}\n","import { execFile as execFileNode } from \"node:child_process\";\nimport { constants } from \"node:fs\";\nimport { access, readdir } from \"node:fs/promises\";\nimport { basename, delimiter, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { type Logger } from \"pino\";\nimport { z } from \"zod\";\nimport { defineTool, type ToolCall, type ToolResult } from \"./types.js\";\n\nexport const findFileArgsSchema = z.object({\n query: z.string().min(1),\n path: z.string().optional().default(\".\"),\n limit: z.number().int().min(1).max(200).optional().default(50),\n});\n\nexport type FindFileToolArgs = z.infer<typeof findFileArgsSchema>;\nexport type FindFileToolCall = ToolCall<\"find_file\", FindFileToolArgs>;\nexport type FindFileToolResult = ToolResult<\"find_file\">;\n\nexport interface FindWorkspaceFilesByNameOptions {\n pathEnv?: string;\n logger?: Logger;\n}\n\ninterface FileMatch {\n path: string;\n score: number;\n}\n\nconst ignoredDirectories = new Set([\n \".git\",\n \".agents\",\n \".cache\",\n \".next\",\n \".turbo\",\n \"build\",\n \"coverage\",\n \"dist\",\n \"node_modules\",\n]);\n\nexport const findFileTool = defineTool({\n name: \"find_file\",\n description: \"Find files by fuzzy name inside the workspace.\",\n prompt:\n 'find_file: find files by fuzzy name inside the workspace. To use it, reply with only JSON: {\"tool\":\"find_file\",\"args\":{\"query\":\"runtime\"}}',\n argsSchema: findFileArgsSchema,\n execute: (context, args) =>\n findWorkspaceFilesByName(context.workspaceRoot, args, { pathEnv: context.pathEnv, logger: context.logger }),\n});\n\nexport async function findWorkspaceFilesByName(\n workspaceRoot: string,\n args: FindFileToolArgs,\n options: FindWorkspaceFilesByNameOptions = {}\n): Promise<FindFileToolResult> {\n const scopedPath = resolveWorkspaceScopedPath(workspaceRoot, args.path);\n const files = await collectWorkspaceFiles(\n scopedPath.workspaceRoot,\n scopedPath.path,\n scopedPath.relativePath,\n options\n );\n const matches = files\n .map((path): FileMatch | undefined => {\n const score = scoreFileMatch(args.query, path);\n\n return score > 0 ? { path, score } : undefined;\n })\n .filter((match): match is FileMatch => Boolean(match))\n .sort((left, right) => right.score - left.score || left.path.localeCompare(right.path))\n .slice(0, args.limit);\n\n return {\n tool: \"find_file\",\n path: scopedPath.relativePath,\n content: matches.length > 0 ? matches.map((match) => match.path).join(\"\\n\") : \"No matching files.\",\n };\n}\n\nasync function collectWorkspaceFiles(\n workspaceRoot: string,\n startPath: string,\n relativeStartPath: string,\n options: FindWorkspaceFilesByNameOptions\n): Promise<string[]> {\n const nativeFiles = await collectWorkspaceFilesWithNativeCommand(workspaceRoot, relativeStartPath, options);\n\n if (nativeFiles) {\n return nativeFiles;\n }\n\n options.logger?.debug(\n {\n event: \"native_tool_selected\",\n tool: \"find_file\",\n nativeTool: \"node\",\n path: relativeStartPath,\n },\n \"native tool selected\"\n );\n\n return collectWorkspaceFilesWithNode(workspaceRoot, startPath);\n}\n\nasync function collectWorkspaceFilesWithNativeCommand(\n workspaceRoot: string,\n relativeStartPath: string,\n options: FindWorkspaceFilesByNameOptions\n): Promise<string[] | undefined> {\n const pathEnv = options.pathEnv ?? process.env.PATH ?? \"\";\n const collectors: NativeCollectorFactory[] = [createRipgrepCollector, createFdCollector, createFindCollector];\n\n for (const createCollector of collectors) {\n const collector = await createCollector(pathEnv, relativeStartPath);\n\n if (!collector) {\n continue;\n }\n\n options.logger?.debug(\n {\n event: \"native_tool_selected\",\n tool: \"find_file\",\n nativeTool: collector.name,\n path: relativeStartPath,\n },\n \"native tool selected\"\n );\n const result = await runCommand(collector.command, collector.args, workspaceRoot);\n options.logger?.debug(\n {\n event: \"find_file_command_result\",\n command: collector.name,\n exitCode: result.exitCode,\n stdoutLength: result.stdout.length,\n stderrLength: result.stderr.length,\n },\n \"find_file command result\"\n );\n options.logger?.trace(\n {\n event: \"find_file_command_output\",\n command: collector.name,\n stdout: result.stdout,\n stderr: result.stderr,\n },\n \"find_file command output\"\n );\n\n if (result.exitCode === 0) {\n return normalizeCommandFileList(workspaceRoot, result.stdout);\n }\n }\n\n return undefined;\n}\n\nasync function collectWorkspaceFilesWithNode(workspaceRoot: string, startPath: string): Promise<string[]> {\n const files: string[] = [];\n const pending = [startPath];\n\n while (pending.length > 0) {\n const currentPath = pending.pop() ?? startPath;\n const entries = await readdir(currentPath, { withFileTypes: true });\n\n for (const entry of entries) {\n const absolutePath = resolve(currentPath, entry.name);\n const relativePath = relative(workspaceRoot, absolutePath);\n\n if (entry.isDirectory()) {\n if (!ignoredDirectories.has(entry.name)) {\n pending.push(absolutePath);\n }\n continue;\n }\n\n if (entry.isFile()) {\n files.push(relativePath || \".\");\n }\n }\n }\n\n return files;\n}\n\ninterface NativeCollector {\n name: string;\n command: string;\n args: string[];\n}\n\ntype NativeCollectorFactory = (pathEnv: string, relativeStartPath: string) => Promise<NativeCollector | undefined>;\n\nasync function createRipgrepCollector(\n pathEnv: string,\n relativeStartPath: string\n): Promise<NativeCollector | undefined> {\n const command = await findExecutable(\"rg\", pathEnv);\n\n if (!command) {\n return undefined;\n }\n\n return {\n name: \"rg\",\n command,\n args: [\"--files\", \"--hidden\", ...ignoredDirectoryGlobArgs(), \"--\", relativeStartPath],\n };\n}\n\nasync function createFdCollector(pathEnv: string, relativeStartPath: string): Promise<NativeCollector | undefined> {\n const fdCommand = await findExecutable(\"fd\", pathEnv);\n const fdfindCommand = fdCommand ? undefined : await findExecutable(\"fdfind\", pathEnv);\n const command = fdCommand ?? fdfindCommand;\n\n if (!command) {\n return undefined;\n }\n\n return {\n name: fdCommand ? \"fd\" : \"fdfind\",\n command,\n args: [\"--type\", \"f\", \"--hidden\", \"--color\", \"never\", ...ignoredDirectoryExcludeArgs(), \".\", relativeStartPath],\n };\n}\n\nasync function createFindCollector(pathEnv: string, relativeStartPath: string): Promise<NativeCollector | undefined> {\n const command = await findExecutable(\"find\", pathEnv);\n\n if (!command) {\n return undefined;\n }\n\n return {\n name: \"find\",\n command,\n args: [relativeStartPath, \"(\", ...ignoredDirectoryFindPruneArgs(), \")\", \"-prune\", \"-o\", \"-type\", \"f\", \"-print\"],\n };\n}\n\nfunction ignoredDirectoryGlobArgs(): string[] {\n return [...ignoredDirectories].flatMap((directory) => [\"--glob\", `!${directory}/**`]);\n}\n\nfunction ignoredDirectoryExcludeArgs(): string[] {\n return [...ignoredDirectories].flatMap((directory) => [\"--exclude\", directory]);\n}\n\nfunction ignoredDirectoryFindPruneArgs(): string[] {\n return [...ignoredDirectories].flatMap((directory, index) =>\n index === 0 ? [\"-name\", directory] : [\"-o\", \"-name\", directory]\n );\n}\n\nfunction normalizeCommandFileList(workspaceRoot: string, stdout: string): string[] {\n return stdout\n .split(\"\\n\")\n .map((line) => normalizeCommandFilePath(workspaceRoot, line))\n .filter((path): path is string => Boolean(path));\n}\n\nfunction normalizeCommandFilePath(workspaceRoot: string, path: string): string | undefined {\n const trimmed = path.trim();\n\n if (!trimmed) {\n return undefined;\n }\n\n const relativePath = isAbsolute(trimmed) ? relative(workspaceRoot, trimmed) : trimmed.replace(/^\\.\\//, \"\");\n\n if (!relativePath || relativePath.startsWith(\"..\") || isAbsolute(relativePath)) {\n return undefined;\n }\n\n return relativePath;\n}\n\nfunction scoreFileMatch(query: string, path: string): number {\n const normalizedQuery = normalize(query);\n const normalizedPath = normalize(path);\n const normalizedName = normalize(basename(path));\n\n if (!normalizedQuery) {\n return 0;\n }\n\n const exactScore = scoreExactMatch(normalizedQuery, normalizedPath, normalizedName);\n if (exactScore > 0) {\n return exactScore;\n }\n\n const pathTokenScore = scoreTokenMatch(normalizedQuery, normalizedPath);\n const nameTokenScore = scoreTokenMatch(normalizedQuery, normalizedName);\n const nameFuzzyScore = scoreSubsequenceMatch(normalizedQuery, normalizedName);\n const pathFuzzyScore = scoreSubsequenceMatch(normalizedQuery, normalizedPath);\n\n return Math.max(pathTokenScore, nameTokenScore, nameFuzzyScore, pathFuzzyScore);\n}\n\nfunction scoreExactMatch(query: string, path: string, name: string): number {\n if (name === query) {\n return 1000;\n }\n\n if (path === query) {\n return 950;\n }\n\n const nameIndex = name.indexOf(query);\n if (nameIndex >= 0) {\n return 900 - nameIndex - Math.max(0, name.length - query.length) / 100;\n }\n\n const pathIndex = path.indexOf(query);\n if (pathIndex >= 0) {\n return 800 - pathIndex - Math.max(0, path.length - query.length) / 100;\n }\n\n return 0;\n}\n\nfunction scoreTokenMatch(query: string, value: string): number {\n const tokens = query.split(/[^a-z0-9]+/).filter(Boolean);\n\n if (tokens.length <= 1 || !tokens.every((token) => value.includes(token))) {\n return 0;\n }\n\n return 700 - Math.max(0, value.length - query.length) / 100;\n}\n\nfunction scoreSubsequenceMatch(query: string, value: string): number {\n let queryIndex = 0;\n let gapCount = 0;\n let lastMatchIndex = -1;\n\n for (let valueIndex = 0; valueIndex < value.length && queryIndex < query.length; valueIndex += 1) {\n if (value[valueIndex] !== query[queryIndex]) {\n continue;\n }\n\n if (lastMatchIndex >= 0) {\n gapCount += valueIndex - lastMatchIndex - 1;\n }\n\n lastMatchIndex = valueIndex;\n queryIndex += 1;\n }\n\n if (queryIndex !== query.length) {\n return 0;\n }\n\n return 600 - gapCount - Math.max(0, value.length - query.length) / 100;\n}\n\nfunction normalize(value: string): string {\n return value.trim().toLowerCase().replaceAll(\"\\\\\", \"/\");\n}\n\nfunction resolveWorkspaceScopedPath(workspaceRoot: string, path: string) {\n const resolvedWorkspace = resolve(workspaceRoot);\n const resolvedPath = isAbsolute(path) ? resolve(path) : resolve(resolvedWorkspace, path);\n const relativePath = relative(resolvedWorkspace, resolvedPath);\n\n if (relativePath.startsWith(\"..\") || isAbsolute(relativePath)) {\n throw new Error(`find_file can only search inside the workspace: ${path}`);\n }\n\n return {\n workspaceRoot: resolvedWorkspace,\n path: resolvedPath,\n relativePath: relativePath || \".\",\n };\n}\n\nasync function findExecutable(name: string, pathEnv: string): Promise<string | undefined> {\n for (const pathEntry of pathEnv.split(delimiter).filter(Boolean)) {\n const executablePath = join(pathEntry, name);\n\n try {\n await access(executablePath, constants.X_OK);\n return executablePath;\n } catch {\n continue;\n }\n }\n\n return undefined;\n}\n\ninterface CommandResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\nfunction runCommand(command: string, args: string[], cwd: string): Promise<CommandResult> {\n return new Promise((resolveCommand) => {\n execFileNode(command, args, { cwd, maxBuffer: 5_000_000 }, (error, stdout, stderr) => {\n resolveCommand({\n exitCode: getExitCode(error),\n stdout: String(stdout),\n stderr: String(stderr),\n });\n });\n });\n}\n\nfunction getExitCode(error: unknown): number {\n if (!error) {\n return 0;\n }\n\n if (isRecord(error) && typeof error.code === \"number\") {\n return error.code;\n }\n\n return 1;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n","import { execFile as execFileNode } from \"node:child_process\";\nimport { constants } from \"node:fs\";\nimport { access } from \"node:fs/promises\";\nimport { delimiter, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { type Logger } from \"pino\";\nimport { z } from \"zod\";\nimport { defineTool, type ToolCall, type ToolResult } from \"./types.js\";\n\nexport const grepArgsSchema = z.object({\n pattern: z.string(),\n path: z.string().optional(),\n});\n\nexport type GrepToolArgs = z.infer<typeof grepArgsSchema>;\nexport type GrepToolCall = ToolCall<\"grep\", GrepToolArgs>;\nexport type GrepToolResult = ToolResult<\"grep\">;\n\nexport interface GrepWorkspaceOptions {\n pathEnv?: string;\n logger?: Logger;\n}\n\nexport const grepTool = defineTool({\n name: \"grep\",\n description: \"Search text inside the workspace.\",\n prompt:\n 'grep: search text inside the workspace. To use it, reply with only JSON: {\"tool\":\"grep\",\"args\":{\"pattern\":\"function name\",\"path\":\"src\"}}',\n argsSchema: grepArgsSchema,\n execute: (context, args) =>\n grepWorkspace(context.workspaceRoot, args, { pathEnv: context.pathEnv, logger: context.logger }),\n});\n\nexport async function grepWorkspace(\n workspaceRoot: string,\n args: GrepToolArgs,\n options: GrepWorkspaceOptions = {}\n): Promise<GrepToolResult> {\n const scopedPath = resolveWorkspaceScopedPath(workspaceRoot, args.path ?? \".\");\n const executable = await findSearchExecutable(options.pathEnv);\n\n if (!executable) {\n const warning = \"grep could not run because neither rg nor grep is available on PATH.\";\n options.logger?.debug(\n {\n event: \"native_tool_unavailable\",\n tool: \"grep\",\n candidates: [\"rg\", \"grep\"],\n path: scopedPath.relativePath,\n },\n \"native tool unavailable\"\n );\n\n return {\n tool: \"grep\",\n path: scopedPath.relativePath,\n content: warning,\n warning,\n };\n }\n\n const commandArgs =\n executable.name === \"rg\"\n ? [\n \"--line-number\",\n \"--color\",\n \"never\",\n \"--hidden\",\n \"--glob\",\n \"!.git/**\",\n \"--no-heading\",\n \"--\",\n args.pattern,\n scopedPath.relativePath,\n ]\n : [\"-R\", \"-n\", \"--\", args.pattern, scopedPath.relativePath];\n options.logger?.debug(\n {\n event: \"native_tool_selected\",\n tool: \"grep\",\n nativeTool: executable.name,\n path: scopedPath.relativePath,\n },\n \"native tool selected\"\n );\n const result = await runCommand(executable.path, commandArgs, scopedPath.workspaceRoot);\n\n options.logger?.debug(\n {\n event: \"grep_command_result\",\n command: executable.name,\n exitCode: result.exitCode,\n stdoutLength: result.stdout.length,\n stderrLength: result.stderr.length,\n },\n \"grep command result\"\n );\n options.logger?.trace(\n {\n event: \"grep_command_output\",\n command: executable.name,\n stdout: result.stdout,\n stderr: result.stderr,\n },\n \"grep command output\"\n );\n\n if (result.exitCode > 1) {\n throw new Error(\n `${executable.name} failed: ${result.stderr.trim() || result.stdout.trim() || `exit ${result.exitCode}`}`\n );\n }\n\n return {\n tool: \"grep\",\n path: scopedPath.relativePath,\n command: executable.name,\n content: truncateToolOutput(result.stdout.trimEnd() || \"No matches.\"),\n };\n}\n\nfunction resolveWorkspaceScopedPath(workspaceRoot: string, path: string) {\n const resolvedWorkspace = resolve(workspaceRoot);\n const resolvedPath = isAbsolute(path) ? resolve(path) : resolve(resolvedWorkspace, path);\n const relativePath = relative(resolvedWorkspace, resolvedPath);\n\n if (relativePath.startsWith(\"..\") || isAbsolute(relativePath)) {\n throw new Error(`grep can only search inside the workspace: ${path}`);\n }\n\n return {\n workspaceRoot: resolvedWorkspace,\n path: resolvedPath,\n relativePath: relativePath || \".\",\n };\n}\n\nasync function findSearchExecutable(pathEnv = process.env.PATH ?? \"\") {\n for (const name of [\"rg\", \"grep\"]) {\n const executablePath = await findExecutable(name, pathEnv);\n\n if (executablePath) {\n return { name, path: executablePath };\n }\n }\n\n return undefined;\n}\n\nasync function findExecutable(name: string, pathEnv: string): Promise<string | undefined> {\n for (const pathEntry of pathEnv.split(delimiter).filter(Boolean)) {\n const executablePath = join(pathEntry, name);\n\n try {\n await access(executablePath, constants.X_OK);\n return executablePath;\n } catch {\n continue;\n }\n }\n\n return undefined;\n}\n\ninterface CommandResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\nfunction runCommand(command: string, args: string[], cwd: string): Promise<CommandResult> {\n return new Promise((resolveCommand) => {\n execFileNode(command, args, { cwd, maxBuffer: 5_000_000 }, (error, stdout, stderr) => {\n const code = getExitCode(error);\n\n resolveCommand({\n exitCode: error ? code : 0,\n stdout: String(stdout),\n stderr: String(stderr),\n });\n });\n });\n}\n\nfunction getExitCode(error: unknown): number {\n if (isRecord(error) && typeof error.code === \"number\") {\n return error.code;\n }\n\n return 1;\n}\n\nfunction truncateToolOutput(output: string): string {\n const maxLength = 40_000;\n\n if (output.length <= maxLength) {\n return output;\n }\n\n return `${output.slice(0, maxLength)}\\n\\n[truncated]`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport { z } from \"zod\";\nimport { defineTool, type ToolCall, type ToolResult } from \"./types.js\";\n\nexport const readFileArgsSchema = z.object({\n path: z.string(),\n});\n\nexport type ReadFileToolArgs = z.infer<typeof readFileArgsSchema>;\nexport type ReadFileToolCall = ToolCall<\"read_file\", ReadFileToolArgs>;\nexport type ReadFileToolResult = ToolResult<\"read_file\">;\n\nexport const readFileTool = defineTool({\n name: \"read_file\",\n description: \"Read a UTF-8 file inside the workspace.\",\n prompt:\n 'read_file: read a UTF-8 file inside the workspace. To use it, reply with only JSON: {\"tool\":\"read_file\",\"args\":{\"path\":\"package.json\"}}',\n argsSchema: readFileArgsSchema,\n execute: (context, args) => readWorkspaceFile(context.workspaceRoot, args.path),\n});\n\nexport async function readWorkspaceFile(workspaceRoot: string, path: string): Promise<ReadFileToolResult> {\n const resolvedWorkspace = resolve(workspaceRoot);\n const resolvedPath = isAbsolute(path) ? resolve(path) : resolve(resolvedWorkspace, path);\n const relativePath = relative(resolvedWorkspace, resolvedPath);\n\n if (relativePath.startsWith(\"..\") || isAbsolute(relativePath)) {\n throw new Error(`read_file can only read files inside the workspace: ${path}`);\n }\n\n const content = await readFile(resolvedPath, \"utf8\");\n\n return {\n tool: \"read_file\",\n path: relativePath || \".\",\n content,\n };\n}\n","import { findFileTool } from \"./find-file.js\";\nimport { grepTool } from \"./grep.js\";\nimport { readFileTool } from \"./read-file.js\";\nimport { type ToolCallForDefinition, type ToolResultForDefinition } from \"./types.js\";\n\nexport const toolRegistry = {\n [readFileTool.name]: readFileTool,\n [grepTool.name]: grepTool,\n [findFileTool.name]: findFileTool,\n} as const;\n\nexport type ToolName = keyof typeof toolRegistry;\nexport type RegisteredTool = (typeof toolRegistry)[ToolName];\nexport type ToolCall = ToolCallForDefinition<RegisteredTool>;\nexport type ToolResult = ToolResultForDefinition<RegisteredTool>;\n\nexport function isToolName(name: string): name is ToolName {\n return name in toolRegistry;\n}\n\nexport function getToolDefinition<Name extends ToolName>(name: Name): (typeof toolRegistry)[Name] {\n return toolRegistry[name];\n}\n\nexport function getToolPromptLines(): string[] {\n return Object.values(toolRegistry).map((tool) => tool.prompt);\n}\n","import { getToolDefinition, type ToolCall, type ToolResult } from \"./registry.js\";\nimport { type ToolDefinition, type ToolContext } from \"./types.js\";\nimport { type Logger } from \"pino\";\n\nexport interface ExecuteToolCallOptions {\n pathEnv?: string;\n logger?: Logger;\n}\n\ntype RuntimeToolDefinition = ToolDefinition<string, unknown, ToolResult>;\n\nexport async function executeToolCall(\n workspaceRoot: string,\n call: ToolCall,\n options: ExecuteToolCallOptions = {}\n): Promise<ToolResult> {\n const definition = getToolDefinition(call.tool) as RuntimeToolDefinition;\n const startedAt = Date.now();\n const context: ToolContext = {\n workspaceRoot,\n pathEnv: options.pathEnv,\n logger: options.logger,\n };\n\n options.logger?.debug({ event: \"tool_call\", tool: call.tool, args: call.args }, \"tool call\");\n\n try {\n const result = await definition.execute(context, call.args);\n const durationMs = Date.now() - startedAt;\n\n options.logger?.debug(\n {\n event: \"tool_result\",\n tool: result.tool,\n path: result.path,\n command: result.command,\n warning: result.warning,\n durationMs,\n contentLength: result.content.length,\n },\n \"tool result\"\n );\n options.logger?.trace(\n {\n event: \"tool_result_content\",\n tool: result.tool,\n path: result.path,\n content: result.content,\n },\n \"tool result content\"\n );\n\n return result;\n } catch (error) {\n options.logger?.error(\n {\n event: \"tool_error\",\n tool: call.tool,\n durationMs: Date.now() - startedAt,\n err: error,\n },\n \"tool failed\"\n );\n throw error;\n }\n}\n","import { getToolDefinition, isToolName, type ToolCall } from \"./registry.js\";\n\nexport function parseToolCall(text: string): ToolCall | undefined {\n const trimmed = stripJsonFence(text.trim());\n let value: unknown;\n\n try {\n value = JSON.parse(trimmed);\n } catch {\n return undefined;\n }\n\n if (!isRecord(value) || typeof value.tool !== \"string\") {\n return undefined;\n }\n\n if (!isToolName(value.tool)) {\n return undefined;\n }\n\n const definition = getToolDefinition(value.tool);\n const parsed = definition.argsSchema.safeParse(value.args);\n\n if (!parsed.success) {\n return undefined;\n }\n\n return {\n tool: definition.name,\n args: parsed.data,\n } as ToolCall;\n}\n\nfunction stripJsonFence(text: string): string {\n const match = text.match(/^```(?:json)?\\s*([\\s\\S]*?)\\s*```$/i);\n\n return match?.[1] ?? text;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n","import { getToolPromptLines } from \"./tools.js\";\n\nexport function getChatSystemPrompt(): string {\n return [\n \"You are Topchester, a plain-spoken terminal coding agent for software engineering work.\",\n \"Your job is to turn ordinary user requests into concrete repository work: inspect the codebase, make focused changes when tools allow it, verify the result when possible, and report the outcome clearly.\",\n \"\",\n \"Working style:\",\n \"- Start by understanding the user's intent and the surrounding code before proposing or changing anything non-trivial.\",\n \"- Prefer local project evidence over assumptions. Use search and read tools to find relevant files, examples, tests, commands, and conventions.\",\n \"- Break multi-step work into a short internal plan. If a planning or todo tool is available, use it for non-trivial tasks and keep it current as work progresses.\",\n \"- Use the most specific available tool for the job. Prefer dedicated file/search/edit/test tools over shell commands when both are available.\",\n \"- Follow existing project style, naming, dependencies, and test patterns. Do not introduce new libraries or broad abstractions unless the existing code clearly supports that choice.\",\n \"- Verify changes with the narrowest relevant test or check when tools allow it. If verification is not possible, say what was not run and why.\",\n \"- Do not commit changes unless the user explicitly asks.\",\n \"- Keep user-facing responses concise and concrete. Mention changed files, verification, and any remaining risk.\",\n \"- Ask a clarifying question only when the missing information blocks useful progress or the safe interpretation is genuinely unclear.\",\n \"\",\n \"You have these tools available:\",\n ...getToolPromptLines(),\n \"\",\n \"Tool use:\",\n \"- Use read/search tools when the user asks about files, code, symbols, usages, tests, or project behavior.\",\n \"- Use edit/write tools when they are available and the user asks you to implement, fix, add, update, or refactor code.\",\n \"- Use command/test tools when they are available and you need to inspect the environment, run tests, format, lint, typecheck, or verify behavior.\",\n \"- After each tool result, decide the next useful action from the new evidence. Continue until the request is handled or blocked.\",\n \"Do not make up file contents or search results.\",\n ].join(\"\\n\");\n}\n","import { executeSlashCommand } from \"./commands.js\";\nimport { type ConversationTurn, buildConversationPrompt } from \"./conversation.js\";\nimport { agentEvent, choiceAction, type AgentRuntimeEvent } from \"./events.js\";\nimport { checkAgentReady } from \"./health.js\";\nimport { getChatSystemPrompt } from \"./prompts.js\";\nimport { executeToolCall, parseToolCall, type ToolCall, type ToolResult } from \"./tools.js\";\nimport { type AppContext } from \"../app/context.js\";\nimport { getKnowledgeStatus, type KnowledgeStatus } from \"../knowledge/status.js\";\nimport { type KnowledgeProgressReporter } from \"../knowledge/progress.js\";\n\nexport interface AgentRuntime {\n checkAgent(abortSignal?: AbortSignal): Promise<AgentRuntimeEvent[]>;\n checkKnowledgeBase(): AgentRuntimeEvent[];\n submitMessage(\n conversation: ConversationTurn[],\n message: string,\n abortSignal?: AbortSignal\n ): Promise<AgentRuntimeEvent[]>;\n submitSlashCommand(command: string, onProgress?: KnowledgeProgressReporter): Promise<AgentRuntimeEvent[]>;\n}\n\nexport class TopchesterAgentRuntime implements AgentRuntime {\n constructor(private readonly context: AppContext) {}\n\n async checkAgent(abortSignal?: AbortSignal): Promise<AgentRuntimeEvent[]> {\n const result = await checkAgentReady(this.context.modelGateway, abortSignal);\n\n if (result === \"ready\") {\n return [agentEvent.assistantMessage(\"ready\"), agentEvent.status(\"ready\")];\n }\n\n if (result === \"timed-out\") {\n return [\n agentEvent.systemMessage(\"Agent is taking a while, so I skipped the startup check.\"),\n agentEvent.status(\"ready\"),\n ];\n }\n\n return [agentEvent.systemMessage(\"Agent did not say it was ready.\"), agentEvent.status(\"ready\")];\n }\n\n checkKnowledgeBase(): AgentRuntimeEvent[] {\n return getKnowledgeStatusEvents(getKnowledgeStatus(this.context.workspaceRoot), this.context.devFlags);\n }\n\n async submitMessage(\n conversation: ConversationTurn[],\n message: string,\n abortSignal?: AbortSignal\n ): Promise<AgentRuntimeEvent[]> {\n const prompt = buildConversationPrompt(conversation, message);\n const startedAt = Date.now();\n const result = await this.context.modelGateway.generateText({\n purpose: \"agent.primary\",\n system: getChatSystemPrompt(),\n prompt,\n abortSignal,\n });\n const durationMs = Date.now() - startedAt;\n const meta = formatAgentMessageMeta(result.modelId, durationMs);\n const toolCall = parseToolCall(result.text);\n\n this.context.logger.debug(\n {\n event: \"model_response\",\n purpose: \"agent.primary\",\n modelId: result.modelId,\n durationMs,\n textLength: result.text.length,\n hasToolCall: Boolean(toolCall),\n },\n \"model response\"\n );\n this.context.logger.trace(\n {\n event: \"model_response_text\",\n purpose: \"agent.primary\",\n modelId: result.modelId,\n text: result.text,\n },\n \"model response text\"\n );\n\n if (toolCall) {\n const toolResult = await executeToolCall(this.context.workspaceRoot, toolCall, {\n logger: this.context.logger,\n });\n const finalStartedAt = Date.now();\n const finalResult = await this.context.modelGateway.generateText({\n purpose: \"agent.primary\",\n system: getChatSystemPrompt(),\n prompt: `${prompt}\\n\\n${formatToolResultForPrompt(toolResult)}\\n\\nAnswer the user's request using the tool result above. Do not guess.`,\n abortSignal,\n });\n const finalModelDurationMs = Date.now() - finalStartedAt;\n const finalDurationMs = durationMs + finalModelDurationMs;\n const finalMeta = formatAgentMessageMeta(finalResult.modelId, finalDurationMs);\n\n this.context.logger.debug(\n {\n event: \"model_response\",\n purpose: \"agent.primary\",\n modelId: finalResult.modelId,\n durationMs: finalModelDurationMs,\n totalDurationMs: finalDurationMs,\n textLength: finalResult.text.length,\n afterTool: toolCall.tool,\n },\n \"model response after tool\"\n );\n this.context.logger.trace(\n {\n event: \"model_response_text\",\n purpose: \"agent.primary\",\n modelId: finalResult.modelId,\n afterTool: toolCall.tool,\n text: finalResult.text,\n },\n \"model response text after tool\"\n );\n\n return [\n agentEvent.toolCall(toolCall, formatToolCallMessage(toolCall)),\n agentEvent.assistantMessage(finalResult.text.trim() || \"I got an empty response from the model.\", finalMeta),\n agentEvent.status(\"ready\"),\n ];\n }\n\n return [\n agentEvent.assistantMessage(result.text.trim() || \"I got an empty response from the model.\", meta),\n agentEvent.status(\"ready\"),\n ];\n }\n\n async submitSlashCommand(command: string, onProgress?: KnowledgeProgressReporter): Promise<AgentRuntimeEvent[]> {\n const result = await executeSlashCommand(command, {\n workspaceRoot: this.context.workspaceRoot,\n modelGateway: this.context.modelGateway,\n onProgress,\n });\n\n return [agentEvent.systemMessage(result.messages.join(\"\\n\")), agentEvent.status(\"ready\")];\n }\n}\n\nexport function getKnowledgeStatusEvents(status: KnowledgeStatus, devFlags = new Set<string>()): AgentRuntimeEvent[] {\n const events: AgentRuntimeEvent[] = [agentEvent.knowledgeStatus(status)];\n\n if (devFlags.has(\"disable-kb-check-modal\")) {\n return events;\n }\n\n if (!status.kbExists) {\n events.push(\n agentEvent.choice({\n tone: \"warning\",\n title: \"No KB found\",\n body: \"Topchester needs a project knowledge base before normal coding can start.\",\n actions: [choiceAction(\"Create KB now\", \"/kb init\"), choiceAction(\"Exit\")],\n })\n );\n } else if (!status.kbIsDirectory) {\n events.push(\n agentEvent.choice({\n tone: \"warning\",\n title: \"KB path is not a folder\",\n body: `This path exists but is not a folder:\\n${status.kbPath}`,\n actions: [choiceAction(\"Exit\")],\n })\n );\n }\n\n return events;\n}\n\nfunction formatToolResultForPrompt(result: ToolResult): string {\n const path = result.path ? ` ${JSON.stringify(result.path)}` : \"\";\n const command = result.command ? ` via ${result.command}` : \"\";\n const warning = result.warning ? `\\nWarning: ${result.warning}` : \"\";\n\n return [`Tool result from ${result.tool}${path}${command}:${warning}`, \"```\", result.content, \"```\"].join(\"\\n\");\n}\n\nfunction formatToolCallMessage(call: ToolCall): string {\n switch (call.tool) {\n case \"read_file\":\n return `Tool read_file: ${call.args.path}`;\n case \"grep\":\n return `Tool grep: ${call.args.pattern} in ${call.args.path ?? \".\"}`;\n case \"find_file\":\n return `Tool find_file: ${call.args.query} in ${call.args.path}`;\n }\n}\n\nfunction formatAgentMessageMeta(model: string, durationMs: number): string {\n return `${model} · ${formatDuration(durationMs)}`;\n}\n\nfunction formatDuration(durationMs: number): string {\n const totalSeconds = Math.max(0, durationMs / 1000);\n\n if (totalSeconds < 10) {\n return `${formatNumber(totalSeconds, 1)} sec`;\n }\n\n if (totalSeconds < 60) {\n return `${Math.round(totalSeconds)} sec`;\n }\n\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = Math.round(totalSeconds % 60);\n\n if (seconds === 0) {\n return `${minutes} min`;\n }\n\n return `${minutes} min ${seconds} sec`;\n}\n\nfunction formatNumber(value: number, fractionDigits: number): string {\n return value.toLocaleString(\"en\", {\n minimumFractionDigits: fractionDigits,\n maximumFractionDigits: fractionDigits,\n });\n}\n","import { type AgentRuntimeEvent } from \"../agent/events.js\";\nimport { getKnowledgeStatusEvents } from \"../agent/runtime.js\";\nimport { type KnowledgeStatus } from \"../knowledge/status.js\";\nimport { agentMessage, modalMessage, systemMessage, type ChatMessage } from \"./messages.js\";\nimport { formatPathStatus } from \"./status.js\";\n\nexport function getKnowledgeStatusMessages(status: KnowledgeStatus, devFlags = new Set<string>()): ChatMessage[] {\n return renderRuntimeEvents(getKnowledgeStatusEvents(status, devFlags));\n}\n\nexport function renderRuntimeEvents(events: AgentRuntimeEvent[]): ChatMessage[] {\n return events.flatMap(renderRuntimeEvent);\n}\n\nexport function renderRuntimeEvent(event: AgentRuntimeEvent): ChatMessage[] {\n switch (event.type) {\n case \"message\":\n return [event.role === \"assistant\" ? agentMessage(event.text, event.meta) : systemMessage(event.text)];\n case \"tool_call\":\n return [systemMessage(event.label)];\n case \"knowledge_status\":\n return [\n systemMessage(\n `KB status: ${formatPathStatus(event.status.kbPath, event.status.kbExists, event.status.kbIsDirectory)} (${event.status.kbPathSource})`\n ),\n ];\n case \"choice\":\n return [\n modalMessage({\n tone: event.tone,\n title: event.title,\n body: event.body,\n actions: event.actions,\n }),\n ];\n case \"status\":\n return [];\n }\n}\n","import { type Terminal } from \"@earendil-works/pi-tui\";\n\nexport function enterAlternateScreen(terminal: Pick<Terminal, \"write\" | \"clearScreen\">): void {\n terminal.write(\"\\u001b[?1049h\");\n terminal.clearScreen();\n}\n\nexport function exitAlternateScreen(terminal: Pick<Terminal, \"write\">): void {\n terminal.write(\"\\u001b[?1049l\");\n}\n","import { isKeyRelease, isKeyRepeat, matchesKey, ProcessTerminal, TUI } from \"@earendil-works/pi-tui\";\nimport { type AgentRuntimeEvent } from \"../agent/events.js\";\nimport { TopchesterAgentRuntime, type AgentRuntime } from \"../agent/runtime.js\";\nimport { type AppContext } from \"../app/context.js\";\nimport { BusyIndicator } from \"./busy.js\";\nimport { ChatLayout } from \"./layout.js\";\nimport { systemMessage } from \"./messages.js\";\nimport { renderRuntimeEvent } from \"./runtime-events.js\";\nimport { getFolderName, getModelLabel, getStartupThreadMessages, renderStaticLayout } from \"./status.js\";\nimport { enterAlternateScreen, exitAlternateScreen } from \"./terminal.js\";\n\nexport interface TuiShell {\n render(): Promise<void>;\n}\n\nexport class TopchesterTuiShell implements TuiShell {\n private readonly runtime: AgentRuntime;\n\n constructor(\n private readonly context: AppContext,\n runtime?: AgentRuntime\n ) {\n this.runtime = runtime ?? new TopchesterAgentRuntime(context);\n }\n\n async render(): Promise<void> {\n const messages = getStartupThreadMessages(this.context);\n const folderName = getFolderName(this.context.workspaceRoot);\n const modelLabel = getModelLabel(this.context);\n\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n console.log(renderStaticLayout(messages, folderName, modelLabel));\n return;\n }\n\n const terminal = new ProcessTerminal();\n enterAlternateScreen(terminal);\n const tui = new TUI(terminal, true);\n const exit = () => {\n tui.stop();\n exitAlternateScreen(terminal);\n };\n const app = new ChatLayout(terminal, messages, folderName, modelLabel, () => {\n exit();\n process.exit(0);\n });\n app.setSubmitMessage((message) => {\n void this.submitChatMessage(app, tui, message);\n });\n app.setSubmitCommand((command) => {\n void this.submitSlashCommand(app, tui, command);\n });\n\n tui.addChild(app);\n tui.setFocus(app);\n tui.addInputListener(\n createExitConfirmationInputListener({\n setNoticeLine: (line) => {\n app.setNoticeLine(line);\n },\n requestRender: () => {\n tui.requestRender();\n },\n exit: () => {\n exit();\n process.exit(0);\n },\n })\n );\n tui.start();\n void this.checkAgent(app, tui);\n }\n\n private async checkAgent(app: ChatLayout, tui: TUI): Promise<void> {\n const busy = new BusyIndicator(app, tui, {\n status: \"checking agent\",\n promptHint: \"press Esc to stop\",\n activities: [\"Checking model config...\", \"Calling agent.fast...\", \"Waiting for model...\"],\n });\n const abortController = new AbortController();\n let cancelled = false;\n\n app.setCancelPending(() => {\n cancelled = true;\n abortController.abort();\n });\n busy.start();\n tui.requestRender();\n\n try {\n this.applyRuntimeEvents(app, await this.runtime.checkAgent(abortController.signal));\n } catch (error) {\n if (cancelled) {\n app.addMessage(systemMessage(\"Agent check stopped.\"));\n app.setStatus(\"ready\");\n } else {\n const message = error instanceof Error ? error.message : String(error);\n app.addMessage(systemMessage(`Agent check failed: ${message}`));\n app.setStatus(\"agent check failed\");\n }\n } finally {\n app.setCancelPending(undefined);\n busy.stop();\n }\n\n if (app.isReady()) {\n this.applyRuntimeEvents(app, this.runtime.checkKnowledgeBase());\n }\n\n tui.requestRender();\n }\n\n private async submitChatMessage(app: ChatLayout, tui: TUI, message: string): Promise<void> {\n const busy = new BusyIndicator(app, tui, {\n status: \"thinking\",\n promptHint: \"press Esc to stop\",\n activities: [\"Thinking...\", \"Calling model...\", \"Writing response...\"],\n });\n const abortController = new AbortController();\n let cancelled = false;\n\n app.setCancelPending(() => {\n cancelled = true;\n abortController.abort();\n });\n busy.start();\n tui.requestRender();\n\n try {\n this.applyRuntimeEvents(\n app,\n await this.runtime.submitMessage(app.getConversationTurns(), message, abortController.signal)\n );\n } catch (error) {\n if (cancelled) {\n app.addMessage(systemMessage(\"Response stopped.\"));\n app.setStatus(\"ready\");\n } else {\n const errorMessage = error instanceof Error ? error.message : String(error);\n app.addMessage(systemMessage(`Chat failed: ${errorMessage}`));\n app.setStatus(\"chat failed\");\n }\n } finally {\n app.setCancelPending(undefined);\n busy.stop();\n tui.requestRender();\n }\n }\n\n private async submitSlashCommand(app: ChatLayout, tui: TUI, command: string): Promise<void> {\n const busy = new BusyIndicator(app, tui, {\n status: \"running command\",\n promptHint: \"working...\",\n activities: getSlashCommandActivities(command),\n activityEveryMs: 5000,\n });\n\n busy.start();\n tui.requestRender();\n\n try {\n this.applyRuntimeEvents(\n app,\n await this.runtime.submitSlashCommand(command, (event) => {\n busy.setActivity(event.message);\n })\n );\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n app.addMessage(systemMessage(`Command failed: ${errorMessage}`));\n app.setStatus(\"command failed\");\n } finally {\n busy.stop();\n tui.requestRender();\n }\n }\n\n private applyRuntimeEvents(app: ChatLayout, events: AgentRuntimeEvent[]): void {\n for (const event of events) {\n if (event.type === \"status\") {\n app.setStatus(event.status);\n }\n\n for (const message of renderRuntimeEvent(event)) {\n app.addMessage(message);\n }\n }\n }\n}\n\nfunction getSlashCommandActivities(command: string): string[] {\n if (command.startsWith(\"/kb compile\")) {\n return [\n \"Checking project knowledge folders...\",\n \"Reading .gitignore files...\",\n \"Listing project files...\",\n \"Queueing L1 work...\",\n ];\n }\n\n if (command.startsWith(\"/kb reset\")) {\n return [\"Checking project knowledge paths...\", \"Removing knowledge folder...\", \"Removing local cache folder...\"];\n }\n\n return [\"Running command...\", \"Preparing project knowledge folders...\", \"Writing project knowledge folders...\"];\n}\n\nexport interface ExitConfirmationOptions {\n setNoticeLine(line: string | undefined): void;\n requestRender(): void;\n exit(): void;\n timeoutMs?: number;\n}\n\nexport function createExitConfirmationInputListener(options: ExitConfirmationOptions) {\n const timeoutMs = options.timeoutMs ?? 2500;\n let exitPending = false;\n let exitPendingUntil = 0;\n let clearTimer: ReturnType<typeof setTimeout> | undefined;\n\n const clearExitNotice = () => {\n clearTimer = undefined;\n exitPending = false;\n exitPendingUntil = 0;\n options.setNoticeLine(undefined);\n options.requestRender();\n };\n\n return (data: string) => {\n if ((isKeyRelease(data) || isKeyRepeat(data)) && matchesKey(data, \"ctrl+c\")) {\n return { consume: true };\n }\n\n if (!matchesKey(data, \"ctrl+c\")) {\n return undefined;\n }\n\n if (exitPending && Date.now() <= exitPendingUntil) {\n if (clearTimer) {\n clearTimeout(clearTimer);\n clearTimer = undefined;\n }\n\n options.exit();\n return { consume: true };\n }\n\n exitPending = true;\n exitPendingUntil = Date.now() + timeoutMs;\n options.setNoticeLine(\"press Ctrl-C again to exit.\");\n options.requestRender();\n\n if (clearTimer) {\n clearTimeout(clearTimer);\n }\n\n clearTimer = setTimeout(clearExitNotice, timeoutMs);\n clearTimer.unref?.();\n\n return { consume: true };\n };\n}\n","#!/usr/bin/env node\nimport { cwd } from \"node:process\";\nimport { isAbsolute, resolve } from \"node:path\";\nimport { Command } from \"commander\";\nimport { createAppContext } from \"./app/context.js\";\nimport { ui } from \"./cli/ui.js\";\nimport {\n compileKnowledgeBase,\n formatKnowledgeCompileResult,\n isPartialKnowledgeCompileResult,\n} from \"./knowledge/compiler/index.js\";\nimport { formatKnowledgeInitResult, initializeKnowledgeBase } from \"./knowledge/init.js\";\nimport { formatKnowledgeResetResult, resetKnowledgeBase } from \"./knowledge/reset.js\";\nimport { getKnowledgeStatus } from \"./knowledge/status.js\";\nimport { TopchesterTuiShell } from \"./tui/index.js\";\n\nconst program = new Command();\n\nprogram.name(\"topchester\").description(\"KB-first terminal coding agent\").version(\"0.0.0\");\n\nprogram\n .option(\"-c, --config <path>\", \"explicit config file path\")\n .option(\"--workspace <path>\", \"workspace root\", cwd())\n .option(\"--dev <flag>\", \"enable a development flag\", collectDevFlag, []);\n\nprogram.action(async () => {\n const context = createContextFromOptions();\n\n await new TopchesterTuiShell(context).render();\n});\n\nprogram\n .command(\"dev\")\n .description(\"start local development mode\")\n .action(() => {\n const context = createContextFromOptions();\n\n console.log(\"Topchester local dev mode\");\n printStartupSummary(context);\n });\n\nconst kbCommand = program.command(\"kb\").description(\"knowledge base commands\");\n\nkbCommand\n .command(\"init\")\n .description(\"initialize a project knowledge base\")\n .action(async () => {\n const context = createContextFromOptions();\n const result = await ui.progress(\"Preparing project knowledge folders...\", (report) =>\n initializeKnowledgeBase(context.workspaceRoot, { onProgress: (event) => report(event.message) })\n );\n\n console.log(formatKnowledgeInitResult(result).join(\"\\n\"));\n });\n\nkbCommand\n .command(\"compile\")\n .description(\"compile the project knowledge base\")\n .action(async () => {\n const context = createContextFromOptions();\n const result = await ui.progress(\"Processing L1 file entries...\", (report) =>\n compileKnowledgeBase(context.workspaceRoot, {\n model: context.modelGateway,\n requireModel: true,\n onProgress: (event) => report(event.message),\n })\n );\n\n console.log(formatKnowledgeCompileResult(result).join(\"\\n\"));\n if (isPartialKnowledgeCompileResult(result)) {\n process.exitCode = 2;\n }\n });\n\nkbCommand\n .command(\"reset\")\n .description(\"delete the local project knowledge base and cache\")\n .action(async () => {\n const context = createContextFromOptions();\n const result = await ui.progress(\"Resetting project knowledge base...\", (report) =>\n resetKnowledgeBase(context.workspaceRoot, { onProgress: (event) => report(event.message) })\n );\n\n console.log(formatKnowledgeResetResult(result).join(\"\\n\"));\n });\n\nkbCommand\n .command(\"status\")\n .description(\"show project knowledge base status\")\n .action(async () => {\n const context = createContextFromOptions();\n const status = await ui.spinner(\"Checking knowledge base...\", () => getKnowledgeStatus(context.workspaceRoot));\n\n console.log(ui.heading(\"KB status\"));\n console.log(`${ui.label(\"workspace\")}: ${status.workspaceRoot}`);\n console.log(\n `${ui.label(\"knowledge folder\")}: ${formatPathStatus(status.kbPath, status.kbExists, status.kbIsDirectory)} ${ui.label(`(${status.kbPathSource})`)}`\n );\n console.log(\n `${ui.label(\"local cache folder\")}: ${formatPathStatus(status.cachePath, status.cacheExists, status.cacheIsDirectory)} ${ui.label(`(${status.cachePathSource})`)}`\n );\n\n if (!status.kbExists) {\n console.log(`${ui.label(\"state\")}: ${ui.warn(\"no knowledge base found yet\")}`);\n } else if (!status.kbIsDirectory) {\n console.log(`${ui.label(\"state\")}: ${ui.error(\"knowledge base path is not a folder\")}`);\n } else {\n console.log(`${ui.label(\"state\")}: ${ui.ok(\"knowledge base found\")}`);\n }\n });\n\nawait program.parseAsync();\n\nfunction printStartupSummary(context: ReturnType<typeof createAppContext>) {\n const assignments = context.config.models?.assignments ?? {};\n const providers = context.config.models?.providers ?? {};\n\n console.log(`workspace: ${context.workspaceRoot}`);\n console.log(`default model purpose: ${context.config.models?.defaultPurpose ?? \"agent.primary\"}`);\n if (context.devFlags.size > 0) {\n console.log(`dev flags: ${[...context.devFlags].join(\", \")}`);\n }\n if (context.logFilePath) {\n console.log(`log file: ${context.logFilePath}`);\n }\n\n if (Object.keys(assignments).length === 0) {\n console.log(\"model assignments: none configured\");\n } else {\n console.log(\"model assignments:\");\n for (const [purpose, model] of Object.entries(assignments)) {\n const provider = model.provider ? ` [${model.provider}]` : \"\";\n console.log(` ${purpose}: ${model.name}${provider}`);\n }\n }\n\n const namedProviders = Object.entries(providers).filter(([providerId]) => providerId !== \"default\");\n\n if (namedProviders.length === 0) {\n console.log(\"providers: none configured\");\n } else {\n console.log(\"providers:\");\n if (typeof providers.default === \"string\") {\n console.log(` default: ${providers.default}`);\n }\n for (const [providerId, provider] of namedProviders) {\n if (typeof provider === \"string\") {\n continue;\n }\n const auth = provider.apiKeyEnv ? `env:${provider.apiKeyEnv}` : provider.apiKey ? \"inline\" : \"none\";\n console.log(` ${providerId}: ${provider.type} ${provider.baseURL} auth=${auth}`);\n }\n }\n}\n\nfunction createContextFromOptions() {\n const options = program.opts<{ config?: string; workspace: string; dev: string[] }>();\n\n return createAppContext({\n workspaceRoot: options.workspace,\n configPath: options.config && (isAbsolute(options.config) ? options.config : resolve(cwd(), options.config)),\n devFlags: options.dev,\n });\n}\n\nfunction collectDevFlag(flag: string, flags: string[]): string[] {\n return [...flags, flag];\n}\n\nfunction formatPathStatus(path: string, exists: boolean, isDirectory: boolean): string {\n if (!exists) {\n return `${path} ${ui.warn(\"[missing]\")}`;\n }\n\n if (!isDirectory) {\n return `${path} ${ui.error(\"[not a folder]\")}`;\n }\n\n return `${path} ${ui.ok(\"[ok]\")}`;\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "topchester-ai",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Terminal-native TUI coding agent tightly coupled to a project knowledge base.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"topchester": "dist/cli.mjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"type": "module",
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsdown src/cli.ts --format esm --dts --out-dir dist --clean --sourcemap",
|
|
16
|
+
"dev": "tsx src/cli.ts dev --config config/example.yaml",
|
|
17
|
+
"format": "oxfmt .",
|
|
18
|
+
"format-check": "oxfmt . --check",
|
|
19
|
+
"hooks:install": "lefthook install",
|
|
20
|
+
"format:check": "pnpm format-check",
|
|
21
|
+
"lint": "oxlint",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"check": "pnpm typecheck && pnpm format-check && pnpm lint && pnpm test",
|
|
25
|
+
"prepublishOnly": "pnpm build"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@ai-sdk/openai-compatible": "^2.0.47",
|
|
29
|
+
"@earendil-works/pi-tui": "^0.74.0",
|
|
30
|
+
"ai": "^6.0.177",
|
|
31
|
+
"commander": "^14.0.3",
|
|
32
|
+
"pino": "^10.3.1",
|
|
33
|
+
"yaml": "^2.8.4",
|
|
34
|
+
"zod": "^4.4.3"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^24.12.3",
|
|
38
|
+
"lefthook": "^2.1.6",
|
|
39
|
+
"oxfmt": "^0.48.0",
|
|
40
|
+
"oxlint": "^1.63.0",
|
|
41
|
+
"tsdown": "^0.22.0",
|
|
42
|
+
"tsx": "^4.21.0",
|
|
43
|
+
"typescript": "^6.0.3",
|
|
44
|
+
"vitest": "^4.1.5"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=24",
|
|
48
|
+
"pnpm": ">=11"
|
|
49
|
+
},
|
|
50
|
+
"packageManager": "pnpm@11.0.8"
|
|
51
|
+
}
|