@orquentra/codebuddy 2.8.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/{chunk-6DONJW3W.js → chunk-2WH2Q4TA.js} +22 -5
  2. package/dist/chunk-2WH2Q4TA.js.map +1 -0
  3. package/dist/{chunk-EJQVGFH2.js → chunk-ENKDFLOO.js} +2 -2
  4. package/dist/{chunk-ZNLSCV3J.js → chunk-F4BJ3DXW.js} +5 -5
  5. package/dist/{chunk-NY2YXP3R.js → chunk-QN76UJP7.js} +2 -2
  6. package/dist/{chunk-6KGYAFG7.js → chunk-SRA4MDVG.js} +2 -2
  7. package/dist/{chunk-6KGYAFG7.js.map → chunk-SRA4MDVG.js.map} +1 -1
  8. package/dist/{chunk-XL2HLACE.js → chunk-YN7TEIUH.js} +1 -1
  9. package/dist/chunk-YN7TEIUH.js.map +1 -0
  10. package/dist/cli/index.js +3 -3
  11. package/dist/index.js +5 -5
  12. package/dist/{main-QUASSFP7.js → main-YJKSYFPT.js} +638 -204
  13. package/dist/main-YJKSYFPT.js.map +1 -0
  14. package/dist/{operations-WJR7AZZF.js → operations-OG4ISWIM.js} +3 -3
  15. package/dist/{pretool-command-JTKX6G3M.js → pretool-command-PRFOIHMW.js} +3 -3
  16. package/dist/{runtime-OQQ22VJF.js → runtime-GCSEIAVD.js} +4 -4
  17. package/package.json +1 -1
  18. package/dist/chunk-6DONJW3W.js.map +0 -1
  19. package/dist/chunk-XL2HLACE.js.map +0 -1
  20. package/dist/main-QUASSFP7.js.map +0 -1
  21. /package/dist/{chunk-EJQVGFH2.js.map → chunk-ENKDFLOO.js.map} +0 -0
  22. /package/dist/{chunk-ZNLSCV3J.js.map → chunk-F4BJ3DXW.js.map} +0 -0
  23. /package/dist/{chunk-NY2YXP3R.js.map → chunk-QN76UJP7.js.map} +0 -0
  24. /package/dist/{operations-WJR7AZZF.js.map → operations-OG4ISWIM.js.map} +0 -0
  25. /package/dist/{pretool-command-JTKX6G3M.js.map → pretool-command-PRFOIHMW.js.map} +0 -0
  26. /package/dist/{runtime-OQQ22VJF.js.map → runtime-GCSEIAVD.js.map} +0 -0
