@remnic/core 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abort-error.d.ts +32 -0
- package/dist/abort-error.js +11 -0
- package/dist/access-cli.js +41 -40
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +3 -2
- package/dist/access-http.js +11 -11
- package/dist/access-mcp.d.ts +3 -2
- package/dist/access-mcp.js +7 -7
- package/dist/access-schema.d.ts +16 -16
- package/dist/access-service-HmO1Trrx.d.ts +732 -0
- package/dist/access-service.d.ts +11 -658
- package/dist/access-service.js +9 -9
- package/dist/bootstrap.d.ts +1 -1
- package/dist/briefing.js +6 -6
- package/dist/calibration.js +3 -3
- package/dist/causal-consolidation.js +10 -10
- package/dist/{chunk-PMB3WGDL.js → chunk-37UIFYWO.js} +64 -3
- package/dist/chunk-37UIFYWO.js.map +1 -0
- package/dist/{chunk-X4WESCKA.js → chunk-3QHL5ABG.js} +5 -5
- package/dist/{chunk-2VFW5K5U.js → chunk-3SV6CQHO.js} +10 -8
- package/dist/chunk-3SV6CQHO.js.map +1 -0
- package/dist/{chunk-U2IQTSBY.js → chunk-3WHVNEN7.js} +1 -1
- package/dist/chunk-3WHVNEN7.js.map +1 -0
- package/dist/{chunk-QKAH5B6E.js → chunk-44ICJRF3.js} +97 -9
- package/dist/chunk-44ICJRF3.js.map +1 -0
- package/dist/{chunk-S4LX5EBI.js → chunk-47UU5PU2.js} +48 -9
- package/dist/chunk-47UU5PU2.js.map +1 -0
- package/dist/{chunk-ECKDIK5F.js → chunk-4LACOVZX.js} +2 -2
- package/dist/{chunk-AYPYCLR7.js → chunk-6LX5ORAS.js} +2 -2
- package/dist/{chunk-GJQPH5G3.js → chunk-6UJ47TVX.js} +2 -2
- package/dist/{chunk-KWP7T3DP.js → chunk-7ECD5ATE.js} +2 -2
- package/dist/{chunk-74JR4N5J.js → chunk-7WQ6SLIE.js} +2 -2
- package/dist/{chunk-7PA4OZEU.js → chunk-BLKTA7MM.js} +6 -14
- package/dist/chunk-BLKTA7MM.js.map +1 -0
- package/dist/{chunk-XMGSSBFX.js → chunk-DEPL3635.js} +172 -100
- package/dist/chunk-DEPL3635.js.map +1 -0
- package/dist/{chunk-JROGC36Y.js → chunk-DHHP2Z4X.js} +2 -2
- package/dist/{chunk-BKQJBXXX.js → chunk-GGD5W7TB.js} +2 -2
- package/dist/chunk-GGD5W7TB.js.map +1 -0
- package/dist/{chunk-POMSFKTB.js → chunk-GV6NLQ4X.js} +14 -14
- package/dist/{chunk-AAI7JARD.js → chunk-HMDCOMYU.js} +8 -11
- package/dist/chunk-HMDCOMYU.js.map +1 -0
- package/dist/{chunk-POBPGDWI.js → chunk-ITRLGI2T.js} +2 -2
- package/dist/{chunk-MYQWXITD.js → chunk-JIU55F3X.js} +2 -2
- package/dist/{chunk-UPMD5XND.js → chunk-JL2PU6AI.js} +16 -5
- package/dist/chunk-JL2PU6AI.js.map +1 -0
- package/dist/{chunk-OJFGVJS6.js → chunk-MBJHSA7F.js} +65 -9
- package/dist/chunk-MBJHSA7F.js.map +1 -0
- package/dist/{chunk-V7XCAHIB.js → chunk-MVTHXUBX.js} +46 -23
- package/dist/chunk-MVTHXUBX.js.map +1 -0
- package/dist/{chunk-BTY5RRRF.js → chunk-N42IWANG.js} +5 -5
- package/dist/{chunk-NSB3WSYS.js → chunk-NQEVYWX6.js} +74 -3
- package/dist/chunk-NQEVYWX6.js.map +1 -0
- package/dist/chunk-OIT5QGG4.js +80 -0
- package/dist/chunk-OIT5QGG4.js.map +1 -0
- package/dist/chunk-PVGDJXVK.js +21 -0
- package/dist/chunk-PVGDJXVK.js.map +1 -0
- package/dist/{chunk-RCICHSHL.js → chunk-SYUK3VLY.js} +2 -2
- package/dist/{chunk-YFYL2SIJ.js → chunk-WBSAYXVI.js} +127 -39
- package/dist/chunk-WBSAYXVI.js.map +1 -0
- package/dist/{chunk-KEG4GNGI.js → chunk-XZ2TIKGC.js} +38 -8
- package/dist/chunk-XZ2TIKGC.js.map +1 -0
- package/dist/chunk-Y4FHOFJ2.js +140 -0
- package/dist/chunk-Y4FHOFJ2.js.map +1 -0
- package/dist/chunk-YNB73F22.js +137 -0
- package/dist/chunk-YNB73F22.js.map +1 -0
- package/dist/{chunk-HITJFT7E.js → chunk-ZVBB3T7V.js} +10 -5
- package/dist/chunk-ZVBB3T7V.js.map +1 -0
- package/dist/{cli-DwIBnp2g.d.ts → cli-BneVIEvh.d.ts} +2 -2
- package/dist/cli.d.ts +4 -3
- package/dist/cli.js +25 -24
- package/dist/config.js +1 -1
- package/dist/contradiction-review-WIUBAR52.js +21 -0
- package/dist/contradiction-review-WIUBAR52.js.map +1 -0
- package/dist/contradiction-scan-GR33PONM.js +376 -0
- package/dist/contradiction-scan-GR33PONM.js.map +1 -0
- package/dist/direct-answer-wiring.d.ts +77 -0
- package/dist/direct-answer-wiring.js +75 -0
- package/dist/direct-answer-wiring.js.map +1 -0
- package/dist/direct-answer.d.ts +106 -0
- package/dist/direct-answer.js +10 -0
- package/dist/direct-answer.js.map +1 -0
- package/dist/{engine-X7X3AAG3.js → engine-5TIQBYZR.js} +7 -7
- package/dist/engine-5TIQBYZR.js.map +1 -0
- package/dist/entity-retrieval.js +6 -6
- package/dist/explicit-capture.d.ts +1 -1
- package/dist/extraction.js +6 -6
- package/dist/fallback-llm.d.ts +11 -2
- package/dist/fallback-llm.js +3 -3
- package/dist/harmonic-retrieval.js +2 -1
- package/dist/index.d.ts +10 -124
- package/dist/index.js +74 -137
- package/dist/index.js.map +1 -1
- package/dist/intent.js +1 -1
- package/dist/local-llm.d.ts +10 -3
- package/dist/local-llm.js +1 -1
- package/dist/operator-toolkit.js +12 -11
- package/dist/{orchestrator-B9kwlCep.d.ts → orchestrator-DRYA6_lW.d.ts} +21 -2
- package/dist/orchestrator.d.ts +1 -1
- package/dist/orchestrator.js +36 -35
- package/dist/qmd.js +2 -1
- package/dist/recall-state.d.ts +28 -1
- package/dist/recall-state.js +1 -1
- package/dist/resolution-QBTDHTG7.js +100 -0
- package/dist/resolution-QBTDHTG7.js.map +1 -0
- package/dist/resolve-provider-secret.d.ts +24 -1
- package/dist/resolve-provider-secret.js +3 -1
- package/dist/resume-bundles.js +3 -3
- package/dist/schemas.d.ts +14 -14
- package/dist/semantic-consolidation.js +6 -6
- package/dist/semantic-rule-promotion.js +6 -6
- package/dist/semantic-rule-verifier.js +6 -6
- package/dist/storage.js +5 -5
- package/dist/summarizer.js +5 -5
- package/dist/types-DJhqDJUV.d.ts +50 -0
- package/dist/types.d.ts +34 -2
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +6 -6
- package/package.json +1 -1
- package/dist/chunk-2VFW5K5U.js.map +0 -1
- package/dist/chunk-7PA4OZEU.js.map +0 -1
- package/dist/chunk-AAI7JARD.js.map +0 -1
- package/dist/chunk-BKQJBXXX.js.map +0 -1
- package/dist/chunk-HITJFT7E.js.map +0 -1
- package/dist/chunk-KEG4GNGI.js.map +0 -1
- package/dist/chunk-NSB3WSYS.js.map +0 -1
- package/dist/chunk-OJFGVJS6.js.map +0 -1
- package/dist/chunk-PMB3WGDL.js.map +0 -1
- package/dist/chunk-QKAH5B6E.js.map +0 -1
- package/dist/chunk-S4LX5EBI.js.map +0 -1
- package/dist/chunk-U2IQTSBY.js.map +0 -1
- package/dist/chunk-UPMD5XND.js.map +0 -1
- package/dist/chunk-V7XCAHIB.js.map +0 -1
- package/dist/chunk-XMGSSBFX.js.map +0 -1
- package/dist/chunk-YFYL2SIJ.js.map +0 -1
- /package/dist/{engine-X7X3AAG3.js.map → abort-error.js.map} +0 -0
- /package/dist/{chunk-X4WESCKA.js.map → chunk-3QHL5ABG.js.map} +0 -0
- /package/dist/{chunk-ECKDIK5F.js.map → chunk-4LACOVZX.js.map} +0 -0
- /package/dist/{chunk-AYPYCLR7.js.map → chunk-6LX5ORAS.js.map} +0 -0
- /package/dist/{chunk-GJQPH5G3.js.map → chunk-6UJ47TVX.js.map} +0 -0
- /package/dist/{chunk-KWP7T3DP.js.map → chunk-7ECD5ATE.js.map} +0 -0
- /package/dist/{chunk-74JR4N5J.js.map → chunk-7WQ6SLIE.js.map} +0 -0
- /package/dist/{chunk-JROGC36Y.js.map → chunk-DHHP2Z4X.js.map} +0 -0
- /package/dist/{chunk-POMSFKTB.js.map → chunk-GV6NLQ4X.js.map} +0 -0
- /package/dist/{chunk-POBPGDWI.js.map → chunk-ITRLGI2T.js.map} +0 -0
- /package/dist/{chunk-MYQWXITD.js.map → chunk-JIU55F3X.js.map} +0 -0
- /package/dist/{chunk-BTY5RRRF.js.map → chunk-N42IWANG.js.map} +0 -0
- /package/dist/{chunk-RCICHSHL.js.map → chunk-SYUK3VLY.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/qmd.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { log } from \"./logger.js\";\nimport { getCachedQmdSearch, setCachedQmdSearch } from \"./memory-cache.js\";\nimport {\n abortError,\n isAbortError,\n throwIfAborted,\n} from \"./abort-error.js\";\nimport type { QmdSearchExplain, QmdSearchResult } from \"./types.js\";\nimport type { SearchBackend, SearchExecutionOptions, SearchQueryOptions } from \"./search/port.js\";\nimport { launchProcess, type CommandChildProcess } from \"./runtime/child-process.js\";\nimport { mergeEnv } from \"./runtime/env.js\";\n\nexport interface QmdClientOptions {\n slowLog?: { enabled: boolean; thresholdMs: number };\n updateTimeoutMs?: number;\n updateMinIntervalMs?: number;\n qmdPath?: string;\n daemonUrl?: string;\n daemonRecheckIntervalMs?: number;\n}\n\nconst QMD_TIMEOUT_MS = 30_000;\n// Daemon timeout for individual search calls. Keep well under RECALL_TIMEOUT_MS (75s) so a\n// slow/loading daemon fails fast and the caller can return early rather than hanging.\n// After the daemon has loaded its index (~90s for 75K files), actual searches complete in <3s.\n// During the loading window, searches will timeout/return [] quickly — this is preferable to\n// blocking the full 75s on every recall request.\n// Note: keep this ≥ 5s to allow normal searches (post-load) to complete reliably.\nconst QMD_DAEMON_TIMEOUT_MS = 8_000;\nconst QMD_PROBE_TIMEOUT_MS = 8_000;\nconst QMD_UPDATE_BACKOFF_MS = 15 * 60 * 1000; // 15m\nconst QMD_EMBED_BACKOFF_MS = 60 * 60 * 1000; // 60m\nconst QMD_CLI_WARN_THROTTLE_MS = 15 * 60 * 1000; // 15m\nconst QMD_FALLBACK_PATHS = [\n path.join(os.homedir(), \".bun\", \"bin\", \"qmd\"),\n \"/usr/local/bin/qmd\",\n \"/opt/homebrew/bin/qmd\",\n];\nconst QMD_GLOBAL_STATE_KEY = \"__openclawEngramQmdGlobalState\";\n\ntype QmdGlobalState = {\n warnedGlobalUpdateBehavior: boolean;\n lastGlobalUpdateRunAtMs: number | null;\n lastGlobalUpdateFailAtMs: number | null;\n lastGlobalEmbedRunAtMs: number | null;\n lastGlobalEmbedFailAtMs: number | null;\n lastCliWarnAtMs: number | null;\n lastUpdateByCollectionMs: Record<string, number>;\n lastUpdateFailByCollectionMs: Record<string, number>;\n lastEmbedByCollectionMs: Record<string, number>;\n lastEmbedFailByCollectionMs: Record<string, number>;\n};\n\nfunction getGlobalQmdState(): QmdGlobalState {\n const g = globalThis as any;\n if (!g[QMD_GLOBAL_STATE_KEY]) {\n g[QMD_GLOBAL_STATE_KEY] = {\n warnedGlobalUpdateBehavior: false,\n lastGlobalUpdateRunAtMs: null,\n lastGlobalUpdateFailAtMs: null,\n lastGlobalEmbedRunAtMs: null,\n lastGlobalEmbedFailAtMs: null,\n lastCliWarnAtMs: null,\n lastUpdateByCollectionMs: {},\n lastUpdateFailByCollectionMs: {},\n lastEmbedByCollectionMs: {},\n lastEmbedFailByCollectionMs: {},\n } satisfies QmdGlobalState;\n }\n return g[QMD_GLOBAL_STATE_KEY] as QmdGlobalState;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nfunction errorMessage(err: unknown): string {\n if (typeof err === \"string\") return err;\n if (err instanceof Error) return err.message;\n if (err && typeof err === \"object\" && \"message\" in err && typeof (err as { message?: unknown }).message === \"string\") {\n return (err as { message: string }).message;\n }\n return String(err);\n}\n\nfunction isCallerCancellation(err: unknown, signal?: AbortSignal): boolean {\n if (signal?.aborted) return true;\n if (isAbortError(err)) return true;\n if (err && typeof err === \"object\") {\n const code = \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (code === \"ABORT_ERR\" || code === \"ERR_CANCELED\") return true;\n }\n return false;\n}\n\nfunction isDaemonTimeoutError(err: unknown): boolean {\n return /timed out/i.test(errorMessage(err));\n}\n\nfunction sleepWithSignal(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n throwIfAborted(signal);\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n cleanup();\n reject(abortError(\"operation aborted while waiting\"));\n };\n const cleanup = () => {\n signal?.removeEventListener(\"abort\", onAbort);\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction isSqliteBusyError(msg: string): boolean {\n const lower = msg.toLowerCase();\n return (\n lower.includes(\"database is locked\") ||\n lower.includes(\"sqlite_busy\") ||\n lower.includes(\"sqlite_busy_recovery\") ||\n lower.includes(\"sqliterror: database is locked\")\n );\n}\n\nfunction stripControlChars(s: string): string {\n // Remove ANSI escapes and other control characters that explode logs.\n return s.replace(/\\x1b\\[[0-9;]*[A-Za-z]/g, \"\").replace(/[\\u0000-\\u001f\\u007f]/g, \"\");\n}\n\nfunction truncateForLog(s: string, max = 2000): string {\n const cleaned = stripControlChars(s);\n return cleaned.length > max ? cleaned.slice(0, max) + \"…(truncated)\" : cleaned;\n}\n\nfunction isVectorDimensionMismatchError(err: unknown): boolean {\n const msg = err instanceof Error ? err.message : String(err);\n return (\n /dimension mismatch/i.test(msg) ||\n (/vectors?_vec/i.test(msg) && /float\\[\\d+\\]/i.test(msg)) ||\n (/embedding/i.test(msg) && /dimensions?/i.test(msg))\n );\n}\n\nfunction parseQmdVersion(version: string | null): [number, number, number] | null {\n if (!version) return null;\n const match = version.match(/v?(\\d{1,10})\\.(\\d{1,10})\\.(\\d{1,10})/i);\n if (!match) return null;\n return [\n Number.parseInt(match[1] ?? \"0\", 10),\n Number.parseInt(match[2] ?? \"0\", 10),\n Number.parseInt(match[3] ?? \"0\", 10),\n ];\n}\n\nfunction versionAtLeast(\n current: [number, number, number] | null,\n target: [number, number, number],\n): boolean {\n if (!current) return false;\n for (let i = 0; i < 3; i += 1) {\n if ((current[i] ?? 0) > target[i]) return true;\n if ((current[i] ?? 0) < target[i]) return false;\n }\n return true;\n}\n\nfunction normalizeSearchOptions(options?: SearchQueryOptions): SearchQueryOptions | undefined {\n if (!options) return undefined;\n const intent = typeof options.intent === \"string\" ? options.intent.trim() : \"\";\n const normalized: SearchQueryOptions = {};\n if (intent.length > 0) {\n normalized.intent = intent;\n }\n if (options.explain === true) {\n normalized.explain = true;\n }\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\nfunction parseExplainScores(value: unknown): number[] | undefined {\n if (!Array.isArray(value)) return undefined;\n const scores = value.filter((entry): entry is number => typeof entry === \"number\");\n return scores.length > 0 ? scores : undefined;\n}\n\nexport function parseQmdExplain(value: unknown): QmdSearchExplain | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const candidate = value as Record<string, unknown>;\n const parsed: QmdSearchExplain = {\n ftsScores: parseExplainScores(candidate.ftsScores),\n vectorScores: parseExplainScores(candidate.vectorScores),\n rrf: typeof candidate.rrf === \"number\" ? candidate.rrf : undefined,\n rerankScore: typeof candidate.rerankScore === \"number\" ? candidate.rerankScore : undefined,\n blendedScore: typeof candidate.blendedScore === \"number\" ? candidate.blendedScore : undefined,\n };\n return Object.values(parsed).some((entry) => entry !== undefined) ? parsed : undefined;\n}\n\nclass AsyncMutex {\n private locked = false;\n private queue: Array<{\n resolve: (release: () => void) => void;\n reject: (reason: Error) => void;\n signal?: AbortSignal;\n onAbort: () => void;\n }> = [];\n\n async runExclusive<T>(fn: () => Promise<T>, signal?: AbortSignal): Promise<T> {\n const release = await this.acquire(signal);\n try {\n throwIfAborted(signal);\n return await fn();\n } finally {\n release();\n }\n }\n\n private acquire(signal?: AbortSignal): Promise<() => void> {\n throwIfAborted(signal);\n if (!this.locked) {\n this.locked = true;\n return Promise.resolve(() => this.release());\n }\n\n return new Promise((resolve, reject) => {\n const waiter = {\n resolve: (release: () => void) => {\n signal?.removeEventListener(\"abort\", waiter.onAbort);\n resolve(release);\n },\n reject: (reason: Error) => {\n signal?.removeEventListener(\"abort\", waiter.onAbort);\n reject(reason);\n },\n signal,\n onAbort: () => {\n this.queue = this.queue.filter((entry) => entry !== waiter);\n reject(abortError(\"operation aborted while waiting for qmd mutex\"));\n },\n };\n signal?.addEventListener(\"abort\", waiter.onAbort, { once: true });\n this.queue.push(waiter);\n });\n }\n\n private release(): void {\n while (this.queue.length > 0) {\n const next = this.queue.shift();\n if (!next) break;\n if (next.signal?.aborted) {\n next.reject(abortError(\"operation aborted while waiting for qmd mutex\"));\n continue;\n }\n this.locked = true;\n next.resolve(() => this.release());\n return;\n }\n this.locked = false;\n }\n}\n\nconst QMD_MUTEX = new AsyncMutex();\n\nfunction runQmd(\n args: string[],\n timeoutMs: number = QMD_TIMEOUT_MS,\n qmdPath: string = \"qmd\",\n signal?: AbortSignal,\n): Promise<{ stdout: string; stderr: string }> {\n // Serialize all qmd calls. This avoids SQLite lock contention when multiple\n // channels/agents trigger QMD operations at nearly the same time.\n return QMD_MUTEX.runExclusive(async () => {\n throwIfAborted(signal, `qmd ${args.join(\" \")} aborted before start`);\n const maxAttempts = isLikelyWriteCommand(args) ? 3 : 1;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await runQmdOnce(args, timeoutMs, qmdPath, signal);\n } catch (err) {\n if (isAbortError(err)) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n if (attempt < maxAttempts && isSqliteBusyError(msg)) {\n // Another qmd call (or an external qmd process) currently holds the DB.\n // Back off briefly and retry.\n await sleepWithSignal(1500 * attempt, signal);\n continue;\n }\n throw err;\n }\n }\n // unreachable\n throw new Error(\"qmd command failed\");\n }, signal);\n}\n\nfunction isLikelyWriteCommand(args: string[]): boolean {\n const cmd = args[0] ?? \"\";\n return cmd === \"update\" || cmd === \"embed\" || cmd === \"cleanup\" || cmd === \"collection\";\n}\n\nfunction runQmdOnce(\n args: string[],\n timeoutMs: number,\n qmdPath: string,\n signal?: AbortSignal,\n): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n throwIfAborted(signal, `qmd ${args.join(\" \")} aborted before spawn`);\n const child = launchProcess(qmdPath, args, {\n env: mergeEnv({ NO_COLOR: \"1\" }),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n if (!child.stdout || !child.stderr) {\n reject(new Error(`qmd ${args.join(\" \")} failed to open stdio pipes`));\n return;\n }\n\n let stdout = \"\";\n let stderr = \"\";\n let settled = false;\n\n const timer = setTimeout(() => {\n settled = true;\n cleanup();\n child.kill(\"SIGKILL\");\n reject(new Error(`qmd ${args.join(\" \")} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n const onAbort = () => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n cleanup();\n child.kill(\"SIGKILL\");\n reject(abortError(`qmd ${args.join(\" \")} aborted`));\n };\n const cleanup = () => {\n signal?.removeEventListener(\"abort\", onAbort);\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n child.stdout.on(\"data\", (data: Buffer) => {\n stdout += data.toString();\n });\n child.stderr.on(\"data\", (data: Buffer) => {\n stderr += data.toString();\n });\n child.on(\"error\", (err) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n cleanup();\n reject(err);\n });\n child.on(\"close\", (code) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n cleanup();\n // QMD returns exit code 1 for --version (shows usage), but that's ok\n const isVersionCheck = args.length === 1 && args[0] === \"--version\";\n if (code === 0 || (isVersionCheck && code === 1)) {\n resolve({ stdout, stderr });\n } else {\n reject(\n new Error(\n `qmd ${args.join(\" \")} failed (code ${code}): ${truncateForLog(stderr || stdout)}`,\n ),\n );\n }\n });\n });\n}\n\n// ---------------------------------------------------------------------------\n// QMD Stdio Daemon Session (MCP over stdio child process)\n// ---------------------------------------------------------------------------\n\nlet nextJsonRpcId = 1;\n\nclass QmdDaemonSession {\n private child: CommandChildProcess | null = null;\n private initialized = false;\n private buffer = \"\";\n private startPromise: Promise<boolean> | null = null;\n private pendingRequests = new Map<\n number,\n {\n resolve: (value: unknown) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n cleanup: () => void;\n }\n >();\n private readonly qmdPath: string;\n\n constructor(qmdPath: string) {\n this.qmdPath = qmdPath;\n }\n\n /** Spawn the qmd mcp child process and perform MCP handshake. */\n async start(): Promise<boolean> {\n if (this.child && !this.child.killed && this.initialized) {\n return true;\n }\n if (this.startPromise) {\n return this.startPromise;\n }\n this.startPromise = (async () => {\n // If the process is already running but not yet initialized (e.g. it is still\n // loading its index after a previous handshake timeout), reuse it instead of\n // killing and re-spawning. This prevents accumulating zombie qmd-mcp processes\n // when the daemon takes >15s to load a large collection.\n const processAlreadyRunning = this.child != null && !this.child.killed;\n if (!processAlreadyRunning) {\n if (this.child) {\n this.cleanup({ killChild: true });\n }\n try {\n const child = launchProcess(this.qmdPath, [\"mcp\"], {\n env: mergeEnv({ NO_COLOR: \"1\" }),\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n this.child = child;\n this.buffer = \"\";\n\n child.stdout?.on(\"data\", (data: Buffer) => {\n if (this.child !== child) return;\n this.handleStdoutData(data);\n });\n child.stderr?.on(\"data\", (data: Buffer) => {\n if (this.child !== child) return;\n const msg = data.toString().trim();\n if (msg) log.debug(`QMD mcp stderr: ${stripControlChars(msg)}`);\n });\n child.stdin?.on(\"error\", (err) => {\n // Swallow EPIPE/ERR_STREAM_DESTROYED — these happen when the child\n // process is killed (e.g. due to recall timeout) and a write arrives\n // after the pipe is broken. Without this handler Node.js would throw\n // an uncaught exception and crash the process.\n log.debug(`QMD mcp stdin error (suppressed): ${err.message}`);\n });\n child.on(\"error\", (err) => {\n if (this.child !== child) return;\n log.debug(`QMD mcp process error: ${err.message}`);\n this.cleanup({ child });\n });\n child.on(\"close\", (code) => {\n if (this.child !== child) return;\n log.debug(`QMD mcp process exited (code ${code})`);\n this.cleanup({ child });\n });\n } catch (err) {\n log.debug(`QMD mcp: failed to spawn process: ${err}`);\n this.cleanup({ killChild: true });\n return false;\n }\n } else {\n log.debug(\"QMD mcp: process already running, retrying handshake\");\n }\n\n try {\n // Use a generous timeout — large collections (75K+ files) can take 60-90s\n // to load their vector index. We keep the process alive across retries so\n // only one mcp instance is running at a time.\n const result = await this.sendRequest(\n \"initialize\",\n {\n protocolVersion: \"2024-11-05\",\n capabilities: {},\n clientInfo: { name: \"openclaw-remnic\", version: \"1.0.0\" },\n },\n 60_000,\n );\n if (!result) {\n // Null result (non-timeout failure) — kill and let the next probe respawn.\n this.cleanup({ killChild: true });\n return false;\n }\n this.sendNotification(\"notifications/initialized\");\n this.initialized = true;\n log.info(\"QMD mcp: stdio session initialized\");\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (/timed out/i.test(msg)) {\n // Handshake timeout — process is still loading. Keep it alive for the\n // next retry (daemonRecheckIntervalMs). Do NOT kill and respawn.\n log.debug(`QMD mcp: handshake timed out — process still loading, will retry later`);\n // Reset initialized flag but leave child running.\n this.initialized = false;\n } else {\n log.debug(`QMD mcp: failed to start stdio session: ${err}`);\n this.cleanup({ killChild: true });\n }\n return false;\n } finally {\n this.startPromise = null;\n }\n })();\n return this.startPromise;\n }\n\n /** Call an MCP tool and return the parsed result. */\n async callTool(\n name: string,\n args: Record<string, unknown>,\n timeoutMs: number = 30_000,\n signal?: AbortSignal,\n ): Promise<unknown> {\n if (!this.child || this.child.killed || !this.initialized) {\n throw new Error(\"QMD mcp process not running\");\n }\n return this.sendRequest(\"tools/call\", { name, arguments: args }, timeoutMs, signal);\n }\n\n /** Kill stdio process and clear state so the next probe can restart. */\n invalidate(): void {\n this.cleanup({ killChild: true });\n }\n\n isActive(): boolean {\n return this.child !== null && !this.child.killed && this.initialized;\n }\n\n /** True while the process is spawned but the MCP handshake has not yet completed. */\n isLoading(): boolean {\n return this.child !== null && !this.child.killed && !this.initialized;\n }\n\n private sendRequest(\n method: string,\n params: Record<string, unknown>,\n timeoutMs: number,\n signal?: AbortSignal,\n ): Promise<unknown> {\n return new Promise((resolve, reject) => {\n throwIfAborted(signal, `QMD mcp ${method} aborted before request`);\n if (!this.child || !this.child.stdin || this.child.killed) {\n reject(new Error(\"QMD mcp process not available\"));\n return;\n }\n\n const id = nextJsonRpcId++;\n const timer = setTimeout(() => {\n this.pendingRequests.delete(id);\n cleanup();\n reject(new Error(`QMD mcp ${method} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n const onAbort = () => {\n clearTimeout(timer);\n this.pendingRequests.delete(id);\n cleanup();\n reject(abortError(`QMD mcp ${method} aborted`));\n };\n const cleanup = () => {\n signal?.removeEventListener(\"abort\", onAbort);\n };\n\n this.pendingRequests.set(id, { resolve, reject, timer, cleanup });\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n const message = JSON.stringify({ jsonrpc: \"2.0\", id, method, params }) + \"\\n\";\n this.child.stdin.write(message, (err) => {\n if (err) {\n clearTimeout(timer);\n this.pendingRequests.delete(id);\n cleanup();\n reject(new Error(`Failed to write to QMD mcp stdin: ${err.message}`));\n }\n });\n });\n }\n\n private sendNotification(method: string, params?: Record<string, unknown>): void {\n if (!this.child || !this.child.stdin || this.child.killed) return;\n if (this.child.stdin.destroyed) return;\n const msg: Record<string, unknown> = { jsonrpc: \"2.0\", method };\n if (params) msg.params = params;\n try {\n this.child.stdin.write(JSON.stringify(msg) + \"\\n\");\n } catch {\n // Ignore EPIPE / write-after-close\n }\n }\n\n private handleStdoutData(data: Buffer): void {\n this.buffer += data.toString();\n let newlineIdx: number;\n while ((newlineIdx = this.buffer.indexOf(\"\\n\")) !== -1) {\n const line = this.buffer.slice(0, newlineIdx).trim();\n this.buffer = this.buffer.slice(newlineIdx + 1);\n if (!line) continue;\n try {\n const msg = JSON.parse(line);\n this.handleMessage(msg);\n } catch {\n log.debug(`QMD mcp: unparseable stdout: ${truncateForLog(line, 200)}`);\n }\n }\n }\n\n private handleMessage(msg: Record<string, unknown>): void {\n if (msg.id !== undefined && msg.id !== null) {\n const pending = this.pendingRequests.get(msg.id as number);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingRequests.delete(msg.id as number);\n pending.cleanup();\n if (msg.error) {\n pending.reject(new Error(JSON.stringify(msg.error)));\n } else {\n pending.resolve(msg.result);\n }\n }\n return;\n }\n if (msg.method) {\n log.debug(`QMD mcp notification: ${msg.method}`);\n }\n }\n\n private cleanup(opts?: { killChild?: boolean; child?: CommandChildProcess | null }): void {\n const target = opts?.child ?? this.child;\n if (!target) return;\n if (opts?.child && this.child !== opts.child) {\n return;\n }\n if (opts?.killChild && !target.killed) {\n target.kill(\"SIGTERM\");\n }\n this.initialized = false;\n for (const [, pending] of this.pendingRequests) {\n clearTimeout(pending.timer);\n pending.cleanup();\n pending.reject(new Error(\"QMD mcp process terminated\"));\n }\n this.pendingRequests.clear();\n this.startPromise = null;\n this.child = null;\n this.buffer = \"\";\n }\n}\n\n/** Matches `#<hex-docid> <score>% <rest-of-line>` — rest is split in a second pass. */\nconst QMD_RESULT_LINE_RE = /^#([0-9a-fA-F]+)\\s+(\\d+)%\\s+(.+)/;\n\n/**\n * Splits `collection/path.ext - Title text` into path and title.\n * Non-greedy `.+?` finds the FIRST dot-extension (2+ alphabetic chars)\n * followed by ` - `, accepting any indexed file type while skipping\n * version-like segments (e.g. `v1.2` where `.2` is a single digit).\n */\nconst QMD_PATH_TITLE_RE = /^(.+?\\.[a-zA-Z]{2,10})\\s+-\\s+(.*)$/;\n\nfunction parseQmdMarkdownResultText(\n text: string,\n transport: QmdSearchResult[\"transport\"],\n): QmdSearchResult[] {\n const results: QmdSearchResult[] = [];\n for (const line of text.split(\"\\n\")) {\n const m = QMD_RESULT_LINE_RE.exec(line.trim());\n if (!m) continue;\n const rest = m[3]; // \"collection/path.md - Title with - dashes\"\n // Find the path by looking for known file extensions followed by \" - \"\n const pathTitleSplit = QMD_PATH_TITLE_RE.exec(rest);\n if (!pathTitleSplit) continue;\n results.push({\n docid: m[1],\n path: pathTitleSplit[1] ?? \"unknown\",\n snippet: \"\",\n score: parseInt(m[2], 10) / 100,\n transport,\n });\n }\n return results;\n}\n\nfunction parseMcpSearchResult(\n result: unknown,\n transport: QmdSearchResult[\"transport\"] = \"daemon\",\n): QmdSearchResult[] {\n const resultObj = result as Record<string, unknown> | null;\n if (!resultObj) return [];\n const results: QmdSearchResult[] = [];\n const pushDocs = (docs: unknown[]) => {\n for (const doc of docs) {\n const d = doc as Record<string, unknown>;\n results.push({\n docid: typeof d.docid === \"string\" ? d.docid.replace(/^#/, \"\") : \"\",\n path: typeof d.file === \"string\"\n ? d.file\n : typeof d.path === \"string\"\n ? d.path\n : (typeof d.docid === \"string\" ? d.docid.replace(/^#/, \"\") : \"unknown\"),\n snippet: typeof d.snippet === \"string\" ? d.snippet : \"\",\n score: typeof d.score === \"number\" ? d.score : 0,\n explain: parseQmdExplain(d.explain),\n transport,\n });\n }\n };\n const topStructured = resultObj.structuredContent as Record<string, unknown> | undefined;\n const topDocs = topStructured?.results ?? topStructured?.documents;\n if (Array.isArray(topDocs)) pushDocs(topDocs);\n const content = resultObj.content;\n if (Array.isArray(content)) {\n for (const item of content) {\n const structured = item?.structuredContent;\n const docResults = structured?.results ?? structured?.documents;\n if (Array.isArray(docResults)) pushDocs(docResults);\n if (typeof item?.text === \"string\") {\n try {\n const parsed = JSON.parse(item.text);\n const textResults = parsed?.results ?? parsed?.documents;\n if (Array.isArray(textResults)) pushDocs(textResults);\n } catch {\n const existingKeys = new Set(results.map((r) => `${r.docid.toLowerCase()}|${r.path}`));\n const parsed = parseQmdMarkdownResultText(item.text, transport);\n for (const p of parsed) {\n const key = `${p.docid.toLowerCase()}|${p.path}`;\n if (!existingKeys.has(key)) {\n results.push(p);\n existingKeys.add(key);\n }\n }\n }\n }\n }\n }\n return results;\n}\n\nfunction parseQmdSearchStdout(\n stdout: string,\n transport: QmdSearchResult[\"transport\"] = \"subprocess\",\n): QmdSearchResult[] {\n const trimmedOut = stdout.trim();\n if (!trimmedOut || trimmedOut === \"No results found.\") return [];\n const parsed = JSON.parse(trimmedOut);\n if (!Array.isArray(parsed)) return [];\n return parsed.map(\n (entry: Record<string, unknown>): QmdSearchResult => ({\n docid: (entry.docid as string) ?? \"\",\n path:\n (entry.file as string) ??\n (entry.path as string) ??\n (entry.docid as string) ??\n \"unknown\",\n snippet: (entry.snippet as string) ?? \"\",\n score: typeof entry.score === \"number\" ? entry.score : 0,\n explain: parseQmdExplain(entry.explain),\n transport,\n }),\n );\n}\n\nlet _sharedDaemonSession: QmdDaemonSession | null = null;\nlet _sharedDaemonSessionPath: string | null = null;\n\nfunction getSharedDaemonSession(qmdPath: string): QmdDaemonSession {\n const normalizedPath = qmdPath.trim() || \"qmd\";\n if (_sharedDaemonSession && _sharedDaemonSessionPath !== normalizedPath) {\n _sharedDaemonSession.invalidate();\n _sharedDaemonSession = null;\n _sharedDaemonSessionPath = null;\n }\n if (!_sharedDaemonSession) {\n _sharedDaemonSession = new QmdDaemonSession(normalizedPath);\n _sharedDaemonSessionPath = normalizedPath;\n }\n return _sharedDaemonSession;\n}\n\n// ---------------------------------------------------------------------------\n// QmdClient\n// ---------------------------------------------------------------------------\n\nexport class QmdClient implements SearchBackend {\n private available: boolean | null = null;\n private _lastUpdateFailAtMs: number | null = null;\n private lastEmbedFailAtMs: number | null = null;\n private lastUpdateRunAtMs: number | null = null;\n\n get lastUpdateFailedAtMs(): number | null {\n return this._lastUpdateFailAtMs;\n }\n\n get lastUpdateRanAtMs(): number | null {\n return this.lastUpdateRunAtMs;\n }\n\n resetUpdateThrottles(): void {\n this._lastUpdateFailAtMs = null;\n this.lastUpdateRunAtMs = null;\n const gs = getGlobalQmdState();\n gs.lastGlobalUpdateRunAtMs = null;\n gs.lastGlobalUpdateFailAtMs = null;\n }\n\n private readonly updateTimeoutMs: number;\n private readonly updateMinIntervalMs: number;\n private readonly slowLog?: { enabled: boolean; thresholdMs: number };\n private readonly configuredQmdPath?: string;\n private qmdPathSource: \"auto-path\" | \"auto-fallback\" | \"configured\" = \"auto-path\";\n private cliVersion: string | null = null;\n private lastCliProbeError: string | null = null;\n\n // Daemon mode fields\n private daemonSession: QmdDaemonSession | null = null;\n private daemonAvailable = false;\n private lastDaemonCheckAtMs = 0;\n private readonly daemonEnabled: boolean;\n private readonly daemonRecheckIntervalMs: number;\n /** Consecutive transient daemon failures before invalidating the session. */\n private daemonTransientFailures = 0;\n private static readonly DAEMON_MAX_TRANSIENT_FAILURES = 3;\n\n constructor(\n private readonly collection: string,\n private readonly maxResults: number,\n opts?: QmdClientOptions,\n ) {\n this.slowLog = opts?.slowLog;\n this.updateTimeoutMs = opts?.updateTimeoutMs ?? 120_000;\n this.updateMinIntervalMs = Math.max(0, opts?.updateMinIntervalMs ?? 15 * 60_000);\n this.configuredQmdPath = opts?.qmdPath?.trim() ? opts.qmdPath.trim() : undefined;\n if (this.configuredQmdPath) {\n this.qmdPath = this.configuredQmdPath;\n this.qmdPathSource = \"configured\";\n }\n this.daemonEnabled = Boolean(opts?.daemonUrl);\n this.daemonRecheckIntervalMs = opts?.daemonRecheckIntervalMs ?? 15_000;\n }\n\n private qmdPath: string = \"qmd\";\n\n async probe(): Promise<boolean> {\n const cliOk = await this.probeCli();\n if (this.daemonEnabled) {\n await this.probeDaemon();\n }\n return cliOk || this.daemonAvailable;\n }\n\n private async probeDaemon(): Promise<boolean> {\n this.lastDaemonCheckAtMs = Date.now();\n this.daemonSession = getSharedDaemonSession(this.qmdPath);\n try {\n // Race start() against a short window: if the session is already initialized\n // this returns instantly; if the process is still loading its index we fail\n // fast and let the caller fall back gracefully. The underlying start() promise\n // continues running in the background so the process is NOT killed. On the\n // next recheck cycle (daemonRecheckIntervalMs=15s) start() returns true\n // immediately once the handshake has completed.\n const PROBE_QUICK_TIMEOUT_MS = 3_000;\n const ok = await Promise.race([\n this.daemonSession.start(),\n new Promise<false>((resolve) => setTimeout(() => resolve(false), PROBE_QUICK_TIMEOUT_MS)),\n ]);\n if (!ok) {\n const loading = this.daemonSession.isLoading();\n log.debug(`QMD daemon: stdio session not ready within ${PROBE_QUICK_TIMEOUT_MS}ms probe window${loading ? \" (still loading)\" : \"\"}`);\n this.daemonAvailable = false;\n return false;\n }\n log.info(`QMD daemon: stdio session active (collection=${this.collection})`);\n this.daemonAvailable = true;\n this.daemonTransientFailures = 0;\n return true;\n } catch (err) {\n log.debug(`QMD daemon: probe failed: ${err}`);\n this.daemonAvailable = false;\n return false;\n }\n }\n\n private async probeCli(): Promise<boolean> {\n const parseVersion = (stdout: string, stderr: string): string | null => {\n const lines = `${stdout}\\n${stderr}`\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n if (lines.length === 0) return null;\n const semanticLines = lines.filter((line) => parseQmdVersion(line) !== null);\n if (semanticLines.length === 0) return lines[0] ?? null;\n return semanticLines.find((line) => /\\bqmd\\b/i.test(line)) ?? semanticLines[0] ?? null;\n };\n const markProbeFailure = (err: unknown): void => {\n this.lastCliProbeError = err instanceof Error ? err.message : String(err);\n };\n\n if (this.configuredQmdPath) {\n try {\n const result = await runQmd([\"--version\"], QMD_PROBE_TIMEOUT_MS, this.configuredQmdPath);\n this.available = true;\n this.qmdPath = this.configuredQmdPath;\n this.qmdPathSource = \"configured\";\n this.cliVersion = parseVersion(result.stdout, result.stderr);\n this.lastCliProbeError = null;\n return true;\n } catch (err) {\n markProbeFailure(err);\n // Do not hard-fail here: fall through to PATH/fallback probing.\n // This keeps recall healthy even when configured path is stale.\n this.logCliProbeWarning(\n `QMD: configured qmdPath failed (${this.configuredQmdPath}): ${this.lastCliProbeError}`,\n );\n }\n }\n\n // Try PATH first\n try {\n const result = await runQmd([\"--version\"], QMD_PROBE_TIMEOUT_MS, \"qmd\");\n this.available = true;\n this.qmdPath = \"qmd\";\n this.qmdPathSource = \"auto-path\";\n this.cliVersion = parseVersion(result.stdout, result.stderr);\n this.lastCliProbeError = null;\n return true;\n } catch (err) {\n markProbeFailure(err);\n // Try fallback paths\n for (const fallbackPath of QMD_FALLBACK_PATHS) {\n try {\n const result = await runQmd([\"--version\"], QMD_PROBE_TIMEOUT_MS, fallbackPath);\n this.available = true;\n this.qmdPath = fallbackPath;\n this.qmdPathSource = \"auto-fallback\";\n this.cliVersion = parseVersion(result.stdout, result.stderr);\n this.lastCliProbeError = null;\n log.info(`QMD: found at ${fallbackPath}`);\n return true;\n } catch (fallbackErr) {\n markProbeFailure(fallbackErr);\n // Continue to next fallback\n }\n }\n this.available = false;\n return false;\n }\n }\n\n private logCliProbeWarning(message: string): void {\n const state = getGlobalQmdState();\n const now = Date.now();\n const canWarn =\n state.lastCliWarnAtMs === null || now - state.lastCliWarnAtMs >= QMD_CLI_WARN_THROTTLE_MS;\n if (!canWarn) {\n log.debug(message);\n return;\n }\n state.lastCliWarnAtMs = now;\n if (this.daemonAvailable) {\n // Daemon mode is healthy; keep this as debug noise rather than warning.\n log.debug(message);\n return;\n }\n log.warn(message);\n }\n\n /** Re-probe daemon if it was down and recheck interval has elapsed. */\n private async maybeProbeDaemon(): Promise<void> {\n if (!this.daemonEnabled) return;\n // If daemon is marked healthy and session is active, nothing to do.\n if (this.daemonAvailable && this.daemonSession?.isActive()) return;\n // If recently checked and failed, respect the recheck interval.\n if (this.daemonAvailable === false) {\n const elapsed = Date.now() - this.lastDaemonCheckAtMs;\n if (elapsed < this.daemonRecheckIntervalMs) return;\n }\n this.daemonAvailable = false;\n await this.probeDaemon();\n }\n\n isAvailable(): boolean {\n return this.available === true || this.daemonAvailable;\n }\n\n /** Debug string for troubleshooting availability issues. */\n debugStatus(): string {\n const cliPath = this.available ? this.qmdPath : (this.configuredQmdPath ?? \"unavailable\");\n const cliVersion = this.cliVersion ?? \"unknown\";\n const probeError = this.lastCliProbeError ? ` cliProbeError=${this.lastCliProbeError}` : \"\";\n return `cli=${this.available} daemon=${this.daemonAvailable} session=${!!this.daemonSession} cliPath=${cliPath} cliPathSource=${this.qmdPathSource} cliVersion=${cliVersion}${probeError}`;\n }\n\n isDaemonMode(): boolean {\n return this.daemonAvailable;\n }\n\n /**\n * Record a daemon search success — resets the transient failure counter.\n */\n private recordDaemonSuccess(): void {\n this.daemonTransientFailures = 0;\n }\n\n /**\n * Handle a non-timeout, non-cancellation daemon error.\n * Tolerates up to DAEMON_MAX_TRANSIENT_FAILURES consecutive failures\n * before invalidating the session. This prevents a single transient\n * error from pushing all concurrent searches through the subprocess\n * mutex for the full recheck interval.\n */\n private handleDaemonTransientError(label: string, err: unknown, durationMs: number): void {\n // If daemon was already marked unavailable by a concurrent call, don't\n // increment further — the counter will reset on the next successful probe.\n if (!this.daemonAvailable) {\n log.debug(`QMD daemon ${label} failed after ${durationMs}ms (daemon already unavailable, ignoring): ${err}`);\n return;\n }\n this.daemonTransientFailures += 1;\n if (this.daemonTransientFailures >= QmdClient.DAEMON_MAX_TRANSIENT_FAILURES) {\n log.debug(`QMD daemon ${label} failed after ${durationMs}ms (${this.daemonTransientFailures} consecutive failures, invalidating): ${err}`);\n this.daemonSession?.invalidate();\n this.daemonAvailable = false;\n this.daemonTransientFailures = 0;\n } else {\n log.debug(`QMD daemon ${label} failed after ${durationMs}ms (transient ${this.daemonTransientFailures}/${QmdClient.DAEMON_MAX_TRANSIENT_FAILURES}): ${err}`);\n }\n }\n\n private async runQmdCommand(\n args: string[],\n timeoutMs: number,\n signal?: AbortSignal,\n ): Promise<{ stdout: string; stderr: string }> {\n return runQmd(args, timeoutMs, this.qmdPath, signal);\n }\n\n private supportsIntentHints(): boolean {\n return versionAtLeast(parseQmdVersion(this.cliVersion), [1, 1, 5]);\n }\n\n private supportsExplainTraces(): boolean {\n return versionAtLeast(parseQmdVersion(this.cliVersion), [1, 1, 2]);\n }\n\n /**\n * QMD v2 (>= 2.0.0) uses a new MCP tool API:\n * - `search` and `vsearch` tools removed; only `query` tool exists\n * - `query` accepts `{ searches: [{ type, query }], collections?: string[] }`\n * instead of `{ query: string, collection?: string }`\n * - `collection` (singular) → `collections` (plural array)\n */\n private isQmdV2(): boolean {\n return versionAtLeast(parseQmdVersion(this.cliVersion), [2, 0, 0]);\n }\n\n private resolveSearchOptions(options?: SearchQueryOptions): SearchQueryOptions | undefined {\n const normalized = normalizeSearchOptions(options);\n if (!normalized) return undefined;\n const resolved: SearchQueryOptions = {};\n if (normalized.intent && this.supportsIntentHints()) {\n resolved.intent = normalized.intent;\n }\n if (normalized.explain === true && this.supportsExplainTraces()) {\n resolved.explain = true;\n }\n return Object.keys(resolved).length > 0 ? resolved : undefined;\n }\n\n resolveSupportedSearchOptions(options?: SearchQueryOptions): SearchQueryOptions | undefined {\n return this.resolveSearchOptions(options);\n }\n\n async search(\n query: string,\n collection?: string,\n maxResults?: number,\n options?: SearchQueryOptions,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n\n const col = collection ?? this.collection;\n const n = maxResults ?? this.maxResults;\n const searchOptions = this.resolveSearchOptions(options);\n\n // Short-lived search result cache — avoids redundant daemon calls for\n // repeated queries within the same recall cycle (e.g., primary + hybrid\n // top-up, or conversation recall using the same collection).\n const optionsFingerprint = searchOptions ? JSON.stringify(searchOptions) : \"\";\n const cacheKey = createHash(\"sha256\").update(`${col}:${n}:${optionsFingerprint}:${trimmed}`).digest(\"hex\");\n const cached = getCachedQmdSearch(cacheKey);\n if (cached) {\n log.debug(`QMD search cache hit (${cached.length} results)`);\n return cached as QmdSearchResult[];\n }\n\n // Try daemon first (bypasses QMD_MUTEX — daemon handles its own concurrency)\n await this.maybeProbeDaemon();\n if (this.daemonAvailable) {\n let results: QmdSearchResult[] | null;\n try {\n results = await this.searchViaDaemon(trimmed, col, n, searchOptions, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon search aborted\");\n }\n throw err;\n }\n // When the daemon is available, trust its outcome and skip the subprocess.\n // The subprocess runs `qmd query` (BM25 + LLM expansion) which hangs at\n // 99% CPU on large collections (75K+ files) making it strictly worse than\n // the daemon for this workload. Specifically:\n // results !== null → daemon succeeded (even with 0 hits) → return as-is\n // results === null → daemon timed-out or errored → still skip subprocess\n // because subprocess will also hang or timeout\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon search returned 0 results; skipping subprocess\");\n }\n setCachedQmdSearch(cacheKey, results);\n return results;\n }\n // Daemon timed out or had a transient error — skip subprocess for large\n // collections. Return empty rather than hanging the caller.\n log.debug(\"QMD daemon search timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n\n // If the daemon process is spawned but still loading (handshake not yet complete),\n // skip subprocess — it would add load and block under QMD_MUTEX without helping.\n // Return empty and let the next recheck cycle pick up the daemon once ready.\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD search: daemon loading, skipping subprocess\");\n return [];\n }\n\n // Subprocess fallback (only reached when daemon is unavailable and not loading)\n const subprocessResults = await this.searchViaSubprocess(trimmed, col, n, searchOptions, execution?.signal);\n setCachedQmdSearch(cacheKey, subprocessResults);\n return subprocessResults;\n }\n\n async searchGlobal(\n query: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n\n const n = maxResults ?? 6;\n\n // Try daemon first\n await this.maybeProbeDaemon();\n if (this.daemonAvailable) {\n // Global search: no collection filter\n let results: QmdSearchResult[] | null;\n try {\n results = await this.searchViaDaemon(trimmed, undefined, n, undefined, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon global search aborted\");\n }\n throw err;\n }\n // Same rationale as search() — trust daemon outcome, skip subprocess.\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon global search returned 0 results; skipping subprocess\");\n }\n return results;\n }\n log.debug(\"QMD daemon global search timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n\n // If the daemon is spawned but still loading, skip subprocess — same as search().\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD searchGlobal: daemon loading, skipping subprocess\");\n return [];\n }\n\n // Subprocess fallback (only reached when daemon is unavailable and not loading)\n return this.searchGlobalViaSubprocess(trimmed, n, execution?.signal);\n }\n\n /**\n * BM25 keyword search (fast, ~0.3s). Uses `qmd search`.\n */\n async bm25Search(\n query: string,\n collection?: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n const col = collection ?? this.collection;\n const n = maxResults ?? this.maxResults;\n\n // Try daemon first — BM25 via daemon is much faster than subprocess.\n await this.maybeProbeDaemon();\n if (this.daemonAvailable && this.daemonSession) {\n let results: QmdSearchResult[] | null;\n try {\n results = await this.bm25SearchViaDaemon(trimmed, col, n, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon bm25 aborted\");\n }\n throw err;\n }\n // When daemon is available, trust its outcome and skip subprocess (same\n // rationale as search() — subprocess hangs at 99% CPU on 75K+ files).\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon bm25 returned 0 results; skipping subprocess\");\n }\n return results;\n }\n log.debug(\"QMD daemon bm25 timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD bm25: daemon loading, skipping subprocess\");\n return [];\n }\n return this.bm25SearchViaSubprocess(trimmed, col, n, execution?.signal);\n }\n\n /**\n * Vector similarity search (~3-4s). Uses `qmd vsearch`.\n */\n async vectorSearch(\n query: string,\n collection?: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n const col = collection ?? this.collection;\n const n = maxResults ?? this.maxResults;\n\n // Try daemon first — keeps models warm, avoids cold subprocess loads.\n await this.maybeProbeDaemon();\n if (this.daemonAvailable && this.daemonSession) {\n let results: QmdSearchResult[] | null;\n try {\n results = await this.vsearchViaDaemon(trimmed, col, n, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon vsearch aborted\");\n }\n throw err;\n }\n // When daemon is available, trust its outcome and skip subprocess (same\n // rationale as search() — subprocess hangs at 99% CPU on 75K+ files).\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon vsearch returned 0 results; skipping subprocess\");\n }\n return results;\n }\n log.debug(\"QMD daemon vsearch timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD vsearch: daemon loading, skipping subprocess\");\n return [];\n }\n return this.vsearchViaSubprocess(trimmed, col, n, execution?.signal);\n }\n\n /**\n * Hybrid search: runs BM25 + vector in parallel, merges/dedupes by path\n * keeping the best score and first non-empty snippet.\n */\n async hybridSearch(\n query: string,\n collection?: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n const n = maxResults ?? this.maxResults;\n const trimmed = query.trim();\n if (!trimmed) return [];\n\n const [bm25Results, vectorResults] = await Promise.all([\n this.bm25Search(trimmed, collection, n, execution),\n this.vectorSearch(trimmed, collection, n, execution),\n ]);\n\n // Merge by path, keeping best score\n const merged = new Map<string, QmdSearchResult>();\n for (const r of [...bm25Results, ...vectorResults]) {\n const key = r.path || r.docid;\n const existing = merged.get(key);\n if (!existing || r.score > existing.score) {\n merged.set(key, {\n ...r,\n snippet: r.snippet || existing?.snippet || \"\",\n });\n }\n }\n\n // Sort by score descending, take top N\n return [...merged.values()]\n .sort((a, b) => b.score - a.score)\n .slice(0, n);\n }\n\n private async searchViaDaemon(\n query: string,\n collection: string | undefined,\n maxResults: number,\n options?: SearchQueryOptions,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[] | null> {\n if (!this.daemonSession || !this.daemonAvailable) return null;\n\n const startedAtMs = Date.now();\n const v2 = this.isQmdV2();\n try {\n let args: Record<string, unknown>;\n if (v2) {\n // QMD v2: query tool expects { searches: [...], collections?: [...] }\n // A plain query without type prefix uses LLM auto-expansion on the daemon side\n const searches: Array<{ type: string; query: string }> = [{ type: \"lex\", query }];\n // Add a vec sub-query for hybrid recall (mirrors v1 behavior)\n searches.push({ type: \"vec\", query });\n args = { searches, limit: maxResults };\n if (collection) {\n args.collections = [collection];\n }\n if (options?.intent) {\n args.intent = options.intent;\n }\n if (options?.explain === true) {\n args.explain = true;\n }\n } else {\n // QMD v1: query tool accepts { query, collection?, limit }\n args = { query, limit: maxResults };\n if (collection) {\n args.collection = collection;\n }\n if (options?.intent) {\n args.intent = options.intent;\n }\n if (options?.explain === true) {\n args.explain = true;\n }\n }\n\n const result = await this.daemonSession.callTool(\"query\", args, QMD_DAEMON_TIMEOUT_MS, signal);\n const durationMs = Date.now() - startedAtMs;\n\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(\n `SLOW QMD daemon query: durationMs=${durationMs} collection=${collection ?? \"global\"} maxResults=${maxResults} queryChars=${query.length} v2=${v2}`,\n );\n }\n\n const results = parseMcpSearchResult(result, \"daemon\");\n\n log.debug(`QMD daemon search: ${results.length} results in ${durationMs}ms (v2=${v2})`);\n this.recordDaemonSuccess();\n return results;\n } catch (err) {\n const durationMs = Date.now() - startedAtMs;\n if (isCallerCancellation(err, signal)) {\n log.debug(`QMD daemon search aborted/cancelled after ${durationMs}ms`);\n throw isAbortError(err) ? err : abortError(\"QMD daemon search aborted\");\n }\n // Timeout: don't invalidate session — daemon is still running, just slow.\n if (isDaemonTimeoutError(err)) {\n log.debug(`QMD daemon search timed out after ${durationMs}ms, falling back to subprocess`);\n return null;\n }\n // Transient error: tolerate a few before invalidating.\n this.handleDaemonTransientError(\"search\", err, durationMs);\n return null;\n }\n }\n\n private async bm25SearchViaDaemon(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[] | null> {\n if (!this.daemonSession || !this.daemonAvailable) return null;\n\n const startedAtMs = Date.now();\n const v2 = this.isQmdV2();\n try {\n let result: unknown;\n if (v2) {\n // QMD v2: no `search` tool — use `query` with lex-only sub-query\n result = await this.daemonSession.callTool(\n \"query\",\n {\n searches: [{ type: \"lex\", query }],\n collections: [collection],\n limit: maxResults,\n },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n } else {\n // QMD v1: dedicated `search` tool for BM25\n result = await this.daemonSession.callTool(\n \"search\",\n { query, limit: maxResults, collection },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n }\n const durationMs = Date.now() - startedAtMs;\n const results = parseMcpSearchResult(result);\n log.debug(`QMD daemon bm25: ${results.length} results in ${durationMs}ms (v2=${v2})`);\n this.recordDaemonSuccess();\n return results;\n } catch (err) {\n const durationMs = Date.now() - startedAtMs;\n if (isCallerCancellation(err, signal)) {\n log.debug(`QMD daemon bm25 aborted/cancelled after ${durationMs}ms`);\n throw isAbortError(err) ? err : abortError(\"QMD daemon bm25 aborted\");\n }\n if (isDaemonTimeoutError(err)) {\n log.debug(`QMD daemon bm25 timed out after ${durationMs}ms, falling back to subprocess`);\n return null;\n }\n this.handleDaemonTransientError(\"bm25\", err, durationMs);\n return null;\n }\n }\n\n private async vsearchViaDaemon(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[] | null> {\n if (!this.daemonSession || !this.daemonAvailable) return null;\n\n const startedAtMs = Date.now();\n const v2 = this.isQmdV2();\n try {\n let result: unknown;\n if (v2) {\n // QMD v2: no `vsearch` tool — use `query` with vec-only sub-query\n result = await this.daemonSession.callTool(\n \"query\",\n {\n searches: [{ type: \"vec\", query }],\n collections: [collection],\n limit: maxResults,\n },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n } else {\n // QMD v1: dedicated `vsearch` tool for vector search\n result = await this.daemonSession.callTool(\n \"vsearch\",\n { query, limit: maxResults, collection },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n }\n const durationMs = Date.now() - startedAtMs;\n const results = parseMcpSearchResult(result);\n log.debug(`QMD daemon vsearch: ${results.length} results in ${durationMs}ms (v2=${v2})`);\n this.recordDaemonSuccess();\n return results;\n } catch (err) {\n const durationMs = Date.now() - startedAtMs;\n if (isCallerCancellation(err, signal)) {\n log.debug(`QMD daemon vsearch aborted/cancelled after ${durationMs}ms`);\n throw isAbortError(err) ? err : abortError(\"QMD daemon vsearch aborted\");\n }\n if (isDaemonTimeoutError(err)) {\n log.debug(`QMD daemon vsearch timed out after ${durationMs}ms, falling back to subprocess`);\n return null;\n }\n this.handleDaemonTransientError(\"vsearch\", err, durationMs);\n return null;\n }\n }\n\n private async searchViaSubprocess(\n query: string,\n collection: string,\n maxResults: number,\n options?: SearchQueryOptions,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n\n const startedAtMs = Date.now();\n try {\n const args = [\"query\", query, \"-c\", collection, \"--json\", \"-n\", String(maxResults)];\n if (options?.intent) {\n args.push(\"--intent\", options.intent);\n }\n if (options?.explain === true) {\n args.push(\"--explain\");\n }\n const { stdout } = await runQmd(\n args,\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(\n `SLOW QMD query: durationMs=${durationMs} collection=${collection} maxResults=${maxResults} queryChars=${query.length}`,\n );\n }\n\n return parseQmdSearchStdout(stdout, \"subprocess\");\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess search aborted\");\n }\n log.debug(`QMD search failed: ${err}`);\n return [];\n }\n }\n\n private async bm25SearchViaSubprocess(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n const startedAtMs = Date.now();\n try {\n const { stdout } = await runQmd(\n [\"search\", query, \"-c\", collection, \"--json\", \"-n\", String(maxResults)],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n log.debug(`QMD bm25: ${Date.now() - startedAtMs}ms`);\n return parseQmdSearchStdout(stdout);\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess bm25 aborted\");\n }\n log.debug(`QMD bm25 search failed: ${err}`);\n return [];\n }\n }\n\n private async vsearchViaSubprocess(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n const startedAtMs = Date.now();\n try {\n const { stdout } = await runQmd(\n [\"vsearch\", query, \"-c\", collection, \"--json\", \"-n\", String(maxResults)],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n log.debug(`QMD vsearch: ${Date.now() - startedAtMs}ms`);\n return parseQmdSearchStdout(stdout);\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess vsearch aborted\");\n }\n log.debug(`QMD vsearch failed: ${err}`);\n return [];\n }\n }\n\n private async searchGlobalViaSubprocess(\n query: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n\n const startedAtMs = Date.now();\n try {\n const { stdout } = await runQmd(\n [\"query\", query, \"--json\", \"-n\", String(maxResults)],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(\n `SLOW QMD global query: durationMs=${durationMs} maxResults=${maxResults} queryChars=${query.length}`,\n );\n }\n\n return parseQmdSearchStdout(stdout);\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess global search aborted\");\n }\n log.debug(`QMD global search failed: ${err}`);\n return [];\n }\n }\n\n async update(signal?: AbortSignal): Promise<void> {\n await this.runUpdateForCollection(this.collection, { perCollectionThrottle: false }, signal);\n }\n\n async updateCollection(collection: string): Promise<void> {\n await this.runUpdateForCollection(collection, { perCollectionThrottle: true });\n }\n\n private async runUpdateForCollection(\n collection: string,\n options: { perCollectionThrottle: boolean },\n signal?: AbortSignal,\n ): Promise<void> {\n if (this.available === false) return;\n const name = collection.trim();\n if (!name) return;\n const globalState = getGlobalQmdState();\n const now = Date.now();\n if (options.perCollectionThrottle) {\n if (\n globalState.lastGlobalUpdateFailAtMs &&\n now - globalState.lastGlobalUpdateFailAtMs < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(\"QMD update: suppressed by global failure backoff\");\n return;\n }\n const lastCollectionRun = globalState.lastUpdateByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionRun) &&\n now - lastCollectionRun < this.updateMinIntervalMs\n ) {\n log.debug(`QMD update: suppressed by per-collection min-interval gate (${name})`);\n return;\n }\n const lastCollectionFail = globalState.lastUpdateFailByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionFail) &&\n now - lastCollectionFail < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(`QMD update: suppressed by per-collection failure backoff (${name})`);\n return;\n }\n } else {\n if (\n this.lastUpdateRunAtMs &&\n now - this.lastUpdateRunAtMs < this.updateMinIntervalMs\n ) {\n log.debug(\"QMD update: suppressed due to min-interval gate\");\n return;\n }\n if (\n this._lastUpdateFailAtMs &&\n now - this._lastUpdateFailAtMs < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(\"QMD update: suppressed due to recent failures (backoff)\");\n return;\n }\n if (\n globalState.lastGlobalUpdateRunAtMs &&\n now - globalState.lastGlobalUpdateRunAtMs < this.updateMinIntervalMs\n ) {\n log.debug(\"QMD update: suppressed by global min-interval gate\");\n return;\n }\n if (\n globalState.lastGlobalUpdateFailAtMs &&\n now - globalState.lastGlobalUpdateFailAtMs < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(\"QMD update: suppressed by global failure backoff\");\n return;\n }\n }\n try {\n if (!globalState.warnedGlobalUpdateBehavior) {\n globalState.warnedGlobalUpdateBehavior = true;\n log.warn(\n \"QMD update runs globally across collections in current CLI versions; Engram now rate-limits update calls to reduce gateway load.\",\n );\n }\n const startedAtMs = Date.now();\n await this.runQmdCommand([\"update\", \"-c\", name], this.updateTimeoutMs, signal);\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(`SLOW QMD update: durationMs=${durationMs}`);\n }\n const at = Date.now();\n if (options.perCollectionThrottle) {\n globalState.lastUpdateByCollectionMs[name] = at;\n globalState.lastGlobalUpdateRunAtMs = at;\n } else {\n this.lastUpdateRunAtMs = at;\n globalState.lastGlobalUpdateRunAtMs = at;\n }\n log.debug(`QMD update completed for collection=${name}`);\n } catch (err) {\n const at = Date.now();\n if (options.perCollectionThrottle) {\n globalState.lastUpdateFailByCollectionMs[name] = at;\n globalState.lastGlobalUpdateFailAtMs = at;\n } else {\n this._lastUpdateFailAtMs = at;\n globalState.lastGlobalUpdateFailAtMs = at;\n }\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`QMD update failed for collection ${name}: ${msg}`);\n }\n }\n\n async embed(): Promise<void> {\n if (this.available === false) return;\n const globalState = getGlobalQmdState();\n if (\n this.lastEmbedFailAtMs &&\n Date.now() - this.lastEmbedFailAtMs < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(\"QMD embed: suppressed due to recent failures (backoff)\");\n return;\n }\n if (\n globalState.lastGlobalEmbedRunAtMs &&\n Date.now() - globalState.lastGlobalEmbedRunAtMs < this.updateMinIntervalMs\n ) {\n log.debug(\"QMD embed: suppressed by global min-interval gate\");\n return;\n }\n if (\n globalState.lastGlobalEmbedFailAtMs &&\n Date.now() - globalState.lastGlobalEmbedFailAtMs < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(\"QMD embed: suppressed by global failure backoff\");\n return;\n }\n try {\n const startedAtMs = Date.now();\n await this.runQmdCommand([\"embed\", \"-c\", this.collection], 300_000);\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(`SLOW QMD embed: durationMs=${durationMs}`);\n }\n globalState.lastGlobalEmbedRunAtMs = Date.now();\n log.debug(\"QMD embed completed\");\n } catch (err) {\n if (isVectorDimensionMismatchError(err)) {\n try {\n log.warn(\"QMD embed hit a vector dimension mismatch; retrying with force re-embed\");\n await this.runQmdCommand([\"embed\", \"-f\", \"-c\", this.collection], 300_000);\n globalState.lastGlobalEmbedRunAtMs = Date.now();\n this.lastEmbedFailAtMs = null;\n globalState.lastGlobalEmbedFailAtMs = null;\n log.warn(\"QMD embed recovered by forcing a full vector rebuild\");\n return;\n } catch (retryErr) {\n const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);\n log.warn(`QMD force re-embed failed after dimension mismatch: ${retryMsg}`);\n }\n }\n const now = Date.now();\n this.lastEmbedFailAtMs = now;\n globalState.lastGlobalEmbedFailAtMs = now;\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`QMD embed failed: ${msg}`);\n }\n }\n\n async embedCollection(collection: string): Promise<void> {\n if (this.available === false) return;\n const name = collection.trim();\n if (!name) return;\n const globalState = getGlobalQmdState();\n const now = Date.now();\n if (\n globalState.lastGlobalEmbedFailAtMs &&\n now - globalState.lastGlobalEmbedFailAtMs < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(`QMD embed: suppressed by global failure backoff (${name})`);\n return;\n }\n const lastCollectionRun = globalState.lastEmbedByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionRun) &&\n now - lastCollectionRun < this.updateMinIntervalMs\n ) {\n log.debug(`QMD embed: suppressed by per-collection min-interval gate (${name})`);\n return;\n }\n const lastCollectionFail = globalState.lastEmbedFailByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionFail) &&\n now - lastCollectionFail < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(`QMD embed: suppressed by per-collection failure backoff (${name})`);\n return;\n }\n try {\n await this.runQmdCommand([\"embed\", \"-c\", name], 300_000);\n const at = Date.now();\n globalState.lastEmbedByCollectionMs[name] = at;\n globalState.lastGlobalEmbedRunAtMs = at;\n } catch (err) {\n if (isVectorDimensionMismatchError(err)) {\n try {\n log.warn(`QMD embed for collection ${name} hit a vector dimension mismatch; retrying with force re-embed`);\n await this.runQmdCommand([\"embed\", \"-f\", \"-c\", name], 300_000);\n const recoveredAt = Date.now();\n globalState.lastEmbedByCollectionMs[name] = recoveredAt;\n globalState.lastGlobalEmbedRunAtMs = recoveredAt;\n delete globalState.lastEmbedFailByCollectionMs[name];\n globalState.lastGlobalEmbedFailAtMs = null;\n log.warn(`QMD embed for collection ${name} recovered by forcing a full vector rebuild`);\n return;\n } catch (retryErr) {\n const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);\n log.warn(`QMD force re-embed failed for collection ${name}: ${retryMsg}`);\n }\n }\n const at = Date.now();\n globalState.lastEmbedFailByCollectionMs[name] = at;\n globalState.lastGlobalEmbedFailAtMs = at;\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`QMD embed failed for collection ${name}: ${msg}`);\n }\n }\n\n async ensureCollection(memoryDir: string): Promise<\"present\" | \"missing\" | \"unknown\" | \"skipped\"> {\n if (this.available === false && !this.daemonAvailable) return \"unknown\";\n // If only daemon is available (no CLI), skip collection check\n if (this.available === false) return \"skipped\";\n try {\n const { stdout } = await runQmd(\n [\"collection\", \"list\"],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n );\n // Parse text output: \"openclaw-engram (qmd://openclaw-engram/)\"\n const collectionRegex = new RegExp(\n `^${this.collection}\\\\s+\\\\(qmd://`,\n \"m\",\n );\n if (collectionRegex.test(stdout)) {\n return \"present\";\n }\n } catch (err) {\n // Treat command/probe failures as unknown so callers do not disable features\n // permanently after a transient CLI or daemon hiccup.\n log.debug(\n `QMD collection check unavailable for \"${this.collection}\" (will not disable features): ${err instanceof Error ? err.message : String(err)}`,\n );\n return \"unknown\";\n }\n\n log.info(\n `QMD collection \"${this.collection}\" not found. ` +\n `Add it to ~/.config/qmd/index.yml pointing at ${memoryDir}`,\n );\n return \"missing\";\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,SAAS,kBAAkB;AAC3B,OAAO,QAAQ;AACf,OAAO,UAAU;AAsBjB,IAAM,iBAAiB;AAOvB,IAAM,wBAAwB;AAC9B,IAAM,uBAAuB;AAC7B,IAAM,wBAAwB,KAAK,KAAK;AACxC,IAAM,uBAAuB,KAAK,KAAK;AACvC,IAAM,2BAA2B,KAAK,KAAK;AAC3C,IAAM,qBAAqB;AAAA,EACzB,KAAK,KAAK,GAAG,QAAQ,GAAG,QAAQ,OAAO,KAAK;AAAA,EAC5C;AAAA,EACA;AACF;AACA,IAAM,uBAAuB;AAe7B,SAAS,oBAAoC;AAC3C,QAAM,IAAI;AACV,MAAI,CAAC,EAAE,oBAAoB,GAAG;AAC5B,MAAE,oBAAoB,IAAI;AAAA,MACxB,4BAA4B;AAAA,MAC5B,yBAAyB;AAAA,MACzB,0BAA0B;AAAA,MAC1B,wBAAwB;AAAA,MACxB,yBAAyB;AAAA,MACzB,iBAAiB;AAAA,MACjB,0BAA0B,CAAC;AAAA,MAC3B,8BAA8B,CAAC;AAAA,MAC/B,yBAAyB,CAAC;AAAA,MAC1B,6BAA6B,CAAC;AAAA,IAChC;AAAA,EACF;AACA,SAAO,EAAE,oBAAoB;AAC/B;AAMA,SAAS,aAAa,KAAsB;AAC1C,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,MAAI,eAAe,MAAO,QAAO,IAAI;AACrC,MAAI,OAAO,OAAO,QAAQ,YAAY,aAAa,OAAO,OAAQ,IAA8B,YAAY,UAAU;AACpH,WAAQ,IAA4B;AAAA,EACtC;AACA,SAAO,OAAO,GAAG;AACnB;AAEA,SAAS,qBAAqB,KAAc,QAA+B;AACzE,MAAI,QAAQ,QAAS,QAAO;AAC5B,MAAI,aAAa,GAAG,EAAG,QAAO;AAC9B,MAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,UAAM,OAAO,UAAU,MAAO,IAA2B,OAAO;AAChE,QAAI,SAAS,eAAe,SAAS,eAAgB,QAAO;AAAA,EAC9D;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,KAAuB;AACnD,SAAO,aAAa,KAAK,aAAa,GAAG,CAAC;AAC5C;AAEA,SAAS,gBAAgB,IAAY,QAAqC;AACxE,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,mBAAe,MAAM;AACrB,UAAM,QAAQ,WAAW,MAAM;AAC7B,cAAQ;AACR,cAAQ;AAAA,IACV,GAAG,EAAE;AACL,UAAM,UAAU,MAAM;AACpB,mBAAa,KAAK;AAClB,cAAQ;AACR,aAAO,WAAW,iCAAiC,CAAC;AAAA,IACtD;AACA,UAAM,UAAU,MAAM;AACpB,cAAQ,oBAAoB,SAAS,OAAO;AAAA,IAC9C;AACA,YAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC3D,CAAC;AACH;AAEA,SAAS,kBAAkB,KAAsB;AAC/C,QAAM,QAAQ,IAAI,YAAY;AAC9B,SACE,MAAM,SAAS,oBAAoB,KACnC,MAAM,SAAS,aAAa,KAC5B,MAAM,SAAS,sBAAsB,KACrC,MAAM,SAAS,gCAAgC;AAEnD;AAEA,SAAS,kBAAkB,GAAmB;AAE5C,SAAO,EAAE,QAAQ,0BAA0B,EAAE,EAAE,QAAQ,0BAA0B,EAAE;AACrF;AAEA,SAAS,eAAe,GAAW,MAAM,KAAc;AACrD,QAAM,UAAU,kBAAkB,CAAC;AACnC,SAAO,QAAQ,SAAS,MAAM,QAAQ,MAAM,GAAG,GAAG,IAAI,sBAAiB;AACzE;AAEA,SAAS,+BAA+B,KAAuB;AAC7D,QAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,SACE,sBAAsB,KAAK,GAAG,KAC7B,gBAAgB,KAAK,GAAG,KAAK,gBAAgB,KAAK,GAAG,KACrD,aAAa,KAAK,GAAG,KAAK,eAAe,KAAK,GAAG;AAEtD;AAEA,SAAS,gBAAgB,SAAyD;AAChF,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,QAAQ,QAAQ,MAAM,uCAAuC;AACnE,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO;AAAA,IACL,OAAO,SAAS,MAAM,CAAC,KAAK,KAAK,EAAE;AAAA,IACnC,OAAO,SAAS,MAAM,CAAC,KAAK,KAAK,EAAE;AAAA,IACnC,OAAO,SAAS,MAAM,CAAC,KAAK,KAAK,EAAE;AAAA,EACrC;AACF;AAEA,SAAS,eACP,SACA,QACS;AACT,MAAI,CAAC,QAAS,QAAO;AACrB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG;AAC7B,SAAK,QAAQ,CAAC,KAAK,KAAK,OAAO,CAAC,EAAG,QAAO;AAC1C,SAAK,QAAQ,CAAC,KAAK,KAAK,OAAO,CAAC,EAAG,QAAO;AAAA,EAC5C;AACA,SAAO;AACT;AAEA,SAAS,uBAAuB,SAA8D;AAC5F,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,SAAS,OAAO,QAAQ,WAAW,WAAW,QAAQ,OAAO,KAAK,IAAI;AAC5E,QAAM,aAAiC,CAAC;AACxC,MAAI,OAAO,SAAS,GAAG;AACrB,eAAW,SAAS;AAAA,EACtB;AACA,MAAI,QAAQ,YAAY,MAAM;AAC5B,eAAW,UAAU;AAAA,EACvB;AACA,SAAO,OAAO,KAAK,UAAU,EAAE,SAAS,IAAI,aAAa;AAC3D;AAEA,SAAS,mBAAmB,OAAsC;AAChE,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,QAAM,SAAS,MAAM,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ;AACjF,SAAO,OAAO,SAAS,IAAI,SAAS;AACtC;AAEO,SAAS,gBAAgB,OAA8C;AAC5E,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,YAAY;AAClB,QAAM,SAA2B;AAAA,IAC/B,WAAW,mBAAmB,UAAU,SAAS;AAAA,IACjD,cAAc,mBAAmB,UAAU,YAAY;AAAA,IACvD,KAAK,OAAO,UAAU,QAAQ,WAAW,UAAU,MAAM;AAAA,IACzD,aAAa,OAAO,UAAU,gBAAgB,WAAW,UAAU,cAAc;AAAA,IACjF,cAAc,OAAO,UAAU,iBAAiB,WAAW,UAAU,eAAe;AAAA,EACtF;AACA,SAAO,OAAO,OAAO,MAAM,EAAE,KAAK,CAAC,UAAU,UAAU,MAAS,IAAI,SAAS;AAC/E;AAEA,IAAM,aAAN,MAAiB;AAAA,EACP,SAAS;AAAA,EACT,QAKH,CAAC;AAAA,EAEN,MAAM,aAAgB,IAAsB,QAAkC;AAC5E,UAAM,UAAU,MAAM,KAAK,QAAQ,MAAM;AACzC,QAAI;AACF,qBAAe,MAAM;AACrB,aAAO,MAAM,GAAG;AAAA,IAClB,UAAE;AACA,cAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEQ,QAAQ,QAA2C;AACzD,mBAAe,MAAM;AACrB,QAAI,CAAC,KAAK,QAAQ;AAChB,WAAK,SAAS;AACd,aAAO,QAAQ,QAAQ,MAAM,KAAK,QAAQ,CAAC;AAAA,IAC7C;AAEA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,SAAS;AAAA,QACb,SAAS,CAAC,YAAwB;AAChC,kBAAQ,oBAAoB,SAAS,OAAO,OAAO;AACnD,kBAAQ,OAAO;AAAA,QACjB;AAAA,QACA,QAAQ,CAAC,WAAkB;AACzB,kBAAQ,oBAAoB,SAAS,OAAO,OAAO;AACnD,iBAAO,MAAM;AAAA,QACf;AAAA,QACA;AAAA,QACA,SAAS,MAAM;AACb,eAAK,QAAQ,KAAK,MAAM,OAAO,CAAC,UAAU,UAAU,MAAM;AAC1D,iBAAO,WAAW,+CAA+C,CAAC;AAAA,QACpE;AAAA,MACF;AACA,cAAQ,iBAAiB,SAAS,OAAO,SAAS,EAAE,MAAM,KAAK,CAAC;AAChE,WAAK,MAAM,KAAK,MAAM;AAAA,IACxB,CAAC;AAAA,EACH;AAAA,EAEQ,UAAgB;AACtB,WAAO,KAAK,MAAM,SAAS,GAAG;AAC5B,YAAM,OAAO,KAAK,MAAM,MAAM;AAC9B,UAAI,CAAC,KAAM;AACX,UAAI,KAAK,QAAQ,SAAS;AACxB,aAAK,OAAO,WAAW,+CAA+C,CAAC;AACvE;AAAA,MACF;AACA,WAAK,SAAS;AACd,WAAK,QAAQ,MAAM,KAAK,QAAQ,CAAC;AACjC;AAAA,IACF;AACA,SAAK,SAAS;AAAA,EAChB;AACF;AAEA,IAAM,YAAY,IAAI,WAAW;AAEjC,SAAS,OACP,MACA,YAAoB,gBACpB,UAAkB,OAClB,QAC6C;AAG7C,SAAO,UAAU,aAAa,YAAY;AACxC,mBAAe,QAAQ,OAAO,KAAK,KAAK,GAAG,CAAC,uBAAuB;AACnE,UAAM,cAAc,qBAAqB,IAAI,IAAI,IAAI;AACrD,aAAS,UAAU,GAAG,WAAW,aAAa,WAAW;AACvD,UAAI;AACF,eAAO,MAAM,WAAW,MAAM,WAAW,SAAS,MAAM;AAAA,MAC1D,SAAS,KAAK;AACZ,YAAI,aAAa,GAAG,EAAG,OAAM;AAC7B,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAI,UAAU,eAAe,kBAAkB,GAAG,GAAG;AAGnD,gBAAM,gBAAgB,OAAO,SAAS,MAAM;AAC5C;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC,GAAG,MAAM;AACX;AAEA,SAAS,qBAAqB,MAAyB;AACrD,QAAM,MAAM,KAAK,CAAC,KAAK;AACvB,SAAO,QAAQ,YAAY,QAAQ,WAAW,QAAQ,aAAa,QAAQ;AAC7E;AAEA,SAAS,WACP,MACA,WACA,SACA,QAC6C;AAC7C,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,mBAAe,QAAQ,OAAO,KAAK,KAAK,GAAG,CAAC,uBAAuB;AACnE,UAAM,QAAQ,cAAc,SAAS,MAAM;AAAA,MACzC,KAAK,SAAS,EAAE,UAAU,IAAI,CAAC;AAAA,MAC/B,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,IAClC,CAAC;AACD,QAAI,CAAC,MAAM,UAAU,CAAC,MAAM,QAAQ;AAClC,aAAO,IAAI,MAAM,OAAO,KAAK,KAAK,GAAG,CAAC,6BAA6B,CAAC;AACpE;AAAA,IACF;AAEA,QAAI,SAAS;AACb,QAAI,SAAS;AACb,QAAI,UAAU;AAEd,UAAM,QAAQ,WAAW,MAAM;AAC7B,gBAAU;AACV,cAAQ;AACR,YAAM,KAAK,SAAS;AACpB,aAAO,IAAI,MAAM,OAAO,KAAK,KAAK,GAAG,CAAC,oBAAoB,SAAS,IAAI,CAAC;AAAA,IAC1E,GAAG,SAAS;AACZ,UAAM,UAAU,MAAM;AACpB,UAAI,QAAS;AACb,gBAAU;AACV,mBAAa,KAAK;AAClB,cAAQ;AACR,YAAM,KAAK,SAAS;AACpB,aAAO,WAAW,OAAO,KAAK,KAAK,GAAG,CAAC,UAAU,CAAC;AAAA,IACpD;AACA,UAAM,UAAU,MAAM;AACpB,cAAQ,oBAAoB,SAAS,OAAO;AAAA,IAC9C;AACA,YAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAEzD,UAAM,OAAO,GAAG,QAAQ,CAAC,SAAiB;AACxC,gBAAU,KAAK,SAAS;AAAA,IAC1B,CAAC;AACD,UAAM,OAAO,GAAG,QAAQ,CAAC,SAAiB;AACxC,gBAAU,KAAK,SAAS;AAAA,IAC1B,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,UAAI,QAAS;AACb,gBAAU;AACV,mBAAa,KAAK;AAClB,cAAQ;AACR,aAAO,GAAG;AAAA,IACZ,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,UAAI,QAAS;AACb,gBAAU;AACV,mBAAa,KAAK;AAClB,cAAQ;AAER,YAAM,iBAAiB,KAAK,WAAW,KAAK,KAAK,CAAC,MAAM;AACxD,UAAI,SAAS,KAAM,kBAAkB,SAAS,GAAI;AAChD,gBAAQ,EAAE,QAAQ,OAAO,CAAC;AAAA,MAC5B,OAAO;AACL;AAAA,UACE,IAAI;AAAA,YACF,OAAO,KAAK,KAAK,GAAG,CAAC,iBAAiB,IAAI,MAAM,eAAe,UAAU,MAAM,CAAC;AAAA,UAClF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAMA,IAAI,gBAAgB;AAEpB,IAAM,mBAAN,MAAuB;AAAA,EACb,QAAoC;AAAA,EACpC,cAAc;AAAA,EACd,SAAS;AAAA,EACT,eAAwC;AAAA,EACxC,kBAAkB,oBAAI,IAQ5B;AAAA,EACe;AAAA,EAEjB,YAAY,SAAiB;AAC3B,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA,EAGA,MAAM,QAA0B;AAC9B,QAAI,KAAK,SAAS,CAAC,KAAK,MAAM,UAAU,KAAK,aAAa;AACxD,aAAO;AAAA,IACT;AACA,QAAI,KAAK,cAAc;AACrB,aAAO,KAAK;AAAA,IACd;AACA,SAAK,gBAAgB,YAAY;AAK/B,YAAM,wBAAwB,KAAK,SAAS,QAAQ,CAAC,KAAK,MAAM;AAChE,UAAI,CAAC,uBAAuB;AAC1B,YAAI,KAAK,OAAO;AACd,eAAK,QAAQ,EAAE,WAAW,KAAK,CAAC;AAAA,QAClC;AACA,YAAI;AACF,gBAAM,QAAQ,cAAc,KAAK,SAAS,CAAC,KAAK,GAAG;AAAA,YACjD,KAAK,SAAS,EAAE,UAAU,IAAI,CAAC;AAAA,YAC/B,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,UAChC,CAAC;AACD,eAAK,QAAQ;AACb,eAAK,SAAS;AAEd,gBAAM,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AACzC,gBAAI,KAAK,UAAU,MAAO;AAC1B,iBAAK,iBAAiB,IAAI;AAAA,UAC5B,CAAC;AACD,gBAAM,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AACzC,gBAAI,KAAK,UAAU,MAAO;AAC1B,kBAAM,MAAM,KAAK,SAAS,EAAE,KAAK;AACjC,gBAAI,IAAK,KAAI,MAAM,mBAAmB,kBAAkB,GAAG,CAAC,EAAE;AAAA,UAChE,CAAC;AACD,gBAAM,OAAO,GAAG,SAAS,CAAC,QAAQ;AAKhC,gBAAI,MAAM,qCAAqC,IAAI,OAAO,EAAE;AAAA,UAC9D,CAAC;AACD,gBAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,gBAAI,KAAK,UAAU,MAAO;AAC1B,gBAAI,MAAM,0BAA0B,IAAI,OAAO,EAAE;AACjD,iBAAK,QAAQ,EAAE,MAAM,CAAC;AAAA,UACxB,CAAC;AACD,gBAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,gBAAI,KAAK,UAAU,MAAO;AAC1B,gBAAI,MAAM,gCAAgC,IAAI,GAAG;AACjD,iBAAK,QAAQ,EAAE,MAAM,CAAC;AAAA,UACxB,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,cAAI,MAAM,qCAAqC,GAAG,EAAE;AACpD,eAAK,QAAQ,EAAE,WAAW,KAAK,CAAC;AAChC,iBAAO;AAAA,QACT;AAAA,MACF,OAAO;AACL,YAAI,MAAM,sDAAsD;AAAA,MAClE;AAEA,UAAI;AAIF,cAAM,SAAS,MAAM,KAAK;AAAA,UACxB;AAAA,UACA;AAAA,YACE,iBAAiB;AAAA,YACjB,cAAc,CAAC;AAAA,YACf,YAAY,EAAE,MAAM,mBAAmB,SAAS,QAAQ;AAAA,UAC1D;AAAA,UACA;AAAA,QACF;AACA,YAAI,CAAC,QAAQ;AAEX,eAAK,QAAQ,EAAE,WAAW,KAAK,CAAC;AAChC,iBAAO;AAAA,QACT;AACA,aAAK,iBAAiB,2BAA2B;AACjD,aAAK,cAAc;AACnB,YAAI,KAAK,oCAAoC;AAC7C,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAI,aAAa,KAAK,GAAG,GAAG;AAG1B,cAAI,MAAM,6EAAwE;AAElF,eAAK,cAAc;AAAA,QACrB,OAAO;AACL,cAAI,MAAM,2CAA2C,GAAG,EAAE;AAC1D,eAAK,QAAQ,EAAE,WAAW,KAAK,CAAC;AAAA,QAClC;AACA,eAAO;AAAA,MACT,UAAE;AACA,aAAK,eAAe;AAAA,MACtB;AAAA,IACF,GAAG;AACH,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,SACJ,MACA,MACA,YAAoB,KACpB,QACkB;AAClB,QAAI,CAAC,KAAK,SAAS,KAAK,MAAM,UAAU,CAAC,KAAK,aAAa;AACzD,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,WAAO,KAAK,YAAY,cAAc,EAAE,MAAM,WAAW,KAAK,GAAG,WAAW,MAAM;AAAA,EACpF;AAAA;AAAA,EAGA,aAAmB;AACjB,SAAK,QAAQ,EAAE,WAAW,KAAK,CAAC;AAAA,EAClC;AAAA,EAEA,WAAoB;AAClB,WAAO,KAAK,UAAU,QAAQ,CAAC,KAAK,MAAM,UAAU,KAAK;AAAA,EAC3D;AAAA;AAAA,EAGA,YAAqB;AACnB,WAAO,KAAK,UAAU,QAAQ,CAAC,KAAK,MAAM,UAAU,CAAC,KAAK;AAAA,EAC5D;AAAA,EAEQ,YACN,QACA,QACA,WACA,QACkB;AAClB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,qBAAe,QAAQ,WAAW,MAAM,yBAAyB;AACjE,UAAI,CAAC,KAAK,SAAS,CAAC,KAAK,MAAM,SAAS,KAAK,MAAM,QAAQ;AACzD,eAAO,IAAI,MAAM,+BAA+B,CAAC;AACjD;AAAA,MACF;AAEA,YAAM,KAAK;AACX,YAAM,QAAQ,WAAW,MAAM;AAC7B,aAAK,gBAAgB,OAAO,EAAE;AAC9B,gBAAQ;AACR,eAAO,IAAI,MAAM,WAAW,MAAM,oBAAoB,SAAS,IAAI,CAAC;AAAA,MACtE,GAAG,SAAS;AACZ,YAAM,UAAU,MAAM;AACpB,qBAAa,KAAK;AAClB,aAAK,gBAAgB,OAAO,EAAE;AAC9B,gBAAQ;AACR,eAAO,WAAW,WAAW,MAAM,UAAU,CAAC;AAAA,MAChD;AACA,YAAM,UAAU,MAAM;AACpB,gBAAQ,oBAAoB,SAAS,OAAO;AAAA,MAC9C;AAEA,WAAK,gBAAgB,IAAI,IAAI,EAAE,SAAS,QAAQ,OAAO,QAAQ,CAAC;AAChE,cAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACzD,YAAM,UAAU,KAAK,UAAU,EAAE,SAAS,OAAO,IAAI,QAAQ,OAAO,CAAC,IAAI;AACzE,WAAK,MAAM,MAAM,MAAM,SAAS,CAAC,QAAQ;AACvC,YAAI,KAAK;AACP,uBAAa,KAAK;AAClB,eAAK,gBAAgB,OAAO,EAAE;AAC9B,kBAAQ;AACR,iBAAO,IAAI,MAAM,qCAAqC,IAAI,OAAO,EAAE,CAAC;AAAA,QACtE;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,iBAAiB,QAAgB,QAAwC;AAC/E,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,MAAM,SAAS,KAAK,MAAM,OAAQ;AAC3D,QAAI,KAAK,MAAM,MAAM,UAAW;AAChC,UAAM,MAA+B,EAAE,SAAS,OAAO,OAAO;AAC9D,QAAI,OAAQ,KAAI,SAAS;AACzB,QAAI;AACF,WAAK,MAAM,MAAM,MAAM,KAAK,UAAU,GAAG,IAAI,IAAI;AAAA,IACnD,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,iBAAiB,MAAoB;AAC3C,SAAK,UAAU,KAAK,SAAS;AAC7B,QAAI;AACJ,YAAQ,aAAa,KAAK,OAAO,QAAQ,IAAI,OAAO,IAAI;AACtD,YAAM,OAAO,KAAK,OAAO,MAAM,GAAG,UAAU,EAAE,KAAK;AACnD,WAAK,SAAS,KAAK,OAAO,MAAM,aAAa,CAAC;AAC9C,UAAI,CAAC,KAAM;AACX,UAAI;AACF,cAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,aAAK,cAAc,GAAG;AAAA,MACxB,QAAQ;AACN,YAAI,MAAM,gCAAgC,eAAe,MAAM,GAAG,CAAC,EAAE;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,cAAc,KAAoC;AACxD,QAAI,IAAI,OAAO,UAAa,IAAI,OAAO,MAAM;AAC3C,YAAM,UAAU,KAAK,gBAAgB,IAAI,IAAI,EAAY;AACzD,UAAI,SAAS;AACX,qBAAa,QAAQ,KAAK;AAC1B,aAAK,gBAAgB,OAAO,IAAI,EAAY;AAC5C,gBAAQ,QAAQ;AAChB,YAAI,IAAI,OAAO;AACb,kBAAQ,OAAO,IAAI,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,CAAC;AAAA,QACrD,OAAO;AACL,kBAAQ,QAAQ,IAAI,MAAM;AAAA,QAC5B;AAAA,MACF;AACA;AAAA,IACF;AACA,QAAI,IAAI,QAAQ;AACd,UAAI,MAAM,yBAAyB,IAAI,MAAM,EAAE;AAAA,IACjD;AAAA,EACF;AAAA,EAEQ,QAAQ,MAA0E;AACxF,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,QAAI,CAAC,OAAQ;AACb,QAAI,MAAM,SAAS,KAAK,UAAU,KAAK,OAAO;AAC5C;AAAA,IACF;AACA,QAAI,MAAM,aAAa,CAAC,OAAO,QAAQ;AACrC,aAAO,KAAK,SAAS;AAAA,IACvB;AACA,SAAK,cAAc;AACnB,eAAW,CAAC,EAAE,OAAO,KAAK,KAAK,iBAAiB;AAC9C,mBAAa,QAAQ,KAAK;AAC1B,cAAQ,QAAQ;AAChB,cAAQ,OAAO,IAAI,MAAM,4BAA4B,CAAC;AAAA,IACxD;AACA,SAAK,gBAAgB,MAAM;AAC3B,SAAK,eAAe;AACpB,SAAK,QAAQ;AACb,SAAK,SAAS;AAAA,EAChB;AACF;AAGA,IAAM,qBAAqB;AAQ3B,IAAM,oBAAoB;AAE1B,SAAS,2BACP,MACA,WACmB;AACnB,QAAM,UAA6B,CAAC;AACpC,aAAW,QAAQ,KAAK,MAAM,IAAI,GAAG;AACnC,UAAM,IAAI,mBAAmB,KAAK,KAAK,KAAK,CAAC;AAC7C,QAAI,CAAC,EAAG;AACR,UAAM,OAAO,EAAE,CAAC;AAEhB,UAAM,iBAAiB,kBAAkB,KAAK,IAAI;AAClD,QAAI,CAAC,eAAgB;AACrB,YAAQ,KAAK;AAAA,MACX,OAAO,EAAE,CAAC;AAAA,MACV,MAAM,eAAe,CAAC,KAAK;AAAA,MAC3B,SAAS;AAAA,MACT,OAAO,SAAS,EAAE,CAAC,GAAG,EAAE,IAAI;AAAA,MAC5B;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,qBACP,QACA,YAA0C,UACvB;AACnB,QAAM,YAAY;AAClB,MAAI,CAAC,UAAW,QAAO,CAAC;AACxB,QAAM,UAA6B,CAAC;AACpC,QAAM,WAAW,CAAC,SAAoB;AACpC,eAAW,OAAO,MAAM;AACtB,YAAM,IAAI;AACV,cAAQ,KAAK;AAAA,QACX,OAAO,OAAO,EAAE,UAAU,WAAW,EAAE,MAAM,QAAQ,MAAM,EAAE,IAAI;AAAA,QACjE,MAAM,OAAO,EAAE,SAAS,WACpB,EAAE,OACF,OAAO,EAAE,SAAS,WAClB,EAAE,OACD,OAAO,EAAE,UAAU,WAAW,EAAE,MAAM,QAAQ,MAAM,EAAE,IAAI;AAAA,QAC/D,SAAS,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU;AAAA,QACrD,OAAO,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ;AAAA,QAC/C,SAAS,gBAAgB,EAAE,OAAO;AAAA,QAClC;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACA,QAAM,gBAAgB,UAAU;AAChC,QAAM,UAAU,eAAe,WAAW,eAAe;AACzD,MAAI,MAAM,QAAQ,OAAO,EAAG,UAAS,OAAO;AAC5C,QAAM,UAAU,UAAU;AAC1B,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,eAAW,QAAQ,SAAS;AAC1B,YAAM,aAAa,MAAM;AACzB,YAAM,aAAa,YAAY,WAAW,YAAY;AACtD,UAAI,MAAM,QAAQ,UAAU,EAAG,UAAS,UAAU;AAClD,UAAI,OAAO,MAAM,SAAS,UAAU;AAClC,YAAI;AACF,gBAAM,SAAS,KAAK,MAAM,KAAK,IAAI;AACnC,gBAAM,cAAc,QAAQ,WAAW,QAAQ;AAC/C,cAAI,MAAM,QAAQ,WAAW,EAAG,UAAS,WAAW;AAAA,QACtD,QAAQ;AACN,gBAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;AACrF,gBAAM,SAAS,2BAA2B,KAAK,MAAM,SAAS;AAC9D,qBAAW,KAAK,QAAQ;AACtB,kBAAM,MAAM,GAAG,EAAE,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI;AAC9C,gBAAI,CAAC,aAAa,IAAI,GAAG,GAAG;AAC1B,sBAAQ,KAAK,CAAC;AACd,2BAAa,IAAI,GAAG;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,qBACP,QACA,YAA0C,cACvB;AACnB,QAAM,aAAa,OAAO,KAAK;AAC/B,MAAI,CAAC,cAAc,eAAe,oBAAqB,QAAO,CAAC;AAC/D,QAAM,SAAS,KAAK,MAAM,UAAU;AACpC,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AACpC,SAAO,OAAO;AAAA,IACZ,CAAC,WAAqD;AAAA,MACpD,OAAQ,MAAM,SAAoB;AAAA,MAClC,MACG,MAAM,QACN,MAAM,QACN,MAAM,SACP;AAAA,MACF,SAAU,MAAM,WAAsB;AAAA,MACtC,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAAA,MACvD,SAAS,gBAAgB,MAAM,OAAO;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAI,uBAAgD;AACpD,IAAI,2BAA0C;AAE9C,SAAS,uBAAuB,SAAmC;AACjE,QAAM,iBAAiB,QAAQ,KAAK,KAAK;AACzC,MAAI,wBAAwB,6BAA6B,gBAAgB;AACvE,yBAAqB,WAAW;AAChC,2BAAuB;AACvB,+BAA2B;AAAA,EAC7B;AACA,MAAI,CAAC,sBAAsB;AACzB,2BAAuB,IAAI,iBAAiB,cAAc;AAC1D,+BAA2B;AAAA,EAC7B;AACA,SAAO;AACT;AAMO,IAAM,YAAN,MAAM,WAAmC;AAAA,EAwC9C,YACmB,YACA,YACjB,MACA;AAHiB;AACA;AAGjB,SAAK,UAAU,MAAM;AACrB,SAAK,kBAAkB,MAAM,mBAAmB;AAChD,SAAK,sBAAsB,KAAK,IAAI,GAAG,MAAM,uBAAuB,KAAK,GAAM;AAC/E,SAAK,oBAAoB,MAAM,SAAS,KAAK,IAAI,KAAK,QAAQ,KAAK,IAAI;AACvE,QAAI,KAAK,mBAAmB;AAC1B,WAAK,UAAU,KAAK;AACpB,WAAK,gBAAgB;AAAA,IACvB;AACA,SAAK,gBAAgB,QAAQ,MAAM,SAAS;AAC5C,SAAK,0BAA0B,MAAM,2BAA2B;AAAA,EAClE;AAAA,EAdmB;AAAA,EACA;AAAA,EAzCX,YAA4B;AAAA,EAC5B,sBAAqC;AAAA,EACrC,oBAAmC;AAAA,EACnC,oBAAmC;AAAA,EAE3C,IAAI,uBAAsC;AACxC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,oBAAmC;AACrC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,uBAA6B;AAC3B,SAAK,sBAAsB;AAC3B,SAAK,oBAAoB;AACzB,UAAM,KAAK,kBAAkB;AAC7B,OAAG,0BAA0B;AAC7B,OAAG,2BAA2B;AAAA,EAChC;AAAA,EAEiB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,gBAA8D;AAAA,EAC9D,aAA4B;AAAA,EAC5B,oBAAmC;AAAA;AAAA,EAGnC,gBAAyC;AAAA,EACzC,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACb;AAAA,EACA;AAAA;AAAA,EAET,0BAA0B;AAAA,EAClC,OAAwB,gCAAgC;AAAA,EAmBhD,UAAkB;AAAA,EAE1B,MAAM,QAA0B;AAC9B,UAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,QAAI,KAAK,eAAe;AACtB,YAAM,KAAK,YAAY;AAAA,IACzB;AACA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAc,cAAgC;AAC5C,SAAK,sBAAsB,KAAK,IAAI;AACpC,SAAK,gBAAgB,uBAAuB,KAAK,OAAO;AACxD,QAAI;AAOF,YAAM,yBAAyB;AAC/B,YAAM,KAAK,MAAM,QAAQ,KAAK;AAAA,QAC5B,KAAK,cAAc,MAAM;AAAA,QACzB,IAAI,QAAe,CAAC,YAAY,WAAW,MAAM,QAAQ,KAAK,GAAG,sBAAsB,CAAC;AAAA,MAC1F,CAAC;AACD,UAAI,CAAC,IAAI;AACP,cAAM,UAAU,KAAK,cAAc,UAAU;AAC7C,YAAI,MAAM,8CAA8C,sBAAsB,kBAAkB,UAAU,qBAAqB,EAAE,EAAE;AACnI,aAAK,kBAAkB;AACvB,eAAO;AAAA,MACT;AACA,UAAI,KAAK,gDAAgD,KAAK,UAAU,GAAG;AAC3E,WAAK,kBAAkB;AACvB,WAAK,0BAA0B;AAC/B,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,MAAM,6BAA6B,GAAG,EAAE;AAC5C,WAAK,kBAAkB;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,WAA6B;AACzC,UAAM,eAAe,CAAC,QAAgB,WAAkC;AACtE,YAAM,QAAQ,GAAG,MAAM;AAAA,EAAK,MAAM,GAC/B,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC7B,UAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,YAAM,gBAAgB,MAAM,OAAO,CAAC,SAAS,gBAAgB,IAAI,MAAM,IAAI;AAC3E,UAAI,cAAc,WAAW,EAAG,QAAO,MAAM,CAAC,KAAK;AACnD,aAAO,cAAc,KAAK,CAAC,SAAS,WAAW,KAAK,IAAI,CAAC,KAAK,cAAc,CAAC,KAAK;AAAA,IACpF;AACA,UAAM,mBAAmB,CAAC,QAAuB;AAC/C,WAAK,oBAAoB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IAC1E;AAEA,QAAI,KAAK,mBAAmB;AAC1B,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,CAAC,WAAW,GAAG,sBAAsB,KAAK,iBAAiB;AACvF,aAAK,YAAY;AACjB,aAAK,UAAU,KAAK;AACpB,aAAK,gBAAgB;AACrB,aAAK,aAAa,aAAa,OAAO,QAAQ,OAAO,MAAM;AAC3D,aAAK,oBAAoB;AACzB,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,yBAAiB,GAAG;AAGpB,aAAK;AAAA,UACH,mCAAmC,KAAK,iBAAiB,MAAM,KAAK,iBAAiB;AAAA,QACvF;AAAA,MACF;AAAA,IACF;AAGA,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,CAAC,WAAW,GAAG,sBAAsB,KAAK;AACtE,WAAK,YAAY;AACjB,WAAK,UAAU;AACf,WAAK,gBAAgB;AACrB,WAAK,aAAa,aAAa,OAAO,QAAQ,OAAO,MAAM;AAC3D,WAAK,oBAAoB;AACzB,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,uBAAiB,GAAG;AAEpB,iBAAW,gBAAgB,oBAAoB;AAC7C,YAAI;AACF,gBAAM,SAAS,MAAM,OAAO,CAAC,WAAW,GAAG,sBAAsB,YAAY;AAC7E,eAAK,YAAY;AACjB,eAAK,UAAU;AACf,eAAK,gBAAgB;AACrB,eAAK,aAAa,aAAa,OAAO,QAAQ,OAAO,MAAM;AAC3D,eAAK,oBAAoB;AACzB,cAAI,KAAK,iBAAiB,YAAY,EAAE;AACxC,iBAAO;AAAA,QACT,SAAS,aAAa;AACpB,2BAAiB,WAAW;AAAA,QAE9B;AAAA,MACF;AACA,WAAK,YAAY;AACjB,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,mBAAmB,SAAuB;AAChD,UAAM,QAAQ,kBAAkB;AAChC,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,UACJ,MAAM,oBAAoB,QAAQ,MAAM,MAAM,mBAAmB;AACnE,QAAI,CAAC,SAAS;AACZ,UAAI,MAAM,OAAO;AACjB;AAAA,IACF;AACA,UAAM,kBAAkB;AACxB,QAAI,KAAK,iBAAiB;AAExB,UAAI,MAAM,OAAO;AACjB;AAAA,IACF;AACA,QAAI,KAAK,OAAO;AAAA,EAClB;AAAA;AAAA,EAGA,MAAc,mBAAkC;AAC9C,QAAI,CAAC,KAAK,cAAe;AAEzB,QAAI,KAAK,mBAAmB,KAAK,eAAe,SAAS,EAAG;AAE5D,QAAI,KAAK,oBAAoB,OAAO;AAClC,YAAM,UAAU,KAAK,IAAI,IAAI,KAAK;AAClC,UAAI,UAAU,KAAK,wBAAyB;AAAA,IAC9C;AACA,SAAK,kBAAkB;AACvB,UAAM,KAAK,YAAY;AAAA,EACzB;AAAA,EAEA,cAAuB;AACrB,WAAO,KAAK,cAAc,QAAQ,KAAK;AAAA,EACzC;AAAA;AAAA,EAGA,cAAsB;AACpB,UAAM,UAAU,KAAK,YAAY,KAAK,UAAW,KAAK,qBAAqB;AAC3E,UAAM,aAAa,KAAK,cAAc;AACtC,UAAM,aAAa,KAAK,oBAAoB,kBAAkB,KAAK,iBAAiB,KAAK;AACzF,WAAO,OAAO,KAAK,SAAS,WAAW,KAAK,eAAe,YAAY,CAAC,CAAC,KAAK,aAAa,YAAY,OAAO,kBAAkB,KAAK,aAAa,eAAe,UAAU,GAAG,UAAU;AAAA,EAC1L;AAAA,EAEA,eAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAA4B;AAClC,SAAK,0BAA0B;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,2BAA2B,OAAe,KAAc,YAA0B;AAGxF,QAAI,CAAC,KAAK,iBAAiB;AACzB,UAAI,MAAM,cAAc,KAAK,iBAAiB,UAAU,8CAA8C,GAAG,EAAE;AAC3G;AAAA,IACF;AACA,SAAK,2BAA2B;AAChC,QAAI,KAAK,2BAA2B,WAAU,+BAA+B;AAC3E,UAAI,MAAM,cAAc,KAAK,iBAAiB,UAAU,OAAO,KAAK,uBAAuB,yCAAyC,GAAG,EAAE;AACzI,WAAK,eAAe,WAAW;AAC/B,WAAK,kBAAkB;AACvB,WAAK,0BAA0B;AAAA,IACjC,OAAO;AACL,UAAI,MAAM,cAAc,KAAK,iBAAiB,UAAU,iBAAiB,KAAK,uBAAuB,IAAI,WAAU,6BAA6B,MAAM,GAAG,EAAE;AAAA,IAC7J;AAAA,EACF;AAAA,EAEA,MAAc,cACZ,MACA,WACA,QAC6C;AAC7C,WAAO,OAAO,MAAM,WAAW,KAAK,SAAS,MAAM;AAAA,EACrD;AAAA,EAEQ,sBAA+B;AACrC,WAAO,eAAe,gBAAgB,KAAK,UAAU,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA,EACnE;AAAA,EAEQ,wBAAiC;AACvC,WAAO,eAAe,gBAAgB,KAAK,UAAU,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,UAAmB;AACzB,WAAO,eAAe,gBAAgB,KAAK,UAAU,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;AAAA,EACnE;AAAA,EAEQ,qBAAqB,SAA8D;AACzF,UAAM,aAAa,uBAAuB,OAAO;AACjD,QAAI,CAAC,WAAY,QAAO;AACxB,UAAM,WAA+B,CAAC;AACtC,QAAI,WAAW,UAAU,KAAK,oBAAoB,GAAG;AACnD,eAAS,SAAS,WAAW;AAAA,IAC/B;AACA,QAAI,WAAW,YAAY,QAAQ,KAAK,sBAAsB,GAAG;AAC/D,eAAS,UAAU;AAAA,IACrB;AACA,WAAO,OAAO,KAAK,QAAQ,EAAE,SAAS,IAAI,WAAW;AAAA,EACvD;AAAA,EAEA,8BAA8B,SAA8D;AAC1F,WAAO,KAAK,qBAAqB,OAAO;AAAA,EAC1C;AAAA,EAEA,MAAM,OACJ,OACA,YACA,YACA,SACA,WAC4B;AAC5B,QAAI,CAAC,KAAK,YAAY,EAAG,QAAO,CAAC;AACjC,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,QAAS,QAAO,CAAC;AAEtB,UAAM,MAAM,cAAc,KAAK;AAC/B,UAAM,IAAI,cAAc,KAAK;AAC7B,UAAM,gBAAgB,KAAK,qBAAqB,OAAO;AAKvD,UAAM,qBAAqB,gBAAgB,KAAK,UAAU,aAAa,IAAI;AAC3E,UAAM,WAAW,WAAW,QAAQ,EAAE,OAAO,GAAG,GAAG,IAAI,CAAC,IAAI,kBAAkB,IAAI,OAAO,EAAE,EAAE,OAAO,KAAK;AACzG,UAAM,SAAS,mBAAmB,QAAQ;AAC1C,QAAI,QAAQ;AACV,UAAI,MAAM,yBAAyB,OAAO,MAAM,WAAW;AAC3D,aAAO;AAAA,IACT;AAGA,UAAM,KAAK,iBAAiB;AAC5B,QAAI,KAAK,iBAAiB;AACxB,UAAI;AACJ,UAAI;AACF,kBAAU,MAAM,KAAK,gBAAgB,SAAS,KAAK,GAAG,eAAe,WAAW,MAAM;AAAA,MACxF,SAAS,KAAK;AACZ,YAAI,qBAAqB,KAAK,WAAW,MAAM,GAAG;AAChD,gBAAM,aAAa,GAAG,IAAI,MAAM,WAAW,2BAA2B;AAAA,QACxE;AACA,cAAM;AAAA,MACR;AAQA,UAAI,YAAY,MAAM;AACpB,YAAI,QAAQ,WAAW,GAAG;AACxB,cAAI,MAAM,2DAA2D;AAAA,QACvE;AACA,2BAAmB,UAAU,OAAO;AACpC,eAAO;AAAA,MACT;AAGA,UAAI,MAAM,4EAA4E;AACtF,aAAO,CAAC;AAAA,IACV;AAKA,QAAI,KAAK,eAAe,UAAU,GAAG;AACnC,UAAI,MAAM,iDAAiD;AAC3D,aAAO,CAAC;AAAA,IACV;AAGA,UAAM,oBAAoB,MAAM,KAAK,oBAAoB,SAAS,KAAK,GAAG,eAAe,WAAW,MAAM;AAC1G,uBAAmB,UAAU,iBAAiB;AAC9C,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,aACJ,OACA,YACA,WAC4B;AAC5B,QAAI,CAAC,KAAK,YAAY,EAAG,QAAO,CAAC;AACjC,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,QAAS,QAAO,CAAC;AAEtB,UAAM,IAAI,cAAc;AAGxB,UAAM,KAAK,iBAAiB;AAC5B,QAAI,KAAK,iBAAiB;AAExB,UAAI;AACJ,UAAI;AACF,kBAAU,MAAM,KAAK,gBAAgB,SAAS,QAAW,GAAG,QAAW,WAAW,MAAM;AAAA,MAC1F,SAAS,KAAK;AACZ,YAAI,qBAAqB,KAAK,WAAW,MAAM,GAAG;AAChD,gBAAM,aAAa,GAAG,IAAI,MAAM,WAAW,kCAAkC;AAAA,QAC/E;AACA,cAAM;AAAA,MACR;AAEA,UAAI,YAAY,MAAM;AACpB,YAAI,QAAQ,WAAW,GAAG;AACxB,cAAI,MAAM,kEAAkE;AAAA,QAC9E;AACA,eAAO;AAAA,MACT;AACA,UAAI,MAAM,mFAAmF;AAC7F,aAAO,CAAC;AAAA,IACV;AAGA,QAAI,KAAK,eAAe,UAAU,GAAG;AACnC,UAAI,MAAM,uDAAuD;AACjE,aAAO,CAAC;AAAA,IACV;AAGA,WAAO,KAAK,0BAA0B,SAAS,GAAG,WAAW,MAAM;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WACJ,OACA,YACA,YACA,WAC4B;AAC5B,QAAI,CAAC,KAAK,YAAY,EAAG,QAAO,CAAC;AACjC,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,QAAS,QAAO,CAAC;AACtB,UAAM,MAAM,cAAc,KAAK;AAC/B,UAAM,IAAI,cAAc,KAAK;AAG7B,UAAM,KAAK,iBAAiB;AAC5B,QAAI,KAAK,mBAAmB,KAAK,eAAe;AAC9C,UAAI;AACJ,UAAI;AACF,kBAAU,MAAM,KAAK,oBAAoB,SAAS,KAAK,GAAG,WAAW,MAAM;AAAA,MAC7E,SAAS,KAAK;AACZ,YAAI,qBAAqB,KAAK,WAAW,MAAM,GAAG;AAChD,gBAAM,aAAa,GAAG,IAAI,MAAM,WAAW,yBAAyB;AAAA,QACtE;AACA,cAAM;AAAA,MACR;AAGA,UAAI,YAAY,MAAM;AACpB,YAAI,QAAQ,WAAW,GAAG;AACxB,cAAI,MAAM,yDAAyD;AAAA,QACrE;AACA,eAAO;AAAA,MACT;AACA,UAAI,MAAM,0EAA0E;AACpF,aAAO,CAAC;AAAA,IACV;AACA,QAAI,KAAK,eAAe,UAAU,GAAG;AACnC,UAAI,MAAM,+CAA+C;AACzD,aAAO,CAAC;AAAA,IACV;AACA,WAAO,KAAK,wBAAwB,SAAS,KAAK,GAAG,WAAW,MAAM;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aACJ,OACA,YACA,YACA,WAC4B;AAC5B,QAAI,CAAC,KAAK,YAAY,EAAG,QAAO,CAAC;AACjC,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,QAAS,QAAO,CAAC;AACtB,UAAM,MAAM,cAAc,KAAK;AAC/B,UAAM,IAAI,cAAc,KAAK;AAG7B,UAAM,KAAK,iBAAiB;AAC5B,QAAI,KAAK,mBAAmB,KAAK,eAAe;AAC9C,UAAI;AACJ,UAAI;AACF,kBAAU,MAAM,KAAK,iBAAiB,SAAS,KAAK,GAAG,WAAW,MAAM;AAAA,MAC1E,SAAS,KAAK;AACZ,YAAI,qBAAqB,KAAK,WAAW,MAAM,GAAG;AAChD,gBAAM,aAAa,GAAG,IAAI,MAAM,WAAW,4BAA4B;AAAA,QACzE;AACA,cAAM;AAAA,MACR;AAGA,UAAI,YAAY,MAAM;AACpB,YAAI,QAAQ,WAAW,GAAG;AACxB,cAAI,MAAM,4DAA4D;AAAA,QACxE;AACA,eAAO;AAAA,MACT;AACA,UAAI,MAAM,6EAA6E;AACvF,aAAO,CAAC;AAAA,IACV;AACA,QAAI,KAAK,eAAe,UAAU,GAAG;AACnC,UAAI,MAAM,kDAAkD;AAC5D,aAAO,CAAC;AAAA,IACV;AACA,WAAO,KAAK,qBAAqB,SAAS,KAAK,GAAG,WAAW,MAAM;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aACJ,OACA,YACA,YACA,WAC4B;AAC5B,UAAM,IAAI,cAAc,KAAK;AAC7B,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,QAAS,QAAO,CAAC;AAEtB,UAAM,CAAC,aAAa,aAAa,IAAI,MAAM,QAAQ,IAAI;AAAA,MACrD,KAAK,WAAW,SAAS,YAAY,GAAG,SAAS;AAAA,MACjD,KAAK,aAAa,SAAS,YAAY,GAAG,SAAS;AAAA,IACrD,CAAC;AAGD,UAAM,SAAS,oBAAI,IAA6B;AAChD,eAAW,KAAK,CAAC,GAAG,aAAa,GAAG,aAAa,GAAG;AAClD,YAAM,MAAM,EAAE,QAAQ,EAAE;AACxB,YAAM,WAAW,OAAO,IAAI,GAAG;AAC/B,UAAI,CAAC,YAAY,EAAE,QAAQ,SAAS,OAAO;AACzC,eAAO,IAAI,KAAK;AAAA,UACd,GAAG;AAAA,UACH,SAAS,EAAE,WAAW,UAAU,WAAW;AAAA,QAC7C,CAAC;AAAA,MACH;AAAA,IACF;AAGA,WAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EACvB,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAChC,MAAM,GAAG,CAAC;AAAA,EACf;AAAA,EAEA,MAAc,gBACZ,OACA,YACA,YACA,SACA,QACmC;AACnC,QAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,gBAAiB,QAAO;AAEzD,UAAM,cAAc,KAAK,IAAI;AAC7B,UAAM,KAAK,KAAK,QAAQ;AACxB,QAAI;AACF,UAAI;AACJ,UAAI,IAAI;AAGN,cAAM,WAAmD,CAAC,EAAE,MAAM,OAAO,MAAM,CAAC;AAEhF,iBAAS,KAAK,EAAE,MAAM,OAAO,MAAM,CAAC;AACpC,eAAO,EAAE,UAAU,OAAO,WAAW;AACrC,YAAI,YAAY;AACd,eAAK,cAAc,CAAC,UAAU;AAAA,QAChC;AACA,YAAI,SAAS,QAAQ;AACnB,eAAK,SAAS,QAAQ;AAAA,QACxB;AACA,YAAI,SAAS,YAAY,MAAM;AAC7B,eAAK,UAAU;AAAA,QACjB;AAAA,MACF,OAAO;AAEL,eAAO,EAAE,OAAO,OAAO,WAAW;AAClC,YAAI,YAAY;AACd,eAAK,aAAa;AAAA,QACpB;AACA,YAAI,SAAS,QAAQ;AACnB,eAAK,SAAS,QAAQ;AAAA,QACxB;AACA,YAAI,SAAS,YAAY,MAAM;AAC7B,eAAK,UAAU;AAAA,QACjB;AAAA,MACF;AAEA,YAAM,SAAS,MAAM,KAAK,cAAc,SAAS,SAAS,MAAM,uBAAuB,MAAM;AAC7F,YAAM,aAAa,KAAK,IAAI,IAAI;AAEhC,UAAI,KAAK,SAAS,WAAW,cAAc,KAAK,QAAQ,aAAa;AACnE,YAAI;AAAA,UACF,qCAAqC,UAAU,eAAe,cAAc,QAAQ,eAAe,UAAU,eAAe,MAAM,MAAM,OAAO,EAAE;AAAA,QACnJ;AAAA,MACF;AAEA,YAAM,UAAU,qBAAqB,QAAQ,QAAQ;AAErD,UAAI,MAAM,sBAAsB,QAAQ,MAAM,eAAe,UAAU,UAAU,EAAE,GAAG;AACtF,WAAK,oBAAoB;AACzB,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,aAAa,KAAK,IAAI,IAAI;AAChC,UAAI,qBAAqB,KAAK,MAAM,GAAG;AACrC,YAAI,MAAM,6CAA6C,UAAU,IAAI;AACrE,cAAM,aAAa,GAAG,IAAI,MAAM,WAAW,2BAA2B;AAAA,MACxE;AAEA,UAAI,qBAAqB,GAAG,GAAG;AAC7B,YAAI,MAAM,qCAAqC,UAAU,gCAAgC;AACzF,eAAO;AAAA,MACT;AAEA,WAAK,2BAA2B,UAAU,KAAK,UAAU;AACzD,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,oBACZ,OACA,YACA,YACA,QACmC;AACnC,QAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,gBAAiB,QAAO;AAEzD,UAAM,cAAc,KAAK,IAAI;AAC7B,UAAM,KAAK,KAAK,QAAQ;AACxB,QAAI;AACF,UAAI;AACJ,UAAI,IAAI;AAEN,iBAAS,MAAM,KAAK,cAAc;AAAA,UAChC;AAAA,UACA;AAAA,YACE,UAAU,CAAC,EAAE,MAAM,OAAO,MAAM,CAAC;AAAA,YACjC,aAAa,CAAC,UAAU;AAAA,YACxB,OAAO;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF,OAAO;AAEL,iBAAS,MAAM,KAAK,cAAc;AAAA,UAChC;AAAA,UACA,EAAE,OAAO,OAAO,YAAY,WAAW;AAAA,UACvC;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,YAAM,aAAa,KAAK,IAAI,IAAI;AAChC,YAAM,UAAU,qBAAqB,MAAM;AAC3C,UAAI,MAAM,oBAAoB,QAAQ,MAAM,eAAe,UAAU,UAAU,EAAE,GAAG;AACpF,WAAK,oBAAoB;AACzB,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,aAAa,KAAK,IAAI,IAAI;AAChC,UAAI,qBAAqB,KAAK,MAAM,GAAG;AACrC,YAAI,MAAM,2CAA2C,UAAU,IAAI;AACnE,cAAM,aAAa,GAAG,IAAI,MAAM,WAAW,yBAAyB;AAAA,MACtE;AACA,UAAI,qBAAqB,GAAG,GAAG;AAC7B,YAAI,MAAM,mCAAmC,UAAU,gCAAgC;AACvF,eAAO;AAAA,MACT;AACA,WAAK,2BAA2B,QAAQ,KAAK,UAAU;AACvD,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,iBACZ,OACA,YACA,YACA,QACmC;AACnC,QAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,gBAAiB,QAAO;AAEzD,UAAM,cAAc,KAAK,IAAI;AAC7B,UAAM,KAAK,KAAK,QAAQ;AACxB,QAAI;AACF,UAAI;AACJ,UAAI,IAAI;AAEN,iBAAS,MAAM,KAAK,cAAc;AAAA,UAChC;AAAA,UACA;AAAA,YACE,UAAU,CAAC,EAAE,MAAM,OAAO,MAAM,CAAC;AAAA,YACjC,aAAa,CAAC,UAAU;AAAA,YACxB,OAAO;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF,OAAO;AAEL,iBAAS,MAAM,KAAK,cAAc;AAAA,UAChC;AAAA,UACA,EAAE,OAAO,OAAO,YAAY,WAAW;AAAA,UACvC;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,YAAM,aAAa,KAAK,IAAI,IAAI;AAChC,YAAM,UAAU,qBAAqB,MAAM;AAC3C,UAAI,MAAM,uBAAuB,QAAQ,MAAM,eAAe,UAAU,UAAU,EAAE,GAAG;AACvF,WAAK,oBAAoB;AACzB,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,aAAa,KAAK,IAAI,IAAI;AAChC,UAAI,qBAAqB,KAAK,MAAM,GAAG;AACrC,YAAI,MAAM,8CAA8C,UAAU,IAAI;AACtE,cAAM,aAAa,GAAG,IAAI,MAAM,WAAW,4BAA4B;AAAA,MACzE;AACA,UAAI,qBAAqB,GAAG,GAAG;AAC7B,YAAI,MAAM,sCAAsC,UAAU,gCAAgC;AAC1F,eAAO;AAAA,MACT;AACA,WAAK,2BAA2B,WAAW,KAAK,UAAU;AAC1D,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,oBACZ,OACA,YACA,YACA,SACA,QAC4B;AAC5B,QAAI,KAAK,cAAc,MAAO,QAAO,CAAC;AAEtC,UAAM,cAAc,KAAK,IAAI;AAC7B,QAAI;AACF,YAAM,OAAO,CAAC,SAAS,OAAO,MAAM,YAAY,UAAU,MAAM,OAAO,UAAU,CAAC;AAClF,UAAI,SAAS,QAAQ;AACnB,aAAK,KAAK,YAAY,QAAQ,MAAM;AAAA,MACtC;AACA,UAAI,SAAS,YAAY,MAAM;AAC7B,aAAK,KAAK,WAAW;AAAA,MACvB;AACA,YAAM,EAAE,OAAO,IAAI,MAAM;AAAA,QACvB;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL;AAAA,MACF;AACA,YAAM,aAAa,KAAK,IAAI,IAAI;AAChC,UAAI,KAAK,SAAS,WAAW,cAAc,KAAK,QAAQ,aAAa;AACnE,YAAI;AAAA,UACF,8BAA8B,UAAU,eAAe,UAAU,eAAe,UAAU,eAAe,MAAM,MAAM;AAAA,QACvH;AAAA,MACF;AAEA,aAAO,qBAAqB,QAAQ,YAAY;AAAA,IAClD,SAAS,KAAK;AACZ,UAAI,qBAAqB,KAAK,MAAM,GAAG;AACrC,cAAM,aAAa,GAAG,IAAI,MAAM,WAAW,+BAA+B;AAAA,MAC5E;AACA,UAAI,MAAM,sBAAsB,GAAG,EAAE;AACrC,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAc,wBACZ,OACA,YACA,YACA,QAC4B;AAC5B,QAAI,KAAK,cAAc,MAAO,QAAO,CAAC;AACtC,UAAM,cAAc,KAAK,IAAI;AAC7B,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAM;AAAA,QACvB,CAAC,UAAU,OAAO,MAAM,YAAY,UAAU,MAAM,OAAO,UAAU,CAAC;AAAA,QACtE;AAAA,QACA,KAAK;AAAA,QACL;AAAA,MACF;AACA,UAAI,MAAM,aAAa,KAAK,IAAI,IAAI,WAAW,IAAI;AACnD,aAAO,qBAAqB,MAAM;AAAA,IACpC,SAAS,KAAK;AACZ,UAAI,qBAAqB,KAAK,MAAM,GAAG;AACrC,cAAM,aAAa,GAAG,IAAI,MAAM,WAAW,6BAA6B;AAAA,MAC1E;AACA,UAAI,MAAM,2BAA2B,GAAG,EAAE;AAC1C,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAc,qBACZ,OACA,YACA,YACA,QAC4B;AAC5B,QAAI,KAAK,cAAc,MAAO,QAAO,CAAC;AACtC,UAAM,cAAc,KAAK,IAAI;AAC7B,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAM;AAAA,QACvB,CAAC,WAAW,OAAO,MAAM,YAAY,UAAU,MAAM,OAAO,UAAU,CAAC;AAAA,QACvE;AAAA,QACA,KAAK;AAAA,QACL;AAAA,MACF;AACA,UAAI,MAAM,gBAAgB,KAAK,IAAI,IAAI,WAAW,IAAI;AACtD,aAAO,qBAAqB,MAAM;AAAA,IACpC,SAAS,KAAK;AACZ,UAAI,qBAAqB,KAAK,MAAM,GAAG;AACrC,cAAM,aAAa,GAAG,IAAI,MAAM,WAAW,gCAAgC;AAAA,MAC7E;AACA,UAAI,MAAM,uBAAuB,GAAG,EAAE;AACtC,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAc,0BACZ,OACA,YACA,QAC4B;AAC5B,QAAI,KAAK,cAAc,MAAO,QAAO,CAAC;AAEtC,UAAM,cAAc,KAAK,IAAI;AAC7B,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAM;AAAA,QACvB,CAAC,SAAS,OAAO,UAAU,MAAM,OAAO,UAAU,CAAC;AAAA,QACnD;AAAA,QACA,KAAK;AAAA,QACL;AAAA,MACF;AACA,YAAM,aAAa,KAAK,IAAI,IAAI;AAChC,UAAI,KAAK,SAAS,WAAW,cAAc,KAAK,QAAQ,aAAa;AACnE,YAAI;AAAA,UACF,qCAAqC,UAAU,eAAe,UAAU,eAAe,MAAM,MAAM;AAAA,QACrG;AAAA,MACF;AAEA,aAAO,qBAAqB,MAAM;AAAA,IACpC,SAAS,KAAK;AACZ,UAAI,qBAAqB,KAAK,MAAM,GAAG;AACrC,cAAM,aAAa,GAAG,IAAI,MAAM,WAAW,sCAAsC;AAAA,MACnF;AACA,UAAI,MAAM,6BAA6B,GAAG,EAAE;AAC5C,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,QAAqC;AAChD,UAAM,KAAK,uBAAuB,KAAK,YAAY,EAAE,uBAAuB,MAAM,GAAG,MAAM;AAAA,EAC7F;AAAA,EAEA,MAAM,iBAAiB,YAAmC;AACxD,UAAM,KAAK,uBAAuB,YAAY,EAAE,uBAAuB,KAAK,CAAC;AAAA,EAC/E;AAAA,EAEA,MAAc,uBACZ,YACA,SACA,QACe;AACf,QAAI,KAAK,cAAc,MAAO;AAC9B,UAAM,OAAO,WAAW,KAAK;AAC7B,QAAI,CAAC,KAAM;AACX,UAAM,cAAc,kBAAkB;AACtC,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,QAAQ,uBAAuB;AACjC,UACE,YAAY,4BACZ,MAAM,YAAY,2BAA2B,uBAC7C;AACA,YAAI,MAAM,kDAAkD;AAC5D;AAAA,MACF;AACA,YAAM,oBAAoB,YAAY,yBAAyB,IAAI;AACnE,UACE,OAAO,SAAS,iBAAiB,KACjC,MAAM,oBAAoB,KAAK,qBAC/B;AACA,YAAI,MAAM,+DAA+D,IAAI,GAAG;AAChF;AAAA,MACF;AACA,YAAM,qBAAqB,YAAY,6BAA6B,IAAI;AACxE,UACE,OAAO,SAAS,kBAAkB,KAClC,MAAM,qBAAqB,uBAC3B;AACA,YAAI,MAAM,6DAA6D,IAAI,GAAG;AAC9E;AAAA,MACF;AAAA,IACF,OAAO;AACL,UACE,KAAK,qBACL,MAAM,KAAK,oBAAoB,KAAK,qBACpC;AACA,YAAI,MAAM,iDAAiD;AAC3D;AAAA,MACF;AACA,UACE,KAAK,uBACL,MAAM,KAAK,sBAAsB,uBACjC;AACA,YAAI,MAAM,yDAAyD;AACnE;AAAA,MACF;AACA,UACE,YAAY,2BACZ,MAAM,YAAY,0BAA0B,KAAK,qBACjD;AACA,YAAI,MAAM,oDAAoD;AAC9D;AAAA,MACF;AACA,UACE,YAAY,4BACZ,MAAM,YAAY,2BAA2B,uBAC7C;AACA,YAAI,MAAM,kDAAkD;AAC5D;AAAA,MACF;AAAA,IACF;AACA,QAAI;AACF,UAAI,CAAC,YAAY,4BAA4B;AAC3C,oBAAY,6BAA6B;AACzC,YAAI;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,YAAM,cAAc,KAAK,IAAI;AAC7B,YAAM,KAAK,cAAc,CAAC,UAAU,MAAM,IAAI,GAAG,KAAK,iBAAiB,MAAM;AAC7E,YAAM,aAAa,KAAK,IAAI,IAAI;AAChC,UAAI,KAAK,SAAS,WAAW,cAAc,KAAK,QAAQ,aAAa;AACnE,YAAI,KAAK,+BAA+B,UAAU,EAAE;AAAA,MACtD;AACA,YAAM,KAAK,KAAK,IAAI;AACpB,UAAI,QAAQ,uBAAuB;AACjC,oBAAY,yBAAyB,IAAI,IAAI;AAC7C,oBAAY,0BAA0B;AAAA,MACxC,OAAO;AACL,aAAK,oBAAoB;AACzB,oBAAY,0BAA0B;AAAA,MACxC;AACA,UAAI,MAAM,uCAAuC,IAAI,EAAE;AAAA,IACzD,SAAS,KAAK;AACZ,YAAM,KAAK,KAAK,IAAI;AACpB,UAAI,QAAQ,uBAAuB;AACjC,oBAAY,6BAA6B,IAAI,IAAI;AACjD,oBAAY,2BAA2B;AAAA,MACzC,OAAO;AACL,aAAK,sBAAsB;AAC3B,oBAAY,2BAA2B;AAAA,MACzC;AACA,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAI,KAAK,oCAAoC,IAAI,KAAK,GAAG,EAAE;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,cAAc,MAAO;AAC9B,UAAM,cAAc,kBAAkB;AACtC,QACE,KAAK,qBACL,KAAK,IAAI,IAAI,KAAK,oBAAoB,sBACtC;AACA,UAAI,MAAM,wDAAwD;AAClE;AAAA,IACF;AACA,QACE,YAAY,0BACZ,KAAK,IAAI,IAAI,YAAY,yBAAyB,KAAK,qBACvD;AACA,UAAI,MAAM,mDAAmD;AAC7D;AAAA,IACF;AACA,QACE,YAAY,2BACZ,KAAK,IAAI,IAAI,YAAY,0BAA0B,sBACnD;AACA,UAAI,MAAM,iDAAiD;AAC3D;AAAA,IACF;AACA,QAAI;AACF,YAAM,cAAc,KAAK,IAAI;AAC7B,YAAM,KAAK,cAAc,CAAC,SAAS,MAAM,KAAK,UAAU,GAAG,GAAO;AAClE,YAAM,aAAa,KAAK,IAAI,IAAI;AAChC,UAAI,KAAK,SAAS,WAAW,cAAc,KAAK,QAAQ,aAAa;AACnE,YAAI,KAAK,8BAA8B,UAAU,EAAE;AAAA,MACrD;AACA,kBAAY,yBAAyB,KAAK,IAAI;AAC9C,UAAI,MAAM,qBAAqB;AAAA,IACjC,SAAS,KAAK;AACZ,UAAI,+BAA+B,GAAG,GAAG;AACvC,YAAI;AACF,cAAI,KAAK,yEAAyE;AAClF,gBAAM,KAAK,cAAc,CAAC,SAAS,MAAM,MAAM,KAAK,UAAU,GAAG,GAAO;AACxE,sBAAY,yBAAyB,KAAK,IAAI;AAC9C,eAAK,oBAAoB;AACzB,sBAAY,0BAA0B;AACtC,cAAI,KAAK,sDAAsD;AAC/D;AAAA,QACF,SAAS,UAAU;AACjB,gBAAM,WAAW,oBAAoB,QAAQ,SAAS,UAAU,OAAO,QAAQ;AAC/E,cAAI,KAAK,uDAAuD,QAAQ,EAAE;AAAA,QAC5E;AAAA,MACF;AACA,YAAM,MAAM,KAAK,IAAI;AACrB,WAAK,oBAAoB;AACzB,kBAAY,0BAA0B;AACtC,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAI,KAAK,qBAAqB,GAAG,EAAE;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,YAAmC;AACvD,QAAI,KAAK,cAAc,MAAO;AAC9B,UAAM,OAAO,WAAW,KAAK;AAC7B,QAAI,CAAC,KAAM;AACX,UAAM,cAAc,kBAAkB;AACtC,UAAM,MAAM,KAAK,IAAI;AACrB,QACE,YAAY,2BACZ,MAAM,YAAY,0BAA0B,sBAC5C;AACA,UAAI,MAAM,oDAAoD,IAAI,GAAG;AACrE;AAAA,IACF;AACA,UAAM,oBAAoB,YAAY,wBAAwB,IAAI;AAClE,QACE,OAAO,SAAS,iBAAiB,KACjC,MAAM,oBAAoB,KAAK,qBAC/B;AACA,UAAI,MAAM,8DAA8D,IAAI,GAAG;AAC/E;AAAA,IACF;AACA,UAAM,qBAAqB,YAAY,4BAA4B,IAAI;AACvE,QACE,OAAO,SAAS,kBAAkB,KAClC,MAAM,qBAAqB,sBAC3B;AACA,UAAI,MAAM,4DAA4D,IAAI,GAAG;AAC7E;AAAA,IACF;AACA,QAAI;AACF,YAAM,KAAK,cAAc,CAAC,SAAS,MAAM,IAAI,GAAG,GAAO;AACvD,YAAM,KAAK,KAAK,IAAI;AACpB,kBAAY,wBAAwB,IAAI,IAAI;AAC5C,kBAAY,yBAAyB;AAAA,IACvC,SAAS,KAAK;AACZ,UAAI,+BAA+B,GAAG,GAAG;AACvC,YAAI;AACF,cAAI,KAAK,4BAA4B,IAAI,gEAAgE;AACzG,gBAAM,KAAK,cAAc,CAAC,SAAS,MAAM,MAAM,IAAI,GAAG,GAAO;AAC7D,gBAAM,cAAc,KAAK,IAAI;AAC7B,sBAAY,wBAAwB,IAAI,IAAI;AAC5C,sBAAY,yBAAyB;AACrC,iBAAO,YAAY,4BAA4B,IAAI;AACnD,sBAAY,0BAA0B;AACtC,cAAI,KAAK,4BAA4B,IAAI,6CAA6C;AACtF;AAAA,QACF,SAAS,UAAU;AACjB,gBAAM,WAAW,oBAAoB,QAAQ,SAAS,UAAU,OAAO,QAAQ;AAC/E,cAAI,KAAK,4CAA4C,IAAI,KAAK,QAAQ,EAAE;AAAA,QAC1E;AAAA,MACF;AACA,YAAM,KAAK,KAAK,IAAI;AACpB,kBAAY,4BAA4B,IAAI,IAAI;AAChD,kBAAY,0BAA0B;AACtC,YAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAI,KAAK,mCAAmC,IAAI,KAAK,GAAG,EAAE;AAAA,IAC5D;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,WAA2E;AAChG,QAAI,KAAK,cAAc,SAAS,CAAC,KAAK,gBAAiB,QAAO;AAE9D,QAAI,KAAK,cAAc,MAAO,QAAO;AACrC,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAM;AAAA,QACvB,CAAC,cAAc,MAAM;AAAA,QACrB;AAAA,QACA,KAAK;AAAA,MACP;AAEA,YAAM,kBAAkB,IAAI;AAAA,QAC1B,IAAI,KAAK,UAAU;AAAA,QACnB;AAAA,MACF;AACA,UAAI,gBAAgB,KAAK,MAAM,GAAG;AAChC,eAAO;AAAA,MACT;AAAA,IACF,SAAS,KAAK;AAGZ,UAAI;AAAA,QACF,yCAAyC,KAAK,UAAU,kCAAkC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC5I;AACA,aAAO;AAAA,IACT;AAEA,QAAI;AAAA,MACF,mBAAmB,KAAK,UAAU,8DACiB,SAAS;AAAA,IAC9D;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
|