@riconext/hermes-repo 1.2.1 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/config/debugLog.ts","../src/init/paths.ts","../src/config/readConfig.ts","../src/config/findRepoRoot.ts","../src/capture/runLlmJob.ts","../src/config/llmConfig.ts","../src/capture/claude-code/parseJsonl.ts","../src/capture/enqueueLlmJob.ts","../src/llm/buildSessionDigest.ts","../src/llm/renderCaptureFromJson.ts","../src/llm/chatCompletions.ts","../src/capture/formatCapture.ts","../src/capture/writeCapture.ts","../src/hookExit.ts","../src/commands/captureLlm.ts","../src/capture/hookInput.ts","../src/capture/signalStrength.ts","../src/capture/needsLlm.ts","../src/consolidate/scheduleConsolidate.ts","../src/consolidate/state.ts","../src/consolidate/sessionScanner.ts","../src/consolidate/llmConsolidateV2.ts","../src/consolidate/writeKnowledge.ts","../src/consolidate/archive.ts","../src/consolidate/runConsolidate.ts","../src/consolidate/constants.ts","../src/capture/commitCapture.ts","../src/capture/claude-code/resolveSession.ts","../src/capture/claude-code/run.ts","../src/capture/codebuddy/resolveSession.ts","../src/capture/codebuddy/run.ts","../src/capture/cursor/resolveSession.ts","../src/capture/cursor/run.ts","../src/capture/router.ts","../src/capture/runCapture.ts","../src/commands/capture.ts","../src/commands/flush.ts","../src/inject/runInject.ts","../src/inject/constants.ts","../src/commands/inject.ts","../src/init/runInit.ts","../src/init/assistants/claude-code.ts","../src/init/mergeClaudeSettings.ts","../src/init/templateDir.ts","../src/index.ts","../src/init/assistants/codex.ts","../src/init/mergeCodexConfig.ts","../src/init/assistants/codebuddy.ts","../src/init/mergeCodebuddySettings.ts","../src/init/assistants/cursor.ts","../src/init/mergeCursorHooks.ts","../src/init/assistants/registry.ts","../src/init/ensureDirs.ts","../src/init/mergeAssistants.ts","../src/init/mergeGitignore.ts","../src/init/writeScaffoldFile.ts","../src/init/mergeConfig.ts","../src/init/mergeAgentsMd.ts","../src/init/scaffoldWrite.ts","../src/init/prompts.ts","../src/commands/init.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { runCaptureLlmCommand } from \"./commands/captureLlm.js\";\nimport { runCaptureCommand } from \"./commands/capture.js\";\nimport { runFlushCommandCli } from \"./commands/flush.js\";\nimport { runInjectCommand } from \"./commands/inject.js\";\nimport { runInitCommand } from \"./commands/init.js\";\nimport { readPkgVersion } from \"./index.js\";\n\nconst MIN_NODE_MAJOR = 20;\n\nfunction assertNodeVersion(): void {\n const major = Number.parseInt(process.versions.node.split(\".\")[0] ?? \"0\", 10);\n if (major < MIN_NODE_MAJOR) {\n console.error(\n `hermes-repo requires Node.js >= ${MIN_NODE_MAJOR}. Current: ${process.version}`,\n );\n process.exit(1);\n }\n}\n\nfunction main(): void {\n assertNodeVersion();\n\n const program = new Command();\n\n program\n .name(\"hermes-repo\")\n .description(\n \"跨编程助手的项目级记忆系统:在 Git 仓库中沉淀约定、踩坑与可复用流程\",\n )\n .version(readPkgVersion(), \"-V, --version\", \"显示版本号\");\n\n program\n .command(\"init\")\n .description(\"在当前 Git 仓库初始化 .memory/ 记忆脚手架\")\n .option(\"-y, --yes\", \"非交互模式,使用默认选项\")\n .option(\"-f, --force\", \"覆盖已存在的脚手架文件(不删除 captures 等内容)\")\n .option(\"-C, --cwd <dir>\", \"目标目录,默认 process.cwd()\")\n .option(\n \"--tools <ids>\",\n \"逗号分隔的助手 id,如 claude-code(须与 -y 合用)\",\n )\n .action(\n (options: {\n yes?: boolean;\n force?: boolean;\n cwd?: string;\n tools?: string;\n }) => {\n void runInitCommand({\n yes: options.yes,\n force: options.force,\n cwd: options.cwd,\n tools: options.tools,\n });\n },\n );\n\n program\n .command(\"capture\")\n .description(\"Stop hook:捕获当前会话到 .memory/captures/raw/\")\n .option(\"-C, --cwd <dir>\", \"目标仓库根目录\")\n .option(\"--dry-run\", \"仅预览,不写入文件\")\n .option(\"--strict\", \"失败时 exit 1(hook 默认 exit 0)\")\n .action((options: { cwd?: string; dryRun?: boolean; strict?: boolean }) => {\n runCaptureCommand({\n cwd: options.cwd,\n dryRun: options.dryRun,\n strict: options.strict,\n });\n });\n\n program\n .command(\"capture-llm\")\n .description(\"异步 LLM 升级 capture(由 capture hook 入队,亦可 --flush)\")\n .option(\"-C, --cwd <dir>\", \"目标仓库根目录\")\n .option(\"--job <id>\", \"处理指定 pending job\")\n .option(\"--flush\", \"处理所有 pending job\")\n .option(\"--strict\", \"失败时 exit 1\")\n .action(\n (options: {\n cwd?: string;\n job?: string;\n flush?: boolean;\n strict?: boolean;\n }) => {\n runCaptureLlmCommand({\n cwd: options.cwd,\n job: options.job,\n flush: options.flush,\n strict: options.strict,\n });\n },\n );\n\n program\n .command(\"flush\")\n .description(\n \"手动触发 consolidate:LLM 提炼 captures → 知识库 + MEMORY.md\",\n )\n .option(\"-C, --cwd <dir>\", \"目标仓库根目录\")\n .option(\"--force\", \"重处理全部 session 文件\")\n .option(\"--dry-run\", \"仅预览,不写入\")\n .option(\"--strict\", \"失败时 exit 1\")\n .action(\n (options: {\n cwd?: string;\n force?: boolean;\n dryRun?: boolean;\n strict?: boolean;\n }) => {\n void runFlushCommandCli({\n cwd: options.cwd,\n force: options.force,\n dryRun: options.dryRun,\n strict: options.strict,\n });\n },\n );\n\n program\n .command(\"inject\")\n .description(\"SessionStart hook:将 MEMORY.md 导航 + rules 注入到 stdout\")\n .option(\"-C, --cwd <dir>\", \"目标仓库根目录\")\n .option(\"--strict\", \"失败时 exit 1(hook 默认 exit 0)\")\n .action((options: { cwd?: string; strict?: boolean }) => {\n runInjectCommand({\n cwd: options.cwd,\n strict: options.strict,\n });\n });\n\n if (process.argv.length <= 2) {\n program.outputHelp();\n process.exit(0);\n }\n\n program.parse(process.argv);\n}\n\nmain();\n","import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { RepoContext } from \"./types.js\";\nimport { memoryPath } from \"../init/paths.js\";\n\nexport const DEBUG_LOG_FILE = \"hermes-debug.log\";\n\nlet logFilePath: string | null = null;\n\nexport function configureDebugLogging(\n repoRoot: string | null,\n enabled: boolean,\n): void {\n if (!enabled || !repoRoot) {\n logFilePath = null;\n return;\n }\n logFilePath = memoryPath(repoRoot, DEBUG_LOG_FILE);\n}\n\nfunction formatLine(phase: string, message: string): string {\n return `${new Date().toISOString()} hermes-repo [${phase}] ${message}`;\n}\n\nfunction writeToLogFile(line: string): void {\n if (!logFilePath) {\n return;\n }\n mkdirSync(dirname(logFilePath), { recursive: true });\n appendFileSync(logFilePath, `${line}\\n`, \"utf8\");\n}\n\nexport function debugLog(\n enabled: boolean,\n phase: string,\n message: string,\n): void {\n if (!enabled) {\n return;\n }\n const line = formatLine(phase, message);\n console.error(line);\n writeToLogFile(line);\n}\n\nexport function debugFromContext(\n ctx: RepoContext | null | undefined,\n phase: string,\n message: string,\n): void {\n debugLog(ctx?.config.debug === true, phase, message);\n}\n","import { join } from \"node:path\";\n\nexport const MEMORY_DIR = \".memory\";\n\n/** v2 目录结构 */\nexport const MEMORY_SUBDIRS = [\n \"rules\",\n \"domains/general\",\n \"workflows\",\n \"decisions\",\n \"incidents\",\n \"captures/raw\",\n \"captures/archived\",\n] as const;\n\n/** 需要创建 .gitkeep 的目录(确保空目录能被 git 追踪) */\nexport const GITKEEP_DIRS = [\n \"rules\",\n \"domains/general\",\n \"workflows\",\n \"decisions\",\n \"incidents\",\n] as const;\n\n/** init 时复制的示例模板文件 */\nexport const EXAMPLE_TEMPLATE_FILES = [\n \"capture-session.example.md\",\n] as const;\n\n/** init 时生成的脚手架文件路径列表 */\nexport const SCAFFOLD_RELATIVE_PATHS = [\n \".memory/config.json\",\n \".memory/MEMORY.md\",\n \".memory/consolidate-state.json\",\n \"AGENTS.md\",\n \".claude/settings.local.json\",\n] as const;\n\nexport function memoryPath(root: string, ...segments: string[]): string {\n return join(root, MEMORY_DIR, ...segments);\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AssistantId } from \"../init/assistants/types.js\";\nimport { findRepoRoot } from \"./findRepoRoot.js\";\nimport type {\n ConsolidateConfig,\n HermesConfig,\n LlmConfigV2,\n RepoContext,\n} from \"./types.js\";\n\nfunction isAssistantId(value: unknown): value is AssistantId {\n return typeof value === \"string\";\n}\n\nfunction parseLlmConfig(raw: Record<string, unknown>): LlmConfigV2 {\n const llm = raw.llm as Record<string, unknown> | undefined;\n return {\n enabled: typeof llm?.enabled === \"boolean\" ? llm.enabled : false,\n provider: typeof llm?.provider === \"string\" ? llm.provider : \"openai\",\n baseUrl: typeof llm?.baseUrl === \"string\" ? llm.baseUrl : \"https://api.openai.com/v1\",\n model: typeof llm?.model === \"string\" ? llm.model : \"gpt-4o\",\n apiKey: typeof llm?.apiKey === \"string\" ? llm.apiKey : \"\",\n timeoutMs:\n typeof llm?.timeoutMs === \"number\" && llm.timeoutMs > 0\n ? llm.timeoutMs\n : 60_000,\n maxInputChars:\n typeof llm?.maxInputChars === \"number\" && llm.maxInputChars > 0\n ? llm.maxInputChars\n : 24_000,\n mode: llm?.mode === \"sync\" ? \"sync\" : \"async\",\n };\n}\n\nfunction parseConsolidateConfig(raw: Record<string, unknown>): ConsolidateConfig {\n const c = raw.consolidate as Record<string, unknown> | undefined;\n const autoFlush =\n c?.autoFlush && typeof c.autoFlush === \"object\" && !Array.isArray(c.autoFlush)\n ? (c.autoFlush as Record<string, unknown>)\n : {};\n return {\n autoArchiveDays: typeof c?.autoArchiveDays === \"number\" ? c.autoArchiveDays : 30,\n autoFlush: {\n enabled: autoFlush.enabled === true,\n minPendingSessions:\n typeof autoFlush.minPendingSessions === \"number\" &&\n autoFlush.minPendingSessions > 0\n ? autoFlush.minPendingSessions\n : 3,\n minIntervalMinutes:\n typeof autoFlush.minIntervalMinutes === \"number\" &&\n autoFlush.minIntervalMinutes > 0\n ? autoFlush.minIntervalMinutes\n : 30,\n maxPendingChars:\n typeof autoFlush.maxPendingChars === \"number\" &&\n autoFlush.maxPendingChars > 0\n ? autoFlush.maxPendingChars\n : 20_000,\n },\n };\n}\n\nexport function readConfigAtRepo(repoRoot: string): HermesConfig | null {\n const configPath = join(repoRoot, \".memory\", \"config.json\");\n try {\n const raw = JSON.parse(readFileSync(configPath, \"utf8\")) as Record<string, unknown>;\n const version = raw.version;\n\n // v2 配置\n if (version === 2) {\n const assistants = Array.isArray(raw.assistants)\n ? raw.assistants.filter(isAssistantId)\n : [];\n return {\n version: 2,\n storage: { backend: (raw.storage as Record<string, unknown>)?.backend === \"file\" ? \"file\" : \"file\" },\n assistants,\n debug: raw.debug === true,\n llm: parseLlmConfig(raw),\n consolidate: parseConsolidateConfig(raw),\n };\n }\n\n // v1 兼容(自动升级字段)\n if (version === 1 || version === undefined) {\n const assistants = Array.isArray(raw.assistants)\n ? raw.assistants.filter(isAssistantId)\n : [];\n return {\n version: 2, // 自动升级为 v2\n storage: { backend: \"file\" },\n assistants,\n debug: raw.debug === true,\n llm: {\n enabled: false,\n provider: \"openai\",\n baseUrl: \"https://api.openai.com/v1\",\n model: \"gpt-4o\",\n apiKey: \"\",\n timeoutMs: 60_000,\n maxInputChars: 24_000,\n mode: \"async\",\n },\n consolidate: {\n autoArchiveDays: 30,\n autoFlush: {\n enabled: false,\n minPendingSessions: 3,\n minIntervalMinutes: 30,\n maxPendingChars: 20_000,\n },\n },\n };\n }\n\n return null; // 不支持的版本\n } catch {\n return null;\n }\n}\n\nexport function loadRepoContext(cwd?: string): RepoContext | null {\n const repoRoot = findRepoRoot(cwd);\n if (!repoRoot) {\n return null;\n }\n const config = readConfigAtRepo(repoRoot);\n if (!config) {\n return null;\n }\n return { repoRoot, config };\n}\n","import { existsSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nconst CONFIG_REL = join(\".memory\", \"config.json\");\n\nexport function findRepoRoot(startDir?: string): string | null {\n let dir = resolve(startDir ?? process.cwd());\n\n while (true) {\n if (existsSync(join(dir, CONFIG_REL))) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return null;\n }\n dir = parent;\n }\n}\n","import { existsSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { debugLog } from \"../config/debugLog.js\";\nimport { isLlmAvailable } from \"../config/llmConfig.js\";\nimport { readConfigAtRepo } from \"../config/readConfig.js\";\nimport { parseJsonlFile } from \"./claude-code/parseJsonl.js\";\nimport {\n deleteLlmJob,\n listPendingJobs,\n readLlmJob,\n type LlmJobPayload,\n} from \"./enqueueLlmJob.js\";\nimport { llmFormat } from \"./formatCapture.js\";\nimport { renderCaptureMarkdown } from \"./writeCapture.js\";\n\nfunction captureAlreadyUpgraded(repoRoot: string, captureFile: string): boolean {\n const path = join(repoRoot, captureFile);\n if (!existsSync(path)) {\n return false;\n }\n const text = readFileSync(path, \"utf8\");\n return /llmUpgradedAt:/.test(text);\n}\n\nexport async function runLlmJob(\n repoRoot: string,\n job: LlmJobPayload,\n debug?: boolean,\n): Promise<{ ok: boolean; reason?: string }> {\n if (captureAlreadyUpgraded(repoRoot, job.captureFile)) {\n deleteLlmJob(repoRoot, job.jobId);\n return { ok: true, reason: \"already-upgraded\" };\n }\n\n const llm = readConfigAtRepo(repoRoot)?.llm ?? null;\n if (!isLlmAvailable(llm)) {\n return { ok: false, reason: \"llm not available\" };\n }\n\n if (!existsSync(job.jsonlPath)) {\n return { ok: false, reason: \"jsonl missing\" };\n }\n\n const session = parseJsonlFile(job.jsonlPath);\n const upgraded = await llmFormat(session, job.assistant, llm!);\n if (!upgraded) {\n debugLog(debug === true, \"capture-llm\", `llm job failed: ${job.jobId}`);\n return { ok: false, reason: \"llm format failed\" };\n }\n\n const target = join(repoRoot, job.captureFile);\n const temp = `${target}.hermes-tmp`;\n const date = new Date().toISOString().slice(0, 10);\n writeFileSync(temp, renderCaptureMarkdown(upgraded, date), \"utf8\");\n renameSync(temp, target);\n\n deleteLlmJob(repoRoot, job.jobId);\n debugLog(debug === true, \"capture-llm\", `ok: upgraded ${job.captureFile}`);\n return { ok: true };\n}\n\nexport async function runLlmJobById(\n repoRoot: string,\n jobId: string,\n debug?: boolean,\n): Promise<{ ok: boolean; reason?: string }> {\n const job = readLlmJob(repoRoot, jobId);\n if (!job) {\n return { ok: false, reason: \"job not found\" };\n }\n return runLlmJob(repoRoot, job, debug);\n}\n\nexport async function flushPendingLlmJobs(\n repoRoot: string,\n debug?: boolean,\n): Promise<number> {\n const jobs = listPendingJobs(repoRoot);\n let done = 0;\n for (const job of jobs) {\n const result = await runLlmJob(repoRoot, job, debug);\n if (result.ok) {\n done += 1;\n }\n }\n return done;\n}\n","import type { LlmConfigV2 } from \"./types.js\";\n\nexport type LlmCaptureMode = \"async\" | \"sync\";\nexport type LlmConfig = LlmConfigV2;\n\nexport const DEFAULT_LLM_TIMEOUT_MS = 60_000;\nexport const DEFAULT_LLM_MAX_INPUT_CHARS = 24_000;\nexport const DEFAULT_LLM_BASE_URL = \"https://api.deepseek.com\";\nexport const DEFAULT_LLM_MODEL = \"deepseek-v4-flash\";\n\nexport function defaultDisabledLlmConfig(): LlmConfig {\n return {\n enabled: false,\n provider: \"openai\",\n baseUrl: DEFAULT_LLM_BASE_URL,\n model: DEFAULT_LLM_MODEL,\n apiKey: \"\",\n timeoutMs: DEFAULT_LLM_TIMEOUT_MS,\n maxInputChars: DEFAULT_LLM_MAX_INPUT_CHARS,\n mode: \"async\",\n };\n}\n\nexport function isLlmAvailable(cfg: LlmConfig | null): boolean {\n if (!cfg?.enabled) {\n return false;\n }\n return (\n Boolean(cfg.apiKey?.trim()) &&\n Boolean(cfg.baseUrl?.trim()) &&\n Boolean(cfg.model?.trim())\n );\n}\n\nexport function effectiveLlmMode(cfg: LlmConfig): LlmCaptureMode {\n return cfg.mode === \"sync\" ? \"sync\" : \"async\";\n}\n\nexport function parseLlmConfigRaw(raw: Record<string, unknown>): LlmConfig | null {\n if (raw.enabled !== true && raw.enabled !== false) {\n return null;\n }\n const baseUrl = typeof raw.baseUrl === \"string\" ? raw.baseUrl : \"\";\n const model = typeof raw.model === \"string\" ? raw.model : \"\";\n const apiKey = typeof raw.apiKey === \"string\" ? raw.apiKey : \"\";\n const timeoutMs =\n typeof raw.timeoutMs === \"number\" && raw.timeoutMs > 0\n ? raw.timeoutMs\n : DEFAULT_LLM_TIMEOUT_MS;\n const maxInputChars =\n typeof raw.maxInputChars === \"number\" && raw.maxInputChars > 0\n ? raw.maxInputChars\n : DEFAULT_LLM_MAX_INPUT_CHARS;\n const mode = raw.mode === \"sync\" ? \"sync\" : \"async\";\n const provider =\n typeof raw.provider === \"string\" ? raw.provider : \"openai\";\n\n return {\n enabled: raw.enabled,\n provider,\n baseUrl,\n model,\n apiKey,\n timeoutMs,\n maxInputChars,\n mode,\n };\n}\n","import { readFileSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport type { ParsedSession, SessionMessage } from \"../types.js\";\n\nconst FILE_CHANGE_TOOLS =\n /^(Write|Edit|MultiEdit|NotebookEdit|write|edit)$/i;\n\n/** CodeBuddy:跳过元数据行,避免干扰统计 */\nconst SKIP_LINE_TYPES = new Set([\n \"file-history-snapshot\",\n \"summary\",\n \"function_call_result\",\n]);\n\nfunction textFromContentParts(content: unknown): string {\n if (!Array.isArray(content)) {\n return \"\";\n }\n return content\n .map((part) => {\n if (!part || typeof part !== \"object\") {\n return \"\";\n }\n const p = part as Record<string, unknown>;\n if (typeof p.text === \"string\") {\n return p.text;\n }\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction extractText(record: Record<string, unknown>): string {\n if (typeof record.content === \"string\") {\n return record.content;\n }\n if (Array.isArray(record.content)) {\n const top = textFromContentParts(record.content);\n if (top) {\n return top;\n }\n }\n const message = record.message;\n if (message && typeof message === \"object\") {\n const msg = message as Record<string, unknown>;\n if (typeof msg.content === \"string\") {\n return msg.content;\n }\n if (Array.isArray(msg.content)) {\n return textFromContentParts(msg.content);\n }\n }\n return \"\";\n}\n\nfunction inferRole(record: Record<string, unknown>): string {\n if (typeof record.role === \"string\") {\n return record.role;\n }\n if (typeof record.type === \"string\") {\n const t = record.type.toLowerCase();\n if (t === \"user\" || t === \"human\") return \"user\";\n if (t === \"assistant\") return \"assistant\";\n }\n return \"unknown\";\n}\n\nfunction isSkippedLine(record: Record<string, unknown>): boolean {\n const t = String(record.type ?? \"\").toLowerCase();\n return SKIP_LINE_TYPES.has(t);\n}\n\nfunction isToolUse(record: Record<string, unknown>): boolean {\n const t = String(record.type ?? \"\").toLowerCase();\n return t === \"tool_use\" || t === \"tool\" || t === \"function_call\";\n}\n\nfunction toolName(record: Record<string, unknown>): string {\n if (typeof record.name === \"string\") return record.name;\n const tool = record.tool;\n if (tool && typeof tool === \"object\" && \"name\" in tool) {\n return String((tool as { name: string }).name);\n }\n return \"\";\n}\n\n/** Cursor 等助手:tool_use 嵌在 message.content 数组内 */\nfunction countNestedTools(record: Record<string, unknown>): {\n toolCalls: number;\n fileChanges: number;\n} {\n let toolCalls = 0;\n let fileChanges = 0;\n const message = record.message;\n if (!message || typeof message !== \"object\") {\n return { toolCalls, fileChanges };\n }\n const content = (message as Record<string, unknown>).content;\n if (!Array.isArray(content)) {\n return { toolCalls, fileChanges };\n }\n for (const part of content) {\n if (!part || typeof part !== \"object\") {\n continue;\n }\n const p = part as Record<string, unknown>;\n const t = String(p.type ?? \"\").toLowerCase();\n if (t !== \"tool_use\" && t !== \"tool\") {\n continue;\n }\n toolCalls += 1;\n const name = typeof p.name === \"string\" ? p.name : \"\";\n if (FILE_CHANGE_TOOLS.test(name)) {\n fileChanges += 1;\n }\n }\n return { toolCalls, fileChanges };\n}\n\nexport function parseJsonlFile(jsonlPath: string): ParsedSession {\n const sessionId = basename(jsonlPath, \".jsonl\");\n const raw = readFileSync(jsonlPath, \"utf8\");\n const messages: SessionMessage[] = [];\n let fileChanges = 0;\n let toolCalls = 0;\n\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const record = JSON.parse(trimmed) as Record<string, unknown>;\n if (isSkippedLine(record)) {\n continue;\n }\n if (isToolUse(record)) {\n toolCalls += 1;\n const name = toolName(record);\n if (FILE_CHANGE_TOOLS.test(name)) {\n fileChanges += 1;\n }\n continue;\n }\n const nested = countNestedTools(record);\n toolCalls += nested.toolCalls;\n fileChanges += nested.fileChanges;\n const role = inferRole(record);\n const text = extractText(record);\n if (text) {\n messages.push({ role, text });\n }\n } catch {\n // skip malformed lines\n }\n }\n\n const text = messages.map((m) => m.text).join(\"\\n\");\n\n return {\n sessionId,\n messages,\n text,\n fileChanges,\n toolCalls,\n };\n}\n","import { spawn } from \"node:child_process\";\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { debugLog } from \"../config/debugLog.js\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { AssistantId } from \"../init/assistants/types.js\";\n\nexport interface LlmJobPayload {\n jobId: string;\n sessionId: string;\n jsonlPath: string;\n captureFile: string;\n assistant: AssistantId;\n enqueuedAt: string;\n}\n\nfunction pendingDir(repoRoot: string): string {\n return memoryPath(repoRoot, \"captures\", \"pending\");\n}\n\nfunction cliPath(): string {\n return join(dirname(fileURLToPath(import.meta.url)), \"..\", \"cli.js\");\n}\n\nfunction makeJobId(sessionId: string): string {\n const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, \"\").slice(0, 32);\n return `${Date.now()}-${safe || \"session\"}`;\n}\n\nfunction removeStaleJobsForSession(\n repoRoot: string,\n sessionId: string,\n): void {\n const dir = pendingDir(repoRoot);\n if (!existsSync(dir)) {\n return;\n }\n for (const name of readdirSync(dir)) {\n if (!name.endsWith(\".json\")) {\n continue;\n }\n try {\n const raw = JSON.parse(\n readFileSync(join(dir, name), \"utf8\"),\n ) as LlmJobPayload;\n if (raw.sessionId === sessionId) {\n rmSync(join(dir, name), { force: true });\n }\n } catch {\n // skip\n }\n }\n}\n\nexport function enqueueLlmJob(opts: {\n repoRoot: string;\n sessionId: string;\n jsonlPath: string;\n captureFile: string;\n assistant: AssistantId;\n debug?: boolean;\n}): boolean {\n const { repoRoot, sessionId, jsonlPath, captureFile, assistant, debug } =\n opts;\n const dir = pendingDir(repoRoot);\n mkdirSync(dir, { recursive: true });\n removeStaleJobsForSession(repoRoot, sessionId);\n\n const jobId = makeJobId(sessionId);\n const payload: LlmJobPayload = {\n jobId,\n sessionId,\n jsonlPath,\n captureFile,\n assistant,\n enqueuedAt: new Date().toISOString(),\n };\n writeFileSync(\n join(dir, `${jobId}.json`),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n\n const child = spawn(\n process.execPath,\n [cliPath(), \"capture-llm\", \"--job\", jobId, \"-C\", repoRoot],\n {\n detached: true,\n stdio: \"ignore\",\n cwd: repoRoot,\n },\n );\n child.unref();\n\n debugLog(debug === true, \"capture\", `llm job enqueued: ${jobId}`);\n return true;\n}\n\nexport function readLlmJob(\n repoRoot: string,\n jobId: string,\n): LlmJobPayload | null {\n const path = join(pendingDir(repoRoot), `${jobId}.json`);\n if (!existsSync(path)) {\n return null;\n }\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as LlmJobPayload;\n } catch {\n return null;\n }\n}\n\nexport function deleteLlmJob(repoRoot: string, jobId: string): void {\n const path = join(pendingDir(repoRoot), `${jobId}.json`);\n if (existsSync(path)) {\n rmSync(path, { force: true });\n }\n}\n\nexport function listPendingJobs(repoRoot: string): LlmJobPayload[] {\n const dir = pendingDir(repoRoot);\n if (!existsSync(dir)) {\n return [];\n }\n const jobs: LlmJobPayload[] = [];\n for (const name of readdirSync(dir)) {\n if (!name.endsWith(\".json\")) {\n continue;\n }\n try {\n jobs.push(\n JSON.parse(readFileSync(join(dir, name), \"utf8\")) as LlmJobPayload,\n );\n } catch {\n // skip\n }\n }\n return jobs;\n}\n","import type { ParsedSession } from \"../capture/types.js\";\n\nexport function buildSessionDigest(\n session: ParsedSession,\n maxChars: number,\n): string {\n const parts: string[] = [\n `sessionId: ${session.sessionId}`,\n `messages: ${session.messages.length}`,\n `toolCalls: ${session.toolCalls}`,\n `fileChanges: ${session.fileChanges}`,\n \"\",\n \"--- transcript (truncated) ---\",\n ];\n\n let used = parts.join(\"\\n\").length;\n const userFirst = [...session.messages].sort((a, b) => {\n if (a.role === \"user\" && b.role !== \"user\") return -1;\n if (b.role === \"user\" && a.role !== \"user\") return 1;\n return 0;\n });\n\n for (const m of userFirst) {\n const block = `[${m.role}]\\n${m.text.slice(0, 2000)}\\n`;\n if (used + block.length > maxChars) {\n parts.push(\"[... truncated ...]\");\n break;\n }\n parts.push(block);\n used += block.length;\n }\n\n return parts.join(\"\\n\");\n}\n","import type { CaptureMemoryType } from \"../capture/types.js\";\n\nexport interface LlmExtractResult {\n type: CaptureMemoryType;\n tags: string[];\n scope: string;\n title?: string;\n context: string;\n findings?: string;\n impact?: string;\n goal?: string;\n steps?: string[];\n cautions?: string[];\n verification?: string[];\n}\n\nconst VALID_TYPES = new Set<CaptureMemoryType>([\n \"semantic\",\n \"episodic\",\n \"procedural\",\n]);\n\nexport function parseLlmExtractJson(raw: unknown): LlmExtractResult | null {\n if (!raw || typeof raw !== \"object\") {\n return null;\n }\n const o = raw as Record<string, unknown>;\n const type = o.type;\n if (typeof type !== \"string\" || !VALID_TYPES.has(type as CaptureMemoryType)) {\n return null;\n }\n const context = typeof o.context === \"string\" ? o.context.trim() : \"\";\n if (!context) {\n return null;\n }\n const tags = Array.isArray(o.tags)\n ? o.tags.filter((t): t is string => typeof t === \"string\")\n : [];\n const scope =\n typeof o.scope === \"string\" && o.scope.trim()\n ? o.scope.trim()\n : \"all\";\n\n return {\n type: type as CaptureMemoryType,\n tags,\n scope,\n title: typeof o.title === \"string\" ? o.title : undefined,\n context,\n findings: typeof o.findings === \"string\" ? o.findings : undefined,\n impact: typeof o.impact === \"string\" ? o.impact : undefined,\n goal: typeof o.goal === \"string\" ? o.goal : undefined,\n steps: Array.isArray(o.steps)\n ? o.steps.filter((s): s is string => typeof s === \"string\")\n : undefined,\n cautions: Array.isArray(o.cautions)\n ? o.cautions.filter((s): s is string => typeof s === \"string\")\n : undefined,\n verification: Array.isArray(o.verification)\n ? o.verification.filter((s): s is string => typeof s === \"string\")\n : undefined,\n };\n}\n\nfunction listSection(title: string, items: string[] | undefined): string {\n if (!items?.length) {\n return \"\";\n }\n return `\\n\\n## ${title}\\n\\n${items.map((s, i) => `${i + 1}. ${s}`).join(\"\\n\")}`;\n}\n\nexport function renderBodyFromExtract(extract: LlmExtractResult): string {\n if (extract.type === \"procedural\") {\n const steps =\n extract.steps?.map((s, i) => `${i + 1}. ${s}`).join(\"\\n\") ??\n extract.findings ??\n \"(无步骤)\";\n const cautions =\n extract.cautions?.map((s) => `- ${s}`).join(\"\\n\") ?? \"(无)\";\n const verification =\n extract.verification?.map((s) => `- ${s}`).join(\"\\n\") ?? \"(无)\";\n return `## 目标\n\n${extract.goal ?? extract.context}\n\n## 步骤\n\n${steps}\n${extract.cautions?.length ? `\\n\\n## 注意\\n\\n${cautions}` : \"\"}\n${extract.verification?.length ? `\\n\\n## 验证\\n\\n${verification}` : \"\"}`;\n }\n\n return `## 上下文\n\n${extract.context}\n\n## 发现\n\n${extract.findings ?? extract.title ?? \"(见上下文)\"}\n\n## 影响\n\n${extract.impact ?? \"(待 consolidate 或人工补充)\"}`;\n}\n","import type { LlmConfig } from \"../config/llmConfig.js\";\nimport { buildSessionDigest } from \"./buildSessionDigest.js\";\nimport {\n parseLlmExtractJson,\n type LlmExtractResult,\n} from \"./renderCaptureFromJson.js\";\nimport type { ParsedSession } from \"../capture/types.js\";\n\nconst SYSTEM_PROMPT = `You extract project memory from an AI coding session transcript.\nRespond with a single JSON object only (no markdown fence), matching this shape:\n{\n \"type\": \"semantic\" | \"episodic\" | \"procedural\",\n \"tags\": [\"tag1\"],\n \"scope\": \"all\" | \"frontend\" | \"backend\",\n \"title\": \"short summary\",\n \"context\": \"what was being done\",\n \"findings\": \"facts/decisions/root cause (semantic/episodic)\",\n \"impact\": \"effect on future work\",\n \"goal\": \"for procedural only\",\n \"steps\": [\"step 1\"],\n \"cautions\": [\"pitfall\"],\n \"verification\": [\"how to verify\"]\n}\nUse procedural only for repeatable multi-step workflows. Use Chinese for content when the session is mainly Chinese.`;\n\nexport async function extractCaptureViaLlm(\n session: ParsedSession,\n llm: LlmConfig,\n): Promise<LlmExtractResult | null> {\n const digest = buildSessionDigest(session, llm.maxInputChars);\n const url = `${llm.baseUrl.replace(/\\/$/, \"\")}/chat/completions`;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), llm.timeoutMs);\n\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${llm.apiKey}`,\n },\n body: JSON.stringify({\n model: llm.model,\n response_format: { type: \"json_object\" },\n messages: [\n { role: \"system\", content: SYSTEM_PROMPT },\n {\n role: \"user\",\n content: `Extract memory from this session:\\n\\n${digest}`,\n },\n ],\n temperature: 0.2,\n }),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n return null;\n }\n\n const data = (await res.json()) as {\n choices?: Array<{ message?: { content?: string } }>;\n };\n const content = data.choices?.[0]?.message?.content;\n if (!content) {\n return null;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch {\n return null;\n }\n return parseLlmExtractJson(parsed);\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n}\n","import type { LlmConfig } from \"../config/llmConfig.js\";\nimport { extractCaptureViaLlm } from \"../llm/chatCompletions.js\";\nimport {\n renderBodyFromExtract,\n type LlmExtractResult,\n} from \"../llm/renderCaptureFromJson.js\";\nimport type { AssistantId } from \"../init/assistants/types.js\";\nimport type { CaptureMemoryType, ParsedSession } from \"./types.js\";\n\n/** 内联:推断 capture 类型(原 shouldCapture.ts,v2 保留用于 capture-llm 兼容) */\nfunction inferCaptureType(session: ParsedSession): \"semantic\" | \"episodic\" {\n const SEMANTIC_SIGNAL_RE =\n /约定|必须|架构|决策|规范|convention|pattern|always|never/i;\n if (SEMANTIC_SIGNAL_RE.test(session.text)) {\n return \"semantic\";\n }\n return \"episodic\";\n}\n\nexport interface FormattedCapture {\n type: CaptureMemoryType;\n sessionId: string;\n tags: string[];\n scope: string;\n bodyMarkdown: string;\n llmUpgradedAt?: string;\n}\n\nfunction assistantLabel(assistant: AssistantId): string {\n return assistant;\n}\n\nexport function simpleFormat(\n session: ParsedSession,\n assistant: AssistantId,\n): FormattedCapture {\n const type = inferCaptureType(session);\n const recent = session.messages.slice(-6);\n const context = recent\n .map((m) => `**${m.role}**: ${m.text.slice(0, 500)}`)\n .join(\"\\n\\n\");\n\n const bodyMarkdown = `## 上下文\n\n自动捕获自 ${assistantLabel(assistant)} 会话 \\`${session.sessionId}\\`。\n\n## 发现\n\n${context || \"(无提取内容)\"}\n\n## 影响\n\n(待 consolidate 或人工补充)`;\n\n return {\n type,\n sessionId: session.sessionId,\n tags: [\"auto-capture\", assistant],\n scope: \"all\",\n bodyMarkdown,\n };\n}\n\nexport function formattedFromLlmExtract(\n session: ParsedSession,\n assistant: AssistantId,\n extract: LlmExtractResult,\n): FormattedCapture {\n const tagSet = new Set([\"auto-capture\", assistant, ...extract.tags]);\n return {\n type: extract.type,\n sessionId: session.sessionId,\n tags: [...tagSet],\n scope: extract.scope,\n bodyMarkdown: renderBodyFromExtract(extract),\n llmUpgradedAt: new Date().toISOString(),\n };\n}\n\nexport async function llmFormat(\n session: ParsedSession,\n assistant: AssistantId,\n llm: LlmConfig,\n): Promise<FormattedCapture | null> {\n const extract = await extractCaptureViaLlm(session, llm);\n if (!extract) {\n return null;\n }\n return formattedFromLlmExtract(session, assistant, extract);\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { FormattedCapture } from \"./formatCapture.js\";\n\n// ─── Types ────────────────────────────────────────────\n\nexport type CaptureSource = \"session\" | \"commit\" | \"manual\";\n\nexport type SessionFileStatus = \"pending\" | \"done\" | \"stale\";\n\nexport interface SessionFileFrontmatter {\n sessionId: string;\n source: CaptureSource;\n status: SessionFileStatus;\n domain: string | null; // consolidate 后由 LLM 填写\n createdAt: string; // ISO 8601\n lastModifiedAt: string;\n consolidatedAt: string | null;\n captureCount: number;\n}\n\n// ─── Helpers ──────────────────────────────────────────\n\nfunction isoNow(): string {\n return new Date().toISOString();\n}\n\n/** 从已有文件中解析 frontmatter */\nfunction parseSessionFileFrontmatter(content: string): SessionFileFrontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const frontmatter: Record<string, unknown> = {};\n for (const line of match[1].split(\"\\n\")) {\n const idx = line.indexOf(\":\");\n if (idx === -1) continue;\n const key = line.slice(0, idx).trim();\n const val = line.slice(idx + 1).trim();\n\n // 解析布尔、null 和数字\n if (val === \"null\") frontmatter[key] = null;\n else if (val === \"true\") frontmatter[key] = true;\n else if (val === \"false\") frontmatter[key] = false;\n else if (/^\\d+$/.test(val)) frontmatter[key] = Number.parseInt(val, 10);\n else frontmatter[key] = val.replace(/^[\"']|[\"']$/g, \"\");\n }\n\n return frontmatter as unknown as SessionFileFrontmatter;\n}\n\n/** 序列化 frontmatter 为 YAML 块 */\nfunction serializeSessionFrontmatter(fm: SessionFileFrontmatter): string {\n const lines = [\n \"---\",\n `sessionId: ${fm.sessionId}`,\n `source: ${fm.source}`,\n `status: ${fm.status}`,\n `domain: ${fm.domain ?? null}`,\n `createdAt: ${fm.createdAt}`,\n `lastModifiedAt: ${fm.lastModifiedAt}`,\n `consolidatedAt: ${fm.consolidatedAt ?? null}`,\n `captureCount: ${fm.captureCount}`,\n \"---\",\n ];\n return lines.join(\"\\n\");\n}\n\n/** 格式化单个 capture 段落(追加到文件 body 中) */\nfunction renderCaptureSection(\n formatted: FormattedCapture,\n index: number,\n): string {\n const time = isoNow().slice(11, 19); // HH:mm:ss\n const tagsStr = formatted.tags.map((t) => JSON.stringify(t)).join(\", \");\n\n return [\n \"\",\n `## Capture #${index} — ${time}`,\n `### type: ${formatted.type}`,\n `### tags: [${tagsStr}]`,\n \"\",\n formatted.bodyMarkdown,\n ].join(\"\\n\");\n}\n\n// ─── Core: find or create session file ───────────────\n\n/**\n * 获取或创建 session 文件路径。\n * v2 规则:一个对话对应一个文件 `captures/raw/session-{id}.md`\n */\nexport function resolveSessionFile(\n repoRoot: string,\n sessionId: string,\n): { absolutePath: string; relativePath: string; exists: boolean } {\n const filename = `session-${sessionId}.md`;\n const absolutePath = memoryPath(repoRoot, \"captures\", \"raw\", filename);\n const relativePath = join(\".memory\", \"captures\", \"raw\", filename);\n return { absolutePath, relativePath, exists: existsSync(absolutePath) };\n}\n\n// ─── Legacy: renderCaptureMarkdown (LLM upgrade 用) ────\n\n/**\n * @deprecated v2 保留用于 LLM upgrade 兼容。Phase 2 将移除或重写为 session 文件的增量更新。\n */\nexport function renderCaptureMarkdown(\n formatted: FormattedCapture,\n date: string,\n): string {\n const tagsStr = formatted.tags.map((t) => JSON.stringify(t)).join(\", \");\n const lines = [\n \"---\",\n `type: ${formatted.type}`,\n `date: ${date}`,\n `session: ${formatted.sessionId}`,\n `tags: [${tagsStr}]`,\n `scope: ${formatted.scope}`,\n \"confidence: pending\",\n ];\n if (formatted.llmUpgradedAt) {\n lines.push(`llmUpgradedAt: ${formatted.llmUpgradedAt}`);\n }\n lines.push(\"---\", \"\", formatted.bodyMarkdown);\n return `${lines.join(\"\\n\")}\\n`;\n}\n\n// ─── Core: append capture to session file ─────────────\n\ninterface AppendCaptureResult {\n absolutePath: string;\n relativePath: string;\n filename: string;\n isNewFile: boolean;\n captureIndex: number;\n previousStatus: SessionFileStatus | null;\n}\n\n/**\n * 将一条 capture 追加到对应的 session 文件。\n *\n * 行为:\n * - 文件不存在 → 创建,status=pending\n * - 文件存在 → 追加新的 Capture 段落\n * - 若 status=done → 改为 stale(有新内容需重新 consolidate)\n * - 若 status=stale/pending → 保持不变\n */\nexport function appendCaptureToSession(\n repoRoot: string,\n formatted: FormattedCapture,\n): AppendCaptureResult {\n const { absolutePath, relativePath, exists } = resolveSessionFile(repoRoot, formatted.sessionId);\n const filename = `session-${formatted.sessionId}.md`;\n\n mkdirSync(join(absolutePath, \"..\"), { recursive: true });\n const now = isoNow();\n\n if (!exists) {\n // 新建文件\n const fm: SessionFileFrontmatter = {\n sessionId: formatted.sessionId,\n source: \"session\",\n status: \"pending\",\n domain: null,\n createdAt: now,\n lastModifiedAt: now,\n consolidatedAt: null,\n captureCount: 1,\n };\n\n const content =\n serializeSessionFrontmatter(fm) +\n \"\\n\" +\n renderCaptureSection(formatted, 1) +\n \"\\n\";\n\n writeFileSync(absolutePath, content, \"utf8\");\n\n return {\n absolutePath,\n relativePath,\n filename,\n isNewFile: true,\n captureIndex: 1,\n previousStatus: null,\n };\n }\n\n // 已有文件 → 追加\n const existingContent = readFileSync(absolutePath, \"utf8\");\n const existingFm = parseSessionFileFrontmatter(existingContent);\n\n if (!existingFm) {\n // 格式异常,覆盖写入\n const fm: SessionFileFrontmatter = {\n sessionId: formatted.sessionId,\n source: \"session\",\n status: \"pending\",\n domain: null,\n createdAt: now,\n lastModifiedAt: now,\n consolidatedAt: null,\n captureCount: 1,\n };\n\n writeFileSync(\n absolutePath,\n serializeSessionFrontmatter(fm) +\n \"\\n\" +\n renderCaptureSection(formatted, 1) +\n \"\\n\",\n \"utf8\",\n );\n return {\n absolutePath,\n relativePath,\n filename,\n isNewFile: false,\n captureIndex: 1,\n previousStatus: null,\n };\n }\n\n const previousStatus = existingFm.status;\n const nextIndex = existingFm.captureCount + 1;\n\n // 状态机:done → stale(有新内容需要重新处理)\n const newStatus: SessionFileStatus =\n existingFm.status === \"done\" ? \"stale\" : existingFm.status;\n\n const updatedFm: SessionFileFrontmatter = {\n ...existingFm,\n status: newStatus,\n lastModifiedAt: now,\n captureCount: nextIndex,\n };\n\n // 找到第一个 --- (frontmatter 结束位置)\n const fmEndIndex = existingContent.indexOf(\"---\", 4); // 跳过开头的 ---\n const bodyStart = fmEndIndex >= 0 ? fmEndIndex + 3 : existingContent.length;\n\n const updatedContent =\n serializeSessionFrontmatter(updatedFm) +\n \"\\n\" +\n existingContent.slice(bodyStart) + // 保留原有 body\n renderCaptureSection(formatted, nextIndex) + // 追加新的 capture 段落\n \"\\n\";\n\n writeFileSync(absolutePath, updatedContent, \"utf8\");\n\n return {\n absolutePath,\n relativePath,\n filename,\n isNewFile: false,\n captureIndex: nextIndex,\n previousStatus,\n };\n}\n\n// ─── Legacy compat: writeCaptureFile ──────────────────\n/**\n * @deprecated v2 使用 appendCaptureToSession 替代。保留此函数以兼容尚未迁移的调用方。\n */\nexport function writeCaptureFile(\n repoRoot: string,\n formatted: FormattedCapture,\n _filename?: string,\n): { absolutePath: string; filename: string } {\n const result = appendCaptureToSession(repoRoot, formatted);\n return { absolutePath: result.absolutePath, filename: result.filename };\n}\n\n/** 更新 session 文件的 consolidate 状态 */\nexport function markSessionConsolidated(\n repoRoot: string,\n sessionId: string,\n): void {\n const { absolutePath, exists } = resolveSessionFile(repoRoot, sessionId);\n if (!exists) return;\n\n const content = readFileSync(absolutePath, \"utf8\");\n const fm = parseSessionFileFrontmatter(content);\n if (!fm) return;\n\n const updatedFm: SessionFileFrontmatter = {\n ...fm,\n status: \"done\",\n consolidatedAt: isoNow(),\n };\n\n const fmEndIndex = content.indexOf(\"---\", 4);\n const bodyStart = fmEndIndex >= 0 ? fmEndIndex + 3 : content.length;\n\n writeFileSync(\n absolutePath,\n serializeSessionFrontmatter(updatedFm) + \"\\n\" + content.slice(bodyStart),\n \"utf8\",\n );\n}\n","import { debugLog } from \"./config/debugLog.js\";\n\n/** Hook 路径下失败仍 exit 0,避免阻塞 Claude Code */\nexport function hookExit(code: number, strict?: boolean): never {\n process.exit(strict ? code : code === 0 ? 0 : 0);\n}\n\nexport function finalizeHookCommand(\n fn: () => void | Promise<void>,\n strict?: boolean,\n debug?: boolean,\n): void {\n void (async () => {\n try {\n await fn();\n process.exit(0);\n } catch (error) {\n debugLog(debug === true, \"hook\", error instanceof Error ? error.message : String(error));\n process.exit(strict ? 1 : 0);\n }\n })();\n}\n","import { configureDebugLogging } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { flushPendingLlmJobs, runLlmJobById } from \"../capture/runLlmJob.js\";\nimport { finalizeHookCommand } from \"../hookExit.js\";\n\nexport interface CaptureLlmCommandOptions {\n cwd?: string;\n job?: string;\n flush?: boolean;\n strict?: boolean;\n}\n\nexport function runCaptureLlmCommand(opts: CaptureLlmCommandOptions): void {\n const ctx = loadRepoContext(opts.cwd);\n const debug = ctx?.config.debug === true;\n configureDebugLogging(ctx?.repoRoot ?? null, debug);\n\n finalizeHookCommand(async () => {\n if (!ctx) {\n console.error(\"hermes-repo: not initialized\");\n return;\n }\n const repoRoot = ctx.repoRoot;\n\n if (opts.flush) {\n const n = await flushPendingLlmJobs(repoRoot, debug);\n if (debug) {\n console.error(`hermes-repo: flushed ${n} llm job(s)`);\n }\n return;\n }\n\n if (!opts.job) {\n console.error(\"hermes-repo capture-llm: require --job <id> or --flush\");\n return;\n }\n\n const result = await runLlmJobById(repoRoot, opts.job, debug);\n if (!result.ok && opts.strict) {\n throw new Error(result.reason ?? \"capture-llm failed\");\n }\n }, opts.strict, debug);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nexport type HookInput = {\n /** Claude / CodeBuddy Stop hook(文件存在时已 resolve) */\n transcriptPath?: string;\n /** hook stdin 中的 transcript_path 原值(无论文件是否存在) */\n transcriptPathRaw?: string;\n hookEventName?: string;\n sessionId?: string;\n conversationId?: string;\n workspaceRoots?: string[];\n status?: string;\n};\n\nfunction pickString(obj: Record<string, unknown>, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const v = obj[key];\n if (typeof v === \"string\" && v.length > 0) {\n return v;\n }\n }\n return undefined;\n}\n\nfunction pickStringArray(\n obj: Record<string, unknown>,\n ...keys: string[]\n): string[] | undefined {\n for (const key of keys) {\n const v = obj[key];\n if (Array.isArray(v)) {\n const roots = v.filter((x): x is string => typeof x === \"string\");\n if (roots.length > 0) {\n return roots;\n }\n }\n }\n return undefined;\n}\n\n/** 路径是否属于某助手 transcript 根目录 */\nexport function isTranscriptUnderAssistant(\n transcriptPath: string | undefined,\n segment: \".codebuddy\" | \".claude\",\n): boolean {\n if (!transcriptPath) {\n return false;\n }\n const normalized = transcriptPath.replace(/\\\\/g, \"/\");\n return normalized.includes(`${segment}/`);\n}\n\nexport function parseHookInputJson(raw: string): HookInput | null {\n const trimmed = raw.trim();\n if (!trimmed) {\n return null;\n }\n try {\n const parsed = JSON.parse(trimmed) as Record<string, unknown>;\n const transcriptRaw = pickString(parsed, \"transcript_path\", \"transcriptPath\");\n const transcriptPath =\n transcriptRaw && existsSync(transcriptRaw) ? resolve(transcriptRaw) : undefined;\n\n return {\n transcriptPath,\n transcriptPathRaw: transcriptRaw,\n hookEventName: pickString(parsed, \"hook_event_name\", \"hookEventName\"),\n sessionId: pickString(parsed, \"session_id\", \"sessionId\"),\n conversationId: pickString(parsed, \"conversation_id\", \"conversationId\"),\n workspaceRoots: pickStringArray(parsed, \"workspace_roots\", \"workspaceRoots\"),\n status: pickString(parsed, \"status\"),\n };\n } catch {\n return null;\n }\n}\n\n/** 从 hook stdin 读取一次(非 TTY 时) */\nexport function readHookInputSync(): HookInput | null {\n if (process.stdin.isTTY) {\n return null;\n }\n try {\n const raw = readFileSync(0, \"utf8\");\n return parseHookInputJson(raw);\n } catch {\n return null;\n }\n}\n\nexport function isCodebuddyCaptureHook(hook: HookInput | null | undefined): boolean {\n if (!hook) {\n return false;\n }\n return (\n isTranscriptUnderAssistant(hook.transcriptPath, \".codebuddy\") ||\n isTranscriptUnderAssistant(hook.transcriptPathRaw, \".codebuddy\")\n );\n}\n\nexport function isClaudeCaptureHook(hook: HookInput | null | undefined): boolean {\n if (!hook) {\n return false;\n }\n if (isCodebuddyCaptureHook(hook)) {\n return false;\n }\n if (isTranscriptUnderAssistant(hook.transcriptPath, \".claude\")) {\n return true;\n }\n if (hook.transcriptPath) {\n return true;\n }\n const name = hook.hookEventName?.toLowerCase();\n return name === \"stop\" && !hook.sessionId && !hook.conversationId;\n}\n\nexport function isCursorCaptureHook(hook: HookInput | null | undefined): boolean {\n if (!hook) {\n return false;\n }\n if (hook.transcriptPath) {\n if (\n isTranscriptUnderAssistant(hook.transcriptPath, \".codebuddy\") ||\n isTranscriptUnderAssistant(hook.transcriptPath, \".claude\")\n ) {\n return false;\n }\n }\n const name = hook.hookEventName?.toLowerCase();\n if (name === \"stop\") {\n return true;\n }\n return Boolean(hook.sessionId || hook.conversationId);\n}\n\nexport function isCursorInjectHook(hook: HookInput | null | undefined): boolean {\n if (!hook) {\n return false;\n }\n const name = hook.hookEventName?.toLowerCase();\n return name === \"sessionstart\";\n}\n","import type { ParsedSession } from \"./types.js\";\n\n/**\n * 修复 3:信号强度分级\n * 从二元判断(有/无)改进为多级评分(强/中/弱/无)\n * 根据信号强度和对话复杂度加权决策\n */\n\nexport type SignalStrength = \"strong\" | \"medium\" | \"weak\" | \"none\";\n\nconst STRONG_SIGNAL_RE = /改成|不对|错了|应该是|决定用|约定是|必须|架构/i;\nconst MEDIUM_SIGNAL_RE =\n /考虑|也许|可能|试试|我们可以|看起来|似乎|建议|优化/i;\nconst WEAK_SIGNAL_RE = /为什么|怎样|怎么|什么时候|哪里|如何/i;\n\n/**\n * 判断文本的信号强度\n * strong: 明确的决策或纠正\n * medium: 有价值但不确定的建议\n * weak: 可能有价值的探索性问题\n * none: 无信号\n */\nexport function getSignalStrength(text: string): SignalStrength {\n if (STRONG_SIGNAL_RE.test(text)) {\n return \"strong\";\n }\n if (MEDIUM_SIGNAL_RE.test(text)) {\n return \"medium\";\n }\n if (WEAK_SIGNAL_RE.test(text)) {\n return \"weak\";\n }\n return \"none\";\n}\n\n/**\n * 根据信号强度和对话复杂度加权决策\n */\nexport function shouldCaptureBySignalStrength(session: ParsedSession): boolean {\n const strength = getSignalStrength(session.text);\n\n // 强信号:始终保留\n if (strength === \"strong\") {\n return true;\n }\n\n // 中等信号:需要多轮对话或复杂任务\n if (strength === \"medium\") {\n return session.messages.length >= 4 || session.toolCalls > 3;\n }\n\n // 弱信号:只有特别复杂的任务才保留\n if (strength === \"weak\") {\n return session.toolCalls > 8 || session.fileChanges > 5;\n }\n\n // 无信号:返回 false,让其他逻辑决策\n return false;\n}\n\n/**\n * 为捕获计算综合强度分数(0-100)\n * 考虑文本信号、会话复杂度、文件修改等多个因子\n */\nexport function computeSignalScore(session: ParsedSession): number {\n let score = 0;\n\n // 文本信号权重:30 分\n const strength = getSignalStrength(session.text);\n if (strength === \"strong\") {\n score += 30;\n } else if (strength === \"medium\") {\n score += 15;\n } else if (strength === \"weak\") {\n score += 5;\n }\n\n // 会话复杂度权重:30 分\n const messageBonus = Math.min(30, (session.messages.length - 2) * 5);\n score += Math.max(0, messageBonus);\n\n // 工具调用权重:20 分\n const toolBonus = Math.min(20, session.toolCalls * 2);\n score += toolBonus;\n\n // 文件修改权重:20 分\n const fileBonus = Math.min(20, session.fileChanges * 5);\n score += fileBonus;\n\n return Math.min(100, score);\n}\n\n/**\n * 根据综合分数决策是否捕获\n * < 40: 不捕获\n * 40-70: 边界情况(可选 LLM 判断)\n * > 70: 捕获\n */\nexport function shouldCaptureByScore(session: ParsedSession): boolean {\n const score = computeSignalScore(session);\n return score >= 70;\n}\n","import type { ParsedSession } from \"./types.js\";\nimport {\n computeSignalScore,\n getSignalStrength,\n} from \"./signalStrength.js\";\n\nconst ARCHITECTURE_SIGNAL_RE =\n /约定|必须|架构|决策|规范|根因|migration|refactor|convention|root cause/i;\nconst CORRECTION_RE =\n /不对|错了|不是这样|不应该|别用|stop|wrong|incorrect|改成|修正/i;\n\n/** 内联:用户纠正检测(原 shouldCapture.ts) */\nfunction hasUserCorrection(session: ParsedSession): boolean {\n return session.messages.some(\n (m) => m.role === \"user\" && CORRECTION_RE.test(m.text),\n );\n}\n\nexport function hasArchitectureSignal(text: string): boolean {\n return ARCHITECTURE_SIGNAL_RE.test(text);\n}\n\n/**\n * 判断会话是否需要 LLM 升级\n *\n * 触发条件(满足任一即可):\n * 1. 高复杂度:消息数、文件修改、工具调用达到阈值\n * 2. 强信号:明确决策、约定、架构相关\n * 3. 用户纠正:用户有纠正行为\n * 4. 组合条件:中等复杂度 + 中等信号\n * 5. 综合分数:分数 ≥ 55\n */\nexport function needsLlm(session: ParsedSession): boolean {\n // 1. 高复杂度会话\n if (session.messages.length >= 20) return true;\n if (session.fileChanges >= 3) return true;\n if (session.toolCalls >= 8) return true;\n\n // 2. 强信号(重要约定、决策应被 LLM 提炼)\n const strength = getSignalStrength(session.text);\n if (strength === \"strong\") return true;\n\n // 3. 架构信号\n if (hasArchitectureSignal(session.text)) return true;\n\n // 4. 用户纠正(纠正过程有价值,需要 LLM 总结)\n if (hasUserCorrection(session)) return true;\n\n // 5. 组合条件:中等复杂度 + 有实质工作\n if (session.messages.length >= 10 && session.toolCalls >= 5) return true;\n if (strength === \"medium\" && session.fileChanges >= 2) return true;\n if (session.toolCalls >= 5 && session.fileChanges >= 1) return true;\n\n // 6. 基于综合分数\n const score = computeSignalScore(session);\n if (score >= 55) return true;\n\n return false;\n}\n","import { spawn } from \"node:child_process\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { debugLog } from \"../config/debugLog.js\";\nimport { isLlmAvailable } from \"../config/llmConfig.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport type { ConsolidateConfig } from \"../config/types.js\";\nimport {\n runConsolidate,\n type ConsolidateResultV2,\n} from \"./runConsolidate.js\";\nimport { CONSOLIDATE_LOCK_TTL_MS } from \"./constants.js\";\nimport {\n scanAllSessions,\n filterPendingSessions,\n type ScannedSession,\n} from \"./sessionScanner.js\";\nimport {\n readConsolidateLock,\n isLockStale,\n readConsolidateState,\n} from \"./state.js\";\n\nfunction cliPath(): string {\n return join(dirname(fileURLToPath(import.meta.url)), \"..\", \"cli.js\");\n}\n\n/**\n * v2: flush 命令入口。\n * 直接调用 runConsolidate(单次 LLM 调用)。\n */\nexport async function runFlushCommand(opts: {\n cwd?: string;\n force?: boolean;\n dryRun?: boolean;\n debug?: boolean;\n}): Promise<ConsolidateResultV2> {\n const ctx = loadRepoContext(opts.cwd);\n if (!ctx) {\n return {\n ran: false,\n reason: \"not-initialized\",\n sessionsProcessed: 0,\n knowledgeCreated: 0,\n knowledgeUpdated: 0,\n skippedCount: 0,\n archived: 0,\n };\n }\n\n // 检查是否有可处理的 session\n const allSessions = scanAllSessions(ctx.repoRoot);\n const pendingSessions = opts.force\n ? allSessions\n : filterPendingSessions(allSessions);\n\n if (pendingSessions.length === 0 && !opts.force && !opts.dryRun) {\n return {\n ran: false,\n reason: \"no-pending-sessions\",\n sessionsProcessed: 0,\n knowledgeCreated: 0,\n knowledgeUpdated: 0,\n skippedCount: 0,\n archived: 0,\n };\n }\n\n return runConsolidate({\n repoRoot: ctx.repoRoot,\n config: ctx.config,\n force: opts.force,\n dryRun: opts.dryRun,\n debug: opts.debug ?? ctx.config.debug,\n });\n}\n\nexport function shouldAutoFlush(\n sessions: ScannedSession[],\n consolidate: ConsolidateConfig,\n lastConsolidatedAt: string,\n): boolean {\n const autoFlush = consolidate.autoFlush;\n if (!autoFlush.enabled || sessions.length === 0) {\n return false;\n }\n\n if (sessions.length >= autoFlush.minPendingSessions) {\n return true;\n }\n\n const pendingChars = sessions.reduce(\n (sum, session) => sum + session.bodyContent.length,\n 0,\n );\n if (pendingChars >= autoFlush.maxPendingChars) {\n return true;\n }\n\n const last = Date.parse(lastConsolidatedAt);\n if (Number.isNaN(last)) {\n return true;\n }\n\n const minIntervalMs = autoFlush.minIntervalMinutes * 60 * 1000;\n return Date.now() - last >= minIntervalMs;\n}\n\n/**\n * v2: 自动调度 consolidate(由 capture hook 触发)。\n */\nexport function maybeScheduleConsolidate(opts: {\n repoRoot: string;\n debug?: boolean;\n}): void {\n const ctx = loadRepoContext(opts.repoRoot);\n if (!ctx) {\n return;\n }\n\n const autoFlush = ctx.config.consolidate.autoFlush;\n if (!autoFlush.enabled) {\n return;\n }\n\n if (!isLlmAvailable(ctx.config.llm)) {\n debugLog(opts.debug === true, \"consolidate\", \"auto flush skipped: llm not available\");\n return;\n }\n\n const lock = readConsolidateLock(opts.repoRoot);\n if (lock && !isLockStale(lock, CONSOLIDATE_LOCK_TTL_MS)) {\n debugLog(opts.debug === true, \"consolidate\", \"auto flush skipped: lock held\");\n return; // 锁已被持有\n }\n\n const pendingSessions = filterPendingSessions(scanAllSessions(opts.repoRoot));\n const state = readConsolidateState(opts.repoRoot);\n if (\n !shouldAutoFlush(\n pendingSessions,\n ctx.config.consolidate,\n state.lastConsolidatedAt,\n )\n ) {\n debugLog(\n opts.debug === true,\n \"consolidate\",\n `auto flush skipped: ${pendingSessions.length} pending session(s) below thresholds`,\n );\n return;\n }\n\n try {\n const child = spawn(\n process.execPath,\n [cliPath(), \"flush\", \"-C\", opts.repoRoot],\n {\n detached: true,\n stdio: \"ignore\",\n cwd: opts.repoRoot,\n },\n );\n child.unref();\n debugLog(\n opts.debug === true,\n \"consolidate\",\n `auto flush scheduled: ${pendingSessions.length} pending session(s)`,\n );\n } catch (err) {\n debugLog(\n opts.debug === true,\n \"consolidate\",\n `auto flush spawn failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { memoryPath } from \"../init/paths.js\";\n\n// ─── v2 状态模型 ─────────────────────────────\n\nexport interface SessionStatusRecord {\n status: \"pending\" | \"done\" | \"stale\";\n consolidatedAt: string | null;\n lastCaptureAt: string;\n}\n\nexport interface ConsolidateStateV2 {\n version: 2;\n lastConsolidatedAt: string;\n stats: {\n totalCapturesProcessed: number;\n domains: string[];\n knowledgeFilesCreated: number;\n };\n /** sessionId → status record */\n processedSessions: Record<string, SessionStatusRecord>;\n}\n\nconst EMPTY_STATE: ConsolidateStateV2 = {\n version: 2,\n lastConsolidatedAt: new Date(0).toISOString(),\n stats: {\n totalCapturesProcessed: 0,\n domains: [],\n knowledgeFilesCreated: 0,\n },\n processedSessions: {},\n};\n\nexport function consolidateStatePath(repoRoot: string): string {\n return memoryPath(repoRoot, \"consolidate-state.json\");\n}\n\nexport function consolidateLockPath(repoRoot: string): string {\n return memoryPath(repoRoot, \".consolidate.lock\");\n}\n\nexport function readConsolidateState(repoRoot: string): ConsolidateStateV2 {\n const path = consolidateStatePath(repoRoot);\n if (!existsSync(path)) {\n return { ...EMPTY_STATE, processedSessions: {} };\n }\n try {\n const raw = JSON.parse(readFileSync(path, \"utf8\")) as unknown;\n // v1 → v2 自动升级\n if (typeof raw === \"object\" && raw !== null) {\n const obj = raw as Record<string, unknown>;\n if (obj.version === 2 && typeof obj.processedSessions === \"object\") {\n return raw as ConsolidateStateV2;\n }\n // v1 升级:processedCapturePaths → 空 processedSessions\n return {\n ...EMPTY_STATE,\n lastConsolidatedAt:\n typeof obj.lastConsolidatedAt === \"string\"\n ? obj.lastConsolidatedAt\n : EMPTY_STATE.lastConsolidatedAt,\n };\n }\n return { ...EMPTY_STATE, processedSessions: {} };\n } catch {\n return { ...EMPTY_STATE, processedSessions: {} };\n }\n}\n\nexport function writeConsolidateState(\n repoRoot: string,\n state: ConsolidateStateV2,\n): void {\n const path = consolidateStatePath(repoRoot);\n mkdirSync(memoryPath(repoRoot), { recursive: true });\n writeFileSync(path, `${JSON.stringify(state, null, 2)}\\n`, \"utf8\");\n}\n\n// ─── Lock(保留不变)─────────────────────────\n\nexport interface ConsolidateLock {\n pid: number;\n startedAt: string;\n}\n\nexport function readConsolidateLock(repoRoot: string): ConsolidateLock | null {\n const path = consolidateLockPath(repoRoot);\n if (!existsSync(path)) {\n return null;\n }\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as ConsolidateLock;\n } catch {\n return null;\n }\n}\n\nexport function writeConsolidateLock(repoRoot: string): void {\n const payload: ConsolidateLock = {\n pid: process.pid,\n startedAt: new Date().toISOString(),\n };\n mkdirSync(memoryPath(repoRoot), { recursive: true });\n writeFileSync(\n consolidateLockPath(repoRoot),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n}\n\nexport function releaseConsolidateLock(repoRoot: string): void {\n const path = consolidateLockPath(repoRoot);\n if (existsSync(path)) {\n rmSync(path, { force: true });\n }\n}\n\nexport function isLockStale(\n lock: ConsolidateLock,\n ttlMs: number,\n): boolean {\n const started = Date.parse(lock.startedAt);\n if (Number.isNaN(started)) {\n return true;\n }\n return Date.now() - started > ttlMs;\n}\n","import { readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { SessionFileFrontmatter } from \"../capture/writeCapture.js\";\n\n// ─── Types ────────────────────────────────────\n\nexport interface ScannedSession {\n sessionId: string;\n filename: string;\n absolutePath: string;\n relativePath: string;\n frontmatter: SessionFileFrontmatter;\n bodyContent: string; // frontmatter 之后的完整 body\n}\n\n// ─── 解析 session 文件 frontmatter ───────────\n\nfunction parseSessionFrontmatter(\n content: string,\n): SessionFileFrontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: Record<string, unknown> = {};\n for (const line of match[1].split(\"\\n\")) {\n const idx = line.indexOf(\":\");\n if (idx === -1) continue;\n const key = line.slice(0, idx).trim();\n const val = line.slice(idx + 1).trim();\n\n if (val === \"null\") fm[key] = null;\n else if (val === \"true\") fm[key] = true;\n else if (val === \"false\") fm[key] = false;\n else if (/^\\d+$/.test(val)) fm[key] = Number.parseInt(val, 10);\n else fm[key] = val.replace(/^[\"']|[\"']$/g, \"\");\n }\n\n return fm as unknown as SessionFileFrontmatter;\n}\n\n// ─── 扫描 captures/raw/ ──────────────────────\n\n/**\n * 扫描 captures/raw/ 下所有 session 文件,返回全部。\n */\nexport function scanAllSessions(repoRoot: string): ScannedSession[] {\n const rawDir = memoryPath(repoRoot, \"captures\", \"raw\");\n let files: string[];\n try {\n files = readdirSync(rawDir).filter((f) => f.endsWith(\".md\"));\n } catch {\n return [];\n }\n\n const sessions: ScannedSession[] = [];\n for (const file of files) {\n const absolutePath = join(rawDir, file);\n try {\n const content = readFileSync(absolutePath, \"utf8\");\n const fm = parseSessionFrontmatter(content);\n if (!fm || !fm.sessionId) continue;\n\n // 提取 body(frontmatter 之后的内容)\n const fmEndIndex = content.indexOf(\"---\", 4);\n const bodyStart = fmEndIndex >= 0 ? fmEndIndex + 3 : content.length;\n const bodyContent = content.slice(bodyStart);\n\n sessions.push({\n sessionId: fm.sessionId,\n filename: file,\n absolutePath,\n relativePath: join(\".memory\", \"captures\", \"raw\", file),\n frontmatter: fm,\n bodyContent: bodyContent.trim(),\n });\n } catch {\n // 跳过无法解析的文件\n }\n }\n\n // 按最后修改时间倒序(优先处理最近的)\n sessions.sort(\n (a, b) =>\n new Date(b.frontmatter.lastModifiedAt).getTime() -\n new Date(a.frontmatter.lastModifiedAt).getTime(),\n );\n\n return sessions;\n}\n\n/**\n * 过滤出需要 consolidate 的 session 文件(pending + stale)。\n */\nexport function filterPendingSessions(\n sessions: ScannedSession[],\n): ScannedSession[] {\n return sessions.filter(\n (s) =>\n s.frontmatter.status === \"pending\" ||\n s.frontmatter.status === \"stale\",\n );\n}\n","import { readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { LlmConfigV2 } from \"../config/types.js\";\nimport type { ScannedSession } from \"./sessionScanner.js\";\n\n// ─── Types ────────────────────────────────────\n\nexport interface ExistingKnowledge {\n path: string;\n title: string;\n type: \"rule\" | \"domain-knowledge\" | \"workflow\" | \"decision\" | \"incident\";\n domain: string | null;\n status: string;\n summary: string;\n}\n\nexport interface LlmConsolidateInput {\n pendingSessions: PendingSessionInput[];\n existingKnowledge: ExistingKnowledge[];\n currentMemoryMd: string | null;\n}\n\nexport interface PendingSessionInput {\n sessionId: string;\n status: \"pending\" | \"stale\";\n content: string; // 完整的 markdown(含 frontmatter + body)\n captureCount: number;\n createdAt: string;\n}\n\nexport interface KnowledgeFileOutput {\n targetPath: string;\n action: \"create\" | \"update\";\n frontmatter: Record<string, unknown>;\n body: string;\n}\n\nexport interface LlmConsolidateResult {\n knowledgeFiles: KnowledgeFileOutput[];\n memoryMd: string;\n skippedSessions: Array<{ sessionId: string; reason: string }>;\n}\n\n// ─── System Prompt ────────────────────────────\n\nconst CONSOLIDATE_SYSTEM_PROMPT = `你是一个项目知识整理专家。你的任务是从 AI 编程助手的对话记录中提炼出结构化的知识库。\n\n## 工作流程\n\n### 第一步:分析理解\n通读所有待处理的 session 记录,理解:\n- 讨论了哪些业务领域(模块、子系统、功能)\n- 产生了哪类知识(规范、事实、流程、决策、踩坑)\n- 哪些内容有长期保留价值,哪些是临时噪音\n\n### 第二步:域识别与匹配\n为每条有价值的内容确定所属业务域:\n- 查看 existingKnowledge 中已有的域列表\n- 优先复用已有域,只有确实无法匹配时才新建域\n- 无法归类的放入 general 域\n- 域名用 kebab-case,简洁明了(如 quoted, inventory, payment)\n- 不要创建过于细粒度的域(如不要按文件名建域)\n\n### 第三步:分类判定\n\n| 类型 | 判定条件 | 写入目录 |\n|------|---------|---------|\n| rule | 编码规范、约定、禁令 | rules/{name}.md |\n| domain-knowledge | 业务域的事实、概念、数据模型 | domains/{domain}/{name}.md |\n| workflow | 可复用的操作步骤、流程 | workflows/{name}.md |\n| decision | 架构选型、方案选择及原因 | decisions/{date}-{slug}.md |\n| incident | 踩坑记录、问题根因、修复方式 | incidents/{date}-{slug}.md |\n\n分类优先级:\n1. 如果是可执行的步骤流程 → workflow\n2. 如果是\"为什么选了X而不是Y\" → decision\n3. 如果是\"遇到了X问题,原因是Y,修法是Z\" → incident\n4. 如果是编码规范、团队约定 → rule\n5. 其余 → domain-knowledge(默认)\n\n### 第四步:内容提炼\n对归类后的内容进行提炼:\n\n提炼原则:\n1. 去除口语化表达、重复讨论、中间错误结论\n2. 保留最终确定的结论和关键决策过程\n3. 用结构化的 markdown 组织(标题、列表、表格、代码块)\n4. 区分\"事实\"和\"推断\",对不确定的内容标注 confidence: low\n5. 保留足够的上下文让未来阅读者理解背景\n\n如果是更新已有文件(action=update):\n- 对比新旧内容,保留仍有效的部分\n- 更新被修正的部分(标注更新日期)\n- 追加全新内容\n- 移除已被完全替代的旧段落\n\n### 第五步:生成导航 (MEMORY.md)\n重新生成导航页面:\n\n组织原则:\n1. rules 放最前(必读),每项一行:[路径](链接) — 摘要\n2. domains 按域分组表格展示\n3. workflows 简短列出\n4. decisions/incidents 只显示计数和最近几条\n5. 每个摘要控制在 20 字以内\n6. 整体保持紧凑(目标 < 100 行),AI 注入时不会太长\n7. 保留用户的自定义编辑标记 <!-- user-edit-start --> ... <!-- user-edit-end -->\n\n## 输出要求\n- 输出严格 JSON 格式\n- knowledgeFiles 数组包含所有需要创建/更新的文件\n - 每项必须包含完整的 frontmatter 和 body markdown\n- memoryMd 是完整 MEMORY.md 内容\n- 无价值的 session 在 skippedSessions 中说明原因(而非生成空内容)`;\n\n// ─── 扫描已有知识文件 ───────────────────────\n\n/**\n * 扫描 rules/, domains/, workflows/, decisions/, incidents/\n * 返回已有知识文件的摘要列表。\n */\nexport function scanExistingKnowledge(repoRoot: string): ExistingKnowledge[] {\n const results: ExistingKnowledge[] = [];\n\n // 定义各类型目录和对应的 type\n const typeDirs: Array<{ dir: string; type: ExistingKnowledge[\"type\"] }> = [\n { dir: \"rules\", type: \"rule\" },\n { dir: \"workflows\", type: \"workflow\" },\n { dir: \"decisions\", type: \"decision\" },\n { dir: \"incidents\", type: \"incident\" },\n ];\n\n for (const { dir, type } of typeDirs) {\n const absDir = memoryPath(repoRoot, dir);\n scanMarkdownDirectory(absDir, dir, type, null, results);\n }\n\n // domains 下可能有多个子目录\n const domainsDir = memoryPath(repoRoot, \"domains\");\n try {\n const subdirs = readdirSync(domainsDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n\n for (const domain of subdirs) {\n const domainAbsDir = join(domainsDir, domain);\n scanMarkdownDirectory(\n domainAbsDir,\n `domains/${domain}`,\n \"domain-knowledge\",\n domain,\n results,\n );\n }\n } catch {\n // domains 目录不存在\n }\n\n return results;\n}\n\nfunction scanMarkdownDirectory(\n absoluteDir: string,\n relativePrefix: string,\n type: ExistingKnowledge[\"type\"],\n domain: string | null,\n results: ExistingKnowledge[],\n): void {\n let files: string[];\n try {\n files = readdirSync(absoluteDir).filter((f) => f.endsWith(\".md\"));\n } catch {\n return;\n }\n\n for (const file of files) {\n try {\n const content = readFileSync(join(absoluteDir, file), \"utf8\");\n // 解析 frontmatter 提取 title\n const fmMatch = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n let title = file.replace(/\\.md$/, \"\");\n if (fmMatch) {\n const titleMatch = fmMatch[1].match(/^title:\\s*(.+)$/m);\n if (titleMatch) title = titleMatch[1].replace(/^[\"']|[\"']$/g, \"\");\n }\n\n // 取前 100 字作为摘要\n const bodyStart = content.indexOf(\"---\", 4);\n const body =\n bodyStart >= 0 ? content.slice(bodyStart + 3).trim() : content;\n const summary = body.slice(0, 150).replace(/\\n/g, \" \").trim();\n\n results.push({\n path: `${relativePrefix}/${file}`,\n title,\n type,\n domain,\n status: \"active\",\n summary,\n });\n } catch {\n // 跳过无法读取的文件\n }\n }\n}\n\n// ─── 构建 LLM Input ──────────────────────────\n\nexport function buildLlmConsolidateInput(\n repoRoot: string,\n sessions: ScannedSession[],\n): LlmConsolidateInput {\n const pendingSessions: PendingSessionInput[] = sessions.map((s) => ({\n sessionId: s.sessionId,\n status: s.frontmatter.status as \"pending\" | \"stale\",\n content: readFileSync(s.absolutePath, \"utf8\"),\n captureCount: s.frontmatter.captureCount,\n createdAt: s.frontmatter.createdAt,\n }));\n\n const existingKnowledge = scanExistingKnowledge(repoRoot);\n\n // 读取当前 MEMORY.md\n const memoryPathAbs = memoryPath(repoRoot, \"MEMORY.md\");\n let currentMemoryMd: string | null = null;\n try {\n currentMemoryMd = readFileSync(memoryPathAbs, \"utf8\");\n } catch {\n // 不存在则传 null\n }\n\n return {\n pendingSessions,\n existingKnowledge,\n currentMemoryMd,\n };\n}\n\n// ─── 调用 LLM ────────────────────────────────\n\n/**\n * 单次 LLM 调用完成完整 consolidate。\n *\n * @throws 当 LLM 未配置或调用失败时抛出错误\n */\nexport async function callLlmConsolidate(\n input: LlmConsolidateInput,\n llmConfig: LlmConfigV2,\n): Promise<LlmConsolidateResult> {\n if (!llmConfig.enabled) {\n throw new Error(\n \"LLM 未启用:请在 config.json 中设置 llm.enabled = true\",\n );\n }\n\n if (!llmConfig.apiKey.trim() || !llmConfig.baseUrl.trim() || !llmConfig.model.trim()) {\n throw new Error(\n \"LLM 未配置:请在 config.json 中设置 llm.apiKey、llm.baseUrl 和 llm.model\",\n );\n }\n\n const url = `${llmConfig.baseUrl.replace(/\\/$/, \"\")}/chat/completions`;\n\n // 构造 user message — 将 input 序列化为 JSON\n const userContent = formatUserMessage(input);\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 120_000); // 2 分钟超时\n\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${llmConfig.apiKey}`,\n },\n body: JSON.stringify({\n model: llmConfig.model,\n response_format: { type: \"json_object\" },\n messages: [\n { role: \"system\", content: CONSOLIDATE_SYSTEM_PROMPT },\n { role: \"user\", content: userContent },\n ],\n temperature: 0.2,\n }),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n const errBody = await res.text().catch(() => \"\");\n throw new Error(\n `LLM API 错误 (${res.status}): ${errBody.slice(0, 300)}`,\n );\n }\n\n const data = (await res.json()) as {\n choices?: Array<{ message?: { content?: string } }>;\n };\n const rawContent = data.choices?.[0]?.message?.content;\n\n if (!rawContent) {\n throw new Error(\"LLM 返回内容为空\");\n }\n\n // 解析 JSON\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawContent);\n } catch {\n throw new Error(\"LLM 返回内容不是合法 JSON\");\n }\n\n return validateAndNormalizeLlmResult(parsed);\n } finally {\n clearTimeout(timeout);\n }\n}\n\n// ─── 格式化 user message ─────────────────────\n\nfunction formatUserMessage(input: LlmConsolidateInput): string {\n // 截断 session 内容避免过长(保留前 8000 字符)\n const maxSessionChars = 8000;\n const truncatedSessions = input.pendingSessions.map((s) => ({\n ...s,\n content:\n s.content.length > maxSessionChars\n ? s.content.slice(0, maxSessionChars) +\n `\\n\\n... [截断,原始长度: ${s.content.length} 字符]`\n : s.content,\n }));\n\n return JSON.stringify(\n {\n pendingSessions: truncatedSessions,\n existingKnowledge: input.existingKnowledge.map((k) => ({\n path: k.path,\n title: k.title,\n type: k.type,\n domain: k.domain,\n status: k.status,\n summary: k.summary,\n })),\n currentMemoryMd: input.currentMemoryMd ?? \"\",\n },\n null,\n 2,\n );\n}\n\n// ─── 验证 & 标准化 LLM 返回结果 ───────────────\n\nfunction validateAndNormalizeLlmResult(\n raw: unknown,\n): LlmConsolidateResult {\n if (!raw || typeof raw !== \"object\") {\n throw new Error(\"LLM 返回格式错误:期望 JSON 对象\");\n }\n\n const obj = raw as Record<string, unknown>;\n\n const knowledgeFiles: KnowledgeFileOutput[] = Array.isArray(obj.knowledgeFiles)\n ? (obj.knowledgeFiles as unknown[]).map(normalizeKnowledgeFile).filter(Boolean) as KnowledgeFileOutput[]\n : [];\n\n const memoryMd =\n typeof obj.memoryMd === \"string\"\n ? obj.memoryMd\n : \"# 项目知识库\\n\\n> 待 consolidate\";\n\n const skippedSessions: Array<{ sessionId: string; reason: string }> = Array.isArray(\n obj.skippedSessions,\n )\n ? (obj.skippedSessions as unknown[]).filter(isSkippedEntry)\n : [];\n\n return { knowledgeFiles, memoryMd, skippedSessions };\n}\n\nfunction normalizeKnowledgeFile(raw: unknown): KnowledgeFileOutput | null {\n if (!raw || typeof raw !== \"object\") return null;\n const obj = raw as Record<string, unknown>;\n\n if (\n typeof obj.targetPath !== \"string\" ||\n ![\"create\", \"update\"].includes(obj.action as string) ||\n typeof obj.body !== \"string\"\n ) {\n return null;\n }\n\n return {\n targetPath: obj.targetPath,\n action: obj.action as \"create\" | \"update\",\n frontmatter:\n typeof obj.frontmatter === \"object\" && obj.frontmatter !== null\n ? (obj.frontmatter as Record<string, unknown>)\n : {},\n body: obj.body as string,\n };\n}\n\nfunction isSkippedEntry(raw: unknown): raw is { sessionId: string; reason: string } {\n if (!raw || typeof raw !== \"object\") return false;\n const obj = raw as Record<string, unknown>;\n return (\n typeof obj.sessionId === \"string\" && typeof obj.reason === \"string\"\n );\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { KnowledgeFileOutput } from \"./llmConsolidateV2.js\";\n\n// ─── Types ────────────────────────────────────\n\nexport interface WriteKnowledgeResult {\n created: string[];\n updated: string[];\n failed: string[];\n}\n\n// ─── 写入知识文件 ─────────────────────────────\n\n/**\n * 将 LLM 返回的 knowledgeFiles 数组写入磁盘。\n *\n * - targetPath 相对于 .memory/ 根目录\n * - 自动创建所需子目录\n * - action=\"create\" 仅在新文件时写入\n * - action=\"update\" 总是覆盖\n */\nexport function writeKnowledgeFiles(\n repoRoot: string,\n files: KnowledgeFileOutput[],\n): WriteKnowledgeResult {\n const result: WriteKnowledgeResult = {\n created: [],\n updated: [],\n failed: [],\n };\n\n for (const kf of files) {\n try {\n const absolutePath = memoryPath(repoRoot, kf.targetPath);\n const dir = dirname(absolutePath);\n\n mkdirSync(dir, { recursive: true });\n\n // 序列化 frontmatter + body\n const content = serializeKnowledgeFile(kf.frontmatter, kf.body);\n\n const alreadyExists = existsSync(absolutePath);\n\n if (kf.action === \"create\" && alreadyExists) {\n // create 但已存在,降级为 update\n result.updated.push(kf.targetPath);\n } else if (kf.action === \"create\") {\n result.created.push(kf.targetPath);\n } else {\n result.updated.push(kf.targetPath);\n }\n\n writeFileSync(absolutePath, content, \"utf8\");\n } catch (err) {\n result.failed.push(kf.targetPath);\n console.error(\n `[consolidate] 写入知识文件失败: ${kf.targetPath}: ${(err as Error).message}`,\n );\n }\n }\n\n return result;\n}\n\n// ─── 写入 MEMORY.md ──────────────────────────\n\n/**\n * 将 LLM 生成的 MEMORY.md 写入磁盘。\n * 保留用户自定义编辑标记 <!-- user-edit-start --> ... <!-- user-edit-end -->\n */\nexport function writeMemoryMd(\n repoRoot: string,\n memoryMd: string,\n): void {\n const memoryPathAbs = memoryPath(repoRoot, \"MEMORY.md\");\n\n // 如果已有文件且包含用户编辑标记,尝试保留用户自定义区域\n if (existsSync(memoryPathAbs)) {\n const existing = readFileSync(memoryPathAbs, \"utf8\");\n const preserved = extractUserEditedSections(existing);\n if (preserved.length > 0) {\n memoryMd = injectUserSections(memoryMd, preserved);\n }\n }\n\n mkdirSync(memoryPath(repoRoot), { recursive: true });\n writeFileSync(memoryPathAbs, `${memoryMd}\\n`, \"utf8\");\n}\n\n// ─── 序列化知识文件 ─────────────────────────\n\nfunction serializeKnowledgeFile(\n frontmatter: Record<string, unknown>,\n body: string,\n): string {\n const lines = [\"---\"];\n\n // 固定顺序输出常用字段\n const fieldOrder = [\"title\", \"domain\", \"type\", \"status\", \"confidence\", \"lastReviewed\"];\n const emitted = new Set<string>();\n\n for (const key of fieldOrder) {\n if (key in frontmatter && frontmatter[key] !== undefined && frontmatter[key] !== null) {\n lines.push(`${key}: ${formatYamlValue(frontmatter[key])}`);\n emitted.add(key);\n }\n }\n\n // sourceSessions 数组特殊处理\n if (Array.isArray(frontmatter.sourceSessions)) {\n lines.push(\"sourceSessions:\");\n for (const s of frontmatter.sourceSessions) {\n lines.push(` - ${s}`);\n }\n emitted.add(\"sourceSessions\");\n }\n\n // 其余字段\n for (const [key, val] of Object.entries(frontmatter)) {\n if (!emitted.has(key) && val !== undefined && val !== null) {\n lines.push(`${key}: ${formatYamlValue(val)}`);\n }\n }\n\n lines.push(\"---\", \"\", body);\n\n return lines.join(\"\\n\");\n}\n\nfunction formatYamlValue(val: unknown): string {\n if (Array.isArray(val)) {\n return `[${val.map(String).join(\", \")}]`;\n }\n return String(val);\n}\n\n// ─── 用户编辑区保留 ──────────────────────────\n\ninterface UserSection {\n marker: string;\n content: string;\n}\n\n/** 提取 <!-- user-edit-start --> ... <!-- user-edit-end --> 区块 */\nfunction extractUserEditedSections(content: string): UserSection[] {\n const sections: UserSection[] = [];\n const regex = /<!--\\s*user-edit-start\\s*-->\\n?([\\s\\S]*?)\\n?<!--\\s*user-edit-end\\s*-->/g;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(content)) !== null) {\n sections.push({\n marker: match[0].split(\"\\n\")[0], // 取开始标记行\n content: match[1],\n });\n }\n return sections;\n}\n\n/** 将用户编辑区注入到新内容中同名的标记位置 */\nfunction injectUserSections(\n newContent: string,\n sections: UserSection[],\n): string {\n let result = newContent;\n for (const section of sections) {\n // 用原有内容替换同名标记区块\n const startMarker = section.marker;\n const endMarker = \"<!-- user-edit-end -->\";\n\n const startIdx = result.indexOf(startMarker);\n if (startIdx === -1) continue;\n\n const endIdx = result.indexOf(endMarker, startIdx);\n if (endIdx === -1) continue;\n\n result =\n result.slice(0, startIdx) +\n `${startMarker}\\n${section.content}\\n${endMarker}` +\n result.slice(endIdx + endMarker.length);\n }\n return result;\n}\n","import { existsSync, mkdirSync, renameSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { SessionFileFrontmatter } from \"../capture/writeCapture.js\";\nimport type { ScannedSession } from \"./sessionScanner.js\";\n\n/**\n * 将符合条件的已处理 capture 文件从 raw/ 移动到 archived/\n *\n * 条件:\n * - status === \"done\"\n * - consolidatedAt 距今超过 autoArchiveDays 天(默认 30)\n */\nexport function archiveDoneSessions(\n repoRoot: string,\n sessions: ScannedSession[],\n autoArchiveDays: number = 30,\n): number {\n const archivedDir = memoryPath(repoRoot, \"captures\", \"archived\");\n const cutoffMs = Date.now() - autoArchiveDays * 24 * 60 * 60 * 1000;\n\n let archivedCount = 0;\n\n for (const s of sessions) {\n if (s.frontmatter.status !== \"done\") continue;\n if (!s.frontmatter.consolidatedAt) continue;\n\n const consolidatedTime = Date.parse(s.frontmatter.consolidatedAt);\n if (Number.isNaN(consolidatedTime)) continue;\n if (consolidatedTime > cutoffMs) continue; // 还没过期\n\n try {\n mkdirSync(archivedDir, { recursive: true });\n renameSync(s.absolutePath, join(archivedDir, s.filename));\n archivedCount++;\n } catch {\n // 忽略移动失败(可能文件已被其他进程删除)\n }\n }\n\n return archivedCount;\n}\n","import { debugLog } from \"../config/debugLog.js\";\nimport { type HermesConfig, type LlmConfigV2, type RepoContext } from \"../config/types.js\";\nimport {\n readConsolidateState,\n releaseConsolidateLock,\n writeConsolidateLock,\n writeConsolidateState,\n} from \"./state.js\";\nimport { scanAllSessions, filterPendingSessions, type ScannedSession } from \"./sessionScanner.js\";\nimport {\n buildLlmConsolidateInput,\n callLlmConsolidate,\n} from \"./llmConsolidateV2.js\";\nimport { writeKnowledgeFiles, writeMemoryMd } from \"./writeKnowledge.js\";\nimport { archiveDoneSessions } from \"./archive.js\";\nimport { markSessionConsolidated } from \"../capture/writeCapture.js\";\n\n// ─── Options & Result ────────────────────────\n\nexport interface RunConsolidateOptions {\n repoRoot: string;\n config: HermesConfig;\n force?: boolean;\n dryRun?: boolean;\n debug?: boolean;\n}\n\nexport interface ConsolidateResultV2 {\n ran: boolean;\n reason?: string;\n sessionsProcessed: number; // 处理的 session 文件数\n knowledgeCreated: number; // 新建知识文件数\n knowledgeUpdated: number; // 更新知识文件数\n skippedCount: number; // 跳过的 session 数\n archived: number; // 归档的文件数\n}\n\n// ─── Main orchestrator ───────────────────────\n\n/**\n * v2 consolidate 主函数:\n *\n * 1. 扫描 captures/raw/ 中 pending/stale 的 session 文件\n * 2. 构造 LLM 输入(sessions + 已有知识 + MEMORY.md)\n * 3. 单次 LLM 调用 → 知识文件 + MEMORY.md\n * 4. 写入磁盘(knowledge files + MEMORY.md)\n * 5. 更新 session 状态 → done\n * 6. 自动归档过期 done 文件\n */\nexport async function runConsolidate(\n opts: RunConsolidateOptions,\n): Promise<ConsolidateResultV2> {\n const { repoRoot, config, force, dryRun, debug } = opts;\n\n writeConsolidateLock(repoRoot);\n try {\n const llmConfig: LlmConfigV2 = config.llm;\n\n if (!llmConfig.enabled) {\n return {\n ran: false,\n reason: \"llm-not-enabled\",\n sessionsProcessed: 0,\n knowledgeCreated: 0,\n knowledgeUpdated: 0,\n skippedCount: 0,\n archived: 0,\n };\n }\n\n // Step 1: 扫描 session 文件\n const allSessions = scanAllSessions(repoRoot);\n const pendingSessions = force\n ? allSessions\n : filterPendingSessions(allSessions);\n\n debugLog(\n debug === true,\n \"consolidate\",\n `扫描到 ${allSessions.length} 个 session,其中 ${pendingSessions.length} 个待处理`,\n );\n\n if (pendingSessions.length === 0 && !force) {\n return {\n ran: false,\n reason: \"no-pending-sessions\",\n sessionsProcessed: 0,\n knowledgeCreated: 0,\n knowledgeUpdated: 0,\n skippedCount: 0,\n archived: 0,\n };\n }\n\n // dry-run:只返回预览信息\n if (dryRun) {\n return {\n ran: true,\n reason: \"dry-run\",\n sessionsProcessed: pendingSessions.length,\n knowledgeCreated: 0,\n knowledgeUpdated: 0,\n skippedCount: 0,\n archived: 0,\n };\n }\n\n // Step 2: 构造 LLM 输入\n const llmInput = buildLlmConsolidateInput(repoRoot, pendingSessions);\n debugLog(debug === true, \"consolidate\", `LLM 输入: ${llmInput.pendingSessions.length} sessions, ${llmInput.existingKnowledge.length} existing knowledge`);\n\n // Step 3: 单次 LLM 调用\n let llmResult;\n try {\n llmResult = await callLlmConsolidate(llmInput, llmConfig);\n } catch (err) {\n console.error(`[consolidate] LLM 调用失败: ${(err as Error).message}`);\n throw err;\n }\n\n debugLog(\n debug === true,\n \"consolidate\",\n `LLM 返回: ${llmResult.knowledgeFiles.length} knowledge files, ${llmResult.skippedSessions.length} skipped`,\n );\n\n // Step 4: 写入知识文件 + MEMORY.md\n const writeResult = writeKnowledgeFiles(repoRoot, llmResult.knowledgeFiles);\n writeMemoryMd(repoRoot, llmResult.memoryMd);\n\n // Step 5: 更新 session 状态为 done\n const processedSessionIds = new Set<string>();\n for (const s of pendingSessions) {\n markSessionConsolidated(repoRoot, s.sessionId);\n processedSessionIds.add(s.sessionId);\n }\n // 也标记 skipped 的 session 为 done(已评估过)\n for (const ss of llmResult.skippedSessions) {\n markSessionConsolidated(repoRoot, ss.sessionId);\n processedSessionIds.add(ss.sessionId);\n }\n\n // Step 6: 更新 consolidate-state.json\n const prevState = readConsolidateState(repoRoot);\n const newDomains = extractDomainsFromResults(llmResult.knowledgeFiles);\n\n writeConsolidateState(repoRoot, {\n version: 2,\n lastConsolidatedAt: new Date().toISOString(),\n stats: {\n totalCapturesProcessed:\n prevState.stats.totalCapturesProcessed +\n pendingSessions.reduce((sum, s) => sum + s.frontmatter.captureCount, 0),\n domains: [...new Set([...prevState.stats.domains, ...newDomains])],\n knowledgeFilesCreated:\n prevState.stats.knowledgeFilesCreated +\n writeResult.created.length,\n },\n processedSessions: {\n ...prevState.processedSessions,\n ...Object.fromEntries(\n [...processedSessionIds].map((id) => [\n id,\n { status: \"done\" as const, consolidatedAt: new Date().toISOString(), lastCaptureAt: new Date().toISOString() },\n ]),\n ),\n },\n });\n\n // Step 7: 自动归档\n const archived = archiveDoneSessions(\n repoRoot,\n allSessions,\n config.consolidate.autoArchiveDays,\n );\n\n return {\n ran: true,\n sessionsProcessed: pendingSessions.length,\n knowledgeCreated: writeResult.created.length,\n knowledgeUpdated: writeResult.updated.length,\n skippedCount: llmResult.skippedSessions.length,\n archived,\n };\n } finally {\n releaseConsolidateLock(repoRoot);\n }\n}\n\n// ─── Helpers ─────────────────────────────────\n\n/** 从 LLM 返回结果中提取所有涉及到的域名 */\nfunction extractDomainsFromResults(\n files: Array<{ frontmatter: Record<string, unknown> }>,\n): string[] {\n const domains = new Set<string>();\n for (const f of files) {\n const domain = f.frontmatter.domain;\n if (typeof domain === \"string\" && domain && domain !== \"null\") {\n domains.add(domain);\n }\n }\n return [...domains];\n}\n","/** 运行锁过期(毫秒) */\nexport const CONSOLIDATE_LOCK_TTL_MS = 30 * 60 * 1000;\n","import { debugLog } from \"../config/debugLog.js\";\nimport { effectiveLlmMode, isLlmAvailable } from \"../config/llmConfig.js\";\nimport { readConfigAtRepo } from \"../config/readConfig.js\";\nimport type { AssistantId } from \"../init/assistants/types.js\";\nimport { enqueueLlmJob } from \"./enqueueLlmJob.js\";\nimport { llmFormat, simpleFormat } from \"./formatCapture.js\";\nimport { needsLlm } from \"./needsLlm.js\";\nimport type { CaptureResult } from \"./types.js\";\nimport { maybeScheduleConsolidate } from \"../consolidate/scheduleConsolidate.js\";\nimport {\n appendCaptureToSession,\n} from \"./writeCapture.js\";\nimport type { ParsedSession } from \"./types.js\";\n\nfunction finishCapture(\n repoRoot: string,\n debug: boolean | undefined,\n result: CaptureResult,\n): CaptureResult {\n if (result.written) {\n maybeScheduleConsolidate({ repoRoot, debug });\n }\n return result;\n}\n\nexport interface CommitCaptureOptions {\n repoRoot: string;\n session: ParsedSession;\n jsonlPath: string;\n assistant: AssistantId;\n dryRun?: boolean;\n debug?: boolean;\n}\n\nexport async function commitCapture(\n opts: CommitCaptureOptions,\n): Promise<CaptureResult> {\n const { repoRoot, session, jsonlPath, assistant, dryRun, debug } = opts;\n const formatted = simpleFormat(session, assistant);\n\n if (dryRun) {\n debugLog(\n debug === true,\n \"capture\",\n `[dry-run] would capture session=${session.sessionId} from ${jsonlPath}`,\n );\n return { written: false, reason: \"dry-run\", jsonlPath };\n }\n\n // v2: 使用 session 聚合模式写入\n const result = appendCaptureToSession(repoRoot, formatted);\n const captureFile = result.relativePath;\n\n // v2: 不再维护 sessions/index.json\n\n const llm = readConfigAtRepo(repoRoot)?.llm ?? null;\n if (!isLlmAvailable(llm) || !needsLlm(session)) {\n debugLog(debug === true, \"capture\", `ok: ${captureFile} (format=simple)`);\n return finishCapture(repoRoot, debug, {\n written: true,\n capturePath: captureFile,\n jsonlPath,\n });\n }\n\n const mode = effectiveLlmMode(llm!);\n if (mode === \"sync\") {\n const upgraded = await llmFormat(session, assistant, llm!);\n if (upgraded) {\n // v2: LLM upgrade 后重新追加到同一 session 文件(覆盖最后一个 capture 段落)\n // 简化处理:当前暂不实现 LLM in-place upgrade,后续在 Phase 2 完善\n debugLog(debug === true, \"capture\", `ok: ${captureFile} (format=llm-sync)`);\n return finishCapture(repoRoot, debug, {\n written: true,\n capturePath: captureFile,\n jsonlPath,\n });\n }\n debugLog(debug === true, \"capture\", `ok: ${captureFile} (format=simple, llm-fallback)`);\n return finishCapture(repoRoot, debug, {\n written: true,\n capturePath: captureFile,\n jsonlPath,\n });\n }\n\n const enqueued = enqueueLlmJob({\n repoRoot,\n sessionId: session.sessionId,\n jsonlPath,\n captureFile,\n assistant,\n debug,\n });\n if (enqueued) {\n debugLog(debug === true, \"capture\", `ok: ${captureFile} (format=simple, llm-enqueued)`);\n } else {\n debugLog(debug === true, \"capture\", `ok: ${captureFile} (format=simple, llm-skip-enqueue)`);\n }\n\n return finishCapture(repoRoot, debug, {\n written: true,\n capturePath: captureFile,\n jsonlPath,\n });\n}\n","import { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\n\n/** Claude Code:项目目录名 = 绝对路径将 `/` 替换为 `-`(见官方 ~/.claude/projects/) */\nexport function encodeClaudeProjectDir(absPath: string): string {\n return resolve(absPath).replace(/\\//g, \"-\");\n}\n\nexport interface ResolveSessionOptions {\n /** Claude Stop hook stdin JSON 的 transcript_path(官方首选) */\n transcriptPath?: string;\n cwd?: string;\n}\n\n/**\n * 解析 Claude Code 会话 JSONL 路径。\n * 依据 https://code.claude.com/docs/en/claude-directory#application-data\n *\n * 优先级:\n * 1. HERMES_SESSION_JSONL(测试 / 手动覆盖)\n * 2. transcriptPath(hook stdin 的 transcript_path)\n * 3. ~/.claude/projects/<encoded-cwd>/*.jsonl(当前仓库)\n * 4. 全局 projects 下最新 .jsonl(含旧版 sessions 子目录回退)\n */\nexport function resolveSessionJsonlPath(\n repoRoot: string,\n options: ResolveSessionOptions = {},\n): string | null {\n const override = process.env.HERMES_SESSION_JSONL;\n if (override && existsSync(override)) {\n return resolve(override);\n }\n\n const fromHook = options.transcriptPath;\n if (fromHook && existsSync(fromHook)) {\n return resolve(fromHook);\n }\n\n const sessionId =\n process.env.CLAUDE_SESSION_ID ??\n process.env.CLAUDE_CODE_SESSION_ID ??\n process.env.SESSION_ID;\n\n const claudeHome = process.env.CLAUDE_CONFIG_DIR\n ? resolve(process.env.CLAUDE_CONFIG_DIR)\n : join(homedir(), \".claude\");\n const projectsRoot = join(claudeHome, \"projects\");\n if (!existsSync(projectsRoot)) {\n return null;\n }\n\n const cwd = resolve(options.cwd ?? repoRoot);\n const preferredProjectDir = encodeClaudeProjectDir(cwd);\n const preferredPath = join(projectsRoot, preferredProjectDir);\n if (existsSync(preferredPath)) {\n const hit = pickNewestJsonl(preferredPath, sessionId);\n if (hit) {\n return hit;\n }\n const legacySessions = join(preferredPath, \"sessions\");\n if (existsSync(legacySessions)) {\n const legacyHit = pickNewestJsonl(legacySessions, sessionId);\n if (legacyHit) {\n return legacyHit;\n }\n }\n }\n\n const candidates: Array<{ path: string; mtime: number }> = [];\n\n for (const projectDir of readdirSync(projectsRoot, { withFileTypes: true })) {\n if (!projectDir.isDirectory()) continue;\n const projectPath = join(projectsRoot, projectDir.name);\n collectJsonlCandidates(projectPath, sessionId, candidates);\n const legacySessions = join(projectPath, \"sessions\");\n if (existsSync(legacySessions)) {\n collectJsonlCandidates(legacySessions, sessionId, candidates);\n }\n }\n\n if (candidates.length === 0) {\n return null;\n }\n\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\n/** @deprecated 使用 readHookInputSync;保留兼容测试与旧调用 */\nexport function readHookTranscriptPathSync(): string | null {\n if (process.stdin.isTTY) {\n return null;\n }\n try {\n const raw = readFileSync(0, \"utf8\").trim();\n if (!raw) {\n return null;\n }\n const parsed = JSON.parse(raw) as { transcript_path?: unknown };\n const p = parsed.transcript_path;\n if (typeof p === \"string\" && existsSync(p)) {\n return resolve(p);\n }\n } catch {\n return null;\n }\n return null;\n}\n\nfunction pickNewestJsonl(\n dir: string,\n sessionId: string | undefined,\n): string | null {\n const candidates: Array<{ path: string; mtime: number }> = [];\n collectJsonlCandidates(dir, sessionId, candidates);\n if (candidates.length === 0) {\n return null;\n }\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\nfunction collectJsonlCandidates(\n dir: string,\n sessionId: string | undefined,\n out: Array<{ path: string; mtime: number }>,\n): void {\n if (!existsSync(dir)) {\n return;\n }\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) {\n continue;\n }\n const fullPath = join(dir, entry.name);\n if (\n sessionId &&\n !entry.name.includes(sessionId) &&\n basename(entry.name, \".jsonl\") !== sessionId\n ) {\n continue;\n }\n try {\n const st = statSync(fullPath);\n out.push({ path: fullPath, mtime: st.mtimeMs });\n } catch {\n // skip\n }\n }\n}\n","import { commitCapture } from \"../commitCapture.js\";\nimport type { CaptureResult } from \"../types.js\";\nimport { parseJsonlFile } from \"./parseJsonl.js\";\nimport { resolveSessionJsonlPath } from \"./resolveSession.js\";\n\nexport async function runClaudeCodeCapture(\n repoRoot: string,\n cwd?: string,\n dryRun?: boolean,\n options?: { transcriptPath?: string; debug?: boolean },\n): Promise<CaptureResult> {\n const jsonlPath = resolveSessionJsonlPath(repoRoot, {\n cwd,\n transcriptPath: options?.transcriptPath,\n });\n if (!jsonlPath) {\n return { written: false, reason: \"no session jsonl found\" };\n }\n\n // v2: 始终捕获(去掉 shouldCapture 质量过滤)\n const session = parseJsonlFile(jsonlPath);\n\n return commitCapture({\n repoRoot,\n session,\n jsonlPath,\n assistant: \"claude-code\",\n dryRun,\n debug: options?.debug,\n });\n}\n","import { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\n\n/**\n * CodeBuddy 项目目录名:绝对路径去掉 leading `/`,再将 `/` 换为 `-`。\n * 例:`/Users/you/proj` → `Users-you-proj`(与 Cursor 一致,非 Claude leading `-`)\n */\nexport function encodeCodebuddyProjectDir(absPath: string): string {\n return resolve(absPath).replace(/^\\//, \"\").replace(/\\//g, \"-\");\n}\n\nexport interface ResolveCodebuddySessionOptions {\n repoRoot: string;\n cwd?: string;\n transcriptPath?: string;\n}\n\n/**\n * 解析 CodeBuddy 会话 JSONL。\n *\n * 优先级:\n * 1. HERMES_CODEBUDDY_SESSION\n * 2. transcriptPath(hook stdin)\n * 3. ~/.codebuddy/projects/<encoded-cwd> 下最新 .jsonl(含子目录)\n */\nexport function resolveCodebuddySessionJsonl(\n options: ResolveCodebuddySessionOptions,\n): string | null {\n const override = process.env.HERMES_CODEBUDDY_SESSION;\n if (override && existsSync(override)) {\n return resolve(override);\n }\n\n const fromHook = options.transcriptPath;\n if (fromHook && existsSync(fromHook)) {\n return resolve(fromHook);\n }\n\n const sessionId =\n process.env.CODEBUDDY_SESSION_ID ?? process.env.SESSION_ID;\n\n const codebuddyHome = process.env.CODEBUDDY_CONFIG_DIR\n ? resolve(process.env.CODEBUDDY_CONFIG_DIR)\n : join(homedir(), \".codebuddy\");\n const projectsRoot = join(codebuddyHome, \"projects\");\n if (!existsSync(projectsRoot)) {\n return null;\n }\n\n const cwd = resolve(options.cwd ?? options.repoRoot);\n const preferredProjectDir = encodeCodebuddyProjectDir(cwd);\n const preferredPath = join(projectsRoot, preferredProjectDir);\n if (existsSync(preferredPath)) {\n const hit = pickNewestJsonlRecursive(preferredPath, sessionId);\n if (hit) {\n return hit;\n }\n }\n\n const candidates: Array<{ path: string; mtime: number }> = [];\n for (const projectDir of readdirSync(projectsRoot, { withFileTypes: true })) {\n if (!projectDir.isDirectory()) {\n continue;\n }\n collectJsonlRecursive(join(projectsRoot, projectDir.name), sessionId, candidates);\n }\n\n if (candidates.length === 0) {\n return null;\n }\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\nfunction pickNewestJsonlRecursive(\n dir: string,\n sessionId: string | undefined,\n): string | null {\n const candidates: Array<{ path: string; mtime: number }> = [];\n collectJsonlRecursive(dir, sessionId, candidates);\n if (candidates.length === 0) {\n return null;\n }\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\nfunction collectJsonlRecursive(\n dir: string,\n sessionId: string | undefined,\n out: Array<{ path: string; mtime: number }>,\n): void {\n if (!existsSync(dir)) {\n return;\n }\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n collectJsonlRecursive(full, sessionId, out);\n continue;\n }\n if (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) {\n continue;\n }\n if (\n sessionId &&\n !entry.name.includes(sessionId) &&\n basename(entry.name, \".jsonl\") !== sessionId\n ) {\n continue;\n }\n try {\n const st = statSync(full);\n out.push({ path: full, mtime: st.mtimeMs });\n } catch {\n // skip\n }\n }\n}\n","import { commitCapture } from \"../commitCapture.js\";\nimport type { CaptureResult } from \"../types.js\";\nimport { parseJsonlFile } from \"../claude-code/parseJsonl.js\";\nimport { resolveCodebuddySessionJsonl } from \"./resolveSession.js\";\n\nexport async function runCodebuddyCapture(\n repoRoot: string,\n cwd?: string,\n dryRun?: boolean,\n options?: { transcriptPath?: string; debug?: boolean },\n): Promise<CaptureResult> {\n const jsonlPath = resolveCodebuddySessionJsonl({\n repoRoot,\n cwd,\n transcriptPath: options?.transcriptPath,\n });\n if (!jsonlPath) {\n return { written: false, reason: \"no codebuddy session found\" };\n }\n\n // v2: 始终捕获(去掉 shouldCapture 质量过滤),由 LLM 在 consolidate 时判断价值\n const session = parseJsonlFile(jsonlPath);\n if (session.messages.length <= 1 && session.toolCalls === 0) {\n return {\n written: false,\n reason: \"empty session (no messages or tool calls)\",\n jsonlPath,\n };\n }\n\n return commitCapture({\n repoRoot,\n session,\n jsonlPath,\n assistant: \"codebuddy\",\n dryRun,\n debug: options?.debug,\n });\n}\n","import { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport type { HookInput } from \"../hookInput.js\";\n\n/**\n * Cursor 项目目录名:绝对路径去掉 leading `/`,再将 `/` 换为 `-`。\n * 例:`/Users/you/proj` → `Users-you-proj`\n * (与 Claude `encodeClaudeProjectDir` 的 leading `-` 不同)\n */\nexport function encodeCursorProjectDir(absPath: string): string {\n return resolve(absPath).replace(/^\\//, \"\").replace(/\\//g, \"-\");\n}\n\nexport interface ResolveCursorSessionOptions {\n repoRoot: string;\n cwd?: string;\n hookInput?: HookInput | null;\n}\n\n/**\n * 解析 Cursor Agent 会话 JSONL。\n *\n * 优先级:\n * 1. HERMES_CURSOR_SESSION(测试 / 手动)\n * 2. hook session_id → ~/.cursor/projects/<encoded>/agent-transcripts/<id>/<id>.jsonl\n * 3. workspace_roots[0] 或 repoRoot 对应项目下最新 transcript\n */\nexport function resolveCursorSessionJsonl(\n options: ResolveCursorSessionOptions,\n): string | null {\n const override = process.env.HERMES_CURSOR_SESSION;\n if (override && existsSync(override)) {\n return resolve(override);\n }\n\n const cursorHome = process.env.CURSOR_CONFIG_DIR\n ? resolve(process.env.CURSOR_CONFIG_DIR)\n : join(homedir(), \".cursor\");\n const projectsRoot = join(cursorHome, \"projects\");\n if (!existsSync(projectsRoot)) {\n return null;\n }\n\n const sessionId =\n options.hookInput?.sessionId ??\n options.hookInput?.conversationId ??\n process.env.CURSOR_SESSION_ID ??\n process.env.CURSOR_AGENT_SESSION_ID;\n\n const workspace =\n options.hookInput?.workspaceRoots?.[0] ??\n (options.cwd ? resolve(options.cwd) : resolve(options.repoRoot));\n\n const encoded = encodeCursorProjectDir(workspace);\n const projectDir = join(projectsRoot, encoded);\n const transcriptsRoot = join(projectDir, \"agent-transcripts\");\n\n if (!existsSync(transcriptsRoot)) {\n return pickNewestCursorJsonl(projectsRoot);\n }\n\n if (sessionId) {\n const direct = join(transcriptsRoot, sessionId, `${sessionId}.jsonl`);\n if (existsSync(direct)) {\n return direct;\n }\n const nested = findJsonlUnderDir(join(transcriptsRoot, sessionId), sessionId);\n if (nested) {\n return nested;\n }\n }\n\n return pickNewestCursorJsonl(transcriptsRoot);\n}\n\nfunction findJsonlUnderDir(dir: string, sessionId: string): string | null {\n if (!existsSync(dir)) {\n return null;\n }\n const direct = join(dir, `${sessionId}.jsonl`);\n if (existsSync(direct)) {\n return direct;\n }\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.isFile() && entry.name.endsWith(\".jsonl\")) {\n return join(dir, entry.name);\n }\n if (entry.isDirectory()) {\n const found = findJsonlUnderDir(join(dir, entry.name), sessionId);\n if (found) {\n return found;\n }\n }\n }\n return null;\n}\n\nfunction pickNewestCursorJsonl(root: string): string | null {\n const candidates: Array<{ path: string; mtime: number }> = [];\n collectJsonlRecursive(root, candidates);\n if (candidates.length === 0) {\n return null;\n }\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\nfunction collectJsonlRecursive(\n dir: string,\n out: Array<{ path: string; mtime: number }>,\n): void {\n if (!existsSync(dir)) {\n return;\n }\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n collectJsonlRecursive(full, out);\n continue;\n }\n if (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) {\n continue;\n }\n try {\n const st = statSync(full);\n out.push({ path: full, mtime: st.mtimeMs });\n } catch {\n // skip\n }\n }\n}\n","import { commitCapture } from \"../commitCapture.js\";\nimport type { CaptureResult } from \"../types.js\";\nimport type { HookInput } from \"../hookInput.js\";\nimport { parseJsonlFile } from \"../claude-code/parseJsonl.js\";\nimport { resolveCursorSessionJsonl } from \"./resolveSession.js\";\n\nexport async function runCursorCapture(\n repoRoot: string,\n cwd?: string,\n dryRun?: boolean,\n options?: { hookInput?: HookInput | null; debug?: boolean },\n): Promise<CaptureResult> {\n if (\n options?.hookInput?.status === \"aborted\" &&\n !options.hookInput.sessionId\n ) {\n return { written: false, reason: \"cursor stop aborted\" };\n }\n\n const jsonlPath = resolveCursorSessionJsonl({\n repoRoot,\n cwd,\n hookInput: options?.hookInput,\n });\n if (!jsonlPath) {\n return { written: false, reason: \"no cursor session found\" };\n }\n\n // v2: 始终捕获(去掉 shouldCapture 质量过滤)\n const session = parseJsonlFile(jsonlPath);\n\n return commitCapture({\n repoRoot,\n session,\n jsonlPath,\n assistant: \"cursor\",\n dryRun,\n debug: options?.debug,\n });\n}\n","import type { RepoContext } from \"../config/types.js\";\nimport { runClaudeCodeCapture } from \"./claude-code/run.js\";\nimport { runCodebuddyCapture } from \"./codebuddy/run.js\";\nimport { runCursorCapture } from \"./cursor/run.js\";\nimport {\n isClaudeCaptureHook,\n isCodebuddyCaptureHook,\n isCursorCaptureHook,\n type HookInput,\n} from \"./hookInput.js\";\nimport type { CaptureResult } from \"./types.js\";\n\nexport async function routeCapture(\n ctx: RepoContext,\n options: {\n cwd?: string;\n dryRun?: boolean;\n transcriptPath?: string;\n hookInput?: HookInput | null;\n },\n): Promise<CaptureResult> {\n const assistants = ctx.config.assistants;\n const hasClaude = assistants.includes(\"claude-code\");\n const hasCursor = assistants.includes(\"cursor\");\n const hasCodebuddy = assistants.includes(\"codebuddy\");\n\n if (!hasClaude && !hasCursor && !hasCodebuddy) {\n return { written: false, reason: \"no capture assistant in config\" };\n }\n\n const hook = options.hookInput;\n const debug = ctx.config.debug === true;\n const codebuddyFromHook = isCodebuddyCaptureHook(hook);\n const claudeFromHook = isClaudeCaptureHook(hook);\n const cursorFromHook = isCursorCaptureHook(hook);\n\n if (codebuddyFromHook && hasCodebuddy) {\n return runCodebuddyCapture(ctx.repoRoot, options.cwd, options.dryRun, {\n transcriptPath: hook?.transcriptPath ?? options.transcriptPath,\n debug,\n });\n }\n\n if (claudeFromHook && hasClaude) {\n return runClaudeCodeCapture(ctx.repoRoot, options.cwd, options.dryRun, {\n transcriptPath: hook?.transcriptPath ?? options.transcriptPath,\n debug,\n });\n }\n\n if (cursorFromHook && hasCursor) {\n return runCursorCapture(ctx.repoRoot, options.cwd, options.dryRun, {\n hookInput: hook,\n debug,\n });\n }\n\n if (hasClaude) {\n const claudeResult = await runClaudeCodeCapture(\n ctx.repoRoot,\n options.cwd,\n options.dryRun,\n {\n transcriptPath: options.transcriptPath,\n debug,\n },\n );\n if (claudeResult.written) {\n return claudeResult;\n }\n if (!hasCursor && !hasCodebuddy) {\n return claudeResult;\n }\n }\n\n if (hasCursor) {\n const cursorResult = await runCursorCapture(\n ctx.repoRoot,\n options.cwd,\n options.dryRun,\n {\n hookInput: hook,\n debug,\n },\n );\n if (cursorResult.written) {\n return cursorResult;\n }\n if (!hasCodebuddy) {\n return cursorResult;\n }\n }\n\n if (hasCodebuddy) {\n return runCodebuddyCapture(ctx.repoRoot, options.cwd, options.dryRun, {\n transcriptPath: options.transcriptPath,\n debug,\n });\n }\n\n return { written: false, reason: \"no capture assistant in config\" };\n}\n","import { debugLog } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport type { HookInput } from \"./hookInput.js\";\nimport { routeCapture } from \"./router.js\";\nimport type { CaptureResult } from \"./types.js\";\n\nexport interface CaptureOptions {\n cwd?: string;\n dryRun?: boolean;\n strict?: boolean;\n /** Claude Stop hook stdin 中的 transcript_path(兼容旧调用) */\n transcriptPath?: string;\n hookInput?: HookInput | null;\n}\n\nfunction logCaptureResult(debug: boolean, result: CaptureResult): void {\n if (!debug) {\n return;\n }\n if (result.written && result.capturePath) {\n debugLog(true, \"capture\", `ok: ${result.capturePath}`);\n return;\n }\n const parts = [result.reason ?? \"unknown\"];\n if (result.jsonlPath) {\n parts.push(`jsonl=${result.jsonlPath}`);\n }\n debugLog(true, \"capture\", `skip: ${parts.join(\", \")}`);\n}\n\nexport async function runCapture(\n options: CaptureOptions = {},\n): Promise<CaptureResult> {\n const ctx = loadRepoContext(options.cwd);\n if (!ctx) {\n return { written: false, reason: \"not initialized\" };\n }\n\n const result = await routeCapture(ctx, {\n cwd: options.cwd,\n dryRun: options.dryRun,\n transcriptPath: options.transcriptPath,\n hookInput: options.hookInput,\n });\n logCaptureResult(ctx.config.debug, result);\n return result;\n}\n","import { readHookInputSync, isCodebuddyCaptureHook } from \"../capture/hookInput.js\";\nimport { runCapture } from \"../capture/runCapture.js\";\nimport { configureDebugLogging, debugLog } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { finalizeHookCommand } from \"../hookExit.js\";\n\nexport interface CaptureCommandOptions {\n cwd?: string;\n dryRun?: boolean;\n strict?: boolean;\n}\n\nexport function runCaptureCommand(opts: CaptureCommandOptions): void {\n const ctx = loadRepoContext(opts.cwd);\n const debug = ctx?.config.debug === true;\n configureDebugLogging(ctx?.repoRoot ?? null, debug);\n const hookInput = readHookInputSync();\n\n if (hookInput && isCodebuddyCaptureHook(hookInput)) {\n const stdinPath =\n hookInput.transcriptPathRaw ??\n hookInput.transcriptPath ??\n \"(missing)\";\n debugLog(\n debug,\n \"capture\",\n `codebuddy stop stdin transcript_path=${stdinPath}`,\n );\n }\n\n finalizeHookCommand(async () => {\n await runCapture({\n cwd: opts.cwd,\n dryRun: opts.dryRun,\n strict: opts.strict,\n hookInput,\n transcriptPath: hookInput?.transcriptPath,\n });\n }, opts.strict, debug);\n}\n","import { hookExit } from \"../hookExit.js\";\nimport { runFlushCommand } from \"../consolidate/scheduleConsolidate.js\";\nimport type { ConsolidateResultV2 } from \"../consolidate/runConsolidate.js\";\n\nexport async function runFlushCommandCli(opts: {\n cwd?: string;\n force?: boolean;\n dryRun?: boolean;\n strict?: boolean;\n}): Promise<void> {\n try {\n const result = await runFlushCommand({\n cwd: opts.cwd,\n force: opts.force,\n dryRun: opts.dryRun,\n });\n\n if (result.ran) {\n if (result.reason === \"dry-run\") {\n console.error(\n `hermes-repo: dry-run would process ${result.sessionsProcessed} session(s)`,\n );\n } else {\n const parts: string[] = [];\n if (result.knowledgeCreated > 0)\n parts.push(`${result.knowledgeCreated} created`);\n if (result.knowledgeUpdated > 0)\n parts.push(`${result.knowledgeUpdated} updated`);\n if (result.skippedCount > 0)\n parts.push(`${result.skippedCount} skipped`);\n if (result.archived > 0)\n parts.push(`${result.archived} archived`);\n const suffix = parts.length > 0 ? `, ${parts.join(\", \")}` : \"\";\n\n console.error(\n `hermes-repo: consolidated ${result.sessionsProcessed} session(s)${suffix}`,\n );\n }\n } else {\n switch (result.reason) {\n case \"not-initialized\":\n console.error(\n \"hermes-repo flush: not initialized (.memory/config.json missing)\",\n );\n break;\n case \"llm-not-enabled\":\n console.error(\"hermes-repo flush: LLM not enabled in config.json\");\n break;\n case \"no-pending-sessions\":\n console.error(\"hermes-repo flush: no pending sessions to process\");\n break;\n default:\n console.error(`hermes-repo flush: ${result.reason ?? \"skipped\"}`);\n }\n }\n\n hookExit(0, opts.strict);\n } catch (err) {\n console.error(\n `hermes-repo flush: ${err instanceof Error ? err.message : String(err)}`,\n );\n hookExit(1, opts.strict);\n }\n}\n","import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { debugFromContext } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { memoryPath } from \"../init/paths.js\";\nimport { INJECT_MAX_CHARS } from \"./constants.js\";\n\n// ─── v2 两阶段注入 ─────────────────────────\n//\n// Phase 0: 注入 MEMORY.md 导航摘要 + rules/ 全部文件内容\n// AI 可按需 cat domains/workflows/decisions/incidents 具体文件\n\nexport interface InjectResult {\n injected: boolean;\n chars: number;\n}\n\n/**\n * v2 inject 主函数。\n *\n * 输出格式:\n * - Cursor hook: JSON {\"additional_context\": \"...\"}\n * - 其他: 纯文本 markdown 到 stdout\n *\n * 内容组成:\n * 1. MEMORY.md 导航摘要(项目知识库入口)\n * 2. 分隔线\n * 3. rules/ 目录下所有 .md 文件的完整内容\n */\nexport function runInject(\n cwd?: string,\n options?: { cursorHookOutput?: boolean },\n): InjectResult {\n const ctx = loadRepoContext(cwd);\n if (!ctx) {\n return { injected: false, chars: 0 };\n }\n\n const repoRoot = ctx.repoRoot;\n\n // 1. 读取 MEMORY.md 导航\n const memoryContent = readMemoryMd(repoRoot);\n // 2. 读取 rules/ 全文\n const rulesContent = readAllRules(repoRoot);\n\n if (!memoryContent && !rulesContent) {\n debugFromContext(ctx, \"inject\", \"skip: no MEMORY.md or rules/\");\n return { injected: false, chars: 0 };\n }\n\n // 组装注入内容\n const sections: string[] = [];\n\n if (memoryContent) {\n sections.push(memoryContent);\n }\n\n if (rulesContent) {\n sections.push(\n \"\",\n \"---\",\n \"\",\n \"> 以下为必读规则全文(每次会话均应遵守)\",\n \"\",\n rulesContent,\n );\n }\n\n let content = sections.join(\"\\n\");\n\n // 截断保护\n if (content.length > INJECT_MAX_CHARS) {\n content =\n `${content.slice(0, INJECT_MAX_CHARS)}\\n\\n...(truncated, total ${content.length} chars)`;\n }\n\n // 输出\n if (options?.cursorHookOutput) {\n process.stdout.write(\n `${JSON.stringify({ additional_context: content })}\\n`,\n );\n } else {\n process.stdout.write(content);\n if (!content.endsWith(\"\\n\")) {\n process.stdout.write(\"\\n\");\n }\n }\n\n debugFromContext(ctx, \"inject\", `ok: injected ${content.length} chars`);\n\n return { injected: true, chars: content.length };\n}\n\n// ─── Helpers ────────────────────────────────\n\nfunction memoryPathOnDisk(repoRoot: string): string {\n return memoryPath(repoRoot, \"MEMORY.md\");\n}\n\nfunction rulesPathOnDisk(repoRoot: string): string {\n return memoryPath(repoRoot, \"rules\");\n}\n\nfunction readMemoryMd(repoRoot: string): string | null {\n const path = memoryPathOnDisk(repoRoot);\n if (!existsSync(path)) return null;\n\n try {\n const content = readFileSync(path, \"utf8\");\n return content.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * 读取 rules/ 下所有 .md 文件,拼接为一个文档块。\n * 返回 null 如果目录不存在或无文件。\n */\nfunction readAllRules(repoRoot: string): string | null {\n const rulesDir = rulesPathOnDisk(repoRoot);\n let files: string[];\n try {\n files = readdirSync(rulesDir)\n .filter((f) => f.endsWith(\".md\"))\n .sort(); // 字母排序确保稳定顺序\n } catch {\n return null; // 目录不存在\n }\n\n if (files.length === 0) return null;\n\n const parts: string[] = [];\n for (const file of files) {\n try {\n const filePath = join(rulesDir, file);\n const content = readFileSync(filePath, \"utf8\").trim();\n if (!content) continue;\n\n // 每个规则文件加标题头\n parts.push(`### ${file}`, \"\", content, \"\");\n } catch {\n // 跳过无法读取的文件\n }\n }\n\n return parts.length > 0 ? parts.join(\"\\n\") : null;\n}\n","/** v2 两阶段注入:导航 + 规则全文,目标 ~8K chars(含 rules 全文) */\nexport const INJECT_MAX_CHARS = 8000;\n","import { isCursorInjectHook, readHookInputSync } from \"../capture/hookInput.js\";\nimport { configureDebugLogging } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { finalizeHookCommand } from \"../hookExit.js\";\nimport { runInject } from \"../inject/runInject.js\";\n\nexport interface InjectCommandOptions {\n cwd?: string;\n strict?: boolean;\n}\n\nexport function runInjectCommand(opts: InjectCommandOptions): void {\n const ctx = loadRepoContext(opts.cwd);\n const debug = ctx?.config.debug === true;\n configureDebugLogging(ctx?.repoRoot ?? null, debug);\n\n const hookInput = readHookInputSync();\n const cursorHookOutput = isCursorInjectHook(hookInput);\n\n finalizeHookCommand(() => {\n runInject(opts.cwd, { cursorHookOutput });\n }, opts.strict, debug);\n}\n","import { spawnSync } from \"node:child_process\";\nimport { resolve } from \"node:path\";\nimport {\n DEFAULT_ASSISTANT_IDS,\n parseToolsArg,\n validateAssistantSelection,\n} from \"./assistants/registry.js\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport { ensureMemoryTree } from \"./ensureDirs.js\";\nimport { mergeAssistants } from \"./mergeAssistants.js\";\nimport { mergeHermesGitignore } from \"./mergeGitignore.js\";\nimport type { InitCliOptions, InitReport, InitResolvedOptions } from \"./types.js\";\nimport { writeScaffoldFiles } from \"./writeScaffoldFile.js\";\nimport { gatherInitOptions } from \"./prompts.js\";\n\nexport function resolveTargetDir(cwd?: string): string {\n const targetDir = resolve(cwd ?? process.cwd());\n const gitCheck = spawnSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n cwd: targetDir,\n encoding: \"utf8\",\n });\n if (gitCheck.status !== 0) {\n console.warn(\n \"warn: 当前目录可能不是 Git 仓库,init 仍会继续(建议在有 git 的项目根目录执行)\",\n );\n }\n return targetDir;\n}\n\nfunction resolveSelectedAssistants(opts: InitCliOptions): AssistantId[] {\n if (opts.assistants) {\n validateAssistantSelection(opts.assistants);\n return opts.assistants;\n }\n if (opts.tools) {\n if (!opts.yes) {\n console.error(\"init --tools requires -y in non-interactive mode\");\n process.exit(1);\n }\n return parseToolsArg(opts.tools);\n }\n if (opts.yes) {\n return [...DEFAULT_ASSISTANT_IDS];\n }\n return [];\n}\n\nexport function printInitReport(report: InitReport): void {\n const created = report.files.filter((f) => f.action === \"created\");\n const skipped = report.files.filter((f) => f.action === \"skipped\");\n const overwritten = report.files.filter((f) => f.action === \"overwritten\");\n const appended = report.files.filter((f) => f.action === \"appended\");\n const replaced = report.files.filter((f) => f.action === \"replaced\");\n\n console.log(`\\nhermes-repo init 完成 → ${report.targetDir}\\n`);\n console.log(`已启用助手: ${report.assistants.join(\", \")}\\n`);\n\n if (created.length > 0) {\n console.log(`已创建 (${created.length}):`);\n for (const f of created) {\n console.log(` + ${f.path}`);\n }\n }\n\n if (overwritten.length > 0) {\n console.log(`已覆盖 (${overwritten.length}):`);\n for (const f of overwritten) {\n console.log(` ~ ${f.path}`);\n }\n }\n\n if (appended.length > 0) {\n console.log(`已追加 (${appended.length}):`);\n for (const f of appended) {\n console.log(` + ${f.path}`);\n }\n }\n\n if (replaced.length > 0) {\n console.log(`已刷新 hermes 块 (${replaced.length}):`);\n for (const f of replaced) {\n console.log(` ↻ ${f.path}`);\n }\n }\n\n if (skipped.length > 0) {\n console.log(`已跳过 (${skipped.length}):`);\n for (const f of skipped) {\n console.log(` - ${f.path}`);\n }\n }\n\n if (report.gitignoreAction) {\n console.log(`\\n.gitignore: ${report.gitignoreAction} hermes-repo 标记块`);\n }\n\n for (const warning of report.warnings) {\n console.warn(`warn: ${warning}`);\n }\n\n console.log(\"\");\n}\n\nexport async function runInit(opts: InitCliOptions): Promise<InitReport> {\n if (!process.stdin.isTTY && !opts.yes) {\n console.error(\"init requires -y in non-interactive environments\");\n process.exit(1);\n }\n\n if (opts.tools && !opts.yes) {\n console.error(\"init --tools requires -y\");\n process.exit(1);\n }\n\n let resolved: InitResolvedOptions;\n\n if (opts.yes) {\n const targetDir = resolveTargetDir(opts.cwd);\n const selected = resolveSelectedAssistants(opts);\n resolved = {\n targetDir,\n force: Boolean(opts.force),\n includeExampleTemplates: opts.includeExampleTemplates ?? true,\n assistants: mergeAssistants(targetDir, selected),\n cancelled: false,\n };\n } else {\n const gathered = await gatherInitOptions(opts);\n if (gathered.cancelled) {\n console.log(\"init 已取消\");\n process.exit(0);\n }\n resolved = {\n ...gathered,\n assistants: mergeAssistants(gathered.targetDir, gathered.assistants),\n };\n }\n\n const report: InitReport = {\n targetDir: resolved.targetDir,\n assistants: resolved.assistants,\n files: [],\n warnings: [],\n };\n\n ensureMemoryTree(resolved.targetDir);\n writeScaffoldFiles(resolved.targetDir, resolved, report);\n\n const gitignore = mergeHermesGitignore(resolved.targetDir);\n report.gitignoreAction = gitignore.action;\n if (gitignore.warnBroadMemoryIgnore) {\n report.warnings.push(\n \".gitignore 中存在对整个 .memory/ 的忽略规则,可能与团队层放行冲突,请手动检查\",\n );\n }\n\n printInitReport(report);\n\n return report;\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n CLAUDE_SETTINGS_LOCAL_REL,\n claudeSettingsLocalPath,\n mergeClaudeLocalSettings,\n} from \"../mergeClaudeSettings.js\";\nimport type { AssistantAdapter, WriteContext } from \"./types.js\";\n\nexport const claudeCodeAdapter: AssistantAdapter = {\n id: \"claude-code\",\n label: \"Claude Code(Stop / SessionStart hooks)\",\n available: true,\n scaffoldPaths: [CLAUDE_SETTINGS_LOCAL_REL],\n write(ctx: WriteContext): void {\n mkdirSync(join(ctx.repoRoot, \".claude\"), { recursive: true });\n const { content, action } = mergeClaudeLocalSettings(ctx.repoRoot);\n writeFileSync(claudeSettingsLocalPath(ctx.repoRoot), content, \"utf8\");\n ctx.report.files.push({ path: CLAUDE_SETTINGS_LOCAL_REL, action });\n },\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { renderTemplate } from \"./templateDir.js\";\nimport type { InitFileAction } from \"./types.js\";\n\nexport const CLAUDE_SETTINGS_LOCAL_REL = \".claude/settings.local.json\";\n\nexport function claudeSettingsLocalPath(repoRoot: string): string {\n return join(repoRoot, \".claude\", \"settings.local.json\");\n}\n\ntype HookHandlers = { hooks: { type: string; command: string }[] }[];\n\n/** 每次 init 合并 hermes 管理的 Stop / SessionStart 到 Claude local settings */\nexport function mergeClaudeLocalSettings(repoRoot: string): {\n content: string;\n action: InitFileAction;\n} {\n const settingsPath = claudeSettingsLocalPath(repoRoot);\n const existed = existsSync(settingsPath);\n\n const templateParsed = JSON.parse(renderTemplate(\"hooks.json.tpl\")) as {\n hooks: {\n Stop: HookHandlers;\n SessionStart: HookHandlers;\n };\n };\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, \"utf8\")) as Record<\n string,\n unknown\n >;\n } catch {\n existing = {};\n }\n }\n\n const prevHooks =\n existing.hooks &&\n typeof existing.hooks === \"object\" &&\n !Array.isArray(existing.hooks)\n ? (existing.hooks as Record<string, unknown>)\n : {};\n\n const merged: Record<string, unknown> = {\n ...existing,\n hooks: {\n ...prevHooks,\n Stop: templateParsed.hooks.Stop,\n SessionStart: templateParsed.hooks.SessionStart,\n },\n };\n\n return {\n content: `${JSON.stringify(merged, null, 2)}\\n`,\n action: existed ? \"overwritten\" : \"created\",\n };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { PACKAGE_NAME } from \"../index.js\";\n\nfunction resolveTemplateDir(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n const candidates = [\n join(here, \"templates\"),\n join(here, \"..\", \"..\", \"templates\"),\n ];\n for (const dir of candidates) {\n if (existsSync(dir)) {\n return dir;\n }\n }\n return join(here, \"templates\");\n}\n\nconst templateDir = resolveTemplateDir();\n\nexport function resolveTemplatePath(name: string): string {\n return join(templateDir, name);\n}\n\nexport function readTemplate(name: string): string {\n return readFileSync(resolveTemplatePath(name), \"utf8\");\n}\n\nexport function renderTemplate(name: string): string {\n const raw = readTemplate(name);\n return raw.replaceAll(\"__PACKAGE_NAME__\", PACKAGE_NAME);\n}\n","import { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const PACKAGE_NAME = \"@riconext/hermes-repo\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport function readPkgVersion(): string {\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as { version: string };\n return pkg.version;\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n CODEX_CONFIG_REL,\n codexConfigPath,\n mergeCodexConfig,\n} from \"../mergeCodexConfig.js\";\nimport type { AssistantAdapter, WriteContext } from \"./types.js\";\n\nexport const codexAdapter: AssistantAdapter = {\n id: \"codex\",\n label: \"OpenAI Codex(AGENTS.md + .codex/config.toml)\",\n available: true,\n scaffoldPaths: [CODEX_CONFIG_REL],\n write(ctx: WriteContext): void {\n mkdirSync(join(ctx.repoRoot, \".codex\"), { recursive: true });\n const { content, action } = mergeCodexConfig(ctx.repoRoot);\n writeFileSync(codexConfigPath(ctx.repoRoot), content, \"utf8\");\n ctx.report.files.push({ path: CODEX_CONFIG_REL, action });\n },\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { InitFileAction } from \"./types.js\";\n\nexport const CODEX_CONFIG_REL = \".codex/config.toml\";\n\nconst CODEX_HERMES_START_MARKER =\n \"# >>> hermes-repo codex (do not edit this block manually)\";\nconst CODEX_HERMES_END_MARKER = \"# <<< hermes-repo codex\";\n\nfunction buildCodexHermesBlock(): string {\n return [\n CODEX_HERMES_START_MARKER,\n \"# Hermes uses AGENTS.md as the shared Codex project guidance entry.\",\n \"# Run `npx @riconext/hermes-repo search <keyword>` to inspect project memory.\",\n \"# Run `npx @riconext/hermes-repo ref --capture <path> --reason \\\"...\\\"` after using memory.\",\n CODEX_HERMES_END_MARKER,\n ].join(\"\\n\");\n}\n\nexport function codexConfigPath(repoRoot: string): string {\n return join(repoRoot, \".codex\", \"config.toml\");\n}\n\nfunction spliceHermesBlock(existing: string, block: string): string {\n const startIdx = existing.indexOf(CODEX_HERMES_START_MARKER);\n const endIdx = existing.indexOf(CODEX_HERMES_END_MARKER);\n\n if (startIdx >= 0 && endIdx >= startIdx) {\n const before = existing.slice(0, startIdx).trimEnd();\n const after = existing.slice(endIdx + CODEX_HERMES_END_MARKER.length).trimStart();\n return `${before ? `${before}\\n\\n` : \"\"}${block}${after ? `\\n\\n${after}` : \"\"}\\n`;\n }\n\n const trimmed = existing.trimEnd();\n return `${trimmed ? `${trimmed}\\n\\n` : \"\"}${block}\\n`;\n}\n\n/** Codex project config is preserved; init only manages a commented Hermes marker block. */\nexport function mergeCodexConfig(repoRoot: string): {\n content: string;\n action: InitFileAction;\n} {\n const configPath = codexConfigPath(repoRoot);\n const existed = existsSync(configPath);\n const block = buildCodexHermesBlock();\n\n if (!existed) {\n return {\n content: `${block}\\n`,\n action: \"created\",\n };\n }\n\n const existing = readFileSync(configPath, \"utf8\");\n const hasBlock =\n existing.includes(CODEX_HERMES_START_MARKER) &&\n existing.includes(CODEX_HERMES_END_MARKER);\n\n return {\n content: spliceHermesBlock(existing, block),\n action: hasBlock ? \"replaced\" : \"appended\",\n };\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n CODEBUDDY_SETTINGS_LOCAL_REL,\n codebuddySettingsLocalPath,\n mergeCodebuddyLocalSettings,\n} from \"../mergeCodebuddySettings.js\";\nimport type { AssistantAdapter, WriteContext } from \"./types.js\";\n\nexport const codebuddyAdapter: AssistantAdapter = {\n id: \"codebuddy\",\n label: \"CodeBuddy(CLI)\",\n available: true,\n scaffoldPaths: [CODEBUDDY_SETTINGS_LOCAL_REL],\n write(ctx: WriteContext): void {\n mkdirSync(join(ctx.repoRoot, \".codebuddy\"), { recursive: true });\n const { content, action } = mergeCodebuddyLocalSettings(ctx.repoRoot);\n writeFileSync(codebuddySettingsLocalPath(ctx.repoRoot), content, \"utf8\");\n ctx.report.files.push({ path: CODEBUDDY_SETTINGS_LOCAL_REL, action });\n },\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { renderTemplate } from \"./templateDir.js\";\nimport type { InitFileAction } from \"./types.js\";\n\nexport const CODEBUDDY_SETTINGS_LOCAL_REL = \".codebuddy/settings.local.json\";\n\nexport function codebuddySettingsLocalPath(repoRoot: string): string {\n return join(repoRoot, \".codebuddy\", \"settings.local.json\");\n}\n\ntype HookHandlers = { hooks: { type: string; command: string }[] }[];\n\n/** 每次 init 合并 hermes 管理的 Stop / SessionStart 到 CodeBuddy local settings */\nexport function mergeCodebuddyLocalSettings(repoRoot: string): {\n content: string;\n action: InitFileAction;\n} {\n const settingsPath = codebuddySettingsLocalPath(repoRoot);\n const existed = existsSync(settingsPath);\n\n const templateParsed = JSON.parse(\n renderTemplate(\"hooks.codebuddy.json.tpl\"),\n ) as {\n hooks: {\n Stop: HookHandlers;\n SessionStart: HookHandlers;\n };\n };\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, \"utf8\")) as Record<\n string,\n unknown\n >;\n } catch {\n existing = {};\n }\n }\n\n const prevHooks =\n existing.hooks &&\n typeof existing.hooks === \"object\" &&\n !Array.isArray(existing.hooks)\n ? (existing.hooks as Record<string, unknown>)\n : {};\n\n const merged: Record<string, unknown> = {\n ...existing,\n hooks: {\n ...prevHooks,\n Stop: templateParsed.hooks.Stop,\n SessionStart: templateParsed.hooks.SessionStart,\n },\n };\n\n return {\n content: `${JSON.stringify(merged, null, 2)}\\n`,\n action: existed ? \"overwritten\" : \"created\",\n };\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n CURSOR_HOOKS_REL,\n cursorHooksPath,\n mergeCursorHooks,\n} from \"../mergeCursorHooks.js\";\nimport type { AssistantAdapter, WriteContext } from \"./types.js\";\n\nexport const cursorAdapter: AssistantAdapter = {\n id: \"cursor\",\n label: \"Cursor(sessionStart / stop hooks)\",\n available: true,\n scaffoldPaths: [CURSOR_HOOKS_REL],\n write(ctx: WriteContext): void {\n mkdirSync(join(ctx.repoRoot, \".cursor\"), { recursive: true });\n const { content, action } = mergeCursorHooks(ctx.repoRoot);\n writeFileSync(cursorHooksPath(ctx.repoRoot), content, \"utf8\");\n ctx.report.files.push({ path: CURSOR_HOOKS_REL, action });\n },\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { renderTemplate } from \"./templateDir.js\";\nimport type { InitFileAction } from \"./types.js\";\n\nexport const CURSOR_HOOKS_REL = \".cursor/hooks.json\";\n\nexport function cursorHooksPath(repoRoot: string): string {\n return join(repoRoot, \".cursor\", \"hooks.json\");\n}\n\ntype CursorHookEntry = { command: string };\n\n/** 每次 init 合并 hermes 管理的 sessionStart / stop 到 .cursor/hooks.json */\nexport function mergeCursorHooks(repoRoot: string): {\n content: string;\n action: InitFileAction;\n} {\n const hooksPath = cursorHooksPath(repoRoot);\n const existed = existsSync(hooksPath);\n\n const templateParsed = JSON.parse(renderTemplate(\"hooks.cursor.json.tpl\")) as {\n version: number;\n hooks: {\n sessionStart: CursorHookEntry[];\n stop: CursorHookEntry[];\n };\n };\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(readFileSync(hooksPath, \"utf8\")) as Record<\n string,\n unknown\n >;\n } catch {\n existing = {};\n }\n }\n\n const prevHooks =\n existing.hooks &&\n typeof existing.hooks === \"object\" &&\n !Array.isArray(existing.hooks)\n ? (existing.hooks as Record<string, unknown>)\n : {};\n\n const merged: Record<string, unknown> = {\n ...existing,\n version: templateParsed.version,\n hooks: {\n ...prevHooks,\n sessionStart: templateParsed.hooks.sessionStart,\n stop: templateParsed.hooks.stop,\n },\n };\n\n return {\n content: `${JSON.stringify(merged, null, 2)}\\n`,\n action: existed ? \"overwritten\" : \"created\",\n };\n}\n","import type { AssistantAdapter, AssistantId } from \"./types.js\";\nimport { claudeCodeAdapter } from \"./claude-code.js\";\nimport { codexAdapter } from \"./codex.js\";\nimport { codebuddyAdapter } from \"./codebuddy.js\";\nimport { cursorAdapter } from \"./cursor.js\";\n\nexport const DEFAULT_ASSISTANT_IDS: AssistantId[] = [\"claude-code\"];\n\nconst ALL_ADAPTERS: AssistantAdapter[] = [\n claudeCodeAdapter,\n cursorAdapter,\n codebuddyAdapter,\n codexAdapter,\n];\n\nconst ADAPTER_BY_ID = new Map<AssistantId, AssistantAdapter>(\n ALL_ADAPTERS.map((a) => [a.id, a]),\n);\n\nexport function getAdapter(id: AssistantId): AssistantAdapter {\n const adapter = ADAPTER_BY_ID.get(id);\n if (!adapter) {\n throw new Error(`Unknown assistant id: ${id}`);\n }\n return adapter;\n}\n\nexport function listAvailable(): AssistantAdapter[] {\n return ALL_ADAPTERS.filter((a) => a.available);\n}\n\nexport function isKnownAssistantId(id: string): id is AssistantId {\n return ADAPTER_BY_ID.has(id as AssistantId);\n}\n\nexport function parseToolsArg(tools: string): AssistantId[] {\n const ids = tools\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n if (ids.length === 0) {\n throw new Error(\"init --tools requires at least one assistant id\");\n }\n\n const result: AssistantId[] = [];\n for (const id of ids) {\n if (!isKnownAssistantId(id)) {\n throw new Error(`Unknown assistant id: ${id}`);\n }\n const adapter = getAdapter(id);\n if (!adapter.available) {\n throw new Error(`Assistant not available yet: ${id}`);\n }\n result.push(id);\n }\n return result;\n}\n\nexport function validateAssistantSelection(ids: AssistantId[]): void {\n if (ids.length === 0) {\n throw new Error(\"At least one assistant must be selected\");\n }\n for (const id of ids) {\n const adapter = getAdapter(id);\n if (!adapter.available) {\n throw new Error(`Assistant not available yet: ${id}`);\n }\n }\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { GITKEEP_DIRS, MEMORY_DIR, MEMORY_SUBDIRS } from \"./paths.js\";\n\nexport function ensureMemoryTree(repoRoot: string): void {\n const memoryRoot = join(repoRoot, MEMORY_DIR);\n mkdirSync(memoryRoot, { recursive: true });\n\n for (const sub of MEMORY_SUBDIRS) {\n mkdirSync(join(memoryRoot, sub), { recursive: true });\n }\n\n mkdirSync(join(repoRoot, \".claude\"), { recursive: true });\n\n for (const sub of GITKEEP_DIRS) {\n const keepPath = join(memoryRoot, sub, \".gitkeep\");\n writeFileSync(keepPath, \"\", { flag: \"a\" });\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport { memoryPath } from \"./paths.js\";\n\nfunction readExistingAssistants(repoRoot: string): AssistantId[] {\n const configPath = memoryPath(repoRoot, \"config.json\");\n if (!existsSync(configPath)) {\n return [];\n }\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf8\")) as {\n assistants?: unknown;\n };\n if (!Array.isArray(config.assistants)) {\n return [];\n }\n return config.assistants.filter((id): id is AssistantId => typeof id === \"string\");\n } catch {\n return [];\n }\n}\n\n/** 与已有 config.assistants 做并集(保留已有 id + 追加本次选择) */\nexport function mergeAssistants(\n repoRoot: string,\n selected: AssistantId[],\n): AssistantId[] {\n const existing = readExistingAssistants(repoRoot);\n return [...new Set([...existing, ...selected])];\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { readTemplate } from \"./templateDir.js\";\n\nconst START_MARKER = \"# >>> hermes-repo memory (do not edit this block manually)\";\nconst END_MARKER = \"# <<< hermes-repo memory\";\n\nexport type GitignoreMergeAction = \"created\" | \"updated\" | \"replaced\" | \"appended\";\n\nexport function mergeHermesGitignore(repoRoot: string): {\n action: GitignoreMergeAction;\n warnBroadMemoryIgnore: boolean;\n} {\n const block = readTemplate(\"gitignore-block.txt\").trimEnd() + \"\\n\";\n const gitignorePath = join(repoRoot, \".gitignore\");\n const contentBefore = existsSync(gitignorePath)\n ? readFileSync(gitignorePath, \"utf8\")\n : \"\";\n\n const warnBroadMemoryIgnore =\n contentBefore.length > 0 &&\n !contentBefore.includes(START_MARKER) &&\n /(^|\\n)\\.memory\\/\\s*$/m.test(contentBefore);\n\n if (!existsSync(gitignorePath)) {\n writeFileSync(gitignorePath, `${block}\\n`, \"utf8\");\n return { action: \"created\", warnBroadMemoryIgnore: false };\n }\n\n const startIdx = contentBefore.indexOf(START_MARKER);\n const endIdx = contentBefore.indexOf(END_MARKER);\n\n if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {\n const before = contentBefore.slice(0, startIdx);\n const after = contentBefore.slice(endIdx + END_MARKER.length);\n const next = `${before}${block}${after}`.replace(/\\n{3,}/g, \"\\n\\n\");\n writeFileSync(gitignorePath, next.endsWith(\"\\n\") ? next : `${next}\\n`, \"utf8\");\n return { action: \"replaced\", warnBroadMemoryIgnore };\n }\n\n if (startIdx !== -1) {\n const before = contentBefore.slice(0, startIdx);\n const next = `${before}${block}\\n`;\n writeFileSync(gitignorePath, next, \"utf8\");\n return { action: \"updated\", warnBroadMemoryIgnore };\n }\n\n const separator = contentBefore.endsWith(\"\\n\") || contentBefore.length === 0 ? \"\\n\" : \"\\n\\n\";\n writeFileSync(gitignorePath, `${contentBefore}${separator}${block}\\n`, \"utf8\");\n return { action: \"appended\", warnBroadMemoryIgnore };\n}\n","import { copyFileSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { getAdapter } from \"./assistants/registry.js\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport type { InitReport, InitResolvedOptions } from \"./types.js\";\nimport { EXAMPLE_TEMPLATE_FILES, memoryPath } from \"./paths.js\";\nimport { renderTemplate, resolveTemplatePath } from \"./templateDir.js\";\nimport { mergeConfigForInit } from \"./mergeConfig.js\";\nimport { mergeAgentsMd } from \"./mergeAgentsMd.js\";\nimport { shouldWriteFile, writeIfAllowed } from \"./scaffoldWrite.js\";\n\nexport { shouldWriteFile } from \"./scaffoldWrite.js\";\n\n/** 生成 v2 config.json 内容 */\nexport function buildConfigJson(assistants: AssistantId[]): string {\n return `${JSON.stringify(\n {\n version: 2,\n storage: { backend: \"file\" },\n assistants,\n debug: false,\n llm: {\n enabled: false,\n provider: \"openai\",\n baseUrl: \"https://api.openai.com/v1\",\n model: \"gpt-4o\",\n apiKey: \"\",\n timeoutMs: 60_000,\n maxInputChars: 24_000,\n mode: \"async\",\n },\n consolidate: {\n autoArchiveDays: 30,\n autoFlush: {\n enabled: false,\n minPendingSessions: 3,\n minIntervalMinutes: 30,\n maxPendingChars: 20_000,\n },\n },\n },\n null,\n 2,\n )}\\n`;\n}\n\nfunction writeConfigJson(\n report: InitReport,\n repoRoot: string,\n assistants: AssistantId[],\n): void {\n const { content, action } = mergeConfigForInit(repoRoot, assistants);\n const absolutePath = memoryPath(repoRoot, \"config.json\");\n writeFileSync(absolutePath, content, \"utf8\");\n report.files.push({ path: \".memory/config.json\", action });\n}\n\nfunction copyTemplateIfAllowed(\n report: InitReport,\n templateName: string,\n destAbsolute: string,\n relativePath: string,\n force: boolean,\n): void {\n const { write, action } = shouldWriteFile(destAbsolute, force);\n if (!write) {\n report.files.push({ path: relativePath, action });\n return;\n }\n copyFileSync(resolveTemplatePath(templateName), destAbsolute);\n report.files.push({ path: relativePath, action });\n}\n\nexport function writeScaffoldFiles(\n repoRoot: string,\n opts: InitResolvedOptions,\n report: InitReport,\n): void {\n const { force, includeExampleTemplates, assistants } = opts;\n\n writeConfigJson(report, repoRoot, assistants);\n\n // v2: LLM settings live in config.json.\n\n // MEMORY.md — v2 导航模板\n writeIfAllowed(\n report,\n memoryPath(repoRoot, \"MEMORY.md\"),\n \".memory/MEMORY.md\",\n renderTemplate(\"MEMORY.md.tpl\"),\n force,\n );\n\n // consolidate-state.json — 初始空状态\n writeIfAllowed(\n report,\n memoryPath(repoRoot, \"consolidate-state.json\"),\n \".memory/consolidate-state.json\",\n `${JSON.stringify(\n {\n version: 1,\n lastConsolidatedAt: null,\n stats: {\n totalCapturesProcessed: 0,\n domains: [],\n knowledgeFilesCreated: 0,\n },\n processedSessions: {},\n },\n null,\n 2,\n )}\\n`,\n force,\n );\n\n // v2: 不再生成 sessions/index.json 和 team/steward-log.md\n\n report.files.push({\n path: \"AGENTS.md\",\n action: mergeAgentsMd(repoRoot, force),\n });\n\n for (const id of assistants) {\n getAdapter(id).write({ repoRoot, force, report });\n }\n\n if (includeExampleTemplates && EXAMPLE_TEMPLATE_FILES.length > 0) {\n // v2: templates/ 目录不在 ensureMemoryTree 中,按需创建\n const templatesDir = memoryPath(repoRoot, \"templates\");\n mkdirSync(templatesDir, { recursive: true });\n for (const name of EXAMPLE_TEMPLATE_FILES) {\n const dest = memoryPath(repoRoot, \"templates\", name);\n copyTemplateIfAllowed(\n report,\n name,\n dest,\n `.memory/templates/${name}`,\n force,\n );\n }\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport type { InitFileAction } from \"./types.js\";\nimport { memoryPath } from \"./paths.js\";\n\n/** v2: init 每次都会写入的完整 config 字段(已有自定义值优先保留) */\nconst DEFAULT_LLM = {\n enabled: false,\n provider: \"openai\",\n baseUrl: \"https://api.openai.com/v1\",\n model: \"gpt-4o\",\n apiKey: \"\",\n timeoutMs: 60_000,\n maxInputChars: 24_000,\n mode: \"async\",\n};\n\nconst DEFAULT_CONSOLIDATE = {\n autoArchiveDays: 30,\n autoFlush: {\n enabled: false,\n minPendingSessions: 3,\n minIntervalMinutes: 30,\n maxPendingChars: 20_000,\n },\n};\n\nexport function mergeConfigForInit(\n repoRoot: string,\n assistants: AssistantId[],\n): { content: string; action: InitFileAction } {\n const configPath = memoryPath(repoRoot, \"config.json\");\n const existed = existsSync(configPath);\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(readFileSync(configPath, \"utf8\")) as Record<\n string,\n unknown\n >;\n } catch {\n existing = {};\n }\n }\n\n const prevStorage =\n existing.storage &&\n typeof existing.storage === \"object\" &&\n !Array.isArray(existing.storage)\n ? (existing.storage as Record<string, unknown>)\n : {};\n\n // v2: 合并 llm 和 consolidate 字段(用户已配置的优先保留)\n const prevLlm =\n existing.llm && typeof existing.llm === \"object\" && !Array.isArray(existing.llm)\n ? (existing.llm as Record<string, unknown>)\n : {};\n const prevConsolidate =\n existing.consolidate && typeof existing.consolidate === \"object\" && !Array.isArray(existing.consolidate)\n ? (existing.consolidate as Record<string, unknown>)\n : {};\n const prevAutoFlush =\n prevConsolidate.autoFlush &&\n typeof prevConsolidate.autoFlush === \"object\" &&\n !Array.isArray(prevConsolidate.autoFlush)\n ? (prevConsolidate.autoFlush as Record<string, unknown>)\n : {};\n\n const merged: Record<string, unknown> = {\n ...existing,\n version: 2,\n storage: {\n ...prevStorage,\n backend: \"file\",\n },\n assistants,\n debug: existing.debug === true,\n llm: { ...DEFAULT_LLM, ...prevLlm },\n consolidate: {\n ...DEFAULT_CONSOLIDATE,\n ...prevConsolidate,\n autoFlush: {\n ...DEFAULT_CONSOLIDATE.autoFlush,\n ...prevAutoFlush,\n },\n },\n };\n\n return {\n content: `${JSON.stringify(merged, null, 2)}\\n`,\n action: existed ? \"overwritten\" : \"created\",\n };\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { InitFileAction } from \"./types.js\";\nimport { readTemplate, renderTemplate } from \"./templateDir.js\";\n\nexport const HERMES_AGENTS_START_MARKER =\n \"<!-- >>> hermes-repo agents (do not edit this block manually) -->\";\nexport const HERMES_AGENTS_END_MARKER = \"<!-- <<< hermes-repo agents -->\";\n\nexport function buildHermesAgentsBlockBody(): string {\n return renderTemplate(\"AGENTS.hermes-block.tpl\").trimEnd();\n}\n\nexport function buildHermesAgentsMarkedBlock(): string {\n const body = buildHermesAgentsBlockBody();\n return `${HERMES_AGENTS_START_MARKER}\\n${body}\\n${HERMES_AGENTS_END_MARKER}`;\n}\n\nexport function buildNewAgentsMd(): string {\n return renderTemplate(\"AGENTS.md.tpl\").replace(\n \"__HERMES_AGENTS_BLOCK__\",\n buildHermesAgentsBlockBody(),\n );\n}\n\nexport function agentsMdHasHermesBlock(content: string): boolean {\n const startIdx = content.indexOf(HERMES_AGENTS_START_MARKER);\n const endIdx = content.indexOf(HERMES_AGENTS_END_MARKER);\n return startIdx !== -1 && endIdx !== -1 && endIdx > startIdx;\n}\n\n/** 无标记块但已手写 hermes 指引时视为已接入(避免重复追加) */\nexport function agentsMdHasLegacyHermesContent(content: string): boolean {\n if (agentsMdHasHermesBlock(content)) {\n return false;\n }\n return (\n content.includes(\"@riconext/hermes-repo\") &&\n content.includes(\"## 记忆系统\") &&\n content.includes(\".memory/MEMORY.md\")\n );\n}\n\nexport function agentsMdHasHermesContent(content: string): boolean {\n return agentsMdHasHermesBlock(content) || agentsMdHasLegacyHermesContent(content);\n}\n\n/** 已有正文与 hermes 标记块之间约两行空行 */\nconst GAP_BEFORE_HERMES_BLOCK = \"\\n\\n\\n\";\n\nfunction withGapBeforeHermesBlock(prefix: string): string {\n const trimmed = prefix.trimEnd();\n if (trimmed.length === 0) {\n return \"\";\n }\n return `${trimmed}${GAP_BEFORE_HERMES_BLOCK}`;\n}\n\nfunction spliceHermesBlock(existing: string, block: string): string {\n const startIdx = existing.indexOf(HERMES_AGENTS_START_MARKER);\n const endIdx = existing.indexOf(HERMES_AGENTS_END_MARKER);\n\n if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {\n const before = existing.slice(0, startIdx);\n const after = existing.slice(endIdx + HERMES_AGENTS_END_MARKER.length);\n const next = `${withGapBeforeHermesBlock(before)}${block}${after}`;\n return next.endsWith(\"\\n\") ? next : `${next}\\n`;\n }\n\n if (startIdx !== -1) {\n const before = existing.slice(0, startIdx);\n return `${withGapBeforeHermesBlock(before)}${block}\\n`;\n }\n\n return `${withGapBeforeHermesBlock(existing)}${block}\\n`;\n}\n\nexport function mergeAgentsMd(\n repoRoot: string,\n force: boolean,\n): InitFileAction {\n const agentsPath = join(repoRoot, \"AGENTS.md\");\n const block = buildHermesAgentsMarkedBlock();\n\n if (!existsSync(agentsPath)) {\n writeFileSync(agentsPath, buildNewAgentsMd(), \"utf8\");\n return \"created\";\n }\n\n const content = readFileSync(agentsPath, \"utf8\");\n\n if (agentsMdHasHermesBlock(content)) {\n if (!force) {\n return \"skipped\";\n }\n writeFileSync(agentsPath, spliceHermesBlock(content, block), \"utf8\");\n return \"replaced\";\n }\n\n if (agentsMdHasLegacyHermesContent(content)) {\n return \"skipped\";\n }\n\n writeFileSync(agentsPath, spliceHermesBlock(content, block), \"utf8\");\n return \"appended\";\n}\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport type { InitFileAction, InitReport } from \"./types.js\";\n\nexport function shouldWriteFile(\n absolutePath: string,\n force: boolean,\n): { write: boolean; action: InitFileAction } {\n if (!existsSync(absolutePath)) {\n return { write: true, action: \"created\" };\n }\n if (force) {\n return { write: true, action: \"overwritten\" };\n }\n return { write: false, action: \"skipped\" };\n}\n\nexport function writeIfAllowed(\n report: InitReport,\n absolutePath: string,\n relativePath: string,\n content: string,\n force: boolean,\n): void {\n const { write, action } = shouldWriteFile(absolutePath, force);\n if (!write) {\n report.files.push({ path: relativePath, action });\n return;\n }\n writeFileSync(absolutePath, content, \"utf8\");\n report.files.push({ path: relativePath, action });\n}\n","import { checkbox, confirm, input } from \"@inquirer/prompts\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { listAvailable } from \"./assistants/registry.js\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport type { InitCliOptions, InitResolvedOptions } from \"./types.js\";\nimport { memoryPath } from \"./paths.js\";\n\nfunction isInitialized(targetDir: string): boolean {\n const configPath = memoryPath(targetDir, \"config.json\");\n if (!existsSync(configPath)) {\n return false;\n }\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf8\")) as {\n version?: number;\n };\n return typeof config.version === \"number\" && config.version >= 1;\n } catch {\n return false;\n }\n}\n\nexport async function gatherInitOptions(\n opts: InitCliOptions,\n): Promise<InitResolvedOptions> {\n const defaultDir = resolve(opts.cwd ?? process.cwd());\n\n const targetInput = await input({\n message: \"目标目录(Git 仓库根)\",\n default: defaultDir,\n });\n const targetDir = resolve(targetInput);\n\n const assistants = (await checkbox({\n message: \"选择要接入的编程助手(可多选)\",\n choices: listAvailable().map((a) => ({\n name: a.label,\n value: a.id,\n checked: a.id === \"claude-code\",\n })),\n validate: (value) => value.length > 0 || \"请至少选择一项\",\n })) as AssistantId[];\n\n const includeExampleTemplates = await confirm({\n message: \"是否写入 capture 示例模板到 .memory/templates/?\",\n default: true,\n });\n\n if (isInitialized(targetDir)) {\n const continueInit = await confirm({\n message: \"检测到已有 .memory/config.json,是否仅补全缺失项?\",\n default: true,\n });\n if (!continueInit) {\n return {\n targetDir,\n force: false,\n includeExampleTemplates,\n assistants,\n cancelled: true,\n };\n }\n }\n\n return {\n targetDir,\n force: Boolean(opts.force),\n includeExampleTemplates,\n assistants,\n cancelled: false,\n };\n}\n","import type { InitCliOptions } from \"../init/types.js\";\nimport { runInit } from \"../init/runInit.js\";\n\nexport async function runInitCommand(opts: InitCliOptions): Promise<void> {\n try {\n await runInit(opts);\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["join","dirname","join","join","existsSync","readFileSync","writeFileSync","join","readFileSync","text","existsSync","mkdirSync","readFileSync","dirname","join","join","dirname","existsSync","readFileSync","mkdirSync","existsSync","mkdirSync","readFileSync","writeFileSync","join","join","existsSync","mkdirSync","writeFileSync","readFileSync","readFileSync","writeFileSync","join","existsSync","readFileSync","writeFileSync","existsSync","readFileSync","resolve","spawn","dirname","join","fileURLToPath","existsSync","mkdirSync","readFileSync","rmSync","writeFileSync","existsSync","readFileSync","mkdirSync","writeFileSync","rmSync","readdirSync","readFileSync","join","readdirSync","join","readFileSync","readFileSync","readdirSync","join","readdirSync","join","readFileSync","input","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","dirname","mkdirSync","existsSync","writeFileSync","readFileSync","mkdirSync","renameSync","join","mkdirSync","renameSync","join","cliPath","join","dirname","fileURLToPath","spawn","existsSync","readdirSync","readFileSync","basename","join","resolve","existsSync","readdirSync","join","basename","existsSync","readdirSync","statSync","homedir","basename","join","resolve","existsSync","readdirSync","statSync","homedir","join","resolve","collectJsonlRecursive","existsSync","readdirSync","readFileSync","join","existsSync","readFileSync","readdirSync","join","resolve","mkdirSync","writeFileSync","join","existsSync","readFileSync","join","existsSync","readFileSync","dirname","join","fileURLToPath","readFileSync","dirname","join","fileURLToPath","dirname","fileURLToPath","join","existsSync","readFileSync","join","existsSync","readFileSync","mkdirSync","join","writeFileSync","mkdirSync","writeFileSync","join","existsSync","readFileSync","join","mkdirSync","join","writeFileSync","mkdirSync","writeFileSync","join","existsSync","readFileSync","join","join","existsSync","readFileSync","mkdirSync","join","writeFileSync","mkdirSync","writeFileSync","join","existsSync","readFileSync","join","join","existsSync","readFileSync","mkdirSync","join","writeFileSync","mkdirSync","writeFileSync","join","join","mkdirSync","writeFileSync","existsSync","readFileSync","existsSync","readFileSync","existsSync","readFileSync","writeFileSync","join","join","existsSync","readFileSync","writeFileSync","mkdirSync","writeFileSync","existsSync","readFileSync","existsSync","readFileSync","existsSync","readFileSync","writeFileSync","join","spliceHermesBlock","join","existsSync","writeFileSync","readFileSync","existsSync","writeFileSync","writeFileSync","mkdirSync","existsSync","readFileSync","resolve","existsSync","readFileSync","resolve","resolve"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/config/debugLog.ts","../src/init/paths.ts","../src/config/readConfig.ts","../src/config/findRepoRoot.ts","../src/capture/runLlmJob.ts","../src/config/llmConfig.ts","../src/capture/claude-code/parseJsonl.ts","../src/capture/enqueueLlmJob.ts","../src/llm/buildSessionDigest.ts","../src/llm/renderCaptureFromJson.ts","../src/llm/chatCompletions.ts","../src/capture/formatCapture.ts","../src/capture/writeCapture.ts","../src/hookExit.ts","../src/commands/captureLlm.ts","../src/capture/hookInput.ts","../src/capture/signalStrength.ts","../src/capture/needsLlm.ts","../src/consolidate/scheduleConsolidate.ts","../src/consolidate/state.ts","../src/consolidate/sessionScanner.ts","../src/consolidate/llmConsolidateV2.ts","../src/consolidate/writeKnowledge.ts","../src/consolidate/archive.ts","../src/consolidate/runConsolidate.ts","../src/consolidate/constants.ts","../src/capture/commitCapture.ts","../src/capture/claude-code/resolveSession.ts","../src/capture/claude-code/run.ts","../src/capture/codebuddy/resolveSession.ts","../src/capture/codebuddy/run.ts","../src/capture/cursor/resolveSession.ts","../src/capture/cursor/run.ts","../src/capture/router.ts","../src/capture/runCapture.ts","../src/commands/capture.ts","../src/commands/flush.ts","../src/inject/runInject.ts","../src/inject/constants.ts","../src/commands/inject.ts","../src/init/runInit.ts","../src/init/assistants/claude-code.ts","../src/init/mergeClaudeSettings.ts","../src/init/templateDir.ts","../src/index.ts","../src/init/assistants/codex.ts","../src/init/mergeCodexConfig.ts","../src/init/assistants/codebuddy.ts","../src/init/mergeCodebuddySettings.ts","../src/init/assistants/cursor.ts","../src/init/mergeCursorHooks.ts","../src/init/assistants/registry.ts","../src/init/ensureDirs.ts","../src/init/mergeAssistants.ts","../src/init/mergeGitignore.ts","../src/init/writeScaffoldFile.ts","../src/init/mergeConfig.ts","../src/init/mergeAgentsMd.ts","../src/init/scaffoldWrite.ts","../src/init/prompts.ts","../src/commands/init.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { runCaptureLlmCommand } from \"./commands/captureLlm.js\";\nimport { runCaptureCommand } from \"./commands/capture.js\";\nimport { runFlushCommandCli } from \"./commands/flush.js\";\nimport { runInjectCommand } from \"./commands/inject.js\";\nimport { runInitCommand } from \"./commands/init.js\";\nimport { readPkgVersion } from \"./index.js\";\n\nconst MIN_NODE_MAJOR = 20;\n\nfunction assertNodeVersion(): void {\n const major = Number.parseInt(process.versions.node.split(\".\")[0] ?? \"0\", 10);\n if (major < MIN_NODE_MAJOR) {\n console.error(\n `hermes-repo requires Node.js >= ${MIN_NODE_MAJOR}. Current: ${process.version}`,\n );\n process.exit(1);\n }\n}\n\nfunction main(): void {\n assertNodeVersion();\n\n const program = new Command();\n\n program\n .name(\"hermes-repo\")\n .description(\n \"跨编程助手的项目级记忆系统:在 Git 仓库中沉淀约定、踩坑与可复用流程\",\n )\n .version(readPkgVersion(), \"-V, --version\", \"显示版本号\");\n\n program\n .command(\"init\")\n .description(\"在当前 Git 仓库初始化 .memory/ 记忆脚手架\")\n .option(\"-y, --yes\", \"非交互模式,使用默认选项\")\n .option(\"-f, --force\", \"覆盖已存在的脚手架文件(不删除 captures 等内容)\")\n .option(\"-C, --cwd <dir>\", \"目标目录,默认 process.cwd()\")\n .option(\n \"--tools <ids>\",\n \"逗号分隔的助手 id,如 claude-code(须与 -y 合用)\",\n )\n .action(\n (options: {\n yes?: boolean;\n force?: boolean;\n cwd?: string;\n tools?: string;\n }) => {\n void runInitCommand({\n yes: options.yes,\n force: options.force,\n cwd: options.cwd,\n tools: options.tools,\n });\n },\n );\n\n program\n .command(\"capture\")\n .description(\"Stop hook:捕获当前会话到 .memory/captures/raw/\")\n .option(\"-C, --cwd <dir>\", \"目标仓库根目录\")\n .option(\"--dry-run\", \"仅预览,不写入文件\")\n .option(\"--strict\", \"失败时 exit 1(hook 默认 exit 0)\")\n .action((options: { cwd?: string; dryRun?: boolean; strict?: boolean }) => {\n runCaptureCommand({\n cwd: options.cwd,\n dryRun: options.dryRun,\n strict: options.strict,\n });\n });\n\n program\n .command(\"capture-llm\")\n .description(\"异步 LLM 升级 capture(由 capture hook 入队,亦可 --flush)\")\n .option(\"-C, --cwd <dir>\", \"目标仓库根目录\")\n .option(\"--job <id>\", \"处理指定 pending job\")\n .option(\"--flush\", \"处理所有 pending job\")\n .option(\"--strict\", \"失败时 exit 1\")\n .action(\n (options: {\n cwd?: string;\n job?: string;\n flush?: boolean;\n strict?: boolean;\n }) => {\n runCaptureLlmCommand({\n cwd: options.cwd,\n job: options.job,\n flush: options.flush,\n strict: options.strict,\n });\n },\n );\n\n program\n .command(\"flush\")\n .description(\n \"手动触发 consolidate:LLM 提炼 captures → 知识库 + MEMORY.md\",\n )\n .option(\"-C, --cwd <dir>\", \"目标仓库根目录\")\n .option(\"--force\", \"重处理全部 session 文件\")\n .option(\"--dry-run\", \"仅预览,不写入\")\n .option(\"--strict\", \"失败时 exit 1\")\n .action(\n (options: {\n cwd?: string;\n force?: boolean;\n dryRun?: boolean;\n strict?: boolean;\n }) => {\n void runFlushCommandCli({\n cwd: options.cwd,\n force: options.force,\n dryRun: options.dryRun,\n strict: options.strict,\n });\n },\n );\n\n program\n .command(\"inject\")\n .description(\"SessionStart hook:将 MEMORY.md 导航 + rules 注入到 stdout\")\n .option(\"-C, --cwd <dir>\", \"目标仓库根目录\")\n .option(\"--strict\", \"失败时 exit 1(hook 默认 exit 0)\")\n .action((options: { cwd?: string; strict?: boolean }) => {\n runInjectCommand({\n cwd: options.cwd,\n strict: options.strict,\n });\n });\n\n if (process.argv.length <= 2) {\n program.outputHelp();\n process.exit(0);\n }\n\n program.parse(process.argv);\n}\n\nmain();\n","import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { RepoContext } from \"./types.js\";\nimport { memoryPath } from \"../init/paths.js\";\n\nexport const DEBUG_LOG_FILE = \"hermes-debug.log\";\n\nlet logFilePath: string | null = null;\n\nexport function configureDebugLogging(\n repoRoot: string | null,\n enabled: boolean,\n): void {\n if (!enabled || !repoRoot) {\n logFilePath = null;\n return;\n }\n logFilePath = memoryPath(repoRoot, DEBUG_LOG_FILE);\n}\n\nfunction formatLine(phase: string, message: string): string {\n return `${new Date().toISOString()} hermes-repo [${phase}] ${message}`;\n}\n\nfunction writeToLogFile(line: string): void {\n if (!logFilePath) {\n return;\n }\n mkdirSync(dirname(logFilePath), { recursive: true });\n appendFileSync(logFilePath, `${line}\\n`, \"utf8\");\n}\n\nexport function debugLog(\n enabled: boolean,\n phase: string,\n message: string,\n): void {\n if (!enabled) {\n return;\n }\n const line = formatLine(phase, message);\n console.error(line);\n writeToLogFile(line);\n}\n\nexport function debugLogBlock(\n enabled: boolean,\n phase: string,\n label: string,\n content: string,\n): void {\n if (!enabled) {\n return;\n }\n\n debugLog(true, phase, `${label} BEGIN`);\n for (const line of content.split(/\\r?\\n/)) {\n debugLog(true, phase, `| ${line}`);\n }\n debugLog(true, phase, `${label} END`);\n}\n\nexport function debugFromContext(\n ctx: RepoContext | null | undefined,\n phase: string,\n message: string,\n): void {\n debugLog(ctx?.config.debug === true, phase, message);\n}\n","import { join } from \"node:path\";\n\nexport const MEMORY_DIR = \".memory\";\n\n/** v2 目录结构 */\nexport const MEMORY_SUBDIRS = [\n \"rules\",\n \"domains/general\",\n \"workflows\",\n \"decisions\",\n \"incidents\",\n \"captures/raw\",\n \"captures/archived\",\n] as const;\n\n/** 需要创建 .gitkeep 的目录(确保空目录能被 git 追踪) */\nexport const GITKEEP_DIRS = [\n \"rules\",\n \"domains/general\",\n \"workflows\",\n \"decisions\",\n \"incidents\",\n] as const;\n\n/** init 时复制的示例模板文件 */\nexport const EXAMPLE_TEMPLATE_FILES = [\n \"capture-session.example.md\",\n] as const;\n\n/** init 时生成的脚手架文件路径列表 */\nexport const SCAFFOLD_RELATIVE_PATHS = [\n \".memory/config.json\",\n \".memory/MEMORY.md\",\n \".memory/consolidate-state.json\",\n \"AGENTS.md\",\n \".claude/settings.local.json\",\n] as const;\n\nexport function memoryPath(root: string, ...segments: string[]): string {\n return join(root, MEMORY_DIR, ...segments);\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AssistantId } from \"../init/assistants/types.js\";\nimport { findRepoRoot } from \"./findRepoRoot.js\";\nimport type {\n ConsolidateConfig,\n HermesConfig,\n LlmConfigV2,\n RepoContext,\n} from \"./types.js\";\n\nfunction isAssistantId(value: unknown): value is AssistantId {\n return typeof value === \"string\";\n}\n\nfunction parseLlmConfig(raw: Record<string, unknown>): LlmConfigV2 {\n const llm = raw.llm as Record<string, unknown> | undefined;\n return {\n enabled: typeof llm?.enabled === \"boolean\" ? llm.enabled : false,\n provider: typeof llm?.provider === \"string\" ? llm.provider : \"openai\",\n baseUrl: typeof llm?.baseUrl === \"string\" ? llm.baseUrl : \"https://api.openai.com/v1\",\n model: typeof llm?.model === \"string\" ? llm.model : \"gpt-4o\",\n apiKey: typeof llm?.apiKey === \"string\" ? llm.apiKey : \"\",\n timeoutMs:\n typeof llm?.timeoutMs === \"number\" && llm.timeoutMs > 0\n ? llm.timeoutMs\n : 60_000,\n maxInputChars:\n typeof llm?.maxInputChars === \"number\" && llm.maxInputChars > 0\n ? llm.maxInputChars\n : 24_000,\n mode: llm?.mode === \"sync\" ? \"sync\" : \"async\",\n };\n}\n\nfunction parseConsolidateConfig(raw: Record<string, unknown>): ConsolidateConfig {\n const c = raw.consolidate as Record<string, unknown> | undefined;\n const autoFlush =\n c?.autoFlush && typeof c.autoFlush === \"object\" && !Array.isArray(c.autoFlush)\n ? (c.autoFlush as Record<string, unknown>)\n : {};\n return {\n autoArchiveDays: typeof c?.autoArchiveDays === \"number\" ? c.autoArchiveDays : 30,\n autoFlush: {\n enabled: autoFlush.enabled === true,\n minPendingSessions:\n typeof autoFlush.minPendingSessions === \"number\" &&\n autoFlush.minPendingSessions > 0\n ? autoFlush.minPendingSessions\n : 3,\n minIntervalMinutes:\n typeof autoFlush.minIntervalMinutes === \"number\" &&\n autoFlush.minIntervalMinutes > 0\n ? autoFlush.minIntervalMinutes\n : 30,\n maxPendingChars:\n typeof autoFlush.maxPendingChars === \"number\" &&\n autoFlush.maxPendingChars > 0\n ? autoFlush.maxPendingChars\n : 20_000,\n },\n };\n}\n\nexport function readConfigAtRepo(repoRoot: string): HermesConfig | null {\n const configPath = join(repoRoot, \".memory\", \"config.json\");\n try {\n const raw = JSON.parse(readFileSync(configPath, \"utf8\")) as Record<string, unknown>;\n const version = raw.version;\n\n // v2 配置\n if (version === 2) {\n const assistants = Array.isArray(raw.assistants)\n ? raw.assistants.filter(isAssistantId)\n : [];\n return {\n version: 2,\n storage: { backend: (raw.storage as Record<string, unknown>)?.backend === \"file\" ? \"file\" : \"file\" },\n assistants,\n debug: raw.debug === true,\n llm: parseLlmConfig(raw),\n consolidate: parseConsolidateConfig(raw),\n };\n }\n\n // v1 兼容(自动升级字段)\n if (version === 1 || version === undefined) {\n const assistants = Array.isArray(raw.assistants)\n ? raw.assistants.filter(isAssistantId)\n : [];\n return {\n version: 2, // 自动升级为 v2\n storage: { backend: \"file\" },\n assistants,\n debug: raw.debug === true,\n llm: {\n enabled: false,\n provider: \"openai\",\n baseUrl: \"https://api.openai.com/v1\",\n model: \"gpt-4o\",\n apiKey: \"\",\n timeoutMs: 60_000,\n maxInputChars: 24_000,\n mode: \"async\",\n },\n consolidate: {\n autoArchiveDays: 30,\n autoFlush: {\n enabled: false,\n minPendingSessions: 3,\n minIntervalMinutes: 30,\n maxPendingChars: 20_000,\n },\n },\n };\n }\n\n return null; // 不支持的版本\n } catch {\n return null;\n }\n}\n\nexport function loadRepoContext(cwd?: string): RepoContext | null {\n const repoRoot = findRepoRoot(cwd);\n if (!repoRoot) {\n return null;\n }\n const config = readConfigAtRepo(repoRoot);\n if (!config) {\n return null;\n }\n return { repoRoot, config };\n}\n","import { existsSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nconst CONFIG_REL = join(\".memory\", \"config.json\");\n\nexport function findRepoRoot(startDir?: string): string | null {\n let dir = resolve(startDir ?? process.cwd());\n\n while (true) {\n if (existsSync(join(dir, CONFIG_REL))) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return null;\n }\n dir = parent;\n }\n}\n","import { existsSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { debugLog } from \"../config/debugLog.js\";\nimport { isLlmAvailable } from \"../config/llmConfig.js\";\nimport { readConfigAtRepo } from \"../config/readConfig.js\";\nimport { parseJsonlFile } from \"./claude-code/parseJsonl.js\";\nimport {\n deleteLlmJob,\n listPendingJobs,\n readLlmJob,\n type LlmJobPayload,\n} from \"./enqueueLlmJob.js\";\nimport { llmFormat } from \"./formatCapture.js\";\nimport { renderCaptureMarkdown } from \"./writeCapture.js\";\n\nfunction captureAlreadyUpgraded(repoRoot: string, captureFile: string): boolean {\n const path = join(repoRoot, captureFile);\n if (!existsSync(path)) {\n return false;\n }\n const text = readFileSync(path, \"utf8\");\n return /llmUpgradedAt:/.test(text);\n}\n\nexport async function runLlmJob(\n repoRoot: string,\n job: LlmJobPayload,\n debug?: boolean,\n): Promise<{ ok: boolean; reason?: string }> {\n if (captureAlreadyUpgraded(repoRoot, job.captureFile)) {\n deleteLlmJob(repoRoot, job.jobId);\n return { ok: true, reason: \"already-upgraded\" };\n }\n\n const llm = readConfigAtRepo(repoRoot)?.llm ?? null;\n if (!isLlmAvailable(llm)) {\n return { ok: false, reason: \"llm not available\" };\n }\n\n if (!existsSync(job.jsonlPath)) {\n return { ok: false, reason: \"jsonl missing\" };\n }\n\n const session = parseJsonlFile(job.jsonlPath);\n const upgraded = await llmFormat(session, job.assistant, llm!);\n if (!upgraded) {\n debugLog(debug === true, \"capture-llm\", `llm job failed: ${job.jobId}`);\n return { ok: false, reason: \"llm format failed\" };\n }\n\n const target = join(repoRoot, job.captureFile);\n const temp = `${target}.hermes-tmp`;\n const date = new Date().toISOString().slice(0, 10);\n writeFileSync(temp, renderCaptureMarkdown(upgraded, date), \"utf8\");\n renameSync(temp, target);\n\n deleteLlmJob(repoRoot, job.jobId);\n debugLog(debug === true, \"capture-llm\", `ok: upgraded ${job.captureFile}`);\n return { ok: true };\n}\n\nexport async function runLlmJobById(\n repoRoot: string,\n jobId: string,\n debug?: boolean,\n): Promise<{ ok: boolean; reason?: string }> {\n const job = readLlmJob(repoRoot, jobId);\n if (!job) {\n return { ok: false, reason: \"job not found\" };\n }\n return runLlmJob(repoRoot, job, debug);\n}\n\nexport async function flushPendingLlmJobs(\n repoRoot: string,\n debug?: boolean,\n): Promise<number> {\n const jobs = listPendingJobs(repoRoot);\n let done = 0;\n for (const job of jobs) {\n const result = await runLlmJob(repoRoot, job, debug);\n if (result.ok) {\n done += 1;\n }\n }\n return done;\n}\n","import type { LlmConfigV2 } from \"./types.js\";\n\nexport type LlmCaptureMode = \"async\" | \"sync\";\nexport type LlmConfig = LlmConfigV2;\n\nexport const DEFAULT_LLM_TIMEOUT_MS = 60_000;\nexport const DEFAULT_LLM_MAX_INPUT_CHARS = 24_000;\nexport const DEFAULT_LLM_BASE_URL = \"https://api.deepseek.com\";\nexport const DEFAULT_LLM_MODEL = \"deepseek-v4-flash\";\n\nexport function defaultDisabledLlmConfig(): LlmConfig {\n return {\n enabled: false,\n provider: \"openai\",\n baseUrl: DEFAULT_LLM_BASE_URL,\n model: DEFAULT_LLM_MODEL,\n apiKey: \"\",\n timeoutMs: DEFAULT_LLM_TIMEOUT_MS,\n maxInputChars: DEFAULT_LLM_MAX_INPUT_CHARS,\n mode: \"async\",\n };\n}\n\nexport function isLlmAvailable(cfg: LlmConfig | null): boolean {\n if (!cfg?.enabled) {\n return false;\n }\n return (\n Boolean(cfg.apiKey?.trim()) &&\n Boolean(cfg.baseUrl?.trim()) &&\n Boolean(cfg.model?.trim())\n );\n}\n\nexport function effectiveLlmMode(cfg: LlmConfig): LlmCaptureMode {\n return cfg.mode === \"sync\" ? \"sync\" : \"async\";\n}\n\nexport function parseLlmConfigRaw(raw: Record<string, unknown>): LlmConfig | null {\n if (raw.enabled !== true && raw.enabled !== false) {\n return null;\n }\n const baseUrl = typeof raw.baseUrl === \"string\" ? raw.baseUrl : \"\";\n const model = typeof raw.model === \"string\" ? raw.model : \"\";\n const apiKey = typeof raw.apiKey === \"string\" ? raw.apiKey : \"\";\n const timeoutMs =\n typeof raw.timeoutMs === \"number\" && raw.timeoutMs > 0\n ? raw.timeoutMs\n : DEFAULT_LLM_TIMEOUT_MS;\n const maxInputChars =\n typeof raw.maxInputChars === \"number\" && raw.maxInputChars > 0\n ? raw.maxInputChars\n : DEFAULT_LLM_MAX_INPUT_CHARS;\n const mode = raw.mode === \"sync\" ? \"sync\" : \"async\";\n const provider =\n typeof raw.provider === \"string\" ? raw.provider : \"openai\";\n\n return {\n enabled: raw.enabled,\n provider,\n baseUrl,\n model,\n apiKey,\n timeoutMs,\n maxInputChars,\n mode,\n };\n}\n","import { readFileSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport type { ParsedSession, SessionMessage } from \"../types.js\";\n\nconst FILE_CHANGE_TOOLS =\n /^(Write|Edit|MultiEdit|NotebookEdit|write|edit)$/i;\n\n/** CodeBuddy:跳过元数据行,避免干扰统计 */\nconst SKIP_LINE_TYPES = new Set([\n \"file-history-snapshot\",\n \"summary\",\n \"function_call_result\",\n]);\n\nfunction textFromContentParts(content: unknown): string {\n if (!Array.isArray(content)) {\n return \"\";\n }\n return content\n .map((part) => {\n if (!part || typeof part !== \"object\") {\n return \"\";\n }\n const p = part as Record<string, unknown>;\n if (typeof p.text === \"string\") {\n return p.text;\n }\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction extractText(record: Record<string, unknown>): string {\n if (typeof record.content === \"string\") {\n return record.content;\n }\n if (Array.isArray(record.content)) {\n const top = textFromContentParts(record.content);\n if (top) {\n return top;\n }\n }\n const message = record.message;\n if (message && typeof message === \"object\") {\n const msg = message as Record<string, unknown>;\n if (typeof msg.content === \"string\") {\n return msg.content;\n }\n if (Array.isArray(msg.content)) {\n return textFromContentParts(msg.content);\n }\n }\n return \"\";\n}\n\nfunction inferRole(record: Record<string, unknown>): string {\n if (typeof record.role === \"string\") {\n return record.role;\n }\n if (typeof record.type === \"string\") {\n const t = record.type.toLowerCase();\n if (t === \"user\" || t === \"human\") return \"user\";\n if (t === \"assistant\") return \"assistant\";\n }\n return \"unknown\";\n}\n\nfunction isSkippedLine(record: Record<string, unknown>): boolean {\n const t = String(record.type ?? \"\").toLowerCase();\n return SKIP_LINE_TYPES.has(t);\n}\n\nfunction isToolUse(record: Record<string, unknown>): boolean {\n const t = String(record.type ?? \"\").toLowerCase();\n return t === \"tool_use\" || t === \"tool\" || t === \"function_call\";\n}\n\nfunction toolName(record: Record<string, unknown>): string {\n if (typeof record.name === \"string\") return record.name;\n const tool = record.tool;\n if (tool && typeof tool === \"object\" && \"name\" in tool) {\n return String((tool as { name: string }).name);\n }\n return \"\";\n}\n\n/** Cursor 等助手:tool_use 嵌在 message.content 数组内 */\nfunction countNestedTools(record: Record<string, unknown>): {\n toolCalls: number;\n fileChanges: number;\n} {\n let toolCalls = 0;\n let fileChanges = 0;\n const message = record.message;\n if (!message || typeof message !== \"object\") {\n return { toolCalls, fileChanges };\n }\n const content = (message as Record<string, unknown>).content;\n if (!Array.isArray(content)) {\n return { toolCalls, fileChanges };\n }\n for (const part of content) {\n if (!part || typeof part !== \"object\") {\n continue;\n }\n const p = part as Record<string, unknown>;\n const t = String(p.type ?? \"\").toLowerCase();\n if (t !== \"tool_use\" && t !== \"tool\") {\n continue;\n }\n toolCalls += 1;\n const name = typeof p.name === \"string\" ? p.name : \"\";\n if (FILE_CHANGE_TOOLS.test(name)) {\n fileChanges += 1;\n }\n }\n return { toolCalls, fileChanges };\n}\n\nexport function parseJsonlFile(jsonlPath: string): ParsedSession {\n const sessionId = basename(jsonlPath, \".jsonl\");\n const raw = readFileSync(jsonlPath, \"utf8\");\n const messages: SessionMessage[] = [];\n let fileChanges = 0;\n let toolCalls = 0;\n\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const record = JSON.parse(trimmed) as Record<string, unknown>;\n if (isSkippedLine(record)) {\n continue;\n }\n if (isToolUse(record)) {\n toolCalls += 1;\n const name = toolName(record);\n if (FILE_CHANGE_TOOLS.test(name)) {\n fileChanges += 1;\n }\n continue;\n }\n const nested = countNestedTools(record);\n toolCalls += nested.toolCalls;\n fileChanges += nested.fileChanges;\n const role = inferRole(record);\n const text = extractText(record);\n if (text) {\n messages.push({ role, text });\n }\n } catch {\n // skip malformed lines\n }\n }\n\n const text = messages.map((m) => m.text).join(\"\\n\");\n\n return {\n sessionId,\n messages,\n text,\n fileChanges,\n toolCalls,\n };\n}\n","import { spawn } from \"node:child_process\";\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { debugLog } from \"../config/debugLog.js\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { AssistantId } from \"../init/assistants/types.js\";\n\nexport interface LlmJobPayload {\n jobId: string;\n sessionId: string;\n jsonlPath: string;\n captureFile: string;\n assistant: AssistantId;\n enqueuedAt: string;\n}\n\nfunction pendingDir(repoRoot: string): string {\n return memoryPath(repoRoot, \"captures\", \"pending\");\n}\n\nfunction cliPath(): string {\n return join(dirname(fileURLToPath(import.meta.url)), \"..\", \"cli.js\");\n}\n\nfunction makeJobId(sessionId: string): string {\n const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, \"\").slice(0, 32);\n return `${Date.now()}-${safe || \"session\"}`;\n}\n\nfunction removeStaleJobsForSession(\n repoRoot: string,\n sessionId: string,\n): void {\n const dir = pendingDir(repoRoot);\n if (!existsSync(dir)) {\n return;\n }\n for (const name of readdirSync(dir)) {\n if (!name.endsWith(\".json\")) {\n continue;\n }\n try {\n const raw = JSON.parse(\n readFileSync(join(dir, name), \"utf8\"),\n ) as LlmJobPayload;\n if (raw.sessionId === sessionId) {\n rmSync(join(dir, name), { force: true });\n }\n } catch {\n // skip\n }\n }\n}\n\nexport function enqueueLlmJob(opts: {\n repoRoot: string;\n sessionId: string;\n jsonlPath: string;\n captureFile: string;\n assistant: AssistantId;\n debug?: boolean;\n}): boolean {\n const { repoRoot, sessionId, jsonlPath, captureFile, assistant, debug } =\n opts;\n const dir = pendingDir(repoRoot);\n mkdirSync(dir, { recursive: true });\n removeStaleJobsForSession(repoRoot, sessionId);\n\n const jobId = makeJobId(sessionId);\n const payload: LlmJobPayload = {\n jobId,\n sessionId,\n jsonlPath,\n captureFile,\n assistant,\n enqueuedAt: new Date().toISOString(),\n };\n writeFileSync(\n join(dir, `${jobId}.json`),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n\n const child = spawn(\n process.execPath,\n [cliPath(), \"capture-llm\", \"--job\", jobId, \"-C\", repoRoot],\n {\n detached: true,\n stdio: \"ignore\",\n cwd: repoRoot,\n },\n );\n child.unref();\n\n debugLog(debug === true, \"capture\", `llm job enqueued: ${jobId}`);\n return true;\n}\n\nexport function readLlmJob(\n repoRoot: string,\n jobId: string,\n): LlmJobPayload | null {\n const path = join(pendingDir(repoRoot), `${jobId}.json`);\n if (!existsSync(path)) {\n return null;\n }\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as LlmJobPayload;\n } catch {\n return null;\n }\n}\n\nexport function deleteLlmJob(repoRoot: string, jobId: string): void {\n const path = join(pendingDir(repoRoot), `${jobId}.json`);\n if (existsSync(path)) {\n rmSync(path, { force: true });\n }\n}\n\nexport function listPendingJobs(repoRoot: string): LlmJobPayload[] {\n const dir = pendingDir(repoRoot);\n if (!existsSync(dir)) {\n return [];\n }\n const jobs: LlmJobPayload[] = [];\n for (const name of readdirSync(dir)) {\n if (!name.endsWith(\".json\")) {\n continue;\n }\n try {\n jobs.push(\n JSON.parse(readFileSync(join(dir, name), \"utf8\")) as LlmJobPayload,\n );\n } catch {\n // skip\n }\n }\n return jobs;\n}\n","import type { ParsedSession } from \"../capture/types.js\";\n\nexport function buildSessionDigest(\n session: ParsedSession,\n maxChars: number,\n): string {\n const parts: string[] = [\n `sessionId: ${session.sessionId}`,\n `messages: ${session.messages.length}`,\n `toolCalls: ${session.toolCalls}`,\n `fileChanges: ${session.fileChanges}`,\n \"\",\n \"--- transcript (truncated) ---\",\n ];\n\n let used = parts.join(\"\\n\").length;\n const userFirst = [...session.messages].sort((a, b) => {\n if (a.role === \"user\" && b.role !== \"user\") return -1;\n if (b.role === \"user\" && a.role !== \"user\") return 1;\n return 0;\n });\n\n for (const m of userFirst) {\n const block = `[${m.role}]\\n${m.text.slice(0, 2000)}\\n`;\n if (used + block.length > maxChars) {\n parts.push(\"[... truncated ...]\");\n break;\n }\n parts.push(block);\n used += block.length;\n }\n\n return parts.join(\"\\n\");\n}\n","import type { CaptureMemoryType } from \"../capture/types.js\";\n\nexport interface LlmExtractResult {\n type: CaptureMemoryType;\n tags: string[];\n scope: string;\n title?: string;\n context: string;\n findings?: string;\n impact?: string;\n goal?: string;\n steps?: string[];\n cautions?: string[];\n verification?: string[];\n}\n\nconst VALID_TYPES = new Set<CaptureMemoryType>([\n \"semantic\",\n \"episodic\",\n \"procedural\",\n]);\n\nexport function parseLlmExtractJson(raw: unknown): LlmExtractResult | null {\n if (!raw || typeof raw !== \"object\") {\n return null;\n }\n const o = raw as Record<string, unknown>;\n const type = o.type;\n if (typeof type !== \"string\" || !VALID_TYPES.has(type as CaptureMemoryType)) {\n return null;\n }\n const context = typeof o.context === \"string\" ? o.context.trim() : \"\";\n if (!context) {\n return null;\n }\n const tags = Array.isArray(o.tags)\n ? o.tags.filter((t): t is string => typeof t === \"string\")\n : [];\n const scope =\n typeof o.scope === \"string\" && o.scope.trim()\n ? o.scope.trim()\n : \"all\";\n\n return {\n type: type as CaptureMemoryType,\n tags,\n scope,\n title: typeof o.title === \"string\" ? o.title : undefined,\n context,\n findings: typeof o.findings === \"string\" ? o.findings : undefined,\n impact: typeof o.impact === \"string\" ? o.impact : undefined,\n goal: typeof o.goal === \"string\" ? o.goal : undefined,\n steps: Array.isArray(o.steps)\n ? o.steps.filter((s): s is string => typeof s === \"string\")\n : undefined,\n cautions: Array.isArray(o.cautions)\n ? o.cautions.filter((s): s is string => typeof s === \"string\")\n : undefined,\n verification: Array.isArray(o.verification)\n ? o.verification.filter((s): s is string => typeof s === \"string\")\n : undefined,\n };\n}\n\nfunction listSection(title: string, items: string[] | undefined): string {\n if (!items?.length) {\n return \"\";\n }\n return `\\n\\n## ${title}\\n\\n${items.map((s, i) => `${i + 1}. ${s}`).join(\"\\n\")}`;\n}\n\nexport function renderBodyFromExtract(extract: LlmExtractResult): string {\n if (extract.type === \"procedural\") {\n const steps =\n extract.steps?.map((s, i) => `${i + 1}. ${s}`).join(\"\\n\") ??\n extract.findings ??\n \"(无步骤)\";\n const cautions =\n extract.cautions?.map((s) => `- ${s}`).join(\"\\n\") ?? \"(无)\";\n const verification =\n extract.verification?.map((s) => `- ${s}`).join(\"\\n\") ?? \"(无)\";\n return `## 目标\n\n${extract.goal ?? extract.context}\n\n## 步骤\n\n${steps}\n${extract.cautions?.length ? `\\n\\n## 注意\\n\\n${cautions}` : \"\"}\n${extract.verification?.length ? `\\n\\n## 验证\\n\\n${verification}` : \"\"}`;\n }\n\n return `## 上下文\n\n${extract.context}\n\n## 发现\n\n${extract.findings ?? extract.title ?? \"(见上下文)\"}\n\n## 影响\n\n${extract.impact ?? \"(待 consolidate 或人工补充)\"}`;\n}\n","import type { LlmConfig } from \"../config/llmConfig.js\";\nimport { buildSessionDigest } from \"./buildSessionDigest.js\";\nimport {\n parseLlmExtractJson,\n type LlmExtractResult,\n} from \"./renderCaptureFromJson.js\";\nimport type { ParsedSession } from \"../capture/types.js\";\n\nconst SYSTEM_PROMPT = `You extract project memory from an AI coding session transcript.\nRespond with a single JSON object only (no markdown fence), matching this shape:\n{\n \"type\": \"semantic\" | \"episodic\" | \"procedural\",\n \"tags\": [\"tag1\"],\n \"scope\": \"all\" | \"frontend\" | \"backend\",\n \"title\": \"short summary\",\n \"context\": \"what was being done\",\n \"findings\": \"facts/decisions/root cause (semantic/episodic)\",\n \"impact\": \"effect on future work\",\n \"goal\": \"for procedural only\",\n \"steps\": [\"step 1\"],\n \"cautions\": [\"pitfall\"],\n \"verification\": [\"how to verify\"]\n}\nUse procedural only for repeatable multi-step workflows. Use Chinese for content when the session is mainly Chinese.`;\n\nexport async function extractCaptureViaLlm(\n session: ParsedSession,\n llm: LlmConfig,\n): Promise<LlmExtractResult | null> {\n const digest = buildSessionDigest(session, llm.maxInputChars);\n const url = `${llm.baseUrl.replace(/\\/$/, \"\")}/chat/completions`;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), llm.timeoutMs);\n\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${llm.apiKey}`,\n },\n body: JSON.stringify({\n model: llm.model,\n response_format: { type: \"json_object\" },\n messages: [\n { role: \"system\", content: SYSTEM_PROMPT },\n {\n role: \"user\",\n content: `Extract memory from this session:\\n\\n${digest}`,\n },\n ],\n temperature: 0.2,\n }),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n return null;\n }\n\n const data = (await res.json()) as {\n choices?: Array<{ message?: { content?: string } }>;\n };\n const content = data.choices?.[0]?.message?.content;\n if (!content) {\n return null;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch {\n return null;\n }\n return parseLlmExtractJson(parsed);\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n}\n","import type { LlmConfig } from \"../config/llmConfig.js\";\nimport { extractCaptureViaLlm } from \"../llm/chatCompletions.js\";\nimport {\n renderBodyFromExtract,\n type LlmExtractResult,\n} from \"../llm/renderCaptureFromJson.js\";\nimport type { AssistantId } from \"../init/assistants/types.js\";\nimport type { CaptureMemoryType, ParsedSession } from \"./types.js\";\n\n/** 内联:推断 capture 类型(原 shouldCapture.ts,v2 保留用于 capture-llm 兼容) */\nfunction inferCaptureType(session: ParsedSession): \"semantic\" | \"episodic\" {\n const SEMANTIC_SIGNAL_RE =\n /约定|必须|架构|决策|规范|convention|pattern|always|never/i;\n if (SEMANTIC_SIGNAL_RE.test(session.text)) {\n return \"semantic\";\n }\n return \"episodic\";\n}\n\nexport interface FormattedCapture {\n type: CaptureMemoryType;\n sessionId: string;\n tags: string[];\n scope: string;\n bodyMarkdown: string;\n llmUpgradedAt?: string;\n}\n\nfunction assistantLabel(assistant: AssistantId): string {\n return assistant;\n}\n\nexport function simpleFormat(\n session: ParsedSession,\n assistant: AssistantId,\n): FormattedCapture {\n const type = inferCaptureType(session);\n const recent = session.messages.slice(-6);\n const context = recent\n .map((m) => `**${m.role}**: ${m.text.slice(0, 500)}`)\n .join(\"\\n\\n\");\n\n const bodyMarkdown = `## 上下文\n\n自动捕获自 ${assistantLabel(assistant)} 会话 \\`${session.sessionId}\\`。\n\n## 发现\n\n${context || \"(无提取内容)\"}\n\n## 影响\n\n(待 consolidate 或人工补充)`;\n\n return {\n type,\n sessionId: session.sessionId,\n tags: [\"auto-capture\", assistant],\n scope: \"all\",\n bodyMarkdown,\n };\n}\n\nexport function formattedFromLlmExtract(\n session: ParsedSession,\n assistant: AssistantId,\n extract: LlmExtractResult,\n): FormattedCapture {\n const tagSet = new Set([\"auto-capture\", assistant, ...extract.tags]);\n return {\n type: extract.type,\n sessionId: session.sessionId,\n tags: [...tagSet],\n scope: extract.scope,\n bodyMarkdown: renderBodyFromExtract(extract),\n llmUpgradedAt: new Date().toISOString(),\n };\n}\n\nexport async function llmFormat(\n session: ParsedSession,\n assistant: AssistantId,\n llm: LlmConfig,\n): Promise<FormattedCapture | null> {\n const extract = await extractCaptureViaLlm(session, llm);\n if (!extract) {\n return null;\n }\n return formattedFromLlmExtract(session, assistant, extract);\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { FormattedCapture } from \"./formatCapture.js\";\n\n// ─── Types ────────────────────────────────────────────\n\nexport type CaptureSource = \"session\" | \"commit\" | \"manual\";\n\nexport type SessionFileStatus = \"pending\" | \"done\" | \"stale\";\n\nexport interface SessionFileFrontmatter {\n sessionId: string;\n source: CaptureSource;\n status: SessionFileStatus;\n domain: string | null; // consolidate 后由 LLM 填写\n createdAt: string; // ISO 8601\n lastModifiedAt: string;\n consolidatedAt: string | null;\n captureCount: number;\n}\n\n// ─── Helpers ──────────────────────────────────────────\n\nfunction isoNow(): string {\n return new Date().toISOString();\n}\n\n/** 从已有文件中解析 frontmatter */\nfunction parseSessionFileFrontmatter(content: string): SessionFileFrontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const frontmatter: Record<string, unknown> = {};\n for (const line of match[1].split(\"\\n\")) {\n const idx = line.indexOf(\":\");\n if (idx === -1) continue;\n const key = line.slice(0, idx).trim();\n const val = line.slice(idx + 1).trim();\n\n // 解析布尔、null 和数字\n if (val === \"null\") frontmatter[key] = null;\n else if (val === \"true\") frontmatter[key] = true;\n else if (val === \"false\") frontmatter[key] = false;\n else if (/^\\d+$/.test(val)) frontmatter[key] = Number.parseInt(val, 10);\n else frontmatter[key] = val.replace(/^[\"']|[\"']$/g, \"\");\n }\n\n return frontmatter as unknown as SessionFileFrontmatter;\n}\n\n/** 序列化 frontmatter 为 YAML 块 */\nfunction serializeSessionFrontmatter(fm: SessionFileFrontmatter): string {\n const lines = [\n \"---\",\n `sessionId: ${fm.sessionId}`,\n `source: ${fm.source}`,\n `status: ${fm.status}`,\n `domain: ${fm.domain ?? null}`,\n `createdAt: ${fm.createdAt}`,\n `lastModifiedAt: ${fm.lastModifiedAt}`,\n `consolidatedAt: ${fm.consolidatedAt ?? null}`,\n `captureCount: ${fm.captureCount}`,\n \"---\",\n ];\n return lines.join(\"\\n\");\n}\n\n/** 格式化单个 capture 段落(追加到文件 body 中) */\nfunction renderCaptureSection(\n formatted: FormattedCapture,\n index: number,\n): string {\n const time = isoNow().slice(11, 19); // HH:mm:ss\n const tagsStr = formatted.tags.map((t) => JSON.stringify(t)).join(\", \");\n\n return [\n \"\",\n `## Capture #${index} — ${time}`,\n `### type: ${formatted.type}`,\n `### tags: [${tagsStr}]`,\n \"\",\n formatted.bodyMarkdown,\n ].join(\"\\n\");\n}\n\n// ─── Core: find or create session file ───────────────\n\n/**\n * 获取或创建 session 文件路径。\n * v2 规则:一个对话对应一个文件 `captures/raw/session-{id}.md`\n */\nexport function resolveSessionFile(\n repoRoot: string,\n sessionId: string,\n): { absolutePath: string; relativePath: string; exists: boolean } {\n const filename = `session-${sessionId}.md`;\n const absolutePath = memoryPath(repoRoot, \"captures\", \"raw\", filename);\n const relativePath = join(\".memory\", \"captures\", \"raw\", filename);\n return { absolutePath, relativePath, exists: existsSync(absolutePath) };\n}\n\n// ─── Legacy: renderCaptureMarkdown (LLM upgrade 用) ────\n\n/**\n * @deprecated v2 保留用于 LLM upgrade 兼容。Phase 2 将移除或重写为 session 文件的增量更新。\n */\nexport function renderCaptureMarkdown(\n formatted: FormattedCapture,\n date: string,\n): string {\n const tagsStr = formatted.tags.map((t) => JSON.stringify(t)).join(\", \");\n const lines = [\n \"---\",\n `type: ${formatted.type}`,\n `date: ${date}`,\n `session: ${formatted.sessionId}`,\n `tags: [${tagsStr}]`,\n `scope: ${formatted.scope}`,\n \"confidence: pending\",\n ];\n if (formatted.llmUpgradedAt) {\n lines.push(`llmUpgradedAt: ${formatted.llmUpgradedAt}`);\n }\n lines.push(\"---\", \"\", formatted.bodyMarkdown);\n return `${lines.join(\"\\n\")}\\n`;\n}\n\n// ─── Core: append capture to session file ─────────────\n\ninterface AppendCaptureResult {\n absolutePath: string;\n relativePath: string;\n filename: string;\n isNewFile: boolean;\n captureIndex: number;\n previousStatus: SessionFileStatus | null;\n}\n\n/**\n * 将一条 capture 追加到对应的 session 文件。\n *\n * 行为:\n * - 文件不存在 → 创建,status=pending\n * - 文件存在 → 追加新的 Capture 段落\n * - 若 status=done → 改为 stale(有新内容需重新 consolidate)\n * - 若 status=stale/pending → 保持不变\n */\nexport function appendCaptureToSession(\n repoRoot: string,\n formatted: FormattedCapture,\n): AppendCaptureResult {\n const { absolutePath, relativePath, exists } = resolveSessionFile(repoRoot, formatted.sessionId);\n const filename = `session-${formatted.sessionId}.md`;\n\n mkdirSync(join(absolutePath, \"..\"), { recursive: true });\n const now = isoNow();\n\n if (!exists) {\n // 新建文件\n const fm: SessionFileFrontmatter = {\n sessionId: formatted.sessionId,\n source: \"session\",\n status: \"pending\",\n domain: null,\n createdAt: now,\n lastModifiedAt: now,\n consolidatedAt: null,\n captureCount: 1,\n };\n\n const content =\n serializeSessionFrontmatter(fm) +\n \"\\n\" +\n renderCaptureSection(formatted, 1) +\n \"\\n\";\n\n writeFileSync(absolutePath, content, \"utf8\");\n\n return {\n absolutePath,\n relativePath,\n filename,\n isNewFile: true,\n captureIndex: 1,\n previousStatus: null,\n };\n }\n\n // 已有文件 → 追加\n const existingContent = readFileSync(absolutePath, \"utf8\");\n const existingFm = parseSessionFileFrontmatter(existingContent);\n\n if (!existingFm) {\n // 格式异常,覆盖写入\n const fm: SessionFileFrontmatter = {\n sessionId: formatted.sessionId,\n source: \"session\",\n status: \"pending\",\n domain: null,\n createdAt: now,\n lastModifiedAt: now,\n consolidatedAt: null,\n captureCount: 1,\n };\n\n writeFileSync(\n absolutePath,\n serializeSessionFrontmatter(fm) +\n \"\\n\" +\n renderCaptureSection(formatted, 1) +\n \"\\n\",\n \"utf8\",\n );\n return {\n absolutePath,\n relativePath,\n filename,\n isNewFile: false,\n captureIndex: 1,\n previousStatus: null,\n };\n }\n\n const previousStatus = existingFm.status;\n const nextIndex = existingFm.captureCount + 1;\n\n // 状态机:done → stale(有新内容需要重新处理)\n const newStatus: SessionFileStatus =\n existingFm.status === \"done\" ? \"stale\" : existingFm.status;\n\n const updatedFm: SessionFileFrontmatter = {\n ...existingFm,\n status: newStatus,\n lastModifiedAt: now,\n captureCount: nextIndex,\n };\n\n // 找到第一个 --- (frontmatter 结束位置)\n const fmEndIndex = existingContent.indexOf(\"---\", 4); // 跳过开头的 ---\n const bodyStart = fmEndIndex >= 0 ? fmEndIndex + 3 : existingContent.length;\n\n const updatedContent =\n serializeSessionFrontmatter(updatedFm) +\n \"\\n\" +\n existingContent.slice(bodyStart) + // 保留原有 body\n renderCaptureSection(formatted, nextIndex) + // 追加新的 capture 段落\n \"\\n\";\n\n writeFileSync(absolutePath, updatedContent, \"utf8\");\n\n return {\n absolutePath,\n relativePath,\n filename,\n isNewFile: false,\n captureIndex: nextIndex,\n previousStatus,\n };\n}\n\n// ─── Legacy compat: writeCaptureFile ──────────────────\n/**\n * @deprecated v2 使用 appendCaptureToSession 替代。保留此函数以兼容尚未迁移的调用方。\n */\nexport function writeCaptureFile(\n repoRoot: string,\n formatted: FormattedCapture,\n _filename?: string,\n): { absolutePath: string; filename: string } {\n const result = appendCaptureToSession(repoRoot, formatted);\n return { absolutePath: result.absolutePath, filename: result.filename };\n}\n\n/** 更新 session 文件的 consolidate 状态 */\nexport function markSessionConsolidated(\n repoRoot: string,\n sessionId: string,\n): void {\n const { absolutePath, exists } = resolveSessionFile(repoRoot, sessionId);\n if (!exists) return;\n\n const content = readFileSync(absolutePath, \"utf8\");\n const fm = parseSessionFileFrontmatter(content);\n if (!fm) return;\n\n const updatedFm: SessionFileFrontmatter = {\n ...fm,\n status: \"done\",\n consolidatedAt: isoNow(),\n };\n\n const fmEndIndex = content.indexOf(\"---\", 4);\n const bodyStart = fmEndIndex >= 0 ? fmEndIndex + 3 : content.length;\n\n writeFileSync(\n absolutePath,\n serializeSessionFrontmatter(updatedFm) + \"\\n\" + content.slice(bodyStart),\n \"utf8\",\n );\n}\n","import { debugLog } from \"./config/debugLog.js\";\n\n/** Hook 路径下失败仍 exit 0,避免阻塞 Claude Code */\nexport function hookExit(code: number, strict?: boolean): never {\n process.exit(strict ? code : code === 0 ? 0 : 0);\n}\n\nexport function finalizeHookCommand(\n fn: () => void | Promise<void>,\n strict?: boolean,\n debug?: boolean,\n): void {\n void (async () => {\n try {\n await fn();\n process.exit(0);\n } catch (error) {\n debugLog(debug === true, \"hook\", error instanceof Error ? error.message : String(error));\n process.exit(strict ? 1 : 0);\n }\n })();\n}\n","import { configureDebugLogging } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { flushPendingLlmJobs, runLlmJobById } from \"../capture/runLlmJob.js\";\nimport { finalizeHookCommand } from \"../hookExit.js\";\n\nexport interface CaptureLlmCommandOptions {\n cwd?: string;\n job?: string;\n flush?: boolean;\n strict?: boolean;\n}\n\nexport function runCaptureLlmCommand(opts: CaptureLlmCommandOptions): void {\n const ctx = loadRepoContext(opts.cwd);\n const debug = ctx?.config.debug === true;\n configureDebugLogging(ctx?.repoRoot ?? null, debug);\n\n finalizeHookCommand(async () => {\n if (!ctx) {\n console.error(\"hermes-repo: not initialized\");\n return;\n }\n const repoRoot = ctx.repoRoot;\n\n if (opts.flush) {\n const n = await flushPendingLlmJobs(repoRoot, debug);\n if (debug) {\n console.error(`hermes-repo: flushed ${n} llm job(s)`);\n }\n return;\n }\n\n if (!opts.job) {\n console.error(\"hermes-repo capture-llm: require --job <id> or --flush\");\n return;\n }\n\n const result = await runLlmJobById(repoRoot, opts.job, debug);\n if (!result.ok && opts.strict) {\n throw new Error(result.reason ?? \"capture-llm failed\");\n }\n }, opts.strict, debug);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nexport type HookInput = {\n /** Claude / CodeBuddy Stop hook(文件存在时已 resolve) */\n transcriptPath?: string;\n /** hook stdin 中的 transcript_path 原值(无论文件是否存在) */\n transcriptPathRaw?: string;\n hookEventName?: string;\n sessionId?: string;\n conversationId?: string;\n workspaceRoots?: string[];\n status?: string;\n};\n\nfunction pickString(obj: Record<string, unknown>, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const v = obj[key];\n if (typeof v === \"string\" && v.length > 0) {\n return v;\n }\n }\n return undefined;\n}\n\nfunction pickStringArray(\n obj: Record<string, unknown>,\n ...keys: string[]\n): string[] | undefined {\n for (const key of keys) {\n const v = obj[key];\n if (Array.isArray(v)) {\n const roots = v.filter((x): x is string => typeof x === \"string\");\n if (roots.length > 0) {\n return roots;\n }\n }\n }\n return undefined;\n}\n\n/** 路径是否属于某助手 transcript 根目录 */\nexport function isTranscriptUnderAssistant(\n transcriptPath: string | undefined,\n segment: \".codebuddy\" | \".claude\",\n): boolean {\n if (!transcriptPath) {\n return false;\n }\n const normalized = transcriptPath.replace(/\\\\/g, \"/\");\n return normalized.includes(`${segment}/`);\n}\n\nexport function parseHookInputJson(raw: string): HookInput | null {\n const trimmed = raw.trim();\n if (!trimmed) {\n return null;\n }\n try {\n const parsed = JSON.parse(trimmed) as Record<string, unknown>;\n const transcriptRaw = pickString(parsed, \"transcript_path\", \"transcriptPath\");\n const transcriptPath =\n transcriptRaw && existsSync(transcriptRaw) ? resolve(transcriptRaw) : undefined;\n\n return {\n transcriptPath,\n transcriptPathRaw: transcriptRaw,\n hookEventName: pickString(parsed, \"hook_event_name\", \"hookEventName\"),\n sessionId: pickString(parsed, \"session_id\", \"sessionId\"),\n conversationId: pickString(parsed, \"conversation_id\", \"conversationId\"),\n workspaceRoots: pickStringArray(parsed, \"workspace_roots\", \"workspaceRoots\"),\n status: pickString(parsed, \"status\"),\n };\n } catch {\n return null;\n }\n}\n\n/** 从 hook stdin 读取一次(非 TTY 时) */\nexport function readHookInputSync(): HookInput | null {\n if (process.stdin.isTTY) {\n return null;\n }\n try {\n const raw = readFileSync(0, \"utf8\");\n return parseHookInputJson(raw);\n } catch {\n return null;\n }\n}\n\nexport function isCodebuddyCaptureHook(hook: HookInput | null | undefined): boolean {\n if (!hook) {\n return false;\n }\n return (\n isTranscriptUnderAssistant(hook.transcriptPath, \".codebuddy\") ||\n isTranscriptUnderAssistant(hook.transcriptPathRaw, \".codebuddy\")\n );\n}\n\nexport function isClaudeCaptureHook(hook: HookInput | null | undefined): boolean {\n if (!hook) {\n return false;\n }\n if (isCodebuddyCaptureHook(hook)) {\n return false;\n }\n if (isTranscriptUnderAssistant(hook.transcriptPath, \".claude\")) {\n return true;\n }\n if (hook.transcriptPath) {\n return true;\n }\n const name = hook.hookEventName?.toLowerCase();\n return name === \"stop\" && !hook.sessionId && !hook.conversationId;\n}\n\nexport function isCursorCaptureHook(hook: HookInput | null | undefined): boolean {\n if (!hook) {\n return false;\n }\n if (hook.transcriptPath) {\n if (\n isTranscriptUnderAssistant(hook.transcriptPath, \".codebuddy\") ||\n isTranscriptUnderAssistant(hook.transcriptPath, \".claude\")\n ) {\n return false;\n }\n }\n const name = hook.hookEventName?.toLowerCase();\n if (name === \"stop\") {\n return true;\n }\n return Boolean(hook.sessionId || hook.conversationId);\n}\n\nexport function isCursorInjectHook(hook: HookInput | null | undefined): boolean {\n if (!hook) {\n return false;\n }\n const name = hook.hookEventName?.toLowerCase();\n return name === \"sessionstart\";\n}\n","import type { ParsedSession } from \"./types.js\";\n\n/**\n * 修复 3:信号强度分级\n * 从二元判断(有/无)改进为多级评分(强/中/弱/无)\n * 根据信号强度和对话复杂度加权决策\n */\n\nexport type SignalStrength = \"strong\" | \"medium\" | \"weak\" | \"none\";\n\nconst STRONG_SIGNAL_RE = /改成|不对|错了|应该是|决定用|约定是|必须|架构/i;\nconst MEDIUM_SIGNAL_RE =\n /考虑|也许|可能|试试|我们可以|看起来|似乎|建议|优化/i;\nconst WEAK_SIGNAL_RE = /为什么|怎样|怎么|什么时候|哪里|如何/i;\n\n/**\n * 判断文本的信号强度\n * strong: 明确的决策或纠正\n * medium: 有价值但不确定的建议\n * weak: 可能有价值的探索性问题\n * none: 无信号\n */\nexport function getSignalStrength(text: string): SignalStrength {\n if (STRONG_SIGNAL_RE.test(text)) {\n return \"strong\";\n }\n if (MEDIUM_SIGNAL_RE.test(text)) {\n return \"medium\";\n }\n if (WEAK_SIGNAL_RE.test(text)) {\n return \"weak\";\n }\n return \"none\";\n}\n\n/**\n * 根据信号强度和对话复杂度加权决策\n */\nexport function shouldCaptureBySignalStrength(session: ParsedSession): boolean {\n const strength = getSignalStrength(session.text);\n\n // 强信号:始终保留\n if (strength === \"strong\") {\n return true;\n }\n\n // 中等信号:需要多轮对话或复杂任务\n if (strength === \"medium\") {\n return session.messages.length >= 4 || session.toolCalls > 3;\n }\n\n // 弱信号:只有特别复杂的任务才保留\n if (strength === \"weak\") {\n return session.toolCalls > 8 || session.fileChanges > 5;\n }\n\n // 无信号:返回 false,让其他逻辑决策\n return false;\n}\n\n/**\n * 为捕获计算综合强度分数(0-100)\n * 考虑文本信号、会话复杂度、文件修改等多个因子\n */\nexport function computeSignalScore(session: ParsedSession): number {\n let score = 0;\n\n // 文本信号权重:30 分\n const strength = getSignalStrength(session.text);\n if (strength === \"strong\") {\n score += 30;\n } else if (strength === \"medium\") {\n score += 15;\n } else if (strength === \"weak\") {\n score += 5;\n }\n\n // 会话复杂度权重:30 分\n const messageBonus = Math.min(30, (session.messages.length - 2) * 5);\n score += Math.max(0, messageBonus);\n\n // 工具调用权重:20 分\n const toolBonus = Math.min(20, session.toolCalls * 2);\n score += toolBonus;\n\n // 文件修改权重:20 分\n const fileBonus = Math.min(20, session.fileChanges * 5);\n score += fileBonus;\n\n return Math.min(100, score);\n}\n\n/**\n * 根据综合分数决策是否捕获\n * < 40: 不捕获\n * 40-70: 边界情况(可选 LLM 判断)\n * > 70: 捕获\n */\nexport function shouldCaptureByScore(session: ParsedSession): boolean {\n const score = computeSignalScore(session);\n return score >= 70;\n}\n","import type { ParsedSession } from \"./types.js\";\nimport {\n computeSignalScore,\n getSignalStrength,\n} from \"./signalStrength.js\";\n\nconst ARCHITECTURE_SIGNAL_RE =\n /约定|必须|架构|决策|规范|根因|migration|refactor|convention|root cause/i;\nconst CORRECTION_RE =\n /不对|错了|不是这样|不应该|别用|stop|wrong|incorrect|改成|修正/i;\n\n/** 内联:用户纠正检测(原 shouldCapture.ts) */\nfunction hasUserCorrection(session: ParsedSession): boolean {\n return session.messages.some(\n (m) => m.role === \"user\" && CORRECTION_RE.test(m.text),\n );\n}\n\nexport function hasArchitectureSignal(text: string): boolean {\n return ARCHITECTURE_SIGNAL_RE.test(text);\n}\n\n/**\n * 判断会话是否需要 LLM 升级\n *\n * 触发条件(满足任一即可):\n * 1. 高复杂度:消息数、文件修改、工具调用达到阈值\n * 2. 强信号:明确决策、约定、架构相关\n * 3. 用户纠正:用户有纠正行为\n * 4. 组合条件:中等复杂度 + 中等信号\n * 5. 综合分数:分数 ≥ 55\n */\nexport function needsLlm(session: ParsedSession): boolean {\n // 1. 高复杂度会话\n if (session.messages.length >= 20) return true;\n if (session.fileChanges >= 3) return true;\n if (session.toolCalls >= 8) return true;\n\n // 2. 强信号(重要约定、决策应被 LLM 提炼)\n const strength = getSignalStrength(session.text);\n if (strength === \"strong\") return true;\n\n // 3. 架构信号\n if (hasArchitectureSignal(session.text)) return true;\n\n // 4. 用户纠正(纠正过程有价值,需要 LLM 总结)\n if (hasUserCorrection(session)) return true;\n\n // 5. 组合条件:中等复杂度 + 有实质工作\n if (session.messages.length >= 10 && session.toolCalls >= 5) return true;\n if (strength === \"medium\" && session.fileChanges >= 2) return true;\n if (session.toolCalls >= 5 && session.fileChanges >= 1) return true;\n\n // 6. 基于综合分数\n const score = computeSignalScore(session);\n if (score >= 55) return true;\n\n return false;\n}\n","import { spawn } from \"node:child_process\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { debugLog } from \"../config/debugLog.js\";\nimport { isLlmAvailable } from \"../config/llmConfig.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport type { ConsolidateConfig } from \"../config/types.js\";\nimport {\n runConsolidate,\n type ConsolidateResultV2,\n} from \"./runConsolidate.js\";\nimport { CONSOLIDATE_LOCK_TTL_MS } from \"./constants.js\";\nimport {\n scanAllSessions,\n filterPendingSessions,\n type ScannedSession,\n} from \"./sessionScanner.js\";\nimport {\n readConsolidateLock,\n isLockStale,\n readConsolidateState,\n} from \"./state.js\";\n\nfunction cliPath(): string {\n return join(dirname(fileURLToPath(import.meta.url)), \"..\", \"cli.js\");\n}\n\n/**\n * v2: flush 命令入口。\n * 直接调用 runConsolidate(单次 LLM 调用)。\n */\nexport async function runFlushCommand(opts: {\n cwd?: string;\n force?: boolean;\n dryRun?: boolean;\n debug?: boolean;\n}): Promise<ConsolidateResultV2> {\n const ctx = loadRepoContext(opts.cwd);\n if (!ctx) {\n return {\n ran: false,\n reason: \"not-initialized\",\n sessionsProcessed: 0,\n knowledgeCreated: 0,\n knowledgeUpdated: 0,\n skippedCount: 0,\n archived: 0,\n };\n }\n\n // 检查是否有可处理的 session\n const allSessions = scanAllSessions(ctx.repoRoot);\n const pendingSessions = opts.force\n ? allSessions\n : filterPendingSessions(allSessions);\n\n if (pendingSessions.length === 0 && !opts.force && !opts.dryRun) {\n return {\n ran: false,\n reason: \"no-pending-sessions\",\n sessionsProcessed: 0,\n knowledgeCreated: 0,\n knowledgeUpdated: 0,\n skippedCount: 0,\n archived: 0,\n };\n }\n\n return runConsolidate({\n repoRoot: ctx.repoRoot,\n config: ctx.config,\n force: opts.force,\n dryRun: opts.dryRun,\n debug: opts.debug ?? ctx.config.debug,\n });\n}\n\nexport function shouldAutoFlush(\n sessions: ScannedSession[],\n consolidate: ConsolidateConfig,\n lastConsolidatedAt: string,\n): boolean {\n const autoFlush = consolidate.autoFlush;\n if (!autoFlush.enabled || sessions.length === 0) {\n return false;\n }\n\n if (sessions.length >= autoFlush.minPendingSessions) {\n return true;\n }\n\n const pendingChars = sessions.reduce(\n (sum, session) => sum + session.bodyContent.length,\n 0,\n );\n if (pendingChars >= autoFlush.maxPendingChars) {\n return true;\n }\n\n const last = Date.parse(lastConsolidatedAt);\n if (Number.isNaN(last)) {\n return true;\n }\n\n const minIntervalMs = autoFlush.minIntervalMinutes * 60 * 1000;\n return Date.now() - last >= minIntervalMs;\n}\n\n/**\n * v2: 自动调度 consolidate(由 capture hook 触发)。\n */\nexport function maybeScheduleConsolidate(opts: {\n repoRoot: string;\n debug?: boolean;\n}): void {\n const ctx = loadRepoContext(opts.repoRoot);\n if (!ctx) {\n return;\n }\n\n const autoFlush = ctx.config.consolidate.autoFlush;\n if (!autoFlush.enabled) {\n return;\n }\n\n if (!isLlmAvailable(ctx.config.llm)) {\n debugLog(opts.debug === true, \"consolidate\", \"auto flush skipped: llm not available\");\n return;\n }\n\n const lock = readConsolidateLock(opts.repoRoot);\n if (lock && !isLockStale(lock, CONSOLIDATE_LOCK_TTL_MS)) {\n debugLog(opts.debug === true, \"consolidate\", \"auto flush skipped: lock held\");\n return; // 锁已被持有\n }\n\n const pendingSessions = filterPendingSessions(scanAllSessions(opts.repoRoot));\n const state = readConsolidateState(opts.repoRoot);\n if (\n !shouldAutoFlush(\n pendingSessions,\n ctx.config.consolidate,\n state.lastConsolidatedAt,\n )\n ) {\n debugLog(\n opts.debug === true,\n \"consolidate\",\n `auto flush skipped: ${pendingSessions.length} pending session(s) below thresholds`,\n );\n return;\n }\n\n try {\n const child = spawn(\n process.execPath,\n [cliPath(), \"flush\", \"-C\", opts.repoRoot],\n {\n detached: true,\n stdio: \"ignore\",\n cwd: opts.repoRoot,\n },\n );\n child.unref();\n debugLog(\n opts.debug === true,\n \"consolidate\",\n `auto flush scheduled: ${pendingSessions.length} pending session(s)`,\n );\n } catch (err) {\n debugLog(\n opts.debug === true,\n \"consolidate\",\n `auto flush spawn failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n","import {\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { memoryPath } from \"../init/paths.js\";\n\n// ─── v2 状态模型 ─────────────────────────────\n\nexport interface SessionStatusRecord {\n status: \"pending\" | \"done\" | \"stale\";\n consolidatedAt: string | null;\n lastCaptureAt: string;\n}\n\nexport interface ConsolidateStateV2 {\n version: 2;\n lastConsolidatedAt: string;\n stats: {\n totalCapturesProcessed: number;\n domains: string[];\n knowledgeFilesCreated: number;\n };\n /** sessionId → status record */\n processedSessions: Record<string, SessionStatusRecord>;\n}\n\nconst EMPTY_STATE: ConsolidateStateV2 = {\n version: 2,\n lastConsolidatedAt: new Date(0).toISOString(),\n stats: {\n totalCapturesProcessed: 0,\n domains: [],\n knowledgeFilesCreated: 0,\n },\n processedSessions: {},\n};\n\nexport function consolidateStatePath(repoRoot: string): string {\n return memoryPath(repoRoot, \"consolidate-state.json\");\n}\n\nexport function consolidateLockPath(repoRoot: string): string {\n return memoryPath(repoRoot, \".consolidate.lock\");\n}\n\nexport function readConsolidateState(repoRoot: string): ConsolidateStateV2 {\n const path = consolidateStatePath(repoRoot);\n if (!existsSync(path)) {\n return { ...EMPTY_STATE, processedSessions: {} };\n }\n try {\n const raw = JSON.parse(readFileSync(path, \"utf8\")) as unknown;\n // v1 → v2 自动升级\n if (typeof raw === \"object\" && raw !== null) {\n const obj = raw as Record<string, unknown>;\n if (obj.version === 2 && typeof obj.processedSessions === \"object\") {\n return raw as ConsolidateStateV2;\n }\n // v1 升级:processedCapturePaths → 空 processedSessions\n return {\n ...EMPTY_STATE,\n lastConsolidatedAt:\n typeof obj.lastConsolidatedAt === \"string\"\n ? obj.lastConsolidatedAt\n : EMPTY_STATE.lastConsolidatedAt,\n };\n }\n return { ...EMPTY_STATE, processedSessions: {} };\n } catch {\n return { ...EMPTY_STATE, processedSessions: {} };\n }\n}\n\nexport function writeConsolidateState(\n repoRoot: string,\n state: ConsolidateStateV2,\n): void {\n const path = consolidateStatePath(repoRoot);\n mkdirSync(memoryPath(repoRoot), { recursive: true });\n writeFileSync(path, `${JSON.stringify(state, null, 2)}\\n`, \"utf8\");\n}\n\n// ─── Lock(保留不变)─────────────────────────\n\nexport interface ConsolidateLock {\n pid: number;\n startedAt: string;\n}\n\nexport function readConsolidateLock(repoRoot: string): ConsolidateLock | null {\n const path = consolidateLockPath(repoRoot);\n if (!existsSync(path)) {\n return null;\n }\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as ConsolidateLock;\n } catch {\n return null;\n }\n}\n\nexport function writeConsolidateLock(repoRoot: string): void {\n const payload: ConsolidateLock = {\n pid: process.pid,\n startedAt: new Date().toISOString(),\n };\n mkdirSync(memoryPath(repoRoot), { recursive: true });\n writeFileSync(\n consolidateLockPath(repoRoot),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n}\n\nexport function releaseConsolidateLock(repoRoot: string): void {\n const path = consolidateLockPath(repoRoot);\n if (existsSync(path)) {\n rmSync(path, { force: true });\n }\n}\n\nexport function isLockStale(\n lock: ConsolidateLock,\n ttlMs: number,\n): boolean {\n const started = Date.parse(lock.startedAt);\n if (Number.isNaN(started)) {\n return true;\n }\n return Date.now() - started > ttlMs;\n}\n","import { readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { SessionFileFrontmatter } from \"../capture/writeCapture.js\";\n\n// ─── Types ────────────────────────────────────\n\nexport interface ScannedSession {\n sessionId: string;\n filename: string;\n absolutePath: string;\n relativePath: string;\n frontmatter: SessionFileFrontmatter;\n bodyContent: string; // frontmatter 之后的完整 body\n}\n\n// ─── 解析 session 文件 frontmatter ───────────\n\nfunction parseSessionFrontmatter(\n content: string,\n): SessionFileFrontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: Record<string, unknown> = {};\n for (const line of match[1].split(\"\\n\")) {\n const idx = line.indexOf(\":\");\n if (idx === -1) continue;\n const key = line.slice(0, idx).trim();\n const val = line.slice(idx + 1).trim();\n\n if (val === \"null\") fm[key] = null;\n else if (val === \"true\") fm[key] = true;\n else if (val === \"false\") fm[key] = false;\n else if (/^\\d+$/.test(val)) fm[key] = Number.parseInt(val, 10);\n else fm[key] = val.replace(/^[\"']|[\"']$/g, \"\");\n }\n\n return fm as unknown as SessionFileFrontmatter;\n}\n\n// ─── 扫描 captures/raw/ ──────────────────────\n\n/**\n * 扫描 captures/raw/ 下所有 session 文件,返回全部。\n */\nexport function scanAllSessions(repoRoot: string): ScannedSession[] {\n const rawDir = memoryPath(repoRoot, \"captures\", \"raw\");\n let files: string[];\n try {\n files = readdirSync(rawDir).filter((f) => f.endsWith(\".md\"));\n } catch {\n return [];\n }\n\n const sessions: ScannedSession[] = [];\n for (const file of files) {\n const absolutePath = join(rawDir, file);\n try {\n const content = readFileSync(absolutePath, \"utf8\");\n const fm = parseSessionFrontmatter(content);\n if (!fm || !fm.sessionId) continue;\n\n // 提取 body(frontmatter 之后的内容)\n const fmEndIndex = content.indexOf(\"---\", 4);\n const bodyStart = fmEndIndex >= 0 ? fmEndIndex + 3 : content.length;\n const bodyContent = content.slice(bodyStart);\n\n sessions.push({\n sessionId: fm.sessionId,\n filename: file,\n absolutePath,\n relativePath: join(\".memory\", \"captures\", \"raw\", file),\n frontmatter: fm,\n bodyContent: bodyContent.trim(),\n });\n } catch {\n // 跳过无法解析的文件\n }\n }\n\n // 按最后修改时间倒序(优先处理最近的)\n sessions.sort(\n (a, b) =>\n new Date(b.frontmatter.lastModifiedAt).getTime() -\n new Date(a.frontmatter.lastModifiedAt).getTime(),\n );\n\n return sessions;\n}\n\n/**\n * 过滤出需要 consolidate 的 session 文件(pending + stale)。\n */\nexport function filterPendingSessions(\n sessions: ScannedSession[],\n): ScannedSession[] {\n return sessions.filter(\n (s) =>\n s.frontmatter.status === \"pending\" ||\n s.frontmatter.status === \"stale\",\n );\n}\n","import { readFileSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { LlmConfigV2 } from \"../config/types.js\";\nimport { debugLog, debugLogBlock } from \"../config/debugLog.js\";\nimport type { ScannedSession } from \"./sessionScanner.js\";\n\n// ─── Types ────────────────────────────────────\n\nexport interface ExistingKnowledge {\n path: string;\n title: string;\n type: \"rule\" | \"domain-knowledge\" | \"workflow\" | \"decision\" | \"incident\";\n domain: string | null;\n status: string;\n summary: string;\n}\n\nexport interface LlmConsolidateInput {\n pendingSessions: PendingSessionInput[];\n existingKnowledge: ExistingKnowledge[];\n currentMemoryMd: string | null;\n}\n\nexport interface PendingSessionInput {\n sessionId: string;\n status: \"pending\" | \"stale\";\n content: string; // 完整的 markdown(含 frontmatter + body)\n captureCount: number;\n createdAt: string;\n}\n\nexport interface KnowledgeFileOutput {\n targetPath: string;\n action: \"create\" | \"update\";\n frontmatter: Record<string, unknown>;\n body: string;\n}\n\nexport interface LlmConsolidateResult {\n knowledgeFiles: KnowledgeFileOutput[];\n memoryMd: string;\n skippedSessions: Array<{ sessionId: string; reason: string }>;\n}\n\n// ─── System Prompt ────────────────────────────\n\nconst CONSOLIDATE_SYSTEM_PROMPT = `你是一个项目知识整理专家。你的任务是从 AI 编程助手的对话记录中提炼出结构化的知识库。\n\n## 工作流程\n\n### 第一步:分析理解\n通读所有待处理的 session 记录,理解:\n- 讨论了哪些业务领域(模块、子系统、功能)\n- 产生了哪类知识(规范、事实、流程、决策、踩坑)\n- 哪些内容有长期保留价值,哪些是临时噪音\n\n### 第二步:域识别与匹配\n为每条有价值的内容确定所属业务域:\n- 查看 existingKnowledge 中已有的域列表\n- 优先复用已有域,只有确实无法匹配时才新建域\n- 无法归类的放入 general 域\n- 域名用 kebab-case,简洁明了(如 quoted, inventory, payment)\n- 不要创建过于细粒度的域(如不要按文件名建域)\n\n### 第三步:分类判定\n\n| 类型 | 判定条件 | 写入目录 |\n|------|---------|---------|\n| rule | 编码规范、约定、禁令 | rules/{name}.md |\n| domain-knowledge | 业务域的事实、概念、数据模型 | domains/{domain}/{name}.md |\n| workflow | 可复用的操作步骤、流程 | workflows/{name}.md |\n| decision | 架构选型、方案选择及原因 | decisions/{date}-{slug}.md |\n| incident | 踩坑记录、问题根因、修复方式 | incidents/{date}-{slug}.md |\n\n分类优先级:\n1. 如果是可执行的步骤流程 → workflow\n2. 如果是\"为什么选了X而不是Y\" → decision\n3. 如果是\"遇到了X问题,原因是Y,修法是Z\" → incident\n4. 如果是编码规范、团队约定 → rule\n5. 其余 → domain-knowledge(默认)\n\n### 第四步:内容提炼\n对归类后的内容进行提炼:\n\n提炼原则:\n1. 去除口语化表达、重复讨论、中间错误结论\n2. 保留最终确定的结论和关键决策过程\n3. 用结构化的 markdown 组织(标题、列表、表格、代码块)\n4. 区分\"事实\"和\"推断\",对不确定的内容标注 confidence: low\n5. 保留足够的上下文让未来阅读者理解背景\n\n如果是更新已有文件(action=update):\n- 对比新旧内容,保留仍有效的部分\n- 更新被修正的部分(标注更新日期)\n- 追加全新内容\n- 移除已被完全替代的旧段落\n\n### 第五步:生成导航 (MEMORY.md)\n重新生成导航页面:\n\n组织原则:\n1. rules 放最前(必读),每项一行:[路径](链接) — 摘要\n2. domains 按域分组表格展示\n3. workflows 简短列出\n4. decisions/incidents 只显示计数和最近几条\n5. 每个摘要控制在 20 字以内\n6. 整体保持紧凑(目标 < 100 行),AI 注入时不会太长\n7. 保留用户的自定义编辑标记 <!-- user-edit-start --> ... <!-- user-edit-end -->\n\n## 输出要求\n- 输出严格 JSON 格式\n- knowledgeFiles 数组包含所有需要创建/更新的文件\n - 每项必须包含完整的 frontmatter 和 body markdown\n- memoryMd 是完整 MEMORY.md 内容\n- 无价值的 session 在 skippedSessions 中说明原因(而非生成空内容)`;\n\n// ─── 扫描已有知识文件 ───────────────────────\n\n/**\n * 扫描 rules/, domains/, workflows/, decisions/, incidents/\n * 返回已有知识文件的摘要列表。\n */\nexport function scanExistingKnowledge(repoRoot: string): ExistingKnowledge[] {\n const results: ExistingKnowledge[] = [];\n\n // 定义各类型目录和对应的 type\n const typeDirs: Array<{ dir: string; type: ExistingKnowledge[\"type\"] }> = [\n { dir: \"rules\", type: \"rule\" },\n { dir: \"workflows\", type: \"workflow\" },\n { dir: \"decisions\", type: \"decision\" },\n { dir: \"incidents\", type: \"incident\" },\n ];\n\n for (const { dir, type } of typeDirs) {\n const absDir = memoryPath(repoRoot, dir);\n scanMarkdownDirectory(absDir, dir, type, null, results);\n }\n\n // domains 下可能有多个子目录\n const domainsDir = memoryPath(repoRoot, \"domains\");\n try {\n const subdirs = readdirSync(domainsDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n\n for (const domain of subdirs) {\n const domainAbsDir = join(domainsDir, domain);\n scanMarkdownDirectory(\n domainAbsDir,\n `domains/${domain}`,\n \"domain-knowledge\",\n domain,\n results,\n );\n }\n } catch {\n // domains 目录不存在\n }\n\n return results;\n}\n\nfunction scanMarkdownDirectory(\n absoluteDir: string,\n relativePrefix: string,\n type: ExistingKnowledge[\"type\"],\n domain: string | null,\n results: ExistingKnowledge[],\n): void {\n let files: string[];\n try {\n files = readdirSync(absoluteDir).filter((f) => f.endsWith(\".md\"));\n } catch {\n return;\n }\n\n for (const file of files) {\n try {\n const content = readFileSync(join(absoluteDir, file), \"utf8\");\n // 解析 frontmatter 提取 title\n const fmMatch = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n let title = file.replace(/\\.md$/, \"\");\n if (fmMatch) {\n const titleMatch = fmMatch[1].match(/^title:\\s*(.+)$/m);\n if (titleMatch) title = titleMatch[1].replace(/^[\"']|[\"']$/g, \"\");\n }\n\n // 取前 100 字作为摘要\n const bodyStart = content.indexOf(\"---\", 4);\n const body =\n bodyStart >= 0 ? content.slice(bodyStart + 3).trim() : content;\n const summary = body.slice(0, 150).replace(/\\n/g, \" \").trim();\n\n results.push({\n path: `${relativePrefix}/${file}`,\n title,\n type,\n domain,\n status: \"active\",\n summary,\n });\n } catch {\n // 跳过无法读取的文件\n }\n }\n}\n\n// ─── 构建 LLM Input ──────────────────────────\n\nexport function buildLlmConsolidateInput(\n repoRoot: string,\n sessions: ScannedSession[],\n): LlmConsolidateInput {\n const pendingSessions: PendingSessionInput[] = sessions.map((s) => ({\n sessionId: s.sessionId,\n status: s.frontmatter.status as \"pending\" | \"stale\",\n content: readFileSync(s.absolutePath, \"utf8\"),\n captureCount: s.frontmatter.captureCount,\n createdAt: s.frontmatter.createdAt,\n }));\n\n const existingKnowledge = scanExistingKnowledge(repoRoot);\n\n // 读取当前 MEMORY.md\n const memoryPathAbs = memoryPath(repoRoot, \"MEMORY.md\");\n let currentMemoryMd: string | null = null;\n try {\n currentMemoryMd = readFileSync(memoryPathAbs, \"utf8\");\n } catch {\n // 不存在则传 null\n }\n\n return {\n pendingSessions,\n existingKnowledge,\n currentMemoryMd,\n };\n}\n\n// ─── 调用 LLM ────────────────────────────────\n\n/**\n * 单次 LLM 调用完成完整 consolidate。\n *\n * @throws 当 LLM 未配置或调用失败时抛出错误\n */\nexport async function callLlmConsolidate(\n input: LlmConsolidateInput,\n llmConfig: LlmConfigV2,\n debug = false,\n): Promise<LlmConsolidateResult> {\n if (!llmConfig.enabled) {\n throw new Error(\n \"LLM 未启用:请在 config.json 中设置 llm.enabled = true\",\n );\n }\n\n if (!llmConfig.apiKey.trim() || !llmConfig.baseUrl.trim() || !llmConfig.model.trim()) {\n throw new Error(\n \"LLM 未配置:请在 config.json 中设置 llm.apiKey、llm.baseUrl 和 llm.model\",\n );\n }\n\n const url = `${llmConfig.baseUrl.replace(/\\/$/, \"\")}/chat/completions`;\n\n // 构造 user message — 将 input 序列化为 JSON\n const userContent = formatUserMessage(input);\n debugLog(\n debug,\n \"llm\",\n `request: provider=${llmConfig.provider}, model=${llmConfig.model}, baseUrl=${llmConfig.baseUrl}, pendingSessions=${input.pendingSessions.length}, existingKnowledge=${input.existingKnowledge.length}, currentMemoryChars=${input.currentMemoryMd?.length ?? 0}`,\n );\n debugLogBlock(debug, \"llm\", \"system prompt\", CONSOLIDATE_SYSTEM_PROMPT);\n debugLogBlock(debug, \"llm\", \"user input\", userContent);\n\n const requestBody = {\n model: llmConfig.model,\n response_format: { type: \"json_object\" },\n messages: [\n { role: \"system\", content: CONSOLIDATE_SYSTEM_PROMPT },\n { role: \"user\", content: userContent },\n ],\n temperature: 0.2,\n };\n debugLogBlock(debug, \"llm\", \"request body\", JSON.stringify(requestBody, null, 2));\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 120_000); // 2 分钟超时\n\n try {\n const res = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${llmConfig.apiKey}`,\n },\n body: JSON.stringify(requestBody),\n signal: controller.signal,\n });\n debugLog(debug, \"llm\", `response status: ${res.status} ${res.statusText}`);\n\n if (!res.ok) {\n const errBody = await res.text().catch(() => \"\");\n debugLogBlock(debug, \"llm\", \"error response body\", errBody);\n throw new Error(\n `LLM API 错误 (${res.status}): ${errBody.slice(0, 300)}`,\n );\n }\n\n const data = (await res.json()) as {\n choices?: Array<{ message?: { content?: string } }>;\n };\n debugLogBlock(debug, \"llm\", \"response json\", JSON.stringify(data, null, 2));\n const rawContent = data.choices?.[0]?.message?.content;\n\n if (!rawContent) {\n throw new Error(\"LLM 返回内容为空\");\n }\n debugLogBlock(debug, \"llm\", \"raw message content\", rawContent);\n\n // 解析 JSON\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawContent);\n } catch {\n throw new Error(\"LLM 返回内容不是合法 JSON\");\n }\n debugLogBlock(debug, \"llm\", \"parsed content\", JSON.stringify(parsed, null, 2));\n\n const normalized = validateAndNormalizeLlmResult(parsed);\n debugLog(\n debug,\n \"llm\",\n `normalized: knowledgeFiles=${normalized.knowledgeFiles.length}, memoryChars=${normalized.memoryMd.length}, skippedSessions=${normalized.skippedSessions.length}`,\n );\n debugLogBlock(\n debug,\n \"llm\",\n \"normalized knowledgeFiles\",\n JSON.stringify(normalized.knowledgeFiles, null, 2),\n );\n debugLogBlock(debug, \"llm\", \"normalized memoryMd\", normalized.memoryMd);\n debugLogBlock(\n debug,\n \"llm\",\n \"normalized skippedSessions\",\n JSON.stringify(normalized.skippedSessions, null, 2),\n );\n\n return normalized;\n } catch (err) {\n debugLog(\n debug,\n \"llm\",\n `error: ${err instanceof Error ? err.message : String(err)}`,\n );\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n}\n\n// ─── 格式化 user message ─────────────────────\n\nfunction formatUserMessage(input: LlmConsolidateInput): string {\n // 截断 session 内容避免过长(保留前 8000 字符)\n const maxSessionChars = 8000;\n const truncatedSessions = input.pendingSessions.map((s) => ({\n ...s,\n content:\n s.content.length > maxSessionChars\n ? s.content.slice(0, maxSessionChars) +\n `\\n\\n... [截断,原始长度: ${s.content.length} 字符]`\n : s.content,\n }));\n\n return JSON.stringify(\n {\n pendingSessions: truncatedSessions,\n existingKnowledge: input.existingKnowledge.map((k) => ({\n path: k.path,\n title: k.title,\n type: k.type,\n domain: k.domain,\n status: k.status,\n summary: k.summary,\n })),\n currentMemoryMd: input.currentMemoryMd ?? \"\",\n },\n null,\n 2,\n );\n}\n\n// ─── 验证 & 标准化 LLM 返回结果 ───────────────\n\nfunction validateAndNormalizeLlmResult(\n raw: unknown,\n): LlmConsolidateResult {\n if (!raw || typeof raw !== \"object\") {\n throw new Error(\"LLM 返回格式错误:期望 JSON 对象\");\n }\n\n const obj = raw as Record<string, unknown>;\n\n const knowledgeFiles: KnowledgeFileOutput[] = Array.isArray(obj.knowledgeFiles)\n ? (obj.knowledgeFiles as unknown[]).map(normalizeKnowledgeFile).filter(Boolean) as KnowledgeFileOutput[]\n : [];\n\n const memoryMd =\n typeof obj.memoryMd === \"string\"\n ? obj.memoryMd\n : \"# 项目知识库\\n\\n> 待 consolidate\";\n\n const skippedSessions: Array<{ sessionId: string; reason: string }> = Array.isArray(\n obj.skippedSessions,\n )\n ? (obj.skippedSessions as unknown[]).filter(isSkippedEntry)\n : [];\n\n return { knowledgeFiles, memoryMd, skippedSessions };\n}\n\nfunction normalizeKnowledgeFile(raw: unknown): KnowledgeFileOutput | null {\n if (!raw || typeof raw !== \"object\") return null;\n const obj = raw as Record<string, unknown>;\n\n if (\n typeof obj.targetPath !== \"string\" ||\n ![\"create\", \"update\"].includes(obj.action as string) ||\n typeof obj.body !== \"string\"\n ) {\n return null;\n }\n\n return {\n targetPath: obj.targetPath,\n action: obj.action as \"create\" | \"update\",\n frontmatter:\n typeof obj.frontmatter === \"object\" && obj.frontmatter !== null\n ? (obj.frontmatter as Record<string, unknown>)\n : {},\n body: obj.body as string,\n };\n}\n\nfunction isSkippedEntry(raw: unknown): raw is { sessionId: string; reason: string } {\n if (!raw || typeof raw !== \"object\") return false;\n const obj = raw as Record<string, unknown>;\n return (\n typeof obj.sessionId === \"string\" && typeof obj.reason === \"string\"\n );\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { KnowledgeFileOutput } from \"./llmConsolidateV2.js\";\n\n// ─── Types ────────────────────────────────────\n\nexport interface WriteKnowledgeResult {\n created: string[];\n updated: string[];\n failed: string[];\n}\n\nconst KNOWLEDGE_LINK_PREFIXES = [\n \"rules/\",\n \"domains/\",\n \"workflows/\",\n \"decisions/\",\n \"incidents/\",\n];\n\n// ─── 写入知识文件 ─────────────────────────────\n\n/**\n * 将 LLM 返回的 knowledgeFiles 数组写入磁盘。\n *\n * - targetPath 相对于 .memory/ 根目录\n * - 自动创建所需子目录\n * - action=\"create\" 仅在新文件时写入\n * - action=\"update\" 总是覆盖\n */\nexport function writeKnowledgeFiles(\n repoRoot: string,\n files: KnowledgeFileOutput[],\n): WriteKnowledgeResult {\n const result: WriteKnowledgeResult = {\n created: [],\n updated: [],\n failed: [],\n };\n\n for (const kf of files) {\n try {\n const absolutePath = memoryPath(repoRoot, kf.targetPath);\n const dir = dirname(absolutePath);\n\n mkdirSync(dir, { recursive: true });\n\n // 序列化 frontmatter + body\n const content = serializeKnowledgeFile(kf.frontmatter, kf.body);\n\n const alreadyExists = existsSync(absolutePath);\n\n if (kf.action === \"create\" && alreadyExists) {\n // create 但已存在,降级为 update\n result.updated.push(kf.targetPath);\n } else if (kf.action === \"create\") {\n result.created.push(kf.targetPath);\n } else {\n result.updated.push(kf.targetPath);\n }\n\n writeFileSync(absolutePath, content, \"utf8\");\n } catch (err) {\n result.failed.push(kf.targetPath);\n console.error(\n `[consolidate] 写入知识文件失败: ${kf.targetPath}: ${(err as Error).message}`,\n );\n }\n }\n\n return result;\n}\n\n// ─── 写入 MEMORY.md ──────────────────────────\n\n/**\n * 将 LLM 生成的 MEMORY.md 写入磁盘。\n * 保留用户自定义编辑标记 <!-- user-edit-start --> ... <!-- user-edit-end -->\n */\nexport function writeMemoryMd(\n repoRoot: string,\n memoryMd: string,\n): void {\n const memoryPathAbs = memoryPath(repoRoot, \"MEMORY.md\");\n\n // 如果已有文件且包含用户编辑标记,尝试保留用户自定义区域\n if (existsSync(memoryPathAbs)) {\n const existing = readFileSync(memoryPathAbs, \"utf8\");\n const preserved = extractUserEditedSections(existing);\n if (preserved.length > 0) {\n memoryMd = injectUserSections(memoryMd, preserved);\n }\n }\n\n mkdirSync(memoryPath(repoRoot), { recursive: true });\n writeFileSync(memoryPathAbs, `${memoryMd}\\n`, \"utf8\");\n}\n\nexport function assertMemoryKnowledgeLinksExist(\n repoRoot: string,\n memoryMd: string,\n): void {\n const missing = findMissingKnowledgeLinks(repoRoot, memoryMd);\n if (missing.length > 0) {\n throw new Error(\n `MEMORY.md 引用了不存在的知识文件: ${missing.join(\", \")}`,\n );\n }\n}\n\nfunction findMissingKnowledgeLinks(repoRoot: string, memoryMd: string): string[] {\n const links = extractKnowledgeLinks(memoryMd);\n return links.filter((link) => !existsSync(memoryPath(repoRoot, link)));\n}\n\nfunction extractKnowledgeLinks(memoryMd: string): string[] {\n const links = new Set<string>();\n const markdownLink = /\\[[^\\]]+\\]\\(([^)]+)\\)/g;\n let match: RegExpExecArray | null;\n\n while ((match = markdownLink.exec(memoryMd)) !== null) {\n const normalized = normalizeKnowledgeLink(match[1]);\n if (normalized) {\n links.add(normalized);\n }\n }\n\n return [...links];\n}\n\nfunction normalizeKnowledgeLink(rawLink: string): string | null {\n const withoutAnchor = rawLink.split(\"#\")[0].trim();\n const withoutDotSlash = withoutAnchor.startsWith(\"./\")\n ? withoutAnchor.slice(2)\n : withoutAnchor;\n\n if (\n withoutDotSlash.includes(\"://\") ||\n withoutDotSlash.startsWith(\"/\") ||\n withoutDotSlash.includes(\"..\") ||\n !withoutDotSlash.endsWith(\".md\")\n ) {\n return null;\n }\n\n return KNOWLEDGE_LINK_PREFIXES.some((prefix) => withoutDotSlash.startsWith(prefix))\n ? withoutDotSlash\n : null;\n}\n\n// ─── 序列化知识文件 ─────────────────────────\n\nfunction serializeKnowledgeFile(\n frontmatter: Record<string, unknown>,\n body: string,\n): string {\n const lines = [\"---\"];\n\n // 固定顺序输出常用字段\n const fieldOrder = [\"title\", \"domain\", \"type\", \"status\", \"confidence\", \"lastReviewed\"];\n const emitted = new Set<string>();\n\n for (const key of fieldOrder) {\n if (key in frontmatter && frontmatter[key] !== undefined && frontmatter[key] !== null) {\n lines.push(`${key}: ${formatYamlValue(frontmatter[key])}`);\n emitted.add(key);\n }\n }\n\n // sourceSessions 数组特殊处理\n if (Array.isArray(frontmatter.sourceSessions)) {\n lines.push(\"sourceSessions:\");\n for (const s of frontmatter.sourceSessions) {\n lines.push(` - ${s}`);\n }\n emitted.add(\"sourceSessions\");\n }\n\n // 其余字段\n for (const [key, val] of Object.entries(frontmatter)) {\n if (!emitted.has(key) && val !== undefined && val !== null) {\n lines.push(`${key}: ${formatYamlValue(val)}`);\n }\n }\n\n lines.push(\"---\", \"\", body);\n\n return lines.join(\"\\n\");\n}\n\nfunction formatYamlValue(val: unknown): string {\n if (Array.isArray(val)) {\n return `[${val.map(String).join(\", \")}]`;\n }\n return String(val);\n}\n\n// ─── 用户编辑区保留 ──────────────────────────\n\ninterface UserSection {\n marker: string;\n content: string;\n}\n\n/** 提取 <!-- user-edit-start --> ... <!-- user-edit-end --> 区块 */\nfunction extractUserEditedSections(content: string): UserSection[] {\n const sections: UserSection[] = [];\n const regex = /<!--\\s*user-edit-start\\s*-->\\n?([\\s\\S]*?)\\n?<!--\\s*user-edit-end\\s*-->/g;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(content)) !== null) {\n sections.push({\n marker: match[0].split(\"\\n\")[0], // 取开始标记行\n content: match[1],\n });\n }\n return sections;\n}\n\n/** 将用户编辑区注入到新内容中同名的标记位置 */\nfunction injectUserSections(\n newContent: string,\n sections: UserSection[],\n): string {\n let result = newContent;\n for (const section of sections) {\n // 用原有内容替换同名标记区块\n const startMarker = section.marker;\n const endMarker = \"<!-- user-edit-end -->\";\n\n const startIdx = result.indexOf(startMarker);\n if (startIdx === -1) continue;\n\n const endIdx = result.indexOf(endMarker, startIdx);\n if (endIdx === -1) continue;\n\n result =\n result.slice(0, startIdx) +\n `${startMarker}\\n${section.content}\\n${endMarker}` +\n result.slice(endIdx + endMarker.length);\n }\n return result;\n}\n","import { existsSync, mkdirSync, renameSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { SessionFileFrontmatter } from \"../capture/writeCapture.js\";\nimport type { ScannedSession } from \"./sessionScanner.js\";\n\n/**\n * 将符合条件的已处理 capture 文件从 raw/ 移动到 archived/\n *\n * 条件:\n * - status === \"done\"\n * - consolidatedAt 距今超过 autoArchiveDays 天(默认 30)\n */\nexport function archiveDoneSessions(\n repoRoot: string,\n sessions: ScannedSession[],\n autoArchiveDays: number = 30,\n): number {\n const archivedDir = memoryPath(repoRoot, \"captures\", \"archived\");\n const cutoffMs = Date.now() - autoArchiveDays * 24 * 60 * 60 * 1000;\n\n let archivedCount = 0;\n\n for (const s of sessions) {\n if (s.frontmatter.status !== \"done\") continue;\n if (!s.frontmatter.consolidatedAt) continue;\n\n const consolidatedTime = Date.parse(s.frontmatter.consolidatedAt);\n if (Number.isNaN(consolidatedTime)) continue;\n if (consolidatedTime > cutoffMs) continue; // 还没过期\n\n try {\n mkdirSync(archivedDir, { recursive: true });\n renameSync(s.absolutePath, join(archivedDir, s.filename));\n archivedCount++;\n } catch {\n // 忽略移动失败(可能文件已被其他进程删除)\n }\n }\n\n return archivedCount;\n}\n","import { debugLog } from \"../config/debugLog.js\";\nimport { type HermesConfig, type LlmConfigV2, type RepoContext } from \"../config/types.js\";\nimport {\n readConsolidateState,\n releaseConsolidateLock,\n writeConsolidateLock,\n writeConsolidateState,\n} from \"./state.js\";\nimport { scanAllSessions, filterPendingSessions, type ScannedSession } from \"./sessionScanner.js\";\nimport {\n buildLlmConsolidateInput,\n callLlmConsolidate,\n} from \"./llmConsolidateV2.js\";\nimport {\n assertMemoryKnowledgeLinksExist,\n writeKnowledgeFiles,\n writeMemoryMd,\n} from \"./writeKnowledge.js\";\nimport { archiveDoneSessions } from \"./archive.js\";\nimport { markSessionConsolidated } from \"../capture/writeCapture.js\";\n\n// ─── Options & Result ────────────────────────\n\nexport interface RunConsolidateOptions {\n repoRoot: string;\n config: HermesConfig;\n force?: boolean;\n dryRun?: boolean;\n debug?: boolean;\n}\n\nexport interface ConsolidateResultV2 {\n ran: boolean;\n reason?: string;\n sessionsProcessed: number; // 处理的 session 文件数\n knowledgeCreated: number; // 新建知识文件数\n knowledgeUpdated: number; // 更新知识文件数\n skippedCount: number; // 跳过的 session 数\n archived: number; // 归档的文件数\n}\n\n// ─── Main orchestrator ───────────────────────\n\n/**\n * v2 consolidate 主函数:\n *\n * 1. 扫描 captures/raw/ 中 pending/stale 的 session 文件\n * 2. 构造 LLM 输入(sessions + 已有知识 + MEMORY.md)\n * 3. 单次 LLM 调用 → 知识文件 + MEMORY.md\n * 4. 写入磁盘(knowledge files + MEMORY.md)\n * 5. 更新 session 状态 → done\n * 6. 自动归档过期 done 文件\n */\nexport async function runConsolidate(\n opts: RunConsolidateOptions,\n): Promise<ConsolidateResultV2> {\n const { repoRoot, config, force, dryRun, debug } = opts;\n\n debugLog(\n debug === true,\n \"consolidate\",\n `start: force=${force === true}, dryRun=${dryRun === true}`,\n );\n writeConsolidateLock(repoRoot);\n debugLog(debug === true, \"consolidate\", \"lock acquired\");\n try {\n const llmConfig: LlmConfigV2 = config.llm;\n\n if (!llmConfig.enabled) {\n debugLog(debug === true, \"consolidate\", \"skip: llm not enabled\");\n return {\n ran: false,\n reason: \"llm-not-enabled\",\n sessionsProcessed: 0,\n knowledgeCreated: 0,\n knowledgeUpdated: 0,\n skippedCount: 0,\n archived: 0,\n };\n }\n\n // Step 1: 扫描 session 文件\n const allSessions = scanAllSessions(repoRoot);\n const pendingSessions = force\n ? allSessions\n : filterPendingSessions(allSessions);\n\n debugLog(\n debug === true,\n \"consolidate\",\n `扫描到 ${allSessions.length} 个 session,其中 ${pendingSessions.length} 个待处理`,\n );\n\n if (pendingSessions.length === 0 && !force) {\n debugLog(debug === true, \"consolidate\", \"skip: no pending sessions\");\n return {\n ran: false,\n reason: \"no-pending-sessions\",\n sessionsProcessed: 0,\n knowledgeCreated: 0,\n knowledgeUpdated: 0,\n skippedCount: 0,\n archived: 0,\n };\n }\n\n // dry-run:只返回预览信息\n if (dryRun) {\n debugLog(\n debug === true,\n \"consolidate\",\n `dry-run: would process ${pendingSessions.length} session(s)`,\n );\n return {\n ran: true,\n reason: \"dry-run\",\n sessionsProcessed: pendingSessions.length,\n knowledgeCreated: 0,\n knowledgeUpdated: 0,\n skippedCount: 0,\n archived: 0,\n };\n }\n\n // Step 2: 构造 LLM 输入\n const llmInput = buildLlmConsolidateInput(repoRoot, pendingSessions);\n debugLog(\n debug === true,\n \"consolidate\",\n `LLM 输入: ${llmInput.pendingSessions.length} sessions, ${llmInput.existingKnowledge.length} existing knowledge`,\n );\n\n // Step 3: 单次 LLM 调用\n let llmResult;\n try {\n llmResult = await callLlmConsolidate(llmInput, llmConfig, debug === true);\n } catch (err) {\n console.error(`[consolidate] LLM 调用失败: ${(err as Error).message}`);\n throw err;\n }\n\n debugLog(\n debug === true,\n \"consolidate\",\n `LLM 返回: ${llmResult.knowledgeFiles.length} knowledge files, ${llmResult.skippedSessions.length} skipped`,\n );\n\n // Step 4: 写入知识文件 + MEMORY.md\n debugLog(debug === true, \"consolidate\", \"writing knowledge files\");\n const writeResult = writeKnowledgeFiles(repoRoot, llmResult.knowledgeFiles);\n if (writeResult.failed.length > 0) {\n debugLog(\n debug === true,\n \"consolidate\",\n `write failed: ${writeResult.failed.join(\", \")}`,\n );\n throw new Error(\n `知识文件写入失败: ${writeResult.failed.join(\", \")}`,\n );\n }\n debugLog(\n debug === true,\n \"consolidate\",\n `knowledge files written: created=${writeResult.created.length}, updated=${writeResult.updated.length}`,\n );\n\n debugLog(debug === true, \"consolidate\", \"validating MEMORY.md links\");\n assertMemoryKnowledgeLinksExist(repoRoot, llmResult.memoryMd);\n debugLog(debug === true, \"consolidate\", \"MEMORY.md links ok\");\n debugLog(debug === true, \"consolidate\", \"writing MEMORY.md\");\n writeMemoryMd(repoRoot, llmResult.memoryMd);\n\n // Step 5: 更新 session 状态为 done\n debugLog(\n debug === true,\n \"consolidate\",\n `marking sessions done: ${pendingSessions.length} processed, ${llmResult.skippedSessions.length} skipped`,\n );\n const processedSessionIds = new Set<string>();\n for (const s of pendingSessions) {\n markSessionConsolidated(repoRoot, s.sessionId);\n processedSessionIds.add(s.sessionId);\n }\n // 也标记 skipped 的 session 为 done(已评估过)\n for (const ss of llmResult.skippedSessions) {\n markSessionConsolidated(repoRoot, ss.sessionId);\n processedSessionIds.add(ss.sessionId);\n }\n\n // Step 6: 更新 consolidate-state.json\n const prevState = readConsolidateState(repoRoot);\n const newDomains = extractDomainsFromResults(llmResult.knowledgeFiles);\n\n debugLog(debug === true, \"consolidate\", \"updating consolidate state\");\n writeConsolidateState(repoRoot, {\n version: 2,\n lastConsolidatedAt: new Date().toISOString(),\n stats: {\n totalCapturesProcessed:\n prevState.stats.totalCapturesProcessed +\n pendingSessions.reduce((sum, s) => sum + s.frontmatter.captureCount, 0),\n domains: [...new Set([...prevState.stats.domains, ...newDomains])],\n knowledgeFilesCreated:\n prevState.stats.knowledgeFilesCreated +\n writeResult.created.length,\n },\n processedSessions: {\n ...prevState.processedSessions,\n ...Object.fromEntries(\n [...processedSessionIds].map((id) => [\n id,\n { status: \"done\" as const, consolidatedAt: new Date().toISOString(), lastCaptureAt: new Date().toISOString() },\n ]),\n ),\n },\n });\n\n // Step 7: 自动归档\n const archived = archiveDoneSessions(\n repoRoot,\n allSessions,\n config.consolidate.autoArchiveDays,\n );\n debugLog(debug === true, \"consolidate\", `archived sessions: ${archived}`);\n\n debugLog(\n debug === true,\n \"consolidate\",\n `done: sessions=${pendingSessions.length}, created=${writeResult.created.length}, updated=${writeResult.updated.length}, skipped=${llmResult.skippedSessions.length}, archived=${archived}`,\n );\n\n return {\n ran: true,\n sessionsProcessed: pendingSessions.length,\n knowledgeCreated: writeResult.created.length,\n knowledgeUpdated: writeResult.updated.length,\n skippedCount: llmResult.skippedSessions.length,\n archived,\n };\n } finally {\n releaseConsolidateLock(repoRoot);\n debugLog(debug === true, \"consolidate\", \"lock released\");\n }\n}\n\n// ─── Helpers ─────────────────────────────────\n\n/** 从 LLM 返回结果中提取所有涉及到的域名 */\nfunction extractDomainsFromResults(\n files: Array<{ frontmatter: Record<string, unknown> }>,\n): string[] {\n const domains = new Set<string>();\n for (const f of files) {\n const domain = f.frontmatter.domain;\n if (typeof domain === \"string\" && domain && domain !== \"null\") {\n domains.add(domain);\n }\n }\n return [...domains];\n}\n","/** 运行锁过期(毫秒) */\nexport const CONSOLIDATE_LOCK_TTL_MS = 30 * 60 * 1000;\n","import { debugLog } from \"../config/debugLog.js\";\nimport { effectiveLlmMode, isLlmAvailable } from \"../config/llmConfig.js\";\nimport { readConfigAtRepo } from \"../config/readConfig.js\";\nimport type { AssistantId } from \"../init/assistants/types.js\";\nimport { enqueueLlmJob } from \"./enqueueLlmJob.js\";\nimport { llmFormat, simpleFormat } from \"./formatCapture.js\";\nimport { needsLlm } from \"./needsLlm.js\";\nimport type { CaptureResult } from \"./types.js\";\nimport { maybeScheduleConsolidate } from \"../consolidate/scheduleConsolidate.js\";\nimport {\n appendCaptureToSession,\n} from \"./writeCapture.js\";\nimport type { ParsedSession } from \"./types.js\";\n\nfunction finishCapture(\n repoRoot: string,\n debug: boolean | undefined,\n result: CaptureResult,\n): CaptureResult {\n if (result.written) {\n maybeScheduleConsolidate({ repoRoot, debug });\n }\n return result;\n}\n\nexport interface CommitCaptureOptions {\n repoRoot: string;\n session: ParsedSession;\n jsonlPath: string;\n assistant: AssistantId;\n dryRun?: boolean;\n debug?: boolean;\n}\n\nexport async function commitCapture(\n opts: CommitCaptureOptions,\n): Promise<CaptureResult> {\n const { repoRoot, session, jsonlPath, assistant, dryRun, debug } = opts;\n const formatted = simpleFormat(session, assistant);\n\n if (dryRun) {\n debugLog(\n debug === true,\n \"capture\",\n `[dry-run] would capture session=${session.sessionId} from ${jsonlPath}`,\n );\n return { written: false, reason: \"dry-run\", jsonlPath };\n }\n\n // v2: 使用 session 聚合模式写入\n const result = appendCaptureToSession(repoRoot, formatted);\n const captureFile = result.relativePath;\n\n // v2: 不再维护 sessions/index.json\n\n const llm = readConfigAtRepo(repoRoot)?.llm ?? null;\n if (!isLlmAvailable(llm) || !needsLlm(session)) {\n debugLog(debug === true, \"capture\", `ok: ${captureFile} (format=simple)`);\n return finishCapture(repoRoot, debug, {\n written: true,\n capturePath: captureFile,\n jsonlPath,\n });\n }\n\n const mode = effectiveLlmMode(llm!);\n if (mode === \"sync\") {\n const upgraded = await llmFormat(session, assistant, llm!);\n if (upgraded) {\n // v2: LLM upgrade 后重新追加到同一 session 文件(覆盖最后一个 capture 段落)\n // 简化处理:当前暂不实现 LLM in-place upgrade,后续在 Phase 2 完善\n debugLog(debug === true, \"capture\", `ok: ${captureFile} (format=llm-sync)`);\n return finishCapture(repoRoot, debug, {\n written: true,\n capturePath: captureFile,\n jsonlPath,\n });\n }\n debugLog(debug === true, \"capture\", `ok: ${captureFile} (format=simple, llm-fallback)`);\n return finishCapture(repoRoot, debug, {\n written: true,\n capturePath: captureFile,\n jsonlPath,\n });\n }\n\n const enqueued = enqueueLlmJob({\n repoRoot,\n sessionId: session.sessionId,\n jsonlPath,\n captureFile,\n assistant,\n debug,\n });\n if (enqueued) {\n debugLog(debug === true, \"capture\", `ok: ${captureFile} (format=simple, llm-enqueued)`);\n } else {\n debugLog(debug === true, \"capture\", `ok: ${captureFile} (format=simple, llm-skip-enqueue)`);\n }\n\n return finishCapture(repoRoot, debug, {\n written: true,\n capturePath: captureFile,\n jsonlPath,\n });\n}\n","import { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\n\n/** Claude Code:项目目录名 = 绝对路径将 `/` 替换为 `-`(见官方 ~/.claude/projects/) */\nexport function encodeClaudeProjectDir(absPath: string): string {\n return resolve(absPath).replace(/\\//g, \"-\");\n}\n\nexport interface ResolveSessionOptions {\n /** Claude Stop hook stdin JSON 的 transcript_path(官方首选) */\n transcriptPath?: string;\n cwd?: string;\n}\n\n/**\n * 解析 Claude Code 会话 JSONL 路径。\n * 依据 https://code.claude.com/docs/en/claude-directory#application-data\n *\n * 优先级:\n * 1. HERMES_SESSION_JSONL(测试 / 手动覆盖)\n * 2. transcriptPath(hook stdin 的 transcript_path)\n * 3. ~/.claude/projects/<encoded-cwd>/*.jsonl(当前仓库)\n * 4. 全局 projects 下最新 .jsonl(含旧版 sessions 子目录回退)\n */\nexport function resolveSessionJsonlPath(\n repoRoot: string,\n options: ResolveSessionOptions = {},\n): string | null {\n const override = process.env.HERMES_SESSION_JSONL;\n if (override && existsSync(override)) {\n return resolve(override);\n }\n\n const fromHook = options.transcriptPath;\n if (fromHook && existsSync(fromHook)) {\n return resolve(fromHook);\n }\n\n const sessionId =\n process.env.CLAUDE_SESSION_ID ??\n process.env.CLAUDE_CODE_SESSION_ID ??\n process.env.SESSION_ID;\n\n const claudeHome = process.env.CLAUDE_CONFIG_DIR\n ? resolve(process.env.CLAUDE_CONFIG_DIR)\n : join(homedir(), \".claude\");\n const projectsRoot = join(claudeHome, \"projects\");\n if (!existsSync(projectsRoot)) {\n return null;\n }\n\n const cwd = resolve(options.cwd ?? repoRoot);\n const preferredProjectDir = encodeClaudeProjectDir(cwd);\n const preferredPath = join(projectsRoot, preferredProjectDir);\n if (existsSync(preferredPath)) {\n const hit = pickNewestJsonl(preferredPath, sessionId);\n if (hit) {\n return hit;\n }\n const legacySessions = join(preferredPath, \"sessions\");\n if (existsSync(legacySessions)) {\n const legacyHit = pickNewestJsonl(legacySessions, sessionId);\n if (legacyHit) {\n return legacyHit;\n }\n }\n }\n\n const candidates: Array<{ path: string; mtime: number }> = [];\n\n for (const projectDir of readdirSync(projectsRoot, { withFileTypes: true })) {\n if (!projectDir.isDirectory()) continue;\n const projectPath = join(projectsRoot, projectDir.name);\n collectJsonlCandidates(projectPath, sessionId, candidates);\n const legacySessions = join(projectPath, \"sessions\");\n if (existsSync(legacySessions)) {\n collectJsonlCandidates(legacySessions, sessionId, candidates);\n }\n }\n\n if (candidates.length === 0) {\n return null;\n }\n\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\n/** @deprecated 使用 readHookInputSync;保留兼容测试与旧调用 */\nexport function readHookTranscriptPathSync(): string | null {\n if (process.stdin.isTTY) {\n return null;\n }\n try {\n const raw = readFileSync(0, \"utf8\").trim();\n if (!raw) {\n return null;\n }\n const parsed = JSON.parse(raw) as { transcript_path?: unknown };\n const p = parsed.transcript_path;\n if (typeof p === \"string\" && existsSync(p)) {\n return resolve(p);\n }\n } catch {\n return null;\n }\n return null;\n}\n\nfunction pickNewestJsonl(\n dir: string,\n sessionId: string | undefined,\n): string | null {\n const candidates: Array<{ path: string; mtime: number }> = [];\n collectJsonlCandidates(dir, sessionId, candidates);\n if (candidates.length === 0) {\n return null;\n }\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\nfunction collectJsonlCandidates(\n dir: string,\n sessionId: string | undefined,\n out: Array<{ path: string; mtime: number }>,\n): void {\n if (!existsSync(dir)) {\n return;\n }\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) {\n continue;\n }\n const fullPath = join(dir, entry.name);\n if (\n sessionId &&\n !entry.name.includes(sessionId) &&\n basename(entry.name, \".jsonl\") !== sessionId\n ) {\n continue;\n }\n try {\n const st = statSync(fullPath);\n out.push({ path: fullPath, mtime: st.mtimeMs });\n } catch {\n // skip\n }\n }\n}\n","import { commitCapture } from \"../commitCapture.js\";\nimport type { CaptureResult } from \"../types.js\";\nimport { parseJsonlFile } from \"./parseJsonl.js\";\nimport { resolveSessionJsonlPath } from \"./resolveSession.js\";\n\nexport async function runClaudeCodeCapture(\n repoRoot: string,\n cwd?: string,\n dryRun?: boolean,\n options?: { transcriptPath?: string; debug?: boolean },\n): Promise<CaptureResult> {\n const jsonlPath = resolveSessionJsonlPath(repoRoot, {\n cwd,\n transcriptPath: options?.transcriptPath,\n });\n if (!jsonlPath) {\n return { written: false, reason: \"no session jsonl found\" };\n }\n\n // v2: 始终捕获(去掉 shouldCapture 质量过滤)\n const session = parseJsonlFile(jsonlPath);\n\n return commitCapture({\n repoRoot,\n session,\n jsonlPath,\n assistant: \"claude-code\",\n dryRun,\n debug: options?.debug,\n });\n}\n","import { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\n\n/**\n * CodeBuddy 项目目录名:绝对路径去掉 leading `/`,再将 `/` 换为 `-`。\n * 例:`/Users/you/proj` → `Users-you-proj`(与 Cursor 一致,非 Claude leading `-`)\n */\nexport function encodeCodebuddyProjectDir(absPath: string): string {\n return resolve(absPath).replace(/^\\//, \"\").replace(/\\//g, \"-\");\n}\n\nexport interface ResolveCodebuddySessionOptions {\n repoRoot: string;\n cwd?: string;\n transcriptPath?: string;\n}\n\n/**\n * 解析 CodeBuddy 会话 JSONL。\n *\n * 优先级:\n * 1. HERMES_CODEBUDDY_SESSION\n * 2. transcriptPath(hook stdin)\n * 3. ~/.codebuddy/projects/<encoded-cwd> 下最新 .jsonl(含子目录)\n */\nexport function resolveCodebuddySessionJsonl(\n options: ResolveCodebuddySessionOptions,\n): string | null {\n const override = process.env.HERMES_CODEBUDDY_SESSION;\n if (override && existsSync(override)) {\n return resolve(override);\n }\n\n const fromHook = options.transcriptPath;\n if (fromHook && existsSync(fromHook)) {\n return resolve(fromHook);\n }\n\n const sessionId =\n process.env.CODEBUDDY_SESSION_ID ?? process.env.SESSION_ID;\n\n const codebuddyHome = process.env.CODEBUDDY_CONFIG_DIR\n ? resolve(process.env.CODEBUDDY_CONFIG_DIR)\n : join(homedir(), \".codebuddy\");\n const projectsRoot = join(codebuddyHome, \"projects\");\n if (!existsSync(projectsRoot)) {\n return null;\n }\n\n const cwd = resolve(options.cwd ?? options.repoRoot);\n const preferredProjectDir = encodeCodebuddyProjectDir(cwd);\n const preferredPath = join(projectsRoot, preferredProjectDir);\n if (existsSync(preferredPath)) {\n const hit = pickNewestJsonlRecursive(preferredPath, sessionId);\n if (hit) {\n return hit;\n }\n }\n\n const candidates: Array<{ path: string; mtime: number }> = [];\n for (const projectDir of readdirSync(projectsRoot, { withFileTypes: true })) {\n if (!projectDir.isDirectory()) {\n continue;\n }\n collectJsonlRecursive(join(projectsRoot, projectDir.name), sessionId, candidates);\n }\n\n if (candidates.length === 0) {\n return null;\n }\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\nfunction pickNewestJsonlRecursive(\n dir: string,\n sessionId: string | undefined,\n): string | null {\n const candidates: Array<{ path: string; mtime: number }> = [];\n collectJsonlRecursive(dir, sessionId, candidates);\n if (candidates.length === 0) {\n return null;\n }\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\nfunction collectJsonlRecursive(\n dir: string,\n sessionId: string | undefined,\n out: Array<{ path: string; mtime: number }>,\n): void {\n if (!existsSync(dir)) {\n return;\n }\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n collectJsonlRecursive(full, sessionId, out);\n continue;\n }\n if (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) {\n continue;\n }\n if (\n sessionId &&\n !entry.name.includes(sessionId) &&\n basename(entry.name, \".jsonl\") !== sessionId\n ) {\n continue;\n }\n try {\n const st = statSync(full);\n out.push({ path: full, mtime: st.mtimeMs });\n } catch {\n // skip\n }\n }\n}\n","import { commitCapture } from \"../commitCapture.js\";\nimport type { CaptureResult } from \"../types.js\";\nimport { parseJsonlFile } from \"../claude-code/parseJsonl.js\";\nimport { resolveCodebuddySessionJsonl } from \"./resolveSession.js\";\n\nexport async function runCodebuddyCapture(\n repoRoot: string,\n cwd?: string,\n dryRun?: boolean,\n options?: { transcriptPath?: string; debug?: boolean },\n): Promise<CaptureResult> {\n const jsonlPath = resolveCodebuddySessionJsonl({\n repoRoot,\n cwd,\n transcriptPath: options?.transcriptPath,\n });\n if (!jsonlPath) {\n return { written: false, reason: \"no codebuddy session found\" };\n }\n\n // v2: 始终捕获(去掉 shouldCapture 质量过滤),由 LLM 在 consolidate 时判断价值\n const session = parseJsonlFile(jsonlPath);\n if (session.messages.length <= 1 && session.toolCalls === 0) {\n return {\n written: false,\n reason: \"empty session (no messages or tool calls)\",\n jsonlPath,\n };\n }\n\n return commitCapture({\n repoRoot,\n session,\n jsonlPath,\n assistant: \"codebuddy\",\n dryRun,\n debug: options?.debug,\n });\n}\n","import { existsSync, readdirSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport type { HookInput } from \"../hookInput.js\";\n\n/**\n * Cursor 项目目录名:绝对路径去掉 leading `/`,再将 `/` 换为 `-`。\n * 例:`/Users/you/proj` → `Users-you-proj`\n * (与 Claude `encodeClaudeProjectDir` 的 leading `-` 不同)\n */\nexport function encodeCursorProjectDir(absPath: string): string {\n return resolve(absPath).replace(/^\\//, \"\").replace(/\\//g, \"-\");\n}\n\nexport interface ResolveCursorSessionOptions {\n repoRoot: string;\n cwd?: string;\n hookInput?: HookInput | null;\n}\n\n/**\n * 解析 Cursor Agent 会话 JSONL。\n *\n * 优先级:\n * 1. HERMES_CURSOR_SESSION(测试 / 手动)\n * 2. hook session_id → ~/.cursor/projects/<encoded>/agent-transcripts/<id>/<id>.jsonl\n * 3. workspace_roots[0] 或 repoRoot 对应项目下最新 transcript\n */\nexport function resolveCursorSessionJsonl(\n options: ResolveCursorSessionOptions,\n): string | null {\n const override = process.env.HERMES_CURSOR_SESSION;\n if (override && existsSync(override)) {\n return resolve(override);\n }\n\n const cursorHome = process.env.CURSOR_CONFIG_DIR\n ? resolve(process.env.CURSOR_CONFIG_DIR)\n : join(homedir(), \".cursor\");\n const projectsRoot = join(cursorHome, \"projects\");\n if (!existsSync(projectsRoot)) {\n return null;\n }\n\n const sessionId =\n options.hookInput?.sessionId ??\n options.hookInput?.conversationId ??\n process.env.CURSOR_SESSION_ID ??\n process.env.CURSOR_AGENT_SESSION_ID;\n\n const workspace =\n options.hookInput?.workspaceRoots?.[0] ??\n (options.cwd ? resolve(options.cwd) : resolve(options.repoRoot));\n\n const encoded = encodeCursorProjectDir(workspace);\n const projectDir = join(projectsRoot, encoded);\n const transcriptsRoot = join(projectDir, \"agent-transcripts\");\n\n if (!existsSync(transcriptsRoot)) {\n return pickNewestCursorJsonl(projectsRoot);\n }\n\n if (sessionId) {\n const direct = join(transcriptsRoot, sessionId, `${sessionId}.jsonl`);\n if (existsSync(direct)) {\n return direct;\n }\n const nested = findJsonlUnderDir(join(transcriptsRoot, sessionId), sessionId);\n if (nested) {\n return nested;\n }\n }\n\n return pickNewestCursorJsonl(transcriptsRoot);\n}\n\nfunction findJsonlUnderDir(dir: string, sessionId: string): string | null {\n if (!existsSync(dir)) {\n return null;\n }\n const direct = join(dir, `${sessionId}.jsonl`);\n if (existsSync(direct)) {\n return direct;\n }\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.isFile() && entry.name.endsWith(\".jsonl\")) {\n return join(dir, entry.name);\n }\n if (entry.isDirectory()) {\n const found = findJsonlUnderDir(join(dir, entry.name), sessionId);\n if (found) {\n return found;\n }\n }\n }\n return null;\n}\n\nfunction pickNewestCursorJsonl(root: string): string | null {\n const candidates: Array<{ path: string; mtime: number }> = [];\n collectJsonlRecursive(root, candidates);\n if (candidates.length === 0) {\n return null;\n }\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\nfunction collectJsonlRecursive(\n dir: string,\n out: Array<{ path: string; mtime: number }>,\n): void {\n if (!existsSync(dir)) {\n return;\n }\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n collectJsonlRecursive(full, out);\n continue;\n }\n if (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) {\n continue;\n }\n try {\n const st = statSync(full);\n out.push({ path: full, mtime: st.mtimeMs });\n } catch {\n // skip\n }\n }\n}\n","import { commitCapture } from \"../commitCapture.js\";\nimport type { CaptureResult } from \"../types.js\";\nimport type { HookInput } from \"../hookInput.js\";\nimport { parseJsonlFile } from \"../claude-code/parseJsonl.js\";\nimport { resolveCursorSessionJsonl } from \"./resolveSession.js\";\n\nexport async function runCursorCapture(\n repoRoot: string,\n cwd?: string,\n dryRun?: boolean,\n options?: { hookInput?: HookInput | null; debug?: boolean },\n): Promise<CaptureResult> {\n if (\n options?.hookInput?.status === \"aborted\" &&\n !options.hookInput.sessionId\n ) {\n return { written: false, reason: \"cursor stop aborted\" };\n }\n\n const jsonlPath = resolveCursorSessionJsonl({\n repoRoot,\n cwd,\n hookInput: options?.hookInput,\n });\n if (!jsonlPath) {\n return { written: false, reason: \"no cursor session found\" };\n }\n\n // v2: 始终捕获(去掉 shouldCapture 质量过滤)\n const session = parseJsonlFile(jsonlPath);\n\n return commitCapture({\n repoRoot,\n session,\n jsonlPath,\n assistant: \"cursor\",\n dryRun,\n debug: options?.debug,\n });\n}\n","import type { RepoContext } from \"../config/types.js\";\nimport { runClaudeCodeCapture } from \"./claude-code/run.js\";\nimport { runCodebuddyCapture } from \"./codebuddy/run.js\";\nimport { runCursorCapture } from \"./cursor/run.js\";\nimport {\n isClaudeCaptureHook,\n isCodebuddyCaptureHook,\n isCursorCaptureHook,\n type HookInput,\n} from \"./hookInput.js\";\nimport type { CaptureResult } from \"./types.js\";\n\nexport async function routeCapture(\n ctx: RepoContext,\n options: {\n cwd?: string;\n dryRun?: boolean;\n transcriptPath?: string;\n hookInput?: HookInput | null;\n },\n): Promise<CaptureResult> {\n const assistants = ctx.config.assistants;\n const hasClaude = assistants.includes(\"claude-code\");\n const hasCursor = assistants.includes(\"cursor\");\n const hasCodebuddy = assistants.includes(\"codebuddy\");\n\n if (!hasClaude && !hasCursor && !hasCodebuddy) {\n return { written: false, reason: \"no capture assistant in config\" };\n }\n\n const hook = options.hookInput;\n const debug = ctx.config.debug === true;\n const codebuddyFromHook = isCodebuddyCaptureHook(hook);\n const claudeFromHook = isClaudeCaptureHook(hook);\n const cursorFromHook = isCursorCaptureHook(hook);\n\n if (codebuddyFromHook && hasCodebuddy) {\n return runCodebuddyCapture(ctx.repoRoot, options.cwd, options.dryRun, {\n transcriptPath: hook?.transcriptPath ?? options.transcriptPath,\n debug,\n });\n }\n\n if (claudeFromHook && hasClaude) {\n return runClaudeCodeCapture(ctx.repoRoot, options.cwd, options.dryRun, {\n transcriptPath: hook?.transcriptPath ?? options.transcriptPath,\n debug,\n });\n }\n\n if (cursorFromHook && hasCursor) {\n return runCursorCapture(ctx.repoRoot, options.cwd, options.dryRun, {\n hookInput: hook,\n debug,\n });\n }\n\n if (hasClaude) {\n const claudeResult = await runClaudeCodeCapture(\n ctx.repoRoot,\n options.cwd,\n options.dryRun,\n {\n transcriptPath: options.transcriptPath,\n debug,\n },\n );\n if (claudeResult.written) {\n return claudeResult;\n }\n if (!hasCursor && !hasCodebuddy) {\n return claudeResult;\n }\n }\n\n if (hasCursor) {\n const cursorResult = await runCursorCapture(\n ctx.repoRoot,\n options.cwd,\n options.dryRun,\n {\n hookInput: hook,\n debug,\n },\n );\n if (cursorResult.written) {\n return cursorResult;\n }\n if (!hasCodebuddy) {\n return cursorResult;\n }\n }\n\n if (hasCodebuddy) {\n return runCodebuddyCapture(ctx.repoRoot, options.cwd, options.dryRun, {\n transcriptPath: options.transcriptPath,\n debug,\n });\n }\n\n return { written: false, reason: \"no capture assistant in config\" };\n}\n","import { debugLog } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport type { HookInput } from \"./hookInput.js\";\nimport { routeCapture } from \"./router.js\";\nimport type { CaptureResult } from \"./types.js\";\n\nexport interface CaptureOptions {\n cwd?: string;\n dryRun?: boolean;\n strict?: boolean;\n /** Claude Stop hook stdin 中的 transcript_path(兼容旧调用) */\n transcriptPath?: string;\n hookInput?: HookInput | null;\n}\n\nfunction logCaptureResult(debug: boolean, result: CaptureResult): void {\n if (!debug) {\n return;\n }\n if (result.written && result.capturePath) {\n debugLog(true, \"capture\", `ok: ${result.capturePath}`);\n return;\n }\n const parts = [result.reason ?? \"unknown\"];\n if (result.jsonlPath) {\n parts.push(`jsonl=${result.jsonlPath}`);\n }\n debugLog(true, \"capture\", `skip: ${parts.join(\", \")}`);\n}\n\nexport async function runCapture(\n options: CaptureOptions = {},\n): Promise<CaptureResult> {\n const ctx = loadRepoContext(options.cwd);\n if (!ctx) {\n return { written: false, reason: \"not initialized\" };\n }\n\n const result = await routeCapture(ctx, {\n cwd: options.cwd,\n dryRun: options.dryRun,\n transcriptPath: options.transcriptPath,\n hookInput: options.hookInput,\n });\n logCaptureResult(ctx.config.debug, result);\n return result;\n}\n","import { readHookInputSync, isCodebuddyCaptureHook } from \"../capture/hookInput.js\";\nimport { runCapture } from \"../capture/runCapture.js\";\nimport { configureDebugLogging, debugLog } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { finalizeHookCommand } from \"../hookExit.js\";\n\nexport interface CaptureCommandOptions {\n cwd?: string;\n dryRun?: boolean;\n strict?: boolean;\n}\n\nexport function runCaptureCommand(opts: CaptureCommandOptions): void {\n const ctx = loadRepoContext(opts.cwd);\n const debug = ctx?.config.debug === true;\n configureDebugLogging(ctx?.repoRoot ?? null, debug);\n const hookInput = readHookInputSync();\n\n if (hookInput && isCodebuddyCaptureHook(hookInput)) {\n const stdinPath =\n hookInput.transcriptPathRaw ??\n hookInput.transcriptPath ??\n \"(missing)\";\n debugLog(\n debug,\n \"capture\",\n `codebuddy stop stdin transcript_path=${stdinPath}`,\n );\n }\n\n finalizeHookCommand(async () => {\n await runCapture({\n cwd: opts.cwd,\n dryRun: opts.dryRun,\n strict: opts.strict,\n hookInput,\n transcriptPath: hookInput?.transcriptPath,\n });\n }, opts.strict, debug);\n}\n","import { hookExit } from \"../hookExit.js\";\nimport { runFlushCommand } from \"../consolidate/scheduleConsolidate.js\";\nimport type { ConsolidateResultV2 } from \"../consolidate/runConsolidate.js\";\nimport { configureDebugLogging, debugLog } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\n\nexport async function runFlushCommandCli(opts: {\n cwd?: string;\n force?: boolean;\n dryRun?: boolean;\n strict?: boolean;\n}): Promise<void> {\n const ctx = loadRepoContext(opts.cwd);\n const debug = ctx?.config.debug === true;\n configureDebugLogging(ctx?.repoRoot ?? null, debug);\n debugLog(\n debug,\n \"flush\",\n `start: force=${opts.force === true}, dryRun=${opts.dryRun === true}`,\n );\n\n try {\n const result = await runFlushCommand({\n cwd: opts.cwd,\n force: opts.force,\n dryRun: opts.dryRun,\n });\n debugLog(\n debug,\n \"flush\",\n `result: ran=${result.ran}, reason=${result.reason ?? \"ok\"}, sessions=${result.sessionsProcessed}, created=${result.knowledgeCreated}, updated=${result.knowledgeUpdated}, skipped=${result.skippedCount}, archived=${result.archived}`,\n );\n\n if (result.ran) {\n if (result.reason === \"dry-run\") {\n console.error(\n `hermes-repo: dry-run would process ${result.sessionsProcessed} session(s)`,\n );\n } else {\n const parts: string[] = [];\n if (result.knowledgeCreated > 0)\n parts.push(`${result.knowledgeCreated} created`);\n if (result.knowledgeUpdated > 0)\n parts.push(`${result.knowledgeUpdated} updated`);\n if (result.skippedCount > 0)\n parts.push(`${result.skippedCount} skipped`);\n if (result.archived > 0)\n parts.push(`${result.archived} archived`);\n const suffix = parts.length > 0 ? `, ${parts.join(\", \")}` : \"\";\n\n console.error(\n `hermes-repo: consolidated ${result.sessionsProcessed} session(s)${suffix}`,\n );\n }\n } else {\n switch (result.reason) {\n case \"not-initialized\":\n console.error(\n \"hermes-repo flush: not initialized (.memory/config.json missing)\",\n );\n break;\n case \"llm-not-enabled\":\n console.error(\"hermes-repo flush: LLM not enabled in config.json\");\n break;\n case \"no-pending-sessions\":\n console.error(\"hermes-repo flush: no pending sessions to process\");\n break;\n default:\n console.error(`hermes-repo flush: ${result.reason ?? \"skipped\"}`);\n }\n }\n\n hookExit(0, opts.strict);\n } catch (err) {\n debugLog(\n debug,\n \"flush\",\n `error: ${err instanceof Error ? err.message : String(err)}`,\n );\n console.error(\n `hermes-repo flush: ${err instanceof Error ? err.message : String(err)}`,\n );\n hookExit(1, opts.strict);\n }\n}\n","import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { debugFromContext } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { memoryPath } from \"../init/paths.js\";\nimport { INJECT_MAX_CHARS } from \"./constants.js\";\n\n// ─── v2 两阶段注入 ─────────────────────────\n//\n// Phase 0: 注入 MEMORY.md 导航摘要 + rules/ 全部文件内容\n// AI 可按需 cat domains/workflows/decisions/incidents 具体文件\n\nexport interface InjectResult {\n injected: boolean;\n chars: number;\n}\n\n/**\n * v2 inject 主函数。\n *\n * 输出格式:\n * - Cursor hook: JSON {\"additional_context\": \"...\"}\n * - 其他: 纯文本 markdown 到 stdout\n *\n * 内容组成:\n * 1. MEMORY.md 导航摘要(项目知识库入口)\n * 2. 分隔线\n * 3. rules/ 目录下所有 .md 文件的完整内容\n */\nexport function runInject(\n cwd?: string,\n options?: { cursorHookOutput?: boolean },\n): InjectResult {\n const ctx = loadRepoContext(cwd);\n if (!ctx) {\n return { injected: false, chars: 0 };\n }\n\n const repoRoot = ctx.repoRoot;\n\n // 1. 读取 MEMORY.md 导航\n const memoryContent = readMemoryMd(repoRoot);\n // 2. 读取 rules/ 全文\n const rulesContent = readAllRules(repoRoot);\n\n if (!memoryContent && !rulesContent) {\n debugFromContext(ctx, \"inject\", \"skip: no MEMORY.md or rules/\");\n return { injected: false, chars: 0 };\n }\n\n // 组装注入内容\n const sections: string[] = [];\n\n if (memoryContent) {\n sections.push(memoryContent);\n }\n\n if (rulesContent) {\n sections.push(\n \"\",\n \"---\",\n \"\",\n \"> 以下为必读规则全文(每次会话均应遵守)\",\n \"\",\n rulesContent,\n );\n }\n\n let content = sections.join(\"\\n\");\n\n // 截断保护\n if (content.length > INJECT_MAX_CHARS) {\n content =\n `${content.slice(0, INJECT_MAX_CHARS)}\\n\\n...(truncated, total ${content.length} chars)`;\n }\n\n // 输出\n if (options?.cursorHookOutput) {\n process.stdout.write(\n `${JSON.stringify({ additional_context: content })}\\n`,\n );\n } else {\n process.stdout.write(content);\n if (!content.endsWith(\"\\n\")) {\n process.stdout.write(\"\\n\");\n }\n }\n\n debugFromContext(ctx, \"inject\", `ok: injected ${content.length} chars`);\n\n return { injected: true, chars: content.length };\n}\n\n// ─── Helpers ────────────────────────────────\n\nfunction memoryPathOnDisk(repoRoot: string): string {\n return memoryPath(repoRoot, \"MEMORY.md\");\n}\n\nfunction rulesPathOnDisk(repoRoot: string): string {\n return memoryPath(repoRoot, \"rules\");\n}\n\nfunction readMemoryMd(repoRoot: string): string | null {\n const path = memoryPathOnDisk(repoRoot);\n if (!existsSync(path)) return null;\n\n try {\n const content = readFileSync(path, \"utf8\");\n return content.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * 读取 rules/ 下所有 .md 文件,拼接为一个文档块。\n * 返回 null 如果目录不存在或无文件。\n */\nfunction readAllRules(repoRoot: string): string | null {\n const rulesDir = rulesPathOnDisk(repoRoot);\n let files: string[];\n try {\n files = readdirSync(rulesDir)\n .filter((f) => f.endsWith(\".md\"))\n .sort(); // 字母排序确保稳定顺序\n } catch {\n return null; // 目录不存在\n }\n\n if (files.length === 0) return null;\n\n const parts: string[] = [];\n for (const file of files) {\n try {\n const filePath = join(rulesDir, file);\n const content = readFileSync(filePath, \"utf8\").trim();\n if (!content) continue;\n\n // 每个规则文件加标题头\n parts.push(`### ${file}`, \"\", content, \"\");\n } catch {\n // 跳过无法读取的文件\n }\n }\n\n return parts.length > 0 ? parts.join(\"\\n\") : null;\n}\n","/** v2 两阶段注入:导航 + 规则全文,目标 ~8K chars(含 rules 全文) */\nexport const INJECT_MAX_CHARS = 8000;\n","import { isCursorInjectHook, readHookInputSync } from \"../capture/hookInput.js\";\nimport { configureDebugLogging } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { finalizeHookCommand } from \"../hookExit.js\";\nimport { runInject } from \"../inject/runInject.js\";\n\nexport interface InjectCommandOptions {\n cwd?: string;\n strict?: boolean;\n}\n\nexport function runInjectCommand(opts: InjectCommandOptions): void {\n const ctx = loadRepoContext(opts.cwd);\n const debug = ctx?.config.debug === true;\n configureDebugLogging(ctx?.repoRoot ?? null, debug);\n\n const hookInput = readHookInputSync();\n const cursorHookOutput = isCursorInjectHook(hookInput);\n\n finalizeHookCommand(() => {\n runInject(opts.cwd, { cursorHookOutput });\n }, opts.strict, debug);\n}\n","import { spawnSync } from \"node:child_process\";\nimport { resolve } from \"node:path\";\nimport {\n DEFAULT_ASSISTANT_IDS,\n parseToolsArg,\n validateAssistantSelection,\n} from \"./assistants/registry.js\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport { ensureMemoryTree } from \"./ensureDirs.js\";\nimport { mergeAssistants } from \"./mergeAssistants.js\";\nimport { mergeHermesGitignore } from \"./mergeGitignore.js\";\nimport type { InitCliOptions, InitReport, InitResolvedOptions } from \"./types.js\";\nimport { writeScaffoldFiles } from \"./writeScaffoldFile.js\";\nimport { gatherInitOptions } from \"./prompts.js\";\n\nexport function resolveTargetDir(cwd?: string): string {\n const targetDir = resolve(cwd ?? process.cwd());\n const gitCheck = spawnSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n cwd: targetDir,\n encoding: \"utf8\",\n });\n if (gitCheck.status !== 0) {\n console.warn(\n \"warn: 当前目录可能不是 Git 仓库,init 仍会继续(建议在有 git 的项目根目录执行)\",\n );\n }\n return targetDir;\n}\n\nfunction resolveSelectedAssistants(opts: InitCliOptions): AssistantId[] {\n if (opts.assistants) {\n validateAssistantSelection(opts.assistants);\n return opts.assistants;\n }\n if (opts.tools) {\n if (!opts.yes) {\n console.error(\"init --tools requires -y in non-interactive mode\");\n process.exit(1);\n }\n return parseToolsArg(opts.tools);\n }\n if (opts.yes) {\n return [...DEFAULT_ASSISTANT_IDS];\n }\n return [];\n}\n\nexport function printInitReport(report: InitReport): void {\n const created = report.files.filter((f) => f.action === \"created\");\n const skipped = report.files.filter((f) => f.action === \"skipped\");\n const overwritten = report.files.filter((f) => f.action === \"overwritten\");\n const appended = report.files.filter((f) => f.action === \"appended\");\n const replaced = report.files.filter((f) => f.action === \"replaced\");\n\n console.log(`\\nhermes-repo init 完成 → ${report.targetDir}\\n`);\n console.log(`已启用助手: ${report.assistants.join(\", \")}\\n`);\n\n if (created.length > 0) {\n console.log(`已创建 (${created.length}):`);\n for (const f of created) {\n console.log(` + ${f.path}`);\n }\n }\n\n if (overwritten.length > 0) {\n console.log(`已覆盖 (${overwritten.length}):`);\n for (const f of overwritten) {\n console.log(` ~ ${f.path}`);\n }\n }\n\n if (appended.length > 0) {\n console.log(`已追加 (${appended.length}):`);\n for (const f of appended) {\n console.log(` + ${f.path}`);\n }\n }\n\n if (replaced.length > 0) {\n console.log(`已刷新 hermes 块 (${replaced.length}):`);\n for (const f of replaced) {\n console.log(` ↻ ${f.path}`);\n }\n }\n\n if (skipped.length > 0) {\n console.log(`已跳过 (${skipped.length}):`);\n for (const f of skipped) {\n console.log(` - ${f.path}`);\n }\n }\n\n if (report.gitignoreAction) {\n console.log(`\\n.gitignore: ${report.gitignoreAction} hermes-repo 标记块`);\n }\n\n for (const warning of report.warnings) {\n console.warn(`warn: ${warning}`);\n }\n\n console.log(\"\");\n}\n\nexport async function runInit(opts: InitCliOptions): Promise<InitReport> {\n if (!process.stdin.isTTY && !opts.yes) {\n console.error(\"init requires -y in non-interactive environments\");\n process.exit(1);\n }\n\n if (opts.tools && !opts.yes) {\n console.error(\"init --tools requires -y\");\n process.exit(1);\n }\n\n let resolved: InitResolvedOptions;\n\n if (opts.yes) {\n const targetDir = resolveTargetDir(opts.cwd);\n const selected = resolveSelectedAssistants(opts);\n resolved = {\n targetDir,\n force: Boolean(opts.force),\n includeExampleTemplates: opts.includeExampleTemplates ?? true,\n assistants: mergeAssistants(targetDir, selected),\n cancelled: false,\n };\n } else {\n const gathered = await gatherInitOptions(opts);\n if (gathered.cancelled) {\n console.log(\"init 已取消\");\n process.exit(0);\n }\n resolved = {\n ...gathered,\n assistants: mergeAssistants(gathered.targetDir, gathered.assistants),\n };\n }\n\n const report: InitReport = {\n targetDir: resolved.targetDir,\n assistants: resolved.assistants,\n files: [],\n warnings: [],\n };\n\n ensureMemoryTree(resolved.targetDir);\n writeScaffoldFiles(resolved.targetDir, resolved, report);\n\n const gitignore = mergeHermesGitignore(resolved.targetDir);\n report.gitignoreAction = gitignore.action;\n if (gitignore.warnBroadMemoryIgnore) {\n report.warnings.push(\n \".gitignore 中存在对整个 .memory/ 的忽略规则,可能与团队层放行冲突,请手动检查\",\n );\n }\n\n printInitReport(report);\n\n return report;\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n CLAUDE_SETTINGS_LOCAL_REL,\n claudeSettingsLocalPath,\n mergeClaudeLocalSettings,\n} from \"../mergeClaudeSettings.js\";\nimport type { AssistantAdapter, WriteContext } from \"./types.js\";\n\nexport const claudeCodeAdapter: AssistantAdapter = {\n id: \"claude-code\",\n label: \"Claude Code(Stop / SessionStart hooks)\",\n available: true,\n scaffoldPaths: [CLAUDE_SETTINGS_LOCAL_REL],\n write(ctx: WriteContext): void {\n mkdirSync(join(ctx.repoRoot, \".claude\"), { recursive: true });\n const { content, action } = mergeClaudeLocalSettings(ctx.repoRoot);\n writeFileSync(claudeSettingsLocalPath(ctx.repoRoot), content, \"utf8\");\n ctx.report.files.push({ path: CLAUDE_SETTINGS_LOCAL_REL, action });\n },\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { renderTemplate } from \"./templateDir.js\";\nimport type { InitFileAction } from \"./types.js\";\n\nexport const CLAUDE_SETTINGS_LOCAL_REL = \".claude/settings.local.json\";\n\nexport function claudeSettingsLocalPath(repoRoot: string): string {\n return join(repoRoot, \".claude\", \"settings.local.json\");\n}\n\ntype HookHandlers = { hooks: { type: string; command: string }[] }[];\n\n/** 每次 init 合并 hermes 管理的 Stop / SessionStart 到 Claude local settings */\nexport function mergeClaudeLocalSettings(repoRoot: string): {\n content: string;\n action: InitFileAction;\n} {\n const settingsPath = claudeSettingsLocalPath(repoRoot);\n const existed = existsSync(settingsPath);\n\n const templateParsed = JSON.parse(renderTemplate(\"hooks.json.tpl\")) as {\n hooks: {\n Stop: HookHandlers;\n SessionStart: HookHandlers;\n };\n };\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, \"utf8\")) as Record<\n string,\n unknown\n >;\n } catch {\n existing = {};\n }\n }\n\n const prevHooks =\n existing.hooks &&\n typeof existing.hooks === \"object\" &&\n !Array.isArray(existing.hooks)\n ? (existing.hooks as Record<string, unknown>)\n : {};\n\n const merged: Record<string, unknown> = {\n ...existing,\n hooks: {\n ...prevHooks,\n Stop: templateParsed.hooks.Stop,\n SessionStart: templateParsed.hooks.SessionStart,\n },\n };\n\n return {\n content: `${JSON.stringify(merged, null, 2)}\\n`,\n action: existed ? \"overwritten\" : \"created\",\n };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { PACKAGE_NAME } from \"../index.js\";\n\nfunction resolveTemplateDir(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n const candidates = [\n join(here, \"templates\"),\n join(here, \"..\", \"..\", \"templates\"),\n ];\n for (const dir of candidates) {\n if (existsSync(dir)) {\n return dir;\n }\n }\n return join(here, \"templates\");\n}\n\nconst templateDir = resolveTemplateDir();\n\nexport function resolveTemplatePath(name: string): string {\n return join(templateDir, name);\n}\n\nexport function readTemplate(name: string): string {\n return readFileSync(resolveTemplatePath(name), \"utf8\");\n}\n\nexport function renderTemplate(name: string): string {\n const raw = readTemplate(name);\n return raw.replaceAll(\"__PACKAGE_NAME__\", PACKAGE_NAME);\n}\n","import { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const PACKAGE_NAME = \"@riconext/hermes-repo\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport function readPkgVersion(): string {\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as { version: string };\n return pkg.version;\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n CODEX_CONFIG_REL,\n codexConfigPath,\n mergeCodexConfig,\n} from \"../mergeCodexConfig.js\";\nimport type { AssistantAdapter, WriteContext } from \"./types.js\";\n\nexport const codexAdapter: AssistantAdapter = {\n id: \"codex\",\n label: \"OpenAI Codex(AGENTS.md + .codex/config.toml)\",\n available: true,\n scaffoldPaths: [CODEX_CONFIG_REL],\n write(ctx: WriteContext): void {\n mkdirSync(join(ctx.repoRoot, \".codex\"), { recursive: true });\n const { content, action } = mergeCodexConfig(ctx.repoRoot);\n writeFileSync(codexConfigPath(ctx.repoRoot), content, \"utf8\");\n ctx.report.files.push({ path: CODEX_CONFIG_REL, action });\n },\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { InitFileAction } from \"./types.js\";\n\nexport const CODEX_CONFIG_REL = \".codex/config.toml\";\n\nconst CODEX_HERMES_START_MARKER =\n \"# >>> hermes-repo codex (do not edit this block manually)\";\nconst CODEX_HERMES_END_MARKER = \"# <<< hermes-repo codex\";\n\nfunction buildCodexHermesBlock(): string {\n return [\n CODEX_HERMES_START_MARKER,\n \"# Hermes uses AGENTS.md as the shared Codex project guidance entry.\",\n \"# Run `npx @riconext/hermes-repo search <keyword>` to inspect project memory.\",\n \"# Run `npx @riconext/hermes-repo ref --capture <path> --reason \\\"...\\\"` after using memory.\",\n CODEX_HERMES_END_MARKER,\n ].join(\"\\n\");\n}\n\nexport function codexConfigPath(repoRoot: string): string {\n return join(repoRoot, \".codex\", \"config.toml\");\n}\n\nfunction spliceHermesBlock(existing: string, block: string): string {\n const startIdx = existing.indexOf(CODEX_HERMES_START_MARKER);\n const endIdx = existing.indexOf(CODEX_HERMES_END_MARKER);\n\n if (startIdx >= 0 && endIdx >= startIdx) {\n const before = existing.slice(0, startIdx).trimEnd();\n const after = existing.slice(endIdx + CODEX_HERMES_END_MARKER.length).trimStart();\n return `${before ? `${before}\\n\\n` : \"\"}${block}${after ? `\\n\\n${after}` : \"\"}\\n`;\n }\n\n const trimmed = existing.trimEnd();\n return `${trimmed ? `${trimmed}\\n\\n` : \"\"}${block}\\n`;\n}\n\n/** Codex project config is preserved; init only manages a commented Hermes marker block. */\nexport function mergeCodexConfig(repoRoot: string): {\n content: string;\n action: InitFileAction;\n} {\n const configPath = codexConfigPath(repoRoot);\n const existed = existsSync(configPath);\n const block = buildCodexHermesBlock();\n\n if (!existed) {\n return {\n content: `${block}\\n`,\n action: \"created\",\n };\n }\n\n const existing = readFileSync(configPath, \"utf8\");\n const hasBlock =\n existing.includes(CODEX_HERMES_START_MARKER) &&\n existing.includes(CODEX_HERMES_END_MARKER);\n\n return {\n content: spliceHermesBlock(existing, block),\n action: hasBlock ? \"replaced\" : \"appended\",\n };\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n CODEBUDDY_SETTINGS_LOCAL_REL,\n codebuddySettingsLocalPath,\n mergeCodebuddyLocalSettings,\n} from \"../mergeCodebuddySettings.js\";\nimport type { AssistantAdapter, WriteContext } from \"./types.js\";\n\nexport const codebuddyAdapter: AssistantAdapter = {\n id: \"codebuddy\",\n label: \"CodeBuddy(CLI)\",\n available: true,\n scaffoldPaths: [CODEBUDDY_SETTINGS_LOCAL_REL],\n write(ctx: WriteContext): void {\n mkdirSync(join(ctx.repoRoot, \".codebuddy\"), { recursive: true });\n const { content, action } = mergeCodebuddyLocalSettings(ctx.repoRoot);\n writeFileSync(codebuddySettingsLocalPath(ctx.repoRoot), content, \"utf8\");\n ctx.report.files.push({ path: CODEBUDDY_SETTINGS_LOCAL_REL, action });\n },\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { renderTemplate } from \"./templateDir.js\";\nimport type { InitFileAction } from \"./types.js\";\n\nexport const CODEBUDDY_SETTINGS_LOCAL_REL = \".codebuddy/settings.local.json\";\n\nexport function codebuddySettingsLocalPath(repoRoot: string): string {\n return join(repoRoot, \".codebuddy\", \"settings.local.json\");\n}\n\ntype HookHandlers = { hooks: { type: string; command: string }[] }[];\n\n/** 每次 init 合并 hermes 管理的 Stop / SessionStart 到 CodeBuddy local settings */\nexport function mergeCodebuddyLocalSettings(repoRoot: string): {\n content: string;\n action: InitFileAction;\n} {\n const settingsPath = codebuddySettingsLocalPath(repoRoot);\n const existed = existsSync(settingsPath);\n\n const templateParsed = JSON.parse(\n renderTemplate(\"hooks.codebuddy.json.tpl\"),\n ) as {\n hooks: {\n Stop: HookHandlers;\n SessionStart: HookHandlers;\n };\n };\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(readFileSync(settingsPath, \"utf8\")) as Record<\n string,\n unknown\n >;\n } catch {\n existing = {};\n }\n }\n\n const prevHooks =\n existing.hooks &&\n typeof existing.hooks === \"object\" &&\n !Array.isArray(existing.hooks)\n ? (existing.hooks as Record<string, unknown>)\n : {};\n\n const merged: Record<string, unknown> = {\n ...existing,\n hooks: {\n ...prevHooks,\n Stop: templateParsed.hooks.Stop,\n SessionStart: templateParsed.hooks.SessionStart,\n },\n };\n\n return {\n content: `${JSON.stringify(merged, null, 2)}\\n`,\n action: existed ? \"overwritten\" : \"created\",\n };\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n CURSOR_HOOKS_REL,\n cursorHooksPath,\n mergeCursorHooks,\n} from \"../mergeCursorHooks.js\";\nimport type { AssistantAdapter, WriteContext } from \"./types.js\";\n\nexport const cursorAdapter: AssistantAdapter = {\n id: \"cursor\",\n label: \"Cursor(sessionStart / stop hooks)\",\n available: true,\n scaffoldPaths: [CURSOR_HOOKS_REL],\n write(ctx: WriteContext): void {\n mkdirSync(join(ctx.repoRoot, \".cursor\"), { recursive: true });\n const { content, action } = mergeCursorHooks(ctx.repoRoot);\n writeFileSync(cursorHooksPath(ctx.repoRoot), content, \"utf8\");\n ctx.report.files.push({ path: CURSOR_HOOKS_REL, action });\n },\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { renderTemplate } from \"./templateDir.js\";\nimport type { InitFileAction } from \"./types.js\";\n\nexport const CURSOR_HOOKS_REL = \".cursor/hooks.json\";\n\nexport function cursorHooksPath(repoRoot: string): string {\n return join(repoRoot, \".cursor\", \"hooks.json\");\n}\n\ntype CursorHookEntry = { command: string };\n\n/** 每次 init 合并 hermes 管理的 sessionStart / stop 到 .cursor/hooks.json */\nexport function mergeCursorHooks(repoRoot: string): {\n content: string;\n action: InitFileAction;\n} {\n const hooksPath = cursorHooksPath(repoRoot);\n const existed = existsSync(hooksPath);\n\n const templateParsed = JSON.parse(renderTemplate(\"hooks.cursor.json.tpl\")) as {\n version: number;\n hooks: {\n sessionStart: CursorHookEntry[];\n stop: CursorHookEntry[];\n };\n };\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(readFileSync(hooksPath, \"utf8\")) as Record<\n string,\n unknown\n >;\n } catch {\n existing = {};\n }\n }\n\n const prevHooks =\n existing.hooks &&\n typeof existing.hooks === \"object\" &&\n !Array.isArray(existing.hooks)\n ? (existing.hooks as Record<string, unknown>)\n : {};\n\n const merged: Record<string, unknown> = {\n ...existing,\n version: templateParsed.version,\n hooks: {\n ...prevHooks,\n sessionStart: templateParsed.hooks.sessionStart,\n stop: templateParsed.hooks.stop,\n },\n };\n\n return {\n content: `${JSON.stringify(merged, null, 2)}\\n`,\n action: existed ? \"overwritten\" : \"created\",\n };\n}\n","import type { AssistantAdapter, AssistantId } from \"./types.js\";\nimport { claudeCodeAdapter } from \"./claude-code.js\";\nimport { codexAdapter } from \"./codex.js\";\nimport { codebuddyAdapter } from \"./codebuddy.js\";\nimport { cursorAdapter } from \"./cursor.js\";\n\nexport const DEFAULT_ASSISTANT_IDS: AssistantId[] = [\"claude-code\"];\n\nconst ALL_ADAPTERS: AssistantAdapter[] = [\n claudeCodeAdapter,\n cursorAdapter,\n codebuddyAdapter,\n codexAdapter,\n];\n\nconst ADAPTER_BY_ID = new Map<AssistantId, AssistantAdapter>(\n ALL_ADAPTERS.map((a) => [a.id, a]),\n);\n\nexport function getAdapter(id: AssistantId): AssistantAdapter {\n const adapter = ADAPTER_BY_ID.get(id);\n if (!adapter) {\n throw new Error(`Unknown assistant id: ${id}`);\n }\n return adapter;\n}\n\nexport function listAvailable(): AssistantAdapter[] {\n return ALL_ADAPTERS.filter((a) => a.available);\n}\n\nexport function isKnownAssistantId(id: string): id is AssistantId {\n return ADAPTER_BY_ID.has(id as AssistantId);\n}\n\nexport function parseToolsArg(tools: string): AssistantId[] {\n const ids = tools\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n if (ids.length === 0) {\n throw new Error(\"init --tools requires at least one assistant id\");\n }\n\n const result: AssistantId[] = [];\n for (const id of ids) {\n if (!isKnownAssistantId(id)) {\n throw new Error(`Unknown assistant id: ${id}`);\n }\n const adapter = getAdapter(id);\n if (!adapter.available) {\n throw new Error(`Assistant not available yet: ${id}`);\n }\n result.push(id);\n }\n return result;\n}\n\nexport function validateAssistantSelection(ids: AssistantId[]): void {\n if (ids.length === 0) {\n throw new Error(\"At least one assistant must be selected\");\n }\n for (const id of ids) {\n const adapter = getAdapter(id);\n if (!adapter.available) {\n throw new Error(`Assistant not available yet: ${id}`);\n }\n }\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { GITKEEP_DIRS, MEMORY_DIR, MEMORY_SUBDIRS } from \"./paths.js\";\n\nexport function ensureMemoryTree(repoRoot: string): void {\n const memoryRoot = join(repoRoot, MEMORY_DIR);\n mkdirSync(memoryRoot, { recursive: true });\n\n for (const sub of MEMORY_SUBDIRS) {\n mkdirSync(join(memoryRoot, sub), { recursive: true });\n }\n\n mkdirSync(join(repoRoot, \".claude\"), { recursive: true });\n\n for (const sub of GITKEEP_DIRS) {\n const keepPath = join(memoryRoot, sub, \".gitkeep\");\n writeFileSync(keepPath, \"\", { flag: \"a\" });\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport { memoryPath } from \"./paths.js\";\n\nfunction readExistingAssistants(repoRoot: string): AssistantId[] {\n const configPath = memoryPath(repoRoot, \"config.json\");\n if (!existsSync(configPath)) {\n return [];\n }\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf8\")) as {\n assistants?: unknown;\n };\n if (!Array.isArray(config.assistants)) {\n return [];\n }\n return config.assistants.filter((id): id is AssistantId => typeof id === \"string\");\n } catch {\n return [];\n }\n}\n\n/** 与已有 config.assistants 做并集(保留已有 id + 追加本次选择) */\nexport function mergeAssistants(\n repoRoot: string,\n selected: AssistantId[],\n): AssistantId[] {\n const existing = readExistingAssistants(repoRoot);\n return [...new Set([...existing, ...selected])];\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { readTemplate } from \"./templateDir.js\";\n\nconst START_MARKER = \"# >>> hermes-repo memory (do not edit this block manually)\";\nconst END_MARKER = \"# <<< hermes-repo memory\";\n\nexport type GitignoreMergeAction = \"created\" | \"updated\" | \"replaced\" | \"appended\";\n\nexport function mergeHermesGitignore(repoRoot: string): {\n action: GitignoreMergeAction;\n warnBroadMemoryIgnore: boolean;\n} {\n const block = readTemplate(\"gitignore-block.txt\").trimEnd() + \"\\n\";\n const gitignorePath = join(repoRoot, \".gitignore\");\n const contentBefore = existsSync(gitignorePath)\n ? readFileSync(gitignorePath, \"utf8\")\n : \"\";\n\n const warnBroadMemoryIgnore =\n contentBefore.length > 0 &&\n !contentBefore.includes(START_MARKER) &&\n /(^|\\n)\\.memory\\/\\s*$/m.test(contentBefore);\n\n if (!existsSync(gitignorePath)) {\n writeFileSync(gitignorePath, `${block}\\n`, \"utf8\");\n return { action: \"created\", warnBroadMemoryIgnore: false };\n }\n\n const startIdx = contentBefore.indexOf(START_MARKER);\n const endIdx = contentBefore.indexOf(END_MARKER);\n\n if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {\n const before = contentBefore.slice(0, startIdx);\n const after = contentBefore.slice(endIdx + END_MARKER.length);\n const next = `${before}${block}${after}`.replace(/\\n{3,}/g, \"\\n\\n\");\n writeFileSync(gitignorePath, next.endsWith(\"\\n\") ? next : `${next}\\n`, \"utf8\");\n return { action: \"replaced\", warnBroadMemoryIgnore };\n }\n\n if (startIdx !== -1) {\n const before = contentBefore.slice(0, startIdx);\n const next = `${before}${block}\\n`;\n writeFileSync(gitignorePath, next, \"utf8\");\n return { action: \"updated\", warnBroadMemoryIgnore };\n }\n\n const separator = contentBefore.endsWith(\"\\n\") || contentBefore.length === 0 ? \"\\n\" : \"\\n\\n\";\n writeFileSync(gitignorePath, `${contentBefore}${separator}${block}\\n`, \"utf8\");\n return { action: \"appended\", warnBroadMemoryIgnore };\n}\n","import { copyFileSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { getAdapter } from \"./assistants/registry.js\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport type { InitReport, InitResolvedOptions } from \"./types.js\";\nimport { EXAMPLE_TEMPLATE_FILES, memoryPath } from \"./paths.js\";\nimport { renderTemplate, resolveTemplatePath } from \"./templateDir.js\";\nimport { mergeConfigForInit } from \"./mergeConfig.js\";\nimport { mergeAgentsMd } from \"./mergeAgentsMd.js\";\nimport { shouldWriteFile, writeIfAllowed } from \"./scaffoldWrite.js\";\n\nexport { shouldWriteFile } from \"./scaffoldWrite.js\";\n\n/** 生成 v2 config.json 内容 */\nexport function buildConfigJson(assistants: AssistantId[]): string {\n return `${JSON.stringify(\n {\n version: 2,\n storage: { backend: \"file\" },\n assistants,\n debug: false,\n llm: {\n enabled: false,\n provider: \"openai\",\n baseUrl: \"https://api.openai.com/v1\",\n model: \"gpt-4o\",\n apiKey: \"\",\n timeoutMs: 60_000,\n maxInputChars: 24_000,\n mode: \"async\",\n },\n consolidate: {\n autoArchiveDays: 30,\n autoFlush: {\n enabled: false,\n minPendingSessions: 3,\n minIntervalMinutes: 30,\n maxPendingChars: 20_000,\n },\n },\n },\n null,\n 2,\n )}\\n`;\n}\n\nfunction writeConfigJson(\n report: InitReport,\n repoRoot: string,\n assistants: AssistantId[],\n): void {\n const { content, action } = mergeConfigForInit(repoRoot, assistants);\n const absolutePath = memoryPath(repoRoot, \"config.json\");\n writeFileSync(absolutePath, content, \"utf8\");\n report.files.push({ path: \".memory/config.json\", action });\n}\n\nfunction copyTemplateIfAllowed(\n report: InitReport,\n templateName: string,\n destAbsolute: string,\n relativePath: string,\n force: boolean,\n): void {\n const { write, action } = shouldWriteFile(destAbsolute, force);\n if (!write) {\n report.files.push({ path: relativePath, action });\n return;\n }\n copyFileSync(resolveTemplatePath(templateName), destAbsolute);\n report.files.push({ path: relativePath, action });\n}\n\nexport function writeScaffoldFiles(\n repoRoot: string,\n opts: InitResolvedOptions,\n report: InitReport,\n): void {\n const { force, includeExampleTemplates, assistants } = opts;\n\n writeConfigJson(report, repoRoot, assistants);\n\n // v2: LLM settings live in config.json.\n\n // MEMORY.md — v2 导航模板\n writeIfAllowed(\n report,\n memoryPath(repoRoot, \"MEMORY.md\"),\n \".memory/MEMORY.md\",\n renderTemplate(\"MEMORY.md.tpl\"),\n force,\n );\n\n // consolidate-state.json — 初始空状态\n writeIfAllowed(\n report,\n memoryPath(repoRoot, \"consolidate-state.json\"),\n \".memory/consolidate-state.json\",\n `${JSON.stringify(\n {\n version: 1,\n lastConsolidatedAt: null,\n stats: {\n totalCapturesProcessed: 0,\n domains: [],\n knowledgeFilesCreated: 0,\n },\n processedSessions: {},\n },\n null,\n 2,\n )}\\n`,\n force,\n );\n\n // v2: 不再生成 sessions/index.json 和 team/steward-log.md\n\n report.files.push({\n path: \"AGENTS.md\",\n action: mergeAgentsMd(repoRoot, force),\n });\n\n for (const id of assistants) {\n getAdapter(id).write({ repoRoot, force, report });\n }\n\n if (includeExampleTemplates && EXAMPLE_TEMPLATE_FILES.length > 0) {\n // v2: templates/ 目录不在 ensureMemoryTree 中,按需创建\n const templatesDir = memoryPath(repoRoot, \"templates\");\n mkdirSync(templatesDir, { recursive: true });\n for (const name of EXAMPLE_TEMPLATE_FILES) {\n const dest = memoryPath(repoRoot, \"templates\", name);\n copyTemplateIfAllowed(\n report,\n name,\n dest,\n `.memory/templates/${name}`,\n force,\n );\n }\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport type { InitFileAction } from \"./types.js\";\nimport { memoryPath } from \"./paths.js\";\n\n/** v2: init 每次都会写入的完整 config 字段(已有自定义值优先保留) */\nconst DEFAULT_LLM = {\n enabled: false,\n provider: \"openai\",\n baseUrl: \"https://api.openai.com/v1\",\n model: \"gpt-4o\",\n apiKey: \"\",\n timeoutMs: 60_000,\n maxInputChars: 24_000,\n mode: \"async\",\n};\n\nconst DEFAULT_CONSOLIDATE = {\n autoArchiveDays: 30,\n autoFlush: {\n enabled: false,\n minPendingSessions: 3,\n minIntervalMinutes: 30,\n maxPendingChars: 20_000,\n },\n};\n\nexport function mergeConfigForInit(\n repoRoot: string,\n assistants: AssistantId[],\n): { content: string; action: InitFileAction } {\n const configPath = memoryPath(repoRoot, \"config.json\");\n const existed = existsSync(configPath);\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(readFileSync(configPath, \"utf8\")) as Record<\n string,\n unknown\n >;\n } catch {\n existing = {};\n }\n }\n\n const prevStorage =\n existing.storage &&\n typeof existing.storage === \"object\" &&\n !Array.isArray(existing.storage)\n ? (existing.storage as Record<string, unknown>)\n : {};\n\n // v2: 合并 llm 和 consolidate 字段(用户已配置的优先保留)\n const prevLlm =\n existing.llm && typeof existing.llm === \"object\" && !Array.isArray(existing.llm)\n ? (existing.llm as Record<string, unknown>)\n : {};\n const prevConsolidate =\n existing.consolidate && typeof existing.consolidate === \"object\" && !Array.isArray(existing.consolidate)\n ? (existing.consolidate as Record<string, unknown>)\n : {};\n const prevAutoFlush =\n prevConsolidate.autoFlush &&\n typeof prevConsolidate.autoFlush === \"object\" &&\n !Array.isArray(prevConsolidate.autoFlush)\n ? (prevConsolidate.autoFlush as Record<string, unknown>)\n : {};\n\n const merged: Record<string, unknown> = {\n ...existing,\n version: 2,\n storage: {\n ...prevStorage,\n backend: \"file\",\n },\n assistants,\n debug: existing.debug === true,\n llm: { ...DEFAULT_LLM, ...prevLlm },\n consolidate: {\n ...DEFAULT_CONSOLIDATE,\n ...prevConsolidate,\n autoFlush: {\n ...DEFAULT_CONSOLIDATE.autoFlush,\n ...prevAutoFlush,\n },\n },\n };\n\n return {\n content: `${JSON.stringify(merged, null, 2)}\\n`,\n action: existed ? \"overwritten\" : \"created\",\n };\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { InitFileAction } from \"./types.js\";\nimport { readTemplate, renderTemplate } from \"./templateDir.js\";\n\nexport const HERMES_AGENTS_START_MARKER =\n \"<!-- >>> hermes-repo agents (do not edit this block manually) -->\";\nexport const HERMES_AGENTS_END_MARKER = \"<!-- <<< hermes-repo agents -->\";\n\nexport function buildHermesAgentsBlockBody(): string {\n return renderTemplate(\"AGENTS.hermes-block.tpl\").trimEnd();\n}\n\nexport function buildHermesAgentsMarkedBlock(): string {\n const body = buildHermesAgentsBlockBody();\n return `${HERMES_AGENTS_START_MARKER}\\n${body}\\n${HERMES_AGENTS_END_MARKER}`;\n}\n\nexport function buildNewAgentsMd(): string {\n return renderTemplate(\"AGENTS.md.tpl\").replace(\n \"__HERMES_AGENTS_BLOCK__\",\n buildHermesAgentsBlockBody(),\n );\n}\n\nexport function agentsMdHasHermesBlock(content: string): boolean {\n const startIdx = content.indexOf(HERMES_AGENTS_START_MARKER);\n const endIdx = content.indexOf(HERMES_AGENTS_END_MARKER);\n return startIdx !== -1 && endIdx !== -1 && endIdx > startIdx;\n}\n\n/** 无标记块但已手写 hermes 指引时视为已接入(避免重复追加) */\nexport function agentsMdHasLegacyHermesContent(content: string): boolean {\n if (agentsMdHasHermesBlock(content)) {\n return false;\n }\n return (\n content.includes(\"@riconext/hermes-repo\") &&\n content.includes(\"## 记忆系统\") &&\n content.includes(\".memory/MEMORY.md\")\n );\n}\n\nexport function agentsMdHasHermesContent(content: string): boolean {\n return agentsMdHasHermesBlock(content) || agentsMdHasLegacyHermesContent(content);\n}\n\n/** 已有正文与 hermes 标记块之间约两行空行 */\nconst GAP_BEFORE_HERMES_BLOCK = \"\\n\\n\\n\";\n\nfunction withGapBeforeHermesBlock(prefix: string): string {\n const trimmed = prefix.trimEnd();\n if (trimmed.length === 0) {\n return \"\";\n }\n return `${trimmed}${GAP_BEFORE_HERMES_BLOCK}`;\n}\n\nfunction spliceHermesBlock(existing: string, block: string): string {\n const startIdx = existing.indexOf(HERMES_AGENTS_START_MARKER);\n const endIdx = existing.indexOf(HERMES_AGENTS_END_MARKER);\n\n if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {\n const before = existing.slice(0, startIdx);\n const after = existing.slice(endIdx + HERMES_AGENTS_END_MARKER.length);\n const next = `${withGapBeforeHermesBlock(before)}${block}${after}`;\n return next.endsWith(\"\\n\") ? next : `${next}\\n`;\n }\n\n if (startIdx !== -1) {\n const before = existing.slice(0, startIdx);\n return `${withGapBeforeHermesBlock(before)}${block}\\n`;\n }\n\n return `${withGapBeforeHermesBlock(existing)}${block}\\n`;\n}\n\nexport function mergeAgentsMd(\n repoRoot: string,\n force: boolean,\n): InitFileAction {\n const agentsPath = join(repoRoot, \"AGENTS.md\");\n const block = buildHermesAgentsMarkedBlock();\n\n if (!existsSync(agentsPath)) {\n writeFileSync(agentsPath, buildNewAgentsMd(), \"utf8\");\n return \"created\";\n }\n\n const content = readFileSync(agentsPath, \"utf8\");\n\n if (agentsMdHasHermesBlock(content)) {\n if (!force) {\n return \"skipped\";\n }\n writeFileSync(agentsPath, spliceHermesBlock(content, block), \"utf8\");\n return \"replaced\";\n }\n\n if (agentsMdHasLegacyHermesContent(content)) {\n return \"skipped\";\n }\n\n writeFileSync(agentsPath, spliceHermesBlock(content, block), \"utf8\");\n return \"appended\";\n}\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport type { InitFileAction, InitReport } from \"./types.js\";\n\nexport function shouldWriteFile(\n absolutePath: string,\n force: boolean,\n): { write: boolean; action: InitFileAction } {\n if (!existsSync(absolutePath)) {\n return { write: true, action: \"created\" };\n }\n if (force) {\n return { write: true, action: \"overwritten\" };\n }\n return { write: false, action: \"skipped\" };\n}\n\nexport function writeIfAllowed(\n report: InitReport,\n absolutePath: string,\n relativePath: string,\n content: string,\n force: boolean,\n): void {\n const { write, action } = shouldWriteFile(absolutePath, force);\n if (!write) {\n report.files.push({ path: relativePath, action });\n return;\n }\n writeFileSync(absolutePath, content, \"utf8\");\n report.files.push({ path: relativePath, action });\n}\n","import { checkbox, confirm, input } from \"@inquirer/prompts\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { listAvailable } from \"./assistants/registry.js\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport type { InitCliOptions, InitResolvedOptions } from \"./types.js\";\nimport { memoryPath } from \"./paths.js\";\n\nfunction isInitialized(targetDir: string): boolean {\n const configPath = memoryPath(targetDir, \"config.json\");\n if (!existsSync(configPath)) {\n return false;\n }\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf8\")) as {\n version?: number;\n };\n return typeof config.version === \"number\" && config.version >= 1;\n } catch {\n return false;\n }\n}\n\nexport async function gatherInitOptions(\n opts: InitCliOptions,\n): Promise<InitResolvedOptions> {\n const defaultDir = resolve(opts.cwd ?? process.cwd());\n\n const targetInput = await input({\n message: \"目标目录(Git 仓库根)\",\n default: defaultDir,\n });\n const targetDir = resolve(targetInput);\n\n const assistants = (await checkbox({\n message: \"选择要接入的编程助手(可多选)\",\n choices: listAvailable().map((a) => ({\n name: a.label,\n value: a.id,\n checked: a.id === \"claude-code\",\n })),\n validate: (value) => value.length > 0 || \"请至少选择一项\",\n })) as AssistantId[];\n\n const includeExampleTemplates = await confirm({\n message: \"是否写入 capture 示例模板到 .memory/templates/?\",\n default: true,\n });\n\n if (isInitialized(targetDir)) {\n const continueInit = await confirm({\n message: \"检测到已有 .memory/config.json,是否仅补全缺失项?\",\n default: true,\n });\n if (!continueInit) {\n return {\n targetDir,\n force: false,\n includeExampleTemplates,\n assistants,\n cancelled: true,\n };\n }\n }\n\n return {\n targetDir,\n force: Boolean(opts.force),\n includeExampleTemplates,\n assistants,\n cancelled: false,\n };\n}\n","import type { InitCliOptions } from \"../init/types.js\";\nimport { runInit } from \"../init/runInit.js\";\n\nexport async function runInitCommand(opts: InitCliOptions): Promise<void> {\n try {\n await runInit(opts);\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;;;ACAxB,SAAS,gBAAgB,iBAAiB;AAC1C,SAAS,eAAe;;;ACDxB,SAAS,YAAY;AAEd,IAAM,aAAa;AAGnB,IAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,yBAAyB;AAAA,EACpC;AACF;AAWO,SAAS,WAAW,SAAiB,UAA4B;AACtE,SAAO,KAAK,MAAM,YAAY,GAAG,QAAQ;AAC3C;;;ADnCO,IAAM,iBAAiB;AAE9B,IAAI,cAA6B;AAE1B,SAAS,sBACd,UACA,SACM;AACN,MAAI,CAAC,WAAW,CAAC,UAAU;AACzB,kBAAc;AACd;AAAA,EACF;AACA,gBAAc,WAAW,UAAU,cAAc;AACnD;AAEA,SAAS,WAAW,OAAe,SAAyB;AAC1D,SAAO,IAAG,oBAAI,KAAK,GAAE,YAAY,CAAC,iBAAiB,KAAK,KAAK,OAAO;AACtE;AAEA,SAAS,eAAe,MAAoB;AAC1C,MAAI,CAAC,aAAa;AAChB;AAAA,EACF;AACA,YAAU,QAAQ,WAAW,GAAG,EAAE,WAAW,KAAK,CAAC;AACnD,iBAAe,aAAa,GAAG,IAAI;AAAA,GAAM,MAAM;AACjD;AAEO,SAAS,SACd,SACA,OACA,SACM;AACN,MAAI,CAAC,SAAS;AACZ;AAAA,EACF;AACA,QAAM,OAAO,WAAW,OAAO,OAAO;AACtC,UAAQ,MAAM,IAAI;AAClB,iBAAe,IAAI;AACrB;AAEO,SAAS,cACd,SACA,OACA,OACA,SACM;AACN,MAAI,CAAC,SAAS;AACZ;AAAA,EACF;AAEA,WAAS,MAAM,OAAO,GAAG,KAAK,QAAQ;AACtC,aAAW,QAAQ,QAAQ,MAAM,OAAO,GAAG;AACzC,aAAS,MAAM,OAAO,KAAK,IAAI,EAAE;AAAA,EACnC;AACA,WAAS,MAAM,OAAO,GAAG,KAAK,MAAM;AACtC;AAEO,SAAS,iBACd,KACA,OACA,SACM;AACN,WAAS,KAAK,OAAO,UAAU,MAAM,OAAO,OAAO;AACrD;;;AEpEA,SAAS,oBAAoB;AAC7B,SAAS,QAAAA,aAAY;;;ACDrB,SAAS,kBAAkB;AAC3B,SAAS,WAAAC,UAAS,QAAAC,OAAM,eAAe;AAEvC,IAAM,aAAaA,MAAK,WAAW,aAAa;AAEzC,SAAS,aAAa,UAAkC;AAC7D,MAAI,MAAM,QAAQ,YAAY,QAAQ,IAAI,CAAC;AAE3C,SAAO,MAAM;AACX,QAAI,WAAWA,MAAK,KAAK,UAAU,CAAC,GAAG;AACrC,aAAO;AAAA,IACT;AACA,UAAM,SAASD,SAAQ,GAAG;AAC1B,QAAI,WAAW,KAAK;AAClB,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;;;ADPA,SAAS,cAAc,OAAsC;AAC3D,SAAO,OAAO,UAAU;AAC1B;AAEA,SAAS,eAAe,KAA2C;AACjE,QAAM,MAAM,IAAI;AAChB,SAAO;AAAA,IACL,SAAS,OAAO,KAAK,YAAY,YAAY,IAAI,UAAU;AAAA,IAC3D,UAAU,OAAO,KAAK,aAAa,WAAW,IAAI,WAAW;AAAA,IAC7D,SAAS,OAAO,KAAK,YAAY,WAAW,IAAI,UAAU;AAAA,IAC1D,OAAO,OAAO,KAAK,UAAU,WAAW,IAAI,QAAQ;AAAA,IACpD,QAAQ,OAAO,KAAK,WAAW,WAAW,IAAI,SAAS;AAAA,IACvD,WACE,OAAO,KAAK,cAAc,YAAY,IAAI,YAAY,IAClD,IAAI,YACJ;AAAA,IACN,eACE,OAAO,KAAK,kBAAkB,YAAY,IAAI,gBAAgB,IAC1D,IAAI,gBACJ;AAAA,IACN,MAAM,KAAK,SAAS,SAAS,SAAS;AAAA,EACxC;AACF;AAEA,SAAS,uBAAuB,KAAiD;AAC/E,QAAM,IAAI,IAAI;AACd,QAAM,YACJ,GAAG,aAAa,OAAO,EAAE,cAAc,YAAY,CAAC,MAAM,QAAQ,EAAE,SAAS,IACxE,EAAE,YACH,CAAC;AACP,SAAO;AAAA,IACL,iBAAiB,OAAO,GAAG,oBAAoB,WAAW,EAAE,kBAAkB;AAAA,IAC9E,WAAW;AAAA,MACT,SAAS,UAAU,YAAY;AAAA,MAC/B,oBACE,OAAO,UAAU,uBAAuB,YACxC,UAAU,qBAAqB,IAC3B,UAAU,qBACV;AAAA,MACN,oBACE,OAAO,UAAU,uBAAuB,YACxC,UAAU,qBAAqB,IAC3B,UAAU,qBACV;AAAA,MACN,iBACE,OAAO,UAAU,oBAAoB,YACrC,UAAU,kBAAkB,IACxB,UAAU,kBACV;AAAA,IACR;AAAA,EACF;AACF;AAEO,SAAS,iBAAiB,UAAuC;AACtE,QAAM,aAAaE,MAAK,UAAU,WAAW,aAAa;AAC1D,MAAI;AACF,UAAM,MAAM,KAAK,MAAM,aAAa,YAAY,MAAM,CAAC;AACvD,UAAM,UAAU,IAAI;AAGpB,QAAI,YAAY,GAAG;AACjB,YAAM,aAAa,MAAM,QAAQ,IAAI,UAAU,IAC3C,IAAI,WAAW,OAAO,aAAa,IACnC,CAAC;AACL,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,EAAE,SAAU,IAAI,SAAqC,YAAY,SAAS,SAAS,OAAO;AAAA,QACnG;AAAA,QACA,OAAO,IAAI,UAAU;AAAA,QACrB,KAAK,eAAe,GAAG;AAAA,QACvB,aAAa,uBAAuB,GAAG;AAAA,MACzC;AAAA,IACF;AAGA,QAAI,YAAY,KAAK,YAAY,QAAW;AAC1C,YAAM,aAAa,MAAM,QAAQ,IAAI,UAAU,IAC3C,IAAI,WAAW,OAAO,aAAa,IACnC,CAAC;AACL,aAAO;AAAA,QACL,SAAS;AAAA;AAAA,QACT,SAAS,EAAE,SAAS,OAAO;AAAA,QAC3B;AAAA,QACA,OAAO,IAAI,UAAU;AAAA,QACrB,KAAK;AAAA,UACH,SAAS;AAAA,UACT,UAAU;AAAA,UACV,SAAS;AAAA,UACT,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,eAAe;AAAA,UACf,MAAM;AAAA,QACR;AAAA,QACA,aAAa;AAAA,UACX,iBAAiB;AAAA,UACjB,WAAW;AAAA,YACT,SAAS;AAAA,YACT,oBAAoB;AAAA,YACpB,oBAAoB;AAAA,YACpB,iBAAiB;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,gBAAgB,KAAkC;AAChE,QAAM,WAAW,aAAa,GAAG;AACjC,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,QAAM,SAAS,iBAAiB,QAAQ;AACxC,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,SAAO,EAAE,UAAU,OAAO;AAC5B;;;AErIA,SAAS,cAAAC,aAAY,gBAAAC,eAAc,YAAY,iBAAAC,sBAAqB;AACpE,SAAS,QAAAC,aAAY;;;ACsBd,SAAS,eAAe,KAAgC;AAC7D,MAAI,CAAC,KAAK,SAAS;AACjB,WAAO;AAAA,EACT;AACA,SACE,QAAQ,IAAI,QAAQ,KAAK,CAAC,KAC1B,QAAQ,IAAI,SAAS,KAAK,CAAC,KAC3B,QAAQ,IAAI,OAAO,KAAK,CAAC;AAE7B;AAEO,SAAS,iBAAiB,KAAgC;AAC/D,SAAO,IAAI,SAAS,SAAS,SAAS;AACxC;;;ACpCA,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,gBAAgB;AAGzB,IAAM,oBACJ;AAGF,IAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,qBAAqB,SAA0B;AACtD,MAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,SAAO,QACJ,IAAI,CAAC,SAAS;AACb,QAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,aAAO;AAAA,IACT;AACA,UAAM,IAAI;AACV,QAAI,OAAO,EAAE,SAAS,UAAU;AAC9B,aAAO,EAAE;AAAA,IACX;AACA,WAAO;AAAA,EACT,CAAC,EACA,OAAO,OAAO,EACd,KAAK,IAAI;AACd;AAEA,SAAS,YAAY,QAAyC;AAC5D,MAAI,OAAO,OAAO,YAAY,UAAU;AACtC,WAAO,OAAO;AAAA,EAChB;AACA,MAAI,MAAM,QAAQ,OAAO,OAAO,GAAG;AACjC,UAAM,MAAM,qBAAqB,OAAO,OAAO;AAC/C,QAAI,KAAK;AACP,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,UAAU,OAAO;AACvB,MAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,UAAM,MAAM;AACZ,QAAI,OAAO,IAAI,YAAY,UAAU;AACnC,aAAO,IAAI;AAAA,IACb;AACA,QAAI,MAAM,QAAQ,IAAI,OAAO,GAAG;AAC9B,aAAO,qBAAqB,IAAI,OAAO;AAAA,IACzC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,UAAU,QAAyC;AAC1D,MAAI,OAAO,OAAO,SAAS,UAAU;AACnC,WAAO,OAAO;AAAA,EAChB;AACA,MAAI,OAAO,OAAO,SAAS,UAAU;AACnC,UAAM,IAAI,OAAO,KAAK,YAAY;AAClC,QAAI,MAAM,UAAU,MAAM,QAAS,QAAO;AAC1C,QAAI,MAAM,YAAa,QAAO;AAAA,EAChC;AACA,SAAO;AACT;AAEA,SAAS,cAAc,QAA0C;AAC/D,QAAM,IAAI,OAAO,OAAO,QAAQ,EAAE,EAAE,YAAY;AAChD,SAAO,gBAAgB,IAAI,CAAC;AAC9B;AAEA,SAAS,UAAU,QAA0C;AAC3D,QAAM,IAAI,OAAO,OAAO,QAAQ,EAAE,EAAE,YAAY;AAChD,SAAO,MAAM,cAAc,MAAM,UAAU,MAAM;AACnD;AAEA,SAAS,SAAS,QAAyC;AACzD,MAAI,OAAO,OAAO,SAAS,SAAU,QAAO,OAAO;AACnD,QAAM,OAAO,OAAO;AACpB,MAAI,QAAQ,OAAO,SAAS,YAAY,UAAU,MAAM;AACtD,WAAO,OAAQ,KAA0B,IAAI;AAAA,EAC/C;AACA,SAAO;AACT;AAGA,SAAS,iBAAiB,QAGxB;AACA,MAAI,YAAY;AAChB,MAAI,cAAc;AAClB,QAAM,UAAU,OAAO;AACvB,MAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,WAAO,EAAE,WAAW,YAAY;AAAA,EAClC;AACA,QAAM,UAAW,QAAoC;AACrD,MAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,WAAO,EAAE,WAAW,YAAY;AAAA,EAClC;AACA,aAAW,QAAQ,SAAS;AAC1B,QAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC;AAAA,IACF;AACA,UAAM,IAAI;AACV,UAAM,IAAI,OAAO,EAAE,QAAQ,EAAE,EAAE,YAAY;AAC3C,QAAI,MAAM,cAAc,MAAM,QAAQ;AACpC;AAAA,IACF;AACA,iBAAa;AACb,UAAM,OAAO,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO;AACnD,QAAI,kBAAkB,KAAK,IAAI,GAAG;AAChC,qBAAe;AAAA,IACjB;AAAA,EACF;AACA,SAAO,EAAE,WAAW,YAAY;AAClC;AAEO,SAAS,eAAe,WAAkC;AAC/D,QAAM,YAAY,SAAS,WAAW,QAAQ;AAC9C,QAAM,MAAMA,cAAa,WAAW,MAAM;AAC1C,QAAM,WAA6B,CAAC;AACpC,MAAI,cAAc;AAClB,MAAI,YAAY;AAEhB,aAAW,QAAQ,IAAI,MAAM,IAAI,GAAG;AAClC,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,QAAS;AACd,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,OAAO;AACjC,UAAI,cAAc,MAAM,GAAG;AACzB;AAAA,MACF;AACA,UAAI,UAAU,MAAM,GAAG;AACrB,qBAAa;AACb,cAAM,OAAO,SAAS,MAAM;AAC5B,YAAI,kBAAkB,KAAK,IAAI,GAAG;AAChC,yBAAe;AAAA,QACjB;AACA;AAAA,MACF;AACA,YAAM,SAAS,iBAAiB,MAAM;AACtC,mBAAa,OAAO;AACpB,qBAAe,OAAO;AACtB,YAAM,OAAO,UAAU,MAAM;AAC7B,YAAMC,QAAO,YAAY,MAAM;AAC/B,UAAIA,OAAM;AACR,iBAAS,KAAK,EAAE,MAAM,MAAAA,MAAK,CAAC;AAAA,MAC9B;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,OAAO,SAAS,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AAElD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACrKA,SAAS,aAAa;AACtB;AAAA,EACE,cAAAC;AAAA,EACA,aAAAC;AAAA,EACA;AAAA,EACA,gBAAAC;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAAC,UAAS,QAAAC,aAAY;AAC9B,SAAS,qBAAqB;AAc9B,SAAS,WAAW,UAA0B;AAC5C,SAAO,WAAW,UAAU,YAAY,SAAS;AACnD;AAEA,SAAS,UAAkB;AACzB,SAAOC,MAAKC,SAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,MAAM,QAAQ;AACrE;AAEA,SAAS,UAAU,WAA2B;AAC5C,QAAM,OAAO,UAAU,QAAQ,mBAAmB,EAAE,EAAE,MAAM,GAAG,EAAE;AACjE,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,QAAQ,SAAS;AAC3C;AAEA,SAAS,0BACP,UACA,WACM;AACN,QAAM,MAAM,WAAW,QAAQ;AAC/B,MAAI,CAACC,YAAW,GAAG,GAAG;AACpB;AAAA,EACF;AACA,aAAW,QAAQ,YAAY,GAAG,GAAG;AACnC,QAAI,CAAC,KAAK,SAAS,OAAO,GAAG;AAC3B;AAAA,IACF;AACA,QAAI;AACF,YAAM,MAAM,KAAK;AAAA,QACfC,cAAaH,MAAK,KAAK,IAAI,GAAG,MAAM;AAAA,MACtC;AACA,UAAI,IAAI,cAAc,WAAW;AAC/B,eAAOA,MAAK,KAAK,IAAI,GAAG,EAAE,OAAO,KAAK,CAAC;AAAA,MACzC;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAEO,SAAS,cAAc,MAOlB;AACV,QAAM,EAAE,UAAU,WAAW,WAAW,aAAa,WAAW,MAAM,IACpE;AACF,QAAM,MAAM,WAAW,QAAQ;AAC/B,EAAAI,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,4BAA0B,UAAU,SAAS;AAE7C,QAAM,QAAQ,UAAU,SAAS;AACjC,QAAM,UAAyB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,EACrC;AACA;AAAA,IACEJ,MAAK,KAAK,GAAG,KAAK,OAAO;AAAA,IACzB,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA;AAAA,IACnC;AAAA,EACF;AAEA,QAAM,QAAQ;AAAA,IACZ,QAAQ;AAAA,IACR,CAAC,QAAQ,GAAG,eAAe,SAAS,OAAO,MAAM,QAAQ;AAAA,IACzD;AAAA,MACE,UAAU;AAAA,MACV,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAAA,EACF;AACA,QAAM,MAAM;AAEZ,WAAS,UAAU,MAAM,WAAW,qBAAqB,KAAK,EAAE;AAChE,SAAO;AACT;AAEO,SAAS,WACd,UACA,OACsB;AACtB,QAAM,OAAOA,MAAK,WAAW,QAAQ,GAAG,GAAG,KAAK,OAAO;AACvD,MAAI,CAACE,YAAW,IAAI,GAAG;AACrB,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,KAAK,MAAMC,cAAa,MAAM,MAAM,CAAC;AAAA,EAC9C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,aAAa,UAAkB,OAAqB;AAClE,QAAM,OAAOH,MAAK,WAAW,QAAQ,GAAG,GAAG,KAAK,OAAO;AACvD,MAAIE,YAAW,IAAI,GAAG;AACpB,WAAO,MAAM,EAAE,OAAO,KAAK,CAAC;AAAA,EAC9B;AACF;AAEO,SAAS,gBAAgB,UAAmC;AACjE,QAAM,MAAM,WAAW,QAAQ;AAC/B,MAAI,CAACA,YAAW,GAAG,GAAG;AACpB,WAAO,CAAC;AAAA,EACV;AACA,QAAM,OAAwB,CAAC;AAC/B,aAAW,QAAQ,YAAY,GAAG,GAAG;AACnC,QAAI,CAAC,KAAK,SAAS,OAAO,GAAG;AAC3B;AAAA,IACF;AACA,QAAI;AACF,WAAK;AAAA,QACH,KAAK,MAAMC,cAAaH,MAAK,KAAK,IAAI,GAAG,MAAM,CAAC;AAAA,MAClD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;;;ACjJO,SAAS,mBACd,SACA,UACQ;AACR,QAAM,QAAkB;AAAA,IACtB,cAAc,QAAQ,SAAS;AAAA,IAC/B,aAAa,QAAQ,SAAS,MAAM;AAAA,IACpC,cAAc,QAAQ,SAAS;AAAA,IAC/B,gBAAgB,QAAQ,WAAW;AAAA,IACnC;AAAA,IACA;AAAA,EACF;AAEA,MAAI,OAAO,MAAM,KAAK,IAAI,EAAE;AAC5B,QAAM,YAAY,CAAC,GAAG,QAAQ,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM;AACrD,QAAI,EAAE,SAAS,UAAU,EAAE,SAAS,OAAQ,QAAO;AACnD,QAAI,EAAE,SAAS,UAAU,EAAE,SAAS,OAAQ,QAAO;AACnD,WAAO;AAAA,EACT,CAAC;AAED,aAAW,KAAK,WAAW;AACzB,UAAM,QAAQ,IAAI,EAAE,IAAI;AAAA,EAAM,EAAE,KAAK,MAAM,GAAG,GAAI,CAAC;AAAA;AACnD,QAAI,OAAO,MAAM,SAAS,UAAU;AAClC,YAAM,KAAK,qBAAqB;AAChC;AAAA,IACF;AACA,UAAM,KAAK,KAAK;AAChB,YAAQ,MAAM;AAAA,EAChB;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACjBA,IAAM,cAAc,oBAAI,IAAuB;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,SAAS,oBAAoB,KAAuC;AACzE,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,QAAM,OAAO,EAAE;AACf,MAAI,OAAO,SAAS,YAAY,CAAC,YAAY,IAAI,IAAyB,GAAG;AAC3E,WAAO;AAAA,EACT;AACA,QAAM,UAAU,OAAO,EAAE,YAAY,WAAW,EAAE,QAAQ,KAAK,IAAI;AACnE,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,QAAM,OAAO,MAAM,QAAQ,EAAE,IAAI,IAC7B,EAAE,KAAK,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IACvD,CAAC;AACL,QAAM,QACJ,OAAO,EAAE,UAAU,YAAY,EAAE,MAAM,KAAK,IACxC,EAAE,MAAM,KAAK,IACb;AAEN,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ;AAAA,IAC/C;AAAA,IACA,UAAU,OAAO,EAAE,aAAa,WAAW,EAAE,WAAW;AAAA,IACxD,QAAQ,OAAO,EAAE,WAAW,WAAW,EAAE,SAAS;AAAA,IAClD,MAAM,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO;AAAA,IAC5C,OAAO,MAAM,QAAQ,EAAE,KAAK,IACxB,EAAE,MAAM,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IACxD;AAAA,IACJ,UAAU,MAAM,QAAQ,EAAE,QAAQ,IAC9B,EAAE,SAAS,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IAC3D;AAAA,IACJ,cAAc,MAAM,QAAQ,EAAE,YAAY,IACtC,EAAE,aAAa,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,IAC/D;AAAA,EACN;AACF;AASO,SAAS,sBAAsB,SAAmC;AACvE,MAAI,QAAQ,SAAS,cAAc;AACjC,UAAM,QACJ,QAAQ,OAAO,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,KACxD,QAAQ,YACR;AACF,UAAM,WACJ,QAAQ,UAAU,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,KAAK;AACvD,UAAM,eACJ,QAAQ,cAAc,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,KAAK;AAC3D,WAAO;AAAA;AAAA,EAET,QAAQ,QAAQ,QAAQ,OAAO;AAAA;AAAA;AAAA;AAAA,EAI/B,KAAK;AAAA,EACL,QAAQ,UAAU,SAAS;AAAA;AAAA;AAAA;AAAA,EAAgB,QAAQ,KAAK,EAAE;AAAA,EAC1D,QAAQ,cAAc,SAAS;AAAA;AAAA;AAAA;AAAA,EAAgB,YAAY,KAAK,EAAE;AAAA,EAClE;AAEA,SAAO;AAAA;AAAA,EAEP,QAAQ,OAAO;AAAA;AAAA;AAAA;AAAA,EAIf,QAAQ,YAAY,QAAQ,SAAS,sCAAQ;AAAA;AAAA;AAAA;AAAA,EAI7C,QAAQ,UAAU,+DAAuB;AAC3C;;;AC/FA,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBtB,eAAsB,qBACpB,SACA,KACkC;AAClC,QAAM,SAAS,mBAAmB,SAAS,IAAI,aAAa;AAC5D,QAAM,MAAM,GAAG,IAAI,QAAQ,QAAQ,OAAO,EAAE,CAAC;AAC7C,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,IAAI,SAAS;AAElE,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,IAAI,MAAM;AAAA,MACrC;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO,IAAI;AAAA,QACX,iBAAiB,EAAE,MAAM,cAAc;AAAA,QACvC,UAAU;AAAA,UACR,EAAE,MAAM,UAAU,SAAS,cAAc;AAAA,UACzC;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA;AAAA,EAAwC,MAAM;AAAA,UACzD;AAAA,QACF;AAAA,QACA,aAAa;AAAA,MACf,CAAC;AAAA,MACD,QAAQ,WAAW;AAAA,IACrB,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,aAAO;AAAA,IACT;AAEA,UAAM,OAAQ,MAAM,IAAI,KAAK;AAG7B,UAAM,UAAU,KAAK,UAAU,CAAC,GAAG,SAAS;AAC5C,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AAEA,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,OAAO;AAAA,IAC7B,QAAQ;AACN,aAAO;AAAA,IACT;AACA,WAAO,oBAAoB,MAAM;AAAA,EACnC,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,iBAAa,OAAO;AAAA,EACtB;AACF;;;ACtEA,SAAS,iBAAiB,SAAiD;AACzE,QAAM,qBACJ;AACF,MAAI,mBAAmB,KAAK,QAAQ,IAAI,GAAG;AACzC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAWA,SAAS,eAAe,WAAgC;AACtD,SAAO;AACT;AAEO,SAAS,aACd,SACA,WACkB;AAClB,QAAM,OAAO,iBAAiB,OAAO;AACrC,QAAM,SAAS,QAAQ,SAAS,MAAM,EAAE;AACxC,QAAM,UAAU,OACb,IAAI,CAAC,MAAM,KAAK,EAAE,IAAI,OAAO,EAAE,KAAK,MAAM,GAAG,GAAG,CAAC,EAAE,EACnD,KAAK,MAAM;AAEd,QAAM,eAAe;AAAA;AAAA,iCAEf,eAAe,SAAS,CAAC,mBAAS,QAAQ,SAAS;AAAA;AAAA;AAAA;AAAA,EAIzD,WAAW,4CAAS;AAAA;AAAA;AAAA;AAAA;AAMpB,SAAO;AAAA,IACL;AAAA,IACA,WAAW,QAAQ;AAAA,IACnB,MAAM,CAAC,gBAAgB,SAAS;AAAA,IAChC,OAAO;AAAA,IACP;AAAA,EACF;AACF;AAEO,SAAS,wBACd,SACA,WACA,SACkB;AAClB,QAAM,SAAS,oBAAI,IAAI,CAAC,gBAAgB,WAAW,GAAG,QAAQ,IAAI,CAAC;AACnE,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,WAAW,QAAQ;AAAA,IACnB,MAAM,CAAC,GAAG,MAAM;AAAA,IAChB,OAAO,QAAQ;AAAA,IACf,cAAc,sBAAsB,OAAO;AAAA,IAC3C,gBAAe,oBAAI,KAAK,GAAE,YAAY;AAAA,EACxC;AACF;AAEA,eAAsB,UACpB,SACA,WACA,KACkC;AAClC,QAAM,UAAU,MAAM,qBAAqB,SAAS,GAAG;AACvD,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,SAAO,wBAAwB,SAAS,WAAW,OAAO;AAC5D;;;ACzFA,SAAS,cAAAK,aAAY,aAAAC,YAAW,gBAAAC,eAAc,iBAAAC,sBAAqB;AACnE,SAAS,QAAAC,aAAY;AAuBrB,SAAS,SAAiB;AACxB,UAAO,oBAAI,KAAK,GAAE,YAAY;AAChC;AAGA,SAAS,4BAA4B,SAAgD;AACnF,QAAM,QAAQ,QAAQ,MAAM,uBAAuB;AACnD,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,cAAuC,CAAC;AAC9C,aAAW,QAAQ,MAAM,CAAC,EAAE,MAAM,IAAI,GAAG;AACvC,UAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,QAAI,QAAQ,GAAI;AAChB,UAAM,MAAM,KAAK,MAAM,GAAG,GAAG,EAAE,KAAK;AACpC,UAAM,MAAM,KAAK,MAAM,MAAM,CAAC,EAAE,KAAK;AAGrC,QAAI,QAAQ,OAAQ,aAAY,GAAG,IAAI;AAAA,aAC9B,QAAQ,OAAQ,aAAY,GAAG,IAAI;AAAA,aACnC,QAAQ,QAAS,aAAY,GAAG,IAAI;AAAA,aACpC,QAAQ,KAAK,GAAG,EAAG,aAAY,GAAG,IAAI,OAAO,SAAS,KAAK,EAAE;AAAA,QACjE,aAAY,GAAG,IAAI,IAAI,QAAQ,gBAAgB,EAAE;AAAA,EACxD;AAEA,SAAO;AACT;AAGA,SAAS,4BAA4B,IAAoC;AACvE,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,cAAc,GAAG,SAAS;AAAA,IAC1B,WAAW,GAAG,MAAM;AAAA,IACpB,WAAW,GAAG,MAAM;AAAA,IACpB,WAAW,GAAG,UAAU,IAAI;AAAA,IAC5B,cAAc,GAAG,SAAS;AAAA,IAC1B,mBAAmB,GAAG,cAAc;AAAA,IACpC,mBAAmB,GAAG,kBAAkB,IAAI;AAAA,IAC5C,iBAAiB,GAAG,YAAY;AAAA,IAChC;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGA,SAAS,qBACP,WACA,OACQ;AACR,QAAM,OAAO,OAAO,EAAE,MAAM,IAAI,EAAE;AAClC,QAAM,UAAU,UAAU,KAAK,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI;AAEtE,SAAO;AAAA,IACL;AAAA,IACA,eAAe,KAAK,WAAM,IAAI;AAAA,IAC9B,aAAa,UAAU,IAAI;AAAA,IAC3B,cAAc,OAAO;AAAA,IACrB;AAAA,IACA,UAAU;AAAA,EACZ,EAAE,KAAK,IAAI;AACb;AAQO,SAAS,mBACd,UACA,WACiE;AACjE,QAAM,WAAW,WAAW,SAAS;AACrC,QAAM,eAAe,WAAW,UAAU,YAAY,OAAO,QAAQ;AACrE,QAAM,eAAeC,MAAK,WAAW,YAAY,OAAO,QAAQ;AAChE,SAAO,EAAE,cAAc,cAAc,QAAQC,YAAW,YAAY,EAAE;AACxE;AAOO,SAAS,sBACd,WACA,MACQ;AACR,QAAM,UAAU,UAAU,KAAK,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI;AACtE,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,SAAS,UAAU,IAAI;AAAA,IACvB,SAAS,IAAI;AAAA,IACb,YAAY,UAAU,SAAS;AAAA,IAC/B,UAAU,OAAO;AAAA,IACjB,UAAU,UAAU,KAAK;AAAA,IACzB;AAAA,EACF;AACA,MAAI,UAAU,eAAe;AAC3B,UAAM,KAAK,kBAAkB,UAAU,aAAa,EAAE;AAAA,EACxD;AACA,QAAM,KAAK,OAAO,IAAI,UAAU,YAAY;AAC5C,SAAO,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA;AAC5B;AAsBO,SAAS,uBACd,UACA,WACqB;AACrB,QAAM,EAAE,cAAc,cAAc,OAAO,IAAI,mBAAmB,UAAU,UAAU,SAAS;AAC/F,QAAM,WAAW,WAAW,UAAU,SAAS;AAE/C,EAAAC,WAAUF,MAAK,cAAc,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACvD,QAAM,MAAM,OAAO;AAEnB,MAAI,CAAC,QAAQ;AAEX,UAAM,KAA6B;AAAA,MACjC,WAAW,UAAU;AAAA,MACrB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB;AAEA,UAAM,UACJ,4BAA4B,EAAE,IAC9B,OACA,qBAAqB,WAAW,CAAC,IACjC;AAEF,IAAAG,eAAc,cAAc,SAAS,MAAM;AAE3C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,gBAAgB;AAAA,IAClB;AAAA,EACF;AAGA,QAAM,kBAAkBC,cAAa,cAAc,MAAM;AACzD,QAAM,aAAa,4BAA4B,eAAe;AAE9D,MAAI,CAAC,YAAY;AAEf,UAAM,KAA6B;AAAA,MACjC,WAAW,UAAU;AAAA,MACrB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB;AAEA,IAAAD;AAAA,MACE;AAAA,MACA,4BAA4B,EAAE,IAC5B,OACA,qBAAqB,WAAW,CAAC,IACjC;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,gBAAgB;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,iBAAiB,WAAW;AAClC,QAAM,YAAY,WAAW,eAAe;AAG5C,QAAM,YACJ,WAAW,WAAW,SAAS,UAAU,WAAW;AAEtD,QAAM,YAAoC;AAAA,IACxC,GAAG;AAAA,IACH,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,cAAc;AAAA,EAChB;AAGA,QAAM,aAAa,gBAAgB,QAAQ,OAAO,CAAC;AACnD,QAAM,YAAY,cAAc,IAAI,aAAa,IAAI,gBAAgB;AAErE,QAAM,iBACJ,4BAA4B,SAAS,IACrC,OACA,gBAAgB,MAAM,SAAS;AAAA,EAC/B,qBAAqB,WAAW,SAAS;AAAA,EACzC;AAEF,EAAAA,eAAc,cAAc,gBAAgB,MAAM;AAElD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,cAAc;AAAA,IACd;AAAA,EACF;AACF;AAgBO,SAAS,wBACd,UACA,WACM;AACN,QAAM,EAAE,cAAc,OAAO,IAAI,mBAAmB,UAAU,SAAS;AACvE,MAAI,CAAC,OAAQ;AAEb,QAAM,UAAUE,cAAa,cAAc,MAAM;AACjD,QAAM,KAAK,4BAA4B,OAAO;AAC9C,MAAI,CAAC,GAAI;AAET,QAAM,YAAoC;AAAA,IACxC,GAAG;AAAA,IACH,QAAQ;AAAA,IACR,gBAAgB,OAAO;AAAA,EACzB;AAEA,QAAM,aAAa,QAAQ,QAAQ,OAAO,CAAC;AAC3C,QAAM,YAAY,cAAc,IAAI,aAAa,IAAI,QAAQ;AAE7D,EAAAC;AAAA,IACE;AAAA,IACA,4BAA4B,SAAS,IAAI,OAAO,QAAQ,MAAM,SAAS;AAAA,IACvE;AAAA,EACF;AACF;;;AR7RA,SAAS,uBAAuB,UAAkB,aAA8B;AAC9E,QAAM,OAAOC,MAAK,UAAU,WAAW;AACvC,MAAI,CAACC,YAAW,IAAI,GAAG;AACrB,WAAO;AAAA,EACT;AACA,QAAM,OAAOC,cAAa,MAAM,MAAM;AACtC,SAAO,iBAAiB,KAAK,IAAI;AACnC;AAEA,eAAsB,UACpB,UACA,KACA,OAC2C;AAC3C,MAAI,uBAAuB,UAAU,IAAI,WAAW,GAAG;AACrD,iBAAa,UAAU,IAAI,KAAK;AAChC,WAAO,EAAE,IAAI,MAAM,QAAQ,mBAAmB;AAAA,EAChD;AAEA,QAAM,MAAM,iBAAiB,QAAQ,GAAG,OAAO;AAC/C,MAAI,CAAC,eAAe,GAAG,GAAG;AACxB,WAAO,EAAE,IAAI,OAAO,QAAQ,oBAAoB;AAAA,EAClD;AAEA,MAAI,CAACD,YAAW,IAAI,SAAS,GAAG;AAC9B,WAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAAA,EAC9C;AAEA,QAAM,UAAU,eAAe,IAAI,SAAS;AAC5C,QAAM,WAAW,MAAM,UAAU,SAAS,IAAI,WAAW,GAAI;AAC7D,MAAI,CAAC,UAAU;AACb,aAAS,UAAU,MAAM,eAAe,mBAAmB,IAAI,KAAK,EAAE;AACtE,WAAO,EAAE,IAAI,OAAO,QAAQ,oBAAoB;AAAA,EAClD;AAEA,QAAM,SAASD,MAAK,UAAU,IAAI,WAAW;AAC7C,QAAM,OAAO,GAAG,MAAM;AACtB,QAAM,QAAO,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AACjD,EAAAG,eAAc,MAAM,sBAAsB,UAAU,IAAI,GAAG,MAAM;AACjE,aAAW,MAAM,MAAM;AAEvB,eAAa,UAAU,IAAI,KAAK;AAChC,WAAS,UAAU,MAAM,eAAe,gBAAgB,IAAI,WAAW,EAAE;AACzE,SAAO,EAAE,IAAI,KAAK;AACpB;AAEA,eAAsB,cACpB,UACA,OACA,OAC2C;AAC3C,QAAM,MAAM,WAAW,UAAU,KAAK;AACtC,MAAI,CAAC,KAAK;AACR,WAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAAA,EAC9C;AACA,SAAO,UAAU,UAAU,KAAK,KAAK;AACvC;AAEA,eAAsB,oBACpB,UACA,OACiB;AACjB,QAAM,OAAO,gBAAgB,QAAQ;AACrC,MAAI,OAAO;AACX,aAAW,OAAO,MAAM;AACtB,UAAM,SAAS,MAAM,UAAU,UAAU,KAAK,KAAK;AACnD,QAAI,OAAO,IAAI;AACb,cAAQ;AAAA,IACV;AAAA,EACF;AACA,SAAO;AACT;;;ASnFO,SAAS,SAAS,MAAc,QAAyB;AAC9D,UAAQ,KAAK,SAAS,OAAO,SAAS,IAAI,IAAI,CAAC;AACjD;AAEO,SAAS,oBACd,IACA,QACA,OACM;AACN,QAAM,YAAY;AAChB,QAAI;AACF,YAAM,GAAG;AACT,cAAQ,KAAK,CAAC;AAAA,IAChB,SAAS,OAAO;AACd,eAAS,UAAU,MAAM,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AACvF,cAAQ,KAAK,SAAS,IAAI,CAAC;AAAA,IAC7B;AAAA,EACF,GAAG;AACL;;;ACTO,SAAS,qBAAqB,MAAsC;AACzE,QAAM,MAAM,gBAAgB,KAAK,GAAG;AACpC,QAAM,QAAQ,KAAK,OAAO,UAAU;AACpC,wBAAsB,KAAK,YAAY,MAAM,KAAK;AAElD,sBAAoB,YAAY;AAC9B,QAAI,CAAC,KAAK;AACR,cAAQ,MAAM,8BAA8B;AAC5C;AAAA,IACF;AACA,UAAM,WAAW,IAAI;AAErB,QAAI,KAAK,OAAO;AACd,YAAM,IAAI,MAAM,oBAAoB,UAAU,KAAK;AACnD,UAAI,OAAO;AACT,gBAAQ,MAAM,wBAAwB,CAAC,aAAa;AAAA,MACtD;AACA;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,KAAK;AACb,cAAQ,MAAM,wDAAwD;AACtE;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,cAAc,UAAU,KAAK,KAAK,KAAK;AAC5D,QAAI,CAAC,OAAO,MAAM,KAAK,QAAQ;AAC7B,YAAM,IAAI,MAAM,OAAO,UAAU,oBAAoB;AAAA,IACvD;AAAA,EACF,GAAG,KAAK,QAAQ,KAAK;AACvB;;;AC1CA,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,WAAAC,gBAAe;AAcxB,SAAS,WAAW,QAAiC,MAAoC;AACvF,aAAW,OAAO,MAAM;AACtB,UAAM,IAAI,IAAI,GAAG;AACjB,QAAI,OAAO,MAAM,YAAY,EAAE,SAAS,GAAG;AACzC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBACP,QACG,MACmB;AACtB,aAAW,OAAO,MAAM;AACtB,UAAM,IAAI,IAAI,GAAG;AACjB,QAAI,MAAM,QAAQ,CAAC,GAAG;AACpB,YAAM,QAAQ,EAAE,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ;AAChE,UAAI,MAAM,SAAS,GAAG;AACpB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,2BACd,gBACA,SACS;AACT,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,EACT;AACA,QAAM,aAAa,eAAe,QAAQ,OAAO,GAAG;AACpD,SAAO,WAAW,SAAS,GAAG,OAAO,GAAG;AAC1C;AAEO,SAAS,mBAAmB,KAA+B;AAChE,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,UAAM,gBAAgB,WAAW,QAAQ,mBAAmB,gBAAgB;AAC5E,UAAM,iBACJ,iBAAiBF,YAAW,aAAa,IAAIE,SAAQ,aAAa,IAAI;AAExE,WAAO;AAAA,MACL;AAAA,MACA,mBAAmB;AAAA,MACnB,eAAe,WAAW,QAAQ,mBAAmB,eAAe;AAAA,MACpE,WAAW,WAAW,QAAQ,cAAc,WAAW;AAAA,MACvD,gBAAgB,WAAW,QAAQ,mBAAmB,gBAAgB;AAAA,MACtE,gBAAgB,gBAAgB,QAAQ,mBAAmB,gBAAgB;AAAA,MAC3E,QAAQ,WAAW,QAAQ,QAAQ;AAAA,IACrC;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,oBAAsC;AACpD,MAAI,QAAQ,MAAM,OAAO;AACvB,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,MAAMD,cAAa,GAAG,MAAM;AAClC,WAAO,mBAAmB,GAAG;AAAA,EAC/B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,uBAAuB,MAA6C;AAClF,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,SACE,2BAA2B,KAAK,gBAAgB,YAAY,KAC5D,2BAA2B,KAAK,mBAAmB,YAAY;AAEnE;AAEO,SAAS,oBAAoB,MAA6C;AAC/E,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,MAAI,uBAAuB,IAAI,GAAG;AAChC,WAAO;AAAA,EACT;AACA,MAAI,2BAA2B,KAAK,gBAAgB,SAAS,GAAG;AAC9D,WAAO;AAAA,EACT;AACA,MAAI,KAAK,gBAAgB;AACvB,WAAO;AAAA,EACT;AACA,QAAM,OAAO,KAAK,eAAe,YAAY;AAC7C,SAAO,SAAS,UAAU,CAAC,KAAK,aAAa,CAAC,KAAK;AACrD;AAEO,SAAS,oBAAoB,MAA6C;AAC/E,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,MAAI,KAAK,gBAAgB;AACvB,QACE,2BAA2B,KAAK,gBAAgB,YAAY,KAC5D,2BAA2B,KAAK,gBAAgB,SAAS,GACzD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,OAAO,KAAK,eAAe,YAAY;AAC7C,MAAI,SAAS,QAAQ;AACnB,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,KAAK,aAAa,KAAK,cAAc;AACtD;AAEO,SAAS,mBAAmB,MAA6C;AAC9E,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,QAAM,OAAO,KAAK,eAAe,YAAY;AAC7C,SAAO,SAAS;AAClB;;;ACrIA,IAAM,mBAAmB;AACzB,IAAM,mBACJ;AACF,IAAM,iBAAiB;AAShB,SAAS,kBAAkB,MAA8B;AAC9D,MAAI,iBAAiB,KAAK,IAAI,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,iBAAiB,KAAK,IAAI,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AA+BO,SAAS,mBAAmB,SAAgC;AACjE,MAAI,QAAQ;AAGZ,QAAM,WAAW,kBAAkB,QAAQ,IAAI;AAC/C,MAAI,aAAa,UAAU;AACzB,aAAS;AAAA,EACX,WAAW,aAAa,UAAU;AAChC,aAAS;AAAA,EACX,WAAW,aAAa,QAAQ;AAC9B,aAAS;AAAA,EACX;AAGA,QAAM,eAAe,KAAK,IAAI,KAAK,QAAQ,SAAS,SAAS,KAAK,CAAC;AACnE,WAAS,KAAK,IAAI,GAAG,YAAY;AAGjC,QAAM,YAAY,KAAK,IAAI,IAAI,QAAQ,YAAY,CAAC;AACpD,WAAS;AAGT,QAAM,YAAY,KAAK,IAAI,IAAI,QAAQ,cAAc,CAAC;AACtD,WAAS;AAET,SAAO,KAAK,IAAI,KAAK,KAAK;AAC5B;;;ACpFA,IAAM,yBACJ;AACF,IAAM,gBACJ;AAGF,SAAS,kBAAkB,SAAiC;AAC1D,SAAO,QAAQ,SAAS;AAAA,IACtB,CAAC,MAAM,EAAE,SAAS,UAAU,cAAc,KAAK,EAAE,IAAI;AAAA,EACvD;AACF;AAEO,SAAS,sBAAsB,MAAuB;AAC3D,SAAO,uBAAuB,KAAK,IAAI;AACzC;AAYO,SAAS,SAAS,SAAiC;AAExD,MAAI,QAAQ,SAAS,UAAU,GAAI,QAAO;AAC1C,MAAI,QAAQ,eAAe,EAAG,QAAO;AACrC,MAAI,QAAQ,aAAa,EAAG,QAAO;AAGnC,QAAM,WAAW,kBAAkB,QAAQ,IAAI;AAC/C,MAAI,aAAa,SAAU,QAAO;AAGlC,MAAI,sBAAsB,QAAQ,IAAI,EAAG,QAAO;AAGhD,MAAI,kBAAkB,OAAO,EAAG,QAAO;AAGvC,MAAI,QAAQ,SAAS,UAAU,MAAM,QAAQ,aAAa,EAAG,QAAO;AACpE,MAAI,aAAa,YAAY,QAAQ,eAAe,EAAG,QAAO;AAC9D,MAAI,QAAQ,aAAa,KAAK,QAAQ,eAAe,EAAG,QAAO;AAG/D,QAAM,QAAQ,mBAAmB,OAAO;AACxC,MAAI,SAAS,GAAI,QAAO;AAExB,SAAO;AACT;;;AC1DA,SAAS,SAAAE,cAAa;AACtB,SAAS,WAAAC,UAAS,QAAAC,cAAY;AAC9B,SAAS,iBAAAC,sBAAqB;;;ACF9B;AAAA,EACE,cAAAC;AAAA,EACA,aAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,UAAAC;AAAA,EACA,iBAAAC;AAAA,OACK;AAuBP,IAAM,cAAkC;AAAA,EACtC,SAAS;AAAA,EACT,qBAAoB,oBAAI,KAAK,CAAC,GAAE,YAAY;AAAA,EAC5C,OAAO;AAAA,IACL,wBAAwB;AAAA,IACxB,SAAS,CAAC;AAAA,IACV,uBAAuB;AAAA,EACzB;AAAA,EACA,mBAAmB,CAAC;AACtB;AAEO,SAAS,qBAAqB,UAA0B;AAC7D,SAAO,WAAW,UAAU,wBAAwB;AACtD;AAEO,SAAS,oBAAoB,UAA0B;AAC5D,SAAO,WAAW,UAAU,mBAAmB;AACjD;AAEO,SAAS,qBAAqB,UAAsC;AACzE,QAAM,OAAO,qBAAqB,QAAQ;AAC1C,MAAI,CAACC,YAAW,IAAI,GAAG;AACrB,WAAO,EAAE,GAAG,aAAa,mBAAmB,CAAC,EAAE;AAAA,EACjD;AACA,MAAI;AACF,UAAM,MAAM,KAAK,MAAMC,cAAa,MAAM,MAAM,CAAC;AAEjD,QAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,YAAM,MAAM;AACZ,UAAI,IAAI,YAAY,KAAK,OAAO,IAAI,sBAAsB,UAAU;AAClE,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,oBACE,OAAO,IAAI,uBAAuB,WAC9B,IAAI,qBACJ,YAAY;AAAA,MACpB;AAAA,IACF;AACA,WAAO,EAAE,GAAG,aAAa,mBAAmB,CAAC,EAAE;AAAA,EACjD,QAAQ;AACN,WAAO,EAAE,GAAG,aAAa,mBAAmB,CAAC,EAAE;AAAA,EACjD;AACF;AAEO,SAAS,sBACd,UACA,OACM;AACN,QAAM,OAAO,qBAAqB,QAAQ;AAC1C,EAAAC,WAAU,WAAW,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AACnD,EAAAC,eAAc,MAAM,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AACnE;AASO,SAAS,oBAAoB,UAA0C;AAC5E,QAAM,OAAO,oBAAoB,QAAQ;AACzC,MAAI,CAACH,YAAW,IAAI,GAAG;AACrB,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,KAAK,MAAMC,cAAa,MAAM,MAAM,CAAC;AAAA,EAC9C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,qBAAqB,UAAwB;AAC3D,QAAM,UAA2B;AAAA,IAC/B,KAAK,QAAQ;AAAA,IACb,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AACA,EAAAC,WAAU,WAAW,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AACnD,EAAAC;AAAA,IACE,oBAAoB,QAAQ;AAAA,IAC5B,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA;AAAA,IACnC;AAAA,EACF;AACF;AAEO,SAAS,uBAAuB,UAAwB;AAC7D,QAAM,OAAO,oBAAoB,QAAQ;AACzC,MAAIH,YAAW,IAAI,GAAG;AACpB,IAAAI,QAAO,MAAM,EAAE,OAAO,KAAK,CAAC;AAAA,EAC9B;AACF;AAEO,SAAS,YACd,MACA,OACS;AACT,QAAM,UAAU,KAAK,MAAM,KAAK,SAAS;AACzC,MAAI,OAAO,MAAM,OAAO,GAAG;AACzB,WAAO;AAAA,EACT;AACA,SAAO,KAAK,IAAI,IAAI,UAAU;AAChC;;;ACrIA,SAAS,eAAAC,cAAa,gBAAAC,qBAAoB;AAC1C,SAAS,QAAAC,aAAY;AAiBrB,SAAS,wBACP,SAC+B;AAC/B,QAAM,QAAQ,QAAQ,MAAM,uBAAuB;AACnD,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,KAA8B,CAAC;AACrC,aAAW,QAAQ,MAAM,CAAC,EAAE,MAAM,IAAI,GAAG;AACvC,UAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,QAAI,QAAQ,GAAI;AAChB,UAAM,MAAM,KAAK,MAAM,GAAG,GAAG,EAAE,KAAK;AACpC,UAAM,MAAM,KAAK,MAAM,MAAM,CAAC,EAAE,KAAK;AAErC,QAAI,QAAQ,OAAQ,IAAG,GAAG,IAAI;AAAA,aACrB,QAAQ,OAAQ,IAAG,GAAG,IAAI;AAAA,aAC1B,QAAQ,QAAS,IAAG,GAAG,IAAI;AAAA,aAC3B,QAAQ,KAAK,GAAG,EAAG,IAAG,GAAG,IAAI,OAAO,SAAS,KAAK,EAAE;AAAA,QACxD,IAAG,GAAG,IAAI,IAAI,QAAQ,gBAAgB,EAAE;AAAA,EAC/C;AAEA,SAAO;AACT;AAOO,SAAS,gBAAgB,UAAoC;AAClE,QAAM,SAAS,WAAW,UAAU,YAAY,KAAK;AACrD,MAAI;AACJ,MAAI;AACF,YAAQC,aAAY,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC;AAAA,EAC7D,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAA6B,CAAC;AACpC,aAAW,QAAQ,OAAO;AACxB,UAAM,eAAeC,MAAK,QAAQ,IAAI;AACtC,QAAI;AACF,YAAM,UAAUC,cAAa,cAAc,MAAM;AACjD,YAAM,KAAK,wBAAwB,OAAO;AAC1C,UAAI,CAAC,MAAM,CAAC,GAAG,UAAW;AAG1B,YAAM,aAAa,QAAQ,QAAQ,OAAO,CAAC;AAC3C,YAAM,YAAY,cAAc,IAAI,aAAa,IAAI,QAAQ;AAC7D,YAAM,cAAc,QAAQ,MAAM,SAAS;AAE3C,eAAS,KAAK;AAAA,QACZ,WAAW,GAAG;AAAA,QACd,UAAU;AAAA,QACV;AAAA,QACA,cAAcD,MAAK,WAAW,YAAY,OAAO,IAAI;AAAA,QACrD,aAAa;AAAA,QACb,aAAa,YAAY,KAAK;AAAA,MAChC,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,WAAS;AAAA,IACP,CAAC,GAAG,MACF,IAAI,KAAK,EAAE,YAAY,cAAc,EAAE,QAAQ,IAC/C,IAAI,KAAK,EAAE,YAAY,cAAc,EAAE,QAAQ;AAAA,EACnD;AAEA,SAAO;AACT;AAKO,SAAS,sBACd,UACkB;AAClB,SAAO,SAAS;AAAA,IACd,CAAC,MACC,EAAE,YAAY,WAAW,aACzB,EAAE,YAAY,WAAW;AAAA,EAC7B;AACF;;;ACtGA,SAAS,gBAAAE,eAAc,eAAAC,oBAAmB;AAC1C,SAAS,QAAAC,aAAY;AA8CrB,IAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4E3B,SAAS,sBAAsB,UAAuC;AAC3E,QAAM,UAA+B,CAAC;AAGtC,QAAM,WAAoE;AAAA,IACxE,EAAE,KAAK,SAAS,MAAM,OAAO;AAAA,IAC7B,EAAE,KAAK,aAAa,MAAM,WAAW;AAAA,IACrC,EAAE,KAAK,aAAa,MAAM,WAAW;AAAA,IACrC,EAAE,KAAK,aAAa,MAAM,WAAW;AAAA,EACvC;AAEA,aAAW,EAAE,KAAK,KAAK,KAAK,UAAU;AACpC,UAAM,SAAS,WAAW,UAAU,GAAG;AACvC,0BAAsB,QAAQ,KAAK,MAAM,MAAM,OAAO;AAAA,EACxD;AAGA,QAAM,aAAa,WAAW,UAAU,SAAS;AACjD,MAAI;AACF,UAAM,UAAUC,aAAY,YAAY,EAAE,eAAe,KAAK,CAAC,EAC5D,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,EAC7B,IAAI,CAAC,MAAM,EAAE,IAAI;AAEpB,eAAW,UAAU,SAAS;AAC5B,YAAM,eAAeC,MAAK,YAAY,MAAM;AAC5C;AAAA,QACE;AAAA,QACA,WAAW,MAAM;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAEA,SAAS,sBACP,aACA,gBACA,MACA,QACA,SACM;AACN,MAAI;AACJ,MAAI;AACF,YAAQD,aAAY,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC;AAAA,EAClE,QAAQ;AACN;AAAA,EACF;AAEA,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,YAAM,UAAUE,cAAaD,MAAK,aAAa,IAAI,GAAG,MAAM;AAE5D,YAAM,UAAU,QAAQ,MAAM,uBAAuB;AACrD,UAAI,QAAQ,KAAK,QAAQ,SAAS,EAAE;AACpC,UAAI,SAAS;AACX,cAAM,aAAa,QAAQ,CAAC,EAAE,MAAM,kBAAkB;AACtD,YAAI,WAAY,SAAQ,WAAW,CAAC,EAAE,QAAQ,gBAAgB,EAAE;AAAA,MAClE;AAGA,YAAM,YAAY,QAAQ,QAAQ,OAAO,CAAC;AAC1C,YAAM,OACJ,aAAa,IAAI,QAAQ,MAAM,YAAY,CAAC,EAAE,KAAK,IAAI;AACzD,YAAM,UAAU,KAAK,MAAM,GAAG,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,KAAK;AAE5D,cAAQ,KAAK;AAAA,QACX,MAAM,GAAG,cAAc,IAAI,IAAI;AAAA,QAC/B;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAIO,SAAS,yBACd,UACA,UACqB;AACrB,QAAM,kBAAyC,SAAS,IAAI,CAAC,OAAO;AAAA,IAClE,WAAW,EAAE;AAAA,IACb,QAAQ,EAAE,YAAY;AAAA,IACtB,SAASC,cAAa,EAAE,cAAc,MAAM;AAAA,IAC5C,cAAc,EAAE,YAAY;AAAA,IAC5B,WAAW,EAAE,YAAY;AAAA,EAC3B,EAAE;AAEF,QAAM,oBAAoB,sBAAsB,QAAQ;AAGxD,QAAM,gBAAgB,WAAW,UAAU,WAAW;AACtD,MAAI,kBAAiC;AACrC,MAAI;AACF,sBAAkBA,cAAa,eAAe,MAAM;AAAA,EACtD,QAAQ;AAAA,EAER;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AASA,eAAsB,mBACpBC,QACA,WACA,QAAQ,OACuB;AAC/B,MAAI,CAAC,UAAU,SAAS;AACtB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,UAAU,OAAO,KAAK,KAAK,CAAC,UAAU,QAAQ,KAAK,KAAK,CAAC,UAAU,MAAM,KAAK,GAAG;AACpF,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,GAAG,UAAU,QAAQ,QAAQ,OAAO,EAAE,CAAC;AAGnD,QAAM,cAAc,kBAAkBA,MAAK;AAC3C;AAAA,IACE;AAAA,IACA;AAAA,IACA,qBAAqB,UAAU,QAAQ,WAAW,UAAU,KAAK,aAAa,UAAU,OAAO,qBAAqBA,OAAM,gBAAgB,MAAM,uBAAuBA,OAAM,kBAAkB,MAAM,wBAAwBA,OAAM,iBAAiB,UAAU,CAAC;AAAA,EACjQ;AACA,gBAAc,OAAO,OAAO,iBAAiB,yBAAyB;AACtE,gBAAc,OAAO,OAAO,cAAc,WAAW;AAErD,QAAM,cAAc;AAAA,IAClB,OAAO,UAAU;AAAA,IACjB,iBAAiB,EAAE,MAAM,cAAc;AAAA,IACvC,UAAU;AAAA,MACR,EAAE,MAAM,UAAU,SAAS,0BAA0B;AAAA,MACrD,EAAE,MAAM,QAAQ,SAAS,YAAY;AAAA,IACvC;AAAA,IACA,aAAa;AAAA,EACf;AACA,gBAAc,OAAO,OAAO,gBAAgB,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AAEhF,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,IAAO;AAE5D,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,UAAU,MAAM;AAAA,MAC3C;AAAA,MACA,MAAM,KAAK,UAAU,WAAW;AAAA,MAChC,QAAQ,WAAW;AAAA,IACrB,CAAC;AACD,aAAS,OAAO,OAAO,oBAAoB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAEzE,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,UAAU,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC/C,oBAAc,OAAO,OAAO,uBAAuB,OAAO;AAC1D,YAAM,IAAI;AAAA,QACR,yBAAe,IAAI,MAAM,MAAM,QAAQ,MAAM,GAAG,GAAG,CAAC;AAAA,MACtD;AAAA,IACF;AAEA,UAAM,OAAQ,MAAM,IAAI,KAAK;AAG7B,kBAAc,OAAO,OAAO,iBAAiB,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAC1E,UAAM,aAAa,KAAK,UAAU,CAAC,GAAG,SAAS;AAE/C,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,0CAAY;AAAA,IAC9B;AACA,kBAAc,OAAO,OAAO,uBAAuB,UAAU;AAG7D,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,UAAU;AAAA,IAChC,QAAQ;AACN,YAAM,IAAI,MAAM,2DAAmB;AAAA,IACrC;AACA,kBAAc,OAAO,OAAO,kBAAkB,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAE7E,UAAM,aAAa,8BAA8B,MAAM;AACvD;AAAA,MACE;AAAA,MACA;AAAA,MACA,8BAA8B,WAAW,eAAe,MAAM,iBAAiB,WAAW,SAAS,MAAM,qBAAqB,WAAW,gBAAgB,MAAM;AAAA,IACjK;AACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,UAAU,WAAW,gBAAgB,MAAM,CAAC;AAAA,IACnD;AACA,kBAAc,OAAO,OAAO,uBAAuB,WAAW,QAAQ;AACtE;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,UAAU,WAAW,iBAAiB,MAAM,CAAC;AAAA,IACpD;AAEA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ;AAAA,MACE;AAAA,MACA;AAAA,MACA,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC5D;AACA,UAAM;AAAA,EACR,UAAE;AACA,iBAAa,OAAO;AAAA,EACtB;AACF;AAIA,SAAS,kBAAkBA,QAAoC;AAE7D,QAAM,kBAAkB;AACxB,QAAM,oBAAoBA,OAAM,gBAAgB,IAAI,CAAC,OAAO;AAAA,IAC1D,GAAG;AAAA,IACH,SACE,EAAE,QAAQ,SAAS,kBACf,EAAE,QAAQ,MAAM,GAAG,eAAe,IAClC;AAAA;AAAA,mDAAqB,EAAE,QAAQ,MAAM,mBACrC,EAAE;AAAA,EACV,EAAE;AAEF,SAAO,KAAK;AAAA,IACV;AAAA,MACE,iBAAiB;AAAA,MACjB,mBAAmBA,OAAM,kBAAkB,IAAI,CAAC,OAAO;AAAA,QACrD,MAAM,EAAE;AAAA,QACR,OAAO,EAAE;AAAA,QACT,MAAM,EAAE;AAAA,QACR,QAAQ,EAAE;AAAA,QACV,QAAQ,EAAE;AAAA,QACV,SAAS,EAAE;AAAA,MACb,EAAE;AAAA,MACF,iBAAiBA,OAAM,mBAAmB;AAAA,IAC5C;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAIA,SAAS,8BACP,KACsB;AACtB,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,UAAM,IAAI,MAAM,8EAAuB;AAAA,EACzC;AAEA,QAAM,MAAM;AAEZ,QAAM,iBAAwC,MAAM,QAAQ,IAAI,cAAc,IACzE,IAAI,eAA6B,IAAI,sBAAsB,EAAE,OAAO,OAAO,IAC5E,CAAC;AAEL,QAAM,WACJ,OAAO,IAAI,aAAa,WACpB,IAAI,WACJ;AAEN,QAAM,kBAAgE,MAAM;AAAA,IAC1E,IAAI;AAAA,EACN,IACK,IAAI,gBAA8B,OAAO,cAAc,IACxD,CAAC;AAEL,SAAO,EAAE,gBAAgB,UAAU,gBAAgB;AACrD;AAEA,SAAS,uBAAuB,KAA0C;AACxE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,MAAM;AAEZ,MACE,OAAO,IAAI,eAAe,YAC1B,CAAC,CAAC,UAAU,QAAQ,EAAE,SAAS,IAAI,MAAgB,KACnD,OAAO,IAAI,SAAS,UACpB;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,YAAY,IAAI;AAAA,IAChB,QAAQ,IAAI;AAAA,IACZ,aACE,OAAO,IAAI,gBAAgB,YAAY,IAAI,gBAAgB,OACtD,IAAI,cACL,CAAC;AAAA,IACP,MAAM,IAAI;AAAA,EACZ;AACF;AAEA,SAAS,eAAe,KAA4D;AAClF,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,MAAM;AACZ,SACE,OAAO,IAAI,cAAc,YAAY,OAAO,IAAI,WAAW;AAE/D;;;ACrcA,SAAS,cAAAC,aAAY,aAAAC,YAAW,gBAAAC,gBAAc,iBAAAC,sBAAqB;AACnE,SAAS,WAAAC,gBAAqB;AAY9B,IAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAYO,SAAS,oBACd,UACA,OACsB;AACtB,QAAM,SAA+B;AAAA,IACnC,SAAS,CAAC;AAAA,IACV,SAAS,CAAC;AAAA,IACV,QAAQ,CAAC;AAAA,EACX;AAEA,aAAW,MAAM,OAAO;AACtB,QAAI;AACF,YAAM,eAAe,WAAW,UAAU,GAAG,UAAU;AACvD,YAAM,MAAMC,SAAQ,YAAY;AAEhC,MAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAGlC,YAAM,UAAU,uBAAuB,GAAG,aAAa,GAAG,IAAI;AAE9D,YAAM,gBAAgBC,YAAW,YAAY;AAE7C,UAAI,GAAG,WAAW,YAAY,eAAe;AAE3C,eAAO,QAAQ,KAAK,GAAG,UAAU;AAAA,MACnC,WAAW,GAAG,WAAW,UAAU;AACjC,eAAO,QAAQ,KAAK,GAAG,UAAU;AAAA,MACnC,OAAO;AACL,eAAO,QAAQ,KAAK,GAAG,UAAU;AAAA,MACnC;AAEA,MAAAC,eAAc,cAAc,SAAS,MAAM;AAAA,IAC7C,SAAS,KAAK;AACZ,aAAO,OAAO,KAAK,GAAG,UAAU;AAChC,cAAQ;AAAA,QACN,mEAA2B,GAAG,UAAU,KAAM,IAAc,OAAO;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAQO,SAAS,cACd,UACA,UACM;AACN,QAAM,gBAAgB,WAAW,UAAU,WAAW;AAGtD,MAAID,YAAW,aAAa,GAAG;AAC7B,UAAM,WAAWE,eAAa,eAAe,MAAM;AACnD,UAAM,YAAY,0BAA0B,QAAQ;AACpD,QAAI,UAAU,SAAS,GAAG;AACxB,iBAAW,mBAAmB,UAAU,SAAS;AAAA,IACnD;AAAA,EACF;AAEA,EAAAH,WAAU,WAAW,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AACnD,EAAAE,eAAc,eAAe,GAAG,QAAQ;AAAA,GAAM,MAAM;AACtD;AAEO,SAAS,gCACd,UACA,UACM;AACN,QAAM,UAAU,0BAA0B,UAAU,QAAQ;AAC5D,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,IAAI;AAAA,MACR,iFAA0B,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC9C;AAAA,EACF;AACF;AAEA,SAAS,0BAA0B,UAAkB,UAA4B;AAC/E,QAAM,QAAQ,sBAAsB,QAAQ;AAC5C,SAAO,MAAM,OAAO,CAAC,SAAS,CAACD,YAAW,WAAW,UAAU,IAAI,CAAC,CAAC;AACvE;AAEA,SAAS,sBAAsB,UAA4B;AACzD,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,eAAe;AACrB,MAAI;AAEJ,UAAQ,QAAQ,aAAa,KAAK,QAAQ,OAAO,MAAM;AACrD,UAAM,aAAa,uBAAuB,MAAM,CAAC,CAAC;AAClD,QAAI,YAAY;AACd,YAAM,IAAI,UAAU;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,CAAC,GAAG,KAAK;AAClB;AAEA,SAAS,uBAAuB,SAAgC;AAC9D,QAAM,gBAAgB,QAAQ,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK;AACjD,QAAM,kBAAkB,cAAc,WAAW,IAAI,IACjD,cAAc,MAAM,CAAC,IACrB;AAEJ,MACE,gBAAgB,SAAS,KAAK,KAC9B,gBAAgB,WAAW,GAAG,KAC9B,gBAAgB,SAAS,IAAI,KAC7B,CAAC,gBAAgB,SAAS,KAAK,GAC/B;AACA,WAAO;AAAA,EACT;AAEA,SAAO,wBAAwB,KAAK,CAAC,WAAW,gBAAgB,WAAW,MAAM,CAAC,IAC9E,kBACA;AACN;AAIA,SAAS,uBACP,aACA,MACQ;AACR,QAAM,QAAQ,CAAC,KAAK;AAGpB,QAAM,aAAa,CAAC,SAAS,UAAU,QAAQ,UAAU,cAAc,cAAc;AACrF,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,OAAO,YAAY;AAC5B,QAAI,OAAO,eAAe,YAAY,GAAG,MAAM,UAAa,YAAY,GAAG,MAAM,MAAM;AACrF,YAAM,KAAK,GAAG,GAAG,KAAK,gBAAgB,YAAY,GAAG,CAAC,CAAC,EAAE;AACzD,cAAQ,IAAI,GAAG;AAAA,IACjB;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,YAAY,cAAc,GAAG;AAC7C,UAAM,KAAK,iBAAiB;AAC5B,eAAW,KAAK,YAAY,gBAAgB;AAC1C,YAAM,KAAK,OAAO,CAAC,EAAE;AAAA,IACvB;AACA,YAAQ,IAAI,gBAAgB;AAAA,EAC9B;AAGA,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,WAAW,GAAG;AACpD,QAAI,CAAC,QAAQ,IAAI,GAAG,KAAK,QAAQ,UAAa,QAAQ,MAAM;AAC1D,YAAM,KAAK,GAAG,GAAG,KAAK,gBAAgB,GAAG,CAAC,EAAE;AAAA,IAC9C;AAAA,EACF;AAEA,QAAM,KAAK,OAAO,IAAI,IAAI;AAE1B,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,gBAAgB,KAAsB;AAC7C,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,WAAO,IAAI,IAAI,IAAI,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,EACvC;AACA,SAAO,OAAO,GAAG;AACnB;AAUA,SAAS,0BAA0B,SAAgC;AACjE,QAAM,WAA0B,CAAC;AACjC,QAAM,QAAQ;AACd,MAAI;AACJ,UAAQ,QAAQ,MAAM,KAAK,OAAO,OAAO,MAAM;AAC7C,aAAS,KAAK;AAAA,MACZ,QAAQ,MAAM,CAAC,EAAE,MAAM,IAAI,EAAE,CAAC;AAAA;AAAA,MAC9B,SAAS,MAAM,CAAC;AAAA,IAClB,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAGA,SAAS,mBACP,YACA,UACQ;AACR,MAAI,SAAS;AACb,aAAW,WAAW,UAAU;AAE9B,UAAM,cAAc,QAAQ;AAC5B,UAAM,YAAY;AAElB,UAAM,WAAW,OAAO,QAAQ,WAAW;AAC3C,QAAI,aAAa,GAAI;AAErB,UAAM,SAAS,OAAO,QAAQ,WAAW,QAAQ;AACjD,QAAI,WAAW,GAAI;AAEnB,aACE,OAAO,MAAM,GAAG,QAAQ,IACxB,GAAG,WAAW;AAAA,EAAK,QAAQ,OAAO;AAAA,EAAK,SAAS,KAChD,OAAO,MAAM,SAAS,UAAU,MAAM;AAAA,EAC1C;AACA,SAAO;AACT;;;AClPA,SAAqB,aAAAG,YAAW,cAAAC,mBAAgC;AAChE,SAAS,QAAAC,cAAY;AAYd,SAAS,oBACd,UACA,UACA,kBAA0B,IAClB;AACR,QAAM,cAAc,WAAW,UAAU,YAAY,UAAU;AAC/D,QAAM,WAAW,KAAK,IAAI,IAAI,kBAAkB,KAAK,KAAK,KAAK;AAE/D,MAAI,gBAAgB;AAEpB,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,YAAY,WAAW,OAAQ;AACrC,QAAI,CAAC,EAAE,YAAY,eAAgB;AAEnC,UAAM,mBAAmB,KAAK,MAAM,EAAE,YAAY,cAAc;AAChE,QAAI,OAAO,MAAM,gBAAgB,EAAG;AACpC,QAAI,mBAAmB,SAAU;AAEjC,QAAI;AACF,MAAAC,WAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAC1C,MAAAC,YAAW,EAAE,cAAcC,OAAK,aAAa,EAAE,QAAQ,CAAC;AACxD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AACT;;;ACYA,eAAsB,eACpB,MAC8B;AAC9B,QAAM,EAAE,UAAU,QAAQ,OAAO,QAAQ,MAAM,IAAI;AAEnD;AAAA,IACE,UAAU;AAAA,IACV;AAAA,IACA,gBAAgB,UAAU,IAAI,YAAY,WAAW,IAAI;AAAA,EAC3D;AACA,uBAAqB,QAAQ;AAC7B,WAAS,UAAU,MAAM,eAAe,eAAe;AACvD,MAAI;AACF,UAAM,YAAyB,OAAO;AAEtC,QAAI,CAAC,UAAU,SAAS;AACtB,eAAS,UAAU,MAAM,eAAe,uBAAuB;AAC/D,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,mBAAmB;AAAA,QACnB,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,cAAc;AAAA,QACd,UAAU;AAAA,MACZ;AAAA,IACF;AAGA,UAAM,cAAc,gBAAgB,QAAQ;AAC5C,UAAM,kBAAkB,QACpB,cACA,sBAAsB,WAAW;AAErC;AAAA,MACE,UAAU;AAAA,MACV;AAAA,MACA,sBAAO,YAAY,MAAM,qCAAiB,gBAAgB,MAAM;AAAA,IAClE;AAEA,QAAI,gBAAgB,WAAW,KAAK,CAAC,OAAO;AAC1C,eAAS,UAAU,MAAM,eAAe,2BAA2B;AACnE,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,mBAAmB;AAAA,QACnB,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,cAAc;AAAA,QACd,UAAU;AAAA,MACZ;AAAA,IACF;AAGA,QAAI,QAAQ;AACV;AAAA,QACE,UAAU;AAAA,QACV;AAAA,QACA,0BAA0B,gBAAgB,MAAM;AAAA,MAClD;AACA,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,mBAAmB,gBAAgB;AAAA,QACnC,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,cAAc;AAAA,QACd,UAAU;AAAA,MACZ;AAAA,IACF;AAGA,UAAM,WAAW,yBAAyB,UAAU,eAAe;AACnE;AAAA,MACE,UAAU;AAAA,MACV;AAAA,MACA,qBAAW,SAAS,gBAAgB,MAAM,cAAc,SAAS,kBAAkB,MAAM;AAAA,IAC3F;AAGA,QAAI;AACJ,QAAI;AACF,kBAAY,MAAM,mBAAmB,UAAU,WAAW,UAAU,IAAI;AAAA,IAC1E,SAAS,KAAK;AACZ,cAAQ,MAAM,+CAA4B,IAAc,OAAO,EAAE;AACjE,YAAM;AAAA,IACR;AAEA;AAAA,MACE,UAAU;AAAA,MACV;AAAA,MACA,qBAAW,UAAU,eAAe,MAAM,qBAAqB,UAAU,gBAAgB,MAAM;AAAA,IACjG;AAGA,aAAS,UAAU,MAAM,eAAe,yBAAyB;AACjE,UAAM,cAAc,oBAAoB,UAAU,UAAU,cAAc;AAC1E,QAAI,YAAY,OAAO,SAAS,GAAG;AACjC;AAAA,QACE,UAAU;AAAA,QACV;AAAA,QACA,iBAAiB,YAAY,OAAO,KAAK,IAAI,CAAC;AAAA,MAChD;AACA,YAAM,IAAI;AAAA,QACR,qDAAa,YAAY,OAAO,KAAK,IAAI,CAAC;AAAA,MAC5C;AAAA,IACF;AACA;AAAA,MACE,UAAU;AAAA,MACV;AAAA,MACA,oCAAoC,YAAY,QAAQ,MAAM,aAAa,YAAY,QAAQ,MAAM;AAAA,IACvG;AAEA,aAAS,UAAU,MAAM,eAAe,4BAA4B;AACpE,oCAAgC,UAAU,UAAU,QAAQ;AAC5D,aAAS,UAAU,MAAM,eAAe,oBAAoB;AAC5D,aAAS,UAAU,MAAM,eAAe,mBAAmB;AAC3D,kBAAc,UAAU,UAAU,QAAQ;AAG1C;AAAA,MACE,UAAU;AAAA,MACV;AAAA,MACA,0BAA0B,gBAAgB,MAAM,eAAe,UAAU,gBAAgB,MAAM;AAAA,IACjG;AACA,UAAM,sBAAsB,oBAAI,IAAY;AAC5C,eAAW,KAAK,iBAAiB;AAC/B,8BAAwB,UAAU,EAAE,SAAS;AAC7C,0BAAoB,IAAI,EAAE,SAAS;AAAA,IACrC;AAEA,eAAW,MAAM,UAAU,iBAAiB;AAC1C,8BAAwB,UAAU,GAAG,SAAS;AAC9C,0BAAoB,IAAI,GAAG,SAAS;AAAA,IACtC;AAGA,UAAM,YAAY,qBAAqB,QAAQ;AAC/C,UAAM,aAAa,0BAA0B,UAAU,cAAc;AAErE,aAAS,UAAU,MAAM,eAAe,4BAA4B;AACpE,0BAAsB,UAAU;AAAA,MAC9B,SAAS;AAAA,MACT,qBAAoB,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC3C,OAAO;AAAA,QACL,wBACE,UAAU,MAAM,yBAChB,gBAAgB,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,YAAY,cAAc,CAAC;AAAA,QACxE,SAAS,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,UAAU,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC;AAAA,QACjE,uBACE,UAAU,MAAM,wBAChB,YAAY,QAAQ;AAAA,MACxB;AAAA,MACA,mBAAmB;AAAA,QACjB,GAAG,UAAU;AAAA,QACb,GAAG,OAAO;AAAA,UACR,CAAC,GAAG,mBAAmB,EAAE,IAAI,CAAC,OAAO;AAAA,YACnC;AAAA,YACA,EAAE,QAAQ,QAAiB,iBAAgB,oBAAI,KAAK,GAAE,YAAY,GAAG,gBAAe,oBAAI,KAAK,GAAE,YAAY,EAAE;AAAA,UAC/G,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,WAAW;AAAA,MACf;AAAA,MACA;AAAA,MACA,OAAO,YAAY;AAAA,IACrB;AACA,aAAS,UAAU,MAAM,eAAe,sBAAsB,QAAQ,EAAE;AAExE;AAAA,MACE,UAAU;AAAA,MACV;AAAA,MACA,kBAAkB,gBAAgB,MAAM,aAAa,YAAY,QAAQ,MAAM,aAAa,YAAY,QAAQ,MAAM,aAAa,UAAU,gBAAgB,MAAM,cAAc,QAAQ;AAAA,IAC3L;AAEA,WAAO;AAAA,MACL,KAAK;AAAA,MACL,mBAAmB,gBAAgB;AAAA,MACnC,kBAAkB,YAAY,QAAQ;AAAA,MACtC,kBAAkB,YAAY,QAAQ;AAAA,MACtC,cAAc,UAAU,gBAAgB;AAAA,MACxC;AAAA,IACF;AAAA,EACF,UAAE;AACA,2BAAuB,QAAQ;AAC/B,aAAS,UAAU,MAAM,eAAe,eAAe;AAAA,EACzD;AACF;AAKA,SAAS,0BACP,OACU;AACV,QAAM,UAAU,oBAAI,IAAY;AAChC,aAAW,KAAK,OAAO;AACrB,UAAM,SAAS,EAAE,YAAY;AAC7B,QAAI,OAAO,WAAW,YAAY,UAAU,WAAW,QAAQ;AAC7D,cAAQ,IAAI,MAAM;AAAA,IACpB;AAAA,EACF;AACA,SAAO,CAAC,GAAG,OAAO;AACpB;;;AClQO,IAAM,0BAA0B,KAAK,KAAK;;;APsBjD,SAASC,WAAkB;AACzB,SAAOC,OAAKC,SAAQC,eAAc,YAAY,GAAG,CAAC,GAAG,MAAM,QAAQ;AACrE;AAMA,eAAsB,gBAAgB,MAKL;AAC/B,QAAM,MAAM,gBAAgB,KAAK,GAAG;AACpC,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,MACL,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,cAAc;AAAA,MACd,UAAU;AAAA,IACZ;AAAA,EACF;AAGA,QAAM,cAAc,gBAAgB,IAAI,QAAQ;AAChD,QAAM,kBAAkB,KAAK,QACzB,cACA,sBAAsB,WAAW;AAErC,MAAI,gBAAgB,WAAW,KAAK,CAAC,KAAK,SAAS,CAAC,KAAK,QAAQ;AAC/D,WAAO;AAAA,MACL,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,mBAAmB;AAAA,MACnB,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,cAAc;AAAA,MACd,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO,eAAe;AAAA,IACpB,UAAU,IAAI;AAAA,IACd,QAAQ,IAAI;AAAA,IACZ,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK,SAAS,IAAI,OAAO;AAAA,EAClC,CAAC;AACH;AAEO,SAAS,gBACd,UACA,aACA,oBACS;AACT,QAAM,YAAY,YAAY;AAC9B,MAAI,CAAC,UAAU,WAAW,SAAS,WAAW,GAAG;AAC/C,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,UAAU,UAAU,oBAAoB;AACnD,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,SAAS;AAAA,IAC5B,CAAC,KAAK,YAAY,MAAM,QAAQ,YAAY;AAAA,IAC5C;AAAA,EACF;AACA,MAAI,gBAAgB,UAAU,iBAAiB;AAC7C,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,KAAK,MAAM,kBAAkB;AAC1C,MAAI,OAAO,MAAM,IAAI,GAAG;AACtB,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,UAAU,qBAAqB,KAAK;AAC1D,SAAO,KAAK,IAAI,IAAI,QAAQ;AAC9B;AAKO,SAAS,yBAAyB,MAGhC;AACP,QAAM,MAAM,gBAAgB,KAAK,QAAQ;AACzC,MAAI,CAAC,KAAK;AACR;AAAA,EACF;AAEA,QAAM,YAAY,IAAI,OAAO,YAAY;AACzC,MAAI,CAAC,UAAU,SAAS;AACtB;AAAA,EACF;AAEA,MAAI,CAAC,eAAe,IAAI,OAAO,GAAG,GAAG;AACnC,aAAS,KAAK,UAAU,MAAM,eAAe,uCAAuC;AACpF;AAAA,EACF;AAEA,QAAM,OAAO,oBAAoB,KAAK,QAAQ;AAC9C,MAAI,QAAQ,CAAC,YAAY,MAAM,uBAAuB,GAAG;AACvD,aAAS,KAAK,UAAU,MAAM,eAAe,+BAA+B;AAC5E;AAAA,EACF;AAEA,QAAM,kBAAkB,sBAAsB,gBAAgB,KAAK,QAAQ,CAAC;AAC5E,QAAM,QAAQ,qBAAqB,KAAK,QAAQ;AAChD,MACE,CAAC;AAAA,IACC;AAAA,IACA,IAAI,OAAO;AAAA,IACX,MAAM;AAAA,EACR,GACA;AACA;AAAA,MACE,KAAK,UAAU;AAAA,MACf;AAAA,MACA,uBAAuB,gBAAgB,MAAM;AAAA,IAC/C;AACA;AAAA,EACF;AAEA,MAAI;AACF,UAAM,QAAQC;AAAA,MACZ,QAAQ;AAAA,MACR,CAACJ,SAAQ,GAAG,SAAS,MAAM,KAAK,QAAQ;AAAA,MACxC;AAAA,QACE,UAAU;AAAA,QACV,OAAO;AAAA,QACP,KAAK,KAAK;AAAA,MACZ;AAAA,IACF;AACA,UAAM,MAAM;AACZ;AAAA,MACE,KAAK,UAAU;AAAA,MACf;AAAA,MACA,yBAAyB,gBAAgB,MAAM;AAAA,IACjD;AAAA,EACF,SAAS,KAAK;AACZ;AAAA,MACE,KAAK,UAAU;AAAA,MACf;AAAA,MACA,4BAA4B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC9E;AAAA,EACF;AACF;;;AQlKA,SAAS,cACP,UACA,OACA,QACe;AACf,MAAI,OAAO,SAAS;AAClB,6BAAyB,EAAE,UAAU,MAAM,CAAC;AAAA,EAC9C;AACA,SAAO;AACT;AAWA,eAAsB,cACpB,MACwB;AACxB,QAAM,EAAE,UAAU,SAAS,WAAW,WAAW,QAAQ,MAAM,IAAI;AACnE,QAAM,YAAY,aAAa,SAAS,SAAS;AAEjD,MAAI,QAAQ;AACV;AAAA,MACE,UAAU;AAAA,MACV;AAAA,MACA,mCAAmC,QAAQ,SAAS,SAAS,SAAS;AAAA,IACxE;AACA,WAAO,EAAE,SAAS,OAAO,QAAQ,WAAW,UAAU;AAAA,EACxD;AAGA,QAAM,SAAS,uBAAuB,UAAU,SAAS;AACzD,QAAM,cAAc,OAAO;AAI3B,QAAM,MAAM,iBAAiB,QAAQ,GAAG,OAAO;AAC/C,MAAI,CAAC,eAAe,GAAG,KAAK,CAAC,SAAS,OAAO,GAAG;AAC9C,aAAS,UAAU,MAAM,WAAW,OAAO,WAAW,kBAAkB;AACxE,WAAO,cAAc,UAAU,OAAO;AAAA,MACpC,SAAS;AAAA,MACT,aAAa;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,iBAAiB,GAAI;AAClC,MAAI,SAAS,QAAQ;AACnB,UAAM,WAAW,MAAM,UAAU,SAAS,WAAW,GAAI;AACzD,QAAI,UAAU;AAGZ,eAAS,UAAU,MAAM,WAAW,OAAO,WAAW,oBAAoB;AAC1E,aAAO,cAAc,UAAU,OAAO;AAAA,QACpC,SAAS;AAAA,QACT,aAAa;AAAA,QACb;AAAA,MACF,CAAC;AAAA,IACH;AACA,aAAS,UAAU,MAAM,WAAW,OAAO,WAAW,gCAAgC;AACtF,WAAO,cAAc,UAAU,OAAO;AAAA,MACpC,SAAS;AAAA,MACT,aAAa;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,cAAc;AAAA,IAC7B;AAAA,IACA,WAAW,QAAQ;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,UAAU;AACZ,aAAS,UAAU,MAAM,WAAW,OAAO,WAAW,gCAAgC;AAAA,EACxF,OAAO;AACL,aAAS,UAAU,MAAM,WAAW,OAAO,WAAW,oCAAoC;AAAA,EAC5F;AAEA,SAAO,cAAc,UAAU,OAAO;AAAA,IACpC,SAAS;AAAA,IACT,aAAa;AAAA,IACb;AAAA,EACF,CAAC;AACH;;;ACzGA,SAAS,cAAAK,aAAY,eAAAC,cAAa,gBAAAC,gBAAc,gBAAgB;AAChE,SAAS,eAAe;AACxB,SAAS,YAAAC,WAAU,QAAAC,QAAM,WAAAC,gBAAe;AAGjC,SAAS,uBAAuB,SAAyB;AAC9D,SAAOA,SAAQ,OAAO,EAAE,QAAQ,OAAO,GAAG;AAC5C;AAkBO,SAAS,wBACd,UACA,UAAiC,CAAC,GACnB;AACf,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,YAAYL,YAAW,QAAQ,GAAG;AACpC,WAAOK,SAAQ,QAAQ;AAAA,EACzB;AAEA,QAAM,WAAW,QAAQ;AACzB,MAAI,YAAYL,YAAW,QAAQ,GAAG;AACpC,WAAOK,SAAQ,QAAQ;AAAA,EACzB;AAEA,QAAM,YACJ,QAAQ,IAAI,qBACZ,QAAQ,IAAI,0BACZ,QAAQ,IAAI;AAEd,QAAM,aAAa,QAAQ,IAAI,oBAC3BA,SAAQ,QAAQ,IAAI,iBAAiB,IACrCD,OAAK,QAAQ,GAAG,SAAS;AAC7B,QAAM,eAAeA,OAAK,YAAY,UAAU;AAChD,MAAI,CAACJ,YAAW,YAAY,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,QAAM,MAAMK,SAAQ,QAAQ,OAAO,QAAQ;AAC3C,QAAM,sBAAsB,uBAAuB,GAAG;AACtD,QAAM,gBAAgBD,OAAK,cAAc,mBAAmB;AAC5D,MAAIJ,YAAW,aAAa,GAAG;AAC7B,UAAM,MAAM,gBAAgB,eAAe,SAAS;AACpD,QAAI,KAAK;AACP,aAAO;AAAA,IACT;AACA,UAAM,iBAAiBI,OAAK,eAAe,UAAU;AACrD,QAAIJ,YAAW,cAAc,GAAG;AAC9B,YAAM,YAAY,gBAAgB,gBAAgB,SAAS;AAC3D,UAAI,WAAW;AACb,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAqD,CAAC;AAE5D,aAAW,cAAcC,aAAY,cAAc,EAAE,eAAe,KAAK,CAAC,GAAG;AAC3E,QAAI,CAAC,WAAW,YAAY,EAAG;AAC/B,UAAM,cAAcG,OAAK,cAAc,WAAW,IAAI;AACtD,2BAAuB,aAAa,WAAW,UAAU;AACzD,UAAM,iBAAiBA,OAAK,aAAa,UAAU;AACnD,QAAIJ,YAAW,cAAc,GAAG;AAC9B,6BAAuB,gBAAgB,WAAW,UAAU;AAAA,IAC9D;AAAA,EACF;AAEA,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,aAAW,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC3C,SAAO,WAAW,CAAC,GAAG,QAAQ;AAChC;AAuBA,SAAS,gBACP,KACA,WACe;AACf,QAAM,aAAqD,CAAC;AAC5D,yBAAuB,KAAK,WAAW,UAAU;AACjD,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,aAAW,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC3C,SAAO,WAAW,CAAC,GAAG,QAAQ;AAChC;AAEA,SAAS,uBACP,KACA,WACA,KACM;AACN,MAAI,CAACM,YAAW,GAAG,GAAG;AACpB;AAAA,EACF;AACA,aAAW,SAASC,aAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC7D,QAAI,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,QAAQ,GAAG;AACrD;AAAA,IACF;AACA,UAAM,WAAWC,OAAK,KAAK,MAAM,IAAI;AACrC,QACE,aACA,CAAC,MAAM,KAAK,SAAS,SAAS,KAC9BC,UAAS,MAAM,MAAM,QAAQ,MAAM,WACnC;AACA;AAAA,IACF;AACA,QAAI;AACF,YAAM,KAAK,SAAS,QAAQ;AAC5B,UAAI,KAAK,EAAE,MAAM,UAAU,OAAO,GAAG,QAAQ,CAAC;AAAA,IAChD,QAAQ;AAAA,IAER;AAAA,EACF;AACF;;;ACjJA,eAAsB,qBACpB,UACA,KACA,QACA,SACwB;AACxB,QAAM,YAAY,wBAAwB,UAAU;AAAA,IAClD;AAAA,IACA,gBAAgB,SAAS;AAAA,EAC3B,CAAC;AACD,MAAI,CAAC,WAAW;AACd,WAAO,EAAE,SAAS,OAAO,QAAQ,yBAAyB;AAAA,EAC5D;AAGA,QAAM,UAAU,eAAe,SAAS;AAExC,SAAO,cAAc;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,OAAO,SAAS;AAAA,EAClB,CAAC;AACH;;;AC9BA,SAAS,cAAAC,cAAY,eAAAC,cAAa,YAAAC,iBAAgB;AAClD,SAAS,WAAAC,gBAAe;AACxB,SAAS,YAAAC,WAAU,QAAAC,QAAM,WAAAC,gBAAe;AAMjC,SAAS,0BAA0B,SAAyB;AACjE,SAAOA,SAAQ,OAAO,EAAE,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,GAAG;AAC/D;AAgBO,SAAS,6BACd,SACe;AACf,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,YAAYN,aAAW,QAAQ,GAAG;AACpC,WAAOM,SAAQ,QAAQ;AAAA,EACzB;AAEA,QAAM,WAAW,QAAQ;AACzB,MAAI,YAAYN,aAAW,QAAQ,GAAG;AACpC,WAAOM,SAAQ,QAAQ;AAAA,EACzB;AAEA,QAAM,YACJ,QAAQ,IAAI,wBAAwB,QAAQ,IAAI;AAElD,QAAM,gBAAgB,QAAQ,IAAI,uBAC9BA,SAAQ,QAAQ,IAAI,oBAAoB,IACxCD,OAAKF,SAAQ,GAAG,YAAY;AAChC,QAAM,eAAeE,OAAK,eAAe,UAAU;AACnD,MAAI,CAACL,aAAW,YAAY,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,QAAM,MAAMM,SAAQ,QAAQ,OAAO,QAAQ,QAAQ;AACnD,QAAM,sBAAsB,0BAA0B,GAAG;AACzD,QAAM,gBAAgBD,OAAK,cAAc,mBAAmB;AAC5D,MAAIL,aAAW,aAAa,GAAG;AAC7B,UAAM,MAAM,yBAAyB,eAAe,SAAS;AAC7D,QAAI,KAAK;AACP,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,aAAqD,CAAC;AAC5D,aAAW,cAAcC,aAAY,cAAc,EAAE,eAAe,KAAK,CAAC,GAAG;AAC3E,QAAI,CAAC,WAAW,YAAY,GAAG;AAC7B;AAAA,IACF;AACA,0BAAsBI,OAAK,cAAc,WAAW,IAAI,GAAG,WAAW,UAAU;AAAA,EAClF;AAEA,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,aAAW,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC3C,SAAO,WAAW,CAAC,GAAG,QAAQ;AAChC;AAEA,SAAS,yBACP,KACA,WACe;AACf,QAAM,aAAqD,CAAC;AAC5D,wBAAsB,KAAK,WAAW,UAAU;AAChD,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,aAAW,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC3C,SAAO,WAAW,CAAC,GAAG,QAAQ;AAChC;AAEA,SAAS,sBACP,KACA,WACA,KACM;AACN,MAAI,CAACL,aAAW,GAAG,GAAG;AACpB;AAAA,EACF;AACA,aAAW,SAASC,aAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC7D,UAAM,OAAOI,OAAK,KAAK,MAAM,IAAI;AACjC,QAAI,MAAM,YAAY,GAAG;AACvB,4BAAsB,MAAM,WAAW,GAAG;AAC1C;AAAA,IACF;AACA,QAAI,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,QAAQ,GAAG;AACrD;AAAA,IACF;AACA,QACE,aACA,CAAC,MAAM,KAAK,SAAS,SAAS,KAC9BD,UAAS,MAAM,MAAM,QAAQ,MAAM,WACnC;AACA;AAAA,IACF;AACA,QAAI;AACF,YAAM,KAAKF,UAAS,IAAI;AACxB,UAAI,KAAK,EAAE,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC;AAAA,IAC5C,QAAQ;AAAA,IAER;AAAA,EACF;AACF;;;AClHA,eAAsB,oBACpB,UACA,KACA,QACA,SACwB;AACxB,QAAM,YAAY,6BAA6B;AAAA,IAC7C;AAAA,IACA;AAAA,IACA,gBAAgB,SAAS;AAAA,EAC3B,CAAC;AACD,MAAI,CAAC,WAAW;AACd,WAAO,EAAE,SAAS,OAAO,QAAQ,6BAA6B;AAAA,EAChE;AAGA,QAAM,UAAU,eAAe,SAAS;AACxC,MAAI,QAAQ,SAAS,UAAU,KAAK,QAAQ,cAAc,GAAG;AAC3D,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,cAAc;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,OAAO,SAAS;AAAA,EAClB,CAAC;AACH;;;ACtCA,SAAS,cAAAK,cAAY,eAAAC,cAAa,YAAAC,iBAAgB;AAClD,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,QAAM,WAAAC,gBAAe;AAQvB,SAAS,uBAAuB,SAAyB;AAC9D,SAAOA,SAAQ,OAAO,EAAE,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,GAAG;AAC/D;AAgBO,SAAS,0BACd,SACe;AACf,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,YAAYL,aAAW,QAAQ,GAAG;AACpC,WAAOK,SAAQ,QAAQ;AAAA,EACzB;AAEA,QAAM,aAAa,QAAQ,IAAI,oBAC3BA,SAAQ,QAAQ,IAAI,iBAAiB,IACrCD,OAAKD,SAAQ,GAAG,SAAS;AAC7B,QAAM,eAAeC,OAAK,YAAY,UAAU;AAChD,MAAI,CAACJ,aAAW,YAAY,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,QAAM,YACJ,QAAQ,WAAW,aACnB,QAAQ,WAAW,kBACnB,QAAQ,IAAI,qBACZ,QAAQ,IAAI;AAEd,QAAM,YACJ,QAAQ,WAAW,iBAAiB,CAAC,MACpC,QAAQ,MAAMK,SAAQ,QAAQ,GAAG,IAAIA,SAAQ,QAAQ,QAAQ;AAEhE,QAAM,UAAU,uBAAuB,SAAS;AAChD,QAAM,aAAaD,OAAK,cAAc,OAAO;AAC7C,QAAM,kBAAkBA,OAAK,YAAY,mBAAmB;AAE5D,MAAI,CAACJ,aAAW,eAAe,GAAG;AAChC,WAAO,sBAAsB,YAAY;AAAA,EAC3C;AAEA,MAAI,WAAW;AACb,UAAM,SAASI,OAAK,iBAAiB,WAAW,GAAG,SAAS,QAAQ;AACpE,QAAIJ,aAAW,MAAM,GAAG;AACtB,aAAO;AAAA,IACT;AACA,UAAM,SAAS,kBAAkBI,OAAK,iBAAiB,SAAS,GAAG,SAAS;AAC5E,QAAI,QAAQ;AACV,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO,sBAAsB,eAAe;AAC9C;AAEA,SAAS,kBAAkB,KAAa,WAAkC;AACxE,MAAI,CAACJ,aAAW,GAAG,GAAG;AACpB,WAAO;AAAA,EACT;AACA,QAAM,SAASI,OAAK,KAAK,GAAG,SAAS,QAAQ;AAC7C,MAAIJ,aAAW,MAAM,GAAG;AACtB,WAAO;AAAA,EACT;AACA,aAAW,SAASC,aAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC7D,QAAI,MAAM,OAAO,KAAK,MAAM,KAAK,SAAS,QAAQ,GAAG;AACnD,aAAOG,OAAK,KAAK,MAAM,IAAI;AAAA,IAC7B;AACA,QAAI,MAAM,YAAY,GAAG;AACvB,YAAM,QAAQ,kBAAkBA,OAAK,KAAK,MAAM,IAAI,GAAG,SAAS;AAChE,UAAI,OAAO;AACT,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,MAA6B;AAC1D,QAAM,aAAqD,CAAC;AAC5D,EAAAE,uBAAsB,MAAM,UAAU;AACtC,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,aAAW,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC3C,SAAO,WAAW,CAAC,GAAG,QAAQ;AAChC;AAEA,SAASA,uBACP,KACA,KACM;AACN,MAAI,CAACN,aAAW,GAAG,GAAG;AACpB;AAAA,EACF;AACA,aAAW,SAASC,aAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC7D,UAAM,OAAOG,OAAK,KAAK,MAAM,IAAI;AACjC,QAAI,MAAM,YAAY,GAAG;AACvB,MAAAE,uBAAsB,MAAM,GAAG;AAC/B;AAAA,IACF;AACA,QAAI,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,QAAQ,GAAG;AACrD;AAAA,IACF;AACA,QAAI;AACF,YAAM,KAAKJ,UAAS,IAAI;AACxB,UAAI,KAAK,EAAE,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC;AAAA,IAC5C,QAAQ;AAAA,IAER;AAAA,EACF;AACF;;;AC7HA,eAAsB,iBACpB,UACA,KACA,QACA,SACwB;AACxB,MACE,SAAS,WAAW,WAAW,aAC/B,CAAC,QAAQ,UAAU,WACnB;AACA,WAAO,EAAE,SAAS,OAAO,QAAQ,sBAAsB;AAAA,EACzD;AAEA,QAAM,YAAY,0BAA0B;AAAA,IAC1C;AAAA,IACA;AAAA,IACA,WAAW,SAAS;AAAA,EACtB,CAAC;AACD,MAAI,CAAC,WAAW;AACd,WAAO,EAAE,SAAS,OAAO,QAAQ,0BAA0B;AAAA,EAC7D;AAGA,QAAM,UAAU,eAAe,SAAS;AAExC,SAAO,cAAc;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,OAAO,SAAS;AAAA,EAClB,CAAC;AACH;;;AC3BA,eAAsB,aACpB,KACA,SAMwB;AACxB,QAAM,aAAa,IAAI,OAAO;AAC9B,QAAM,YAAY,WAAW,SAAS,aAAa;AACnD,QAAM,YAAY,WAAW,SAAS,QAAQ;AAC9C,QAAM,eAAe,WAAW,SAAS,WAAW;AAEpD,MAAI,CAAC,aAAa,CAAC,aAAa,CAAC,cAAc;AAC7C,WAAO,EAAE,SAAS,OAAO,QAAQ,iCAAiC;AAAA,EACpE;AAEA,QAAM,OAAO,QAAQ;AACrB,QAAM,QAAQ,IAAI,OAAO,UAAU;AACnC,QAAM,oBAAoB,uBAAuB,IAAI;AACrD,QAAM,iBAAiB,oBAAoB,IAAI;AAC/C,QAAM,iBAAiB,oBAAoB,IAAI;AAE/C,MAAI,qBAAqB,cAAc;AACrC,WAAO,oBAAoB,IAAI,UAAU,QAAQ,KAAK,QAAQ,QAAQ;AAAA,MACpE,gBAAgB,MAAM,kBAAkB,QAAQ;AAAA,MAChD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,kBAAkB,WAAW;AAC/B,WAAO,qBAAqB,IAAI,UAAU,QAAQ,KAAK,QAAQ,QAAQ;AAAA,MACrE,gBAAgB,MAAM,kBAAkB,QAAQ;AAAA,MAChD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,kBAAkB,WAAW;AAC/B,WAAO,iBAAiB,IAAI,UAAU,QAAQ,KAAK,QAAQ,QAAQ;AAAA,MACjE,WAAW;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,WAAW;AACb,UAAM,eAAe,MAAM;AAAA,MACzB,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,QACE,gBAAgB,QAAQ;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AACA,QAAI,aAAa,SAAS;AACxB,aAAO;AAAA,IACT;AACA,QAAI,CAAC,aAAa,CAAC,cAAc;AAC/B,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,WAAW;AACb,UAAM,eAAe,MAAM;AAAA,MACzB,IAAI;AAAA,MACJ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,QACE,WAAW;AAAA,QACX;AAAA,MACF;AAAA,IACF;AACA,QAAI,aAAa,SAAS;AACxB,aAAO;AAAA,IACT;AACA,QAAI,CAAC,cAAc;AACjB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,cAAc;AAChB,WAAO,oBAAoB,IAAI,UAAU,QAAQ,KAAK,QAAQ,QAAQ;AAAA,MACpE,gBAAgB,QAAQ;AAAA,MACxB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,SAAS,OAAO,QAAQ,iCAAiC;AACpE;;;ACtFA,SAAS,iBAAiB,OAAgB,QAA6B;AACrE,MAAI,CAAC,OAAO;AACV;AAAA,EACF;AACA,MAAI,OAAO,WAAW,OAAO,aAAa;AACxC,aAAS,MAAM,WAAW,OAAO,OAAO,WAAW,EAAE;AACrD;AAAA,EACF;AACA,QAAM,QAAQ,CAAC,OAAO,UAAU,SAAS;AACzC,MAAI,OAAO,WAAW;AACpB,UAAM,KAAK,SAAS,OAAO,SAAS,EAAE;AAAA,EACxC;AACA,WAAS,MAAM,WAAW,SAAS,MAAM,KAAK,IAAI,CAAC,EAAE;AACvD;AAEA,eAAsB,WACpB,UAA0B,CAAC,GACH;AACxB,QAAM,MAAM,gBAAgB,QAAQ,GAAG;AACvC,MAAI,CAAC,KAAK;AACR,WAAO,EAAE,SAAS,OAAO,QAAQ,kBAAkB;AAAA,EACrD;AAEA,QAAM,SAAS,MAAM,aAAa,KAAK;AAAA,IACrC,KAAK,QAAQ;AAAA,IACb,QAAQ,QAAQ;AAAA,IAChB,gBAAgB,QAAQ;AAAA,IACxB,WAAW,QAAQ;AAAA,EACrB,CAAC;AACD,mBAAiB,IAAI,OAAO,OAAO,MAAM;AACzC,SAAO;AACT;;;AClCO,SAAS,kBAAkB,MAAmC;AACnE,QAAM,MAAM,gBAAgB,KAAK,GAAG;AACpC,QAAM,QAAQ,KAAK,OAAO,UAAU;AACpC,wBAAsB,KAAK,YAAY,MAAM,KAAK;AAClD,QAAM,YAAY,kBAAkB;AAEpC,MAAI,aAAa,uBAAuB,SAAS,GAAG;AAClD,UAAM,YACJ,UAAU,qBACV,UAAU,kBACV;AACF;AAAA,MACE;AAAA,MACA;AAAA,MACA,wCAAwC,SAAS;AAAA,IACnD;AAAA,EACF;AAEA,sBAAoB,YAAY;AAC9B,UAAM,WAAW;AAAA,MACf,KAAK,KAAK;AAAA,MACV,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,gBAAgB,WAAW;AAAA,IAC7B,CAAC;AAAA,EACH,GAAG,KAAK,QAAQ,KAAK;AACvB;;;ACjCA,eAAsB,mBAAmB,MAKvB;AAChB,QAAM,MAAM,gBAAgB,KAAK,GAAG;AACpC,QAAM,QAAQ,KAAK,OAAO,UAAU;AACpC,wBAAsB,KAAK,YAAY,MAAM,KAAK;AAClD;AAAA,IACE;AAAA,IACA;AAAA,IACA,gBAAgB,KAAK,UAAU,IAAI,YAAY,KAAK,WAAW,IAAI;AAAA,EACrE;AAEA,MAAI;AACF,UAAM,SAAS,MAAM,gBAAgB;AAAA,MACnC,KAAK,KAAK;AAAA,MACV,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,IACf,CAAC;AACD;AAAA,MACE;AAAA,MACA;AAAA,MACA,eAAe,OAAO,GAAG,YAAY,OAAO,UAAU,IAAI,cAAc,OAAO,iBAAiB,aAAa,OAAO,gBAAgB,aAAa,OAAO,gBAAgB,aAAa,OAAO,YAAY,cAAc,OAAO,QAAQ;AAAA,IACvO;AAEA,QAAI,OAAO,KAAK;AACd,UAAI,OAAO,WAAW,WAAW;AAC/B,gBAAQ;AAAA,UACN,sCAAsC,OAAO,iBAAiB;AAAA,QAChE;AAAA,MACF,OAAO;AACL,cAAM,QAAkB,CAAC;AACzB,YAAI,OAAO,mBAAmB;AAC5B,gBAAM,KAAK,GAAG,OAAO,gBAAgB,UAAU;AACjD,YAAI,OAAO,mBAAmB;AAC5B,gBAAM,KAAK,GAAG,OAAO,gBAAgB,UAAU;AACjD,YAAI,OAAO,eAAe;AACxB,gBAAM,KAAK,GAAG,OAAO,YAAY,UAAU;AAC7C,YAAI,OAAO,WAAW;AACpB,gBAAM,KAAK,GAAG,OAAO,QAAQ,WAAW;AAC1C,cAAM,SAAS,MAAM,SAAS,IAAI,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK;AAE5D,gBAAQ;AAAA,UACN,6BAA6B,OAAO,iBAAiB,cAAc,MAAM;AAAA,QAC3E;AAAA,MACF;AAAA,IACF,OAAO;AACL,cAAQ,OAAO,QAAQ;AAAA,QACrB,KAAK;AACH,kBAAQ;AAAA,YACN;AAAA,UACF;AACA;AAAA,QACF,KAAK;AACH,kBAAQ,MAAM,mDAAmD;AACjE;AAAA,QACF,KAAK;AACH,kBAAQ,MAAM,mDAAmD;AACjE;AAAA,QACF;AACE,kBAAQ,MAAM,sBAAsB,OAAO,UAAU,SAAS,EAAE;AAAA,MACpE;AAAA,IACF;AAEA,aAAS,GAAG,KAAK,MAAM;AAAA,EACzB,SAAS,KAAK;AACZ;AAAA,MACE;AAAA,MACA;AAAA,MACA,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC5D;AACA,YAAQ;AAAA,MACN,sBAAsB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACxE;AACA,aAAS,GAAG,KAAK,MAAM;AAAA,EACzB;AACF;;;ACpFA,SAAS,cAAAK,cAAY,eAAAC,cAAa,gBAAAC,sBAAoB;AACtD,SAAS,QAAAC,cAAY;;;ACAd,IAAM,mBAAmB;;;AD4BzB,SAAS,UACd,KACA,SACc;AACd,QAAM,MAAM,gBAAgB,GAAG;AAC/B,MAAI,CAAC,KAAK;AACR,WAAO,EAAE,UAAU,OAAO,OAAO,EAAE;AAAA,EACrC;AAEA,QAAM,WAAW,IAAI;AAGrB,QAAM,gBAAgB,aAAa,QAAQ;AAE3C,QAAM,eAAe,aAAa,QAAQ;AAE1C,MAAI,CAAC,iBAAiB,CAAC,cAAc;AACnC,qBAAiB,KAAK,UAAU,8BAA8B;AAC9D,WAAO,EAAE,UAAU,OAAO,OAAO,EAAE;AAAA,EACrC;AAGA,QAAM,WAAqB,CAAC;AAE5B,MAAI,eAAe;AACjB,aAAS,KAAK,aAAa;AAAA,EAC7B;AAEA,MAAI,cAAc;AAChB,aAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU,SAAS,KAAK,IAAI;AAGhC,MAAI,QAAQ,SAAS,kBAAkB;AACrC,cACE,GAAG,QAAQ,MAAM,GAAG,gBAAgB,CAAC;AAAA;AAAA,uBAA4B,QAAQ,MAAM;AAAA,EACnF;AAGA,MAAI,SAAS,kBAAkB;AAC7B,YAAQ,OAAO;AAAA,MACb,GAAG,KAAK,UAAU,EAAE,oBAAoB,QAAQ,CAAC,CAAC;AAAA;AAAA,IACpD;AAAA,EACF,OAAO;AACL,YAAQ,OAAO,MAAM,OAAO;AAC5B,QAAI,CAAC,QAAQ,SAAS,IAAI,GAAG;AAC3B,cAAQ,OAAO,MAAM,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,mBAAiB,KAAK,UAAU,gBAAgB,QAAQ,MAAM,QAAQ;AAEtE,SAAO,EAAE,UAAU,MAAM,OAAO,QAAQ,OAAO;AACjD;AAIA,SAAS,iBAAiB,UAA0B;AAClD,SAAO,WAAW,UAAU,WAAW;AACzC;AAEA,SAAS,gBAAgB,UAA0B;AACjD,SAAO,WAAW,UAAU,OAAO;AACrC;AAEA,SAAS,aAAa,UAAiC;AACrD,QAAM,OAAO,iBAAiB,QAAQ;AACtC,MAAI,CAACC,aAAW,IAAI,EAAG,QAAO;AAE9B,MAAI;AACF,UAAM,UAAUC,eAAa,MAAM,MAAM;AACzC,WAAO,QAAQ,KAAK,KAAK;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,SAAS,aAAa,UAAiC;AACrD,QAAM,WAAW,gBAAgB,QAAQ;AACzC,MAAI;AACJ,MAAI;AACF,YAAQC,aAAY,QAAQ,EACzB,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,EAC/B,KAAK;AAAA,EACV,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,YAAM,WAAWC,OAAK,UAAU,IAAI;AACpC,YAAM,UAAUF,eAAa,UAAU,MAAM,EAAE,KAAK;AACpD,UAAI,CAAC,QAAS;AAGd,YAAM,KAAK,OAAO,IAAI,IAAI,IAAI,SAAS,EAAE;AAAA,IAC3C,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI;AAC/C;;;AExIO,SAAS,iBAAiB,MAAkC;AACjE,QAAM,MAAM,gBAAgB,KAAK,GAAG;AACpC,QAAM,QAAQ,KAAK,OAAO,UAAU;AACpC,wBAAsB,KAAK,YAAY,MAAM,KAAK;AAElD,QAAM,YAAY,kBAAkB;AACpC,QAAM,mBAAmB,mBAAmB,SAAS;AAErD,sBAAoB,MAAM;AACxB,cAAU,KAAK,KAAK,EAAE,iBAAiB,CAAC;AAAA,EAC1C,GAAG,KAAK,QAAQ,KAAK;AACvB;;;ACtBA,SAAS,iBAAiB;AAC1B,SAAS,WAAAG,gBAAe;;;ACDxB,SAAS,aAAAC,YAAW,iBAAAC,sBAAqB;AACzC,SAAS,QAAAC,cAAY;;;ACDrB,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,QAAAC,cAAY;;;ACDrB,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,WAAAC,UAAS,QAAAC,cAAY;AAC9B,SAAS,iBAAAC,sBAAqB;;;ACF9B,SAAS,gBAAAC,sBAAoB;AAC7B,SAAS,WAAAC,UAAS,QAAAC,cAAY;AAC9B,SAAS,iBAAAC,sBAAqB;AAEvB,IAAM,eAAe;AAE5B,IAAM,YAAYF,SAAQE,eAAc,YAAY,GAAG,CAAC;AAEjD,SAAS,iBAAyB;AACvC,QAAM,UAAUD,OAAK,WAAW,MAAM,cAAc;AACpD,QAAM,MAAM,KAAK,MAAMF,eAAa,SAAS,MAAM,CAAC;AACpD,SAAO,IAAI;AACb;;;ADPA,SAAS,qBAA6B;AACpC,QAAM,OAAOI,SAAQC,eAAc,YAAY,GAAG,CAAC;AACnD,QAAM,aAAa;AAAA,IACjBC,OAAK,MAAM,WAAW;AAAA,IACtBA,OAAK,MAAM,MAAM,MAAM,WAAW;AAAA,EACpC;AACA,aAAW,OAAO,YAAY;AAC5B,QAAIC,aAAW,GAAG,GAAG;AACnB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAOD,OAAK,MAAM,WAAW;AAC/B;AAEA,IAAM,cAAc,mBAAmB;AAEhC,SAAS,oBAAoB,MAAsB;AACxD,SAAOA,OAAK,aAAa,IAAI;AAC/B;AAEO,SAAS,aAAa,MAAsB;AACjD,SAAOE,eAAa,oBAAoB,IAAI,GAAG,MAAM;AACvD;AAEO,SAAS,eAAe,MAAsB;AACnD,QAAM,MAAM,aAAa,IAAI;AAC7B,SAAO,IAAI,WAAW,oBAAoB,YAAY;AACxD;;;AD3BO,IAAM,4BAA4B;AAElC,SAAS,wBAAwB,UAA0B;AAChE,SAAOC,OAAK,UAAU,WAAW,qBAAqB;AACxD;AAKO,SAAS,yBAAyB,UAGvC;AACA,QAAM,eAAe,wBAAwB,QAAQ;AACrD,QAAM,UAAUC,aAAW,YAAY;AAEvC,QAAM,iBAAiB,KAAK,MAAM,eAAe,gBAAgB,CAAC;AAOlE,MAAI,WAAoC,CAAC;AACzC,MAAI,SAAS;AACX,QAAI;AACF,iBAAW,KAAK,MAAMC,eAAa,cAAc,MAAM,CAAC;AAAA,IAI1D,QAAQ;AACN,iBAAW,CAAC;AAAA,IACd;AAAA,EACF;AAEA,QAAM,YACJ,SAAS,SACT,OAAO,SAAS,UAAU,YAC1B,CAAC,MAAM,QAAQ,SAAS,KAAK,IACxB,SAAS,QACV,CAAC;AAEP,QAAM,SAAkC;AAAA,IACtC,GAAG;AAAA,IACH,OAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,eAAe,MAAM;AAAA,MAC3B,cAAc,eAAe,MAAM;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA;AAAA,IAC3C,QAAQ,UAAU,gBAAgB;AAAA,EACpC;AACF;;;ADnDO,IAAM,oBAAsC;AAAA,EACjD,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,WAAW;AAAA,EACX,eAAe,CAAC,yBAAyB;AAAA,EACzC,MAAM,KAAyB;AAC7B,IAAAC,WAAUC,OAAK,IAAI,UAAU,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,UAAM,EAAE,SAAS,OAAO,IAAI,yBAAyB,IAAI,QAAQ;AACjE,IAAAC,eAAc,wBAAwB,IAAI,QAAQ,GAAG,SAAS,MAAM;AACpE,QAAI,OAAO,MAAM,KAAK,EAAE,MAAM,2BAA2B,OAAO,CAAC;AAAA,EACnE;AACF;;;AIpBA,SAAS,aAAAC,YAAW,iBAAAC,sBAAqB;AACzC,SAAS,QAAAC,cAAY;;;ACDrB,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,QAAAC,cAAY;AAGd,IAAM,mBAAmB;AAEhC,IAAM,4BACJ;AACF,IAAM,0BAA0B;AAEhC,SAAS,wBAAgC;AACvC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEO,SAAS,gBAAgB,UAA0B;AACxD,SAAOA,OAAK,UAAU,UAAU,aAAa;AAC/C;AAEA,SAAS,kBAAkB,UAAkB,OAAuB;AAClE,QAAM,WAAW,SAAS,QAAQ,yBAAyB;AAC3D,QAAM,SAAS,SAAS,QAAQ,uBAAuB;AAEvD,MAAI,YAAY,KAAK,UAAU,UAAU;AACvC,UAAM,SAAS,SAAS,MAAM,GAAG,QAAQ,EAAE,QAAQ;AACnD,UAAM,QAAQ,SAAS,MAAM,SAAS,wBAAwB,MAAM,EAAE,UAAU;AAChF,WAAO,GAAG,SAAS,GAAG,MAAM;AAAA;AAAA,IAAS,EAAE,GAAG,KAAK,GAAG,QAAQ;AAAA;AAAA,EAAO,KAAK,KAAK,EAAE;AAAA;AAAA,EAC/E;AAEA,QAAM,UAAU,SAAS,QAAQ;AACjC,SAAO,GAAG,UAAU,GAAG,OAAO;AAAA;AAAA,IAAS,EAAE,GAAG,KAAK;AAAA;AACnD;AAGO,SAAS,iBAAiB,UAG/B;AACA,QAAM,aAAa,gBAAgB,QAAQ;AAC3C,QAAM,UAAUF,aAAW,UAAU;AACrC,QAAM,QAAQ,sBAAsB;AAEpC,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,MACL,SAAS,GAAG,KAAK;AAAA;AAAA,MACjB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,WAAWC,eAAa,YAAY,MAAM;AAChD,QAAM,WACJ,SAAS,SAAS,yBAAyB,KAC3C,SAAS,SAAS,uBAAuB;AAE3C,SAAO;AAAA,IACL,SAAS,kBAAkB,UAAU,KAAK;AAAA,IAC1C,QAAQ,WAAW,aAAa;AAAA,EAClC;AACF;;;ADtDO,IAAM,eAAiC;AAAA,EAC5C,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,WAAW;AAAA,EACX,eAAe,CAAC,gBAAgB;AAAA,EAChC,MAAM,KAAyB;AAC7B,IAAAE,WAAUC,OAAK,IAAI,UAAU,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAC3D,UAAM,EAAE,SAAS,OAAO,IAAI,iBAAiB,IAAI,QAAQ;AACzD,IAAAC,eAAc,gBAAgB,IAAI,QAAQ,GAAG,SAAS,MAAM;AAC5D,QAAI,OAAO,MAAM,KAAK,EAAE,MAAM,kBAAkB,OAAO,CAAC;AAAA,EAC1D;AACF;;;AEpBA,SAAS,aAAAC,YAAW,iBAAAC,sBAAqB;AACzC,SAAS,QAAAC,cAAY;;;ACDrB,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,QAAAC,cAAY;AAId,IAAM,+BAA+B;AAErC,SAAS,2BAA2B,UAA0B;AACnE,SAAOC,OAAK,UAAU,cAAc,qBAAqB;AAC3D;AAKO,SAAS,4BAA4B,UAG1C;AACA,QAAM,eAAe,2BAA2B,QAAQ;AACxD,QAAM,UAAUC,aAAW,YAAY;AAEvC,QAAM,iBAAiB,KAAK;AAAA,IAC1B,eAAe,0BAA0B;AAAA,EAC3C;AAOA,MAAI,WAAoC,CAAC;AACzC,MAAI,SAAS;AACX,QAAI;AACF,iBAAW,KAAK,MAAMC,eAAa,cAAc,MAAM,CAAC;AAAA,IAI1D,QAAQ;AACN,iBAAW,CAAC;AAAA,IACd;AAAA,EACF;AAEA,QAAM,YACJ,SAAS,SACT,OAAO,SAAS,UAAU,YAC1B,CAAC,MAAM,QAAQ,SAAS,KAAK,IACxB,SAAS,QACV,CAAC;AAEP,QAAM,SAAkC;AAAA,IACtC,GAAG;AAAA,IACH,OAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,eAAe,MAAM;AAAA,MAC3B,cAAc,eAAe,MAAM;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA;AAAA,IAC3C,QAAQ,UAAU,gBAAgB;AAAA,EACpC;AACF;;;ADrDO,IAAM,mBAAqC;AAAA,EAChD,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,WAAW;AAAA,EACX,eAAe,CAAC,4BAA4B;AAAA,EAC5C,MAAM,KAAyB;AAC7B,IAAAC,WAAUC,OAAK,IAAI,UAAU,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AAC/D,UAAM,EAAE,SAAS,OAAO,IAAI,4BAA4B,IAAI,QAAQ;AACpE,IAAAC,eAAc,2BAA2B,IAAI,QAAQ,GAAG,SAAS,MAAM;AACvE,QAAI,OAAO,MAAM,KAAK,EAAE,MAAM,8BAA8B,OAAO,CAAC;AAAA,EACtE;AACF;;;AEpBA,SAAS,aAAAC,aAAW,iBAAAC,sBAAqB;AACzC,SAAS,QAAAC,cAAY;;;ACDrB,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,QAAAC,cAAY;AAId,IAAM,mBAAmB;AAEzB,SAAS,gBAAgB,UAA0B;AACxD,SAAOC,OAAK,UAAU,WAAW,YAAY;AAC/C;AAKO,SAAS,iBAAiB,UAG/B;AACA,QAAM,YAAY,gBAAgB,QAAQ;AAC1C,QAAM,UAAUC,aAAW,SAAS;AAEpC,QAAM,iBAAiB,KAAK,MAAM,eAAe,uBAAuB,CAAC;AAQzE,MAAI,WAAoC,CAAC;AACzC,MAAI,SAAS;AACX,QAAI;AACF,iBAAW,KAAK,MAAMC,eAAa,WAAW,MAAM,CAAC;AAAA,IAIvD,QAAQ;AACN,iBAAW,CAAC;AAAA,IACd;AAAA,EACF;AAEA,QAAM,YACJ,SAAS,SACT,OAAO,SAAS,UAAU,YAC1B,CAAC,MAAM,QAAQ,SAAS,KAAK,IACxB,SAAS,QACV,CAAC;AAEP,QAAM,SAAkC;AAAA,IACtC,GAAG;AAAA,IACH,SAAS,eAAe;AAAA,IACxB,OAAO;AAAA,MACL,GAAG;AAAA,MACH,cAAc,eAAe,MAAM;AAAA,MACnC,MAAM,eAAe,MAAM;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA;AAAA,IAC3C,QAAQ,UAAU,gBAAgB;AAAA,EACpC;AACF;;;ADrDO,IAAM,gBAAkC;AAAA,EAC7C,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,WAAW;AAAA,EACX,eAAe,CAAC,gBAAgB;AAAA,EAChC,MAAM,KAAyB;AAC7B,IAAAC,YAAUC,OAAK,IAAI,UAAU,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,UAAM,EAAE,SAAS,OAAO,IAAI,iBAAiB,IAAI,QAAQ;AACzD,IAAAC,eAAc,gBAAgB,IAAI,QAAQ,GAAG,SAAS,MAAM;AAC5D,QAAI,OAAO,MAAM,KAAK,EAAE,MAAM,kBAAkB,OAAO,CAAC;AAAA,EAC1D;AACF;;;AEdO,IAAM,wBAAuC,CAAC,aAAa;AAElE,IAAM,eAAmC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,gBAAgB,IAAI;AAAA,EACxB,aAAa,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;AACnC;AAEO,SAAS,WAAW,IAAmC;AAC5D,QAAM,UAAU,cAAc,IAAI,EAAE;AACpC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,yBAAyB,EAAE,EAAE;AAAA,EAC/C;AACA,SAAO;AACT;AAEO,SAAS,gBAAoC;AAClD,SAAO,aAAa,OAAO,CAAC,MAAM,EAAE,SAAS;AAC/C;AAEO,SAAS,mBAAmB,IAA+B;AAChE,SAAO,cAAc,IAAI,EAAiB;AAC5C;AAEO,SAAS,cAAc,OAA8B;AAC1D,QAAM,MAAM,MACT,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AAEjB,MAAI,IAAI,WAAW,GAAG;AACpB,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AAEA,QAAM,SAAwB,CAAC;AAC/B,aAAW,MAAM,KAAK;AACpB,QAAI,CAAC,mBAAmB,EAAE,GAAG;AAC3B,YAAM,IAAI,MAAM,yBAAyB,EAAE,EAAE;AAAA,IAC/C;AACA,UAAM,UAAU,WAAW,EAAE;AAC7B,QAAI,CAAC,QAAQ,WAAW;AACtB,YAAM,IAAI,MAAM,gCAAgC,EAAE,EAAE;AAAA,IACtD;AACA,WAAO,KAAK,EAAE;AAAA,EAChB;AACA,SAAO;AACT;AAEO,SAAS,2BAA2B,KAA0B;AACnE,MAAI,IAAI,WAAW,GAAG;AACpB,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AACA,aAAW,MAAM,KAAK;AACpB,UAAM,UAAU,WAAW,EAAE;AAC7B,QAAI,CAAC,QAAQ,WAAW;AACtB,YAAM,IAAI,MAAM,gCAAgC,EAAE,EAAE;AAAA,IACtD;AAAA,EACF;AACF;;;ACrEA,SAAS,aAAAC,aAAW,iBAAAC,uBAAqB;AACzC,SAAS,QAAAC,cAAY;AAGd,SAAS,iBAAiB,UAAwB;AACvD,QAAM,aAAaC,OAAK,UAAU,UAAU;AAC5C,EAAAC,YAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAEzC,aAAW,OAAO,gBAAgB;AAChC,IAAAA,YAAUD,OAAK,YAAY,GAAG,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,EACtD;AAEA,EAAAC,YAAUD,OAAK,UAAU,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AAExD,aAAW,OAAO,cAAc;AAC9B,UAAM,WAAWA,OAAK,YAAY,KAAK,UAAU;AACjD,IAAAE,gBAAc,UAAU,IAAI,EAAE,MAAM,IAAI,CAAC;AAAA,EAC3C;AACF;;;AClBA,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AAIzC,SAAS,uBAAuB,UAAiC;AAC/D,QAAM,aAAa,WAAW,UAAU,aAAa;AACrD,MAAI,CAACC,aAAW,UAAU,GAAG;AAC3B,WAAO,CAAC;AAAA,EACV;AACA,MAAI;AACF,UAAM,SAAS,KAAK,MAAMC,eAAa,YAAY,MAAM,CAAC;AAG1D,QAAI,CAAC,MAAM,QAAQ,OAAO,UAAU,GAAG;AACrC,aAAO,CAAC;AAAA,IACV;AACA,WAAO,OAAO,WAAW,OAAO,CAAC,OAA0B,OAAO,OAAO,QAAQ;AAAA,EACnF,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAGO,SAAS,gBACd,UACA,UACe;AACf,QAAM,WAAW,uBAAuB,QAAQ;AAChD,SAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,UAAU,GAAG,QAAQ,CAAC,CAAC;AAChD;;;AC7BA,SAAS,cAAAC,cAAY,gBAAAC,gBAAc,iBAAAC,uBAAqB;AACxD,SAAS,QAAAC,cAAY;AAGrB,IAAM,eAAe;AACrB,IAAM,aAAa;AAIZ,SAAS,qBAAqB,UAGnC;AACA,QAAM,QAAQ,aAAa,qBAAqB,EAAE,QAAQ,IAAI;AAC9D,QAAM,gBAAgBC,OAAK,UAAU,YAAY;AACjD,QAAM,gBAAgBC,aAAW,aAAa,IAC1CC,eAAa,eAAe,MAAM,IAClC;AAEJ,QAAM,wBACJ,cAAc,SAAS,KACvB,CAAC,cAAc,SAAS,YAAY,KACpC,wBAAwB,KAAK,aAAa;AAE5C,MAAI,CAACD,aAAW,aAAa,GAAG;AAC9B,IAAAE,gBAAc,eAAe,GAAG,KAAK;AAAA,GAAM,MAAM;AACjD,WAAO,EAAE,QAAQ,WAAW,uBAAuB,MAAM;AAAA,EAC3D;AAEA,QAAM,WAAW,cAAc,QAAQ,YAAY;AACnD,QAAM,SAAS,cAAc,QAAQ,UAAU;AAE/C,MAAI,aAAa,MAAM,WAAW,MAAM,SAAS,UAAU;AACzD,UAAM,SAAS,cAAc,MAAM,GAAG,QAAQ;AAC9C,UAAM,QAAQ,cAAc,MAAM,SAAS,WAAW,MAAM;AAC5D,UAAM,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,WAAW,MAAM;AAClE,IAAAA,gBAAc,eAAe,KAAK,SAAS,IAAI,IAAI,OAAO,GAAG,IAAI;AAAA,GAAM,MAAM;AAC7E,WAAO,EAAE,QAAQ,YAAY,sBAAsB;AAAA,EACrD;AAEA,MAAI,aAAa,IAAI;AACnB,UAAM,SAAS,cAAc,MAAM,GAAG,QAAQ;AAC9C,UAAM,OAAO,GAAG,MAAM,GAAG,KAAK;AAAA;AAC9B,IAAAA,gBAAc,eAAe,MAAM,MAAM;AACzC,WAAO,EAAE,QAAQ,WAAW,sBAAsB;AAAA,EACpD;AAEA,QAAM,YAAY,cAAc,SAAS,IAAI,KAAK,cAAc,WAAW,IAAI,OAAO;AACtF,EAAAA,gBAAc,eAAe,GAAG,aAAa,GAAG,SAAS,GAAG,KAAK;AAAA,GAAM,MAAM;AAC7E,SAAO,EAAE,QAAQ,YAAY,sBAAsB;AACrD;;;AClDA,SAAS,cAAc,aAAAC,aAAW,iBAAAC,uBAAqB;;;ACAvD,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AAMzC,IAAM,cAAc;AAAA,EAClB,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,eAAe;AAAA,EACf,MAAM;AACR;AAEA,IAAM,sBAAsB;AAAA,EAC1B,iBAAiB;AAAA,EACjB,WAAW;AAAA,IACT,SAAS;AAAA,IACT,oBAAoB;AAAA,IACpB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,EACnB;AACF;AAEO,SAAS,mBACd,UACA,YAC6C;AAC7C,QAAM,aAAa,WAAW,UAAU,aAAa;AACrD,QAAM,UAAUC,aAAW,UAAU;AAErC,MAAI,WAAoC,CAAC;AACzC,MAAI,SAAS;AACX,QAAI;AACF,iBAAW,KAAK,MAAMC,eAAa,YAAY,MAAM,CAAC;AAAA,IAIxD,QAAQ;AACN,iBAAW,CAAC;AAAA,IACd;AAAA,EACF;AAEA,QAAM,cACJ,SAAS,WACT,OAAO,SAAS,YAAY,YAC5B,CAAC,MAAM,QAAQ,SAAS,OAAO,IAC1B,SAAS,UACV,CAAC;AAGP,QAAM,UACJ,SAAS,OAAO,OAAO,SAAS,QAAQ,YAAY,CAAC,MAAM,QAAQ,SAAS,GAAG,IAC1E,SAAS,MACV,CAAC;AACP,QAAM,kBACJ,SAAS,eAAe,OAAO,SAAS,gBAAgB,YAAY,CAAC,MAAM,QAAQ,SAAS,WAAW,IAClG,SAAS,cACV,CAAC;AACP,QAAM,gBACJ,gBAAgB,aAChB,OAAO,gBAAgB,cAAc,YACrC,CAAC,MAAM,QAAQ,gBAAgB,SAAS,IACnC,gBAAgB,YACjB,CAAC;AAEP,QAAM,SAAkC;AAAA,IACtC,GAAG;AAAA,IACH,SAAS;AAAA,IACT,SAAS;AAAA,MACP,GAAG;AAAA,MACH,SAAS;AAAA,IACX;AAAA,IACA;AAAA,IACA,OAAO,SAAS,UAAU;AAAA,IAC1B,KAAK,EAAE,GAAG,aAAa,GAAG,QAAQ;AAAA,IAClC,aAAa;AAAA,MACX,GAAG;AAAA,MACH,GAAG;AAAA,MACH,WAAW;AAAA,QACT,GAAG,oBAAoB;AAAA,QACvB,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA;AAAA,IAC3C,QAAQ,UAAU,gBAAgB;AAAA,EACpC;AACF;;;AC7FA,SAAS,cAAAC,cAAY,gBAAAC,gBAAc,iBAAAC,uBAAqB;AACxD,SAAS,QAAAC,cAAY;AAId,IAAM,6BACX;AACK,IAAM,2BAA2B;AAEjC,SAAS,6BAAqC;AACnD,SAAO,eAAe,yBAAyB,EAAE,QAAQ;AAC3D;AAEO,SAAS,+BAAuC;AACrD,QAAM,OAAO,2BAA2B;AACxC,SAAO,GAAG,0BAA0B;AAAA,EAAK,IAAI;AAAA,EAAK,wBAAwB;AAC5E;AAEO,SAAS,mBAA2B;AACzC,SAAO,eAAe,eAAe,EAAE;AAAA,IACrC;AAAA,IACA,2BAA2B;AAAA,EAC7B;AACF;AAEO,SAAS,uBAAuB,SAA0B;AAC/D,QAAM,WAAW,QAAQ,QAAQ,0BAA0B;AAC3D,QAAM,SAAS,QAAQ,QAAQ,wBAAwB;AACvD,SAAO,aAAa,MAAM,WAAW,MAAM,SAAS;AACtD;AAGO,SAAS,+BAA+B,SAA0B;AACvE,MAAI,uBAAuB,OAAO,GAAG;AACnC,WAAO;AAAA,EACT;AACA,SACE,QAAQ,SAAS,uBAAuB,KACxC,QAAQ,SAAS,6BAAS,KAC1B,QAAQ,SAAS,mBAAmB;AAExC;AAOA,IAAM,0BAA0B;AAEhC,SAAS,yBAAyB,QAAwB;AACxD,QAAM,UAAU,OAAO,QAAQ;AAC/B,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AACA,SAAO,GAAG,OAAO,GAAG,uBAAuB;AAC7C;AAEA,SAASC,mBAAkB,UAAkB,OAAuB;AAClE,QAAM,WAAW,SAAS,QAAQ,0BAA0B;AAC5D,QAAM,SAAS,SAAS,QAAQ,wBAAwB;AAExD,MAAI,aAAa,MAAM,WAAW,MAAM,SAAS,UAAU;AACzD,UAAM,SAAS,SAAS,MAAM,GAAG,QAAQ;AACzC,UAAM,QAAQ,SAAS,MAAM,SAAS,yBAAyB,MAAM;AACrE,UAAM,OAAO,GAAG,yBAAyB,MAAM,CAAC,GAAG,KAAK,GAAG,KAAK;AAChE,WAAO,KAAK,SAAS,IAAI,IAAI,OAAO,GAAG,IAAI;AAAA;AAAA,EAC7C;AAEA,MAAI,aAAa,IAAI;AACnB,UAAM,SAAS,SAAS,MAAM,GAAG,QAAQ;AACzC,WAAO,GAAG,yBAAyB,MAAM,CAAC,GAAG,KAAK;AAAA;AAAA,EACpD;AAEA,SAAO,GAAG,yBAAyB,QAAQ,CAAC,GAAG,KAAK;AAAA;AACtD;AAEO,SAAS,cACd,UACA,OACgB;AAChB,QAAM,aAAaC,OAAK,UAAU,WAAW;AAC7C,QAAM,QAAQ,6BAA6B;AAE3C,MAAI,CAACC,aAAW,UAAU,GAAG;AAC3B,IAAAC,gBAAc,YAAY,iBAAiB,GAAG,MAAM;AACpD,WAAO;AAAA,EACT;AAEA,QAAM,UAAUC,eAAa,YAAY,MAAM;AAE/C,MAAI,uBAAuB,OAAO,GAAG;AACnC,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AACA,IAAAD,gBAAc,YAAYH,mBAAkB,SAAS,KAAK,GAAG,MAAM;AACnE,WAAO;AAAA,EACT;AAEA,MAAI,+BAA+B,OAAO,GAAG;AAC3C,WAAO;AAAA,EACT;AAEA,EAAAG,gBAAc,YAAYH,mBAAkB,SAAS,KAAK,GAAG,MAAM;AACnE,SAAO;AACT;;;ACzGA,SAAS,cAAAK,cAAY,iBAAAC,uBAAqB;AAGnC,SAAS,gBACd,cACA,OAC4C;AAC5C,MAAI,CAACD,aAAW,YAAY,GAAG;AAC7B,WAAO,EAAE,OAAO,MAAM,QAAQ,UAAU;AAAA,EAC1C;AACA,MAAI,OAAO;AACT,WAAO,EAAE,OAAO,MAAM,QAAQ,cAAc;AAAA,EAC9C;AACA,SAAO,EAAE,OAAO,OAAO,QAAQ,UAAU;AAC3C;AAEO,SAAS,eACd,QACA,cACA,cACA,SACA,OACM;AACN,QAAM,EAAE,OAAO,OAAO,IAAI,gBAAgB,cAAc,KAAK;AAC7D,MAAI,CAAC,OAAO;AACV,WAAO,MAAM,KAAK,EAAE,MAAM,cAAc,OAAO,CAAC;AAChD;AAAA,EACF;AACA,EAAAC,gBAAc,cAAc,SAAS,MAAM;AAC3C,SAAO,MAAM,KAAK,EAAE,MAAM,cAAc,OAAO,CAAC;AAClD;;;AHeA,SAAS,gBACP,QACA,UACA,YACM;AACN,QAAM,EAAE,SAAS,OAAO,IAAI,mBAAmB,UAAU,UAAU;AACnE,QAAM,eAAe,WAAW,UAAU,aAAa;AACvD,EAAAC,gBAAc,cAAc,SAAS,MAAM;AAC3C,SAAO,MAAM,KAAK,EAAE,MAAM,uBAAuB,OAAO,CAAC;AAC3D;AAEA,SAAS,sBACP,QACA,cACA,cACA,cACA,OACM;AACN,QAAM,EAAE,OAAO,OAAO,IAAI,gBAAgB,cAAc,KAAK;AAC7D,MAAI,CAAC,OAAO;AACV,WAAO,MAAM,KAAK,EAAE,MAAM,cAAc,OAAO,CAAC;AAChD;AAAA,EACF;AACA,eAAa,oBAAoB,YAAY,GAAG,YAAY;AAC5D,SAAO,MAAM,KAAK,EAAE,MAAM,cAAc,OAAO,CAAC;AAClD;AAEO,SAAS,mBACd,UACA,MACA,QACM;AACN,QAAM,EAAE,OAAO,yBAAyB,WAAW,IAAI;AAEvD,kBAAgB,QAAQ,UAAU,UAAU;AAK5C;AAAA,IACE;AAAA,IACA,WAAW,UAAU,WAAW;AAAA,IAChC;AAAA,IACA,eAAe,eAAe;AAAA,IAC9B;AAAA,EACF;AAGA;AAAA,IACE;AAAA,IACA,WAAW,UAAU,wBAAwB;AAAA,IAC7C;AAAA,IACA,GAAG,KAAK;AAAA,MACN;AAAA,QACE,SAAS;AAAA,QACT,oBAAoB;AAAA,QACpB,OAAO;AAAA,UACL,wBAAwB;AAAA,UACxB,SAAS,CAAC;AAAA,UACV,uBAAuB;AAAA,QACzB;AAAA,QACA,mBAAmB,CAAC;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA;AAAA,IACD;AAAA,EACF;AAIA,SAAO,MAAM,KAAK;AAAA,IAChB,MAAM;AAAA,IACN,QAAQ,cAAc,UAAU,KAAK;AAAA,EACvC,CAAC;AAED,aAAW,MAAM,YAAY;AAC3B,eAAW,EAAE,EAAE,MAAM,EAAE,UAAU,OAAO,OAAO,CAAC;AAAA,EAClD;AAEA,MAAI,2BAA2B,uBAAuB,SAAS,GAAG;AAEhE,UAAM,eAAe,WAAW,UAAU,WAAW;AACrD,IAAAC,YAAU,cAAc,EAAE,WAAW,KAAK,CAAC;AAC3C,eAAW,QAAQ,wBAAwB;AACzC,YAAM,OAAO,WAAW,UAAU,aAAa,IAAI;AACnD;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA,qBAAqB,IAAI;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AI5IA,SAAS,UAAU,SAAS,aAAa;AACzC,SAAS,cAAAC,cAAY,gBAAAC,sBAAoB;AACzC,SAAS,WAAAC,gBAAe;AAMxB,SAAS,cAAc,WAA4B;AACjD,QAAM,aAAa,WAAW,WAAW,aAAa;AACtD,MAAI,CAACC,aAAW,UAAU,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,MAAI;AACF,UAAM,SAAS,KAAK,MAAMC,eAAa,YAAY,MAAM,CAAC;AAG1D,WAAO,OAAO,OAAO,YAAY,YAAY,OAAO,WAAW;AAAA,EACjE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,kBACpB,MAC8B;AAC9B,QAAM,aAAaC,SAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC;AAEpD,QAAM,cAAc,MAAM,MAAM;AAAA,IAC9B,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AACD,QAAM,YAAYA,SAAQ,WAAW;AAErC,QAAM,aAAc,MAAM,SAAS;AAAA,IACjC,SAAS;AAAA,IACT,SAAS,cAAc,EAAE,IAAI,CAAC,OAAO;AAAA,MACnC,MAAM,EAAE;AAAA,MACR,OAAO,EAAE;AAAA,MACT,SAAS,EAAE,OAAO;AAAA,IACpB,EAAE;AAAA,IACF,UAAU,CAAC,UAAU,MAAM,SAAS,KAAK;AAAA,EAC3C,CAAC;AAED,QAAM,0BAA0B,MAAM,QAAQ;AAAA,IAC5C,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AAED,MAAI,cAAc,SAAS,GAAG;AAC5B,UAAM,eAAe,MAAM,QAAQ;AAAA,MACjC,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,cAAc;AACjB,aAAO;AAAA,QACL;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA,WAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,QAAQ,KAAK,KAAK;AAAA,IACzB;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb;AACF;;;AnBzDO,SAAS,iBAAiB,KAAsB;AACrD,QAAM,YAAYC,SAAQ,OAAO,QAAQ,IAAI,CAAC;AAC9C,QAAM,WAAW,UAAU,OAAO,CAAC,aAAa,uBAAuB,GAAG;AAAA,IACxE,KAAK;AAAA,IACL,UAAU;AAAA,EACZ,CAAC;AACD,MAAI,SAAS,WAAW,GAAG;AACzB,YAAQ;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,0BAA0B,MAAqC;AACtE,MAAI,KAAK,YAAY;AACnB,+BAA2B,KAAK,UAAU;AAC1C,WAAO,KAAK;AAAA,EACd;AACA,MAAI,KAAK,OAAO;AACd,QAAI,CAAC,KAAK,KAAK;AACb,cAAQ,MAAM,kDAAkD;AAChE,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,WAAO,cAAc,KAAK,KAAK;AAAA,EACjC;AACA,MAAI,KAAK,KAAK;AACZ,WAAO,CAAC,GAAG,qBAAqB;AAAA,EAClC;AACA,SAAO,CAAC;AACV;AAEO,SAAS,gBAAgB,QAA0B;AACxD,QAAM,UAAU,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AACjE,QAAM,UAAU,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AACjE,QAAM,cAAc,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,aAAa;AACzE,QAAM,WAAW,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU;AACnE,QAAM,WAAW,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU;AAEnE,UAAQ,IAAI;AAAA,uCAA2B,OAAO,SAAS;AAAA,CAAI;AAC3D,UAAQ,IAAI,mCAAU,OAAO,WAAW,KAAK,IAAI,CAAC;AAAA,CAAI;AAEtD,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI,uBAAQ,QAAQ,MAAM,IAAI;AACtC,eAAW,KAAK,SAAS;AACvB,cAAQ,IAAI,OAAO,EAAE,IAAI,EAAE;AAAA,IAC7B;AAAA,EACF;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,YAAQ,IAAI,uBAAQ,YAAY,MAAM,IAAI;AAC1C,eAAW,KAAK,aAAa;AAC3B,cAAQ,IAAI,OAAO,EAAE,IAAI,EAAE;AAAA,IAC7B;AAAA,EACF;AAEA,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,IAAI,uBAAQ,SAAS,MAAM,IAAI;AACvC,eAAW,KAAK,UAAU;AACxB,cAAQ,IAAI,OAAO,EAAE,IAAI,EAAE;AAAA,IAC7B;AAAA,EACF;AAEA,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,IAAI,qCAAiB,SAAS,MAAM,IAAI;AAChD,eAAW,KAAK,UAAU;AACxB,cAAQ,IAAI,YAAO,EAAE,IAAI,EAAE;AAAA,IAC7B;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI,uBAAQ,QAAQ,MAAM,IAAI;AACtC,eAAW,KAAK,SAAS;AACvB,cAAQ,IAAI,OAAO,EAAE,IAAI,EAAE;AAAA,IAC7B;AAAA,EACF;AAEA,MAAI,OAAO,iBAAiB;AAC1B,YAAQ,IAAI;AAAA,cAAiB,OAAO,eAAe,iCAAkB;AAAA,EACvE;AAEA,aAAW,WAAW,OAAO,UAAU;AACrC,YAAQ,KAAK,SAAS,OAAO,EAAE;AAAA,EACjC;AAEA,UAAQ,IAAI,EAAE;AAChB;AAEA,eAAsB,QAAQ,MAA2C;AACvE,MAAI,CAAC,QAAQ,MAAM,SAAS,CAAC,KAAK,KAAK;AACrC,YAAQ,MAAM,kDAAkD;AAChE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,KAAK,SAAS,CAAC,KAAK,KAAK;AAC3B,YAAQ,MAAM,0BAA0B;AACxC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI;AAEJ,MAAI,KAAK,KAAK;AACZ,UAAM,YAAY,iBAAiB,KAAK,GAAG;AAC3C,UAAM,WAAW,0BAA0B,IAAI;AAC/C,eAAW;AAAA,MACT;AAAA,MACA,OAAO,QAAQ,KAAK,KAAK;AAAA,MACzB,yBAAyB,KAAK,2BAA2B;AAAA,MACzD,YAAY,gBAAgB,WAAW,QAAQ;AAAA,MAC/C,WAAW;AAAA,IACb;AAAA,EACF,OAAO;AACL,UAAM,WAAW,MAAM,kBAAkB,IAAI;AAC7C,QAAI,SAAS,WAAW;AACtB,cAAQ,IAAI,yBAAU;AACtB,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,eAAW;AAAA,MACT,GAAG;AAAA,MACH,YAAY,gBAAgB,SAAS,WAAW,SAAS,UAAU;AAAA,IACrE;AAAA,EACF;AAEA,QAAM,SAAqB;AAAA,IACzB,WAAW,SAAS;AAAA,IACpB,YAAY,SAAS;AAAA,IACrB,OAAO,CAAC;AAAA,IACR,UAAU,CAAC;AAAA,EACb;AAEA,mBAAiB,SAAS,SAAS;AACnC,qBAAmB,SAAS,WAAW,UAAU,MAAM;AAEvD,QAAM,YAAY,qBAAqB,SAAS,SAAS;AACzD,SAAO,kBAAkB,UAAU;AACnC,MAAI,UAAU,uBAAuB;AACnC,WAAO,SAAS;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAEA,kBAAgB,MAAM;AAEtB,SAAO;AACT;;;AoB5JA,eAAsB,eAAe,MAAqC;AACxE,MAAI;AACF,UAAM,QAAQ,IAAI;AAAA,EACpB,SAAS,OAAO;AACd,YAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AACpE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;A7DFA,IAAM,iBAAiB;AAEvB,SAAS,oBAA0B;AACjC,QAAM,QAAQ,OAAO,SAAS,QAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK,KAAK,EAAE;AAC5E,MAAI,QAAQ,gBAAgB;AAC1B,YAAQ;AAAA,MACN,mCAAmC,cAAc,cAAc,QAAQ,OAAO;AAAA,IAChF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,SAAS,OAAa;AACpB,oBAAkB;AAElB,QAAM,UAAU,IAAI,QAAQ;AAE5B,UACG,KAAK,aAAa,EAClB;AAAA,IACC;AAAA,EACF,EACC,QAAQ,eAAe,GAAG,iBAAiB,gCAAO;AAErD,UACG,QAAQ,MAAM,EACd,YAAY,+FAA8B,EAC1C,OAAO,aAAa,0EAAc,EAClC,OAAO,eAAe,8HAA+B,EACrD,OAAO,mBAAmB,0DAAuB,EACjD;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC;AAAA,IACC,CAAC,YAKK;AACJ,WAAK,eAAe;AAAA,QAClB,KAAK,QAAQ;AAAA,QACb,OAAO,QAAQ;AAAA,QACf,KAAK,QAAQ;AAAA,QACb,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAEF,UACG,QAAQ,SAAS,EACjB,YAAY,iFAAyC,EACrD,OAAO,mBAAmB,4CAAS,EACnC,OAAO,aAAa,wDAAW,EAC/B,OAAO,YAAY,+DAA4B,EAC/C,OAAO,CAAC,YAAkE;AACzE,sBAAkB;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AAEH,UACG,QAAQ,aAAa,EACrB,YAAY,6GAAiD,EAC7D,OAAO,mBAAmB,4CAAS,EACnC,OAAO,cAAc,sCAAkB,EACvC,OAAO,WAAW,sCAAkB,EACpC,OAAO,YAAY,2BAAY,EAC/B;AAAA,IACC,CAAC,YAKK;AACJ,2BAAqB;AAAA,QACnB,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,OAAO,QAAQ;AAAA,QACf,QAAQ,QAAQ;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF;AAEF,UACG,QAAQ,OAAO,EACf;AAAA,IACC;AAAA,EACF,EACC,OAAO,mBAAmB,4CAAS,EACnC,OAAO,WAAW,qDAAkB,EACpC,OAAO,aAAa,4CAAS,EAC7B,OAAO,YAAY,2BAAY,EAC/B;AAAA,IACC,CAAC,YAKK;AACJ,WAAK,mBAAmB;AAAA,QACtB,KAAK,QAAQ;AAAA,QACb,OAAO,QAAQ;AAAA,QACf,QAAQ,QAAQ;AAAA,QAChB,QAAQ,QAAQ;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF;AAEF,UACG,QAAQ,QAAQ,EAChB,YAAY,wFAAqD,EACjE,OAAO,mBAAmB,4CAAS,EACnC,OAAO,YAAY,+DAA4B,EAC/C,OAAO,CAAC,YAAgD;AACvD,qBAAiB;AAAA,MACf,KAAK,QAAQ;AAAA,MACb,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AAEH,MAAI,QAAQ,KAAK,UAAU,GAAG;AAC5B,YAAQ,WAAW;AACnB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,MAAM,QAAQ,IAAI;AAC5B;AAEA,KAAK;","names":["join","dirname","join","join","existsSync","readFileSync","writeFileSync","join","readFileSync","text","existsSync","mkdirSync","readFileSync","dirname","join","join","dirname","existsSync","readFileSync","mkdirSync","existsSync","mkdirSync","readFileSync","writeFileSync","join","join","existsSync","mkdirSync","writeFileSync","readFileSync","readFileSync","writeFileSync","join","existsSync","readFileSync","writeFileSync","existsSync","readFileSync","resolve","spawn","dirname","join","fileURLToPath","existsSync","mkdirSync","readFileSync","rmSync","writeFileSync","existsSync","readFileSync","mkdirSync","writeFileSync","rmSync","readdirSync","readFileSync","join","readdirSync","join","readFileSync","readFileSync","readdirSync","join","readdirSync","join","readFileSync","input","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","dirname","mkdirSync","existsSync","writeFileSync","readFileSync","mkdirSync","renameSync","join","mkdirSync","renameSync","join","cliPath","join","dirname","fileURLToPath","spawn","existsSync","readdirSync","readFileSync","basename","join","resolve","existsSync","readdirSync","join","basename","existsSync","readdirSync","statSync","homedir","basename","join","resolve","existsSync","readdirSync","statSync","homedir","join","resolve","collectJsonlRecursive","existsSync","readdirSync","readFileSync","join","existsSync","readFileSync","readdirSync","join","resolve","mkdirSync","writeFileSync","join","existsSync","readFileSync","join","existsSync","readFileSync","dirname","join","fileURLToPath","readFileSync","dirname","join","fileURLToPath","dirname","fileURLToPath","join","existsSync","readFileSync","join","existsSync","readFileSync","mkdirSync","join","writeFileSync","mkdirSync","writeFileSync","join","existsSync","readFileSync","join","mkdirSync","join","writeFileSync","mkdirSync","writeFileSync","join","existsSync","readFileSync","join","join","existsSync","readFileSync","mkdirSync","join","writeFileSync","mkdirSync","writeFileSync","join","existsSync","readFileSync","join","join","existsSync","readFileSync","mkdirSync","join","writeFileSync","mkdirSync","writeFileSync","join","join","mkdirSync","writeFileSync","existsSync","readFileSync","existsSync","readFileSync","existsSync","readFileSync","writeFileSync","join","join","existsSync","readFileSync","writeFileSync","mkdirSync","writeFileSync","existsSync","readFileSync","existsSync","readFileSync","existsSync","readFileSync","writeFileSync","join","spliceHermesBlock","join","existsSync","writeFileSync","readFileSync","existsSync","writeFileSync","writeFileSync","mkdirSync","existsSync","readFileSync","resolve","existsSync","readFileSync","resolve","resolve"]}