@@ -13,7 +13,7 @@ import {
13
13
  llmMemoryOptions,
14
14
  readPolicyFile,
15
15
  resolveRiskPaths
16
- } from "./chunk-ZNLSCV3J.js";
16
+ } from "./chunk-F4BJ3DXW.js";
17
17
  import {
18
18
  SessionCapsuleLedger,
19
19
  coveringTestCandidates,
@@ -22,16 +22,16 @@ import {
22
22
  import {
23
23
  readTraces,
24
24
  recordTrace
25
- } from "./chunk-XL2HLACE.js";
25
+ } from "./chunk-YN7TEIUH.js";
26
26
  import {
27
27
  codeBuddyConfigSchema,
28
28
  createRuntime,
29
29
  listFactsPage
30
- } from "./chunk-NY2YXP3R.js";
30
+ } from "./chunk-QN76UJP7.js";
31
31
  import {
32
32
  MemoryFileStore,
33
33
  VERSION
34
- } from "./chunk-6KGYAFG7.js";
34
+ } from "./chunk-SRA4MDVG.js";
35
35
  import {
36
36
  generateGraphifyGraph,
37
37
  loadProjectArchitectureMap
@@ -172,6 +172,7 @@ function checksum(content) {
172
172
 
173
173
  // src/telemetry/telemetry.ts
174
174
  import { createHash as createHash2, randomUUID } from "crypto";
175
+ import { existsSync } from "fs";
175
176
  import { mkdir, readFile, writeFile } from "fs/promises";
176
177
  import { homedir } from "os";
177
178
  import { dirname, join } from "path";
@@ -286,6 +287,21 @@ async function flushTelemetry(repositoryRoot, options = {}) {
286
287
  return 0;
287
288
  }
288
289
  }
290
+ async function traceCliCommand(command, started, root = process.cwd()) {
291
+ if (/^\[(hook|admin)\]/.test(command.description()) || command.name() === "serve") return;
292
+ if (!existsSync(join(root, ".codebuddy"))) return;
293
+ const path = [];
294
+ for (let current = command; current?.parent; current = current.parent) {
295
+ path.unshift(current.name());
296
+ }
297
+ await recordTrace(root, {
298
+ kind: "cli",
299
+ name: path.join(".") || "use",
300
+ ms: Date.now() - started,
301
+ ok: !process.exitCode
302
+ });
303
+ await flushTelemetry(root);
304
+ }
289
305
  async function installedClients(repositoryRoot) {
290
306
  const { CLIENT_IDS } = await import("./adapters-S4HHTWJW.js");
291
307
  const { detectClient } = await import("./install-BXM56QCD.js");
@@ -1767,9 +1783,10 @@ export {
1767
1783
  TELEMETRY_NOTICE,
1768
1784
  showTelemetryNoticeOnce,
1769
1785
  flushTelemetry,
1786
+ traceCliCommand,
1770
1787
  generateSuggestions,
1771
1788
  mcpToolInputSchemas,
1772
1789
  registerCodeBuddyTools,
1773
1790
  startMcpServer
1774
1791
  };
1775
- //# sourceMappingURL=chunk-6DONJW3W.js.map
1792
+ //# sourceMappingURL=chunk-2WH2Q4TA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/migrate-to-files.ts","../src/telemetry/telemetry.ts","../src/mcp/tools/index.ts","../src/context/delivery.ts","../src/suggest/engine.ts","../src/suggest/types.ts","../src/mcp/tool-result.ts","../src/mcp/server.ts","../src/automation/project-sync.ts","../src/indexer/watch.ts","../src/core/project-root.ts","../src/mcp/database.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { redactPersisted } from \"../core/sensitive.js\";\nimport type { MemoryFileStore } from \"./memory-file-store.js\";\nimport type { MemoryRepository } from \"./repository.js\";\n\nexport type MigrationConflict = {\n kind: \"fact\" | \"summary\";\n id: string;\n databaseChecksum: string;\n fileChecksum: string;\n};\n\nexport type MigrationFailure = {\n kind: \"fact\" | \"summary\";\n id: string;\n error: string;\n};\n\nexport type MigrationPreview = {\n namespace: string;\n dryRun: boolean;\n facts: { found: number; existing: number; toWrite: number; conflicts: number; written: number };\n summaries: {\n found: number;\n existing: number;\n toWrite: number;\n conflicts: number;\n written: number;\n };\n conflicts: MigrationConflict[];\n failures: MigrationFailure[];\n};\n\nexport async function migrateMemoryToFiles(input: {\n repository: MemoryRepository;\n store: MemoryFileStore;\n namespace: string;\n write: boolean;\n}): Promise<MigrationPreview> {\n const namespace = await input.repository.getNamespaceByName(input.namespace);\n if (!namespace) {\n return {\n namespace: input.namespace,\n dryRun: !input.write,\n facts: { found: 0, existing: 0, toWrite: 0, conflicts: 0, written: 0 },\n summaries: { found: 0, existing: 0, toWrite: 0, conflicts: 0, written: 0 },\n conflicts: [],\n failures: [],\n };\n }\n\n const [facts, summaries, existingFacts, existingSummaries] = await Promise.all([\n input.repository.listFacts({ namespaceId: namespace.id, limit: 100_000 }),\n input.repository.listSummaries({ namespaceId: namespace.id, limit: 100_000 }),\n input.store.listFacts(),\n input.store.listSummaries(),\n ]);\n // The DB reads are hard-capped at 100k rows; a namespace at that ceiling\n // may be silently truncated. Say so instead of implying completeness.\n const warnings =\n facts.length >= 100_000 || summaries.length >= 100_000\n ? [\n \"namespace is at or above the 100,000-row read cap; the migration may be partial — prune or export in batches\",\n ]\n : [];\n const existingFactsById = new Map(existingFacts.map((fact) => [fact.id, fact]));\n const existingSummariesById = new Map(existingSummaries.map((summary) => [summary.id, summary]));\n const conflicts: MigrationConflict[] = [];\n const failures: MigrationFailure[] = [];\n const factsToWrite = facts.filter((fact) => {\n const existing = existingFactsById.get(fact.id);\n if (!existing) return true;\n // The file holds the redacted form, so compare against that.\n const databaseChecksum = checksum(redactPersisted(fact).content);\n const fileChecksum = checksum(existing.content);\n if (databaseChecksum !== fileChecksum) {\n conflicts.push({ kind: \"fact\", id: fact.id, databaseChecksum, fileChecksum });\n }\n return false;\n });\n const summariesToWrite = summaries.filter((summary) => {\n const existing = existingSummariesById.get(summary.id);\n if (!existing) return true;\n const databaseChecksum = checksum(summary.content);\n const fileChecksum = checksum(existing.content);\n if (databaseChecksum !== fileChecksum) {\n conflicts.push({ kind: \"summary\", id: summary.id, databaseChecksum, fileChecksum });\n }\n return false;\n });\n let factsWritten = 0;\n let summariesWritten = 0;\n\n if (input.write) {\n for (const fact of factsToWrite) {\n try {\n await input.store.writeFact({\n id: fact.id,\n namespace: input.namespace,\n subject: fact.subject,\n predicate: fact.predicate,\n object: fact.object,\n confidence: fact.confidence,\n createdAt: fact.createdAt.toISOString(),\n createdByAgent: fact.createdByAgent,\n sourceInteractionId: fact.sourceInteractionId,\n sourceDeleted: fact.sourceDeleted,\n supersededBy: fact.supersededBy,\n content: fact.content,\n });\n factsWritten += 1;\n } catch (error) {\n failures.push({ kind: \"fact\", id: fact.id, error: (error as Error).message });\n }\n }\n for (const summary of summariesToWrite) {\n try {\n await input.store.writeSummary({\n id: summary.id,\n namespace: input.namespace,\n sessionId: summary.sessionId,\n version: summary.version,\n tokenCount: summary.tokenCount,\n createdAt: summary.createdAt.toISOString(),\n createdByAgent: summary.createdByAgent,\n content: summary.content,\n });\n summariesWritten += 1;\n } catch (error) {\n failures.push({ kind: \"summary\", id: summary.id, error: (error as Error).message });\n }\n }\n }\n\n const factConflicts = conflicts.filter((conflict) => conflict.kind === \"fact\").length;\n const summaryConflicts = conflicts.length - factConflicts;\n return {\n namespace: input.namespace,\n dryRun: !input.write,\n ...(warnings.length > 0 ? { warnings } : {}),\n facts: {\n found: facts.length,\n existing: facts.length - factsToWrite.length - factConflicts,\n toWrite: factsToWrite.length,\n conflicts: factConflicts,\n written: factsWritten,\n },\n summaries: {\n found: summaries.length,\n existing: summaries.length - summariesToWrite.length - summaryConflicts,\n toWrite: summariesToWrite.length,\n conflicts: summaryConflicts,\n written: summariesWritten,\n },\n conflicts,\n failures,\n };\n}\n\nfunction checksum(content: string): string {\n return createHash(\"sha256\").update(content).digest(\"hex\");\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { readTraces, recordTrace } from \"../tracing/log.js\";\nimport { VERSION } from \"../version.js\";\n\n/**\n * Anonymous usage telemetry: the local traces (`tracing/log.ts`) reduced to\n * counts and timings and sent in batches to the collector\n * (`telemetry/collector.ts`). Never sent: prompts, recalled text, file paths,\n * repository names, trace `detail`, raw session ids. Nothing is sent until the\n * first-run notice has been shown on a terminal, and never under\n * `CODEBUDDY_TELEMETRY=0`, `DO_NOT_TRACK=1`, `CI`, or `codebuddy telemetry\n * disable`. Every failure is silent: telemetry never breaks a tool or a hook.\n */\n\n/** Where installs send batches (`codebuddy collector` behind `tailscale funnel`). Empty = off. */\nexport const TELEMETRY_URL = \"https://tanmay-hp-linux-server.tail41864f.ts.net/v1/events\";\n\n/** One batch at most this often per project. */\nconst FLUSH_INTERVAL_MS = 10 * 60_000;\nconst MAX_EVENTS = 500;\nconst SEND_TIMEOUT_MS = 3_000;\nconst NAME = /^[A-Za-z][A-Za-z0-9_:.-]{0,63}$/;\n\nexport type TelemetryState = { installId: string; noticeAt?: string; disabled?: boolean };\n\nexport type TelemetryEvent = {\n ts: string;\n kind: string;\n name: string;\n ms: number;\n ok: boolean;\n tokensIn?: number;\n tokensOut?: number;\n session?: string;\n};\n\nexport type TelemetryBatch = {\n installId: string;\n project: string;\n version: string;\n platform: string;\n arch: string;\n node: string;\n clients: string[];\n events: TelemetryEvent[];\n};\n\nexport function telemetryStatePath(home = homedir()): string {\n return join(home, \".codebuddy\", \"telemetry.json\");\n}\n\n/** The machine's state, created with a fresh random install id on first read. */\nexport async function readTelemetryState(home = homedir()): Promise<TelemetryState> {\n try {\n const state = JSON.parse(await readFile(telemetryStatePath(home), \"utf8\")) as TelemetryState;\n if (typeof state.installId === \"string\" && state.installId) return state;\n } catch {\n // Missing or corrupt: start over with a new id.\n }\n return writeTelemetryState({ installId: randomUUID() }, home);\n}\n\nexport async function writeTelemetryState(\n state: TelemetryState,\n home = homedir(),\n): Promise<TelemetryState> {\n const path = telemetryStatePath(home);\n await mkdir(dirname(path), { recursive: true, mode: 0o700 });\n await writeFile(path, `${JSON.stringify(state, null, 2)}\\n`, { mode: 0o600 });\n return state;\n}\n\n/** Why telemetry is off, or null when it may send. */\nexport function telemetryBlocked(\n state: TelemetryState,\n env: NodeJS.ProcessEnv = process.env,\n): string | null {\n if (env.CODEBUDDY_TELEMETRY === \"0\") return \"CODEBUDDY_TELEMETRY=0\";\n if (env.DO_NOT_TRACK === \"1\" || env.DO_NOT_TRACK === \"true\") return \"DO_NOT_TRACK\";\n if (env.CI) return \"CI\";\n if (state.disabled) return \"disabled with `codebuddy telemetry disable`\";\n if (!telemetryUrl(env)) return \"no collector configured\";\n if (!state.noticeAt) return \"first-run notice not shown yet\";\n return null;\n}\n\nexport function telemetryUrl(env: NodeJS.ProcessEnv = process.env): string {\n return env.CODEBUDDY_TELEMETRY_URL ?? TELEMETRY_URL;\n}\n\nexport const TELEMETRY_NOTICE = `CodeBuddy collects anonymous usage data (which tools run, how long they take,\nsuccess/failure, version, OS, agent client) to improve the product.\nPrompts, code, file paths and repository names are never sent.\nOpt out any time: \\`codebuddy telemetry disable\\` or CODEBUDDY_TELEMETRY=0.\nDetails: https://github.com/Orquentra-Inc/CodeBuddy/blob/main/docs/telemetry.md`;\n\n/** Print the notice once per machine, only on an interactive terminal. */\nexport async function showTelemetryNoticeOnce(\n write: (text: string) => void = (text) => process.stderr.write(text),\n options: { home?: string; env?: NodeJS.ProcessEnv; tty?: boolean } = {},\n): Promise<void> {\n const env = options.env ?? process.env;\n if (!(options.tty ?? process.stderr.isTTY)) return;\n try {\n const state = await readTelemetryState(options.home);\n if (state.noticeAt || state.disabled || env.CODEBUDDY_TELEMETRY === \"0\" || env.CI) return;\n if (!telemetryUrl(env)) return;\n write(`\\n${TELEMETRY_NOTICE}\\n\\n`);\n await writeTelemetryState({ ...state, noticeAt: new Date().toISOString() }, options.home);\n } catch {\n // An unwritable home directory only means no notice, and so nothing is sent.\n }\n}\n\n/** Salted so the collector can count projects and sessions without learning names. */\nfunction anonymize(installId: string, value: string): string {\n return createHash(\"sha256\").update(`${installId}\\0${value}`).digest(\"hex\").slice(0, 16);\n}\n\n/** The anonymous subset of a local trace. Free-form names become `other`. */\nexport function toTelemetryEvents(\n installId: string,\n traces: Awaited<ReturnType<typeof readTraces>>,\n): TelemetryEvent[] {\n return traces.map((trace) => ({\n ts: trace.ts,\n kind: NAME.test(trace.kind) ? trace.kind : \"other\",\n name: NAME.test(trace.name) ? trace.name : \"other\",\n ms: Math.max(0, Math.round(trace.ms) || 0),\n ok: trace.ok === true,\n ...(typeof trace.tokensIn === \"number\" ? { tokensIn: trace.tokensIn } : {}),\n ...(typeof trace.tokensOut === \"number\" ? { tokensOut: trace.tokensOut } : {}),\n ...(trace.session ? { session: anonymize(installId, trace.session) } : {}),\n }));\n}\n\ntype Cursor = { sentTs?: string; flushedAt?: number };\n\n/**\n * Send this project's traces recorded since the last successful batch. At most\n * one attempt per `FLUSH_INTERVAL_MS`; a failed send is retried next interval.\n * Returns the number of events the collector accepted.\n */\nexport async function flushTelemetry(\n repositoryRoot: string,\n options: {\n home?: string;\n env?: NodeJS.ProcessEnv;\n now?: number;\n fetchImpl?: typeof fetch;\n clients?: () => Promise<string[]>;\n } = {},\n): Promise<number> {\n const env = options.env ?? process.env;\n const now = options.now ?? Date.now();\n try {\n const state = await readTelemetryState(options.home);\n if (telemetryBlocked(state, env)) return 0;\n const cursorPath = join(repositoryRoot, \".codebuddy\", \"cache\", \"telemetry.json\");\n const cursor = await readFile(cursorPath, \"utf8\")\n .then((raw) => JSON.parse(raw) as Cursor)\n .catch((): Cursor => ({}));\n if (cursor.flushedAt && now - cursor.flushedAt < FLUSH_INTERVAL_MS) return 0;\n // Claim the interval first, so concurrent hook processes do not all send.\n const save = (next: Cursor) =>\n mkdir(dirname(cursorPath), { recursive: true }).then(() =>\n writeFile(cursorPath, JSON.stringify(next)),\n );\n await save({ ...cursor, flushedAt: now });\n\n const pending = (await readTraces(repositoryRoot, 10_000))\n .filter((trace) => !cursor.sentTs || trace.ts > cursor.sentTs)\n .slice(-MAX_EVENTS);\n const last = pending.at(-1);\n if (!last) return 0;\n const batch: TelemetryBatch = {\n installId: state.installId,\n project: anonymize(state.installId, repositoryRoot),\n version: VERSION,\n platform: process.platform,\n arch: process.arch,\n node: process.versions.node.split(\".\")[0] ?? \"\",\n clients: await (options.clients ?? (() => installedClients(repositoryRoot)))().catch(\n () => [],\n ),\n events: toTelemetryEvents(state.installId, pending),\n };\n const response = await (options.fetchImpl ?? fetch)(telemetryUrl(env), {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(batch),\n signal: AbortSignal.timeout(SEND_TIMEOUT_MS),\n });\n if (!response.ok) return 0;\n await save({ sentTs: last.ts, flushedAt: now });\n return batch.events.length;\n } catch {\n return 0;\n }\n}\n\ntype CommandLike = { name(): string; description(): string; parent: CommandLike | null };\n\n/**\n * After a CLI command in a CodeBuddy project: trace it (`kind: cli`, the\n * command path such as `hooks.install`, never its arguments) and flush. Hook\n * runtime (`[hook]`), `[admin]` and `serve` commands are skipped: hooks and\n * MCP tools trace themselves. Outside a project nothing is written.\n */\nexport async function traceCliCommand(\n command: CommandLike,\n started: number,\n root = process.cwd(),\n): Promise<void> {\n if (/^\\[(hook|admin)\\]/.test(command.description()) || command.name() === \"serve\") return;\n if (!existsSync(join(root, \".codebuddy\"))) return;\n const path: string[] = [];\n for (let current: CommandLike | null = command; current?.parent; current = current.parent) {\n path.unshift(current.name());\n }\n await recordTrace(root, {\n kind: \"cli\",\n name: path.join(\".\") || \"use\",\n ms: Date.now() - started,\n ok: !process.exitCode,\n });\n await flushTelemetry(root);\n}\n\n/** Agent clients wired into this project (hooks or MCP config). */\nasync function installedClients(repositoryRoot: string): Promise<string[]> {\n const { CLIENT_IDS } = await import(\"../clients/adapters.js\");\n const { detectClient } = await import(\"../clients/install.js\");\n const found: string[] = [];\n for (const id of CLIENT_IDS) {\n const status = await detectClient(id, repositoryRoot).catch(() => null);\n if (status && (status.hooks || status.mcp)) found.push(id);\n }\n return found;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { applySessionDelivery, type DeliveryOptions } from \"../../context/delivery.js\";\nimport { loadProjectArchitectureMap } from \"../../context/discovery.js\";\nimport { buildBeforeEditContext, buildBootstrapContext } from \"../../context/engine.js\";\nimport type { CodeBuddy } from \"../../core/codebuddy.js\";\nimport { loadPlanPolicy } from \"../../core/config-file.js\";\nimport { listFactsPage } from \"../../core/operations.js\";\nimport { PlanFileStore } from \"../../core/plan-file-store.js\";\nimport { PlanLifecycle } from \"../../core/plan-lifecycle.js\";\nimport type { MemoryRepository } from \"../../core/repository.js\";\nimport type {\n CodeBuddyConfig,\n RecallInput,\n RecallResult,\n RememberInput,\n} from \"../../core/types.js\";\nimport { llmMemoryOptions } from \"../../hooks/runtime.js\";\nimport { configuredReranker } from \"../../hooks/semantic.js\";\nimport { loadFreshIndex } from \"../../indexer/engine.js\";\nimport { neighbours, queryMap } from \"../../map/indexer.js\";\nimport { captureAfterTurn } from \"../../memory-extract/engine.js\";\nimport { assessRisk } from \"../../risk/service.js\";\nimport { estimateTokens } from \"../../savings/tokens.js\";\nimport { generateSuggestions } from \"../../suggest/engine.js\";\nimport { recordTrace } from \"../../tracing/log.js\";\nimport type { DatabaseServices, LazyDatabase } from \"../database.js\";\nimport { serializeToolResult } from \"../tool-result.js\";\n\n/**\n * Input caps. The output side is bounded (LIMITS in the context engine,\n * list_facts ≤ 100); the input side must be too — one tool call should never\n * push megabytes of content into Postgres, the embedding queue, or a plan\n * file that later flows back into agent context.\n */\nconst INPUT_LIMITS = {\n contentChars: 32_000,\n batchItems: 100,\n summaryChars: 32_000,\n planBodyChars: 64_000,\n planBriefChars: 4_000,\n titleChars: 300,\n arrayItems: 100,\n pathChars: 1_024,\n taskChars: 2_000,\n agentIdChars: 200,\n /** Entity ids and list cursors are short; a megabyte one is never valid. */\n idChars: 512,\n} as const;\n\n/** Optional session-aware delivery fields shared by the context tools. */\nconst deliverySchema = {\n sessionId: z.string().min(1).max(200).optional(),\n ack: z\n .string()\n .regex(/^dlv_[a-z0-9]+$/)\n .optional(),\n full: z.boolean().optional(),\n};\n\n/** PostgreSQL text rejects U+0000; fail validation, not with a raw SQL error. */\nconst pgText = (max: number) =>\n z\n .string()\n .min(1)\n .max(max)\n .refine((value) => !value.includes(\"\\u0000\"), \"must not contain NUL bytes\");\n\nconst rememberSchema = {\n sessionId: pgText(200).optional(),\n content: pgText(INPUT_LIMITS.contentChars),\n type: z.enum([\"interaction\", \"fact\", \"summary\"]).optional(),\n idempotencyKey: pgText(200).optional(),\n agentId: pgText(INPUT_LIMITS.agentIdChars).optional(),\n};\n\nconst recallSchema = {\n sessionId: pgText(200),\n query: pgText(INPUT_LIMITS.taskChars),\n budget: z.number().int().positive().optional(),\n callerModel: z.string().min(1).max(200).optional(),\n conflictMode: z.enum([\"all\", \"latest\", \"highest_confidence\"]).optional(),\n /** Return only system, message id + content and core stats (no provenance). */\n compact: z.boolean().optional(),\n};\n\nconst shareSchema = {\n from: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n to_namespace: z.string().min(1).max(INPUT_LIMITS.agentIdChars),\n factIds: z.array(z.string().min(1).max(100)).min(1).max(INPUT_LIMITS.arrayItems),\n mode: z.enum([\"reference\", \"snapshot\"]).optional(),\n /** Snapshot mode: the target project's root; its Markdown store receives the copy. */\n to_project_root: z.string().min(1).max(INPUT_LIMITS.pathChars).optional(),\n agentId: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n};\n\nconst unshareSchema = {\n to_namespace: z.string().min(1).max(INPUT_LIMITS.agentIdChars),\n factIds: z.array(z.string().min(1).max(100)).min(1).max(INPUT_LIMITS.arrayItems),\n agentId: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n};\n\nconst plannedFileSchema = z.object({\n path: z.string().min(1).max(INPUT_LIMITS.pathChars),\n action: z.enum([\"create\", \"edit\", \"delete\"]),\n notes: z.string().max(INPUT_LIMITS.taskChars).optional(),\n});\nconst plannedTestSchema = z.object({\n path: z.string().min(1).max(INPUT_LIMITS.pathChars),\n description: z.string().max(INPUT_LIMITS.taskChars).optional(),\n});\nconst planPatchSchema = {\n title: z.string().min(1).max(INPUT_LIMITS.titleChars).optional(),\n brief: z.string().max(INPUT_LIMITS.planBriefChars).optional(),\n body: z.string().max(INPUT_LIMITS.planBodyChars).optional(),\n filesToTouch: z.array(plannedFileSchema).max(INPUT_LIMITS.arrayItems).optional(),\n testsToAdd: z.array(plannedTestSchema).max(INPUT_LIMITS.arrayItems).optional(),\n outOfScope: z\n .array(z.string().max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n risks: z.array(z.string().max(INPUT_LIMITS.taskChars)).max(INPUT_LIMITS.arrayItems).optional(),\n};\n\nexport const mcpToolInputSchemas = {\n remember: z.object(rememberSchema),\n remember_batch: z.object({\n items: z.array(z.object(rememberSchema)).min(1).max(INPUT_LIMITS.batchItems),\n }),\n recall: z.object(recallSchema),\n list_facts: z.object({\n subject: z.string().max(INPUT_LIMITS.titleChars).optional(),\n limit: z.number().int().positive().max(100).default(50),\n cursor: z.string().max(INPUT_LIMITS.idChars).optional(),\n }),\n list_namespaces: z.object({}),\n forget: z.object({ id: z.string().min(1).max(INPUT_LIMITS.idChars) }),\n share: z.object(shareSchema),\n unshare: z.object(unshareSchema),\n plan_current: z.object({}),\n plan_create: z.object({\n title: z.string().min(1).max(INPUT_LIMITS.titleChars),\n brief: z.string().min(1).max(INPUT_LIMITS.planBriefChars),\n body: z.string().max(INPUT_LIMITS.planBodyChars).optional(),\n filesToTouch: z.array(plannedFileSchema).max(INPUT_LIMITS.arrayItems).optional(),\n testsToAdd: z.array(plannedTestSchema).max(INPUT_LIMITS.arrayItems).optional(),\n outOfScope: z\n .array(z.string().max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n risks: z.array(z.string().max(INPUT_LIMITS.taskChars)).max(INPUT_LIMITS.arrayItems).optional(),\n agentId: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n }),\n plan_amend: z.object({ id: z.string().min(1), patch: z.object(planPatchSchema) }),\n plan_status: z.object({\n id: z.string().min(1),\n status: z.enum([\"approved\", \"executing\", \"complete\", \"abandoned\"]),\n commitSha: z.string().optional(),\n notes: z.string().optional(),\n reason: z.string().optional(),\n }),\n risk_assess: z.object({\n planId: z.string().min(1).max(100).optional(),\n paths: z\n .array(z.string().min(1).max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n evidence: z.enum([\"overview\", \"source\"]).optional(),\n useGit: z.boolean().optional(),\n limit: z.number().int().positive().max(100).optional(),\n }),\n map_query: z.object({\n from: z.string().min(1).max(INPUT_LIMITS.pathChars).optional(),\n to: z.string().min(1).max(INPUT_LIMITS.pathChars).optional(),\n limit: z.number().int().positive().max(100).optional(),\n }),\n map_neighbours: z.object({\n module: z.string().min(1).max(INPUT_LIMITS.pathChars),\n direction: z.enum([\"in\", \"out\", \"both\"]).default(\"both\"),\n }),\n context_bootstrap: z.object({ ...deliverySchema }),\n context_before_edit: z.object({\n task: z.string().min(1).max(INPUT_LIMITS.taskChars).optional(),\n paths: z\n .array(z.string().min(1).max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n planId: z.string().min(1).max(100).optional(),\n evidence: z.enum([\"overview\", \"source\"]).optional(),\n useGit: z.boolean().optional(),\n tokenBudget: z.number().int().positive().max(100_000).optional(),\n ...deliverySchema,\n }),\n context_pack: z.object({\n task: z.string().min(1).max(INPUT_LIMITS.taskChars),\n paths: z\n .array(z.string().min(1).max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n planId: z.string().min(1).max(100).optional(),\n evidence: z.enum([\"overview\", \"source\"]).optional(),\n useGit: z.boolean().optional(),\n tokenBudget: z.number().int().positive().max(100_000).optional(),\n ...deliverySchema,\n }),\n context_after_turn: z.object({\n summary: z.string().min(1).max(INPUT_LIMITS.summaryChars),\n changedFiles: z\n .array(z.string().min(1).max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n planId: z.string().min(1).max(100).optional(),\n taskType: z.string().min(1).max(100).optional(),\n agentId: z.string().min(1).max(INPUT_LIMITS.agentIdChars).optional(),\n sessionId: z.string().min(1).max(200).optional(),\n verification: z.array(z.string().min(1).max(500)).max(20).optional(),\n commitSha: z.string().min(7).max(64).optional(),\n }),\n code_suggestions: z.object({\n paths: z\n .array(z.string().min(1).max(INPUT_LIMITS.pathChars))\n .max(INPUT_LIMITS.arrayItems)\n .optional(),\n planId: z.string().min(1).max(100).optional(),\n evidence: z.enum([\"overview\", \"source\"]).optional(),\n useGit: z.boolean().optional(),\n limit: z.number().int().positive().max(100).optional(),\n }),\n health: z.object({}),\n} as const;\n\n/** Tools that need PostgreSQL; every other tool is file-based. */\nconst DATABASE_TOOLS = [\n \"remember\",\n \"remember_batch\",\n \"recall\",\n \"list_facts\",\n \"list_namespaces\",\n \"forget\",\n \"share\",\n \"unshare\",\n];\nconst FILE_TOOLS = Object.keys(mcpToolInputSchemas).filter(\n (name) => !DATABASE_TOOLS.includes(name),\n);\nconst DEGRADED_FALLBACK =\n \"PostgreSQL is unavailable, so this call did nothing. File-based tools still work; read the repository directly and say recall is unavailable instead of guessing. Run `codebuddy db doctor` to diagnose; the next call after retryInMs reconnects.\";\n\n/**\n * Client tool profiles (#45). `full` (default) lists every tool; `core` lists\n * only the automatic context workflow, so a client pays a fraction of the\n * tool-schema tokens per session. Set `CODEBUDDY_TOOL_PROFILE=core` in the\n * client's MCP server environment.\n */\nexport type ToolProfile = \"core\" | \"full\";\nexport const CORE_TOOLS = [\n \"context_pack\",\n \"context_bootstrap\",\n \"context_before_edit\",\n \"context_after_turn\",\n \"code_suggestions\",\n \"health\",\n];\n\nexport function resolveToolProfile(value = process.env.CODEBUDDY_TOOL_PROFILE): ToolProfile {\n if (value === undefined || value === \"\" || value === \"full\") return \"full\";\n if (value === \"core\") return \"core\";\n throw new Error(`CODEBUDDY_TOOL_PROFILE must be \"core\" or \"full\", got \"${value}\"`);\n}\n\nexport type RegisterCodeBuddyToolsOptions =\n | { memory: CodeBuddy; repository: MemoryRepository }\n | {\n /** File-based tools read only namespace/projectRoot/tokenBudget from this. */\n config: Pick<CodeBuddyConfig, \"namespace\"> & {\n projectRoot?: string | undefined;\n tokenBudget?: number | undefined;\n };\n /** Optional PostgreSQL services; database tools degrade while it is unavailable. */\n database: Pick<LazyDatabase, \"get\" | \"status\">;\n };\n\n/** Cap plan bodies returned over MCP so a huge plan can't blow the context. */\nconst PLAN_BODY_LIMIT = 8_000;\n\nfunction serializePlan(plan: import(\"../../core/plan-file-store.js\").PlanSpec | null) {\n if (!plan) return { plan: null };\n const body =\n plan.body.length > PLAN_BODY_LIMIT\n ? `${plan.body.slice(0, PLAN_BODY_LIMIT)}\\n\\n…[truncated]`\n : plan.body;\n return { plan: { ...plan, body } };\n}\n\nexport function registerCodeBuddyTools(\n server: McpServer,\n options: RegisterCodeBuddyToolsOptions,\n profile: ToolProfile = \"full\",\n) {\n const exposed = (name: string) => profile === \"full\" || CORE_TOOLS.includes(name);\n // Every tool is defined once; tools outside the profile are dropped from tools/list.\n const config = \"database\" in options ? options.config : options.memory.config;\n const traceRoot = config.projectRoot ?? process.cwd();\n // Every tool is traced here, once, for `codebuddy dashboard`.\n const register: McpServer[\"registerTool\"] = (name, toolConfig, callback) => {\n const traced = (async (...args: unknown[]) => {\n const started = Date.now();\n const input = args.length > 1 ? (args[0] as { sessionId?: unknown }) : undefined;\n const trace = (ok: boolean, output?: string) =>\n void recordTrace(traceRoot, {\n kind: \"tool\",\n name,\n ms: Date.now() - started,\n ok,\n tokensIn: estimateTokens(input),\n tokensOut: estimateTokens(output),\n ...(typeof input?.sessionId === \"string\" ? { session: input.sessionId } : {}),\n });\n try {\n const result = (await (callback as (...a: unknown[]) => Promise<unknown>)(...args)) as {\n content?: Array<{ text?: string }>;\n isError?: boolean;\n };\n trace(result?.isError !== true, result?.content?.map((part) => part.text ?? \"\").join(\"\"));\n return result;\n } catch (error) {\n trace(false);\n throw error;\n }\n }) as typeof callback;\n const tool = server.registerTool(name, toolConfig, traced);\n if (!exposed(name)) tool.remove();\n return tool;\n };\n const json = serializeToolResult;\n\n const database: Pick<LazyDatabase, \"get\" | \"status\"> =\n \"database\" in options\n ? options.database\n : { get: async () => options, status: () => ({ available: true, state: \"ready\" }) };\n /** Run a database tool, or return an explicit, bounded degraded result. */\n const viaDatabase = async (tool: string, run: (db: DatabaseServices) => Promise<unknown>) => {\n let db: DatabaseServices;\n try {\n db = await database.get();\n } catch {\n return {\n ...json({ degraded: true, tool, database: database.status(), fallback: DEGRADED_FALLBACK }),\n isError: true,\n };\n }\n return json(await run(db));\n };\n\n const namespace = config.namespace;\n const projectRoot = config.projectRoot ?? process.cwd();\n const rankContextFacts = async (\n task: string,\n candidates: Array<{ id: string; text: string }>,\n ) => {\n // File context never starts or waits for an unavailable database connection.\n if (database.status().state !== \"ready\") return {};\n try {\n const { memory } = await database.get();\n return await memory.rankContextFacts(\n task,\n candidates.map(({ id }) => id),\n );\n } catch {\n return {};\n }\n };\n // Read once per server: `rerank` changes take effect on the next restart.\n const reranker = configuredReranker(projectRoot).catch(() => undefined);\n const rerankerOption = async () => {\n const configured = await reranker;\n return configured ? { reranker: configured } : {};\n };\n const planStore = new PlanFileStore(projectRoot);\n const planLifecycle = new PlanLifecycle(planStore);\n const toFiles = (\n items?: Array<{\n path: string;\n action: \"create\" | \"edit\" | \"delete\";\n notes?: string | undefined;\n }>,\n ) => items?.map((item) => ({ path: item.path, action: item.action, notes: item.notes ?? \"\" }));\n const toTests = (items?: Array<{ path: string; description?: string | undefined }>) =>\n items?.map((item) => ({ path: item.path, description: item.description ?? \"\" }));\n\n register(\n \"remember\",\n {\n title: \"Remember\",\n description: \"Store one CodeBuddy memory item.\",\n inputSchema: mcpToolInputSchemas.remember.shape,\n },\n async (input) => viaDatabase(\"remember\", (db) => db.memory.remember(toRememberInput(input))),\n );\n\n register(\n \"remember_batch\",\n {\n title: \"Remember batch\",\n description: \"Store multiple CodeBuddy memory items.\",\n inputSchema: mcpToolInputSchemas.remember_batch.shape,\n },\n async (input) =>\n viaDatabase(\"remember_batch\", async (db) => ({\n items: await db.memory.rememberBatch(input.items.map(toRememberInput)),\n })),\n );\n\n register(\n \"recall\",\n {\n title: \"Recall\",\n description:\n \"Recall prompt-ready CodeBuddy context. `budget` bounds message content (stats.tokensUsed); stats.responseTokens counts the whole JSON text returned (provenance and stats included) and stats.transportTokens the full tool result, which also repeats it as structuredContent. Pass compact=true for only message id + content.\",\n inputSchema: mcpToolInputSchemas.recall.shape,\n },\n async (input) =>\n viaDatabase(\"recall\", async (db) =>\n withResponseTokens(await db.memory.recall(toRecallInput(input)), input.compact === true),\n ),\n );\n\n register(\n \"list_facts\",\n {\n title: \"List facts\",\n description: \"List facts in the configured namespace.\",\n inputSchema: mcpToolInputSchemas.list_facts.shape,\n },\n async (input) =>\n viaDatabase(\"list_facts\", (db) =>\n listFactsPage(\n db.memory,\n db.repository,\n cleanOptional(input) as { subject?: string; limit?: number; cursor?: string },\n ),\n ),\n );\n\n register(\n \"list_namespaces\",\n {\n title: \"List namespaces\",\n description: \"List CodeBuddy namespaces.\",\n inputSchema: mcpToolInputSchemas.list_namespaces.shape,\n },\n async () =>\n viaDatabase(\"list_namespaces\", async (db) => ({\n namespaces: await db.repository.listNamespaces(),\n })),\n );\n\n register(\n \"forget\",\n {\n title: \"Forget\",\n description: \"Delete an interaction or fact by id.\",\n inputSchema: mcpToolInputSchemas.forget.shape,\n },\n async (input) => viaDatabase(\"forget\", (db) => db.memory.forget(input.id)),\n );\n\n register(\n \"share\",\n {\n title: \"Share\",\n description:\n \"Share facts from the configured namespace to another namespace. Reference (default) is a live, revocable grant; snapshot copies the fact into the target project's Markdown store (requires to_project_root).\",\n inputSchema: mcpToolInputSchemas.share.shape,\n },\n async (input) =>\n viaDatabase(\"share\", (db) =>\n db.memory.share({\n from: input.from ?? namespace,\n to: input.to_namespace,\n factIds: input.factIds,\n ...(input.mode ? { mode: input.mode } : {}),\n ...(input.to_project_root ? { targetProjectRoot: input.to_project_root } : {}),\n ...(input.agentId ? { agentId: input.agentId } : {}),\n }),\n ),\n );\n\n register(\n \"unshare\",\n {\n title: \"Unshare\",\n description:\n \"Revoke live reference shares of configured-namespace facts to another namespace.\",\n inputSchema: mcpToolInputSchemas.unshare.shape,\n },\n async (input) =>\n viaDatabase(\"unshare\", (db) =>\n db.memory.unshare({\n to: input.to_namespace,\n factIds: input.factIds,\n ...(input.agentId ? { agentId: input.agentId } : {}),\n }),\n ),\n );\n\n // ── Plan tools (Proposal 02.6) ────────────────────────────────────\n register(\n \"plan_current\",\n {\n title: \"Current plan\",\n description: \"Return the active (approved or executing) plan for this namespace, or null.\",\n inputSchema: mcpToolInputSchemas.plan_current.shape,\n },\n async () => {\n const [current, policy] = await Promise.all([\n planLifecycle.current(namespace),\n loadPlanPolicy(projectRoot),\n ]);\n return json({ ...serializePlan(current), policy });\n },\n );\n\n register(\n \"plan_create\",\n {\n title: \"Create plan\",\n description: \"Create a draft plan in this namespace.\",\n inputSchema: mcpToolInputSchemas.plan_create.shape,\n },\n async (input) => {\n const files = toFiles(input.filesToTouch);\n const tests = toTests(input.testsToAdd);\n const created = await planLifecycle.create({\n namespace,\n title: input.title,\n brief: input.brief,\n ...(input.body !== undefined ? { body: input.body } : {}),\n ...(files ? { filesToTouch: files } : {}),\n ...(tests ? { testsToAdd: tests } : {}),\n ...(input.outOfScope !== undefined ? { outOfScope: input.outOfScope } : {}),\n ...(input.risks !== undefined ? { risks: input.risks } : {}),\n ...(input.agentId !== undefined ? { createdByAgent: input.agentId } : {}),\n });\n return json(serializePlan(created));\n },\n );\n\n register(\n \"plan_amend\",\n {\n title: \"Amend plan\",\n description: \"Amend a draft or executing plan's content fields.\",\n inputSchema: mcpToolInputSchemas.plan_amend.shape,\n },\n async (input) => {\n const patch = input.patch;\n const files = toFiles(patch.filesToTouch);\n const tests = toTests(patch.testsToAdd);\n const amended = await planLifecycle.amend(input.id, {\n ...(patch.title !== undefined ? { title: patch.title } : {}),\n ...(patch.brief !== undefined ? { brief: patch.brief } : {}),\n ...(patch.body !== undefined ? { body: patch.body } : {}),\n ...(files ? { filesToTouch: files } : {}),\n ...(tests ? { testsToAdd: tests } : {}),\n ...(patch.outOfScope !== undefined ? { outOfScope: patch.outOfScope } : {}),\n ...(patch.risks !== undefined ? { risks: patch.risks } : {}),\n });\n return json(serializePlan(amended));\n },\n );\n\n register(\n \"plan_status\",\n {\n title: \"Transition plan\",\n description: \"Move a plan through its lifecycle: approved, executing, complete, abandoned.\",\n inputSchema: mcpToolInputSchemas.plan_status.shape,\n },\n async (input) => {\n let next: import(\"../../core/plan-file-store.js\").PlanSpec;\n if (input.status === \"approved\") next = await planLifecycle.approve(input.id);\n else if (input.status === \"executing\") next = await planLifecycle.start(input.id);\n else if (input.status === \"complete\")\n next = await planLifecycle.complete(input.id, {\n ...(input.commitSha !== undefined ? { commitSha: input.commitSha } : {}),\n ...(input.notes !== undefined ? { notes: input.notes } : {}),\n });\n else\n next = await planLifecycle.abandon(\n input.id,\n input.reason !== undefined ? { reason: input.reason } : {},\n );\n return json(serializePlan(next));\n },\n );\n\n register(\n \"risk_assess\",\n {\n title: \"Assess risk\",\n description: \"Assess evidence-backed risk for a plan, explicit paths, or git changes.\",\n inputSchema: mcpToolInputSchemas.risk_assess.shape,\n },\n async (input) =>\n json(\n await assessRisk({\n repositoryRoot: projectRoot,\n namespace,\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n ...(input.limit !== undefined ? { limit: input.limit } : {}),\n }),\n ),\n );\n\n register(\n \"map_query\",\n {\n title: \"Query architecture map\",\n description: \"Query lightweight module import edges in the current repository.\",\n inputSchema: mcpToolInputSchemas.map_query.shape,\n },\n async (input) => {\n const graph = await cachedMap();\n return json(\n queryMap(graph, {\n ...(input.from !== undefined ? { from: input.from } : {}),\n ...(input.to !== undefined ? { to: input.to } : {}),\n ...(input.limit !== undefined ? { limit: input.limit } : {}),\n }),\n );\n },\n );\n\n register(\n \"map_neighbours\",\n {\n title: \"Module neighbours\",\n description: \"Return inbound/outbound neighbours for a repository module.\",\n inputSchema: mcpToolInputSchemas.map_neighbours.shape,\n },\n async (input) => json(neighbours(await cachedMap(), input.module, input.direction)),\n );\n\n // ── Context engine tools (Proposal 04.2) ──────────────────────────\n const tokenBudget = config.tokenBudget;\n\n /**\n * The same map the context engine uses: the import-map cache\n * (`.codebuddy/cache/architecture.json`) merged with fresh Graphify\n * relations when Graphify is enabled. The index is validated against current\n * source first so edited imports are re-read.\n */\n const cachedMap = async () =>\n loadProjectArchitectureMap(\n projectRoot,\n loadFreshIndex(projectRoot).then(({ manifest }) => manifest),\n );\n\n register(\n \"context_bootstrap\",\n {\n title: \"Bootstrap project context\",\n description:\n \"Return compact project awareness for the start of a turn: identity, active plan and policy, top policy rules, incident hotspots, and an architecture summary. Prefer this over a manual recall at session start. Optional sessionId enables session-aware delivery: pass the previous response's delivery.deliveryId as ack and unchanged sections are omitted (listed in delivery.unchanged); pass full=true to get everything again.\",\n inputSchema: mcpToolInputSchemas.context_bootstrap.shape,\n },\n async (input) =>\n json(\n await applySessionDelivery(\n projectRoot,\n await buildBootstrapContext({\n repositoryRoot: projectRoot,\n namespace,\n ...(tokenBudget !== undefined ? { tokenBudget } : {}),\n }),\n deliveryOptions(input),\n ),\n ),\n );\n\n register(\n \"context_before_edit\",\n {\n title: \"Context before edit\",\n description:\n \"Assemble relevant context before changing code: resolves target files from paths, a plan, or git, then returns the relevant plan, matching policy rules, incident memory, an evidence-backed risk assessment, and import neighbours. Optional sessionId enables session-aware delivery: pass the previous response's delivery.deliveryId as ack and unchanged sections are omitted (listed in delivery.unchanged); pass full=true to get everything again.\",\n inputSchema: mcpToolInputSchemas.context_before_edit.shape,\n },\n async (input) =>\n json(\n await applySessionDelivery(\n projectRoot,\n await buildBeforeEditContext({\n repositoryRoot: projectRoot,\n namespace,\n semanticRanker: rankContextFacts,\n ...(await rerankerOption()),\n ...(input.evidence ? { evidence: input.evidence } : {}),\n ...(input.task !== undefined ? { task: input.task } : {}),\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n ...(input.tokenBudget !== undefined ? { tokenBudget: input.tokenBudget } : {}),\n ...(tokenBudget !== undefined && input.tokenBudget === undefined\n ? { tokenBudget }\n : {}),\n }),\n deliveryOptions(input),\n ),\n ),\n );\n\n register(\n \"context_pack\",\n {\n title: \"Build task context pack\",\n description:\n \"Build the smallest useful context pack for a coding task. Automatically finds relevant files from the local index when paths are omitted, then includes only bounded symbols, policies, risks, incidents, architecture neighbours, and relevant team facts within the requested token budget. Use this once at the start of a task instead of manually chaining context, risk, map, and memory tools. Request evidence=source with exact paths when short excerpts omit needed behavior; source excerpts remain bounded by the token budget. Optional sessionId enables session-aware delivery: pass the previous response's delivery.deliveryId as ack and unchanged sections are omitted (listed in delivery.unchanged); pass full=true to get everything again.\",\n inputSchema: mcpToolInputSchemas.context_pack.shape,\n },\n async (input) =>\n json(\n await applySessionDelivery(\n projectRoot,\n await buildBeforeEditContext({\n repositoryRoot: projectRoot,\n namespace,\n task: input.task,\n semanticRanker: rankContextFacts,\n ...(await rerankerOption()),\n ...(input.evidence ? { evidence: input.evidence } : {}),\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n tokenBudget: input.tokenBudget ?? tokenBudget ?? 4_000,\n }),\n deliveryOptions(input),\n ),\n ),\n );\n\n register(\n \"context_after_turn\",\n {\n title: \"Capture context after a turn\",\n description:\n \"Extract durable knowledge from a turn summary. Confident facts/decisions/incidents are auto-saved as Markdown; temporary notes, low-confidence, and sensitive items are queued for review under .codebuddy/memory/review/; chatter is ignored. Never saves sensitive content automatically. Turns that changed files or report verification also record a bounded worklog handoff under .codebuddy/worklog/ so later chats can recover the work.\",\n inputSchema: mcpToolInputSchemas.context_after_turn.shape,\n },\n async (input) => {\n const result = await captureAfterTurn(\n {\n summary: input.summary,\n namespace,\n ...(input.changedFiles !== undefined ? { changedFiles: input.changedFiles } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.taskType !== undefined ? { taskType: input.taskType } : {}),\n ...(input.agentId !== undefined ? { agentId: input.agentId } : {}),\n ...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),\n ...(input.verification !== undefined ? { verification: input.verification } : {}),\n ...(input.commitSha !== undefined ? { commitSha: input.commitSha } : {}),\n },\n {\n repositoryRoot: projectRoot,\n ...((input.changedFiles?.length ?? 0) > 0 ? await llmMemoryOptions(projectRoot) : {}),\n },\n );\n // Capture writes reviewable Markdown first. Import it immediately so\n // database recall and the embedding worker see the same memory without\n // requiring a restart or a manual `codebuddy reindex`. Without a\n // database the Markdown is still saved and imported on reconnect.\n const db = await database.get().catch(() => undefined);\n await db?.memory.reindexMemory({ respace: false });\n return json({\n saved: result.saved.map((d) => ({\n id: d.ref,\n class: d.candidate.class,\n subject: d.candidate.subject,\n })),\n queuedForReview: result.queuedForReview.map((d) => ({\n id: d.ref,\n class: d.candidate.class,\n reason: d.reason,\n sensitive: d.sensitive,\n })),\n ignored: result.ignored.length,\n reasons: result.reasons,\n extractor: result.extractor,\n worklogId: result.worklogId,\n ...(db ? {} : { degraded: true, database: database.status() }),\n });\n },\n );\n\n register(\n \"code_suggestions\",\n {\n title: \"Code suggestions\",\n description:\n \"Return read-only, evidence-backed code-quality suggestions for a change set (paths, a plan, or git). Composes risk, plan divergence, architecture blast radius, incident history, missing tests, and stale policies. Never edits code.\",\n inputSchema: mcpToolInputSchemas.code_suggestions.shape,\n },\n async (input) =>\n json(\n await generateSuggestions({\n repositoryRoot: projectRoot,\n namespace,\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n ...(input.limit !== undefined ? { limit: input.limit } : {}),\n }),\n ),\n );\n\n register(\n \"health\",\n {\n title: \"Health\",\n description:\n \"Report which CodeBuddy tools are available right now: file-based tools always work; database tools (recall, remember, facts) need PostgreSQL. Does not wait on a connection attempt.\",\n inputSchema: mcpToolInputSchemas.health.shape,\n },\n async () =>\n json({\n database: database.status(),\n tools: {\n profile,\n file: FILE_TOOLS.filter(exposed),\n database: DATABASE_TOOLS.filter(exposed),\n },\n }),\n );\n}\n\nfunction deliveryOptions(input: {\n sessionId?: string | undefined;\n ack?: string | undefined;\n full?: boolean | undefined;\n}): DeliveryOptions {\n return cleanOptional(input as Record<string, unknown>) as DeliveryOptions;\n}\n\nfunction toRememberInput(input: z.infer<typeof mcpToolInputSchemas.remember>): RememberInput {\n return cleanOptional(input) as RememberInput;\n}\n\nfunction toRecallInput(input: z.infer<typeof mcpToolInputSchemas.recall>): RecallInput {\n const { compact: _compact, ...rest } = input;\n return cleanOptional(rest) as RecallInput;\n}\n\n/**\n * `stats.tokensUsed` counts message content only (the budget contract); the\n * response also carries provenance, stats and JSON framing. Report what is\n * really sent: `responseTokens` for the JSON text, `transportTokens` for the\n * whole tool result (structuredContent repeats the payload).\n */\nfunction withResponseTokens(result: RecallResult, compact: boolean) {\n const stats: Record<string, unknown> = compact\n ? {\n tokensUsed: result.stats.tokensUsed,\n itemsIncluded: result.stats.itemsIncluded,\n itemsSkipped: result.stats.itemsSkipped,\n ...(result.stats.budgetStatus ? { budgetStatus: result.stats.budgetStatus } : {}),\n }\n : { ...result.stats };\n const value = compact\n ? {\n system: result.system,\n messages: result.messages.map((message) => ({\n ...(message.fact ? { id: message.fact.id } : {}),\n content: message.content,\n })),\n stats,\n }\n : { ...result, stats };\n // Two passes: the counts are part of the text they count.\n for (let pass = 0; pass < 2; pass++) {\n const serialized = serializeToolResult(value);\n stats.responseTokens = estimateTokens(serialized.content[0]?.text);\n stats.transportTokens = estimateTokens(serialized);\n }\n return value;\n}\n\nfunction cleanOptional(input: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined));\n}\n","import { createHash } from \"node:crypto\";\nimport { estimateTokens } from \"../savings/tokens.js\";\nimport { enforceContextBudget } from \"./budget.js\";\nimport { SessionCapsuleLedger } from \"./session-ledger.js\";\n\n/**\n * Session-aware delivery for the MCP context tools. With a `sessionId`, a\n * section whose exact content the client already confirmed receiving (via\n * `ack`) in this session is omitted and listed in `delivery.unchanged`; the\n * ledger keeps a few acknowledged versions per section, so switching back to\n * an earlier task does not resend what the client still holds. Without a\n * `sessionId` the payload is returned untouched, so clients without session\n * support always get complete context.\n *\n * Safety evidence that changes per call (target paths, risks, diffs) is never\n * omitted. Any ledger failure falls back to the full payload.\n */\n\n/** Delivery contract version, bumped on any incompatible change. */\nexport const DELIVERY_VERSION = 1;\n\n/** Sections that may be omitted when unchanged. Everything else is always sent. */\nconst OMITTABLE_SECTIONS = [\n \"plan\",\n \"policyRules\",\n \"incidents\",\n \"facts\",\n \"rules\",\n \"handoffs\",\n \"architecture\",\n \"symbols\",\n \"neighbours\",\n] as const;\n\n/**\n * An acknowledged section is only treated as already-seen for this long; after\n * that it is resent, bounding how stale a client's copy can get.\n */\nconst SESSION_TTL_MS = 30 * 60 * 1000;\n\nexport type DeliveryOptions = {\n sessionId?: string;\n /** The `deliveryId` of the previous response the client actually received. */\n ack?: string;\n /** Resend every section, e.g. after the client's context was compacted. */\n full?: boolean;\n};\n\nexport type DeliveryInfo = {\n version: typeof DELIVERY_VERSION;\n sessionId: string;\n deliveryId: string;\n ack: \"none\" | \"accepted\" | \"unknown\";\n unchanged: string[];\n avoidedTokens: number;\n note: string;\n};\n\nexport async function applySessionDelivery(\n repositoryRoot: string,\n payload: object,\n options: DeliveryOptions,\n): Promise<Record<string, unknown>> {\n let output: Record<string, unknown> = { ...payload };\n if (!options.sessionId) return output;\n\n // Keys stay `mcp:`-prefixed on purpose, separate from the hook capsule keys\n // (`plan`, `fact:<id>`, ...) in the same session ledger. The hook block sends\n // bounded one-line renderings marked on write; these hashes cover the full\n // JSON section and count only once acknowledged. A shared key would let a\n // clipped hook line suppress a full section it never carried, or the two\n // paths overwrite each other's records. The paths share only reset.\n const sections = OMITTABLE_SECTIONS.filter((key) => output[key] !== undefined).map((key) => ({\n key: `mcp:${key}`,\n hash: createHash(\"sha256\").update(JSON.stringify(output[key])).digest(\"hex\"),\n }));\n\n try {\n await new SessionCapsuleLedger(repositoryRoot).exchange(options.sessionId, sections, {\n ...(options.ack !== undefined ? { ack: options.ack } : {}),\n ttlMs: SESSION_TTL_MS,\n ...(options.full ? { full: true } : {}),\n prepare: (exchange) => {\n const unchanged = exchange.unchanged.map((key) => key.slice(\"mcp:\".length));\n let avoidedTokens = 0;\n for (const key of unchanged) {\n avoidedTokens += estimateTokens(output[key]);\n delete output[key];\n }\n const delivery: DeliveryInfo = {\n version: DELIVERY_VERSION,\n sessionId: options.sessionId as string,\n deliveryId: exchange.deliveryId,\n ack: exchange.ack,\n unchanged,\n avoidedTokens,\n note: \"Pass deliveryId as ack. Use full=true after losing context.\",\n };\n output.delivery = delivery;\n output = enforceContextBudget(output);\n // Hash what was actually delivered. A section shortened or omitted by\n // the budget must never acknowledge its original, complete version.\n return OMITTABLE_SECTIONS.filter((key) => output[key] !== undefined).map((key) => ({\n key: `mcp:${key}`,\n hash: createHash(\"sha256\").update(JSON.stringify(output[key])).digest(\"hex\"),\n }));\n },\n });\n return output;\n } catch {\n return enforceContextBudget({ ...payload });\n }\n}\n","import { constants } from \"node:fs\";\nimport { access } from \"node:fs/promises\";\nimport { extname, join, resolve } from \"node:path\";\nimport { coveringTestCandidates } from \"../context/tests.js\";\nimport { MemoryFileStore } from \"../core/memory-file-store.js\";\nimport { PlanFileStore, type PlanSpec } from \"../core/plan-file-store.js\";\nimport { PlanLifecycle } from \"../core/plan-lifecycle.js\";\nimport { buildArchitectureMap } from \"../map/indexer.js\";\nimport type { ArchitectureMap } from \"../map/types.js\";\nimport { assessRisk, resolveRiskPaths } from \"../risk/service.js\";\nimport { readPolicyFile } from \"../risk/signals/policy.js\";\nimport { SEVERITY_RANK, type Suggestion, type SuggestResult } from \"./types.js\";\n\n/**\n * Deterministic, read-only suggestion generation. Nothing here writes to disk\n * or edits code — it only reads the working tree and CodeBuddy's own artifacts.\n * Each category attaches its own evidence; anything without evidence is not\n * emitted. Findings are de-duplicated per (category, path) and ranked by\n * severity so the few important ones surface first.\n */\n\nconst RISK_SUGGEST_THRESHOLD = 50;\nconst BLAST_RADIUS_MEDIUM = 5;\nconst BLAST_RADIUS_HIGH = 10;\nconst CODE_EXTENSIONS = new Set([\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".py\"]);\n\nexport type SuggestInput = {\n repositoryRoot?: string;\n namespace: string;\n paths?: string[];\n planId?: string;\n useGit?: boolean;\n limit?: number;\n};\n\nexport async function generateSuggestions(input: SuggestInput): Promise<SuggestResult> {\n const repositoryRoot = resolve(input.repositoryRoot ?? process.cwd());\n const namespace = input.namespace;\n\n const targetPaths = await resolveRiskPaths({\n repositoryRoot,\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n });\n\n const planStore = new PlanFileStore(repositoryRoot);\n const memoryStore = new MemoryFileStore(repositoryRoot);\n\n const [risks, plan, incidents, map, policyFile] = await Promise.all([\n assessRisk({\n repositoryRoot,\n namespace,\n ...(input.paths !== undefined ? { paths: input.paths } : {}),\n ...(input.planId !== undefined ? { planId: input.planId } : {}),\n ...(input.useGit !== undefined ? { useGit: input.useGit } : {}),\n }),\n resolveRelevantPlan(planStore, namespace, input.planId),\n memoryStore.findIncidentFactsForPaths({ namespace, paths: targetPaths }),\n buildArchitectureMap(repositoryRoot),\n readPolicyFile(join(repositoryRoot, \".codebuddy\", \"policies.yaml\")),\n ]);\n\n const suggestions: Suggestion[] = [];\n\n // 1. Risk — surface the change set's highest-scoring paths.\n for (const item of risks.items) {\n if (item.score < RISK_SUGGEST_THRESHOLD) continue;\n suggestions.push({\n id: `risk:${item.path}`,\n category: \"risk\",\n severity: item.score >= 75 ? \"high\" : \"medium\",\n title: `Review high-risk change to ${item.path}`,\n detail: item.reason,\n path: item.path,\n evidence: [\n { kind: \"risk_score\", detail: `score ${item.score} (${item.category})` },\n ...(item.evidence.length > 0\n ? [{ kind: \"risk_evidence\", detail: `${item.evidence.length} evidence item(s)` }]\n : []),\n ],\n commandHint: `codebuddy risk assess --paths ${item.path} --explain`,\n });\n }\n\n // 2. Incident history — files with an unresolved past incident.\n for (const incident of incidents) {\n const path = incident.paths[0] ?? \"(unknown)\";\n suggestions.push({\n id: `incident:${path}`,\n category: \"incident\",\n severity: \"high\",\n title: `Recurring incident hotspot: ${path}`,\n detail: `${incident.subject} — proceed carefully; this area has an unresolved incident.`,\n path,\n evidence: [{ kind: \"incident\", detail: `${incident.id} severity=${incident.severity}` }],\n });\n }\n\n // 3. Architecture — high blast radius (many dependents).\n const inbound = inboundDegrees(map);\n for (const path of targetPaths) {\n const dependents = inbound.get(path) ?? 0;\n if (dependents < BLAST_RADIUS_MEDIUM) continue;\n suggestions.push({\n id: `architecture:${path}`,\n category: \"architecture\",\n severity: dependents >= BLAST_RADIUS_HIGH ? \"high\" : \"medium\",\n title: `High blast radius: ${path}`,\n detail: `${dependents} module(s) import ${path}; a change here ripples widely.`,\n path,\n evidence: [{ kind: \"dependents\", detail: `${dependents} inbound import(s)` }],\n commandHint: `codebuddy map dependents ${path}`,\n });\n }\n\n // 4. Plan divergence — editing files the active plan does not cover.\n if (plan) {\n const planned = new Set(plan.filesToTouch.map((file) => normalize(file.path)));\n const strays = targetPaths.filter((path) => !planned.has(normalize(path)));\n if (planned.size > 0 && strays.length > 0) {\n suggestions.push({\n id: `plan_divergence:${plan.id}`,\n category: \"plan_divergence\",\n severity: \"medium\",\n title: `Change set diverges from plan ${plan.id}`,\n detail: `${strays.length} target file(s) are outside the active plan's scope: ${strays\n .slice(0, 5)\n .join(\", \")}.`,\n evidence: [\n { kind: \"plan\", detail: `plan ${plan.id} (${plan.status})` },\n { kind: \"out_of_scope\", detail: strays.slice(0, 5).join(\", \") },\n ],\n commandHint: `codebuddy plan show ${plan.id}`,\n });\n }\n }\n\n // 5. Missing tests — changed code files with no discoverable test.\n for (const path of targetPaths) {\n if (!isTestableCode(path)) continue;\n if (await hasSiblingTest(repositoryRoot, path)) continue;\n suggestions.push({\n id: `missing_test:${path}`,\n category: \"missing_test\",\n severity: \"low\",\n title: `No test found for ${path}`,\n detail: \"Consider adding a test alongside this change.\",\n path,\n evidence: [{ kind: \"no_test\", detail: \"no conventional test file found\" }],\n });\n }\n\n // 6. Stale policy — a rule whose target directory no longer exists.\n for (const rule of policyFile.rules) {\n const prefix = literalPrefix(rule.pattern);\n if (!prefix) continue;\n if (await pathExists(join(repositoryRoot, prefix))) continue;\n suggestions.push({\n id: `stale_policy:${rule.id}`,\n category: \"stale_policy\",\n severity: \"low\",\n title: `Stale policy rule \"${rule.id}\"`,\n detail: `Pattern \"${rule.pattern}\" targets \"${prefix}\", which does not exist.`,\n evidence: [{ kind: \"policy_rule\", detail: `${rule.id} → ${rule.pattern}` }],\n });\n }\n\n const deduped = dedupe(suggestions).sort(compareSuggestions);\n const limited = input.limit ? deduped.slice(0, input.limit) : deduped;\n\n return {\n suggestions: limited,\n stats: buildStats(targetPaths.length, limited),\n };\n}\n\n// ── helpers ─────────────────────────────────────────────────────────\n\nasync function resolveRelevantPlan(\n store: PlanFileStore,\n namespace: string,\n planId?: string,\n): Promise<PlanSpec | null> {\n if (planId) {\n try {\n return await store.readPlan(planId);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return null;\n throw error;\n }\n }\n return new PlanLifecycle(store).current(namespace);\n}\n\nfunction inboundDegrees(map: ArchitectureMap): Map<string, number> {\n const inbound = new Map<string, number>();\n for (const edge of map.edges) inbound.set(edge.to, (inbound.get(edge.to) ?? 0) + 1);\n return inbound;\n}\n\nfunction isTestableCode(path: string): boolean {\n if (/\\.(test|spec)\\.[cm]?[jt]sx?$/.test(path)) return false;\n if (path.endsWith(\".d.ts\")) return false;\n if (path.includes(\"__tests__/\")) return false;\n // Python tests, fixtures and package markers are not modules to cover.\n if (/(^|\\/)(test_[^/]*|[^/]*_test|conftest|__init__)\\.py$|(^|\\/)tests?\\/.*\\.py$/.test(path)) {\n return false;\n }\n return CODE_EXTENSIONS.has(extname(path).toLowerCase());\n}\n\nasync function hasSiblingTest(repositoryRoot: string, path: string): Promise<boolean> {\n for (const candidate of coveringTestCandidates(path)) {\n if (await pathExists(join(repositoryRoot, candidate))) return true;\n }\n return false;\n}\n\n/**\n * The literal directory prefix of a glob — everything before the first\n * wildcard, trimmed to a whole path segment. `src/auth/**` → `src/auth`,\n * `src/**​/*.ts` → `src`, `*.env` → `` (no literal prefix to check).\n */\nfunction literalPrefix(pattern: string): string {\n const normalized = normalize(pattern);\n const wildcard = normalized.search(/[*?[]/);\n if (wildcard === -1) return normalized.replace(/\\/+$/, \"\");\n const beforeWildcard = normalized.slice(0, wildcard);\n const lastSlash = beforeWildcard.lastIndexOf(\"/\");\n return lastSlash === -1 ? \"\" : beforeWildcard.slice(0, lastSlash);\n}\n\nfunction dedupe(suggestions: Suggestion[]): Suggestion[] {\n const byId = new Map<string, Suggestion>();\n for (const suggestion of suggestions) {\n const existing = byId.get(suggestion.id);\n if (!existing || SEVERITY_RANK[suggestion.severity] > SEVERITY_RANK[existing.severity]) {\n byId.set(suggestion.id, suggestion);\n }\n }\n return [...byId.values()];\n}\n\nfunction compareSuggestions(left: Suggestion, right: Suggestion): number {\n const severity = SEVERITY_RANK[right.severity] - SEVERITY_RANK[left.severity];\n if (severity !== 0) return severity;\n if (left.category !== right.category) return left.category.localeCompare(right.category);\n return (left.path ?? \"\").localeCompare(right.path ?? \"\");\n}\n\nfunction buildStats(pathsConsidered: number, suggestions: Suggestion[]) {\n const byCategory: Record<string, number> = {};\n const bySeverity: Record<string, number> = {};\n for (const suggestion of suggestions) {\n byCategory[suggestion.category] = (byCategory[suggestion.category] ?? 0) + 1;\n bySeverity[suggestion.severity] = (bySeverity[suggestion.severity] ?? 0) + 1;\n }\n return { pathsConsidered, produced: suggestions.length, byCategory, bySeverity };\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction normalize(path: string): string {\n return path.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n","/**\n * Suggestion model (Proposal 04 Phase 04.6). The suggestion engine reads the\n * signals CodeBuddy already computes — risk, the active plan, the architecture\n * map, incident memory — plus a couple of deterministic checks (missing tests,\n * stale policies) and turns them into a short list of evidence-backed, severity-\n * ranked suggestions. It is strictly read-only: it never edits code, and it\n * never emits a suggestion without evidence. The bias is a careful senior\n * reviewer, not a noisy linter — few strong findings over many weak ones.\n */\n\nexport const SUGGESTION_CATEGORIES = [\n \"risk\",\n \"plan_divergence\",\n \"architecture\",\n \"incident\",\n \"missing_test\",\n \"stale_policy\",\n] as const;\nexport type SuggestionCategory = (typeof SUGGESTION_CATEGORIES)[number];\n\nexport const SUGGESTION_SEVERITIES = [\"info\", \"low\", \"medium\", \"high\"] as const;\nexport type SuggestionSeverity = (typeof SUGGESTION_SEVERITIES)[number];\n\n/** Every suggestion cites at least one of these. No evidence, no suggestion. */\nexport type SuggestionEvidence = {\n kind: string;\n detail: string;\n};\n\nexport type Suggestion = {\n /** Stable id (`category:path`) so a UI can dedupe and track across runs. */\n id: string;\n category: SuggestionCategory;\n severity: SuggestionSeverity;\n title: string;\n detail: string;\n path?: string;\n evidence: SuggestionEvidence[];\n /** Optional follow-up command, e.g. `codebuddy risk assess --paths …`. */\n commandHint?: string;\n};\n\nexport type SuggestionStats = {\n pathsConsidered: number;\n produced: number;\n byCategory: Record<string, number>;\n bySeverity: Record<string, number>;\n};\n\nexport type SuggestResult = {\n suggestions: Suggestion[];\n stats: SuggestionStats;\n};\n\nexport const SEVERITY_RANK: Record<SuggestionSeverity, number> = {\n high: 3,\n medium: 2,\n low: 1,\n info: 0,\n};\n","/** Preserve compatibility by default; hosts forwarding both forms can select text. */\nexport function serializeToolResult(\n value: unknown,\n format = process.env.CODEBUDDY_RESPONSE_FORMAT ?? \"both\",\n) {\n if (format !== \"text\" && format !== \"both\") {\n throw new Error('CODEBUDDY_RESPONSE_FORMAT must be \"text\" or \"both\"');\n }\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(value) }],\n ...(format === \"both\" && value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? { structuredContent: value as Record<string, unknown> }\n : {}),\n };\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport pino from \"pino\";\nimport { startProjectSync } from \"../automation/project-sync.js\";\nimport type { CodeBuddy } from \"../core/codebuddy.js\";\nimport { codeBuddyConfigSchema } from \"../core/config.js\";\nimport { loadRuntimeConfig } from \"../core/config-file.js\";\nimport { createRuntime } from \"../core/operations.js\";\nimport { resolveInitializedProjectRoot } from \"../core/project-root.js\";\nimport type { CodeBuddyConfig } from \"../core/types.js\";\nimport { flushTelemetry } from \"../telemetry/telemetry.js\";\nimport { VERSION } from \"../version.js\";\nimport { createLazyDatabase } from \"./database.js\";\nimport { serializeToolResult } from \"./tool-result.js\";\nimport { registerCodeBuddyTools, resolveToolProfile } from \"./tools/index.js\";\n\nexport type StartMcpServerOptions = {\n config?: CodeBuddyConfig;\n};\n\nexport async function startMcpServer(options: StartMcpServerOptions = {}): Promise<void> {\n const logger = pino({ level: process.env.LOG_LEVEL ?? \"info\" }, process.stderr);\n let projectRoot: string;\n try {\n projectRoot = await resolveInitializedProjectRoot(\n options.config?.projectRoot ?? process.env.CODEBUDDY_PROJECT_ROOT,\n );\n } catch (error) {\n // Exiting here shows up in the client only as \"server failed to connect\".\n // Stay connected instead, scan nothing, and explain the fix through the\n // `health` tool and the server instructions the agent reads.\n logger.error((error as Error).message);\n await startSetupServer((error as Error).message);\n return;\n }\n const config = {\n ...(options.config ?? (await loadRuntimeConfig(projectRoot, { requireDatabase: false }))),\n projectRoot,\n };\n // Invalid config is a startup error; a missing or unreachable database is not.\n (config.postgresUrl\n ? codeBuddyConfigSchema\n : codeBuddyConfigSchema.omit({ postgresUrl: true })\n ).parse(config);\n const toolProfile = resolveToolProfile();\n // PostgreSQL is optional: file-based tools are served immediately and the\n // database tools report a degraded result until a connection succeeds.\n // A failed or partial memory import must not hide the healthy file-only\n // context, so it is logged, never thrown.\n // `respace` only on connect (server start): a hand edit re-importing live\n // must not re-queue another install's vectors on every file change.\n const importMemory = async (memory: CodeBuddy, respace: boolean) => {\n try {\n const result = await memory.reindexMemory(respace ? {} : { respace: false });\n for (const failure of result.failures) {\n logger.error(`[sync] memory file skipped (${failure.id}): ${failure.error}`);\n }\n } catch (error) {\n logger.error(`[sync] Markdown memory import failed: ${(error as Error).message}`);\n }\n };\n const database = createLazyDatabase(async () => {\n try {\n const runtime = await createRuntime(config, { autoBootstrap: true }).catch(\n (error: unknown) => {\n // The bundled Docker Postgres may simply be stopped (Docker restarted,\n // container removed): start it once in the background (an image pull\n // can take a minute) and fail this attempt now, so database tools\n // answer \"degraded\" at once instead of waiting; once it is up, a\n // retry connects.\n void startBundledPostgres(config.postgresUrl, error, logger).then((started) => {\n if (started) retryUntilConnected();\n });\n throw error;\n },\n );\n await importMemory(runtime.memory, true);\n logger.info(\"PostgreSQL connected; memory tools available\");\n return runtime;\n } catch (error) {\n logger.warn(\n `PostgreSQL unavailable; serving file-based tools only: ${(error as Error).message}`,\n );\n throw error;\n }\n });\n void database.get().catch(() => undefined);\n // After starting the container: PostgreSQL needs a few seconds to accept\n // connections, so retry (past the lazy cooldown) for up to two minutes.\n const retryUntilConnected = (attempt = 0) => {\n if (attempt >= 20 || database.status().state === \"ready\") return;\n setTimeout(() => {\n void database.get().then(\n () => undefined,\n () => retryUntilConnected(attempt + 1),\n );\n }, 6_000).unref();\n };\n const sync = startProjectSync({\n repositoryRoot: projectRoot,\n ...(config.graphify ? { graphify: config.graphify } : {}),\n logger,\n // Hand edits re-import live once PostgreSQL is connected; until then the\n // next successful connect imports everything.\n onMemoryChange: async () => {\n if (database.status().state === \"ready\") {\n await importMemory((await database.get()).memory, false);\n }\n },\n });\n const server = new McpServer({ name: \"codebuddy\", version: VERSION });\n registerCodeBuddyTools(server, { config, database }, toolProfile);\n // Anonymous usage batches; flushTelemetry itself throttles to one per 10 minutes.\n const telemetry = setInterval(() => void flushTelemetry(projectRoot), 60_000);\n telemetry.unref();\n\n const shutdown = async () => {\n logger.info(\"codebuddy MCP server shutting down\");\n clearInterval(telemetry);\n await server.close();\n await sync.close();\n await database.close();\n };\n let stopping: Promise<void> | undefined;\n const stop = () => {\n stopping ??= shutdown().finally(() => process.exit(0));\n };\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n // EOF on stdin means the client is gone; without this the server outlives it.\n process.stdin.once(\"end\", stop);\n\n try {\n await sync.ready;\n await server.connect(new StdioServerTransport());\n } catch (error) {\n await sync.close();\n await database.close();\n throw error;\n }\n logger.info(`codebuddy MCP server started over stdio (tool profile: ${toolProfile})`);\n}\n\n/**\n * Connected, but unconfigured: one `health` tool and MCP instructions that say\n * why no project is served and how to fix it. No file is indexed or read.\n */\nasync function startSetupServer(problem: string): Promise<void> {\n const fix = [\n \"Open your project folder in a terminal and run `codebuddy use` (or `codebuddy init`) if it has no .codebuddy/config.json.\",\n \"Then register CodeBuddy from that folder so the client starts it there: `codebuddy claude install` (Claude Desktop) or `codebuddy codex install` (Codex), and restart the client.\",\n \"Or set CODEBUDDY_PROJECT_ROOT to the project's absolute path in this server's env.\",\n ];\n const server = new McpServer(\n { name: \"codebuddy\", version: VERSION },\n {\n instructions: `CodeBuddy is connected but not serving a project: ${problem} To fix it: ${fix.join(\" \")}`,\n },\n );\n server.registerTool(\n \"health\",\n {\n title: \"Health\",\n description:\n \"Report CodeBuddy's status. This server has no project yet; the result says why and how to fix it.\",\n },\n async () => serializeToolResult({ ok: false, project: null, problem, fix }),\n );\n const stop = () => void server.close().finally(() => process.exit(0));\n process.once(\"SIGINT\", stop);\n process.once(\"SIGTERM\", stop);\n process.stdin.once(\"end\", stop);\n await server.connect(new StdioServerTransport());\n}\n\nlet triedBundledPostgres = false;\n\n/**\n * When PostgreSQL refuses connections at the bundled default address\n * (localhost:5432, user codebuddy), start the bundled container once per\n * process: `docker start codebuddy-postgres`, or `docker compose up -d` when\n * the container was removed (its data volume is reused). Never starts Docker\n * itself. CODEBUDDY_DOCKER_AUTOSTART=0 turns this off.\n */\nexport async function startBundledPostgres(\n postgresUrl: string,\n error: unknown,\n logger: Pick<pino.Logger, \"info\" | \"warn\">,\n): Promise<boolean> {\n if (triedBundledPostgres || process.env.CODEBUDDY_DOCKER_AUTOSTART === \"0\") return false;\n if (!isBundledPostgres(postgresUrl) || !isConnectionRefused(error)) return false;\n triedBundledPostgres = true;\n const { isDockerDaemonRunning } = await import(\"../cli/commands/docker-autostart.js\");\n if (!(await isDockerDaemonRunning())) {\n logger.warn(\n \"PostgreSQL is down and Docker is not running; start Docker Desktop, then `codebuddy postgres up`.\",\n );\n return false;\n }\n const { execFile } = await import(\"node:child_process\");\n const started = await new Promise<boolean>((done) =>\n execFile(\"docker\", [\"start\", \"codebuddy-postgres\"], { timeout: 30_000 }, (failed) =>\n done(failed === null),\n ),\n );\n if (started) {\n logger.info(\"Started the stopped codebuddy-postgres container; retrying PostgreSQL.\");\n return true;\n }\n const { postgresUp } = await import(\"../cli/commands/postgres-docker.js\");\n const result = await postgresUp().catch(() => ({ code: 1, stderr: \"docker compose failed\" }));\n if (result.code === 0) {\n logger.info(\"Started the bundled PostgreSQL container; retrying PostgreSQL.\");\n return true;\n }\n logger.warn(\n `Could not start the bundled PostgreSQL container: ${String(result.stderr).trim().slice(0, 200)}`,\n );\n return false;\n}\n\n/** The address `codebuddy use` / docker-compose.yml set up. */\nexport function isBundledPostgres(postgresUrl: string): boolean {\n try {\n const url = new URL(postgresUrl);\n return (\n [\"localhost\", \"127.0.0.1\", \"::1\", \"[::1]\"].includes(url.hostname) &&\n (url.port === \"\" || url.port === \"5432\") &&\n url.username === \"codebuddy\"\n );\n } catch {\n return false;\n }\n}\n\nfunction isConnectionRefused(error: unknown): boolean {\n for (\n let current = error as { code?: unknown; cause?: unknown; errors?: unknown[] } | undefined;\n current;\n ) {\n if (current.code === \"ECONNREFUSED\") return true;\n if (\n Array.isArray(current.errors) &&\n current.errors.some((inner) => isConnectionRefused(inner))\n ) {\n return true;\n }\n current = current.cause as typeof current;\n }\n return false;\n}\n","import { type FSWatcher, watch as fsWatch } from \"node:fs\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport { indexRepository } from \"../indexer/engine.js\";\nimport { createCoalescer, watchRepository } from \"../indexer/watch.js\";\nimport { generateGraphifyGraph } from \"../integrations/graphify.js\";\nimport { refreshZvecIndex, type ZvecRefresh } from \"../retrieval/zvec.js\";\n\nexport type ProjectSyncOptions = {\n repositoryRoot: string;\n graphify?: { enabled: boolean; graphPath?: string | undefined };\n logger?: Pick<Console, \"info\" | \"error\">;\n /**\n * Called (coalesced) when a managed Markdown memory file changes. The owner\n * of the database runtime re-imports memory; sync itself never needs it.\n */\n onMemoryChange?: () => Promise<void>;\n};\n\nexport type ProjectSyncHandle = {\n ready: Promise<void>;\n close(): Promise<void>;\n};\n\n/**\n * Owns all derived project state. A running MCP server should never require a\n * user or an agent to remember `index`, `graphify`, or `reindex` commands.\n */\nexport function startProjectSync(options: ProjectSyncOptions): ProjectSyncHandle {\n const repositoryRoot = resolve(options.repositoryRoot);\n const logger = options.logger ?? console;\n const controller = new AbortController();\n let watcher: Promise<void> | null = null;\n let closing = false;\n let memoryWatcher: FSWatcher | null = null;\n let memoryRefresh: ReturnType<typeof createCoalescer> | null = null;\n\n /** Run a derived-state refresh in the background, coalescing overlapping requests. */\n const backgroundRefresh = (task: () => Promise<void>) => {\n let current: Promise<void> | null = null;\n let pending = false;\n const schedule = () => {\n if (closing) return;\n if (current) {\n pending = true;\n return;\n }\n current = (async () => {\n do {\n pending = false;\n await task();\n } while (pending && !closing);\n })().finally(() => {\n current = null;\n if (pending && !closing) schedule();\n });\n };\n return { schedule, settled: async () => current?.catch(() => undefined) };\n };\n\n const graphRefresh = backgroundRefresh(() =>\n refreshGraph().catch((error) =>\n logger.error(`[sync] Graphify refresh failed: ${(error as Error).message}`),\n ),\n );\n // Queries never refresh zg on the prompt path (`--refresh off`); this keeps\n // the zg index incrementally current instead, and is a no-op unless enabled.\n // Closing aborts a running `zg index` rather than waiting it out.\n const zvecRefresh = backgroundRefresh(async () => {\n const result = await refreshZvecIndex(repositoryRoot, { signal: controller.signal }).catch(\n (error): ZvecRefresh => ({\n status: \"failed\",\n reason: (error as Error).message,\n }),\n );\n if (result.status !== \"disabled\") logger.info(`[sync] ${result.reason}`);\n });\n\n const ready = (async () => {\n // The index is the useful fallback if Graphify is unavailable in a\n // pre-made repository. Markdown memory is imported by the database\n // runtime when (and whenever) PostgreSQL connects.\n await indexRepository({ repositoryRoot });\n zvecRefresh.schedule();\n watchMemory();\n if (options.graphify?.enabled) {\n await refreshGraph().catch((error) =>\n logger.error(`[sync] Graphify startup refresh failed: ${(error as Error).message}`),\n );\n }\n\n watcher = watchRepository({\n repositoryRoot,\n signal: controller.signal,\n ...(options.graphify?.enabled\n ? {\n ignoredPaths: [\n options.graphify.graphPath\n ? relative(repositoryRoot, resolve(repositoryRoot, options.graphify.graphPath))\n .split(sep)\n .join(\"/\")\n : \"graphify-out\",\n ],\n }\n : {}),\n onIndex: (result) => {\n if (result.added + result.changed + result.removed === 0) return;\n zvecRefresh.schedule();\n if (options.graphify?.enabled) graphRefresh.schedule();\n },\n onError: (error) => logger.error(`[sync] repository watch failed: ${error.message}`),\n });\n // watchRepository performs its own initial index. It is intentionally\n // detached after the awaited startup pass so MCP can accept requests.\n // A platform without recursive fs.watch still gets a healthy MCP server\n // and the completed startup index.\n void watcher.catch((error) =>\n logger.error(`[sync] live repository watch unavailable: ${(error as Error).message}`),\n );\n })().catch((error) => {\n logger.error(`[sync] startup synchronization failed: ${(error as Error).message}`);\n throw error;\n });\n\n // The repository watcher ignores `.codebuddy/`; Markdown memory is the\n // source of truth, so hand edits and deletions are re-imported live.\n function watchMemory(): void {\n const onMemoryChange = options.onMemoryChange;\n if (closing || !onMemoryChange) return;\n try {\n memoryRefresh = createCoalescer(\n () =>\n onMemoryChange().catch((error) =>\n logger.error(`[sync] memory reindex failed: ${(error as Error).message}`),\n ),\n 300,\n );\n memoryWatcher = fsWatch(\n join(repositoryRoot, \".codebuddy\", \"memory\"),\n { recursive: true },\n (_event, filename) => {\n const name = filename?.replace(/\\\\/g, \"/\") ?? \"\";\n if (/^(facts\\/fact|summaries\\/sum)_[a-z0-9]+\\.md$/.test(name)) memoryRefresh?.trigger();\n },\n );\n memoryWatcher.on(\"error\", () => memoryWatcher?.close());\n } catch (error) {\n logger.error(`[sync] live memory watch unavailable: ${(error as Error).message}`);\n }\n }\n\n async function refreshGraph(): Promise<void> {\n const result = await generateGraphifyGraph({\n repositoryRoot,\n ...(options.graphify?.graphPath ? { graphPath: options.graphify.graphPath } : {}),\n });\n logger.info(`[sync] Graphify updated (${result.nodes} nodes, ${result.edges} edges)`);\n }\n\n return {\n ready,\n async close() {\n closing = true;\n controller.abort();\n memoryRefresh?.stop();\n memoryWatcher?.close();\n await watcher?.catch(() => undefined);\n await Promise.all([graphRefresh.settled(), zvecRefresh.settled()]);\n },\n };\n}\n","import { watch as fsWatch } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { type IndexOptions, indexRepository } from \"./engine.js\";\nimport type { IndexResult } from \"./types.js\";\n\n/**\n * `codebuddy watch` is an explicit, foreground incremental indexer — not a\n * hidden daemon (Proposal 04.3 non-goal). It coalesces bursts of file-save\n * events into a single index pass so a formatter rewriting fifty files triggers\n * one refresh, not fifty.\n */\n\nconst DEFAULT_DEBOUNCE_MS = 300;\n\n/**\n * A trailing debouncer: `trigger()` schedules `fn` to run after `delayMs` of\n * quiet, collapsing any calls made in that window into one. Runs are\n * serialized. A trigger marks the work dirty; a run clears the mark when it\n * starts, so an event that lands while a pass is in flight is never lost — the\n * pass reschedules itself when it settles. `stop()` cancels pending work and\n * resolves once any in-flight pass has finished. Exposed on its own so the\n * coalescing logic is testable without touching the filesystem.\n */\nexport function createCoalescer(\n fn: () => Promise<void>,\n delayMs: number,\n): { trigger: () => void; stop: () => Promise<void> } {\n let timer: NodeJS.Timeout | null = null;\n let running: Promise<void> | null = null;\n let dirty = false;\n let stopped = false;\n // Trailing debounce alone starves under sustained event streams (every new\n // event resets the window). maxWait forces a run this long after the FIRST\n // deferred trigger, so continuous activity still indexes eventually.\n let firstTriggerAt: number | null = null;\n let maxWaitTimer: NodeJS.Timeout | null = null;\n\n const clearTimers = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n if (maxWaitTimer) {\n clearTimeout(maxWaitTimer);\n maxWaitTimer = null;\n }\n firstTriggerAt = null;\n };\n\n const run = () => {\n // A busy run keeps `dirty` set; its settle step reschedules.\n if (stopped || running) return;\n clearTimers();\n dirty = false;\n running = (async () => {\n try {\n await fn();\n } finally {\n running = null;\n if (dirty) schedule();\n }\n })();\n };\n\n const schedule = () => {\n if (stopped) return;\n dirty = true;\n if (firstTriggerAt === null) {\n firstTriggerAt = Date.now();\n maxWaitTimer = setTimeout(run, MAX_WAIT_MS);\n }\n if (timer) clearTimeout(timer);\n timer = setTimeout(run, delayMs);\n };\n\n return {\n trigger: schedule,\n stop: async () => {\n stopped = true;\n clearTimers();\n await running?.catch(() => undefined);\n },\n };\n}\n\n/** Hard ceiling on how long a burst of events can defer a run. */\nconst MAX_WAIT_MS = 5_000;\n\nexport type WatchOptions = IndexOptions & {\n debounceMs?: number;\n ignoredPaths?: string[];\n onIndex?: (result: IndexResult) => void;\n onError?: (error: Error) => void;\n /** Abort to stop the watcher (e.g. wired to SIGINT). */\n signal?: AbortSignal;\n};\n\n/** Ignore churn we cause ourselves or that git would ignore. */\nexport function isIgnoredEvent(filename: string | null, ignoredPaths: string[] = []): boolean {\n if (!filename) return false;\n const normalized = filename.replace(/\\\\/g, \"/\");\n return (\n ignoredPaths.some((path) => normalized === path || normalized.startsWith(`${path}/`)) ||\n normalized.startsWith(\".codebuddy/\") ||\n normalized.includes(\"/.git/\") ||\n normalized.startsWith(\".git/\") ||\n normalized.includes(\"/node_modules/\") ||\n normalized.startsWith(\"node_modules/\") ||\n normalized.endsWith(\".tmp\")\n );\n}\n\n/**\n * Watch `repositoryRoot` recursively and run an incremental index on change.\n * Resolves when the signal aborts. Does an initial index pass on start so the\n * manifest is fresh before the first edit.\n */\nexport async function watchRepository(options: WatchOptions = {}): Promise<void> {\n const repositoryRoot = resolve(options.repositoryRoot ?? process.cwd());\n const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n\n const runIndex = async () => {\n try {\n const result = await indexRepository({\n repositoryRoot,\n ...(options.now ? { now: options.now } : {}),\n });\n options.onIndex?.(result);\n } catch (error) {\n options.onError?.(error as Error);\n }\n };\n\n await runIndex();\n\n const coalescer = createCoalescer(runIndex, debounceMs);\n const watcher = fsWatch(repositoryRoot, { recursive: true }, (_event, filename) => {\n if (isIgnoredEvent(filename, options.ignoredPaths)) return;\n coalescer.trigger();\n });\n\n return new Promise<void>((resolvePromise) => {\n const stop = () => {\n watcher.close();\n // Resolve only after an in-flight pass settles, so callers that stop the\n // watcher never race a manifest write.\n void coalescer.stop().then(() => resolvePromise());\n };\n if (options.signal) {\n if (options.signal.aborted) return stop();\n options.signal.addEventListener(\"abort\", stop, { once: true });\n }\n watcher.on(\"error\", () => stop());\n });\n}\n","import { realpath, stat } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, parse, resolve } from \"node:path\";\nimport { configPath } from \"./config-file.js\";\n\n/** Resolve a server's project before any indexing, watching, or database work. */\nexport async function resolveInitializedProjectRoot(\n configuredRoot?: string,\n cwd = process.cwd(),\n): Promise<string> {\n if (configuredRoot !== undefined && !isAbsolute(configuredRoot)) {\n throw new Error(\"CODEBUDDY_PROJECT_ROOT must be an absolute path to an initialized project.\");\n }\n const selected = resolve(configuredRoot ?? cwd);\n const root = await realpath(selected);\n if (root === parse(root).root || root === (await realpath(homedir()))) {\n throw new Error(\n \"Select an initialized project folder, not the filesystem root or home folder.\",\n );\n }\n const initialized = await stat(configPath(root)).then(\n (info) => info.isFile(),\n () => false,\n );\n if (!initialized) {\n throw new Error(\n `CodeBuddy will not scan ${root}: run codebuddy use (or codebuddy init) in your project folder first. ` +\n \"For a desktop client, re-register CodeBuddy from that folder to save its project path.\",\n );\n }\n return root;\n}\n","import type { CodeBuddy } from \"../core/codebuddy.js\";\nimport { redactSecrets } from \"../core/config-file.js\";\nimport type { RuntimeHandle } from \"../core/operations.js\";\nimport type { MemoryRepository } from \"../core/repository.js\";\n\nexport type DatabaseServices = { memory: CodeBuddy; repository: MemoryRepository };\n\nexport type DatabaseStatus = {\n available: boolean;\n state: \"idle\" | \"connecting\" | \"ready\" | \"unavailable\";\n error?: string;\n retryInMs?: number;\n};\n\nexport type LazyDatabase = {\n /** Resolve the runtime, connecting (or retrying after the cooldown) on demand. */\n get(): Promise<DatabaseServices>;\n status(): DatabaseStatus;\n close(): Promise<void>;\n};\n\n/**\n * Owns the optional PostgreSQL runtime for the MCP server so file-based tools\n * never wait on it. One connection attempt runs at a time; a failure is cached\n * for `retryMs` so database tools answer fast while Postgres is down, and the\n * first call after the cooldown retries. Once connected, the runtime (and its\n * embedding worker) is created exactly once.\n */\nexport function createLazyDatabase(\n connect: () => Promise<RuntimeHandle>,\n options: { retryMs?: number } = {},\n): LazyDatabase {\n const retryMs = options.retryMs ?? 5_000;\n let runtime: RuntimeHandle | undefined;\n let pending: Promise<RuntimeHandle> | undefined;\n let failure: { error: string; at: number } | undefined;\n let closed = false;\n\n return {\n get() {\n if (runtime) return Promise.resolve(runtime);\n if (closed) return Promise.reject(new Error(\"CodeBuddy MCP server is shutting down.\"));\n if (pending) return pending;\n if (failure && Date.now() - failure.at < retryMs) {\n return Promise.reject(new Error(failure.error));\n }\n pending = connect()\n .then(\n async (handle) => {\n if (closed) {\n await handle.close();\n throw new Error(\"CodeBuddy MCP server is shutting down.\");\n }\n runtime = handle;\n failure = undefined;\n return handle;\n },\n (error: unknown) => {\n failure = { error: describeError(error), at: Date.now() };\n throw error;\n },\n )\n .finally(() => {\n pending = undefined;\n });\n return pending;\n },\n status() {\n if (runtime) return { available: true, state: \"ready\" };\n if (pending) return { available: false, state: \"connecting\" };\n if (!failure) return { available: false, state: \"idle\" };\n return {\n available: false,\n state: \"unavailable\",\n error: failure.error,\n retryInMs: Math.max(0, failure.at + retryMs - Date.now()),\n };\n },\n async close() {\n closed = true;\n await pending?.catch(() => undefined);\n const current = runtime;\n runtime = undefined;\n await current?.close();\n },\n };\n}\n\n/** Bounded, credential-free error text (connection errors can echo the URL). */\nfunction describeError(error: unknown): string {\n const err = error as { message?: string; code?: string } | undefined;\n const text = err?.message || err?.code || String(error);\n return String(redactSecrets(text)).slice(0, 300);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,kBAAkB;AAiC3B,eAAsB,qBAAqB,OAKb;AAC5B,QAAM,YAAY,MAAM,MAAM,WAAW,mBAAmB,MAAM,SAAS;AAC3E,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,MACL,WAAW,MAAM;AAAA,MACjB,QAAQ,CAAC,MAAM;AAAA,MACf,OAAO,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,EAAE;AAAA,MACrE,WAAW,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,EAAE;AAAA,MACzE,WAAW,CAAC;AAAA,MACZ,UAAU,CAAC;AAAA,IACb;AAAA,EACF;AAEA,QAAM,CAAC,OAAO,WAAW,eAAe,iBAAiB,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC7E,MAAM,WAAW,UAAU,EAAE,aAAa,UAAU,IAAI,OAAO,IAAQ,CAAC;AAAA,IACxE,MAAM,WAAW,cAAc,EAAE,aAAa,UAAU,IAAI,OAAO,IAAQ,CAAC;AAAA,IAC5E,MAAM,MAAM,UAAU;AAAA,IACtB,MAAM,MAAM,cAAc;AAAA,EAC5B,CAAC;AAGD,QAAM,WACJ,MAAM,UAAU,OAAW,UAAU,UAAU,MAC3C;AAAA,IACE;AAAA,EACF,IACA,CAAC;AACP,QAAM,oBAAoB,IAAI,IAAI,cAAc,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC9E,QAAM,wBAAwB,IAAI,IAAI,kBAAkB,IAAI,CAAC,YAAY,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC;AAC/F,QAAM,YAAiC,CAAC;AACxC,QAAM,WAA+B,CAAC;AACtC,QAAM,eAAe,MAAM,OAAO,CAAC,SAAS;AAC1C,UAAM,WAAW,kBAAkB,IAAI,KAAK,EAAE;AAC9C,QAAI,CAAC,SAAU,QAAO;AAEtB,UAAM,mBAAmB,SAAS,gBAAgB,IAAI,EAAE,OAAO;AAC/D,UAAM,eAAe,SAAS,SAAS,OAAO;AAC9C,QAAI,qBAAqB,cAAc;AACrC,gBAAU,KAAK,EAAE,MAAM,QAAQ,IAAI,KAAK,IAAI,kBAAkB,aAAa,CAAC;AAAA,IAC9E;AACA,WAAO;AAAA,EACT,CAAC;AACD,QAAM,mBAAmB,UAAU,OAAO,CAAC,YAAY;AACrD,UAAM,WAAW,sBAAsB,IAAI,QAAQ,EAAE;AACrD,QAAI,CAAC,SAAU,QAAO;AACtB,UAAM,mBAAmB,SAAS,QAAQ,OAAO;AACjD,UAAM,eAAe,SAAS,SAAS,OAAO;AAC9C,QAAI,qBAAqB,cAAc;AACrC,gBAAU,KAAK,EAAE,MAAM,WAAW,IAAI,QAAQ,IAAI,kBAAkB,aAAa,CAAC;AAAA,IACpF;AACA,WAAO;AAAA,EACT,CAAC;AACD,MAAI,eAAe;AACnB,MAAI,mBAAmB;AAEvB,MAAI,MAAM,OAAO;AACf,eAAW,QAAQ,cAAc;AAC/B,UAAI;AACF,cAAM,MAAM,MAAM,UAAU;AAAA,UAC1B,IAAI,KAAK;AAAA,UACT,WAAW,MAAM;AAAA,UACjB,SAAS,KAAK;AAAA,UACd,WAAW,KAAK;AAAA,UAChB,QAAQ,KAAK;AAAA,UACb,YAAY,KAAK;AAAA,UACjB,WAAW,KAAK,UAAU,YAAY;AAAA,UACtC,gBAAgB,KAAK;AAAA,UACrB,qBAAqB,KAAK;AAAA,UAC1B,eAAe,KAAK;AAAA,UACpB,cAAc,KAAK;AAAA,UACnB,SAAS,KAAK;AAAA,QAChB,CAAC;AACD,wBAAgB;AAAA,MAClB,SAAS,OAAO;AACd,iBAAS,KAAK,EAAE,MAAM,QAAQ,IAAI,KAAK,IAAI,OAAQ,MAAgB,QAAQ,CAAC;AAAA,MAC9E;AAAA,IACF;AACA,eAAW,WAAW,kBAAkB;AACtC,UAAI;AACF,cAAM,MAAM,MAAM,aAAa;AAAA,UAC7B,IAAI,QAAQ;AAAA,UACZ,WAAW,MAAM;AAAA,UACjB,WAAW,QAAQ;AAAA,UACnB,SAAS,QAAQ;AAAA,UACjB,YAAY,QAAQ;AAAA,UACpB,WAAW,QAAQ,UAAU,YAAY;AAAA,UACzC,gBAAgB,QAAQ;AAAA,UACxB,SAAS,QAAQ;AAAA,QACnB,CAAC;AACD,4BAAoB;AAAA,MACtB,SAAS,OAAO;AACd,iBAAS,KAAK,EAAE,MAAM,WAAW,IAAI,QAAQ,IAAI,OAAQ,MAAgB,QAAQ,CAAC;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,gBAAgB,UAAU,OAAO,CAAC,aAAa,SAAS,SAAS,MAAM,EAAE;AAC/E,QAAM,mBAAmB,UAAU,SAAS;AAC5C,SAAO;AAAA,IACL,WAAW,MAAM;AAAA,IACjB,QAAQ,CAAC,MAAM;AAAA,IACf,GAAI,SAAS,SAAS,IAAI,EAAE,SAAS,IAAI,CAAC;AAAA,IAC1C,OAAO;AAAA,MACL,OAAO,MAAM;AAAA,MACb,UAAU,MAAM,SAAS,aAAa,SAAS;AAAA,MAC/C,SAAS,aAAa;AAAA,MACtB,WAAW;AAAA,MACX,SAAS;AAAA,IACX;AAAA,IACA,WAAW;AAAA,MACT,OAAO,UAAU;AAAA,MACjB,UAAU,UAAU,SAAS,iBAAiB,SAAS;AAAA,MACvD,SAAS,iBAAiB;AAAA,MAC1B,WAAW;AAAA,MACX,SAAS;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,SAAS,SAAyB;AACzC,SAAO,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAC1D;;;ACjKA,SAAS,cAAAA,aAAY,kBAAkB;AACvC,SAAS,kBAAkB;AAC3B,SAAS,OAAO,UAAU,iBAAiB;AAC3C,SAAS,eAAe;AACxB,SAAS,SAAS,YAAY;AAevB,IAAM,gBAAgB;AAG7B,IAAM,oBAAoB,KAAK;AAC/B,IAAM,aAAa;AACnB,IAAM,kBAAkB;AACxB,IAAM,OAAO;AA0BN,SAAS,mBAAmB,OAAO,QAAQ,GAAW;AAC3D,SAAO,KAAK,MAAM,cAAc,gBAAgB;AAClD;AAGA,eAAsB,mBAAmB,OAAO,QAAQ,GAA4B;AAClF,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,MAAM,SAAS,mBAAmB,IAAI,GAAG,MAAM,CAAC;AACzE,QAAI,OAAO,MAAM,cAAc,YAAY,MAAM,UAAW,QAAO;AAAA,EACrE,QAAQ;AAAA,EAER;AACA,SAAO,oBAAoB,EAAE,WAAW,WAAW,EAAE,GAAG,IAAI;AAC9D;AAEA,eAAsB,oBACpB,OACA,OAAO,QAAQ,GACU;AACzB,QAAM,OAAO,mBAAmB,IAAI;AACpC,QAAM,MAAM,QAAQ,IAAI,GAAG,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAC3D,QAAM,UAAU,MAAM,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,GAAM,EAAE,MAAM,IAAM,CAAC;AAC5E,SAAO;AACT;AAGO,SAAS,iBACd,OACA,MAAyB,QAAQ,KAClB;AACf,MAAI,IAAI,wBAAwB,IAAK,QAAO;AAC5C,MAAI,IAAI,iBAAiB,OAAO,IAAI,iBAAiB,OAAQ,QAAO;AACpE,MAAI,IAAI,GAAI,QAAO;AACnB,MAAI,MAAM,SAAU,QAAO;AAC3B,MAAI,CAAC,aAAa,GAAG,EAAG,QAAO;AAC/B,MAAI,CAAC,MAAM,SAAU,QAAO;AAC5B,SAAO;AACT;AAEO,SAAS,aAAa,MAAyB,QAAQ,KAAa;AACzE,SAAO,IAAI,2BAA2B;AACxC;AAEO,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAOhC,eAAsB,wBACpB,QAAgC,CAAC,SAAS,QAAQ,OAAO,MAAM,IAAI,GACnE,UAAqE,CAAC,GACvD;AACf,QAAM,MAAM,QAAQ,OAAO,QAAQ;AACnC,MAAI,EAAE,QAAQ,OAAO,QAAQ,OAAO,OAAQ;AAC5C,MAAI;AACF,UAAM,QAAQ,MAAM,mBAAmB,QAAQ,IAAI;AACnD,QAAI,MAAM,YAAY,MAAM,YAAY,IAAI,wBAAwB,OAAO,IAAI,GAAI;AACnF,QAAI,CAAC,aAAa,GAAG,EAAG;AACxB,UAAM;AAAA,EAAK,gBAAgB;AAAA;AAAA,CAAM;AACjC,UAAM,oBAAoB,EAAE,GAAG,OAAO,WAAU,oBAAI,KAAK,GAAE,YAAY,EAAE,GAAG,QAAQ,IAAI;AAAA,EAC1F,QAAQ;AAAA,EAER;AACF;AAGA,SAAS,UAAU,WAAmB,OAAuB;AAC3D,SAAOC,YAAW,QAAQ,EAAE,OAAO,GAAG,SAAS,KAAK,KAAK,EAAE,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AACxF;AAGO,SAAS,kBACd,WACA,QACkB;AAClB,SAAO,OAAO,IAAI,CAAC,WAAW;AAAA,IAC5B,IAAI,MAAM;AAAA,IACV,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,MAAM,OAAO;AAAA,IAC3C,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,MAAM,OAAO;AAAA,IAC3C,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,EAAE,KAAK,CAAC;AAAA,IACzC,IAAI,MAAM,OAAO;AAAA,IACjB,GAAI,OAAO,MAAM,aAAa,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,IACzE,GAAI,OAAO,MAAM,cAAc,WAAW,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,IAC5E,GAAI,MAAM,UAAU,EAAE,SAAS,UAAU,WAAW,MAAM,OAAO,EAAE,IAAI,CAAC;AAAA,EAC1E,EAAE;AACJ;AASA,eAAsB,eACpB,gBACA,UAMI,CAAC,GACY;AACjB,QAAM,MAAM,QAAQ,OAAO,QAAQ;AACnC,QAAM,MAAM,QAAQ,OAAO,KAAK,IAAI;AACpC,MAAI;AACF,UAAM,QAAQ,MAAM,mBAAmB,QAAQ,IAAI;AACnD,QAAI,iBAAiB,OAAO,GAAG,EAAG,QAAO;AACzC,UAAM,aAAa,KAAK,gBAAgB,cAAc,SAAS,gBAAgB;AAC/E,UAAM,SAAS,MAAM,SAAS,YAAY,MAAM,EAC7C,KAAK,CAAC,QAAQ,KAAK,MAAM,GAAG,CAAW,EACvC,MAAM,OAAe,CAAC,EAAE;AAC3B,QAAI,OAAO,aAAa,MAAM,OAAO,YAAY,kBAAmB,QAAO;AAE3E,UAAM,OAAO,CAAC,SACZ,MAAM,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC,EAAE;AAAA,MAAK,MACnD,UAAU,YAAY,KAAK,UAAU,IAAI,CAAC;AAAA,IAC5C;AACF,UAAM,KAAK,EAAE,GAAG,QAAQ,WAAW,IAAI,CAAC;AAExC,UAAM,WAAW,MAAM,WAAW,gBAAgB,GAAM,GACrD,OAAO,CAAC,UAAU,CAAC,OAAO,UAAU,MAAM,KAAK,OAAO,MAAM,EAC5D,MAAM,CAAC,UAAU;AACpB,UAAM,OAAO,QAAQ,GAAG,EAAE;AAC1B,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,QAAwB;AAAA,MAC5B,WAAW,MAAM;AAAA,MACjB,SAAS,UAAU,MAAM,WAAW,cAAc;AAAA,MAClD,SAAS;AAAA,MACT,UAAU,QAAQ;AAAA,MAClB,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,MAC7C,SAAS,OAAO,QAAQ,YAAY,MAAM,iBAAiB,cAAc,IAAI,EAAE;AAAA,QAC7E,MAAM,CAAC;AAAA,MACT;AAAA,MACA,QAAQ,kBAAkB,MAAM,WAAW,OAAO;AAAA,IACpD;AACA,UAAM,WAAW,OAAO,QAAQ,aAAa,OAAO,aAAa,GAAG,GAAG;AAAA,MACrE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,KAAK;AAAA,MAC1B,QAAQ,YAAY,QAAQ,eAAe;AAAA,IAC7C,CAAC;AACD,QAAI,CAAC,SAAS,GAAI,QAAO;AACzB,UAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,WAAW,IAAI,CAAC;AAC9C,WAAO,MAAM,OAAO;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAUA,eAAsB,gBACpB,SACA,SACA,OAAO,QAAQ,IAAI,GACJ;AACf,MAAI,oBAAoB,KAAK,QAAQ,YAAY,CAAC,KAAK,QAAQ,KAAK,MAAM,QAAS;AACnF,MAAI,CAAC,WAAW,KAAK,MAAM,YAAY,CAAC,EAAG;AAC3C,QAAM,OAAiB,CAAC;AACxB,WAAS,UAA8B,SAAS,SAAS,QAAQ,UAAU,QAAQ,QAAQ;AACzF,SAAK,QAAQ,QAAQ,KAAK,CAAC;AAAA,EAC7B;AACA,QAAM,YAAY,MAAM;AAAA,IACtB,MAAM;AAAA,IACN,MAAM,KAAK,KAAK,GAAG,KAAK;AAAA,IACxB,IAAI,KAAK,IAAI,IAAI;AAAA,IACjB,IAAI,CAAC,QAAQ;AAAA,EACf,CAAC;AACD,QAAM,eAAe,IAAI;AAC3B;AAGA,eAAe,iBAAiB,gBAA2C;AACzE,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,wBAAwB;AAC5D,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,uBAAuB;AAC7D,QAAM,QAAkB,CAAC;AACzB,aAAW,MAAM,YAAY;AAC3B,UAAM,SAAS,MAAM,aAAa,IAAI,cAAc,EAAE,MAAM,MAAM,IAAI;AACtE,QAAI,WAAW,OAAO,SAAS,OAAO,KAAM,OAAM,KAAK,EAAE;AAAA,EAC3D;AACA,SAAO;AACT;;;AClPA,SAAS,SAAS;;;ACDlB,SAAS,cAAAC,mBAAkB;AAmBpB,IAAM,mBAAmB;AAGhC,IAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMA,IAAM,iBAAiB,KAAK,KAAK;AAoBjC,eAAsB,qBACpB,gBACA,SACA,SACkC;AAClC,MAAI,SAAkC,EAAE,GAAG,QAAQ;AACnD,MAAI,CAAC,QAAQ,UAAW,QAAO;AAQ/B,QAAM,WAAW,mBAAmB,OAAO,CAAC,QAAQ,OAAO,GAAG,MAAM,MAAS,EAAE,IAAI,CAAC,SAAS;AAAA,IAC3F,KAAK,OAAO,GAAG;AAAA,IACf,MAAMC,YAAW,QAAQ,EAAE,OAAO,KAAK,UAAU,OAAO,GAAG,CAAC,CAAC,EAAE,OAAO,KAAK;AAAA,EAC7E,EAAE;AAEF,MAAI;AACF,UAAM,IAAI,qBAAqB,cAAc,EAAE,SAAS,QAAQ,WAAW,UAAU;AAAA,MACnF,GAAI,QAAQ,QAAQ,SAAY,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC;AAAA,MACxD,OAAO;AAAA,MACP,GAAI,QAAQ,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAAA,MACrC,SAAS,CAAC,aAAa;AACrB,cAAM,YAAY,SAAS,UAAU,IAAI,CAAC,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;AAC1E,YAAI,gBAAgB;AACpB,mBAAW,OAAO,WAAW;AAC3B,2BAAiB,eAAe,OAAO,GAAG,CAAC;AAC3C,iBAAO,OAAO,GAAG;AAAA,QACnB;AACA,cAAM,WAAyB;AAAA,UAC7B,SAAS;AAAA,UACT,WAAW,QAAQ;AAAA,UACnB,YAAY,SAAS;AAAA,UACrB,KAAK,SAAS;AAAA,UACd;AAAA,UACA;AAAA,UACA,MAAM;AAAA,QACR;AACA,eAAO,WAAW;AAClB,iBAAS,qBAAqB,MAAM;AAGpC,eAAO,mBAAmB,OAAO,CAAC,QAAQ,OAAO,GAAG,MAAM,MAAS,EAAE,IAAI,CAAC,SAAS;AAAA,UACjF,KAAK,OAAO,GAAG;AAAA,UACf,MAAMA,YAAW,QAAQ,EAAE,OAAO,KAAK,UAAU,OAAO,GAAG,CAAC,CAAC,EAAE,OAAO,KAAK;AAAA,QAC7E,EAAE;AAAA,MACJ;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO,qBAAqB,EAAE,GAAG,QAAQ,CAAC;AAAA,EAC5C;AACF;;;AChHA,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,SAAS,QAAAC,OAAM,eAAe;;;ACoDhC,IAAM,gBAAoD;AAAA,EAC/D,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,MAAM;AACR;;;ADtCA,IAAM,yBAAyB;AAC/B,IAAM,sBAAsB;AAC5B,IAAM,oBAAoB;AAC1B,IAAM,kBAAkB,oBAAI,IAAI,CAAC,OAAO,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,KAAK,CAAC;AAWrF,eAAsB,oBAAoB,OAA6C;AACrF,QAAM,iBAAiB,QAAQ,MAAM,kBAAkB,QAAQ,IAAI,CAAC;AACpE,QAAM,YAAY,MAAM;AAExB,QAAM,cAAc,MAAM,iBAAiB;AAAA,IACzC;AAAA,IACA,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,IAC1D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,IAC7D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,EAC/D,CAAC;AAED,QAAM,YAAY,IAAI,cAAc,cAAc;AAClD,QAAM,cAAc,IAAI,gBAAgB,cAAc;AAEtD,QAAM,CAAC,OAAO,MAAM,WAAW,KAAK,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA,IAClE,WAAW;AAAA,MACT;AAAA,MACA;AAAA,MACA,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,MAC1D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,MAC7D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,IAC/D,CAAC;AAAA,IACD,oBAAoB,WAAW,WAAW,MAAM,MAAM;AAAA,IACtD,YAAY,0BAA0B,EAAE,WAAW,OAAO,YAAY,CAAC;AAAA,IACvE,qBAAqB,cAAc;AAAA,IACnC,eAAeC,MAAK,gBAAgB,cAAc,eAAe,CAAC;AAAA,EACpE,CAAC;AAED,QAAM,cAA4B,CAAC;AAGnC,aAAW,QAAQ,MAAM,OAAO;AAC9B,QAAI,KAAK,QAAQ,uBAAwB;AACzC,gBAAY,KAAK;AAAA,MACf,IAAI,QAAQ,KAAK,IAAI;AAAA,MACrB,UAAU;AAAA,MACV,UAAU,KAAK,SAAS,KAAK,SAAS;AAAA,MACtC,OAAO,8BAA8B,KAAK,IAAI;AAAA,MAC9C,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,UAAU;AAAA,QACR,EAAE,MAAM,cAAc,QAAQ,SAAS,KAAK,KAAK,KAAK,KAAK,QAAQ,IAAI;AAAA,QACvE,GAAI,KAAK,SAAS,SAAS,IACvB,CAAC,EAAE,MAAM,iBAAiB,QAAQ,GAAG,KAAK,SAAS,MAAM,oBAAoB,CAAC,IAC9E,CAAC;AAAA,MACP;AAAA,MACA,aAAa,iCAAiC,KAAK,IAAI;AAAA,IACzD,CAAC;AAAA,EACH;AAGA,aAAW,YAAY,WAAW;AAChC,UAAM,OAAO,SAAS,MAAM,CAAC,KAAK;AAClC,gBAAY,KAAK;AAAA,MACf,IAAI,YAAY,IAAI;AAAA,MACpB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,OAAO,+BAA+B,IAAI;AAAA,MAC1C,QAAQ,GAAG,SAAS,OAAO;AAAA,MAC3B;AAAA,MACA,UAAU,CAAC,EAAE,MAAM,YAAY,QAAQ,GAAG,SAAS,EAAE,aAAa,SAAS,QAAQ,GAAG,CAAC;AAAA,IACzF,CAAC;AAAA,EACH;AAGA,QAAM,UAAU,eAAe,GAAG;AAClC,aAAW,QAAQ,aAAa;AAC9B,UAAM,aAAa,QAAQ,IAAI,IAAI,KAAK;AACxC,QAAI,aAAa,oBAAqB;AACtC,gBAAY,KAAK;AAAA,MACf,IAAI,gBAAgB,IAAI;AAAA,MACxB,UAAU;AAAA,MACV,UAAU,cAAc,oBAAoB,SAAS;AAAA,MACrD,OAAO,sBAAsB,IAAI;AAAA,MACjC,QAAQ,GAAG,UAAU,qBAAqB,IAAI;AAAA,MAC9C;AAAA,MACA,UAAU,CAAC,EAAE,MAAM,cAAc,QAAQ,GAAG,UAAU,qBAAqB,CAAC;AAAA,MAC5E,aAAa,4BAA4B,IAAI;AAAA,IAC/C,CAAC;AAAA,EACH;AAGA,MAAI,MAAM;AACR,UAAM,UAAU,IAAI,IAAI,KAAK,aAAa,IAAI,CAAC,SAAS,UAAU,KAAK,IAAI,CAAC,CAAC;AAC7E,UAAM,SAAS,YAAY,OAAO,CAAC,SAAS,CAAC,QAAQ,IAAI,UAAU,IAAI,CAAC,CAAC;AACzE,QAAI,QAAQ,OAAO,KAAK,OAAO,SAAS,GAAG;AACzC,kBAAY,KAAK;AAAA,QACf,IAAI,mBAAmB,KAAK,EAAE;AAAA,QAC9B,UAAU;AAAA,QACV,UAAU;AAAA,QACV,OAAO,iCAAiC,KAAK,EAAE;AAAA,QAC/C,QAAQ,GAAG,OAAO,MAAM,wDAAwD,OAC7E,MAAM,GAAG,CAAC,EACV,KAAK,IAAI,CAAC;AAAA,QACb,UAAU;AAAA,UACR,EAAE,MAAM,QAAQ,QAAQ,QAAQ,KAAK,EAAE,KAAK,KAAK,MAAM,IAAI;AAAA,UAC3D,EAAE,MAAM,gBAAgB,QAAQ,OAAO,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,EAAE;AAAA,QAChE;AAAA,QACA,aAAa,uBAAuB,KAAK,EAAE;AAAA,MAC7C,CAAC;AAAA,IACH;AAAA,EACF;AAGA,aAAW,QAAQ,aAAa;AAC9B,QAAI,CAAC,eAAe,IAAI,EAAG;AAC3B,QAAI,MAAM,eAAe,gBAAgB,IAAI,EAAG;AAChD,gBAAY,KAAK;AAAA,MACf,IAAI,gBAAgB,IAAI;AAAA,MACxB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,OAAO,qBAAqB,IAAI;AAAA,MAChC,QAAQ;AAAA,MACR;AAAA,MACA,UAAU,CAAC,EAAE,MAAM,WAAW,QAAQ,kCAAkC,CAAC;AAAA,IAC3E,CAAC;AAAA,EACH;AAGA,aAAW,QAAQ,WAAW,OAAO;AACnC,UAAM,SAAS,cAAc,KAAK,OAAO;AACzC,QAAI,CAAC,OAAQ;AACb,QAAI,MAAM,WAAWA,MAAK,gBAAgB,MAAM,CAAC,EAAG;AACpD,gBAAY,KAAK;AAAA,MACf,IAAI,gBAAgB,KAAK,EAAE;AAAA,MAC3B,UAAU;AAAA,MACV,UAAU;AAAA,MACV,OAAO,sBAAsB,KAAK,EAAE;AAAA,MACpC,QAAQ,YAAY,KAAK,OAAO,cAAc,MAAM;AAAA,MACpD,UAAU,CAAC,EAAE,MAAM,eAAe,QAAQ,GAAG,KAAK,EAAE,WAAM,KAAK,OAAO,GAAG,CAAC;AAAA,IAC5E,CAAC;AAAA,EACH;AAEA,QAAM,UAAU,OAAO,WAAW,EAAE,KAAK,kBAAkB;AAC3D,QAAM,UAAU,MAAM,QAAQ,QAAQ,MAAM,GAAG,MAAM,KAAK,IAAI;AAE9D,SAAO;AAAA,IACL,aAAa;AAAA,IACb,OAAO,WAAW,YAAY,QAAQ,OAAO;AAAA,EAC/C;AACF;AAIA,eAAe,oBACb,OACA,WACA,QAC0B;AAC1B,MAAI,QAAQ;AACV,QAAI;AACF,aAAO,MAAM,MAAM,SAAS,MAAM;AAAA,IACpC,SAAS,OAAO;AACd,UAAK,MAAgC,SAAS,SAAU,QAAO;AAC/D,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO,IAAI,cAAc,KAAK,EAAE,QAAQ,SAAS;AACnD;AAEA,SAAS,eAAe,KAA2C;AACjE,QAAM,UAAU,oBAAI,IAAoB;AACxC,aAAW,QAAQ,IAAI,MAAO,SAAQ,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,EAAE,KAAK,KAAK,CAAC;AAClF,SAAO;AACT;AAEA,SAAS,eAAe,MAAuB;AAC7C,MAAI,+BAA+B,KAAK,IAAI,EAAG,QAAO;AACtD,MAAI,KAAK,SAAS,OAAO,EAAG,QAAO;AACnC,MAAI,KAAK,SAAS,YAAY,EAAG,QAAO;AAExC,MAAI,6EAA6E,KAAK,IAAI,GAAG;AAC3F,WAAO;AAAA,EACT;AACA,SAAO,gBAAgB,IAAI,QAAQ,IAAI,EAAE,YAAY,CAAC;AACxD;AAEA,eAAe,eAAe,gBAAwB,MAAgC;AACpF,aAAW,aAAa,uBAAuB,IAAI,GAAG;AACpD,QAAI,MAAM,WAAWA,MAAK,gBAAgB,SAAS,CAAC,EAAG,QAAO;AAAA,EAChE;AACA,SAAO;AACT;AAOA,SAAS,cAAc,SAAyB;AAC9C,QAAM,aAAa,UAAU,OAAO;AACpC,QAAM,WAAW,WAAW,OAAO,OAAO;AAC1C,MAAI,aAAa,GAAI,QAAO,WAAW,QAAQ,QAAQ,EAAE;AACzD,QAAM,iBAAiB,WAAW,MAAM,GAAG,QAAQ;AACnD,QAAM,YAAY,eAAe,YAAY,GAAG;AAChD,SAAO,cAAc,KAAK,KAAK,eAAe,MAAM,GAAG,SAAS;AAClE;AAEA,SAAS,OAAO,aAAyC;AACvD,QAAM,OAAO,oBAAI,IAAwB;AACzC,aAAW,cAAc,aAAa;AACpC,UAAM,WAAW,KAAK,IAAI,WAAW,EAAE;AACvC,QAAI,CAAC,YAAY,cAAc,WAAW,QAAQ,IAAI,cAAc,SAAS,QAAQ,GAAG;AACtF,WAAK,IAAI,WAAW,IAAI,UAAU;AAAA,IACpC;AAAA,EACF;AACA,SAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAC1B;AAEA,SAAS,mBAAmB,MAAkB,OAA2B;AACvE,QAAM,WAAW,cAAc,MAAM,QAAQ,IAAI,cAAc,KAAK,QAAQ;AAC5E,MAAI,aAAa,EAAG,QAAO;AAC3B,MAAI,KAAK,aAAa,MAAM,SAAU,QAAO,KAAK,SAAS,cAAc,MAAM,QAAQ;AACvF,UAAQ,KAAK,QAAQ,IAAI,cAAc,MAAM,QAAQ,EAAE;AACzD;AAEA,SAAS,WAAW,iBAAyB,aAA2B;AACtE,QAAM,aAAqC,CAAC;AAC5C,QAAM,aAAqC,CAAC;AAC5C,aAAW,cAAc,aAAa;AACpC,eAAW,WAAW,QAAQ,KAAK,WAAW,WAAW,QAAQ,KAAK,KAAK;AAC3E,eAAW,WAAW,QAAQ,KAAK,WAAW,WAAW,QAAQ,KAAK,KAAK;AAAA,EAC7E;AACA,SAAO,EAAE,iBAAiB,UAAU,YAAY,QAAQ,YAAY,WAAW;AACjF;AAEA,eAAe,WAAW,MAAgC;AACxD,MAAI;AACF,UAAM,OAAO,MAAM,UAAU,IAAI;AACjC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,MAAsB;AACvC,SAAO,KAAK,QAAQ,OAAO,GAAG,EAAE,QAAQ,SAAS,EAAE;AACrD;;;AE/QO,SAAS,oBACd,OACA,SAAS,QAAQ,IAAI,6BAA6B,QAClD;AACA,MAAI,WAAW,UAAU,WAAW,QAAQ;AAC1C,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AACA,SAAO;AAAA,IACL,SAAS,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,KAAK,EAAE,CAAC;AAAA,IAChE,GAAI,WAAW,UAAU,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IACxF,EAAE,mBAAmB,MAAiC,IACtD,CAAC;AAAA,EACP;AACF;;;AJqBA,IAAM,eAAe;AAAA,EACnB,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW;AAAA,EACX,cAAc;AAAA;AAAA,EAEd,SAAS;AACX;AAGA,IAAM,iBAAiB;AAAA,EACrB,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EAC/C,KAAK,EACF,OAAO,EACP,MAAM,iBAAiB,EACvB,SAAS;AAAA,EACZ,MAAM,EAAE,QAAQ,EAAE,SAAS;AAC7B;AAGA,IAAM,SAAS,CAAC,QACd,EACG,OAAO,EACP,IAAI,CAAC,EACL,IAAI,GAAG,EACP,OAAO,CAAC,UAAU,CAAC,MAAM,SAAS,IAAQ,GAAG,4BAA4B;AAE9E,IAAM,iBAAiB;AAAA,EACrB,WAAW,OAAO,GAAG,EAAE,SAAS;AAAA,EAChC,SAAS,OAAO,aAAa,YAAY;AAAA,EACzC,MAAM,EAAE,KAAK,CAAC,eAAe,QAAQ,SAAS,CAAC,EAAE,SAAS;AAAA,EAC1D,gBAAgB,OAAO,GAAG,EAAE,SAAS;AAAA,EACrC,SAAS,OAAO,aAAa,YAAY,EAAE,SAAS;AACtD;AAEA,IAAM,eAAe;AAAA,EACnB,WAAW,OAAO,GAAG;AAAA,EACrB,OAAO,OAAO,aAAa,SAAS;AAAA,EACpC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,EAC7C,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EACjD,cAAc,EAAE,KAAK,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAAE,SAAS;AAAA;AAAA,EAEvE,SAAS,EAAE,QAAQ,EAAE,SAAS;AAChC;AAEA,IAAM,cAAc;AAAA,EAClB,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,YAAY,EAAE,SAAS;AAAA,EAChE,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,YAAY;AAAA,EAC7D,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,UAAU;AAAA,EAC/E,MAAM,EAAE,KAAK,CAAC,aAAa,UAAU,CAAC,EAAE,SAAS;AAAA;AAAA,EAEjD,iBAAiB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS,EAAE,SAAS;AAAA,EACxE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,YAAY,EAAE,SAAS;AACrE;AAEA,IAAM,gBAAgB;AAAA,EACpB,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,YAAY;AAAA,EAC7D,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,UAAU;AAAA,EAC/E,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,YAAY,EAAE,SAAS;AACrE;AAEA,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACjC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS;AAAA,EAClD,QAAQ,EAAE,KAAK,CAAC,UAAU,QAAQ,QAAQ,CAAC;AAAA,EAC3C,OAAO,EAAE,OAAO,EAAE,IAAI,aAAa,SAAS,EAAE,SAAS;AACzD,CAAC;AACD,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACjC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS;AAAA,EAClD,aAAa,EAAE,OAAO,EAAE,IAAI,aAAa,SAAS,EAAE,SAAS;AAC/D,CAAC;AACD,IAAM,kBAAkB;AAAA,EACtB,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,UAAU,EAAE,SAAS;AAAA,EAC/D,OAAO,EAAE,OAAO,EAAE,IAAI,aAAa,cAAc,EAAE,SAAS;AAAA,EAC5D,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,aAAa,EAAE,SAAS;AAAA,EAC1D,cAAc,EAAE,MAAM,iBAAiB,EAAE,IAAI,aAAa,UAAU,EAAE,SAAS;AAAA,EAC/E,YAAY,EAAE,MAAM,iBAAiB,EAAE,IAAI,aAAa,UAAU,EAAE,SAAS;AAAA,EAC7E,YAAY,EACT,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,SAAS,CAAC,EAC5C,IAAI,aAAa,UAAU,EAC3B,SAAS;AAAA,EACZ,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,SAAS,CAAC,EAAE,IAAI,aAAa,UAAU,EAAE,SAAS;AAC/F;AAEO,IAAM,sBAAsB;AAAA,EACjC,UAAU,EAAE,OAAO,cAAc;AAAA,EACjC,gBAAgB,EAAE,OAAO;AAAA,IACvB,OAAO,EAAE,MAAM,EAAE,OAAO,cAAc,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,UAAU;AAAA,EAC7E,CAAC;AAAA,EACD,QAAQ,EAAE,OAAO,YAAY;AAAA,EAC7B,YAAY,EAAE,OAAO;AAAA,IACnB,SAAS,EAAE,OAAO,EAAE,IAAI,aAAa,UAAU,EAAE,SAAS;AAAA,IAC1D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,IACtD,QAAQ,EAAE,OAAO,EAAE,IAAI,aAAa,OAAO,EAAE,SAAS;AAAA,EACxD,CAAC;AAAA,EACD,iBAAiB,EAAE,OAAO,CAAC,CAAC;AAAA,EAC5B,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,OAAO,EAAE,CAAC;AAAA,EACpE,OAAO,EAAE,OAAO,WAAW;AAAA,EAC3B,SAAS,EAAE,OAAO,aAAa;AAAA,EAC/B,cAAc,EAAE,OAAO,CAAC,CAAC;AAAA,EACzB,aAAa,EAAE,OAAO;AAAA,IACpB,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,UAAU;AAAA,IACpD,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,cAAc;AAAA,IACxD,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,aAAa,EAAE,SAAS;AAAA,IAC1D,cAAc,EAAE,MAAM,iBAAiB,EAAE,IAAI,aAAa,UAAU,EAAE,SAAS;AAAA,IAC/E,YAAY,EAAE,MAAM,iBAAiB,EAAE,IAAI,aAAa,UAAU,EAAE,SAAS;AAAA,IAC7E,YAAY,EACT,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,SAAS,CAAC,EAC5C,IAAI,aAAa,UAAU,EAC3B,SAAS;AAAA,IACZ,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,SAAS,CAAC,EAAE,IAAI,aAAa,UAAU,EAAE,SAAS;AAAA,IAC7F,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,YAAY,EAAE,SAAS;AAAA,EACrE,CAAC;AAAA,EACD,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,OAAO,EAAE,OAAO,eAAe,EAAE,CAAC;AAAA,EAChF,aAAa,EAAE,OAAO;AAAA,IACpB,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IACpB,QAAQ,EAAE,KAAK,CAAC,YAAY,aAAa,YAAY,WAAW,CAAC;AAAA,IACjE,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,IAC3B,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,CAAC;AAAA,EACD,aAAa,EAAE,OAAO;AAAA,IACpB,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,IAC5C,OAAO,EACJ,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS,CAAC,EACnD,IAAI,aAAa,UAAU,EAC3B,SAAS;AAAA,IACZ,UAAU,EAAE,KAAK,CAAC,YAAY,QAAQ,CAAC,EAAE,SAAS;AAAA,IAClD,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC7B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EACvD,CAAC;AAAA,EACD,WAAW,EAAE,OAAO;AAAA,IAClB,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS,EAAE,SAAS;AAAA,IAC7D,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS,EAAE,SAAS;AAAA,IAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EACvD,CAAC;AAAA,EACD,gBAAgB,EAAE,OAAO;AAAA,IACvB,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS;AAAA,IACpD,WAAW,EAAE,KAAK,CAAC,MAAM,OAAO,MAAM,CAAC,EAAE,QAAQ,MAAM;AAAA,EACzD,CAAC;AAAA,EACD,mBAAmB,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC;AAAA,EACjD,qBAAqB,EAAE,OAAO;AAAA,IAC5B,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS,EAAE,SAAS;AAAA,IAC7D,OAAO,EACJ,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS,CAAC,EACnD,IAAI,aAAa,UAAU,EAC3B,SAAS;AAAA,IACZ,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,IAC5C,UAAU,EAAE,KAAK,CAAC,YAAY,QAAQ,CAAC,EAAE,SAAS;AAAA,IAClD,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC7B,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAO,EAAE,SAAS;AAAA,IAC/D,GAAG;AAAA,EACL,CAAC;AAAA,EACD,cAAc,EAAE,OAAO;AAAA,IACrB,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS;AAAA,IAClD,OAAO,EACJ,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS,CAAC,EACnD,IAAI,aAAa,UAAU,EAC3B,SAAS;AAAA,IACZ,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,IAC5C,UAAU,EAAE,KAAK,CAAC,YAAY,QAAQ,CAAC,EAAE,SAAS;AAAA,IAClD,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC7B,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAO,EAAE,SAAS;AAAA,IAC/D,GAAG;AAAA,EACL,CAAC;AAAA,EACD,oBAAoB,EAAE,OAAO;AAAA,IAC3B,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,YAAY;AAAA,IACxD,cAAc,EACX,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS,CAAC,EACnD,IAAI,aAAa,UAAU,EAC3B,SAAS;AAAA,IACZ,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,IAC5C,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,IAC9C,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,YAAY,EAAE,SAAS;AAAA,IACnE,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,IAC/C,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS;AAAA,IACnE,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS;AAAA,EAChD,CAAC;AAAA,EACD,kBAAkB,EAAE,OAAO;AAAA,IACzB,OAAO,EACJ,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,SAAS,CAAC,EACnD,IAAI,aAAa,UAAU,EAC3B,SAAS;AAAA,IACZ,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,IAC5C,UAAU,EAAE,KAAK,CAAC,YAAY,QAAQ,CAAC,EAAE,SAAS;AAAA,IAClD,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC7B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EACvD,CAAC;AAAA,EACD,QAAQ,EAAE,OAAO,CAAC,CAAC;AACrB;AAGA,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAM,aAAa,OAAO,KAAK,mBAAmB,EAAE;AAAA,EAClD,CAAC,SAAS,CAAC,eAAe,SAAS,IAAI;AACzC;AACA,IAAM,oBACJ;AASK,IAAM,aAAa;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,mBAAmB,QAAQ,QAAQ,IAAI,wBAAqC;AAC1F,MAAI,UAAU,UAAa,UAAU,MAAM,UAAU,OAAQ,QAAO;AACpE,MAAI,UAAU,OAAQ,QAAO;AAC7B,QAAM,IAAI,MAAM,yDAAyD,KAAK,GAAG;AACnF;AAeA,IAAM,kBAAkB;AAExB,SAAS,cAAc,MAA+D;AACpF,MAAI,CAAC,KAAM,QAAO,EAAE,MAAM,KAAK;AAC/B,QAAM,OACJ,KAAK,KAAK,SAAS,kBACf,GAAG,KAAK,KAAK,MAAM,GAAG,eAAe,CAAC;AAAA;AAAA,qBACtC,KAAK;AACX,SAAO,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,EAAE;AACnC;AAEO,SAAS,uBACd,QACA,SACA,UAAuB,QACvB;AACA,QAAM,UAAU,CAAC,SAAiB,YAAY,UAAU,WAAW,SAAS,IAAI;AAEhF,QAAM,SAAS,cAAc,UAAU,QAAQ,SAAS,QAAQ,OAAO;AACvE,QAAM,YAAY,OAAO,eAAe,QAAQ,IAAI;AAEpD,QAAM,WAAsC,CAAC,MAAM,YAAY,aAAa;AAC1E,UAAM,UAAU,UAAU,SAAoB;AAC5C,YAAM,UAAU,KAAK,IAAI;AACzB,YAAM,QAAQ,KAAK,SAAS,IAAK,KAAK,CAAC,IAAgC;AACvE,YAAM,QAAQ,CAAC,IAAa,WAC1B,KAAK,YAAY,WAAW;AAAA,QAC1B,MAAM;AAAA,QACN;AAAA,QACA,IAAI,KAAK,IAAI,IAAI;AAAA,QACjB;AAAA,QACA,UAAU,eAAe,KAAK;AAAA,QAC9B,WAAW,eAAe,MAAM;AAAA,QAChC,GAAI,OAAO,OAAO,cAAc,WAAW,EAAE,SAAS,MAAM,UAAU,IAAI,CAAC;AAAA,MAC7E,CAAC;AACH,UAAI;AACF,cAAM,SAAU,MAAO,SAAmD,GAAG,IAAI;AAIjF,cAAM,QAAQ,YAAY,MAAM,QAAQ,SAAS,IAAI,CAAC,SAAS,KAAK,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC;AACxF,eAAO;AAAA,MACT,SAAS,OAAO;AACd,cAAM,KAAK;AACX,cAAM;AAAA,MACR;AAAA,IACF;AACA,UAAM,OAAO,OAAO,aAAa,MAAM,YAAY,MAAM;AACzD,QAAI,CAAC,QAAQ,IAAI,EAAG,MAAK,OAAO;AAChC,WAAO;AAAA,EACT;AACA,QAAM,OAAO;AAEb,QAAM,WACJ,cAAc,UACV,QAAQ,WACR,EAAE,KAAK,YAAY,SAAS,QAAQ,OAAO,EAAE,WAAW,MAAM,OAAO,QAAQ,GAAG;AAEtF,QAAM,cAAc,OAAO,MAAc,QAAoD;AAC3F,QAAI;AACJ,QAAI;AACF,WAAK,MAAM,SAAS,IAAI;AAAA,IAC1B,QAAQ;AACN,aAAO;AAAA,QACL,GAAG,KAAK,EAAE,UAAU,MAAM,MAAM,UAAU,SAAS,OAAO,GAAG,UAAU,kBAAkB,CAAC;AAAA,QAC1F,SAAS;AAAA,MACX;AAAA,IACF;AACA,WAAO,KAAK,MAAM,IAAI,EAAE,CAAC;AAAA,EAC3B;AAEA,QAAM,YAAY,OAAO;AACzB,QAAM,cAAc,OAAO,eAAe,QAAQ,IAAI;AACtD,QAAM,mBAAmB,OACvB,MACA,eACG;AAEH,QAAI,SAAS,OAAO,EAAE,UAAU,QAAS,QAAO,CAAC;AACjD,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAM,SAAS,IAAI;AACtC,aAAO,MAAM,OAAO;AAAA,QAClB;AAAA,QACA,WAAW,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE;AAAA,MAC/B;AAAA,IACF,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAEA,QAAM,WAAW,mBAAmB,WAAW,EAAE,MAAM,MAAM,MAAS;AACtE,QAAM,iBAAiB,YAAY;AACjC,UAAM,aAAa,MAAM;AACzB,WAAO,aAAa,EAAE,UAAU,WAAW,IAAI,CAAC;AAAA,EAClD;AACA,QAAM,YAAY,IAAI,cAAc,WAAW;AAC/C,QAAM,gBAAgB,IAAI,cAAc,SAAS;AACjD,QAAM,UAAU,CACd,UAKG,OAAO,IAAI,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,QAAQ,KAAK,QAAQ,OAAO,KAAK,SAAS,GAAG,EAAE;AAC7F,QAAM,UAAU,CAAC,UACf,OAAO,IAAI,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,aAAa,KAAK,eAAe,GAAG,EAAE;AAEjF;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,SAAS;AAAA,IAC5C;AAAA,IACA,OAAO,UAAU,YAAY,YAAY,CAAC,OAAO,GAAG,OAAO,SAAS,gBAAgB,KAAK,CAAC,CAAC;AAAA,EAC7F;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,eAAe;AAAA,IAClD;AAAA,IACA,OAAO,UACL,YAAY,kBAAkB,OAAO,QAAQ;AAAA,MAC3C,OAAO,MAAM,GAAG,OAAO,cAAc,MAAM,MAAM,IAAI,eAAe,CAAC;AAAA,IACvE,EAAE;AAAA,EACN;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa,oBAAoB,OAAO;AAAA,IAC1C;AAAA,IACA,OAAO,UACL;AAAA,MAAY;AAAA,MAAU,OAAO,OAC3B,mBAAmB,MAAM,GAAG,OAAO,OAAO,cAAc,KAAK,CAAC,GAAG,MAAM,YAAY,IAAI;AAAA,IACzF;AAAA,EACJ;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,WAAW;AAAA,IAC9C;AAAA,IACA,OAAO,UACL;AAAA,MAAY;AAAA,MAAc,CAAC,OACzB;AAAA,QACE,GAAG;AAAA,QACH,GAAG;AAAA,QACH,cAAc,KAAK;AAAA,MACrB;AAAA,IACF;AAAA,EACJ;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,gBAAgB;AAAA,IACnD;AAAA,IACA,YACE,YAAY,mBAAmB,OAAO,QAAQ;AAAA,MAC5C,YAAY,MAAM,GAAG,WAAW,eAAe;AAAA,IACjD,EAAE;AAAA,EACN;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,OAAO;AAAA,IAC1C;AAAA,IACA,OAAO,UAAU,YAAY,UAAU,CAAC,OAAO,GAAG,OAAO,OAAO,MAAM,EAAE,CAAC;AAAA,EAC3E;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa,oBAAoB,MAAM;AAAA,IACzC;AAAA,IACA,OAAO,UACL;AAAA,MAAY;AAAA,MAAS,CAAC,OACpB,GAAG,OAAO,MAAM;AAAA,QACd,MAAM,MAAM,QAAQ;AAAA,QACpB,IAAI,MAAM;AAAA,QACV,SAAS,MAAM;AAAA,QACf,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,QACzC,GAAI,MAAM,kBAAkB,EAAE,mBAAmB,MAAM,gBAAgB,IAAI,CAAC;AAAA,QAC5E,GAAI,MAAM,UAAU,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,MACpD,CAAC;AAAA,IACH;AAAA,EACJ;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa,oBAAoB,QAAQ;AAAA,IAC3C;AAAA,IACA,OAAO,UACL;AAAA,MAAY;AAAA,MAAW,CAAC,OACtB,GAAG,OAAO,QAAQ;AAAA,QAChB,IAAI,MAAM;AAAA,QACV,SAAS,MAAM;AAAA,QACf,GAAI,MAAM,UAAU,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,MACpD,CAAC;AAAA,IACH;AAAA,EACJ;AAGA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,aAAa;AAAA,IAChD;AAAA,IACA,YAAY;AACV,YAAM,CAAC,SAAS,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC1C,cAAc,QAAQ,SAAS;AAAA,QAC/B,eAAe,WAAW;AAAA,MAC5B,CAAC;AACD,aAAO,KAAK,EAAE,GAAG,cAAc,OAAO,GAAG,OAAO,CAAC;AAAA,IACnD;AAAA,EACF;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,YAAY;AAAA,IAC/C;AAAA,IACA,OAAO,UAAU;AACf,YAAM,QAAQ,QAAQ,MAAM,YAAY;AACxC,YAAM,QAAQ,QAAQ,MAAM,UAAU;AACtC,YAAM,UAAU,MAAM,cAAc,OAAO;AAAA,QACzC;AAAA,QACA,OAAO,MAAM;AAAA,QACb,OAAO,MAAM;AAAA,QACb,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,QACvD,GAAI,QAAQ,EAAE,cAAc,MAAM,IAAI,CAAC;AAAA,QACvC,GAAI,QAAQ,EAAE,YAAY,MAAM,IAAI,CAAC;AAAA,QACrC,GAAI,MAAM,eAAe,SAAY,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,QACzE,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC1D,GAAI,MAAM,YAAY,SAAY,EAAE,gBAAgB,MAAM,QAAQ,IAAI,CAAC;AAAA,MACzE,CAAC;AACD,aAAO,KAAK,cAAc,OAAO,CAAC;AAAA,IACpC;AAAA,EACF;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,WAAW;AAAA,IAC9C;AAAA,IACA,OAAO,UAAU;AACf,YAAM,QAAQ,MAAM;AACpB,YAAM,QAAQ,QAAQ,MAAM,YAAY;AACxC,YAAM,QAAQ,QAAQ,MAAM,UAAU;AACtC,YAAM,UAAU,MAAM,cAAc,MAAM,MAAM,IAAI;AAAA,QAClD,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC1D,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC1D,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,QACvD,GAAI,QAAQ,EAAE,cAAc,MAAM,IAAI,CAAC;AAAA,QACvC,GAAI,QAAQ,EAAE,YAAY,MAAM,IAAI,CAAC;AAAA,QACrC,GAAI,MAAM,eAAe,SAAY,EAAE,YAAY,MAAM,WAAW,IAAI,CAAC;AAAA,QACzE,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,MAC5D,CAAC;AACD,aAAO,KAAK,cAAc,OAAO,CAAC;AAAA,IACpC;AAAA,EACF;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,YAAY;AAAA,IAC/C;AAAA,IACA,OAAO,UAAU;AACf,UAAI;AACJ,UAAI,MAAM,WAAW,WAAY,QAAO,MAAM,cAAc,QAAQ,MAAM,EAAE;AAAA,eACnE,MAAM,WAAW,YAAa,QAAO,MAAM,cAAc,MAAM,MAAM,EAAE;AAAA,eACvE,MAAM,WAAW;AACxB,eAAO,MAAM,cAAc,SAAS,MAAM,IAAI;AAAA,UAC5C,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,UACtE,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC5D,CAAC;AAAA;AAED,eAAO,MAAM,cAAc;AAAA,UACzB,MAAM;AAAA,UACN,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,QAC3D;AACF,aAAO,KAAK,cAAc,IAAI,CAAC;AAAA,IACjC;AAAA,EACF;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,YAAY;AAAA,IAC/C;AAAA,IACA,OAAO,UACL;AAAA,MACE,MAAM,WAAW;AAAA,QACf,gBAAgB;AAAA,QAChB;AAAA,QACA,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,QAC7D,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC1D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,QAC7D,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,MAC5D,CAAC;AAAA,IACH;AAAA,EACJ;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,UAAU;AAAA,IAC7C;AAAA,IACA,OAAO,UAAU;AACf,YAAM,QAAQ,MAAM,UAAU;AAC9B,aAAO;AAAA,QACL,SAAS,OAAO;AAAA,UACd,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,UACvD,GAAI,MAAM,OAAO,SAAY,EAAE,IAAI,MAAM,GAAG,IAAI,CAAC;AAAA,UACjD,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC5D,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,oBAAoB,eAAe;AAAA,IAClD;AAAA,IACA,OAAO,UAAU,KAAK,WAAW,MAAM,UAAU,GAAG,MAAM,QAAQ,MAAM,SAAS,CAAC;AAAA,EACpF;AAGA,QAAM,cAAc,OAAO;AAQ3B,QAAM,YAAY,YAChB;AAAA,IACE;AAAA,IACA,eAAe,WAAW,EAAE,KAAK,CAAC,EAAE,SAAS,MAAM,QAAQ;AAAA,EAC7D;AAEF;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa,oBAAoB,kBAAkB;AAAA,IACrD;AAAA,IACA,OAAO,UACL;AAAA,MACE,MAAM;AAAA,QACJ;AAAA,QACA,MAAM,sBAAsB;AAAA,UAC1B,gBAAgB;AAAA,UAChB;AAAA,UACA,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,QACrD,CAAC;AAAA,QACD,gBAAgB,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACJ;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa,oBAAoB,oBAAoB;AAAA,IACvD;AAAA,IACA,OAAO,UACL;AAAA,MACE,MAAM;AAAA,QACJ;AAAA,QACA,MAAM,uBAAuB;AAAA,UAC3B,gBAAgB;AAAA,UAChB;AAAA,UACA,gBAAgB;AAAA,UAChB,GAAI,MAAM,eAAe;AAAA,UACzB,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,UACrD,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,UACvD,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,UAC1D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,UAC7D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,UAC7D,GAAI,MAAM,gBAAgB,SAAY,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;AAAA,UAC5E,GAAI,gBAAgB,UAAa,MAAM,gBAAgB,SACnD,EAAE,YAAY,IACd,CAAC;AAAA,QACP,CAAC;AAAA,QACD,gBAAgB,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACJ;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa,oBAAoB,aAAa;AAAA,IAChD;AAAA,IACA,OAAO,UACL;AAAA,MACE,MAAM;AAAA,QACJ;AAAA,QACA,MAAM,uBAAuB;AAAA,UAC3B,gBAAgB;AAAA,UAChB;AAAA,UACA,MAAM,MAAM;AAAA,UACZ,gBAAgB;AAAA,UAChB,GAAI,MAAM,eAAe;AAAA,UACzB,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,UACrD,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,UAC1D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,UAC7D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,UAC7D,aAAa,MAAM,eAAe,eAAe;AAAA,QACnD,CAAC;AAAA,QACD,gBAAgB,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACJ;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa,oBAAoB,mBAAmB;AAAA,IACtD;AAAA,IACA,OAAO,UAAU;AACf,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,UACE,SAAS,MAAM;AAAA,UACf;AAAA,UACA,GAAI,MAAM,iBAAiB,SAAY,EAAE,cAAc,MAAM,aAAa,IAAI,CAAC;AAAA,UAC/E,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,UAC7D,GAAI,MAAM,aAAa,SAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,UACnE,GAAI,MAAM,YAAY,SAAY,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,UAChE,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,UACtE,GAAI,MAAM,iBAAiB,SAAY,EAAE,cAAc,MAAM,aAAa,IAAI,CAAC;AAAA,UAC/E,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,QACxE;AAAA,QACA;AAAA,UACE,gBAAgB;AAAA,UAChB,IAAK,MAAM,cAAc,UAAU,KAAK,IAAI,MAAM,iBAAiB,WAAW,IAAI,CAAC;AAAA,QACrF;AAAA,MACF;AAKA,YAAM,KAAK,MAAM,SAAS,IAAI,EAAE,MAAM,MAAM,MAAS;AACrD,YAAM,IAAI,OAAO,cAAc,EAAE,SAAS,MAAM,CAAC;AACjD,aAAO,KAAK;AAAA,QACV,OAAO,OAAO,MAAM,IAAI,CAAC,OAAO;AAAA,UAC9B,IAAI,EAAE;AAAA,UACN,OAAO,EAAE,UAAU;AAAA,UACnB,SAAS,EAAE,UAAU;AAAA,QACvB,EAAE;AAAA,QACF,iBAAiB,OAAO,gBAAgB,IAAI,CAAC,OAAO;AAAA,UAClD,IAAI,EAAE;AAAA,UACN,OAAO,EAAE,UAAU;AAAA,UACnB,QAAQ,EAAE;AAAA,UACV,WAAW,EAAE;AAAA,QACf,EAAE;AAAA,QACF,SAAS,OAAO,QAAQ;AAAA,QACxB,SAAS,OAAO;AAAA,QAChB,WAAW,OAAO;AAAA,QAClB,WAAW,OAAO;AAAA,QAClB,GAAI,KAAK,CAAC,IAAI,EAAE,UAAU,MAAM,UAAU,SAAS,OAAO,EAAE;AAAA,MAC9D,CAAC;AAAA,IACH;AAAA,EACF;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa,oBAAoB,iBAAiB;AAAA,IACpD;AAAA,IACA,OAAO,UACL;AAAA,MACE,MAAM,oBAAoB;AAAA,QACxB,gBAAgB;AAAA,QAChB;AAAA,QACA,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,QAC1D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,QAC7D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,QAC7D,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,MAC5D,CAAC;AAAA,IACH;AAAA,EACJ;AAEA;AAAA,IACE;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAa,oBAAoB,OAAO;AAAA,IAC1C;AAAA,IACA,YACE,KAAK;AAAA,MACH,UAAU,SAAS,OAAO;AAAA,MAC1B,OAAO;AAAA,QACL;AAAA,QACA,MAAM,WAAW,OAAO,OAAO;AAAA,QAC/B,UAAU,eAAe,OAAO,OAAO;AAAA,MACzC;AAAA,IACF,CAAC;AAAA,EACL;AACF;AAEA,SAAS,gBAAgB,OAIL;AAClB,SAAO,cAAc,KAAgC;AACvD;AAEA,SAAS,gBAAgB,OAAoE;AAC3F,SAAO,cAAc,KAAK;AAC5B;AAEA,SAAS,cAAc,OAAgE;AACrF,QAAM,EAAE,SAAS,UAAU,GAAG,KAAK,IAAI;AACvC,SAAO,cAAc,IAAI;AAC3B;AAQA,SAAS,mBAAmB,QAAsB,SAAkB;AAClE,QAAM,QAAiC,UACnC;AAAA,IACE,YAAY,OAAO,MAAM;AAAA,IACzB,eAAe,OAAO,MAAM;AAAA,IAC5B,cAAc,OAAO,MAAM;AAAA,IAC3B,GAAI,OAAO,MAAM,eAAe,EAAE,cAAc,OAAO,MAAM,aAAa,IAAI,CAAC;AAAA,EACjF,IACA,EAAE,GAAG,OAAO,MAAM;AACtB,QAAM,QAAQ,UACV;AAAA,IACE,QAAQ,OAAO;AAAA,IACf,UAAU,OAAO,SAAS,IAAI,CAAC,aAAa;AAAA,MAC1C,GAAI,QAAQ,OAAO,EAAE,IAAI,QAAQ,KAAK,GAAG,IAAI,CAAC;AAAA,MAC9C,SAAS,QAAQ;AAAA,IACnB,EAAE;AAAA,IACF;AAAA,EACF,IACA,EAAE,GAAG,QAAQ,MAAM;AAEvB,WAAS,OAAO,GAAG,OAAO,GAAG,QAAQ;AACnC,UAAM,aAAa,oBAAoB,KAAK;AAC5C,UAAM,iBAAiB,eAAe,WAAW,QAAQ,CAAC,GAAG,IAAI;AACjE,UAAM,kBAAkB,eAAe,UAAU;AAAA,EACnD;AACA,SAAO;AACT;AAEA,SAAS,cAAc,OAAyD;AAC9E,SAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS,CAAC;AAC5F;;;AK33BA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AACrC,OAAO,UAAU;;;ACFjB,SAAyB,SAASC,gBAAe;AACjD,SAAS,QAAAC,OAAM,UAAU,WAAAC,UAAS,WAAW;;;ACD7C,SAAS,SAAS,eAAe;AACjC,SAAS,WAAAC,gBAAe;AAWxB,IAAM,sBAAsB;AAWrB,SAAS,gBACd,IACA,SACoD;AACpD,MAAI,QAA+B;AACnC,MAAI,UAAgC;AACpC,MAAI,QAAQ;AACZ,MAAI,UAAU;AAId,MAAI,iBAAgC;AACpC,MAAI,eAAsC;AAE1C,QAAM,cAAc,MAAM;AACxB,QAAI,OAAO;AACT,mBAAa,KAAK;AAClB,cAAQ;AAAA,IACV;AACA,QAAI,cAAc;AAChB,mBAAa,YAAY;AACzB,qBAAe;AAAA,IACjB;AACA,qBAAiB;AAAA,EACnB;AAEA,QAAM,MAAM,MAAM;AAEhB,QAAI,WAAW,QAAS;AACxB,gBAAY;AACZ,YAAQ;AACR,eAAW,YAAY;AACrB,UAAI;AACF,cAAM,GAAG;AAAA,MACX,UAAE;AACA,kBAAU;AACV,YAAI,MAAO,UAAS;AAAA,MACtB;AAAA,IACF,GAAG;AAAA,EACL;AAEA,QAAM,WAAW,MAAM;AACrB,QAAI,QAAS;AACb,YAAQ;AACR,QAAI,mBAAmB,MAAM;AAC3B,uBAAiB,KAAK,IAAI;AAC1B,qBAAe,WAAW,KAAK,WAAW;AAAA,IAC5C;AACA,QAAI,MAAO,cAAa,KAAK;AAC7B,YAAQ,WAAW,KAAK,OAAO;AAAA,EACjC;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,YAAY;AAChB,gBAAU;AACV,kBAAY;AACZ,YAAM,SAAS,MAAM,MAAM,MAAS;AAAA,IACtC;AAAA,EACF;AACF;AAGA,IAAM,cAAc;AAYb,SAAS,eAAe,UAAyB,eAAyB,CAAC,GAAY;AAC5F,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,aAAa,SAAS,QAAQ,OAAO,GAAG;AAC9C,SACE,aAAa,KAAK,CAAC,SAAS,eAAe,QAAQ,WAAW,WAAW,GAAG,IAAI,GAAG,CAAC,KACpF,WAAW,WAAW,aAAa,KACnC,WAAW,SAAS,QAAQ,KAC5B,WAAW,WAAW,OAAO,KAC7B,WAAW,SAAS,gBAAgB,KACpC,WAAW,WAAW,eAAe,KACrC,WAAW,SAAS,MAAM;AAE9B;AAOA,eAAsB,gBAAgB,UAAwB,CAAC,GAAkB;AAC/E,QAAM,iBAAiBC,SAAQ,QAAQ,kBAAkB,QAAQ,IAAI,CAAC;AACtE,QAAM,aAAa,QAAQ,cAAc;AAEzC,QAAM,WAAW,YAAY;AAC3B,QAAI;AACF,YAAM,SAAS,MAAM,gBAAgB;AAAA,QACnC;AAAA,QACA,GAAI,QAAQ,MAAM,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC;AAAA,MAC5C,CAAC;AACD,cAAQ,UAAU,MAAM;AAAA,IAC1B,SAAS,OAAO;AACd,cAAQ,UAAU,KAAc;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,SAAS;AAEf,QAAM,YAAY,gBAAgB,UAAU,UAAU;AACtD,QAAM,UAAU,QAAQ,gBAAgB,EAAE,WAAW,KAAK,GAAG,CAAC,QAAQ,aAAa;AACjF,QAAI,eAAe,UAAU,QAAQ,YAAY,EAAG;AACpD,cAAU,QAAQ;AAAA,EACpB,CAAC;AAED,SAAO,IAAI,QAAc,CAAC,mBAAmB;AAC3C,UAAM,OAAO,MAAM;AACjB,cAAQ,MAAM;AAGd,WAAK,UAAU,KAAK,EAAE,KAAK,MAAM,eAAe,CAAC;AAAA,IACnD;AACA,QAAI,QAAQ,QAAQ;AAClB,UAAI,QAAQ,OAAO,QAAS,QAAO,KAAK;AACxC,cAAQ,OAAO,iBAAiB,SAAS,MAAM,EAAE,MAAM,KAAK,CAAC;AAAA,IAC/D;AACA,YAAQ,GAAG,SAAS,MAAM,KAAK,CAAC;AAAA,EAClC,CAAC;AACH;;;AD/HO,SAAS,iBAAiB,SAAgD;AAC/E,QAAM,iBAAiBC,SAAQ,QAAQ,cAAc;AACrD,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,aAAa,IAAI,gBAAgB;AACvC,MAAI,UAAgC;AACpC,MAAI,UAAU;AACd,MAAI,gBAAkC;AACtC,MAAI,gBAA2D;AAG/D,QAAM,oBAAoB,CAAC,SAA8B;AACvD,QAAI,UAAgC;AACpC,QAAI,UAAU;AACd,UAAM,WAAW,MAAM;AACrB,UAAI,QAAS;AACb,UAAI,SAAS;AACX,kBAAU;AACV;AAAA,MACF;AACA,iBAAW,YAAY;AACrB,WAAG;AACD,oBAAU;AACV,gBAAM,KAAK;AAAA,QACb,SAAS,WAAW,CAAC;AAAA,MACvB,GAAG,EAAE,QAAQ,MAAM;AACjB,kBAAU;AACV,YAAI,WAAW,CAAC,QAAS,UAAS;AAAA,MACpC,CAAC;AAAA,IACH;AACA,WAAO,EAAE,UAAU,SAAS,YAAY,SAAS,MAAM,MAAM,MAAS,EAAE;AAAA,EAC1E;AAEA,QAAM,eAAe;AAAA,IAAkB,MACrC,aAAa,EAAE;AAAA,MAAM,CAAC,UACpB,OAAO,MAAM,mCAAoC,MAAgB,OAAO,EAAE;AAAA,IAC5E;AAAA,EACF;AAIA,QAAM,cAAc,kBAAkB,YAAY;AAChD,UAAM,SAAS,MAAM,iBAAiB,gBAAgB,EAAE,QAAQ,WAAW,OAAO,CAAC,EAAE;AAAA,MACnF,CAAC,WAAwB;AAAA,QACvB,QAAQ;AAAA,QACR,QAAS,MAAgB;AAAA,MAC3B;AAAA,IACF;AACA,QAAI,OAAO,WAAW,WAAY,QAAO,KAAK,UAAU,OAAO,MAAM,EAAE;AAAA,EACzE,CAAC;AAED,QAAM,SAAS,YAAY;AAIzB,UAAM,gBAAgB,EAAE,eAAe,CAAC;AACxC,gBAAY,SAAS;AACrB,gBAAY;AACZ,QAAI,QAAQ,UAAU,SAAS;AAC7B,YAAM,aAAa,EAAE;AAAA,QAAM,CAAC,UAC1B,OAAO,MAAM,2CAA4C,MAAgB,OAAO,EAAE;AAAA,MACpF;AAAA,IACF;AAEA,cAAU,gBAAgB;AAAA,MACxB;AAAA,MACA,QAAQ,WAAW;AAAA,MACnB,GAAI,QAAQ,UAAU,UAClB;AAAA,QACE,cAAc;AAAA,UACZ,QAAQ,SAAS,YACb,SAAS,gBAAgBA,SAAQ,gBAAgB,QAAQ,SAAS,SAAS,CAAC,EACzE,MAAM,GAAG,EACT,KAAK,GAAG,IACX;AAAA,QACN;AAAA,MACF,IACA,CAAC;AAAA,MACL,SAAS,CAAC,WAAW;AACnB,YAAI,OAAO,QAAQ,OAAO,UAAU,OAAO,YAAY,EAAG;AAC1D,oBAAY,SAAS;AACrB,YAAI,QAAQ,UAAU,QAAS,cAAa,SAAS;AAAA,MACvD;AAAA,MACA,SAAS,CAAC,UAAU,OAAO,MAAM,mCAAmC,MAAM,OAAO,EAAE;AAAA,IACrF,CAAC;AAKD,SAAK,QAAQ;AAAA,MAAM,CAAC,UAClB,OAAO,MAAM,6CAA8C,MAAgB,OAAO,EAAE;AAAA,IACtF;AAAA,EACF,GAAG,EAAE,MAAM,CAAC,UAAU;AACpB,WAAO,MAAM,0CAA2C,MAAgB,OAAO,EAAE;AACjF,UAAM;AAAA,EACR,CAAC;AAID,WAAS,cAAoB;AAC3B,UAAM,iBAAiB,QAAQ;AAC/B,QAAI,WAAW,CAAC,eAAgB;AAChC,QAAI;AACF,sBAAgB;AAAA,QACd,MACE,eAAe,EAAE;AAAA,UAAM,CAAC,UACtB,OAAO,MAAM,iCAAkC,MAAgB,OAAO,EAAE;AAAA,QAC1E;AAAA,QACF;AAAA,MACF;AACA,sBAAgBC;AAAA,QACdC,MAAK,gBAAgB,cAAc,QAAQ;AAAA,QAC3C,EAAE,WAAW,KAAK;AAAA,QAClB,CAAC,QAAQ,aAAa;AACpB,gBAAM,OAAO,UAAU,QAAQ,OAAO,GAAG,KAAK;AAC9C,cAAI,+CAA+C,KAAK,IAAI,EAAG,gBAAe,QAAQ;AAAA,QACxF;AAAA,MACF;AACA,oBAAc,GAAG,SAAS,MAAM,eAAe,MAAM,CAAC;AAAA,IACxD,SAAS,OAAO;AACd,aAAO,MAAM,yCAA0C,MAAgB,OAAO,EAAE;AAAA,IAClF;AAAA,EACF;AAEA,iBAAe,eAA8B;AAC3C,UAAM,SAAS,MAAM,sBAAsB;AAAA,MACzC;AAAA,MACA,GAAI,QAAQ,UAAU,YAAY,EAAE,WAAW,QAAQ,SAAS,UAAU,IAAI,CAAC;AAAA,IACjF,CAAC;AACD,WAAO,KAAK,4BAA4B,OAAO,KAAK,WAAW,OAAO,KAAK,SAAS;AAAA,EACtF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,QAAQ;AACZ,gBAAU;AACV,iBAAW,MAAM;AACjB,qBAAe,KAAK;AACpB,qBAAe,MAAM;AACrB,YAAM,SAAS,MAAM,MAAM,MAAS;AACpC,YAAM,QAAQ,IAAI,CAAC,aAAa,QAAQ,GAAG,YAAY,QAAQ,CAAC,CAAC;AAAA,IACnE;AAAA,EACF;AACF;;;AEzKA,SAAS,UAAU,YAAY;AAC/B,SAAS,WAAAC,gBAAe;AACxB,SAAS,YAAY,OAAO,WAAAC,gBAAe;AAI3C,eAAsB,8BACpB,gBACA,MAAM,QAAQ,IAAI,GACD;AACjB,MAAI,mBAAmB,UAAa,CAAC,WAAW,cAAc,GAAG;AAC/D,UAAM,IAAI,MAAM,4EAA4E;AAAA,EAC9F;AACA,QAAM,WAAWC,SAAQ,kBAAkB,GAAG;AAC9C,QAAM,OAAO,MAAM,SAAS,QAAQ;AACpC,MAAI,SAAS,MAAM,IAAI,EAAE,QAAQ,SAAU,MAAM,SAASC,SAAQ,CAAC,GAAI;AACrE,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,cAAc,MAAM,KAAK,WAAW,IAAI,CAAC,EAAE;AAAA,IAC/C,CAAC,SAAS,KAAK,OAAO;AAAA,IACtB,MAAM;AAAA,EACR;AACA,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI;AAAA,MACR,2BAA2B,IAAI;AAAA,IAEjC;AAAA,EACF;AACA,SAAO;AACT;;;ACHO,SAAS,mBACd,SACA,UAAgC,CAAC,GACnB;AACd,QAAM,UAAU,QAAQ,WAAW;AACnC,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,SAAS;AAEb,SAAO;AAAA,IACL,MAAM;AACJ,UAAI,QAAS,QAAO,QAAQ,QAAQ,OAAO;AAC3C,UAAI,OAAQ,QAAO,QAAQ,OAAO,IAAI,MAAM,wCAAwC,CAAC;AACrF,UAAI,QAAS,QAAO;AACpB,UAAI,WAAW,KAAK,IAAI,IAAI,QAAQ,KAAK,SAAS;AAChD,eAAO,QAAQ,OAAO,IAAI,MAAM,QAAQ,KAAK,CAAC;AAAA,MAChD;AACA,gBAAU,QAAQ,EACf;AAAA,QACC,OAAO,WAAW;AAChB,cAAI,QAAQ;AACV,kBAAM,OAAO,MAAM;AACnB,kBAAM,IAAI,MAAM,wCAAwC;AAAA,UAC1D;AACA,oBAAU;AACV,oBAAU;AACV,iBAAO;AAAA,QACT;AAAA,QACA,CAAC,UAAmB;AAClB,oBAAU,EAAE,OAAO,cAAc,KAAK,GAAG,IAAI,KAAK,IAAI,EAAE;AACxD,gBAAM;AAAA,QACR;AAAA,MACF,EACC,QAAQ,MAAM;AACb,kBAAU;AAAA,MACZ,CAAC;AACH,aAAO;AAAA,IACT;AAAA,IACA,SAAS;AACP,UAAI,QAAS,QAAO,EAAE,WAAW,MAAM,OAAO,QAAQ;AACtD,UAAI,QAAS,QAAO,EAAE,WAAW,OAAO,OAAO,aAAa;AAC5D,UAAI,CAAC,QAAS,QAAO,EAAE,WAAW,OAAO,OAAO,OAAO;AACvD,aAAO;AAAA,QACL,WAAW;AAAA,QACX,OAAO;AAAA,QACP,OAAO,QAAQ;AAAA,QACf,WAAW,KAAK,IAAI,GAAG,QAAQ,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,IACA,MAAM,QAAQ;AACZ,eAAS;AACT,YAAM,SAAS,MAAM,MAAM,MAAS;AACpC,YAAM,UAAU;AAChB,gBAAU;AACV,YAAM,SAAS,MAAM;AAAA,IACvB;AAAA,EACF;AACF;AAGA,SAAS,cAAc,OAAwB;AAC7C,QAAM,MAAM;AACZ,QAAM,OAAO,KAAK,WAAW,KAAK,QAAQ,OAAO,KAAK;AACtD,SAAO,OAAO,cAAc,IAAI,CAAC,EAAE,MAAM,GAAG,GAAG;AACjD;;;AJzEA,eAAsB,eAAe,UAAiC,CAAC,GAAkB;AACvF,QAAM,SAAS,KAAK,EAAE,OAAO,QAAQ,IAAI,aAAa,OAAO,GAAG,QAAQ,MAAM;AAC9E,MAAI;AACJ,MAAI;AACF,kBAAc,MAAM;AAAA,MAClB,QAAQ,QAAQ,eAAe,QAAQ,IAAI;AAAA,IAC7C;AAAA,EACF,SAAS,OAAO;AAId,WAAO,MAAO,MAAgB,OAAO;AACrC,UAAM,iBAAkB,MAAgB,OAAO;AAC/C;AAAA,EACF;AACA,QAAM,SAAS;AAAA,IACb,GAAI,QAAQ,UAAW,MAAM,kBAAkB,aAAa,EAAE,iBAAiB,MAAM,CAAC;AAAA,IACtF;AAAA,EACF;AAEA,GAAC,OAAO,cACJ,wBACA,sBAAsB,KAAK,EAAE,aAAa,KAAK,CAAC,GAClD,MAAM,MAAM;AACd,QAAM,cAAc,mBAAmB;AAOvC,QAAM,eAAe,OAAO,QAAmB,YAAqB;AAClE,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,cAAc,UAAU,CAAC,IAAI,EAAE,SAAS,MAAM,CAAC;AAC3E,iBAAW,WAAW,OAAO,UAAU;AACrC,eAAO,MAAM,+BAA+B,QAAQ,EAAE,MAAM,QAAQ,KAAK,EAAE;AAAA,MAC7E;AAAA,IACF,SAAS,OAAO;AACd,aAAO,MAAM,yCAA0C,MAAgB,OAAO,EAAE;AAAA,IAClF;AAAA,EACF;AACA,QAAM,WAAW,mBAAmB,YAAY;AAC9C,QAAI;AACF,YAAM,UAAU,MAAM,cAAc,QAAQ,EAAE,eAAe,KAAK,CAAC,EAAE;AAAA,QACnE,CAAC,UAAmB;AAMlB,eAAK,qBAAqB,OAAO,aAAa,OAAO,MAAM,EAAE,KAAK,CAAC,YAAY;AAC7E,gBAAI,QAAS,qBAAoB;AAAA,UACnC,CAAC;AACD,gBAAM;AAAA,QACR;AAAA,MACF;AACA,YAAM,aAAa,QAAQ,QAAQ,IAAI;AACvC,aAAO,KAAK,8CAA8C;AAC1D,aAAO;AAAA,IACT,SAAS,OAAO;AACd,aAAO;AAAA,QACL,0DAA2D,MAAgB,OAAO;AAAA,MACpF;AACA,YAAM;AAAA,IACR;AAAA,EACF,CAAC;AACD,OAAK,SAAS,IAAI,EAAE,MAAM,MAAM,MAAS;AAGzC,QAAM,sBAAsB,CAAC,UAAU,MAAM;AAC3C,QAAI,WAAW,MAAM,SAAS,OAAO,EAAE,UAAU,QAAS;AAC1D,eAAW,MAAM;AACf,WAAK,SAAS,IAAI,EAAE;AAAA,QAClB,MAAM;AAAA,QACN,MAAM,oBAAoB,UAAU,CAAC;AAAA,MACvC;AAAA,IACF,GAAG,GAAK,EAAE,MAAM;AAAA,EAClB;AACA,QAAM,OAAO,iBAAiB;AAAA,IAC5B,gBAAgB;AAAA,IAChB,GAAI,OAAO,WAAW,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;AAAA,IACvD;AAAA;AAAA;AAAA,IAGA,gBAAgB,YAAY;AAC1B,UAAI,SAAS,OAAO,EAAE,UAAU,SAAS;AACvC,cAAM,cAAc,MAAM,SAAS,IAAI,GAAG,QAAQ,KAAK;AAAA,MACzD;AAAA,IACF;AAAA,EACF,CAAC;AACD,QAAM,SAAS,IAAI,UAAU,EAAE,MAAM,aAAa,SAAS,QAAQ,CAAC;AACpE,yBAAuB,QAAQ,EAAE,QAAQ,SAAS,GAAG,WAAW;AAEhE,QAAM,YAAY,YAAY,MAAM,KAAK,eAAe,WAAW,GAAG,GAAM;AAC5E,YAAU,MAAM;AAEhB,QAAM,WAAW,YAAY;AAC3B,WAAO,KAAK,oCAAoC;AAChD,kBAAc,SAAS;AACvB,UAAM,OAAO,MAAM;AACnB,UAAM,KAAK,MAAM;AACjB,UAAM,SAAS,MAAM;AAAA,EACvB;AACA,MAAI;AACJ,QAAM,OAAO,MAAM;AACjB,iBAAa,SAAS,EAAE,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,EACvD;AACA,UAAQ,KAAK,UAAU,IAAI;AAC3B,UAAQ,KAAK,WAAW,IAAI;AAE5B,UAAQ,MAAM,KAAK,OAAO,IAAI;AAE9B,MAAI;AACF,UAAM,KAAK;AACX,UAAM,OAAO,QAAQ,IAAI,qBAAqB,CAAC;AAAA,EACjD,SAAS,OAAO;AACd,UAAM,KAAK,MAAM;AACjB,UAAM,SAAS,MAAM;AACrB,UAAM;AAAA,EACR;AACA,SAAO,KAAK,0DAA0D,WAAW,GAAG;AACtF;AAMA,eAAe,iBAAiB,SAAgC;AAC9D,QAAM,MAAM;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,aAAa,SAAS,QAAQ;AAAA,IACtC;AAAA,MACE,cAAc,qDAAqD,OAAO,eAAe,IAAI,KAAK,GAAG,CAAC;AAAA,IACxG;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aACE;AAAA,IACJ;AAAA,IACA,YAAY,oBAAoB,EAAE,IAAI,OAAO,SAAS,MAAM,SAAS,IAAI,CAAC;AAAA,EAC5E;AACA,QAAM,OAAO,MAAM,KAAK,OAAO,MAAM,EAAE,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC;AACpE,UAAQ,KAAK,UAAU,IAAI;AAC3B,UAAQ,KAAK,WAAW,IAAI;AAC5B,UAAQ,MAAM,KAAK,OAAO,IAAI;AAC9B,QAAM,OAAO,QAAQ,IAAI,qBAAqB,CAAC;AACjD;AAEA,IAAI,uBAAuB;AAS3B,eAAsB,qBACpB,aACA,OACA,QACkB;AAClB,MAAI,wBAAwB,QAAQ,IAAI,+BAA+B,IAAK,QAAO;AACnF,MAAI,CAAC,kBAAkB,WAAW,KAAK,CAAC,oBAAoB,KAAK,EAAG,QAAO;AAC3E,yBAAuB;AACvB,QAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,gCAAqC;AACpF,MAAI,CAAE,MAAM,sBAAsB,GAAI;AACpC,WAAO;AAAA,MACL;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,QAAM,EAAE,SAAS,IAAI,MAAM,OAAO,eAAoB;AACtD,QAAM,UAAU,MAAM,IAAI;AAAA,IAAiB,CAAC,SAC1C;AAAA,MAAS;AAAA,MAAU,CAAC,SAAS,oBAAoB;AAAA,MAAG,EAAE,SAAS,IAAO;AAAA,MAAG,CAAC,WACxE,KAAK,WAAW,IAAI;AAAA,IACtB;AAAA,EACF;AACA,MAAI,SAAS;AACX,WAAO,KAAK,wEAAwE;AACpF,WAAO;AAAA,EACT;AACA,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,+BAAoC;AACxE,QAAM,SAAS,MAAM,WAAW,EAAE,MAAM,OAAO,EAAE,MAAM,GAAG,QAAQ,wBAAwB,EAAE;AAC5F,MAAI,OAAO,SAAS,GAAG;AACrB,WAAO,KAAK,gEAAgE;AAC5E,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,qDAAqD,OAAO,OAAO,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC;AAAA,EACjG;AACA,SAAO;AACT;AAGO,SAAS,kBAAkB,aAA8B;AAC9D,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,WAAW;AAC/B,WACE,CAAC,aAAa,aAAa,OAAO,OAAO,EAAE,SAAS,IAAI,QAAQ,MAC/D,IAAI,SAAS,MAAM,IAAI,SAAS,WACjC,IAAI,aAAa;AAAA,EAErB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,oBAAoB,OAAyB;AACpD,WACM,UAAU,OACd,WACA;AACA,QAAI,QAAQ,SAAS,eAAgB,QAAO;AAC5C,QACE,MAAM,QAAQ,QAAQ,MAAM,KAC5B,QAAQ,OAAO,KAAK,CAAC,UAAU,oBAAoB,KAAK,CAAC,GACzD;AACA,aAAO;AAAA,IACT;AACA,cAAU,QAAQ;AAAA,EACpB;AACA,SAAO;AACT;","names":["createHash","createHash","createHash","createHash","join","join","fsWatch","join","resolve","resolve","resolve","resolve","fsWatch","join","homedir","resolve","resolve","homedir"]}
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-FJOTP632.js";
6
6
  import {
7
7
  recordTrace
8
- } from "./chunk-XL2HLACE.js";
8
+ } from "./chunk-YN7TEIUH.js";
9
9
  import {
10
10
  hookRoot
11
11
  } from "./chunk-TGFTKWOR.js";
@@ -212,4 +212,4 @@ async function runPreToolHookCommand() {
212
212
  export {
213
213
  runPreToolHookCommand
214
214
  };
215
- //# sourceMappingURL=chunk-EJQVGFH2.js.map
215
+ //# sourceMappingURL=chunk-ENKDFLOO.js.map
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-GKNYMNFM.js";
7
7
  import {
8
8
  recordTrace
9
- } from "./chunk-XL2HLACE.js";
9
+ } from "./chunk-YN7TEIUH.js";
10
10
  import {
11
11
  hookRoot
12
12
  } from "./chunk-TGFTKWOR.js";
@@ -21,7 +21,7 @@ import {
21
21
  isEligibleMemory,
22
22
  lexicalTerms,
23
23
  termOverlap
24
- } from "./chunk-6KGYAFG7.js";
24
+ } from "./chunk-SRA4MDVG.js";
25
25
  import {
26
26
  generateEntityId
27
27
  } from "./chunk-CAEPHLHC.js";
@@ -2962,7 +2962,7 @@ async function openHookSemantics(repositoryRoot) {
2962
2962
  const connect = async () => {
2963
2963
  const config = await loadRuntimeConfig(repositoryRoot, { requireDatabase: false });
2964
2964
  if (!config.postgresUrl) return null;
2965
- const { createRuntime } = await import("./operations-WJR7AZZF.js");
2965
+ const { createRuntime } = await import("./operations-OG4ISWIM.js");
2966
2966
  const opening = createRuntime(config, {
2967
2967
  repositoryRoot,
2968
2968
  startWorker: false,
@@ -3346,7 +3346,7 @@ async function runSyncHook(repositoryRoot, options = {}) {
3346
3346
  await writeFile(dirty, "").catch(() => void 0);
3347
3347
  return null;
3348
3348
  }
3349
- const { createRuntime } = await import("./operations-WJR7AZZF.js");
3349
+ const { createRuntime } = await import("./operations-OG4ISWIM.js");
3350
3350
  const runtime = await createRuntime(config, { repositoryRoot }).catch(async (error) => {
3351
3351
  await rm4(lock, { recursive: true, force: true });
3352
3352
  throw error;
@@ -3791,4 +3791,4 @@ export {
3791
3791
  lastAssistantMessage,
3792
3792
  renderContextBlock
3793
3793
  };
3794
- //# sourceMappingURL=chunk-ZNLSCV3J.js.map
3794
+ //# sourceMappingURL=chunk-F4BJ3DXW.js.map
@@ -13,7 +13,7 @@ import {
13
13
  sessionSummaries,
14
14
  shares,
15
15
  validSearchVector
16
- } from "./chunk-6KGYAFG7.js";
16
+ } from "./chunk-SRA4MDVG.js";
17
17
  import {
18
18
  clampBudgetForCallerModel,
19
19
  computeContentHash,
@@ -3320,4 +3320,4 @@ export {
3320
3320
  inspectNamespace,
3321
3321
  runDoctor
3322
3322
  };
3323
- //# sourceMappingURL=chunk-NY2YXP3R.js.map
3323
+ //# sourceMappingURL=chunk-QN76UJP7.js.map
@@ -14,7 +14,7 @@ import {
14
14
  // package.json
15
15
  var package_default = {
16
16
  name: "@orquentra/codebuddy",
17
- version: "2.8.0",
17
+ version: "2.9.0",
18
18
  description: "Local-first project context and memory for AI coding agents.",
19
19
  type: "module",
20
20
  license: "MIT",
@@ -1011,4 +1011,4 @@ export {
1011
1011
  INCIDENT_SEVERITIES,
1012
1012
  MemoryFileStore
1013
1013
  };
1014
- //# sourceMappingURL=chunk-6KGYAFG7.js.map
1014
+ //# sourceMappingURL=chunk-SRA4MDVG.js.map