@artenx/dshb 0.1.22 → 0.1.23
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/lib/core/index.js +2 -2
- package/lib/core/index.js.map +1 -1
- package/lib/core/sync/coordinator.d.ts +2 -2
- package/lib/core/sync/coordinator.js +121 -15
- package/lib/core/sync/coordinator.js.map +1 -1
- package/lib/core/sync/internal-routes.d.ts +1 -1
- package/lib/core/sync/internal-routes.js +58 -9
- package/lib/core/sync/internal-routes.js.map +1 -1
- package/lib/core/sync/offline-archive.d.ts +1 -1
- package/lib/core/sync/offline-archive.js +1 -1
- package/lib/core/sync/offline-routes.js +1 -1
- package/lib/core/sync/protocol.d.ts +2 -2
- package/lib/core/sync/protocol.js +4 -1
- package/lib/core/sync/protocol.js.map +1 -1
- package/lib/core/sync/remote-helper.js +10 -4
- package/lib/core/sync/remote-helper.js.map +1 -1
- package/lib/core/sync/routes.d.ts +1 -1
- package/lib/core/sync/session-routes.d.ts +1 -1
- package/lib/core/sync/session-routes.js +1 -1
- package/lib/core/sync/session-sync.d.ts +2 -2
- package/lib/core/sync/session-sync.js +2 -2
- package/lib/core/sync/ssh-transport.d.ts +2 -2
- package/lib/core/sync/ssh-transport.js +97 -104
- package/lib/core/sync/ssh-transport.js.map +1 -1
- package/lib/{protocol-CV7LGE44.d.ts → protocol-KaWZArY8.d.ts} +5 -2
- package/lib/{session-sync-EdfwUON5.js → session-sync-C0uoizyB.js} +834 -98
- package/lib/session-sync-C0uoizyB.js.map +1 -0
- package/lib/{session-sync-g6qKZzjV.d.ts → session-sync-C2j2rk9K.d.ts} +56 -4
- package/lib/{ssh-transport-BcIiLxsX.d.ts → ssh-transport-DGkQh-HA.d.ts} +14 -5
- package/package.json +1 -1
- package/lib/session-sync-EdfwUON5.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-sync-C0uoizyB.js","names":["isRecord","fsConstants","makeSessionId","isRecord","normalizeHostPath"],"sources":["../../../node_modules/@deepseek-ai/dsh-session/lib/index.js","../../../node_modules/@deepseek-ai/dsh-session-persistence/lib/index.js","../src/core/sync/export-cache.ts","../src/core/sync/session-sync.ts"],"sourcesContent":["import { Service } from \"@deepseek-ai/cordis\";\nimport { isAbsolute } from \"node:path\";\nimport { brandNumber, brandString } from \"@deepseek-ai/dsh-brand\";\nimport { assertNever, deepFreeze, snapshotJsonValue } from \"@deepseek-ai/dsh-util-values\";\nimport { scopeOf, scopeTarget } from \"@deepseek-ai/dsh-scope\";\nimport { callConfigEquals } from \"@deepseek-ai/dsh-llm\";\n//#region lib/types/types.js\n/**\n* Brand a string as a {@link SessionId}.\n* @param id - the raw session id string.\n* @returns the same string with the session-id brand.\n*/\nfunction SessionId(id) {\n\treturn brandString(id);\n}\n/**\n* Admit a numeric value as an existing Session event position.\n* @param value - non-negative safe integer admitted by the owning log operation.\n* @returns the same number with the Session-sequence brand.\n*/\nfunction SessionSeq(value) {\n\tif (!Number.isSafeInteger(value) || value < 0 || Object.is(value, -0)) throw new TypeError(`SessionSeq must be a non-negative safe integer, got ${String(value)}`);\n\treturn brandNumber(value);\n}\n/**\n* Admit a numeric value as a Session log offset.\n* @param value - non-negative safe integer used as a gap or prefix length.\n* @returns the same number with the Session-log-offset brand.\n*/\nfunction SessionLogOffset(value) {\n\tif (!Number.isSafeInteger(value) || value < 0 || Object.is(value, -0)) throw new TypeError(`SessionLogOffset must be a non-negative safe integer, got ${String(value)}`);\n\treturn brandNumber(value);\n}\n/**\n* Current logical Session format version, stamped into every newly written\n* {@link SessionHeader}. Current Session and persistence code accept only this\n* value; header-only readers classify supported historical formats, while an\n* event-body read composes the build-static adjacent chain and publishes only\n* this final generation before constructing a Session.\n*\n* The version is a single monotonic integer with no major/minor split. Retain\n* it when older readers resume correctly, preserve safely ignorable records,\n* or refuse required features before execution, mutation, or tail repair.\n* New readers must preserve historical meanings, including logs mixing old\n* and new record representations. Bump when an existing discriminator cannot\n* prevent unsafe interpretation; a structural difference alone is insufficient.\n* Unknown fields and values require evidence of the released reader's actual\n* admission behavior. The per-event {@link SessionEvent.ignorable} marker\n* governs unknown event types, not arbitrary nested payload changes.\n* Same-version readers retain earlier representations: the adjacent migration\n* chain does not run when stored and current versions match. A subsequent\n* migration must account for all supported representations of its source.\n* Compatibility review and the retained migration obligations are recorded in\n* `.agents/notes/implemented/process/2026-10-08-session-reader-compatibility-review.md`.\n*/\nconst SESSION_FORMAT_VERSION = 4;\n//#endregion\n//#region lib/types/known-event-types.js\n/**\n* GENERATED by `scripts/gen-persistence-catalog.ts` — do not edit by hand; run\n* `pnpm run gen-persistence-catalog` to regenerate (verified fresh by\n* `pnpm run verify-persistence-catalog`, part of `doc-sync`).\n* @module @deepseek-ai/dsh-session/known-event-types\n*/\n/**\n* Every `SessionEventMap` member declared in this repository — the event\n* vocabulary this build understands. The persistence read path refuses to\n* interpret a log containing a type outside this set unless the event\n* carries the envelope's `ignorable` marker (see `SessionEvent.ignorable`\n* in `./types.ts`): such a log was likely written by a newer harness, and\n* silently skipping a required event would reconstruct a wrong session.\n* Downstream (out-of-repo) plugin events are outside this list by\n* construction. The persisted `SessionEvent.ignorable` marker is the\n* compatibility mechanism; event-name registration was rejected because\n* it does not classify omission safety and would make reads\n* composition-dependent. The rationale is in\n* `.agents/notes/implemented/architecture/2026-08-30-retain-ignorable-external-session-events.md`.\n*/\nconst KNOWN_SESSION_EVENT_TYPES = new Set([\n\t\"agent-preset/selected\",\n\t\"agent/inbox/spliced\",\n\t\"approval/asked\",\n\t\"approval/decided\",\n\t\"approval/policy\",\n\t\"assistant/attempt\",\n\t\"assistant/message\",\n\t\"command/done\",\n\t\"command/run\",\n\t\"compaction/end\",\n\t\"compaction/prune\",\n\t\"compaction/start\",\n\t\"compaction/summary\",\n\t\"deliverables/presented\",\n\t\"developer/message\",\n\t\"feedback/message-delete\",\n\t\"feedback/message-put\",\n\t\"feedback/record\",\n\t\"goal/change\",\n\t\"hook/invoked\",\n\t\"hook/result\",\n\t\"image/offload\",\n\t\"job/registered\",\n\t\"job/settled\",\n\t\"llm/retry\",\n\t\"llm/retry-started\",\n\t\"model/selection\",\n\t\"permission/preset\",\n\t\"plan/mode\",\n\t\"request/context\",\n\t\"request/header\",\n\t\"sandbox/mode\",\n\t\"schedule/change\",\n\t\"session-log-deepseek/delivery-accepted\",\n\t\"session/end-seed\",\n\t\"session/title\",\n\t\"session/title-llm-request\",\n\t\"step/end\",\n\t\"step/start\",\n\t\"subagent/catalog\",\n\t\"subagent/descriptor\",\n\t\"subagent/model-selection-policy\",\n\t\"system/message\",\n\t\"team/member\",\n\t\"team/message/delivered\",\n\t\"team/message/queued\",\n\t\"team/task\",\n\t\"todo/write\",\n\t\"tool-workflow/agent-end\",\n\t\"tool-workflow/agent-start\",\n\t\"tool-workflow/run-end\",\n\t\"tool-workflow/run-start\",\n\t\"tool/call\",\n\t\"tool/ptc-dispatch\",\n\t\"tool/ptc-dispatch-start\",\n\t\"tool/result\",\n\t\"turn/end\",\n\t\"turn/start\",\n\t\"user/message\",\n\t\"web/deepseek-search-llm-request\",\n\t\"working-directory/change\",\n\t\"workspace/changes\"\n]);\n/** Event types whose model-visible effects require an explicit pure interpreter. */\nconst MESSAGE_PROJECTION_EVENT_TYPES = new Set([\"image/offload\"]);\n//#endregion\n//#region lib/types/surface.js\n/**\n* Surface layer on top of the session event log: an ordered view of events\n* that produce LLM messages. The append-only log remains the source of truth.\n*\n* Browser-safe: web clients consume this subpath export, so it must stay free\n* of `node:` imports (they break the vite bundle).\n*\n* @module @deepseek-ai/dsh-session/surface\n*/\n/** Runtime counterpart of the message-producing event union. */\nconst SURFACE_EVENT_TYPES = new Set([\n\t\"system/message\",\n\t\"developer/message\",\n\t\"user/message\",\n\t\"assistant/message\",\n\t\"tool/result\"\n]);\n/**\n* Whether an event type can join the model-visible surface.\n* @param type - event type to test.\n* @returns true for one of the message-producing event types.\n*/\nfunction isSurfaceEligibleType(type) {\n\treturn SURFACE_EVENT_TYPES.has(type);\n}\n/**\n* Narrow an event to a surface-eligible event carrying its required marker.\n* @param event - event to test.\n* @returns true when both the type and marker identify a surface event.\n*/\nfunction isSurfaceEvent(event) {\n\tif (!SURFACE_EVENT_TYPES.has(event.type)) return false;\n\treturn event.surfaceOp !== void 0;\n}\n/**\n* Narrow an event to an append-origin surface event: one that entered the\n* surface at its own log position and was never itself a replacement copy.\n*\n* The model-visible surface deliberately shadows replaced ranges, so it is the\n* wrong source for a human transcript — a landed replacement would erase\n* conversation the user already saw. Append-origin events are that transcript's\n* durable source material; replacement copies stay model-only.\n* @param event - event to test.\n* @returns true when the event appended to the surface tail.\n*/\nfunction isAppendSurfaceEvent(event) {\n\treturn isSurfaceEvent(event) && event.surfaceOp === \"append\";\n}\n/**\n* Narrow an event to a surface replacement: a node that shadowed an existing\n* surface range instead of appending to the tail. The counterpart of\n* {@link isAppendSurfaceEvent} over the two {@link SurfaceOp} variants.\n* @param event - event to test.\n* @returns true when the event replaced a surface range.\n*/\nfunction isReplacementSurfaceEvent(event) {\n\treturn isSurfaceEvent(event) && event.surfaceOp !== \"append\";\n}\n/**\n* Project a single event into the LLM message it derives to, or null when it\n* produces none — a non-surface event (attempt, boundary, log-only record) or an\n* empty-content system, developer, or assistant message. A caller\n* reconstructing model input supplies the same prefix's `projectedMessages`\n* from {@link foldSurface}; without that map this function reads original\n* event content. Session instance methods apply the live projection. Messages\n* are immutable and unchanged content retains its durable identity.\n* @param event - the event to project.\n* @param projectedMessages - message projections from the same log prefix's surface fold.\n* @returns the derived message, or null when the event produces none.\n*/\nfunction deriveEventMessage(event, projectedMessages) {\n\tconst projected = projectedMessages?.get(event.seq);\n\tif (projected !== void 0) return projected;\n\tswitch (event.type) {\n\t\tcase \"user/message\": return event.data;\n\t\tcase \"system/message\":\n\t\tcase \"developer/message\":\n\t\tcase \"assistant/message\":\n\t\t\tif (event.data.message.content.length === 0) return null;\n\t\t\treturn event.data.message;\n\t\tcase \"tool/result\": return event.data.message;\n\t\tdefault: return null;\n\t}\n}\n/** Whether a payload field is a JSON object rather than an array or scalar. */\nfunction isRecord(value) {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n/**\n* Reject noncanonical request-header fields, developer roles/content, and contradictory tool failure metadata.\n* This does not validate complete event payloads or embedded provider streams.\n* @param event - event whose locally related payload fields are inspected.\n* @param subject - event location to include in validation errors.\n* @throws when request-header fields, developer roles/content, or tool failure metadata are invalid.\n*/\nfunction validateSessionEventData(event, subject) {\n\tconst data = event.data;\n\tif (SURFACE_EVENT_TYPES.has(event.type) && isRecord(data)) {\n\t\tconst message = event.type === \"user/message\" ? data : data[\"message\"];\n\t\tif (isRecord(message)) {\n\t\t\tif (event.type === \"developer/message\" !== (message[\"role\"] === \"developer\")) throw new Error(`${subject} developer/message and developer role must occur together`);\n\t\t\tif (message[\"role\"] !== \"developer\" && Array.isArray(message[\"content\"]) && message[\"content\"].some((block) => isRecord(block) && (block[\"type\"] === \"tool-addition\" || block[\"type\"] === \"tool-removal\"))) throw new Error(`${subject} tool-change blocks require developer role`);\n\t\t\tif (event.type === \"developer/message\" && Array.isArray(message[\"content\"])) {\n\t\t\t\tlet hasAdditions = false;\n\t\t\t\tfor (const block of message[\"content\"]) {\n\t\t\t\t\tif (!isRecord(block) || block[\"type\"] !== \"tool-addition\" && block[\"type\"] !== \"tool-removal\") continue;\n\t\t\t\t\tif (typeof block[\"toolName\"] !== \"string\" || block[\"toolName\"].length === 0) throw new Error(`${subject} ${block[\"type\"]} requires a nonempty toolName`);\n\t\t\t\t\tif (block[\"type\"] === \"tool-addition\") {\n\t\t\t\t\t\thasAdditions = true;\n\t\t\t\t\t\tif (Object.hasOwn(block, \"tool\")) throw new Error(`${subject} tool-addition must omit inline tool definitions`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (hasAdditions ? !isEventSeq(data[\"headerSeq\"]) : Object.hasOwn(data, \"headerSeq\")) throw new Error(`${subject} requires headerSeq exactly when tool additions are present`);\n\t\t\t}\n\t\t}\n\t}\n\tif (event.type === \"request/header\") {\n\t\tif (!isRecord(data)) throw new Error(`${subject} data must be an object`);\n\t\tconst header = data[\"header\"];\n\t\tif (!isRecord(header)) throw new Error(`${subject} header must be an object`);\n\t\tif (Object.hasOwn(header, \"system\")) throw new Error(`${subject} must omit header.system; use system/message`);\n\t\tif (Array.isArray(header[\"tools\"]) && header[\"tools\"].length === 0) throw new Error(`${subject} must omit empty tools`);\n\t\tconst defaults = header[\"adapterDefaults\"];\n\t\tif (isRecord(defaults) && Object.keys(defaults).length === 0) throw new Error(`${subject} must omit empty adapterDefaults`);\n\t} else if (event.type === \"tool/result\") {\n\t\tif (!isRecord(data)) throw new Error(`${subject} data must be an object`);\n\t\tif (data[\"error\"] === void 0) return;\n\t\tconst message = data[\"message\"];\n\t\tif (!isRecord(message) || message[\"isError\"] !== true) throw new Error(`${subject} error requires message.isError === true`);\n\t}\n}\n/** Create an empty surface fold state. */\nfunction createFoldState() {\n\treturn {\n\t\tnodes: [],\n\t\treplaceGeneration: 0,\n\t\tcontentGeneration: 0,\n\t\tprojectedMessages: /* @__PURE__ */ new Map(),\n\t\tprojections: /* @__PURE__ */ new Set()\n\t};\n}\n/** Whether a runtime value is a non-negative safe event sequence. */\nfunction isEventSeq(value) {\n\treturn typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0 && !Object.is(value, -0);\n}\n/** Whether a runtime value is the exact positional-replacement shape. */\nfunction isReplaceOp(value) {\n\tconst op = value;\n\treturn Object.keys(op).length === 3 && Object.hasOwn(op, \"op\") && Object.hasOwn(op, \"startSeq\") && Object.hasOwn(op, \"endSeq\") && op[\"op\"] === \"replace\" && isEventSeq(op[\"startSeq\"]) && isEventSeq(op[\"endSeq\"]);\n}\n/** Validate event-local surface eligibility and return its operation. */\nfunction surfaceOpOf(event) {\n\tconst raw = event;\n\tif (!isSurfaceEligibleType(event.type)) {\n\t\tif (!KNOWN_SESSION_EVENT_TYPES.has(event.type) && event.ignorable === true) return;\n\t\tif (raw.surfaceOp !== void 0) throw new Error(`session event \"${event.type}\" is not surface-eligible and cannot carry surfaceOp`);\n\t\tif (raw.sourceEventSeqs !== void 0) throw new Error(`session event \"${event.type}\" is not surface-eligible and cannot carry sourceEventSeqs`);\n\t\treturn;\n\t}\n\tconst op = raw.surfaceOp;\n\tif (op === void 0) throw new Error(`session event \"${event.type}\" is surface-eligible and requires a surfaceOp marker`);\n\tif (op === \"append\") return op;\n\tif (op === null || typeof op !== \"object\" || Array.isArray(op)) throw new Error(`session event \"${event.type}\" carries an invalid surfaceOp`);\n\tif (!isReplaceOp(op)) throw new Error(`session event \"${event.type}\" carries an invalid replace surfaceOp`);\n\treturn op;\n}\n/** Validate cited source-event seqs against prior log entries and the replacement range. */\nfunction assertSourceEventReferences(event, shadowedSeqs) {\n\tconst raw = event.sourceEventSeqs;\n\tif (event.type === \"assistant/message\" && raw !== void 0) throw new Error(\"assistant/message embeds its source stream and cannot carry sourceEventSeqs\");\n\tconst sources = /* @__PURE__ */ new Set();\n\tif (raw !== void 0) {\n\t\tif (!Array.isArray(raw)) throw new Error(`sourceEventSeqs on event at seq ${event.seq} must be an array when present`);\n\t\tif (raw.length === 0) throw new Error(\"sourceEventSeqs must not be empty\");\n\t\tlet nonEarlierSource;\n\t\tfor (const source of raw) {\n\t\t\tif (!isEventSeq(source)) throw new Error(`session event \"${event.type}\" sourceEventSeqs must densely contain non-negative safe integers`);\n\t\t\tsources.add(source);\n\t\t\tif (nonEarlierSource === void 0 && source >= event.seq) nonEarlierSource = source;\n\t\t}\n\t\tif (sources.size !== raw.length) throw new Error(\"sourceEventSeqs must not contain duplicates\");\n\t\tif (nonEarlierSource !== void 0) throw new Error(`sourceEventSeqs must reference earlier events: ${nonEarlierSource} >= current seq ${event.seq}`);\n\t}\n\tconst missing = shadowedSeqs.filter((seq) => !sources.has(seq));\n\tif (missing.length > 0) throw new Error(`surface replace: sourceEventSeqs must include every shadowed surface node; missing ${missing.join(\", \")}`);\n}\n/** Resolve tool additions against their immutable historical request header. */\nfunction assertDeveloperHeader(event, events, baseSeq) {\n\tif (event.type !== \"developer/message\") return;\n\tvalidateSessionEventData(event, `developer/message at seq ${event.seq}`);\n\tif (event.data.headerSeq === void 0) return;\n\tconst headerSeq = event.data.headerSeq;\n\tconst headerEvent = events[headerSeq - baseSeq];\n\tif (headerSeq >= event.seq || headerEvent?.type !== \"request/header\") throw new Error(\"developer/message headerSeq must reference an earlier request/header\");\n\tfor (const block of event.data.message.content) {\n\t\tif (block.type !== \"tool-addition\") continue;\n\t\tconst definitions = headerEvent.data.header.tools?.filter((tool) => tool.name === block.toolName) ?? [];\n\t\tif (definitions.length !== 1) throw new Error(`developer/message tool-addition \"${block.toolName}\" must name exactly one tool in headerSeq ${headerSeq}`);\n\t\tconst definition = definitions[0];\n\t\tif (typeof definition.description !== \"string\" || !isRecord(definition.parameters)) throw new Error(`developer/message tool-addition \"${block.toolName}\" requires a complete tool definition in headerSeq ${headerSeq}`);\n\t\tif (Object.hasOwn(definition, \"deferLoading\") && definition.deferLoading !== true) throw new Error(\"developer/message referenced tool deferLoading must be true when present\");\n\t}\n}\n/**\n* Validate one event's surface metadata without checking membership in a log or surface.\n* @param event - event whose marker and source sequence values are inspected.\n* Unknown ignorable records retain opaque metadata and never change the surface.\n* @returns the validated operation, or undefined for a log-only or unknown ignorable event.\n* @throws when metadata violates event-local eligibility, marker, or source-sequence rules.\n*/\nfunction validateSurfaceMetadata(event) {\n\tconst op = surfaceOpOf(event);\n\tif (op !== void 0 && op !== \"append\" && (op.startSeq >= event.seq || op.endSeq >= event.seq)) throw new Error(`surface replace at seq ${event.seq}: startSeq and endSeq must reference earlier events`);\n\tif (op !== void 0) assertSourceEventReferences(event, []);\n\treturn op;\n}\n/** Locate one replacement range without mutating the current fold state. */\nfunction replacementRange(state, op) {\n\tconst startIdx = state.nodes.indexOf(op.startSeq);\n\tif (startIdx === -1) throw new Error(`surface replace: start seq ${op.startSeq} not found in surface`);\n\tconst endIdx = state.nodes.indexOf(op.endSeq);\n\tif (endIdx === -1) throw new Error(`surface replace: end seq ${op.endSeq} not found in surface`);\n\tif (startIdx > endIdx) throw new Error(`surface replace: start seq ${op.startSeq} (index ${startIdx}) is after end seq ${op.endSeq} (index ${endIdx})`);\n\treturn {\n\t\tstartIdx,\n\t\tendIdx,\n\t\tshadowedSeqs: state.nodes.slice(startIdx, endIdx + 1)\n\t};\n}\n/**\n* Deep structural equality over the session-event JSON value domain\n* (null/boolean/number/string, arrays, plain objects). Replaces\n* `node:util`'s isDeepStrictEqual to keep this module browser-safe.\n*/\nfunction isDeepEqualJson(a, b) {\n\tif (a === b) return true;\n\tif (Array.isArray(a) || Array.isArray(b)) {\n\t\tif (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;\n\t\treturn a.every((item, i) => isDeepEqualJson(item, b[i]));\n\t}\n\tif (typeof a !== \"object\" || typeof b !== \"object\" || a === null || b === null) return false;\n\tconst aKeys = Object.keys(a);\n\tconst bRecord = b;\n\tif (aKeys.length !== Object.keys(b).length) return false;\n\treturn aKeys.every((key) => Object.hasOwn(b, key) && isDeepEqualJson(a[key], bRecord[key]));\n}\n/** Restrict a tool-result replacement to one current result's content. */\nfunction assertToolResultRewrite(event, shadowedSeqs, events, baseSeq) {\n\tif (event.type !== \"tool/result\") return;\n\tif (shadowedSeqs.length !== 1) throw new Error(\"tool/result surface replacement must rewrite exactly one current node\");\n\tfor (const originalSeq of shadowedSeqs) {\n\t\tconst original = events[originalSeq - baseSeq];\n\t\tif (original?.type !== \"tool/result\") throw new Error(\"tool/result surface replacement must target a current tool/result\");\n\t\tconst originalRest = { ...original.data };\n\t\tconst replacementRest = { ...event.data };\n\t\toriginalRest[\"message\"] = {\n\t\t\t...original.data.message,\n\t\t\tcontent: null\n\t\t};\n\t\treplacementRest[\"message\"] = {\n\t\t\t...event.data.message,\n\t\t\tcontent: null\n\t\t};\n\t\tif (!isDeepEqualJson(originalRest, replacementRest)) throw new Error(\"tool/result surface replacement may change only content\");\n\t}\n}\n/**\n* Protect the system prompt at surface node 0. A replacement covering node 0\n* while that node is a `system/message` must itself be a `system/message` over\n* exactly that node; later system nodes carry no protection and a compaction\n* range may shadow them.\n*/\nfunction assertSystemHeadRewrite(event, state, startIdx, shadowedSeqs, events, baseSeq) {\n\tif (startIdx !== 0) return;\n\tif (events[state.nodes[0] - baseSeq]?.type !== \"system/message\") return;\n\tif (event.type !== \"system/message\" || shadowedSeqs.length !== 1) throw new Error(\"surface replace: node 0 holds the system prompt and may be rewritten only by a system/message over exactly that node\");\n}\n/** Validate one event at its replay boundary and prepare its atomic fold transition. */\nfunction planSurfaceEvent(state, event, expectedSeq, events, baseSeq, projections) {\n\tif (event.seq !== expectedSeq) throw new Error(`session event seq ${event.seq} is not contiguous; expected ${expectedSeq}`);\n\tconst surfaceOp = validateSurfaceMetadata(event);\n\tassertDeveloperHeader(event, events, baseSeq);\n\tconst projection = projections.find((item) => item.type === event.type);\n\tif (projection !== void 0) return {\n\t\tkind: \"project\",\n\t\tprojection,\n\t\tmessages: projection.project(event, {\n\t\t\tnodes: state.nodes,\n\t\t\tevents,\n\t\t\tbaseSeq,\n\t\t\tmessages: state.projectedMessages\n\t\t})\n\t};\n\tif (MESSAGE_PROJECTION_EVENT_TYPES.has(event.type)) throw new Error(`session event \"${event.type}\" requires a message projection; load its owning plugin or supply its projection definition`);\n\tif (surfaceOp === void 0) return;\n\tif (surfaceOp === \"append\") return {\n\t\tkind: \"append\",\n\t\tseq: event.seq\n\t};\n\tconst range = replacementRange(state, surfaceOp);\n\tassertSourceEventReferences(event, range.shadowedSeqs);\n\tassertToolResultRewrite(event, range.shadowedSeqs, events, baseSeq);\n\tassertSystemHeadRewrite(event, state, range.startIdx, range.shadowedSeqs, events, baseSeq);\n\treturn {\n\t\tkind: \"replace\",\n\t\tseq: event.seq,\n\t\tstart: surfaceOp.startSeq,\n\t\tend: surfaceOp.endSeq,\n\t\t...range\n\t};\n}\n/** Apply one event and return replacement metadata only when one occurred. */\nfunction applySurfaceEvent(state, event, expectedSeq, events, baseSeq, projections) {\n\treturn applySurfacePlan(state, planSurfaceEvent(state, event, expectedSeq, events, baseSeq, projections));\n}\n/** Commit one previously validated surface transition. */\nfunction applySurfacePlan(state, plan) {\n\tif (plan?.kind === \"append\") state.nodes.push(plan.seq);\n\telse if (plan?.kind === \"replace\") {\n\t\tstate.nodes.splice(plan.startIdx, plan.endIdx - plan.startIdx + 1, plan.seq);\n\t\tstate.replaceGeneration += 1;\n\t\tstate.contentGeneration += 1;\n\t} else if (plan?.kind === \"project\") {\n\t\tfor (const [seq, message] of plan.messages) state.projectedMessages.set(seq, message);\n\t\tstate.projections.add(plan.projection);\n\t\tstate.contentGeneration += 1;\n\t}\n\tif (plan?.kind !== \"replace\") return;\n\treturn {\n\t\tseq: plan.seq,\n\t\tstart: plan.start,\n\t\tend: plan.end,\n\t\tshadowedSeqs: plan.shadowedSeqs\n\t};\n}\n/**\n* Replay a complete session log through the canonical surface fold.\n* @param events - session events in contiguous seq order.\n* @param projections - pure interpreters for plugin-owned message changes; required definitions must be supplied.\n* @returns detached current sequences and replacement history.\n* @throws when an interpreter is missing or an event violates its projection, surface metadata, source attribution, or replacement rules.\n*/\nfunction foldSurface(events, projections = []) {\n\tconst state = createFoldState();\n\tconst replacements = [];\n\tfor (const [index, event] of events.entries()) {\n\t\tconst replacement = applySurfaceEvent(state, event, SessionSeq(index), events, SessionLogOffset(0), projections);\n\t\tif (replacement !== void 0) replacements.push(replacement);\n\t}\n\treturn {\n\t\tnodes: [...state.nodes],\n\t\treplacements,\n\t\tprojectedMessages: new Map(state.projectedMessages)\n\t};\n}\n/** Incremental ordered surface view and append-boundary validator. */\nvar SurfaceManager = class {\n\tlog;\n\tbaseSeq;\n\tprojections;\n\t/** Shared transition state; replacement history is not retained. */\n\t_state = createFoldState();\n\t/** Last processed absolute seq. */\n\t_lastProcessedSeq;\n\t/** Candidate already validated by `validateNext`, pending exact log admission. */\n\t_pendingPlan;\n\t/**\n\t* @param log - Contiguous complete log or loaded event window.\n\t* @param baseSeq - Absolute sequence of the window's first event.\n\t* @param projections - live borrowed definitions; removing a used definition invalidates further reads.\n\t*/\n\tconstructor(log, baseSeq = SessionLogOffset(0), projections = []) {\n\t\tthis.log = log;\n\t\tthis.baseSeq = baseSeq;\n\t\tthis.projections = projections;\n\t\tthis._lastProcessedSeq = baseSeq === 0 ? -1 : SessionSeq(baseSeq - 1);\n\t}\n\t/**\n\t* Validate the next candidate without mutating the committed surface.\n\t* @param event - candidate event that has not entered the log yet.\n\t*/\n\tvalidateNext(event) {\n\t\tthis._assertProjections();\n\t\tif (this._lastProcessedSeq < this.baseSeq + this.log.length - 1) this._processDelta();\n\t\tconst expectedSeq = SessionSeq(this.baseSeq + this.log.length);\n\t\tthis._pendingPlan = {\n\t\t\tevent,\n\t\t\texpectedSeq,\n\t\t\tplan: planSurfaceEvent(this._state, event, expectedSeq, this.log, this.baseSeq, this.projections)\n\t\t};\n\t}\n\t/** Monotonic count of folded positional replacements. */\n\tget replaceGeneration() {\n\t\tthis._assertProjections();\n\t\tif (this._lastProcessedSeq < this.baseSeq + this.log.length - 1) this._processDelta();\n\t\treturn this._state.replaceGeneration;\n\t}\n\t/** Monotonic count of committed changes to existing model-visible content. */\n\tget contentGeneration() {\n\t\tthis._assertProjections();\n\t\tif (this._lastProcessedSeq < this.baseSeq + this.log.length - 1) this._processDelta();\n\t\treturn this._state.contentGeneration;\n\t}\n\t/**\n\t* Project one message with every committed message projection applied.\n\t* @param event - message-producing or log-only event.\n\t* @returns its immutable projected message, or null when it produces none.\n\t*/\n\tderiveEventMessage(event) {\n\t\tthis._assertProjections();\n\t\tif (this._lastProcessedSeq < this.baseSeq + this.log.length - 1) this._processDelta();\n\t\treturn deriveEventMessage(event, this._state.projectedMessages);\n\t}\n\t/** Surface event sequences in model-visible order. */\n\tget nodes() {\n\t\tthis._assertProjections();\n\t\tif (this._lastProcessedSeq < this.baseSeq + this.log.length - 1) this._processDelta();\n\t\treturn this._state.nodes;\n\t}\n\t/** Fold events appended since the previous access. */\n\t_processDelta() {\n\t\tconst tailSeq = this.baseSeq + this.log.length - 1;\n\t\tfor (let seq = this._lastProcessedSeq + 1; seq <= tailSeq; seq++) {\n\t\t\tconst index = seq - this.baseSeq;\n\t\t\tconst event = this.log[index];\n\t\t\tconst pending = this._pendingPlan;\n\t\t\tif (pending?.event === event && pending.expectedSeq === seq) applySurfacePlan(this._state, pending.plan);\n\t\t\telse applySurfaceEvent(this._state, event, SessionSeq(seq), this.log, this.baseSeq, this.projections);\n\t\t\tif (pending !== void 0 && pending.expectedSeq <= seq) this._pendingPlan = void 0;\n\t\t\tthis._lastProcessedSeq = SessionSeq(seq);\n\t\t}\n\t}\n\t/** Cached messages cannot outlive the definitions that interpreted their log. */\n\t_assertProjections() {\n\t\tconst candidate = this._pendingPlan;\n\t\tconst pending = candidate !== void 0 && this.log[candidate.expectedSeq - this.baseSeq] === candidate.event ? candidate.plan : void 0;\n\t\tconst required = pending?.kind === \"project\" ? [...this._state.projections, pending.projection] : this._state.projections;\n\t\tfor (const projection of required) if (!this.projections.includes(projection)) throw new Error(`session message projection \"${projection.type}\" was removed or replaced; restore the session with its owning plugin`);\n\t}\n};\n//#endregion\n//#region lib/types/request-header.js\n/**\n* Request-header reconstruction utilities over full `request/header` session\n* events. Anyone holding a session log reconstructs the {@link EpochHeader}\n* any request was built under by taking the latest canonical snapshot; the\n* loop uses the same equality helper to avoid logging unchanged headers.\n*\n* @module dsh-session/request-header\n*/\n/**\n* Normalize a header to canonical form: an empty tool list becomes an absent\n* field, matching how requests are built. Logging, folding, and comparison use\n* this one representation.\n* @param header - the header to normalize (not mutated).\n* @returns the canonical header.\n*/\nfunction canonicalHeader(header) {\n\tconst adapterDefaults = header.adapterDefaults;\n\treturn {\n\t\tconfig: header.config,\n\t\t...adapterDefaults?.reasoningEffort === true || adapterDefaults?.maxTokens === true ? { adapterDefaults } : {},\n\t\t...header.tools !== void 0 && header.tools.length > 0 ? { tools: header.tools } : {}\n\t};\n}\n/** Canonical JSON equality for tool schemas assembled through the same path. */\nfunction sameSchema(a, b) {\n\treturn JSON.stringify(a) === JSON.stringify(b);\n}\n/**\n* Field-wise equality over canonical headers. Tool schemas compare in order.\n* @param a - one canonical header.\n* @param b - the other.\n* @returns whether config, adapter defaults, and tools all match.\n*/\nfunction headerEquals(a, b) {\n\tif (!callConfigEquals(a.config, b.config) || a.adapterDefaults?.reasoningEffort !== b.adapterDefaults?.reasoningEffort || a.adapterDefaults?.maxTokens !== b.adapterDefaults?.maxTokens) return false;\n\tconst at = a.tools ?? [];\n\tconst bt = b.tools ?? [];\n\treturn at.length === bt.length && at.every((tool, i) => sameSchema(tool, bt[i]));\n}\n/**\n* Fold the header events of a log (or any prefix) into the\n* {@link EpochHeader} in force after the last snapshot. Non-header events are\n* skipped. This is the pure offline reconstruction path; the live session\n* tracks the same fold incrementally.\n* @param events - session events in log order.\n* @param from - a previously folded state to continue from.\n* @returns the latest canonical header, or undefined when none exists yet.\n*/\nfunction foldRequestHeader(events, from) {\n\tlet state = from;\n\tfor (const event of events) if (event.type === \"request/header\") state = canonicalHeader(event.data.header);\n\treturn state;\n}\n//#endregion\n//#region lib/types/tool-history.js\n/** Stateful reconstruction of historical tool definitions for request projection. */\n/** Folds committed headers and developer messages independently of model capability. */\nvar ToolHistoryProjection = class {\n\t/** Historical declarations indexed by the header sequence referenced by additions. */\n\theaders = /* @__PURE__ */ new Map();\n\t/** Definitions retained in the current declaration series, including removed tools. */\n\tdeclared = /* @__PURE__ */ new Map();\n\t/** Active definitions from the latest request header. */\n\tactive = [];\n\t/** Active names reconstructed from the baseline and recorded updates. */\n\tavailable = /* @__PURE__ */ new Set();\n\t/** Header that starts the current declaration series; absent before the first header. */\n\tbaselineSeq;\n\t/** Immutable request snapshot of the current baseline and resolved updates. */\n\thistory = deepFreeze({\n\t\ttools: [],\n\t\tupdates: []\n\t});\n\t/**\n\t* Consume the next committed event in log order.\n\t* @param event - a session event, including inherited events during restoration.\n\t*/\n\tapply(event) {\n\t\tif (event.type === \"request/header\") {\n\t\t\tconst tools = event.data.header.tools ?? [];\n\t\t\tthis.headers.set(event.seq, tools);\n\t\t\tconst redeclared = tools.some((tool) => {\n\t\t\t\tconst before = this.declared.get(tool.name);\n\t\t\t\treturn before !== void 0 && JSON.stringify(before) !== JSON.stringify(tool);\n\t\t\t});\n\t\t\tif (this.baselineSeq === void 0 || event.data.reason === \"series\" || event.data.startsSeries || redeclared) {\n\t\t\t\tthis.baselineSeq = event.seq;\n\t\t\t\tthis.declared = new Map(tools.map((tool) => [tool.name, tool]));\n\t\t\t\tthis.history = deepFreeze({\n\t\t\t\t\ttools,\n\t\t\t\t\tupdates: []\n\t\t\t\t});\n\t\t\t\tthis.available = new Set(tools.map((tool) => tool.name));\n\t\t\t}\n\t\t\tthis.active = tools;\n\t\t} else if (event.type === \"developer/message\") {\n\t\t\tconst { message, headerSeq } = event.data;\n\t\t\tconst definitions = headerSeq === void 0 ? [] : this.headers.get(headerSeq);\n\t\t\tconst additions = message.content.flatMap((block) => {\n\t\t\t\tif (block.type !== \"tool-addition\") return [];\n\t\t\t\tconst tool = definitions?.find((tool) => tool.name === block.toolName);\n\t\t\t\tif (tool === void 0) throw new Error(`tool history: missing definition for ${block.toolName}`);\n\t\t\t\treturn [tool];\n\t\t\t});\n\t\t\tfor (const tool of additions) this.declared.set(tool.name, tool);\n\t\t\tfor (const block of message.content) if (block.type === \"tool-addition\") this.available.add(block.toolName);\n\t\t\telse if (block.type === \"tool-removal\") this.available.delete(block.toolName);\n\t\t\tthis.history = deepFreeze({\n\t\t\t\ttools: this.history.tools,\n\t\t\t\tupdates: [...this.history.updates, {\n\t\t\t\t\tmessageId: message.id,\n\t\t\t\t\tadditions\n\t\t\t\t}]\n\t\t\t});\n\t\t}\n\t}\n\t/**\n\t* Read an immutable snapshot; subsequent events do not mutate it.\n\t* @returns initial declarations and historically resolved additions for the current series.\n\t*/\n\tsnapshot() {\n\t\tif (this.active.length !== this.available.size || this.active.some((tool) => !this.available.has(tool.name))) return deepFreeze({\n\t\t\ttools: this.active,\n\t\t\tupdates: []\n\t\t});\n\t\treturn this.history;\n\t}\n};\n//#endregion\n//#region lib/types/repair.js\n/**\n* Pending tool-result recovery shared by failed live steps, interrupted logs,\n* and fork seeds. Tail repair preserves closed steps and supplies only missing\n* tool results and lifecycle boundaries, with cause-specific retry guidance.\n* @module @deepseek-ai/dsh-session/repair\n*/\n/** Recovery code for an assistant tool request that never reached a recorded call start. */\nconst TOOL_NOT_STARTED = \"TOOL_NOT_STARTED\";\n/** Recovery code for a recorded tool call whose completed outcome was not durably recorded. */\nconst TOOL_OUTCOME_UNKNOWN = \"TOOL_OUTCOME_UNKNOWN\";\n/** Model-visible wording of the synthetic error tool results, keyed by cause. */\nconst CLOSER_TEXT = {\n\tinterrupted: {\n\t\tstarted: \"The tool call was interrupted after it was recorded, but no result was durably recorded. Its outcome is unknown. Decide whether to retry from the tool semantics: retry only if the operation is read-only or idempotent; if it may have side effects, first verify external state or ask the user. Do not retry blindly.\",\n\t\tnotStarted: \"The tool call was interrupted before the Harness recorded it as started. Retry it if it is still needed.\"\n\t},\n\tforked: {\n\t\tstarted: \"The history inherited by this branch records this tool call starting but does not include its result. The parent session may have completed it after the fork point. Decide whether to retry from the tool semantics: retry only if the operation is read-only or idempotent; if it may have side effects, first verify external state or ask the user. Do not retry blindly.\",\n\t\tnotStarted: \"The history inherited by this branch has no record of this tool call starting. The parent session may have executed it after the fork point. Decide whether to retry from the tool semantics: retry only if the operation is read-only or idempotent; if it may have side effects, first verify external state or ask the user. Do not retry blindly.\"\n\t}\n};\n/**\n* Return deterministic synthetic events that close an open tail turn. Unmatched\n* calls receive error results first, followed by an open `step/end` and a\n* cause-specific `turn/end`; sequences continue the log and timestamps reuse the\n* last real event. A balanced or empty log returns no events.\n*\n* @param events - the loaded durable log to scan (a valid committed prefix, possibly with a crash tail).\n* @param cause - the owning close operation: selects result wording and the turn-ending reason.\n* @returns the synthetic closer events to append after `events`, in order; empty when the log is already balanced.\n*/\nfunction openTurnClosers(events, cause) {\n\tlet openTurn = null;\n\tlet openStep = null;\n\tconst recovery = new ToolCallRecovery(cause);\n\tfor (const event of events) {\n\t\trecovery.observe(event);\n\t\tswitch (event.type) {\n\t\t\tcase \"turn/start\":\n\t\t\t\topenTurn = event.data.turn;\n\t\t\t\topenStep = null;\n\t\t\t\tbreak;\n\t\t\tcase \"turn/end\":\n\t\t\t\topenTurn = null;\n\t\t\t\topenStep = null;\n\t\t\t\tbreak;\n\t\t\tcase \"step/start\":\n\t\t\t\topenStep = event.data.step;\n\t\t\t\tbreak;\n\t\t\tcase \"step/end\":\n\t\t\t\topenStep = null;\n\t\t\t\tbreak;\n\t\t\tdefault: break;\n\t\t}\n\t}\n\tconst last = events.at(-1);\n\tif (openTurn === null || last === void 0) return [];\n\tconst closers = recovery.results();\n\tlet seq = last.seq + closers.length + 1;\n\tconst time = last.time;\n\tif (openStep !== null) closers.push({\n\t\ttype: \"step/end\",\n\t\tseq: SessionSeq(seq++),\n\t\ttime,\n\t\tdata: {\n\t\t\tturn: openTurn,\n\t\t\tstep: openStep\n\t\t}\n\t});\n\tclosers.push({\n\t\ttype: \"turn/end\",\n\t\tseq: SessionSeq(seq++),\n\t\ttime,\n\t\tdata: {\n\t\t\tturn: openTurn,\n\t\t\treason: { kind: cause.kind }\n\t\t}\n\t});\n\treturn closers;\n}\n/**\n* Track unanswered assistant tool requests from one Session's committed events.\n* Observe from the start of the owned step or replay prefix, and recover before\n* its step closes. This state retains pending identities, not event history.\n*/\nvar ToolCallRecovery = class {\n\tcause;\n\tpendingCalls = /* @__PURE__ */ new Map();\n\tlast;\n\t/** @param cause - defaults to interrupted live/crash recovery; fork-seed construction supplies its own cause. */\n\tconstructor(cause = { kind: \"interrupted\" }) {\n\t\tthis.cause = cause;\n\t}\n\t/**\n\t* Consume the next committed event; closed steps and turn boundaries discard pending requests.\n\t* @param event - the next event from the same Session, in sequence order.\n\t*/\n\tobserve(event) {\n\t\tthis.last = {\n\t\t\tseq: event.seq,\n\t\t\ttime: event.time\n\t\t};\n\t\tswitch (event.type) {\n\t\t\tcase \"turn/start\":\n\t\t\tcase \"turn/end\":\n\t\t\tcase \"step/end\":\n\t\t\t\tthis.pendingCalls.clear();\n\t\t\t\tbreak;\n\t\t\tcase \"assistant/message\":\n\t\t\t\tfor (const block of event.data.message.content) if (block.type === \"tool-call\") this.pendingCalls.set(block.id, {\n\t\t\t\t\tturn: event.data.turn,\n\t\t\t\t\tstep: event.data.step\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"tool/call\": {\n\t\t\t\tconst entry = this.pendingCalls.get(event.data.callId);\n\t\t\t\tif (entry) entry.callSeq = event.seq;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"tool/result\": {\n\t\t\t\tconst callId = event.data.message.source.callId;\n\t\t\t\tconst entry = this.pendingCalls.get(callId);\n\t\t\t\tif (event.surfaceOp === \"append\" && entry !== void 0 && entry.turn === event.data.turn && entry.step === event.data.step) this.pendingCalls.delete(callId);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: break;\n\t\t}\n\t}\n\t/**\n\t* Build conservative error results in assistant order without changing tracked state.\n\t* Sequences follow the latest observed event and timestamps reuse its time.\n\t* Callers commit the results and observe those commits before recovering again.\n\t* @returns pending tool-result events, empty when no request remains unanswered.\n\t*/\n\tresults() {\n\t\tif (this.last === void 0) return [];\n\t\tlet seq = this.last.seq + 1;\n\t\tconst time = this.last.time;\n\t\tconst results = [];\n\t\tconst text = CLOSER_TEXT[this.cause.kind];\n\t\tfor (const [callId, { turn, step, callSeq }] of this.pendingCalls) {\n\t\t\tconst started = callSeq !== void 0;\n\t\t\tconst message = deepFreeze({\n\t\t\t\tid: brandString(`${this.cause.kind}-tool-result-${callId}-${seq}`),\n\t\t\t\trole: \"tool\",\n\t\t\t\ttoolCallId: callId,\n\t\t\t\tisError: true,\n\t\t\t\tsource: {\n\t\t\t\t\tkind: \"tool\",\n\t\t\t\t\tcallId\n\t\t\t\t},\n\t\t\t\tcontent: [{\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: started ? text.started : text.notStarted\n\t\t\t\t}]\n\t\t\t});\n\t\t\tresults.push({\n\t\t\t\ttype: \"tool/result\",\n\t\t\t\tseq: SessionSeq(seq++),\n\t\t\t\ttime,\n\t\t\t\tdata: {\n\t\t\t\t\tturn,\n\t\t\t\t\tstep,\n\t\t\t\t\tmessage,\n\t\t\t\t\terror: started ? {\n\t\t\t\t\t\tname: \"ToolOutcomeUnknownError\",\n\t\t\t\t\t\tcode: TOOL_OUTCOME_UNKNOWN\n\t\t\t\t\t} : {\n\t\t\t\t\t\tname: \"ToolNotStartedError\",\n\t\t\t\t\t\tcode: TOOL_NOT_STARTED\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tsurfaceOp: \"append\",\n\t\t\t\t...started ? { sourceEventSeqs: [callSeq] } : {}\n\t\t\t});\n\t\t}\n\t\treturn results;\n\t}\n};\n/**\n* Crash-recovery entry point: synthetic closers that balance a persisted log\n* whose tail turn was interrupted. Used by crash-recovery callers; fork\n* seeds receive their `forked`-cause closers through `buildForkSeed` in\n* `./fork.ts`.\n*\n* @param events - the persisted log to scan, possibly ending inside an open turn.\n* @returns the synthetic `interrupted` closer events to append after `events`; empty when the log is already balanced.\n*/\nfunction interruptedTurnClosers(events) {\n\treturn openTurnClosers(events, { kind: \"interrupted\" });\n}\n//#endregion\n//#region lib/types/fork.js\n/**\n* Fork seed construction over an exact source-event prefix.\n* @module @deepseek-ai/dsh-session/fork\n*/\n/**\n* Copy an inclusive event prefix, mark its inherited cut, and close its open tail with forked results\n* and step/turn endings. Closed steps and turns are preserved unchanged.\n* The caller validates that the boundary is an existing contiguous event seq;\n* Session construction snapshots the borrowed events before publication.\n*\n* @param events - source log with contiguous seqs from zero.\n* @param boundary - inclusive source event seq the child inherits through.\n* @returns a new array retaining the source event objects, followed by synthetic\n* closers outside the inherited prefix counted by `inheritedEventCount`.\n*/\nfunction buildForkSeed(events, boundary) {\n\tconst prefix = events.slice(0, boundary + 1);\n\tprefix.push({\n\t\ttype: \"session/end-seed\",\n\t\tseq: SessionSeq(boundary + 1),\n\t\ttime: events[boundary].time,\n\t\tdata: { inherited: true }\n\t});\n\treturn prefix.concat(openTurnClosers(prefix, { kind: \"forked\" }));\n}\n//#endregion\n//#region lib/types/preparation.js\n/**\n* Ownership of one unpublished Session before registry publication.\n* @module @deepseek-ai/dsh-session/preparation\n*/\n/**\n* One exact unpublished Session and the provider state that keeps it usable.\n* Disposal is synchronous and idempotent. Providers decide whether release\n* returns the Session to a cache or discards it; publication may consume that\n* state before disposal, making the callback a no-op.\n*/\nvar SessionPreparation = class SessionPreparation {\n\toptions;\n\treleased = false;\n\t/** The exact Session to use for setup and publication. */\n\tsession;\n\tconstructor(session, options) {\n\t\tthis.options = options;\n\t\tthis.session = session;\n\t}\n\t/**\n\t* Wrap an unpublished Session in one preparation lifetime.\n\t* @param session - exact unpublished Session.\n\t* @param options - optional provider release behavior.\n\t* @returns a preparation disposed after publication or rollback.\n\t*/\n\tstatic create(session, options) {\n\t\treturn new SessionPreparation(session, options ?? {});\n\t}\n\t/** Release provider state once when this preparation leaves its caller. */\n\t[Symbol.dispose]() {\n\t\tif (this.released) return;\n\t\tthis.released = true;\n\t\tthis.options.release?.();\n\t}\n};\n//#endregion\n//#region lib/types/seq-ranges.js\n/** Lossless range encoding for JSONL `sourceEventSeqs` arrays. */\nfunction isStrictlyIncreasing(values) {\n\treturn values.every((value, index) => index === 0 || value > values[index - 1]);\n}\n/**\n* Replace profitable consecutive runs with inclusive pairs.\n* @param values - validated in-memory source sequences.\n* @returns a lossless JSON storage form.\n*/\nfunction encodeSeqRanges(values) {\n\tif (!isStrictlyIncreasing(values)) return [...values];\n\tconst encoded = [];\n\tfor (let start = 0; start < values.length;) {\n\t\tlet end = start;\n\t\twhile (end + 1 < values.length && values[end + 1] === values[end] + 1) end += 1;\n\t\tif (end - start >= 2) encoded.push([values[start], values[end]]);\n\t\telse for (let index = start; index <= end; index += 1) encoded.push(values[index]);\n\t\tstart = end + 1;\n\t}\n\treturn encoded;\n}\n/**\n* Expand a JSON storage-form source sequence array.\n* @param value - parsed storage value.\n* @param maxEntries - largest list permitted by the owning event.\n* @returns the in-memory source sequences.\n*/\nfunction decodeSeqRanges(value, maxEntries = Number.MAX_SAFE_INTEGER) {\n\tif (!Array.isArray(value)) throw new TypeError(\"sourceEventSeqs must be an array\");\n\tconst decoded = [];\n\tlet hasRange = false;\n\tfor (const entry of value) {\n\t\tif (typeof entry === \"number\") {\n\t\t\tassertSeq(entry);\n\t\t\tif (decoded.length >= maxEntries) throw new TypeError(\"sourceEventSeqs exceeds its event sequence\");\n\t\t\tdecoded.push(SessionSeq(entry));\n\t\t\tcontinue;\n\t\t}\n\t\tif (!Array.isArray(entry) || entry.length !== 2) throw new TypeError(\"sourceEventSeqs range entries must be [start, end] pairs\");\n\t\tconst start = entry[0];\n\t\tconst end = entry[1];\n\t\tassertSeq(start);\n\t\tassertSeq(end);\n\t\tif (end < start) throw new TypeError(\"sourceEventSeqs ranges require start <= end\");\n\t\tif (end - start + 1 > maxEntries - decoded.length) throw new TypeError(\"sourceEventSeqs range exceeds its event sequence\");\n\t\tfor (let seq = start; seq <= end; seq += 1) decoded.push(SessionSeq(seq));\n\t\thasRange = true;\n\t}\n\tif (hasRange && !isStrictlyIncreasing(decoded)) throw new TypeError(\"sourceEventSeqs ranges must be strictly increasing\");\n\treturn decoded;\n}\nfunction assertSeq(value) {\n\tif (!Number.isSafeInteger(value) || value < 0) throw new TypeError(\"sourceEventSeqs must contain non-negative safe integers\");\n}\n//#endregion\n//#region lib/types/index.js\n/**\n* Event-sourced session service: append-only session log, in-memory store, and\n* the derived LLM message history. Persistence is a plugin concern (subscribe\n* to `session/event`, drain on `session/flush`).\n*\n* @module @deepseek-ai/dsh-session\n*/\n/** Validate and freeze one detached creation header in place. */\nfunction validateSessionHeader(id, input) {\n\tif (input === null || typeof input !== \"object\" || Array.isArray(input)) throw new Error(\"session header is not a plain JSON record\");\n\tconst record = input;\n\tif (Object.hasOwn(record, \"seedLength\")) throw new Error(\"session header has invalid field \\\"seedLength\\\"\");\n\tif (record.version !== 4) throw new Error(`session header version must be 4, got ${String(record.version)}`);\n\tif (record.id !== id) throw new Error(`session header id \"${String(record.id)}\" does not match session id \"${id}\"`);\n\tif (typeof record.createdAt !== \"number\" || !Number.isSafeInteger(record.createdAt) || record.createdAt < 0) throw new Error(\"session header createdAt must be a non-negative safe integer\");\n\tif (record.cwd !== void 0) {\n\t\tif (typeof record.cwd !== \"string\") throw new Error(\"session header cwd must be a string\");\n\t\tif (!isAbsolute(record.cwd)) throw new Error(`session header cwd must be an absolute path, got \"${record.cwd}\"`);\n\t}\n\tif (record.parentSession !== void 0 && typeof record.parentSession !== \"string\") throw new Error(\"session header parentSession must be a string\");\n\tif (typeof record.isSeeded !== \"boolean\") throw new Error(\"session header isSeeded must be a boolean\");\n\tif (record.origin !== void 0 && record.origin !== \"subagent\") throw new Error(\"session header origin must be \\\"subagent\\\"\");\n\tif (record.delegationDepth !== void 0 && (typeof record.delegationDepth !== \"number\" || !Number.isSafeInteger(record.delegationDepth) || record.delegationDepth < 0)) throw new Error(\"session header delegationDepth must be a non-negative safe integer\");\n\tif (record.agentPreset !== void 0 && typeof record.agentPreset !== \"string\") throw new Error(\"session header agentPreset must be a string\");\n\treturn deepFreeze(record);\n}\n/** Validate and freeze one exclusively owned persistence header in place. */\nfunction validateRestoredSessionHeader(id, input) {\n\tif (input !== null && typeof input === \"object\" && !Array.isArray(input)) {\n\t\tconst prototype = Reflect.getPrototypeOf(input);\n\t\tif (prototype !== Object.prototype && prototype !== null) throw new Error(\"session header is not a plain JSON record\");\n\t}\n\treturn validateSessionHeader(id, input);\n}\n/** Detach, validate, and freeze the creation metadata published by a session. */\nfunction snapshotSessionHeader(id, source) {\n\tconst snapshot = snapshotJsonValue(source === void 0 ? {\n\t\tversion: 4,\n\t\tid,\n\t\tcreatedAt: Date.now(),\n\t\tisSeeded: false\n\t} : source);\n\tif (snapshot === void 0) throw new Error(\"session header is not losslessly JSON-serializable\");\n\treturn validateSessionHeader(id, snapshot);\n}\n/**\n* Validate an exclusively owned event and deeply freeze its identified message\n* without copying the event. The caller transfers an object graph that no\n* producer retains and that shares no mutable children with another event.\n* Use {@link snapshotSessionEvent} when exclusive ownership is not guaranteed.\n* @param event - exclusively owned event imported across a trusted boundary.\n* @returns the same event object with a validated, deeply frozen message.\n* @throws when event-local surface metadata, request-header fields, or message invariants are invalid; history relations are not checked.\n*/\nfunction adoptSessionEvent(event) {\n\tvalidateSessionEventData(event, `session event at seq ${event.seq}`);\n\tvalidateSurfaceMetadata(event);\n\tassertMessageEventShape(event, `session event at seq ${event.seq}`);\n\tswitch (event.type) {\n\t\tcase \"user/message\":\n\t\t\tdeepFreeze(event.data);\n\t\t\tbreak;\n\t\tcase \"developer/message\":\n\t\tcase \"system/message\":\n\t\tcase \"assistant/message\":\n\t\tcase \"tool/result\":\n\t\t\tdeepFreeze(event.data.message);\n\t\t\tbreak;\n\t\tdefault: break;\n\t}\n\treturn event;\n}\n/**\n* Detach one event while preserving deep immutability for its identified message.\n* @param event - event imported across a query or persistence boundary.\n* @returns a detached event snapshot with a validated, deeply frozen message.\n*/\nfunction snapshotSessionEvent(event) {\n\treturn adoptSessionEvent(structuredClone(event));\n}\n/** Validate the fixed event envelope after one-pass JSON materialization. */\nfunction assertSessionEventEnvelope(value, index) {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`seed event at index ${index} has an invalid event envelope`);\n\tconst event = value;\n\tfor (const key in event) switch (key) {\n\t\tcase \"type\":\n\t\tcase \"seq\":\n\t\tcase \"time\":\n\t\tcase \"data\":\n\t\tcase \"surfaceOp\":\n\t\tcase \"sourceEventSeqs\":\n\t\tcase \"ignorable\": break;\n\t\tdefault: throw new Error(`seed event at index ${index} has an invalid event envelope`);\n\t}\n\tconst type = event[\"type\"];\n\tconst seq = event[\"seq\"];\n\tconst time = event[\"time\"];\n\tif (typeof type !== \"string\" || typeof seq !== \"number\" || !Number.isSafeInteger(seq) || seq < 0 || Object.is(seq, -0) || typeof time !== \"number\" || !Number.isSafeInteger(time) || event[\"data\"] === void 0 || event[\"ignorable\"] !== void 0 && event[\"ignorable\"] !== true) throw new Error(`seed event at index ${index} has an invalid event envelope`);\n\tvalidateSessionEventData(event, `seed ${type} at index ${index}`);\n\tswitch (type) {\n\t\tcase \"request/header\":\n\t\tcase \"developer/message\":\n\t\tcase \"system/message\":\n\t\tcase \"user/message\":\n\t\tcase \"assistant/attempt\":\n\t\tcase \"assistant/message\":\n\t\tcase \"tool/result\":\n\t\t\tassertCurrentLlmShape(event, index);\n\t\t\tbreak;\n\t}\n}\n/** Reject obsolete request headers and malformed messages at the seed/load boundary. */\nfunction assertCurrentLlmShape(event, index) {\n\tconst data = event[\"data\"];\n\tconst record = typeof data === \"object\" && data !== null ? data : void 0;\n\tif (event[\"type\"] === \"request/header\") {\n\t\tconst headerRecord = record?.[\"header\"];\n\t\tconst config = headerRecord[\"config\"];\n\t\tif (!hasProviderModel(config)) throw new Error(`seed request/header at index ${index} lacks provider/model`);\n\t\tconst configRecord = config;\n\t\tconst reasoningEffort = configRecord[\"reasoningEffort\"];\n\t\tif (reasoningEffort !== void 0 && (typeof reasoningEffort !== \"string\" || reasoningEffort.length === 0)) throw new Error(`seed request/header at index ${index} has an invalid reasoningEffort`);\n\t\tassertAdapterDefaults(headerRecord[\"adapterDefaults\"], configRecord, index);\n\t\tconst reason = record?.[\"reason\"];\n\t\tif (reason !== \"initial\" && reason !== \"resume\" && reason !== \"change\" && reason !== \"series\") throw new Error(`seed request/header at index ${index} has an invalid reason`);\n\t\tif (record?.[\"startsSeries\"] !== void 0 && record[\"startsSeries\"] !== true) throw new Error(`seed request/header at index ${index} has an invalid startsSeries marker`);\n\t}\n\tconst type = event[\"type\"];\n\tif (type === \"assistant/attempt\") {\n\t\tassertAssistantSettlementShape(record, type, index);\n\t\treturn;\n\t}\n\tif (!isMessageEventType(type)) return;\n\tassertMessageEventShape(event, `seed ${type} at index ${index}`);\n\tif (type === \"assistant/message\") assertAssistantSettlementShape(record, type, index);\n}\n/** Validate fields used directly by restored Session lifecycle logic without replaying the embedded stream. */\nfunction assertAssistantSettlementShape(data, type, index) {\n\tconst turn = data?.[\"turn\"];\n\tconst step = data?.[\"step\"];\n\tif (typeof turn !== \"number\" || !Number.isSafeInteger(turn) || turn < 0 || Object.is(turn, -0) || typeof step !== \"number\" || !Number.isSafeInteger(step) || step < 0 || Object.is(step, -0) || !Array.isArray(data?.[\"stream\"])) throw new Error(`seed ${type} at index ${index} has invalid settlement fields`);\n}\nconst allowedAdapterKeys = new Set([\"reasoningEffort\", \"maxTokens\"]);\n/** Validate adapter-default markers imported from a durable request header. */\nfunction assertAdapterDefaults(value, config, index) {\n\tif (value === void 0) return;\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) throw new Error(`seed request/header at index ${index} has invalid adapterDefaults`);\n\tconst defaults = value;\n\tif (Object.keys(defaults).some((key) => !allowedAdapterKeys.has(key)) || Object.values(defaults).some((marker) => marker !== true) || defaults[\"reasoningEffort\"] === true && config[\"reasoningEffort\"] === void 0 || defaults[\"maxTokens\"] === true && config[\"maxTokens\"] === void 0) throw new Error(`seed request/header at index ${index} has invalid adapterDefaults`);\n}\n/** The surface event types whose payload carries an identified message. */\nfunction isMessageEventType(type) {\n\treturn type === \"developer/message\" || type === \"system/message\" || type === \"user/message\" || type === \"assistant/message\" || type === \"tool/result\";\n}\nconst MESSAGE_ROLE_BY_TYPE = {\n\t\"system/message\": \"system\",\n\t\"developer/message\": \"developer\",\n\t\"user/message\": \"user\",\n\t\"assistant/message\": \"assistant\",\n\t\"tool/result\": \"tool\"\n};\n/** Validate only the event-specific invariants needed to safely replay a message. */\nfunction assertMessageEventShape(event, subject) {\n\tconst type = event[\"type\"];\n\tif (!isMessageEventType(type)) return;\n\tconst data = event[\"data\"];\n\tconst record = typeof data === \"object\" && data !== null ? data : void 0;\n\tconst message = type === \"user/message\" ? record : record?.[\"message\"];\n\tif (typeof message !== \"object\" || message === null || typeof message[\"id\"] !== \"string\" || message[\"id\"] === \"\") throw new Error(`${subject} lacks an identified message`);\n\tconst messageRecord = message;\n\tconst expectedRole = MESSAGE_ROLE_BY_TYPE[type];\n\tif (messageRecord[\"role\"] !== expectedRole) throw new Error(`${subject} message must have role \"${expectedRole}\"`);\n\tconst source = messageRecord[\"source\"];\n\tif (typeof source !== \"object\" || source === null || typeof source[\"kind\"] !== \"string\" || source[\"kind\"] === \"\") throw new Error(`${subject} message has invalid source`);\n\tif (!Array.isArray(messageRecord[\"content\"])) throw new Error(`${subject} message has invalid content`);\n\tconst sourceRecord = source;\n\tif (type === \"system/message\") {\n\t\tif (sourceRecord[\"kind\"] !== \"system-prompt\") throw new Error(`${subject} message must have system-prompt source`);\n\t\treturn;\n\t}\n\tif (type === \"assistant/message\") {\n\t\tif (sourceRecord[\"kind\"] !== \"model\" || !hasProviderModel(sourceRecord)) throw new Error(`${subject} message must have model source`);\n\t\treturn;\n\t}\n\tif (type !== \"tool/result\") return;\n\tif (sourceRecord[\"kind\"] !== \"tool\" || typeof sourceRecord[\"callId\"] !== \"string\" || sourceRecord[\"callId\"] === \"\") throw new Error(`${subject} message must have tool source`);\n\tif (messageRecord[\"toolCallId\"] !== sourceRecord[\"callId\"]) throw new Error(`${subject} message has mismatched tool call ids`);\n}\n/** Whether an unknown value carries the current provider/model pair. */\nfunction hasProviderModel(value) {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst pair = value;\n\treturn typeof pair[\"provider\"] === \"string\" && pair[\"provider\"].length > 0 && typeof pair[\"model\"] === \"string\" && pair[\"model\"].length > 0;\n}\n/** Resolve one listener snapshot, including Cordis's internal dispatch checks. */\nfunction collectSessionCallbacks(ctx, args) {\n\treturn [...ctx.events.dispatch(\"emit\", args)];\n}\n/** Invoke one resolved observe-only listener snapshot with per-listener containment. */\nfunction invokeContainedSessionObservers(ctx, name, id, args, callbacks) {\n\tfor (const callback of callbacks) try {\n\t\tconst returned = callback(...args);\n\t\tPromise.resolve(returned).catch((error) => {\n\t\t\tctx.logger.warn(`session \"${id}\": ${name} listener rejected: ${String(error)}`);\n\t\t});\n\t} catch (error) {\n\t\tctx.logger.warn(`session \"${id}\": ${name} listener threw: ${String(error)}`);\n\t}\n}\n/** Store attachment for the append path; module-private to keep Session store-agnostic publicly. */\nconst attachments = /* @__PURE__ */ new WeakMap();\n/**\n* Grammar of a {@link PluginRecordType}: `plugin:` followed by\n* slash-separated segments of lowercase letters, digits, `.`, `_`, and `-`,\n* each segment starting with a letter or digit.\n*/\nconst PLUGIN_RECORD_TYPE = /^plugin:[a-z0-9][a-z0-9._-]*(?:\\/[a-z0-9][a-z0-9._-]*)*$/u;\n/**\n* Whether one event type name follows the plugin record grammar.\n* @param type - an event type name.\n* @returns whether the name is a {@link PluginRecordType}.\n*/\nfunction isPluginRecordType(type) {\n\treturn PLUGIN_RECORD_TYPE.test(type);\n}\n/**\n* Type one constructed plugin record as a log event after checking its type\n* against the plugin record grammar. A restored Session already holds events\n* whose types are outside `SessionEventMap` when they are marked ignorable;\n* a plugin record is such an event.\n* @param value - the frozen record envelope built by {@link Session}.\n* @throws when the record type is outside the plugin record grammar.\n*/\nfunction assertPluginRecordEvent(value) {\n\tconst { type } = value;\n\tif (!isPluginRecordType(type)) throw new Error(`plugin record type \"${type}\" must be \"plugin:\" followed by lowercase slash-separated segments`);\n}\n/** Module-private access to {@link Session}'s record commit, assigned once by its static block. */\nlet commitPluginRecord;\n/**\n* Append one experimental plugin record: an event marked `ignorable` whose\n* type is declared in {@link PluginRecordMap}, outside {@link SessionEventMap}.\n* The plugin record catalog lists it separately from released event schemas.\n* A reader that does not recognize the type retains and skips the record, which never\n* enters the model-visible surface, and fork and resume carry it with the rest\n* of the log. A Session format migration retains records on a best-effort\n* basis, so a record holds plugin-owned state that its owner can lose without\n* changing how the rest of the log is interpreted.\n*\n* Only production source under `packages/experimental/` may call this\n* function; the `verify-plugin-record-callers` gate rejects any other\n* production caller in this repository. Read records back with\n* {@link pluginRecordOf}.\n* @param session - the Session whose log receives the record.\n* @param type - declared record name: `plugin:` followed by slash-separated\n* segments of lowercase letters, digits, `.`, `_`, and `-`, each starting\n* with a letter or digit.\n* @param data - JSON payload, snapshotted before it enters the log.\n* @returns the sequence number of the committed record.\n* @throws when `type` is outside that grammar, when `data` is not losslessly\n* JSON-serializable, or when the call reenters another append's publication;\n* a rejected record does not change the log.\n*/\nfunction appendPluginRecord(session, type, data) {\n\treturn commitPluginRecord(session, type, data);\n}\n/**\n* Read one committed event as a plugin record. The V3-to-V4 format edge also\n* renames each unknown ignorable V3 event into the `plugin:` namespace, so an\n* owner names its records under its own package name and validates `data`.\n* @param event - any committed Session event, live or restored.\n* @returns the record, or undefined when the event is not an ignorable event\n* whose type follows the plugin record grammar.\n*/\nfunction pluginRecordOf(event) {\n\tconst type = event.type;\n\tif (event.ignorable !== true || !isPluginRecordType(type)) return void 0;\n\treturn {\n\t\ttype,\n\t\tseq: event.seq,\n\t\ttime: event.time,\n\t\tdata: event.data\n\t};\n}\n/**\n* An event-sourced session: an append-only log of {@link SessionEvent}s.\n*\n* Plain class (not a Service) — create live instances via\n* `ctx.sessions.create()` and detached instances via {@link create}.\n* Seeding with an existing event log replays/forks a session.\n* @typert object\n*/\nvar Session = class Session {\n\tlog = [];\n\t/** Single incremental owner of surface acceptance and projection state. */\n\tsurfaceManager;\n\t/** The ordered surface over this session's event log. */\n\tget surface() {\n\t\treturn this.surfaceManager;\n\t}\n\t/**\n\t* Detached, deep-frozen creation metadata (format version, cwd, lineage,\n\t* and whether fork history exists). Supplied by the store via `ctx.sessions.create()`. When a\n\t* `Session` is created without a store-owned header, a minimal header is\n\t* synthesized (stamped with the current {@link SESSION_FORMAT_VERSION}) so\n\t* `session.header` is always present. Kept out of the event log — it is a\n\t* storage concern, not replayable conversation state.\n\t*/\n\theader;\n\t/** Number of leading events inherited from this Session's fork parent. */\n\tinheritedEventCount;\n\t/** The session identity, derived from its durable header's single copy. */\n\tget id() {\n\t\treturn this.header.id;\n\t}\n\t/**\n\t* The constructor seed length (0 without one), before any marker appended\n\t* during construction. Seed events never publish on `session/event`. A\n\t* marker appended before the store attaches occupies this seq without\n\t* publishing either; otherwise this seq is available for the next append.\n\t*\n\t* This in-process offset is not persisted. A fork seed can already contain\n\t* the child's inherited marker and synthetic closers, so its child-owned\n\t* history starts at {@link inheritedEventCount}, before this offset. A\n\t* resumed Session's seed contains its full stored log, while its inherited\n\t* count keeps the durable fork cut. Consumers needing complete canonical\n\t* history start at seq 0.\n\t*/\n\tfirstLiveSeq;\n\t/**\n\t* First event produced for this object lifecycle. A new fork includes its\n\t* child-owned seed marker and closers; a restored Session starts after its\n\t* complete stored prefix. This in-process capture offset is not persisted.\n\t*/\n\tfirstLifecycleSeq;\n\t/**\n\t* Create a detached session by validating and snapshotting borrowed seed\n\t* events and storage metadata.\n\t* @param id - session identity.\n\t* @param seed - optional borrowed replay or fork events.\n\t* @param header - optional borrowed storage metadata.\n\t* @param inheritedEventCount - exact fork-inherited prefix length for a seeded header.\n\t* @param projections - pure interpreters for plugin-owned message changes.\n\t* @returns a detached session.\n\t* @throws when a seed event requires a missing message interpreter or fails validation.\n\t*/\n\tstatic create(id, seed, header, inheritedEventCount, projections) {\n\t\treturn new Session(id, seed, header, \"snapshot\", inheritedEventCount, projections);\n\t}\n\t/**\n\t* Restore a detached session by adopting an independently owned or deeply frozen seed.\n\t* Runtime-required event fields, event envelopes, sequence continuity, surface\n\t* transitions, and header fields are validated without copying or freezing events.\n\t* Embedded Assistant streams remain opaque until a stream consumer or storage\n\t* verifier reads them.\n\t* @param id - restored session identity.\n\t* @param seed - independently owned or deeply frozen events.\n\t* @param header - independently owned storage metadata.\n\t* @param inheritedEventCount - exact fork-inherited prefix length decoded from storage.\n\t* @param eventState - aliasing state carried from the operation that produced the seed.\n\t* @param projections - pure interpreters for plugin-owned message changes.\n\t* @returns a restored detached session.\n\t* @throws when a seed event requires a missing message interpreter or fails validation.\n\t*/\n\tstatic fromRestore(id, seed, header, inheritedEventCount, eventState, projections) {\n\t\treturn new Session(id, seed, header, eventState, inheritedEventCount, projections);\n\t}\n\tconstructor(id, seed, header, mode = \"snapshot\", suppliedInheritedEventCount, projections = []) {\n\t\tthis.surfaceManager = new SurfaceManager(this.log, SessionLogOffset(0), projections);\n\t\tconst restoredHeader = mode === \"snapshot\" ? void 0 : validateRestoredSessionHeader(id, header);\n\t\tif (seed !== void 0) for (const [index, source] of seed.entries()) {\n\t\t\tconst snapshot = mode === \"snapshot\" ? snapshotJsonValue(source) : source;\n\t\t\tif (snapshot === void 0) throw new Error(`seed event at index ${index} is not losslessly JSON-serializable`);\n\t\t\tassertSessionEventEnvelope(snapshot, index);\n\t\t\tif (snapshot.seq !== index) throw new Error(`seed event at index ${index} has seq ${snapshot.seq} (expected ${index}); seed must be contiguous from 0`);\n\t\t\ttry {\n\t\t\t\tthis.surfaceManager.validateNext(snapshot);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(`invalid seed event at index ${index}: ${error instanceof Error ? error.message : \"invalid surface metadata\"}`);\n\t\t\t}\n\t\t\tthis.log.push(mode === \"snapshot\" ? deepFreeze(snapshot) : snapshot);\n\t\t}\n\t\tthis.firstLiveSeq = SessionLogOffset(this.log.length);\n\t\tthis.header = restoredHeader ?? snapshotSessionHeader(id, header);\n\t\tif (this.header.isSeeded && seed === void 0) throw new Error(\"seeded session requires an explicit constructor seed\");\n\t\tif (this.header.isSeeded && suppliedInheritedEventCount === void 0) throw new Error(\"seeded session requires an inherited event count\");\n\t\tconst inheritedEventCount = SessionLogOffset(suppliedInheritedEventCount ?? 0);\n\t\tif (!this.header.isSeeded && inheritedEventCount !== 0) throw new Error(\"unseeded session inherited event count must be 0\");\n\t\tif (inheritedEventCount > this.log.length) throw new Error(\"session inherited event count exceeds its event log\");\n\t\tconst seedMarker = this.log[inheritedEventCount];\n\t\tconst markedSeed = seedMarker?.type === \"session/end-seed\" && seedMarker.data.inherited === true;\n\t\tif (mode === \"snapshot\" && this.header.isSeeded && inheritedEventCount !== this.log.length && !markedSeed) throw new Error(\"seeded session constructor seed must equal its inherited prefix or mark its inherited cut\");\n\t\tif (markedSeed && this.log.slice(inheritedEventCount + 1).some((event) => event.type === \"session/end-seed\" && event.data.inherited === true)) throw new Error(\"session inherited event count must identify the final inherited marker\");\n\t\tthis.inheritedEventCount = inheritedEventCount;\n\t\tthis.firstLifecycleSeq = mode === \"snapshot\" && this.header.isSeeded ? inheritedEventCount : this.firstLiveSeq;\n\t\tif (seed !== void 0 && mode === \"snapshot\" && this.header.isSeeded && !markedSeed) this.append(\"session/end-seed\", { inherited: true });\n\t\telse if (seed !== void 0 && !(mode === \"snapshot\" && this.header.isSeeded) && this.log.at(-1)?.type !== \"session/end-seed\") this.append(\"session/end-seed\", {});\n\t}\n\t/** Cached immutable full snapshot of the private append-only log. */\n\teventsSnapshot;\n\t/**\n\t* Return the immutable event stored at one exact sequence number.\n\t* @deprecated Existing logic may remain unmigrated for now, but new calls are prohibited.\n\t* See the [Agent Note](../../../../.agents/notes/implemented/architecture/2026-09-09-deprecate-synchronous-session-event-reads.md).\n\t* @param seq - event sequence number.\n\t* @returns the accepted event, or undefined when the log does not contain it.\n\t*/\n\teventAt(seq) {\n\t\treturn this.log[seq];\n\t}\n\t/**\n\t* Materialize an immutable snapshot of a half-open event sequence range.\n\t* A full current snapshot is reused until the next append; every previously\n\t* returned snapshot remains stable after later appends.\n\t* @deprecated Existing logic may remain unmigrated for now, but new calls are prohibited.\n\t* See the [Agent Note](../../../../.agents/notes/implemented/architecture/2026-09-09-deprecate-synchronous-session-event-reads.md).\n\t* @param fromSeq - non-negative inclusive sequence number; defaults to the log start.\n\t* @param toSeqExclusive - non-negative exclusive sequence number; defaults to the current end.\n\t* @returns a frozen array of the selected deeply frozen events.\n\t*/\n\tsnapshotEvents(fromSeq = SessionLogOffset(0), toSeqExclusive = this.seq) {\n\t\tif (fromSeq === 0 && toSeqExclusive === this.log.length) {\n\t\t\tthis.eventsSnapshot ??= Object.freeze([...this.log]);\n\t\t\treturn this.eventsSnapshot;\n\t\t}\n\t\treturn Object.freeze(this.log.slice(fromSeq, toSeqExclusive));\n\t}\n\t/**\n\t* Return this Session's events after its fork-inherited prefix.\n\t* @deprecated Existing logic may remain unmigrated for now, but new calls are prohibited.\n\t* See the [Agent Note](../../../../.agents/notes/implemented/architecture/2026-09-09-deprecate-synchronous-session-event-reads.md).\n\t* @returns a fresh array containing child-owned events in log order.\n\t*/\n\townEvents() {\n\t\treturn this.snapshotEvents(this.inheritedEventCount);\n\t}\n\t/**\n\t* Whether one existing event position is outside the fork-inherited prefix.\n\t* @param seq - event position in this Session.\n\t* @returns true when the event belongs to this Session rather than its parent.\n\t*/\n\tisOwnSeq(seq) {\n\t\treturn seq >= this.inheritedEventCount && seq < this.seq;\n\t}\n\t/** The next event's sequence number — always the log length (the `seq = log.length` contiguity contract). */\n\tget seq() {\n\t\treturn SessionLogOffset(this.log.length);\n\t}\n\t/**\n\t* Append one typed event to the log and synchronously notify observers via\n\t* the store-owned, module-private publication hooks. The hot path never blocks\n\t* on I/O — persistence plugins buffer asynchronously. Once the event enters\n\t* the log, the append is committed: observer failures are logged and\n\t* contained per listener, so they do not change the return value or prevent\n\t* later listeners from observing the same accepted event.\n\t*\n\t* @param type - The event type (key of {@link SessionEventMap}).\n\t* @param data - The event payload; must be JSON-serializable.\n\t* @param opts - Surface metadata: `surfaceOp` controls how the event enters\n\t* the ordered surface; `sourceEventSeqs` lists the seq numbers of earlier\n\t* events this one derives from. REQUIRED for\n\t* {@link SurfaceEventType} events (every message-producing event must\n\t* declare how it joins the surface, the sole source of derived model\n\t* history) and\n\t* rejected by the compiler for non-surface types like `turn/start` or\n\t* `assistant/attempt`. Assistant messages embed their exact provider\n\t* stream and cannot cite top-level source events.\n\t* @returns the logged event — its assigned `seq`/`time` plus the SNAPSHOT of\n\t* `data` that entered the log, so reading `event.data` back sees the logged\n\t* value, never the caller's still-mutable input.\n\t* @throws if `data` or surface metadata is not losslessly JSON-serializable\n\t* (BigInt, function, symbol, undefined, negative zero, non-finite number,\n\t* circular reference, sparse array, or an exotic object such as\n\t* Map/Set/Date/class instance), or when the candidate violates the\n\t* request-header empty-field or tool-error consistency rules, or the\n\t* canonical surface contract (marker shape and eligibility, unique\n\t* earlier source-event references, positional replacement validity, and complete\n\t* shadowed-node coverage). One iterative pass reads, validates, and\n\t* copies each nested value once, so a stateful getter cannot supply one value\n\t* to validation and another to storage. The event log is the durable source\n\t* of truth, so a bad event fails at the append site rather than later during\n\t* a backend flush. A synchronous internal dispatch validation failure or an\n\t* append reentered while this acceptance/publication boundary is open also\n\t* rejects before the log changes.\n\t*/\n\tappend(type, data, ...opts) {\n\t\tconst surfaceOpts = opts[0];\n\t\tconst surfaceMetadata = {\n\t\t\t...surfaceOpts?.sourceEventSeqs === void 0 ? {} : { sourceEventSeqs: surfaceOpts.sourceEventSeqs },\n\t\t\t...surfaceOpts?.surfaceOp === void 0 ? {} : { surfaceOp: surfaceOpts.surfaceOp }\n\t\t};\n\t\tconst dataSnapshot = snapshotJsonValue(data);\n\t\tif (dataSnapshot === void 0) throw new Error(`session event \"${type}\" carries non-JSON-serializable data`);\n\t\tconst surfaceMetadataSnapshot = snapshotJsonValue(surfaceMetadata);\n\t\tif (surfaceMetadataSnapshot === void 0) throw new Error(`session event \"${type}\" carries non-JSON-serializable surface metadata`);\n\t\tconst entry = this.publicationEntry();\n\t\tconst event = deepFreeze({\n\t\t\ttype,\n\t\t\tseq: SessionSeq(this.log.length),\n\t\t\ttime: Date.now(),\n\t\t\tdata: dataSnapshot,\n\t\t\t...surfaceMetadataSnapshot\n\t\t});\n\t\tvalidateSessionEventData(event, `session event \"${type}\" at seq ${event.seq}`);\n\t\tthis.commit(event, entry);\n\t\treturn event;\n\t}\n\tstatic {\n\t\tcommitPluginRecord = (session, type, data) => session.#appendRecord(type, data);\n\t}\n\t/**\n\t* Commit one plugin record; {@link appendPluginRecord} is the only caller.\n\t* @param type - record type, checked against the plugin record grammar.\n\t* @param data - JSON payload, snapshotted before it enters the log.\n\t* @returns the record's sequence number.\n\t*/\n\t#appendRecord(type, data) {\n\t\tconst dataSnapshot = snapshotJsonValue(data);\n\t\tif (dataSnapshot === void 0) throw new Error(`plugin record \"${type}\" carries non-JSON-serializable data`);\n\t\tconst entry = this.publicationEntry();\n\t\tconst record = deepFreeze({\n\t\t\ttype,\n\t\t\tseq: SessionSeq(this.log.length),\n\t\t\ttime: Date.now(),\n\t\t\tdata: dataSnapshot,\n\t\t\tignorable: true\n\t\t});\n\t\tassertPluginRecordEvent(record);\n\t\tthis.commit(record, entry);\n\t\treturn record.seq;\n\t}\n\t/**\n\t* Read the store attachment for one append, refusing an append that\n\t* reenters while another append is being published.\n\t* @returns the attachment, or undefined for a detached Session.\n\t*/\n\tpublicationEntry() {\n\t\tconst entry = attachments.get(this);\n\t\tif (entry?.appending) throw new Error(\"session append cannot reenter while another append is being published\");\n\t\treturn entry;\n\t}\n\t/**\n\t* Accept one frozen candidate at the next sequence number, enter it into the\n\t* log, and notify `session/event` observers with per-listener containment.\n\t* @param event - the candidate built at the current log length.\n\t* @param entry - the attachment read before the candidate was built.\n\t*/\n\tcommit(event, entry) {\n\t\tthis.surfaceManager.validateNext(event);\n\t\tif (entry !== void 0) entry.appending = true;\n\t\ttry {\n\t\t\tlet callbacks;\n\t\t\tconst callbackArgs = [this, event];\n\t\t\tif (entry !== void 0) callbacks = collectSessionCallbacks(entry.emitCtx, [\n\t\t\t\tentry.carrier,\n\t\t\t\t\"session/event\",\n\t\t\t\t...callbackArgs\n\t\t\t]);\n\t\t\tthis.log.push(event);\n\t\t\tthis.eventsSnapshot = void 0;\n\t\t\tif (callbacks !== void 0 && entry !== void 0) invokeContainedSessionObservers(entry.emitCtx, \"session/event\", entry.id, callbackArgs, callbacks);\n\t\t} finally {\n\t\t\tif (entry !== void 0) {\n\t\t\t\tentry.appending = false;\n\t\t\t\tif (entry.detachRequested && !entry.announcing) entry.detach();\n\t\t\t}\n\t\t}\n\t}\n\t/** Cached fold of the request-header events — see {@link requestHeader}. */\n\theaderFold;\n\t/** Log position (events consumed) the header fold has reached. */\n\theaderFoldSeq = 0;\n\t/**\n\t* The {@link EpochHeader} in force after the log's last header event — the\n\t* header the NEXT request will be compared against — or undefined before\n\t* the first `request/header` snapshot. The live, incrementally-maintained\n\t* form of `foldRequestHeader(session.snapshotEvents())`: each header event is folded\n\t* once, when first seen, so a per-step read costs O(new events).\n\t* @returns the folded header, or undefined when no header event exists yet.\n\t*/\n\trequestHeader() {\n\t\tif (this.headerFoldSeq < this.log.length) {\n\t\t\tthis.headerFold = deepFreeze(foldRequestHeader(this.log.slice(this.headerFoldSeq), this.headerFold));\n\t\t\tthis.headerFoldSeq = this.log.length;\n\t\t}\n\t\treturn this.headerFold;\n\t}\n\t/** Cached fold of `request/context` events. */\n\tcontextFold;\n\tcontextFoldSeq = 0;\n\t/**\n\t* Return the latest resolved route metadata, or `undefined` before the first\n\t* `request/context` event. Each event is folded once.\n\t* @returns the latest immutable route metadata.\n\t*/\n\trequestContext() {\n\t\tif (this.contextFoldSeq < this.log.length) {\n\t\t\tfor (const event of this.log.slice(this.contextFoldSeq)) if (event.type === \"request/context\") this.contextFold = deepFreeze({ ...event.data });\n\t\t\tthis.contextFoldSeq = this.log.length;\n\t\t}\n\t\treturn this.contextFold;\n\t}\n\t/** Cached historical tool definitions and updates for request projection. */\n\ttoolHistoryProjection = new ToolHistoryProjection();\n\t/** Index of the next committed event not yet consumed by the tool-history fold. */\n\ttoolHistorySeq = 0;\n\t/**\n\t* Fold unseen committed events into capability-independent tool history.\n\t* Initial access reconstructs inherited history; later reads consume only new events.\n\t* @returns an immutable snapshot for LLM request projection, including historical addition definitions.\n\t*/\n\ttoolHistory() {\n\t\tfor (const event of this.log.slice(this.toolHistorySeq)) this.toolHistoryProjection.apply(event);\n\t\tthis.toolHistorySeq = this.log.length;\n\t\treturn this.toolHistoryProjection.snapshot();\n\t}\n\t/** The derived-message cache: frozen projections, extended per unseen node. */\n\tderived = [];\n\t/** Surface position (nodes projected) the cache has reached. */\n\tderivedNodes = 0;\n\t/** {@link SurfaceManager.contentGeneration} the cache was built under. */\n\tderivedGeneration = 0;\n\t/**\n\t* Derive the LLM message history by walking the ordered sequences of\n\t* message-producing events maintained by `surfaceOp` markers. The\n\t* surface is the single source of derived history: every message-producing\n\t* append records its `surfaceOp`, so a raw event with no marker (a chunk, a\n\t* turn boundary) is correctly absent, and a compaction `replace` deletes the\n\t* shadowed nodes from the derivation. The projection rules are\n\t* {@link deriveEventMessage}, with logged message projections applied\n\t* without changing node membership or message identity.\n\t*\n\t* CACHED: pure tail growth costs O(new nodes); a replacement or message projection\n\t* ({@link SessionSurface.contentGeneration}) rebuilds. The returned array is\n\t* a fresh snapshot per call (later appends never grow an array a caller\n\t* already holds); the `Message` objects in it are SHARED and **deep-frozen**.\n\t* Unchanged content reuses frozen event data; projected blocks are frozen\n\t* derived copies. Consumers cannot mutate the log through either form.\n\t* @returns a fresh array of the shared, frozen derived history.\n\t*/\n\tderiveMessages() {\n\t\tconst surface = this.surface;\n\t\tconst nodes = surface.nodes;\n\t\tconst generation = surface.contentGeneration;\n\t\tif (generation !== this.derivedGeneration) {\n\t\t\tthis.derived = [];\n\t\t\tthis.derivedNodes = 0;\n\t\t\tthis.derivedGeneration = generation;\n\t\t}\n\t\tfor (const seq of nodes.slice(this.derivedNodes)) {\n\t\t\tconst msg = this.deriveEventMessage(this.log[seq]);\n\t\t\tif (msg) this.derived.push(msg);\n\t\t}\n\t\tthis.derivedNodes = nodes.length;\n\t\treturn [...this.derived];\n\t}\n\t/**\n\t* Project one event with all committed message projections applied.\n\t* The original durable event remains unchanged.\n\t* @param event - the event to project.\n\t* @returns the derived message, or null when the event produces none.\n\t*/\n\tderiveEventMessage(event) {\n\t\treturn this.surfaceManager.deriveEventMessage(event);\n\t}\n};\n/** Typed error for session fork rejections. */\nvar SessionForkError = class extends Error {\n\tcode;\n\tconstructor(message, code) {\n\t\tsuper(message);\n\t\tthis.code = code;\n\t\tthis.name = \"SessionForkError\";\n\t}\n};\n/**\n* In-memory session store (`ctx.sessions`).\n*\n* Persistence is intentionally not implemented here — the agent lifecycle\n* attaches a session-log writer to each published session's write handle;\n* a session published outside that lifecycle persists nothing.\n*/\nvar SessionStore = class extends Service {\n\tstore = /* @__PURE__ */ new Map();\n\tcounter = 0;\n\tprojections = [];\n\t/** Borrowed definitions for detached replay; contributions live until their registering fibers unload. */\n\tget messageProjections() {\n\t\treturn this.projections;\n\t}\n\t/**\n\t* Register one event interpreter for live creation, restore, and fork.\n\t* Disposing the contribution makes sessions that used it refuse further derivation.\n\t* @param projection - pure definition owned by the event's plugin.\n\t* @returns the fiber-owned disposer.\n\t* @throws when another definition already owns this event type.\n\t*/\n\tregisterMessageProjection(projection) {\n\t\tif (this.projections.some((item) => item.type === projection.type)) throw new Error(`session message projection \"${projection.type}\" is already registered`);\n\t\treturn this.ctx.effect(() => {\n\t\t\tthis.projections.push(projection);\n\t\t\treturn () => {\n\t\t\t\tthis.projections.splice(this.projections.indexOf(projection), 1);\n\t\t\t};\n\t\t}, \"sessions.registerMessageProjection()\");\n\t}\n\tconstructor(ctx) {\n\t\tsuper(ctx, \"sessions\");\n\t\tctx.inject([\"typert\"], (typeCtx) => {\n\t\t\ttypeCtx.typert.lookups.register(\"session\", {\n\t\t\t\tparameter: \"session\",\n\t\t\t\twire: \"sessionId\",\n\t\t\t\tresource: \"session\",\n\t\t\t\thostTypeSymbol: \"@deepseek-ai/dsh-session#Session\",\n\t\t\t\twireTypeSymbol: \"@deepseek-ai/dsh-session/types#SessionId\",\n\t\t\t\tresolve: (sessionId) => this.get(sessionId)\n\t\t\t});\n\t\t});\n\t}\n\t/**\n\t* Create a session owned by the calling fiber: disposing that fiber stops\n\t* event notification and removes the session from the store. `options.seed`\n\t* populates the session with a copy of those events (replay/fork);\n\t* `options.meta` attaches creation metadata (validated absolute `cwd`, seed\n\t* and parent lineage, and delegation depth) as the immutable\n\t* {@link SessionHeader} (the store fills `version`/`id`/`createdAt`).\n\t*\n\t* For an agent whose session must be torn down IN ORDER with its loop (so the\n\t* loop's final events are published before the store attachment ends), do NOT use this\n\t* — fold the session lifecycle into the agent's own effect via\n\t* {@link prepare} + {@link enter} + {@link announce} (see\n\t* `dsh-agent-loop`'s creation transaction).\n\t*\n\t* @param id - the session id; omitted, the store mints `session-<n>`.\n\t* @param options - seed events and/or creation metadata for the header.\n\t* @returns the live session, already entered and announced.\n\t* @throws if a session with `id` already exists, metadata is not a plain\n\t* lossless-JSON record with valid scalar fields, or `meta.cwd` is a\n\t* non-absolute path (storage backends key directories off it).\n\t*/\n\tcreate(id, options) {\n\t\tconst session = this.prepare(id, options);\n\t\tthis.ctx.effect(function* () {\n\t\t\tyield this.enter(session);\n\t\t\tthis.announce(session);\n\t\t}.bind(this), \"sessions.create()\");\n\t\treturn session;\n\t}\n\t/**\n\t* Build a session WITHOUT entering it into the store — validate the id/cwd and\n\t* construct the {@link Session} (with its immutable {@link SessionHeader}).\n\t* Pairs with {@link enter} + {@link announce}: a caller that owns a composite\n\t* `ctx.effect` (the agent factory) folds the session lifecycle into that ONE\n\t* effect so a fiber unload tears the session + agent down as a single ORDERED\n\t* chain rather than as racing sibling effects — which would remove the publication hooks\n\t* before the driver's closing events commit, dropping them.\n\t*\n\t* @param id - the session id; omitted, the store mints `session-<n>`.\n\t* @param options - seed events and/or creation metadata for the header. With\n\t* `eventState`, every seed event is either independently owned or any\n\t* shared value is deeply frozen; {@link Session.fromRestore} validates and\n\t* adopts those values without copying or freezing them.\n\t* @returns the constructed session, NOT yet in the store.\n\t* @throws if a session with `id` already exists, metadata is not a plain\n\t* lossless-JSON record with valid scalar fields, or `meta.cwd` is a\n\t* non-absolute path.\n\t*/\n\tprepare(id, options) {\n\t\tlet sessionId;\n\t\tif (id === void 0) do\n\t\t\tsessionId = brandString(`session-${++this.counter}`);\n\t\twhile (this.store.has(sessionId));\n\t\telse sessionId = brandString(id);\n\t\tif (this.store.has(sessionId)) throw new Error(`session \"${sessionId}\" already exists`);\n\t\tif (options !== void 0) {\n\t\t\tconst { eventState } = options;\n\t\t\tswitch (eventState) {\n\t\t\t\tcase \"detached\":\n\t\t\t\tcase \"shared-frozen\": return Session.fromRestore(sessionId, options.seed, options.meta, options.inheritedEventCount, eventState, this.projections);\n\t\t\t\tcase void 0: break;\n\t\t\t\t/* v8 ignore next -- closed-union exhaustiveness guard */\n\t\t\t\tdefault: assertNever(eventState, \"SessionStore.prepare event state\");\n\t\t\t}\n\t\t}\n\t\tconst seed = options?.seed;\n\t\tconst meta = options?.meta;\n\t\tconst header = {\n\t\t\tversion: 4,\n\t\t\tid: sessionId,\n\t\t\tcreatedAt: meta?.createdAt ?? Date.now(),\n\t\t\t...meta?.cwd === void 0 ? {} : { cwd: meta.cwd },\n\t\t\t...meta?.parentSession === void 0 ? {} : { parentSession: meta.parentSession },\n\t\t\tisSeeded: meta?.isSeeded ?? false,\n\t\t\t...meta?.origin === void 0 ? {} : { origin: meta.origin },\n\t\t\t...meta?.delegationDepth === void 0 ? {} : { delegationDepth: meta.delegationDepth },\n\t\t\t...meta?.agentPreset === void 0 ? {} : { agentPreset: meta.agentPreset }\n\t\t};\n\t\treturn Session.create(sessionId, seed, header, options?.inheritedEventCount, this.projections);\n\t}\n\t/**\n\t* Enter a {@link prepare}d session into the store: install the module-private\n\t* append publication hooks and add it to the store. Returns the DETACH\n\t* disposer (hooks + store removal). Does NOT emit `session/created` —\n\t* the caller yields this disposer inside its effect and THEN calls\n\t* {@link announce}, so a throwing `session/created` listener rolls the attach\n\t* back instead of leaking it.\n\t*\n\t* Re-checks the id for a duplicate: `prepare` and `enter` are public\n\t* cross-package primitives and a caller may interleave arbitrary work (or\n\t* another create) between them, so a stale prepared session must NOT overwrite\n\t* a live store entry of the same id — its detach disposer would later delete\n\t* the REAL session. The {@link create} convenience and the agent factory call\n\t* the two back-to-back so they never trip this, but the public API cannot\n\t* assume that.\n\t*\n\t* @param session - a {@link prepare}d session not yet in the store.\n\t* @returns the detach disposer (publication hooks + store removal). When called from\n\t* a synchronous `session/created` listener, removal and disposal wait until\n\t* that creation dispatch unwinds.\n\t* @throws if a session with this id is already in the store.\n\t*/\n\tenter(session) {\n\t\tconst id = session.id;\n\t\tconst carrier = scopeTarget(session, scopeOf(this.ctx));\n\t\tif (this.store.has(id)) throw new Error(`session \"${id}\" already exists`);\n\t\tif (attachments.has(session)) throw new Error(`session \"${id}\" is already attached to a store`);\n\t\tconst entry = {\n\t\t\tid,\n\t\t\tsession,\n\t\t\tcarrier,\n\t\t\temitCtx: this.ctx,\n\t\t\tannounced: false,\n\t\t\tannouncing: false,\n\t\t\tappending: false,\n\t\t\tdetachRequested: false,\n\t\t\tdetach: () => {\n\t\t\t\tthis.detachEntered(entry);\n\t\t\t}\n\t\t};\n\t\tthis.store.set(id, entry);\n\t\tattachments.set(session, entry);\n\t\tlet entered = true;\n\t\tconst detach = () => {\n\t\t\tif (!entered) return;\n\t\t\tentered = false;\n\t\t\tif (entry.announcing || entry.appending) {\n\t\t\t\tentry.detachRequested = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tentry.detach();\n\t\t};\n\t\treturn detach;\n\t}\n\t/** Remove one exact entered session and emit its paired disposal when announced. */\n\tdetachEntered(entry) {\n\t\tentry.detachRequested = false;\n\t\t/* v8 ignore next -- enter() rejects replacement while this single-shot detach capability is live. */\n\t\tif (this.store.get(entry.id) !== entry) return;\n\t\tthis.store.delete(entry.id);\n\t\tattachments.delete(entry.session);\n\t\tif (entry.announced) this.emitDisposed(entry);\n\t}\n\t/** Emit `session/created` exactly once for an {@link enter}ed session (with\n\t* the carrier {@link enter} captured). Separate from {@link enter} so the\n\t* caller can yield the detach disposer first (rollback safety — see\n\t* {@link enter}).\n\t* @param session - the entered session to announce to listeners.\n\t* @throws if the session is not live or its announcement already began,\n\t* including a reentrant call from a creation listener. */\n\tannounce(session) {\n\t\tconst entry = this.liveEntryFor(session);\n\t\tif (entry.announced || entry.announcing) throw new Error(`session \"${entry.id}\" was already announced`);\n\t\tentry.announced = true;\n\t\tconst callbackArgs = [session];\n\t\tentry.announcing = true;\n\t\ttry {\n\t\t\tconst callbacks = collectSessionCallbacks(this.ctx, [\n\t\t\t\tentry.carrier,\n\t\t\t\t\"session/created\",\n\t\t\t\tsession\n\t\t\t]);\n\t\t\tfor (const callback of callbacks) {\n\t\t\t\tconst returned = callback(...callbackArgs);\n\t\t\t\tPromise.resolve(returned).catch((error) => {\n\t\t\t\t\tthis.ctx.logger.warn(`session \"${entry.id}\": session/created listener rejected: ${String(error)}`);\n\t\t\t\t});\n\t\t\t}\n\t\t} finally {\n\t\t\tentry.announcing = false;\n\t\t\tif (entry.detachRequested && !entry.appending) entry.detach();\n\t\t}\n\t}\n\t/** Emit the paired teardown notification with per-listener containment. */\n\temitDisposed(entry) {\n\t\tconst callbackArgs = [entry.session];\n\t\ttry {\n\t\t\tconst callbacks = collectSessionCallbacks(this.ctx, [\n\t\t\t\tentry.carrier,\n\t\t\t\t\"session/disposed\",\n\t\t\t\tentry.session\n\t\t\t]);\n\t\t\tinvokeContainedSessionObservers(this.ctx, \"session/disposed\", entry.id, callbackArgs, callbacks);\n\t\t} catch (error) {\n\t\t\tthis.ctx.logger.warn(`session \"${entry.id}\": session/disposed dispatch threw: ${String(error)}`);\n\t\t}\n\t}\n\t/**\n\t* Dispatch the awaited `session/flush` durability checkpoint for `session`,\n\t* with the carrier captured at {@link enter}. THE flush entry point: the\n\t* store owns the carrier, so callers (the checkpoint policy's per-request\n\t* barrier, goal-round-driver's idle checkpoint, teardown drains, and consumers\n\t* that flush themselves before reading storage) must come through here\n\t* rather than dispatch a raw `ctx.parallel('session/flush', …)` — one owner\n\t* and one spelling.\n\t* @param session - the session whose buffered events must reach durable storage.\n\t* @returns whether at least one durability listener participated, after every\n\t* listener has settled successfully.\n\t* @throws the first registered listener failure after every listener settles.\n\t*/\n\tasync flush(session) {\n\t\tconst { carrier } = this.liveEntryFor(session);\n\t\tconst callbackArgs = [session];\n\t\tconst callbacks = collectSessionCallbacks(this.ctx, [\n\t\t\tcarrier,\n\t\t\t\"session/flush\",\n\t\t\tsession\n\t\t]);\n\t\tconst failure = (await Promise.allSettled(callbacks.map((callback) => {\n\t\t\ttry {\n\t\t\t\treturn callback(...callbackArgs);\n\t\t\t} catch (error) {\n\t\t\t\treturn Promise.reject(error);\n\t\t\t}\n\t\t}))).find((result) => result.status === \"rejected\");\n\t\tif (failure !== void 0) throw failure.reason;\n\t\treturn callbacks.length > 0;\n\t}\n\t/** Return the exact live entry; detached/prepared objects reject. */\n\tliveEntryFor(session) {\n\t\tconst entry = attachments.get(session);\n\t\tif (entry === void 0 || this.store.get(entry.id) !== entry) throw new Error(`session \"${session.id}\" is not live in this store`);\n\t\treturn entry;\n\t}\n\t/**\n\t* Look up a live session.\n\t* @param id - the session id to look up.\n\t* @returns the session, or undefined when no live session has that id.\n\t*/\n\tget(id) {\n\t\treturn this.store.get(id)?.session;\n\t}\n\t/**\n\t* All live sessions, in creation order.\n\t* @returns a fresh array; mutating it does not affect the store.\n\t*/\n\tlist() {\n\t\treturn [...this.store.values()].map((entry) => entry.session);\n\t}\n\t/**\n\t* Create a live child session from an exact prefix of a live source.\n\t* `boundary` is an inclusive source event seq; omitted means the source's\n\t* current last event. An open tail receives synthetic tool results and\n\t* step/turn closers with the forked cause. Closed steps and turns remain\n\t* unchanged, including any failed tool calls already missing results.\n\t* `inheritedEventCount` counts only copied source events, excluding these closers.\n\t*\n\t* @param source - Live source session object or id.\n\t* @param boundary - Inclusive source event seq to fork through; omitted means\n\t* the source's current last event, and omitted on an empty source forks an\n\t* empty child.\n\t* @param childSessionId - Optional child session id; omitted delegates to\n\t* `SessionStore`'s id policy.\n\t* @returns The created live child session.\n\t*/\n\tfork(source, boundary, childSessionId) {\n\t\tif (childSessionId !== void 0 && this.get(childSessionId) !== void 0) throw new SessionForkError(`session \"${childSessionId}\" already exists`, \"SESSION_ALREADY_EXISTS\");\n\t\tconst liveSource = this._resolveForkSource(source);\n\t\tconst events = liveSource.snapshotEvents();\n\t\tconst resolved = this._forkBoundary(liveSource.id, events, boundary);\n\t\tconst seed = resolved === void 0 ? [] : buildForkSeed(events, resolved);\n\t\treturn this.create(childSessionId, {\n\t\t\tseed,\n\t\t\tinheritedEventCount: SessionLogOffset(resolved === void 0 ? 0 : resolved + 1),\n\t\t\tmeta: {\n\t\t\t\t...liveSource.header.cwd !== void 0 ? { cwd: liveSource.header.cwd } : {},\n\t\t\t\tparentSession: liveSource.id,\n\t\t\t\tisSeeded: true\n\t\t\t}\n\t\t});\n\t}\n\t_forkBoundary(sessionId, events, requestedBoundary) {\n\t\tconst lastEvent = events.at(-1);\n\t\tlet boundary;\n\t\tif (requestedBoundary !== void 0) boundary = requestedBoundary;\n\t\telse {\n\t\t\tif (lastEvent === void 0) return void 0;\n\t\t\tboundary = lastEvent.seq;\n\t\t}\n\t\tif (!Number.isSafeInteger(boundary) || boundary < 0) throw new SessionForkError(`fork boundary for session \"${sessionId}\" must be a non-negative safe integer, got ${String(boundary)}`, \"INVALID_BOUNDARY\");\n\t\tif (boundary >= events.length) {\n\t\t\tconst lastSeq = lastEvent?.seq;\n\t\t\tthrow new SessionForkError(`fork boundary ${boundary} does not exist in session \"${sessionId}\" (last seq: ${lastSeq ?? \"none\"})`, \"INVALID_BOUNDARY\");\n\t\t}\n\t\tconst boundaryEvent = events[boundary];\n\t\tif (boundaryEvent === void 0 || boundaryEvent.seq !== boundary) throw new SessionForkError(`fork boundary ${boundary} does not match a contiguous event seq in session \"${sessionId}\"`, \"INVALID_BOUNDARY\");\n\t\treturn boundary;\n\t}\n\t_resolveForkSource(source) {\n\t\tif (typeof source === \"string\") {\n\t\t\tconst session = this.get(source);\n\t\t\tif (session === void 0) throw new SessionForkError(`session \"${source}\" not found`, \"SESSION_NOT_FOUND\");\n\t\t\treturn session;\n\t\t}\n\t\tconst live = this.get(source.id);\n\t\tif (live === void 0) throw new SessionForkError(`session \"${source.id}\" not found`, \"SESSION_NOT_FOUND\");\n\t\tif (live !== source) throw new SessionForkError(`session \"${source.id}\" is not the live store instance`, \"SESSION_NOT_LIVE\");\n\t\treturn source;\n\t}\n};\n//#endregion\nexport { KNOWN_SESSION_EVENT_TYPES, SESSION_FORMAT_VERSION, Session, SessionForkError, SessionId, SessionLogOffset, SessionPreparation, SessionSeq, SessionStore, SessionStore as default, TOOL_NOT_STARTED, TOOL_OUTCOME_UNKNOWN, ToolCallRecovery, adoptSessionEvent, appendPluginRecord, buildForkSeed, canonicalHeader, decodeSeqRanges, deriveEventMessage, encodeSeqRanges, foldRequestHeader, foldSurface, headerEquals, interruptedTurnClosers, isAppendSurfaceEvent, isReplacementSurfaceEvent, isSurfaceEligibleType, isSurfaceEvent, pluginRecordOf, snapshotSessionEvent };\n","import { Service } from \"@deepseek-ai/cordis\";\nimport { KNOWN_SESSION_EVENT_TYPES, SESSION_FORMAT_VERSION, adoptSessionEvent } from \"@deepseek-ai/dsh-session\";\nimport { snapshotJsonValue } from \"@deepseek-ai/dsh-util-values\";\n//#region lib/types/revision.js\n/** Opaque revision identity for lightweight persistence observations. */\n/**\n* Brand a backend revision for the provider-neutral persistence contract.\n* @param value - backend-owned opaque revision representation.\n* @returns the same runtime string with persistence-revision identity.\n*/\nfunction SessionPersistenceRevision(value) {\n\treturn value;\n}\n//#endregion\n//#region lib/types/errors.js\n/**\n* Stable failures exposed by the session-persistence service and its handles,\n* including the format refusals shared by every backend: a stored log this\n* build cannot faithfully interpret is refused, never misread, and the\n* refusal points at the raw artifact when the backend keeps one per session.\n* @module @deepseek-ai/dsh-session-persistence/errors\n*/\n/** The requested Session identity has no durable log visible to this caller. */\nvar SessionPersistenceNotFoundError = class extends Error {\n\tsessionId;\n\t/** @param sessionId - absent durable Session identity. */\n\tconstructor(sessionId) {\n\t\tsuper(`session \"${sessionId}\" not found`);\n\t\tthis.sessionId = sessionId;\n\t\tthis.name = \"SessionPersistenceNotFoundError\";\n\t}\n};\n/** `create` targeted a Session identity that already exists in this backend. */\nvar SessionAlreadyExistsError = class extends Error {\n\tsessionId;\n\t/** @param sessionId - the occupied durable Session identity. */\n\tconstructor(sessionId) {\n\t\tsuper(`session \"${sessionId}\" already exists`);\n\t\tthis.sessionId = sessionId;\n\t\tthis.name = \"SessionAlreadyExistsError\";\n\t}\n};\n/** A write open found the session already bound to an active write handle. */\nvar SessionAlreadyOwnedError = class extends Error {\n\tsessionId;\n\t/** @param sessionId - the session whose write ownership is taken. */\n\tconstructor(sessionId) {\n\t\tsuper(`session \"${sessionId}\" is already owned by an active write handle`);\n\t\tthis.sessionId = sessionId;\n\t\tthis.name = \"SessionAlreadyOwnedError\";\n\t}\n};\n/** A mutation (`append`/`flush`) was called on a read handle. */\nvar SessionReadOnlyError = class extends Error {\n\tsessionId;\n\t/**\n\t* @param sessionId - the session the read handle observes.\n\t* @param operation - the refused mutating operation name.\n\t*/\n\tconstructor(sessionId, operation) {\n\t\tsuper(`session \"${sessionId}\": ${operation} is not available on a read handle`);\n\t\tthis.sessionId = sessionId;\n\t\tthis.name = \"SessionReadOnlyError\";\n\t}\n};\n/**\n* A write handle's ownership is permanently gone: its lease expired, a renewal\n* failed, or the durable ownership record no longer names this handle. The\n* handle never re-acquires ownership — close it and reopen for write.\n*\n* Declared for the cross-process lease layer; the shipped in-process backends\n* never throw it yet.\n*/\nvar SessionOwnershipLostError = class extends Error {\n\tsessionId;\n\t/** @param sessionId - the session whose write ownership this handle lost. */\n\tconstructor(sessionId) {\n\t\tsuper(`session \"${sessionId}\": write ownership was lost; close this handle and reopen`);\n\t\tthis.sessionId = sessionId;\n\t\tthis.name = \"SessionOwnershipLostError\";\n\t}\n};\n/** An operation was called on a handle after `close()` was called. */\nvar SessionHandleClosedError = class extends Error {\n\tsessionId;\n\t/**\n\t* @param sessionId - the session the closed handle addressed.\n\t* @param operation - the refused operation name.\n\t*/\n\tconstructor(sessionId, operation) {\n\t\tsuper(`session \"${sessionId}\": ${operation} on a closed handle`);\n\t\tthis.sessionId = sessionId;\n\t\tthis.name = \"SessionHandleClosedError\";\n\t}\n};\n/** Durable session contents failed validation after a successful backend read. */\nvar SessionPersistenceCorruptionError = class extends Error {\n\t/**\n\t* @param message - stable corruption context.\n\t* @param options - original validation failure.\n\t*/\n\tconstructor(message, options) {\n\t\tsuper(message, options);\n\t\tthis.name = \"SessionPersistenceCorruptionError\";\n\t}\n};\n/**\n* The stored log is intact but this runtime cannot faithfully interpret it:\n* the header carries an unsupported format version, or an event's type is\n* unknown to this build. Distinct from {@link SessionPersistenceCorruptionError}\n* — nothing is damaged; the raw log remains readable at {@link location} when\n* the backend keeps one artifact per session.\n*/\nvar SessionFormatUnsupportedError = class extends Error {\n\tlocation;\n\t/**\n\t* @param message - stable reason the log cannot be interpreted, already\n\t* including the raw-log path when one exists.\n\t* @param location - the backend's artifact location, when one exists.\n\t*/\n\tconstructor(message, location) {\n\t\tsuper(message);\n\t\tthis.location = location;\n\t\tthis.name = \"SessionFormatUnsupportedError\";\n\t}\n};\n/**\n* Direction-aware refusal text for a stored session whose format version this\n* build does not read. Shared by load-time checks and by backends that must\n* refuse BEFORE decoding version-dependent structure (a future format may not\n* satisfy this build's structural checks at all, and the user must see\n* \"upgrade the harness\", never \"corrupt\").\n* @param id - the stored session id, for message context.\n* @param version - the stored format version.\n* @returns the stable refusal text, without a raw-log path suffix.\n*/\nfunction sessionFormatVersionRefusal(id, version) {\n\treturn version > SESSION_FORMAT_VERSION ? `session \"${id}\" uses log format v${version}, but this harness reads only v${SESSION_FORMAT_VERSION}: the log was written by a newer harness — upgrade the harness to open it` : `session \"${id}\" uses log format v${version}, older than the supported v${SESSION_FORMAT_VERSION}, and this build ships no upgrade path for it`;\n}\n//#endregion\n//#region lib/types/storage-contract.js\n/**\n* Backend-shared storage validation: the version gate, the fail-closed event\n* vocabulary, append-batch materialization, and contiguity — one place so\n* every backend refuses the same inputs identically.\n* @module @deepseek-ai/dsh-session-persistence/storage-contract\n*/\n/** Build a format refusal that points at the raw artifact when the backend has one. */\nfunction unsupported(reason, location) {\n\treturn new SessionFormatUnsupportedError(location === void 0 ? reason : `${reason} (raw log: ${location.path})`, location);\n}\n/**\n* Refuse stored metadata that is not bound to the requested session id.\n* @param id - the requested session id.\n* @param meta - the stored header.\n*/\nfunction assertStoredId(id, meta) {\n\tif (meta.id !== id) throw new Error(`stored session identity mismatch: requested \"${id}\", header contains \"${meta.id}\"`);\n}\n/**\n* Refuse a header that has not been restored to the current logical format.\n* @param meta - the stored header.\n* @param location - the backend's artifact location for the refusal, when one exists.\n*/\nfunction assertVersion(meta, location) {\n\tif (meta.version !== SESSION_FORMAT_VERSION) throw unsupported(sessionFormatVersionRefusal(meta.id, meta.version), location);\n}\n/**\n* Validate one exclusively owned stored event array in place: adopt each\n* record (validating and freezing it) and refuse any event type this build\n* does not know, unless its writer marked it `ignorable: true` — silently\n* skipping an unknown required event could reconstruct a wrong session (the\n* envelope contract on `SessionEvent.ignorable`). Unknown required types and\n* retired pre-release shapes refuse here; this validator performs no migration.\n* @param meta - the stored header the events belong to.\n* @param events - exclusively owned decoded events; validated in place.\n* @param location - the backend's artifact location for refusals, when one exists.\n* @returns the same array, validated and frozen.\n* @throws {SessionFormatUnsupportedError} for unknown event types.\n* @throws {SessionPersistenceCorruptionError} for records that fail validation.\n*/\nfunction validateStoredEvents(meta, events, location) {\n\tfor (const event of events) {\n\t\tif (!KNOWN_SESSION_EVENT_TYPES.has(event.type) && event.ignorable !== true) throw unsupported(`session \"${meta.id}\" contains event type \"${event.type}\" (seq ${event.seq}) unknown to this harness and not marked ignorable; refusing to interpret the log — it was likely written by a newer harness`, location);\n\t\tif (event.type === \"request/header\") {\n\t\t\tconst data = event.data;\n\t\t\tif (typeof data === \"object\" && data !== null && data[\"reason\"] === \"fallback\") throw unsupported(`session \"${meta.id}\" contains a request/header event (seq ${event.seq}) with the unsupported legacy reason \"fallback\"; refusing to interpret the log — it was written by a retired pre-release harness`, location);\n\t\t}\n\t}\n\ttry {\n\t\tfor (const [index, event] of events.entries()) events[index] = adoptSessionEvent(event);\n\t} catch (error) {\n\t\tif (error instanceof SessionFormatUnsupportedError) throw error;\n\t\tthrow new SessionPersistenceCorruptionError(`stored session \"${meta.id}\" failed validation: ${String(error)}`, { cause: error });\n\t}\n\treturn events;\n}\n/**\n* Validate and deep-snapshot a header passed to `create` in one traversal.\n* @param header - the caller's header.\n* @returns the detached lossless-JSON header.\n* @throws {TypeError} for non-JSON metadata or an invalid `createdAt`.\n*/\nfunction materializeCreateHeader(header) {\n\tconst snapshot = snapshotJsonValue(header);\n\tif (snapshot === void 0) throw new TypeError(\"session metadata must be losslessly JSON-serializable\");\n\tif (!Number.isSafeInteger(snapshot.createdAt) || snapshot.createdAt < 0) throw new TypeError(\"session metadata createdAt must be a non-negative safe integer\");\n\treturn snapshot;\n}\n/**\n* Validate and deep-snapshot one append batch in a single traversal, so the\n* checked value is exactly the value persisted (a check followed by a copy\n* could reread accessors into a different record).\n* @param events - the caller's batch.\n* @returns the detached lossless-JSON batch.\n* @throws {TypeError} when any event data is not losslessly JSON-serializable.\n*/\nfunction materializeAppendBatch(events) {\n\tconst batch = snapshotJsonValue(events);\n\tif (batch === void 0) throw new TypeError(\"session event batch is not losslessly JSON-serializable because it contains non-JSON-serializable data\");\n\treturn batch;\n}\n/**\n* Refuse a batch that does not contiguously continue the stored log.\n* @param id - the session the batch belongs to.\n* @param events - the batch, in seq order.\n* @param cursor - the stored next-seq.\n*/\nfunction assertContiguous(id, events, cursor) {\n\tfor (const [index, event] of events.entries()) if (event.seq !== cursor + index) throw new Error(`append seq mismatch for \"${id}\": expected ${cursor + index} at index ${index}, got ${event.seq}`);\n}\n//#endregion\n//#region lib/types/index.js\n/**\n* Durable session-persistence Service Definition (`ctx.sessionPersistence`). Backends store\n* {@link SessionEvent}s as the event-sourced log and carry non-replayable\n* {@link SessionHeader} metadata separately; callers address one stored\n* session through a {@link SessionHandle} obtained from `create`/`open`.\n* @module @deepseek-ai/dsh-session-persistence\n*/\n/**\n* Durable append-only session storage addressed through per-session handles.\n*\n* Storage semantics shared by every backend: events are contiguous from seq 0\n* and never rewritten; a torn physical tail is never returned to a reader and\n* is truncated by the write path before its first append; reads validate\n* current-format records only and refuse unknown vocabulary fail-closed.\n* `append` persists best-effort; `flush` — per handle or service-wide — is\n* the durability barrier.\n*\n* Visibility: a created session is observable through `stat`/`list`/`open`\n* in this process from the moment `create` resolves, even while a backend\n* defers physical materialization (a pure optimization); other processes see\n* the session only once it materializes, and a session that never\n* materialized before a crash never existed. `SessionHandle.flush` forces\n* materialization.\n*\n* Freshness: once an `append` or `flush` resolves, reads started afterwards\n* on this backend instance observe at least that prefix.\n*/\nvar SessionPersistence = class extends Service {\n\t/** Process-local instance identity, stable through Context proxies and distinct after service replacement. */\n\tidentity = Symbol(\"sessionPersistence\");\n\tconstructor(ctx) {\n\t\tsuper(ctx, \"sessionPersistence\");\n\t}\n};\n//#endregion\nexport { SessionAlreadyExistsError, SessionAlreadyOwnedError, SessionFormatUnsupportedError, SessionHandleClosedError, SessionOwnershipLostError, SessionPersistence, SessionPersistence as default, SessionPersistenceCorruptionError, SessionPersistenceNotFoundError, SessionPersistenceRevision, SessionReadOnlyError, assertContiguous, assertStoredId, assertVersion, materializeAppendBatch, materializeCreateHeader, sessionFormatVersionRefusal, validateStoredEvents };\n","import { chmodSync, closeSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { randomBytes } from 'node:crypto'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { isRecord, isNonNegativeSafeInteger } from './model.js'\nimport type { SyncRecordMetadata } from './model.js'\n\nconst MAX_EXPORT_CACHE_FILE_BYTES = 8 * 1024 * 1024\n\nexport interface PersistedSessionExportCacheEntry {\n fingerprint: string\n metadata: SyncRecordMetadata\n eventCount: number\n eventDigest: string\n inheritedEventCount: number\n}\n\ninterface PersistedExportCache {\n version: 1\n entries: Record<string, PersistedSessionExportCacheEntry>\n}\n\nfunction cacheHome(home?: string): string {\n return home ?? process.env.DSH_HOME ?? join(homedir(), '.dsh')\n}\n\nfunction atomicWrite(file: string, content: string): void {\n const dir = dirname(file)\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n const temporary = `${file}.${process.pid}.${randomBytes(8).toString('hex')}.tmp`\n let fd: number | undefined\n try {\n fd = openSync(temporary, 'wx', 0o600)\n writeFileSync(fd, content, 'utf8')\n fsyncSync(fd)\n closeSync(fd)\n fd = undefined\n renameSync(temporary, file)\n chmodSync(file, 0o600)\n } catch (error) {\n if (fd !== undefined) closeSync(fd)\n try {\n unlinkSync(temporary)\n } catch {}\n throw error\n }\n}\n\nfunction validRevision(value: unknown): boolean {\n return isRecord(value) && isNonNegativeSafeInteger(value.physicalTimeMs) &&\n isNonNegativeSafeInteger(value.logicalCounter) && typeof value.writerInstanceId === 'string' && !!value.writerInstanceId\n}\n\nfunction validEntry(value: unknown): value is PersistedSessionExportCacheEntry {\n if (!isRecord(value) || typeof value.fingerprint !== 'string' || !/^sha256:[a-f0-9]{64}$/.test(value.fingerprint) ||\n !isRecord(value.metadata) || typeof value.metadata.contentDigest !== 'string' || !validRevision(value.metadata.revision) ||\n !isNonNegativeSafeInteger(value.eventCount) || typeof value.eventDigest !== 'string' ||\n !/^sha256:[a-f0-9]{64}$/.test(value.eventDigest) || !isNonNegativeSafeInteger(value.inheritedEventCount)) {\n return false\n }\n return true\n}\n\nexport class SyncSessionExportCacheStore {\n private readonly filePath: string\n private data: PersistedExportCache | undefined\n private dirty = false\n\n constructor(home?: string) {\n this.filePath = join(cacheHome(home), 'dshb', 'sync-export-cache.json')\n }\n\n get(key: string): PersistedSessionExportCacheEntry | undefined {\n return this.load().entries[key]\n }\n\n set(key: string, entry: PersistedSessionExportCacheEntry): void {\n if (!validEntry(entry)) return\n this.load().entries[key] = entry\n this.dirty = true\n }\n\n delete(key: string): void {\n if (!(key in this.load().entries)) return\n delete this.load().entries[key]\n this.dirty = true\n }\n\n flush(): void {\n if (!this.dirty || !this.data) return\n this.dirty = false\n try {\n atomicWrite(this.filePath, `${JSON.stringify(this.data)}\\n`)\n } catch {\n this.dirty = true\n }\n }\n\n entries(): Iterable<[string, PersistedSessionExportCacheEntry]> {\n return Object.entries(this.load().entries)\n }\n\n private load(): PersistedExportCache {\n if (this.data) return this.data\n let restored: PersistedExportCache = { version: 1, entries: {} }\n try {\n const raw = readFileSync(this.filePath, 'utf8')\n if (raw.length <= MAX_EXPORT_CACHE_FILE_BYTES) {\n const parsed: unknown = JSON.parse(raw)\n if (isRecord(parsed) && parsed.version === 1 && isRecord(parsed.entries)) {\n const entries: Record<string, PersistedSessionExportCacheEntry> = {}\n for (const [key, entry] of Object.entries(parsed.entries)) {\n if (/^\\[\".+?\",(null|\".*?\")\\]$/.test(key) && validEntry(entry)) entries[key] = entry\n }\n restored = { version: 1, entries }\n }\n }\n } catch {}\n this.data = restored\n return restored\n }\n}\n","import { createHash } from 'node:crypto'\nimport { constants as fsConstants, mkdirSync } from 'node:fs'\nimport { lstat, mkdir, open, realpath, unlink } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, join, normalize as normalizeHostPath, posix, resolve } from 'node:path'\nimport {\n SESSION_FORMAT_VERSION,\n SessionId as makeSessionId,\n snapshotSessionEvent,\n} from '@deepseek-ai/dsh-session'\nimport type { SessionEvent, SessionHeader, SessionId } from '@deepseek-ai/dsh-session'\nimport { assertContiguous, validateStoredEvents } from '@deepseek-ai/dsh-session-persistence'\nimport type { FileAttachmentRef, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'\nimport { INSTRUCTION_MAX_BYTES, type SessionInstructionSnapshot } from '../workspace-instructions.js'\nimport { SessionInstructionSnapshotStore } from '../workspace-instructions.js'\nimport type { NodeRegistry, NodeType } from '../node-registry.js'\nimport type { WorkspaceBindingsStore } from '../workspace-bindings.js'\nimport { SyncNodeService } from './node-sync.js'\nimport { compareSyncRevision, HybridLogicalClock } from './revision.js'\nimport type { SyncRevision } from './revision.js'\nimport { isNonNegativeSafeInteger, isRecord, syncRecordKey, syncWorkspaceKey } from './model.js'\nimport type {\n SyncImportMethod,\n SyncOrigin,\n SyncRecordMetadata,\n SyncSessionArchive,\n SyncState,\n SyncWorkspaceMapping,\n} from './model.js'\nimport { SyncStateStore } from './stores.js'\nimport { SyncSessionJournalStore } from './session-journal.js'\nimport { SyncSessionExportCacheStore } from './export-cache.js'\nimport { MAX_SYNC_TRANSFER_BYTES } from './protocol.js'\n\nconst SESSION_READ_PAGE_SIZE = 256\nconst MAX_SYNC_SESSIONS = 10_000\nconst MAX_MANIFEST_PAYLOAD_CACHE_BYTES = 4 * 1024 * 1024\nconst MAX_MANIFEST_PAYLOAD_CACHE_COUNT = 8\n// Bump when sessionEventDigest's normalization changes.\nconst SESSION_EXPORT_CACHE_VERSION = 1\nconst SPILL_META_VERSION = 1\nconst SPILL_ARTIFACT_META_KEY = '@deepseek-ai/dsh-spill'\n\ninterface SpillTransferReference {\n owner: { sessionId: string }\n source: { toolName: string; callId: string; label: string }\n suggestedName: string\n ref: { locator: string; bytes?: number; retrievalHint: string }\n}\n\nconst LEGACY_LOCAL_SPILL_HINT = 'Use read with offset/limit, or grep this path to search within it.'\nconst LEGACY_LOCAL_SPILL_MARKER = 'Full formatted result stored at: '\nconst LEGACY_LOCAL_SPILL_SUFFIX = `. ${LEGACY_LOCAL_SPILL_HINT})`\n\nexport interface SyncSessionWorkspace {\n originInstanceId: string\n originWorkspaceId: string\n nodeOrigin: SyncOrigin\n remotePath: string\n title: string\n revision: SyncRevision\n contentDigest: string\n}\n\nexport interface SyncSessionInstructionSnapshot {\n text: string\n capturedAt: string\n workspaceOrigin?: SyncOrigin\n workspaceRemotePath?: string\n workspaceRevision?: number\n digest?: string\n inheritedFromOrigin?: SyncOrigin\n}\n\nexport interface SyncSessionEventDelta {\n baseEventCount: number\n baseEventDigest: string\n baseInheritedEventCount: number\n fullEventCount: number\n fullEventDigest: string\n}\n\nexport type SyncSessionObject =\n | { id: string; kind: 'image'; ref: ImageAttachmentRef; bytes: number; digest: string; data: string }\n | { id: string; kind: 'file'; ref: FileAttachmentRef; bytes: number; digest: string; data: string }\n | {\n id: string\n kind: 'spill'\n reference: SpillTransferReference\n bytes: number\n digest: string\n data: string\n unavailable?: boolean\n }\n\nexport interface SyncSessionEntry {\n metadata: SyncRecordMetadata\n branchId?: string\n sourceLocalSessionId?: string\n header?: SessionHeader\n inheritedEventCount?: number\n parentOrigin?: SyncOrigin\n workspace?: SyncSessionWorkspace\n workspacePosition?: number\n archived?: boolean\n pinned?: boolean\n instructionSnapshot?: SyncSessionInstructionSnapshot\n events?: SessionEvent[]\n objects?: SyncSessionObject[]\n sharedObjectIds?: string[]\n eventDelta?: SyncSessionEventDelta\n eventCount?: number\n eventDigest?: string\n}\n\nexport interface SyncSessionBundle {\n protocolVersion: 1\n instanceId: string\n entries: SyncSessionEntry[]\n skipped: Array<{ sessionId: string; reason: string }>\n objects?: SyncSessionObject[]\n digest: string\n}\n\nexport type SyncSessionManifestEntry = Pick<SyncSessionEntry, 'metadata' | 'branchId'> & {\n eventCount?: number\n eventDigest?: string\n inheritedEventCount?: number\n}\n\nexport interface SyncSessionEventPrefix {\n key: string\n eventCount: number\n eventDigest: string\n inheritedEventCount: number\n}\n\nexport interface SyncSessionManifest {\n protocolVersion: 1\n instanceId: string\n entries: SyncSessionManifestEntry[]\n skipped: Array<{ sessionId: string; reason: string }>\n digest: string\n}\n\nexport interface SyncSessionApplyResult {\n created: number\n updated: number\n archived: number\n deleted: number\n skipped: number\n unmapped: number\n}\n\ninterface PreparedSyncSession {\n metadata: SyncRecordMetadata\n branchId?: string\n localSessionId: SessionId\n header: SessionHeader\n inheritedEventCount: number\n events: SessionEvent[]\n workspaceId: string\n workspacePath: string\n workspace: SyncSessionWorkspace\n workspacePosition: number\n archived: boolean\n pinned: boolean\n sourceName: string\n importedVia: SyncImportMethod\n instructionSnapshot?: SessionInstructionSnapshot\n}\n\nexport interface SyncSessionApplyOptions {\n importedVia?: SyncImportMethod\n allowSameInstance?: boolean\n}\n\ntype SyncSessionJournalBatch = ReturnType<SyncSessionJournalStore['pendingBatches']>[number]\n\ntype ImportedSessionObjectRef = ImageAttachmentRef | FileAttachmentRef | SpillTransferReference['ref']\n\ninterface SessionExportCacheEntry {\n fingerprint: string\n metadata: SyncRecordMetadata\n eventCount: number\n eventDigest: string\n inheritedEventCount: number\n}\n\ninterface SessionExportResult {\n entry: SyncSessionEntry\n eventCount: number\n eventDigest: string\n inheritedEventCount: number\n}\n\ninterface SessionExportOptions {\n manifestOnly?: boolean\n selectedKeys?: ReadonlySet<string>\n payloadCache?: SessionManifestPayloadCache\n sharedObjects?: boolean\n}\n\ninterface ExportObjectCacheEntry {\n object: SyncSessionObject\n}\n\ntype ExportObjectCache = Map<string, ExportObjectCacheEntry>\n\ninterface SessionManifestPayloadCache {\n instanceId: string\n entries: Map<string, SyncSessionEntry>\n bytes: number\n}\n\nexport interface SyncSessionTransferPlan {\n toLocal: SyncSessionEntry[]\n toRemote: SyncSessionEntry[]\n skipped: number\n}\n\nexport class SyncSessionError extends Error {\n constructor(readonly code: string, message: string, cause?: unknown) {\n super(message, cause === undefined ? undefined : { cause })\n this.name = 'SyncSessionError'\n }\n}\n\ninterface SessionSnapshotLike {\n header: SessionHeader\n formatStatus?: 'current' | 'migration-required'\n revision: unknown\n eventCount?: number\n}\n\ninterface SessionMetadataSnapshot {\n snapshot: SessionSnapshotLike\n header: SessionHeader\n inheritedEventCount: number\n}\n\ninterface SessionHandleLike {\n readonly id: SessionId\n readonly header: SessionHeader\n readonly inheritedEventCount: number\n read(offset?: number, length?: number): Promise<{ events: readonly SessionEvent[] }>\n append(events: readonly SessionEvent[]): Promise<void>\n flush(): Promise<void>\n close(): Promise<void>\n}\n\ninterface SessionPersistenceLike {\n flush(): Promise<void>\n list(): Promise<readonly SessionSnapshotLike[]>\n stat(id: SessionId): Promise<SessionSnapshotLike | undefined>\n open(id: SessionId, access: 'read' | 'write'): Promise<SessionHandleLike>\n create(header: SessionHeader, options?: { inheritedEventCount?: number }): Promise<SessionHandleLike>\n}\n\nasync function readStableSessionMetadata(\n persistence: SessionPersistenceLike,\n sessionId: SessionId,\n firstSnapshot: SessionSnapshotLike,\n): Promise<SessionMetadataSnapshot | undefined> {\n const handle = await persistence.open(sessionId, 'read')\n try {\n const snapshot = await persistence.stat(sessionId)\n if (!snapshot || snapshot.formatStatus === 'migration-required') return undefined\n try {\n if (\n canonicalJson(firstSnapshot.revision) !== canonicalJson(snapshot.revision) ||\n canonicalJson(firstSnapshot.header) !== canonicalJson(snapshot.header) ||\n canonicalJson(handle.header) !== canonicalJson(snapshot.header)\n ) return undefined\n } catch {\n return undefined\n }\n const inheritedEventCount = Number(handle.inheritedEventCount)\n if (!Number.isSafeInteger(inheritedEventCount) || inheritedEventCount < 0) return undefined\n return { snapshot, header: handle.header, inheritedEventCount }\n } finally {\n await handle.close()\n }\n}\n\ninterface WorkspaceLike {\n id: string\n path: string\n title: string\n sessionIds: readonly SessionId[]\n setTitle(title: string): Promise<void>\n attachSession(sessionId: SessionId): Promise<void>\n insertSessionBefore(sessionId: SessionId, beforeSessionId?: SessionId): Promise<void>\n}\n\nexport interface WorkspaceRegistryLike {\n list(): WorkspaceLike[]\n get(id: string): WorkspaceLike | undefined\n create(path: string, title?: string): Promise<WorkspaceLike>\n archiveSession(sessionId: SessionId, options?: { stopActivity?: boolean }): Promise<void>\n unarchiveSession(sessionId: SessionId): Promise<void>\n pinSession?(sessionId: SessionId): Promise<void>\n unpinSession?(sessionId: SessionId): Promise<void>\n readonly archivedSessionIds: readonly SessionId[]\n readonly pinnedSessionIds?: readonly SessionId[]\n}\n\ninterface AttachmentStoreLike {\n readImage(ref: ImageAttachmentRef): Promise<{ ref: ImageAttachmentRef; data: Uint8Array }>\n saveImage(input: { data: Uint8Array; mediaType: ImageAttachmentRef['mediaType']; name?: string }): Promise<ImageAttachmentRef>\n readFileStream(ref: FileAttachmentRef): AsyncIterable<Uint8Array>\n saveFileStream(input: { data: AsyncIterable<Uint8Array>; name?: string }): Promise<FileAttachmentRef>\n}\n\ninterface SpillStoreLike {\n root?: string\n readTextStream?(input: { owner: { sessionId: SessionId }; ref: SpillTransferReference['ref'] }): AsyncIterable<Uint8Array>\n saveTextStream?(input: {\n owner: { sessionId: SessionId }\n source: SpillTransferReference['source']\n suggestedName: string\n transferId: string\n bytes: number\n digest: string\n content: AsyncIterable<Uint8Array>\n }): Promise<SpillTransferReference['ref']>\n}\n\nfunction spillSessionDirectoryName(sessionId: string): string {\n return `session-${createHash('sha256').update(sessionId).digest('hex').slice(0, 12)}`\n}\n\nfunction spillTransferReferenceError(cause?: unknown): SyncSessionError {\n return new SyncSessionError('spill-integrity', 'spill artifact could not be safely transferred', cause)\n}\n\nasync function* readLocalSpillFile(\n configuredRoot: string | undefined,\n reference: SpillTransferReference,\n): AsyncGenerator<Uint8Array> {\n const filePath = resolve(reference.ref.locator)\n const sessionDirectory = dirname(filePath)\n const root = dirname(sessionDirectory)\n const expectedSessionDirectory = spillSessionDirectoryName(reference.owner.sessionId)\n const leaf = basename(filePath)\n if (\n filePath !== reference.ref.locator || basename(sessionDirectory) !== expectedSessionDirectory ||\n !/^(?:[a-f0-9]{12}-.+|transfer-[a-f0-9]{64})$/.test(leaf)\n ) throw spillTransferReferenceError()\n\n const normalizedRoot = resolve(root)\n const normalizedConfiguredRoot = configuredRoot === undefined ? undefined : resolve(configuredRoot)\n if (normalizedRoot !== normalizedConfiguredRoot) {\n const tempRoot = resolve(tmpdir())\n if (dirname(normalizedRoot) !== tempRoot || !basename(normalizedRoot).startsWith('dsh-spill-')) {\n throw spillTransferReferenceError()\n }\n }\n\n let handle: Awaited<ReturnType<typeof open>> | undefined\n try {\n const rootPath = await realpath(normalizedRoot)\n const expectedDirectory = join(rootPath, expectedSessionDirectory)\n if (await realpath(sessionDirectory) !== expectedDirectory) throw spillTransferReferenceError()\n const directoryStat = await lstat(sessionDirectory)\n const entryStat = await lstat(filePath)\n const expectedBytes = reference.ref.bytes ?? entryStat.size\n if (\n directoryStat.isSymbolicLink() || !directoryStat.isDirectory() ||\n entryStat.isSymbolicLink() || !entryStat.isFile() || entryStat.size !== expectedBytes ||\n !Number.isSafeInteger(expectedBytes) || expectedBytes < 0 ||\n (process.platform !== 'win32' && ((directoryStat.mode & 0o077) !== 0 || (entryStat.mode & 0o077) !== 0))\n ) throw spillTransferReferenceError()\n\n const noFollow = typeof fsConstants.O_NOFOLLOW === 'number' ? fsConstants.O_NOFOLLOW : 0\n handle = await open(filePath, fsConstants.O_RDONLY | noFollow)\n const openedStat = await handle.stat()\n if (\n !openedStat.isFile() || openedStat.size !== expectedBytes ||\n (entryStat.ino !== 0 && openedStat.ino !== 0 && entryStat.ino !== openedStat.ino) ||\n (entryStat.dev !== 0 && openedStat.dev !== 0 && entryStat.dev !== openedStat.dev)\n ) throw spillTransferReferenceError()\n\n let bytes = 0\n for (;;) {\n const buffer = Buffer.allocUnsafe(64 * 1024)\n const { bytesRead } = await handle.read(buffer, 0, buffer.byteLength, null)\n if (bytesRead === 0) break\n bytes += bytesRead\n if (bytes > expectedBytes) throw spillTransferReferenceError()\n yield buffer.subarray(0, bytesRead)\n }\n const finalStat = await handle.stat()\n if (bytes !== expectedBytes || finalStat.size !== expectedBytes || finalStat.mtimeMs !== openedStat.mtimeMs) {\n throw spillTransferReferenceError()\n }\n } catch (error) {\n if (error instanceof SyncSessionError) throw error\n throw spillTransferReferenceError(error)\n } finally {\n if (handle) await handle.close()\n }\n}\n\nfunction isUnownedSpillRead(error: unknown): boolean {\n return error instanceof Error && error.name === 'SpillReadError' &&\n 'code' in error && (error as Error & { code?: unknown }).code === 'not-owned'\n}\n\nasync function* readSpillStream(store: SpillStoreLike, reference: SpillTransferReference): AsyncGenerator<Uint8Array> {\n if (store.readTextStream) {\n try {\n yield* store.readTextStream({ owner: { sessionId: makeSessionId(reference.owner.sessionId) }, ref: reference.ref })\n return\n } catch (error) {\n if (!isUnownedSpillRead(error)) throw error\n }\n }\n yield* readLocalSpillFile(store.root, reference)\n}\n\nasync function writeLocalSpillTransfer(\n root: string,\n input: {\n owner: { sessionId: SessionId }\n transferId: string\n bytes: number\n digest: string\n data: Buffer\n },\n): Promise<SpillTransferReference['ref']> {\n if (!input.transferId || input.transferId.length > 4096 || input.bytes !== input.data.byteLength || sha256(input.data) !== input.digest) {\n throw new SyncSessionError('spill-integrity', 'spill transfer metadata is invalid')\n }\n try {\n new TextDecoder('utf-8', { fatal: true }).decode(input.data)\n } catch (error) {\n throw new SyncSessionError('spill-integrity', 'spill content is not valid UTF-8', error)\n }\n\n let rootPath: string\n let directory: string\n let filePath: string\n const sessionId = String(input.owner.sessionId)\n try {\n await mkdir(resolve(root), { recursive: true, mode: 0o700 })\n rootPath = await realpath(resolve(root))\n directory = join(rootPath, spillSessionDirectoryName(sessionId))\n await mkdir(directory, { recursive: true, mode: 0o700 })\n if (await realpath(directory) !== directory) throw spillTransferReferenceError()\n const directoryStat = await lstat(directory)\n if (\n directoryStat.isSymbolicLink() || !directoryStat.isDirectory() ||\n (process.platform !== 'win32' && (directoryStat.mode & 0o077) !== 0)\n ) throw spillTransferReferenceError()\n filePath = join(directory, `transfer-${createHash('sha256').update(input.transferId).digest('hex')}`)\n } catch (error) {\n if (error instanceof SyncSessionError) throw error\n throw spillTransferReferenceError(error)\n }\n\n const ref: SpillTransferReference['ref'] = {\n locator: filePath as SpillTransferReference['ref']['locator'],\n bytes: input.bytes,\n retrievalHint: LEGACY_LOCAL_SPILL_HINT,\n }\n let handle: Awaited<ReturnType<typeof open>> | undefined\n try {\n handle = await open(filePath, 'wx', 0o600)\n } catch (error) {\n if (error instanceof Error && 'code' in error && (error as NodeJS.ErrnoException).code === 'EEXIST') {\n const existing = await collectBytes(readLocalSpillFile(rootPath, { owner: { sessionId }, source: { toolName: 'sync', callId: input.transferId, label: 'spill' }, suggestedName: 'spill.txt', ref }))\n if (existing.byteLength === input.bytes && sha256(existing) === input.digest) return ref\n throw new SyncSessionError('spill-transfer-conflict', 'spill transfer key already contains different content', error)\n }\n throw spillTransferReferenceError(error)\n }\n\n try {\n let offset = 0\n while (offset < input.data.byteLength) {\n const { bytesWritten } = await handle.write(input.data, offset, input.data.byteLength - offset, null)\n if (bytesWritten === 0) throw spillTransferReferenceError()\n offset += bytesWritten\n }\n await handle.sync()\n const stat = await handle.stat()\n if (!stat.isFile() || stat.size !== input.bytes || (process.platform !== 'win32' && (stat.mode & 0o077) !== 0)) {\n throw spillTransferReferenceError()\n }\n } catch (error) {\n await handle.close()\n handle = undefined\n try {\n await unlink(filePath)\n } catch {}\n if (error instanceof SyncSessionError) throw error\n throw spillTransferReferenceError(error)\n } finally {\n if (handle) await handle.close()\n }\n return ref\n}\n\nasync function saveSpillTransfer(\n store: SpillStoreLike,\n input: {\n owner: { sessionId: SessionId }\n source: SpillTransferReference['source']\n suggestedName: string\n transferId: string\n bytes: number\n digest: string\n data: Buffer\n },\n): Promise<SpillTransferReference['ref']> {\n if (store.saveTextStream) {\n return store.saveTextStream({\n owner: input.owner,\n source: input.source,\n suggestedName: input.suggestedName,\n transferId: input.transferId,\n bytes: input.bytes,\n digest: input.digest,\n content: oneChunk(input.data),\n })\n }\n if (typeof store.root === 'string') return writeLocalSpillTransfer(store.root, input)\n throw new SyncSessionError('spill-transfer-unavailable', '目标实例的 spill provider 不支持安全写入')\n}\n\ninterface WorkspaceCandidate {\n workspace: WorkspaceLike\n binding: { mirrorPath: string; nodeId: string; remotePath: string; workspaceId?: string }\n nodeOrigin: SyncOrigin\n nodeType: NodeType\n descriptor: SyncSessionWorkspace\n}\n\nfunction canonicalJson(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value)\n if (Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`\n const object = value as Record<string, unknown>\n return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(object[key])}`).join(',')}}`\n}\n\nfunction sha256(value: string | Uint8Array): string {\n return `sha256:${createHash('sha256').update(value).digest('hex')}`\n}\n\nfunction objectKey(kind: SyncSessionObject['kind'], id: string): string {\n return JSON.stringify([kind, id])\n}\n\nfunction attachmentKey(kind: 'image' | 'file', ref: ImageAttachmentRef | FileAttachmentRef): string {\n return objectKey(kind, `${ref.attachmentId}\\0${ref.name ?? ''}`)\n}\n\nfunction spillKey(reference: SpillTransferReference): string {\n return objectKey('spill', `${reference.owner.sessionId}\\0${reference.ref.locator}`)\n}\n\nfunction sessionOriginKey(metadata: SyncRecordMetadata): string {\n return syncRecordKey('session', metadata)\n}\n\nfunction isImageRef(value: unknown): value is ImageAttachmentRef {\n return isRecord(value) && typeof value.attachmentId === 'string' && typeof value.mediaType === 'string' &&\n isNonNegativeSafeInteger(value.bytes) && isNonNegativeSafeInteger(value.width) && isNonNegativeSafeInteger(value.height)\n}\n\nfunction isFileRef(value: unknown): value is FileAttachmentRef {\n return isRecord(value) && typeof value.attachmentId === 'string' && typeof value.name === 'string' &&\n isNonNegativeSafeInteger(value.bytes) && value.mediaType === undefined\n}\n\nfunction spillReferences(value: unknown): SpillTransferReference[] {\n const output: SpillTransferReference[] = []\n const visit = (current: unknown): void => {\n if (Array.isArray(current)) {\n for (const entry of current) visit(entry)\n return\n }\n if (!isRecord(current)) return\n const spillMeta = current[SPILL_ARTIFACT_META_KEY]\n if (spillMeta !== undefined) {\n if (\n !isRecord(spillMeta) || spillMeta.version !== SPILL_META_VERSION || !Array.isArray(spillMeta.references)\n ) throw new SyncSessionError('spill-metadata-invalid', 'spill references are invalid')\n for (const reference of spillMeta.references) {\n if (\n !isRecord(reference) || !isRecord(reference.owner) || typeof reference.owner.sessionId !== 'string' ||\n !isRecord(reference.source) || typeof reference.source.toolName !== 'string' ||\n typeof reference.source.callId !== 'string' || typeof reference.source.label !== 'string' ||\n typeof reference.suggestedName !== 'string' || !isRecord(reference.ref) ||\n typeof reference.ref.locator !== 'string' ||\n (reference.ref.bytes !== undefined && !isNonNegativeSafeInteger(reference.ref.bytes)) ||\n typeof reference.ref.retrievalHint !== 'string'\n ) throw new SyncSessionError('spill-metadata-invalid', 'spill reference fields are invalid')\n output.push(reference as unknown as SpillTransferReference)\n }\n }\n for (const child of Object.values(current)) visit(child)\n }\n visit(value)\n return output\n}\n\nfunction legacySpillReferences(events: readonly SessionEvent[], sessionId: string): SpillTransferReference[] {\n const toolNames = new Map<string, string>()\n for (const event of events as readonly { type: string; data: unknown }[]) {\n if (event.type !== 'tool/call') continue\n const data = isRecord(event.data) ? event.data as { callId?: string; name?: string } : {}\n if (typeof data.callId === 'string' && typeof data.name === 'string') toolNames.set(data.callId, data.name)\n }\n const found = new Map<string, SpillTransferReference>()\n const scan = (value: unknown, source: SpillTransferReference['source']): void => {\n if (Array.isArray(value)) {\n for (const child of value) scan(child, source)\n return\n }\n if (!isRecord(value)) return\n if (value.type === 'text' && typeof value.text === 'string') {\n let start = value.text.indexOf(LEGACY_LOCAL_SPILL_MARKER)\n while (start >= 0) {\n const locatorStart = start + LEGACY_LOCAL_SPILL_MARKER.length\n const end = value.text.indexOf(LEGACY_LOCAL_SPILL_SUFFIX, locatorStart)\n if (end < 0) throw new SyncSessionError('spill-format-unsupported', '旧 spill 通知格式无法安全识别')\n const locator = value.text.slice(locatorStart, end)\n if (!locator || locator.length > 4096 || /[\\u0000-\\u001f\\u007f]/.test(locator)) {\n throw new SyncSessionError('spill-format-unsupported', '旧 spill locator 无效')\n }\n const reference: SpillTransferReference = {\n owner: { sessionId },\n source,\n suggestedName: `${source.toolName}.txt`,\n ref: { locator, retrievalHint: LEGACY_LOCAL_SPILL_HINT },\n }\n found.set(spillKey(reference), reference)\n start = value.text.indexOf(LEGACY_LOCAL_SPILL_MARKER, end + LEGACY_LOCAL_SPILL_SUFFIX.length)\n }\n }\n for (const child of Object.values(value)) scan(child, source)\n }\n\n for (const event of events as readonly { type: string; data: unknown }[]) {\n if (event.type === 'tool/result') {\n const data = isRecord(event.data) ? event.data : {}\n const message = isRecord(data.message) ? data.message as { source?: { callId?: string }; content?: unknown } : {}\n const callId = message.source?.callId\n if (typeof callId === 'string') {\n scan(message.content, { toolName: toolNames.get(callId) ?? 'unknown', callId, label: 'result' })\n }\n } else if (event.type === 'tool/code-dispatch') {\n const data = isRecord(event.data) ? event.data as { name?: string; subCallId?: string; content?: unknown } : {}\n if (typeof data.name === 'string' && typeof data.subCallId === 'string') {\n scan(data.content, { toolName: data.name, callId: data.subCallId, label: 'dispatch' })\n }\n }\n }\n return [...found.values()]\n}\n\nfunction attachmentReferences(events: readonly SessionEvent[]): { images: ImageAttachmentRef[]; files: FileAttachmentRef[] } {\n const images = new Map<string, ImageAttachmentRef>()\n const files = new Map<string, FileAttachmentRef>()\n const visit = (value: unknown): void => {\n if (Array.isArray(value)) {\n for (const child of value) visit(child)\n return\n }\n if (!isRecord(value)) return\n if (value.type === 'image' && isImageRef(value.attachment)) images.set(attachmentKey('image', value.attachment), value.attachment)\n if (value.type === 'file' && isFileRef(value.attachment)) files.set(attachmentKey('file', value.attachment), value.attachment)\n for (const child of Object.values(value)) visit(child)\n }\n for (const event of events) visit(event)\n return { images: [...images.values()], files: [...files.values()] }\n}\n\nfunction sessionEventDigest(\n header: SessionHeader,\n inheritedEventCount: number,\n events: readonly SessionEvent[],\n workspace: SyncSessionWorkspace,\n instructionSnapshot: SyncSessionInstructionSnapshot | undefined,\n objects: readonly SyncSessionObject[],\n parentOrigin: SyncOrigin | undefined,\n): string {\n const imageDigests = new Map<string, SyncSessionObject>()\n const fileDigests = new Map<string, SyncSessionObject>()\n const spillDigests = new Map<string, SyncSessionObject>()\n for (const object of objects) {\n if (object.kind === 'image') imageDigests.set(attachmentKey('image', object.ref), object)\n else if (object.kind === 'file') fileDigests.set(attachmentKey('file', object.ref), object)\n else spillDigests.set(spillKey(object.reference), object)\n }\n\n const normalize = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(normalize)\n if (!isRecord(value)) return value\n if (value.type === 'image' && isImageRef(value.attachment)) {\n const object = imageDigests.get(attachmentKey('image', value.attachment))\n return object\n ? { type: 'image', digest: object.digest, ...(value.attachment.name ? { name: value.attachment.name } : {}) }\n : { type: 'image', missing: value.attachment.attachmentId }\n }\n if (value.type === 'file' && isFileRef(value.attachment)) {\n const object = fileDigests.get(attachmentKey('file', value.attachment))\n return object ? { type: 'file', digest: object.digest, name: value.attachment.name } : { type: 'file', missing: value.attachment.attachmentId }\n }\n const output: Record<string, unknown> = {}\n for (const [key, child] of Object.entries(value)) {\n if (key === SPILL_ARTIFACT_META_KEY && isRecord(child) && Array.isArray(child.references)) {\n output[key] = {\n version: child.version,\n references: child.references.map((reference) => {\n if (!isRecord(reference) || !isRecord(reference.ref)) return reference\n const spill = spillDigests.get(spillKey(reference as unknown as SpillTransferReference))\n return spill\n ? { source: reference.source, suggestedName: reference.suggestedName, digest: spill.digest, bytes: spill.bytes }\n : { source: reference.source, suggestedName: reference.suggestedName, missing: reference.ref.locator }\n }),\n }\n } else if (key === 'text' && typeof child === 'string') {\n let text = child\n for (const object of objects) {\n if (object.kind !== 'spill') continue\n const ref = object.reference.ref\n text = text.replaceAll(\n `Full formatted result stored at: ${ref.locator}. ${ref.retrievalHint}`,\n `Full formatted result stored at: ${object.digest}.`,\n )\n }\n output[key] = text\n } else {\n output[key] = normalize(child)\n }\n }\n return output\n }\n\n const { id: _id, cwd: _cwd, parentSession: _parent, ...stableHeader } = header\n void _id\n void _cwd\n void _parent\n return sha256(canonicalJson({\n header: stableHeader,\n inheritedEventCount,\n events: events.map(normalize),\n workspace: {\n originInstanceId: workspace.originInstanceId,\n originWorkspaceId: workspace.originWorkspaceId,\n nodeOrigin: workspace.nodeOrigin,\n remotePath: workspace.remotePath,\n },\n parentOrigin,\n instructionSnapshot: instructionSnapshot ? {\n text: instructionSnapshot.text,\n capturedAt: instructionSnapshot.capturedAt,\n workspaceOrigin: instructionSnapshot.workspaceOrigin,\n workspaceRemotePath: instructionSnapshot.workspaceRemotePath,\n workspaceRevision: instructionSnapshot.workspaceRevision,\n digest: instructionSnapshot.digest,\n inheritedFromOrigin: instructionSnapshot.inheritedFromOrigin,\n } : undefined,\n }))\n}\n\nexport function sessionEventListDigest(events: readonly SessionEvent[]): string {\n return sha256(canonicalJson(events))\n}\n\nfunction sessionStateDigest(\n workspace: SyncSessionWorkspace,\n workspacePosition: number,\n archived: boolean,\n pinned: boolean,\n): string {\n return sha256(canonicalJson({\n workspace: {\n originInstanceId: workspace.originInstanceId,\n originWorkspaceId: workspace.originWorkspaceId,\n nodeOrigin: workspace.nodeOrigin,\n remotePath: workspace.remotePath,\n title: workspace.title,\n revision: workspace.revision,\n contentDigest: workspace.contentDigest,\n },\n workspacePosition,\n archived,\n pinned,\n }))\n}\n\nfunction sessionExportFingerprint(input: {\n revision: unknown\n header: SessionHeader\n inheritedEventCount: number\n workspace: SyncSessionWorkspace\n instructionSnapshot?: SyncSessionInstructionSnapshot\n parentOrigin?: SyncOrigin\n}): string | undefined {\n if (input.revision === undefined) return undefined\n try {\n return sha256(canonicalJson({ version: SESSION_EXPORT_CACHE_VERSION, ...input }))\n } catch {\n return undefined\n }\n}\n\nfunction sessionExportCacheKey(sessionId: string, branchId?: string): string {\n return JSON.stringify([sessionId, branchId ?? null])\n}\n\nfunction estimateJsonBytes(value: unknown, limit: number): number | undefined {\n const active = new WeakSet<object>()\n const measure = (item: unknown): number => {\n if (item === null) return 4\n if (typeof item === 'string') {\n const bytes = Buffer.byteLength(item, 'utf8')\n return bytes > limit / 6 ? limit + 1 : bytes * 6 + 2\n }\n if (typeof item === 'number') return Number.isFinite(item) ? String(item).length : 4\n if (typeof item === 'boolean') return item ? 4 : 5\n if (item === undefined || typeof item === 'function' || typeof item === 'symbol') return 4\n if (typeof item === 'bigint') return limit + 1\n if (Array.isArray(item)) {\n if (active.has(item)) return limit + 1\n active.add(item)\n let bytes = 2\n for (let index = 0; index < item.length; index += 1) {\n if (index > 0) bytes += 1\n bytes += measure(item[index])\n if (bytes > limit) break\n }\n active.delete(item)\n return bytes\n }\n if (typeof item === 'object') {\n if (active.has(item)) return limit + 1\n const prototype = Object.getPrototypeOf(item)\n if (prototype !== Object.prototype && prototype !== null) return limit + 1\n active.add(item)\n let bytes = 2\n let first = true\n for (const [key, child] of Object.entries(item)) {\n if (child === undefined || typeof child === 'function' || typeof child === 'symbol') continue\n if (!first) bytes += 1\n first = false\n bytes += Buffer.byteLength(key, 'utf8') * 6 + 3 + measure(child)\n if (bytes > limit) break\n }\n active.delete(item)\n return bytes\n }\n return limit + 1\n }\n try {\n const bytes = measure(value)\n return bytes <= limit ? bytes : undefined\n } catch {\n return undefined\n }\n}\n\nexport function planSessionTransfers(\n direction: 'pull' | 'bidirectional',\n localEntries: readonly SyncSessionEntry[],\n remoteEntries: readonly SyncSessionEntry[],\n): SyncSessionTransferPlan {\n const toLocal: SyncSessionEntry[] = []\n const toRemote: SyncSessionEntry[] = []\n const keyOf = (entry: SyncSessionEntry): string => entry.branchId ?? sessionOriginKey(entry.metadata)\n const localByKey = new Map(localEntries.map((entry) => [keyOf(entry), entry]))\n const remoteByKey = new Map(remoteEntries.map((entry) => [keyOf(entry), entry]))\n if (direction === 'pull') {\n let skipped = 0\n for (const [key, remote] of remoteByKey) {\n const local = localByKey.get(key)\n if (!local) {\n toLocal.push(remote)\n continue\n }\n const comparison = compareSyncRevision(local.metadata.revision, remote.metadata.revision)\n if (comparison < 0) toLocal.push(remote)\n else if (comparison === 0) {\n if (\n local.metadata.contentDigest !== remote.metadata.contentDigest ||\n local.metadata.stateDigest !== remote.metadata.stateDigest ||\n Boolean(local.metadata.deleted) !== Boolean(remote.metadata.deleted)\n ) throw new SyncSessionError('revision-conflict', 'Equal session revisions contain different content')\n skipped += 1\n } else skipped += 1\n }\n return { toLocal, toRemote, skipped }\n }\n const keys = new Set([...localByKey.keys(), ...remoteByKey.keys()])\n let skipped = 0\n for (const key of keys) {\n const local = localByKey.get(key)\n const remote = remoteByKey.get(key)\n if (!local) { toLocal.push(remote!); continue }\n if (!remote) { toRemote.push(local); continue }\n const comparison = compareSyncRevision(local.metadata.revision, remote.metadata.revision)\n if (comparison > 0) toRemote.push(local)\n else if (comparison < 0) toLocal.push(remote)\n else if (\n local.metadata.contentDigest === remote.metadata.contentDigest &&\n local.metadata.stateDigest === remote.metadata.stateDigest &&\n Boolean(local.metadata.deleted) === Boolean(remote.metadata.deleted)\n ) skipped += 1\n else throw new SyncSessionError('revision-conflict', 'Equal session revisions contain different content')\n }\n return { toLocal, toRemote, skipped }\n}\n\nasync function collectBytes(stream: AsyncIterable<Uint8Array>, maxBytes = MAX_SYNC_TRANSFER_BYTES): Promise<Buffer> {\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of stream) {\n if (!(chunk instanceof Uint8Array)) throw new SyncSessionError('object-invalid', 'session object stream contains a non-byte chunk')\n size += chunk.byteLength\n if (size > maxBytes) throw new SyncSessionError('bundle-too-large', 'session object exceeds the transfer limit')\n chunks.push(Buffer.from(chunk))\n }\n return Buffer.concat(chunks, size)\n}\n\nasync function* oneChunk(data: Uint8Array): AsyncIterable<Uint8Array> {\n yield data\n}\n\nfunction findSessionRecordByLocalId(state: SyncState, localSessionId: string): SyncRecordMetadata | undefined {\n return Object.values(state.records)\n .filter((metadata) => metadata.kind === 'session' && metadata.localEntityId === localSessionId)\n .sort((a, b) => compareSyncRevision(b.revision, a.revision))[0]\n}\n\ninterface SessionStateIndex {\n state: SyncState\n recordsByLocalId: Map<string, SyncRecordMetadata>\n workspacesByLocalId: Map<string, SyncWorkspaceMapping[]>\n archivesByLocalSessionId: Map<string, SyncSessionArchive>\n}\n\nfunction createSessionStateIndex(state: SyncState): SessionStateIndex {\n const index: SessionStateIndex = {\n state,\n recordsByLocalId: new Map(),\n workspacesByLocalId: new Map(),\n archivesByLocalSessionId: new Map(),\n }\n for (const metadata of Object.values(state.records)) {\n if (metadata.kind !== 'session') continue\n const current = index.recordsByLocalId.get(metadata.localEntityId)\n if (!current || compareSyncRevision(metadata.revision, current.revision) > 0) {\n index.recordsByLocalId.set(metadata.localEntityId, metadata)\n }\n }\n for (const mapping of Object.values(state.workspaces)) {\n const mappings = index.workspacesByLocalId.get(mapping.localWorkspaceId) ?? []\n mappings.push(mapping)\n index.workspacesByLocalId.set(mapping.localWorkspaceId, mappings)\n }\n for (const archive of Object.values(state.archives)) {\n if (!index.archivesByLocalSessionId.has(archive.localSessionId)) {\n index.archivesByLocalSessionId.set(archive.localSessionId, archive)\n }\n }\n return index\n}\n\nfunction indexSessionRecord(index: SessionStateIndex, metadata: SyncRecordMetadata): void {\n const key = sessionOriginKey(metadata)\n const previous = index.state.records[key]\n if (previous && previous.localEntityId !== metadata.localEntityId &&\n index.recordsByLocalId.get(previous.localEntityId) === previous) {\n delete index.state.records[key]\n index.recordsByLocalId.delete(previous.localEntityId)\n for (const candidate of Object.values(index.state.records)) {\n if (candidate.kind !== 'session' || candidate.localEntityId !== previous.localEntityId) continue\n const current = index.recordsByLocalId.get(previous.localEntityId)\n if (!current || compareSyncRevision(candidate.revision, current.revision) > 0) {\n index.recordsByLocalId.set(previous.localEntityId, candidate)\n }\n }\n }\n index.state.records[key] = metadata\n const current = index.recordsByLocalId.get(metadata.localEntityId)\n if (current === previous || !current || compareSyncRevision(metadata.revision, current.revision) > 0) {\n index.recordsByLocalId.set(metadata.localEntityId, metadata)\n }\n}\n\nfunction indexWorkspaceMapping(index: SessionStateIndex, key: string, mapping: SyncWorkspaceMapping): void {\n const previous = index.state.workspaces[key]\n if (previous) {\n const mappings = index.workspacesByLocalId.get(previous.localWorkspaceId)\n const previousIndex = mappings?.findIndex((item) =>\n syncWorkspaceKey(item.originInstanceId, item.originWorkspaceId, item.remotePath) === key,\n ) ?? -1\n if (mappings && previousIndex !== -1 && previous.localWorkspaceId === mapping.localWorkspaceId) {\n index.state.workspaces[key] = mapping\n mappings[previousIndex] = mapping\n return\n }\n if (mappings && previousIndex !== -1) mappings.splice(previousIndex, 1)\n if (mappings?.length === 0) index.workspacesByLocalId.delete(previous.localWorkspaceId)\n }\n index.state.workspaces[key] = mapping\n const mappings = index.workspacesByLocalId.get(mapping.localWorkspaceId) ?? []\n mappings.push(mapping)\n index.workspacesByLocalId.set(mapping.localWorkspaceId, mappings)\n}\n\nfunction indexArchive(index: SessionStateIndex, previousBranchId: string, archive: SyncSessionArchive): void {\n delete index.state.archives[previousBranchId]\n index.state.archives[archive.branchId] = archive\n index.archivesByLocalSessionId.clear()\n for (const entry of Object.values(index.state.archives)) {\n if (!index.archivesByLocalSessionId.has(entry.localSessionId)) {\n index.archivesByLocalSessionId.set(entry.localSessionId, entry)\n }\n }\n}\n\nfunction findSessionRecordByOrigin(state: SyncState, origin: SyncOrigin): SyncRecordMetadata | undefined {\n return state.records[syncRecordKey('session', origin)]\n}\n\nfunction findSessionOriginByLocalId(state: SyncState, localSessionId: string): SyncOrigin | undefined {\n const metadata = findSessionRecordByLocalId(state, localSessionId)\n return metadata ? { originInstanceId: metadata.originInstanceId, originEntityId: metadata.originEntityId } : undefined\n}\n\nfunction workspaceDigest(workspace: Omit<SyncSessionWorkspace, 'revision' | 'contentDigest'>): string {\n return sha256(canonicalJson(workspace))\n}\n\nfunction workspaceCandidateKey(workspace: WorkspaceLike): string {\n return normalizeHostPath(workspace.path)\n}\n\nfunction validateObjectPayload(object: unknown): SyncSessionObject {\n if (!isRecord(object) || typeof object.id !== 'string' || !object.id || typeof object.digest !== 'string' ||\n !/^sha256:[a-f0-9]{64}$/.test(object.digest) || !isNonNegativeSafeInteger(object.bytes) || typeof object.data !== 'string') {\n throw new SyncSessionError('object-invalid', 'session object metadata is invalid')\n }\n const isUnavailableSpill = object.kind === 'spill' && object.unavailable === true && object.bytes === 0 && object.data === ''\n if (!isUnavailableSpill) {\n const bytes = Buffer.from(object.data, 'base64')\n if (bytes.toString('base64') !== object.data || bytes.byteLength !== object.bytes || sha256(bytes) !== object.digest) {\n throw new SyncSessionError('object-invalid', 'session object encoding or digest is invalid')\n }\n }\n if (object.kind === 'image' && isImageRef(object.ref) && object.id === attachmentKey('image', object.ref)) {\n return object as unknown as SyncSessionObject\n }\n if (object.kind === 'file' && isFileRef(object.ref) && object.id === attachmentKey('file', object.ref)) {\n return object as unknown as SyncSessionObject\n }\n if (\n object.kind === 'spill' && isRecord(object.reference) && isRecord(object.reference.owner) &&\n typeof object.reference.owner.sessionId === 'string' && isRecord(object.reference.ref) &&\n typeof object.reference.ref.locator === 'string' && object.id === spillKey(object.reference as unknown as SpillTransferReference)\n ) {\n return object as unknown as SyncSessionObject\n }\n throw new SyncSessionError('object-invalid', 'session object kind or reference is invalid')\n}\n\nfunction validateEventDelta(value: unknown): SyncSessionEventDelta {\n if (!isRecord(value) || !isNonNegativeSafeInteger(value.baseEventCount) ||\n typeof value.baseEventDigest !== 'string' || !/^sha256:[a-f0-9]{64}$/.test(value.baseEventDigest) ||\n !isNonNegativeSafeInteger(value.baseInheritedEventCount) ||\n !isNonNegativeSafeInteger(value.fullEventCount) || value.fullEventCount < value.baseEventCount ||\n typeof value.fullEventDigest !== 'string' || !/^sha256:[a-f0-9]{64}$/.test(value.fullEventDigest)) {\n throw new SyncSessionError('manifest-invalid', 'session event delta metadata is invalid')\n }\n return {\n baseEventCount: value.baseEventCount,\n baseEventDigest: value.baseEventDigest,\n baseInheritedEventCount: value.baseInheritedEventCount,\n fullEventCount: value.fullEventCount,\n fullEventDigest: value.fullEventDigest,\n }\n}\n\nfunction validateEntry(entry: unknown): SyncSessionEntry {\n if (!isRecord(entry) || !isRecord(entry.metadata) || entry.metadata.kind !== 'session') {\n throw new SyncSessionError('manifest-invalid', 'session entry metadata is invalid')\n }\n const metadata = entry.metadata as unknown as SyncRecordMetadata\n if (\n typeof metadata.originInstanceId !== 'string' || !metadata.originInstanceId || metadata.originInstanceId.length > 512 || /[\\u0000-\\u001f\\u007f]/.test(metadata.originInstanceId) ||\n typeof metadata.originEntityId !== 'string' || !metadata.originEntityId || metadata.originEntityId.length > 512 || /[\\u0000-\\u001f\\u007f]/.test(metadata.originEntityId) ||\n typeof metadata.localEntityId !== 'string' || !metadata.localEntityId || metadata.localEntityId.length > 512 || /[\\u0000-\\u001f\\u007f]/.test(metadata.localEntityId) ||\n typeof metadata.contentDigest !== 'string' ||\n !/^sha256:[a-f0-9]{64}$/.test(metadata.contentDigest) || !metadata.revision ||\n !isNonNegativeSafeInteger(metadata.revision.physicalTimeMs) ||\n !isNonNegativeSafeInteger(metadata.revision.logicalCounter) || typeof metadata.revision.writerInstanceId !== 'string' ||\n !metadata.revision.writerInstanceId || /[\\u0000-\\u001f\\u007f]/.test(metadata.revision.writerInstanceId)\n ) throw new SyncSessionError('manifest-invalid', 'session entry metadata fields are invalid')\n if (metadata.stateDigest !== undefined && !/^sha256:[a-f0-9]{64}$/.test(metadata.stateDigest)) {\n throw new SyncSessionError('manifest-invalid', 'session state digest is invalid')\n }\n if (metadata.deleted !== undefined && typeof metadata.deleted !== 'boolean') {\n throw new SyncSessionError('manifest-invalid', 'session tombstone flag is invalid')\n }\n if (entry.branchId !== undefined && (typeof entry.branchId !== 'string' || !/^b-[a-f0-9]{32}$/.test(entry.branchId))) {\n throw new SyncSessionError('manifest-invalid', 'session branch ID is invalid')\n }\n if (metadata.workspaceOrigin !== undefined) validateOrigin(metadata.workspaceOrigin)\n const eventDelta = entry.eventDelta === undefined ? undefined : validateEventDelta(entry.eventDelta)\n if (metadata.deleted) {\n if (eventDelta) throw new SyncSessionError('manifest-invalid', 'session tombstones cannot carry event deltas')\n if (metadata.contentDigest !== sessionTombstoneDigest(metadata)) throw new SyncSessionError('manifest-invalid', 'session tombstone digest is invalid')\n return { metadata, ...(entry.branchId ? { branchId: entry.branchId as string } : {}) }\n }\n const workspace = isRecord(entry.workspace) ? entry.workspace : undefined\n const workspaceRevision = workspace && isRecord(workspace.revision) ? workspace.revision : undefined\n if (\n typeof entry.sourceLocalSessionId !== 'string' || !isRecord(entry.header) ||\n typeof entry.inheritedEventCount !== 'number' || !Number.isSafeInteger(entry.inheritedEventCount) || entry.inheritedEventCount < 0 ||\n !Array.isArray(entry.events) || !workspace || !Array.isArray(entry.objects) ||\n typeof workspace.originInstanceId !== 'string' || typeof workspace.originWorkspaceId !== 'string' ||\n !isRecord(workspace.nodeOrigin) || typeof workspace.nodeOrigin.originInstanceId !== 'string' ||\n typeof workspace.nodeOrigin.originEntityId !== 'string' || typeof workspace.remotePath !== 'string' ||\n !posix.isAbsolute(workspace.remotePath) || posix.normalize(workspace.remotePath) !== workspace.remotePath ||\n typeof workspace.title !== 'string' || typeof workspace.contentDigest !== 'string' ||\n !/^sha256:[a-f0-9]{64}$/.test(workspace.contentDigest) ||\n !workspaceRevision || !isNonNegativeSafeInteger(workspaceRevision.physicalTimeMs) ||\n !isNonNegativeSafeInteger(workspaceRevision.logicalCounter) ||\n typeof workspaceRevision.writerInstanceId !== 'string' ||\n typeof entry.workspacePosition !== 'number' || !Number.isSafeInteger(entry.workspacePosition) || entry.workspacePosition < 0 ||\n typeof entry.archived !== 'boolean' || typeof entry.pinned !== 'boolean'\n ) throw new SyncSessionError('manifest-invalid', 'active session entry fields are invalid')\n if (eventDelta && (entry.branchId !== undefined || entry.archived)) {\n throw new SyncSessionError('manifest-invalid', 'archives cannot use event tail deltas')\n }\n if (entry.events.length > MAX_SYNC_SESSIONS * 100) throw new SyncSessionError('manifest-invalid', 'session event count exceeds limit')\n const header = entry.header as unknown as SessionHeader\n if (header.version !== SESSION_FORMAT_VERSION || header.id !== entry.sourceLocalSessionId) {\n throw new SyncSessionError('session-format', 'session header format or id is invalid')\n }\n let events: SessionEvent[]\n if (eventDelta) {\n if (eventDelta.baseInheritedEventCount !== entry.inheritedEventCount ||\n eventDelta.fullEventCount > MAX_SYNC_SESSIONS * 100 ||\n eventDelta.fullEventCount - eventDelta.baseEventCount !== entry.events.length) {\n throw new SyncSessionError('manifest-invalid', 'session event delta counts are inconsistent')\n }\n events = structuredClone(entry.events) as SessionEvent[]\n for (let index = 0; index < events.length; index += 1) {\n if (!isNonNegativeSafeInteger(events[index]?.seq) || events[index]?.seq !== eventDelta.baseEventCount + index) {\n throw new SyncSessionError('manifest-invalid', 'session event delta sequence is invalid')\n }\n }\n } else {\n events = validateStoredEvents(header, structuredClone(entry.events) as SessionEvent[])\n assertContiguous(header.id, events, 0)\n }\n const objects = entry.objects.map(validateObjectPayload)\n if (new Set(objects.map((object) => object.id)).size !== objects.length) {\n throw new SyncSessionError('manifest-invalid', 'session entry contains duplicate objects')\n }\n const workspaceValue = workspace as unknown as SyncSessionWorkspace\n const workspaceBase = {\n originInstanceId: workspaceValue.originInstanceId,\n originWorkspaceId: workspaceValue.originWorkspaceId,\n nodeOrigin: workspaceValue.nodeOrigin,\n remotePath: workspaceValue.remotePath,\n title: workspaceValue.title,\n }\n if (workspaceDigest(workspaceBase) !== workspaceValue.contentDigest) {\n throw new SyncSessionError('manifest-invalid', 'workspace content digest is invalid')\n }\n const instructionSnapshot = entry.instructionSnapshot === undefined\n ? undefined\n : validateInstructionSnapshot(entry.instructionSnapshot)\n const referencedObjects = new Set<string>()\n const attachments = attachmentReferences(events)\n for (const ref of attachments.images) referencedObjects.add(attachmentKey('image', ref))\n for (const ref of attachments.files) referencedObjects.add(attachmentKey('file', ref))\n for (const reference of [...spillReferences(events), ...legacySpillReferences(events, String(header.id))]) {\n referencedObjects.add(spillKey(reference))\n }\n const objectIds = new Set(objects.map((object) => object.id))\n if ([...referencedObjects].some((id) => !objectIds.has(id)) ||\n (!eventDelta && [...objectIds].some((id) => !referencedObjects.has(id)))) {\n throw new SyncSessionError('manifest-invalid', 'session object references and payloads do not match')\n }\n const parentOrigin = entry.parentOrigin === undefined ? undefined : validateOrigin(entry.parentOrigin)\n if (!eventDelta) {\n const contentDigest = sessionEventDigest(\n header,\n entry.inheritedEventCount as number,\n events,\n workspaceValue,\n instructionSnapshot,\n objects,\n parentOrigin,\n )\n if (contentDigest !== metadata.contentDigest) throw new SyncSessionError('manifest-invalid', 'session content digest is invalid')\n }\n if (metadata.stateDigest !== sessionStateDigest(workspaceValue, entry.workspacePosition as number, entry.archived as boolean, entry.pinned as boolean)) {\n throw new SyncSessionError('manifest-invalid', 'session state digest is invalid')\n }\n return {\n metadata,\n ...(entry.branchId ? { branchId: entry.branchId as string } : {}),\n sourceLocalSessionId: entry.sourceLocalSessionId,\n header,\n inheritedEventCount: entry.inheritedEventCount,\n ...(parentOrigin ? { parentOrigin } : {}),\n workspace: workspaceValue,\n workspacePosition: entry.workspacePosition,\n archived: entry.archived,\n pinned: entry.pinned,\n ...(instructionSnapshot ? { instructionSnapshot } : {}),\n events,\n objects,\n ...(eventDelta ? { eventDelta } : {}),\n }\n}\n\nfunction validateManifestEntry(entry: unknown): SyncSessionManifestEntry {\n if (!isRecord(entry) || !isRecord(entry.metadata) || entry.metadata.kind !== 'session') {\n throw new SyncSessionError('manifest-invalid', 'session manifest entry metadata is invalid')\n }\n const metadata = entry.metadata as unknown as SyncRecordMetadata\n if (\n typeof metadata.originInstanceId !== 'string' || !metadata.originInstanceId || metadata.originInstanceId.length > 512 || /[\\u0000-\\u001f\\u007f]/.test(metadata.originInstanceId) ||\n typeof metadata.originEntityId !== 'string' || !metadata.originEntityId || metadata.originEntityId.length > 512 || /[\\u0000-\\u001f\\u007f]/.test(metadata.originEntityId) ||\n typeof metadata.localEntityId !== 'string' || !metadata.localEntityId || metadata.localEntityId.length > 512 || /[\\u0000-\\u001f\\u007f]/.test(metadata.localEntityId) ||\n typeof metadata.contentDigest !== 'string' || !/^sha256:[a-f0-9]{64}$/.test(metadata.contentDigest) || !metadata.revision ||\n !isNonNegativeSafeInteger(metadata.revision.physicalTimeMs) ||\n !isNonNegativeSafeInteger(metadata.revision.logicalCounter) || typeof metadata.revision.writerInstanceId !== 'string' ||\n !metadata.revision.writerInstanceId || /[\\u0000-\\u001f\\u007f]/.test(metadata.revision.writerInstanceId)\n ) throw new SyncSessionError('manifest-invalid', 'session manifest metadata fields are invalid')\n if (metadata.stateDigest !== undefined && !/^sha256:[a-f0-9]{64}$/.test(metadata.stateDigest)) {\n throw new SyncSessionError('manifest-invalid', 'session manifest state digest is invalid')\n }\n if (metadata.deleted !== undefined && typeof metadata.deleted !== 'boolean') {\n throw new SyncSessionError('manifest-invalid', 'session manifest tombstone flag is invalid')\n }\n const hasEventCount = entry.eventCount !== undefined\n const hasEventDigest = entry.eventDigest !== undefined\n const hasInheritedEventCount = entry.inheritedEventCount !== undefined\n if (hasEventCount || hasEventDigest || hasInheritedEventCount) {\n if (!hasEventCount || !hasEventDigest || !hasInheritedEventCount || metadata.deleted ||\n !isNonNegativeSafeInteger(entry.eventCount) || entry.eventCount > MAX_SYNC_SESSIONS * 100 ||\n typeof entry.eventDigest !== 'string' || !/^sha256:[a-f0-9]{64}$/.test(entry.eventDigest) ||\n !isNonNegativeSafeInteger(entry.inheritedEventCount) || entry.inheritedEventCount > entry.eventCount) {\n throw new SyncSessionError('manifest-invalid', 'session event summary is invalid')\n }\n }\n if (entry.branchId !== undefined && (typeof entry.branchId !== 'string' || !/^b-[a-f0-9]{32}$/.test(entry.branchId))) {\n throw new SyncSessionError('manifest-invalid', 'session manifest branch ID is invalid')\n }\n if (metadata.workspaceOrigin !== undefined) validateOrigin(metadata.workspaceOrigin)\n if (metadata.deleted && metadata.contentDigest !== sessionTombstoneDigest(metadata)) {\n throw new SyncSessionError('manifest-invalid', 'session manifest tombstone digest is invalid')\n }\n return {\n metadata,\n ...(entry.branchId ? { branchId: entry.branchId as string } : {}),\n ...(hasEventCount ? { eventCount: entry.eventCount as number } : {}),\n ...(hasEventDigest ? { eventDigest: entry.eventDigest as string } : {}),\n ...(hasInheritedEventCount ? { inheritedEventCount: entry.inheritedEventCount as number } : {}),\n }\n}\n\nfunction bundleDigest(bundle: Pick<SyncSessionBundle, 'instanceId' | 'entries' | 'skipped' | 'objects'>): string {\n const sharedObjects = new Map((bundle.objects ?? []).map((object) => [object.id, object]))\n const manifest = bundle.entries.map((entry) => ({\n key: entry.branchId ?? sessionOriginKey(entry.metadata),\n revision: entry.metadata.revision,\n contentDigest: entry.metadata.contentDigest,\n stateDigest: entry.metadata.stateDigest,\n deleted: Boolean(entry.metadata.deleted),\n objects: (entry.objects ?? (entry.sharedObjectIds ?? []).map((id) => {\n const object = sharedObjects.get(id)\n if (!object) throw new SyncSessionError('manifest-invalid', 'session shared object id is unknown')\n return object\n })).map((object) => ({ id: object.id, digest: object.digest, bytes: object.bytes }))\n .sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0),\n eventDelta: entry.eventDelta === undefined ? undefined : {\n ...entry.eventDelta,\n suffixDigest: sessionEventListDigest(entry.events ?? []),\n },\n })).sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0)\n const skipped = bundle.skipped.map((entry) => ({ sessionId: entry.sessionId, reason: entry.reason }))\n .sort((a, b) => a.sessionId < b.sessionId ? -1 : a.sessionId > b.sessionId ? 1 : 0)\n return sha256(canonicalJson({ instanceId: bundle.instanceId, entries: manifest, skipped }))\n}\n\nfunction materializeSharedObjects(bundle: {\n objects?: SyncSessionObject[]\n entries: Array<Pick<SyncSessionEntry, 'sharedObjectIds'>>\n}): Map<string, SyncSessionObject> {\n const shared = bundle.objects === undefined ? new Map<string, SyncSessionObject>() : new Map(\n bundle.objects.map((object) => {\n const validated = validateObjectPayload(object)\n return [validated.id, validated] as const\n }),\n )\n if (shared.size !== (bundle.objects?.length ?? 0)) {\n throw new SyncSessionError('manifest-invalid', 'session bundle contains duplicate shared objects')\n }\n for (const entry of bundle.entries) {\n if (!entry || typeof entry !== 'object') continue\n if (entry.sharedObjectIds !== undefined && (!Array.isArray(entry.sharedObjectIds) ||\n new Set(entry.sharedObjectIds).size !== entry.sharedObjectIds.length ||\n entry.sharedObjectIds.some((id) => !shared.has(id)))) {\n throw new SyncSessionError('manifest-invalid', 'session entry shared object references are invalid')\n }\n }\n return shared\n}\n\nexport function validateSyncSessionBundle(value: unknown): SyncSessionBundle {\n if (!isRecord(value) || value.protocolVersion !== 1 || typeof value.instanceId !== 'string' ||\n !/^i-[a-f0-9]{32}$/.test(value.instanceId) || !Array.isArray(value.entries) || typeof value.digest !== 'string') {\n throw new SyncSessionError('manifest-invalid', 'session bundle header is invalid')\n }\n if (value.objects !== undefined && (!Array.isArray(value.objects) || value.objects.some((object) => !isRecord(object)))) {\n throw new SyncSessionError('manifest-invalid', 'session bundle shared object table is invalid')\n }\n const sharedObjects = materializeSharedObjects({\n ...(value.objects === undefined ? {} : { objects: value.objects as SyncSessionObject[] }),\n entries: value.entries as Array<Pick<SyncSessionEntry, 'sharedObjectIds'>>,\n })\n const skipped = value.skipped === undefined ? [] : value.skipped\n if (!Array.isArray(skipped) || skipped.some((item) =>\n !isRecord(item) || typeof item.sessionId !== 'string' || typeof item.reason !== 'string'\n )) throw new SyncSessionError('manifest-invalid', 'session bundle skip report is invalid')\n if (value.entries.length > MAX_SYNC_SESSIONS) throw new SyncSessionError('manifest-invalid', 'session bundle contains too many records')\n const entries = value.entries.map((entry) => {\n const materialized: SyncSessionEntry = { ...entry } as SyncSessionEntry\n if (materialized.sharedObjectIds !== undefined) {\n if (materialized.objects !== undefined) {\n throw new SyncSessionError('manifest-invalid', 'session entry cannot carry inline and shared objects')\n }\n materialized.objects = materialized.sharedObjectIds.map((id) => sharedObjects.get(id)!)\n }\n return validateEntry(materialized)\n })\n const keys = entries.map((entry) => entry.branchId ?? sessionOriginKey(entry.metadata))\n if (new Set(keys).size !== keys.length) throw new SyncSessionError('manifest-invalid', 'session bundle contains duplicate records')\n const bundle: SyncSessionBundle = {\n protocolVersion: 1,\n instanceId: value.instanceId,\n entries,\n skipped: skipped as Array<{ sessionId: string; reason: string }>,\n ...(value.objects === undefined ? {} : { objects: value.objects as SyncSessionObject[] }),\n digest: value.digest,\n }\n if (bundleDigest(bundle) !== bundle.digest) throw new SyncSessionError('manifest-digest', 'session bundle digest does not match')\n if (Buffer.byteLength(JSON.stringify(bundle), 'utf8') > MAX_SYNC_TRANSFER_BYTES) {\n throw new SyncSessionError('bundle-too-large', 'session bundle exceeds the transfer limit')\n }\n return bundle\n}\n\nexport function makeSyncSessionBundle(\n instanceId: string,\n entries: SyncSessionEntry[],\n skipped: Array<{ sessionId: string; reason: string }> = [],\n sharedObjects?: SyncSessionObject[],\n): SyncSessionBundle {\n if (sharedObjects !== undefined) {\n const referencesShared = entries.some((entry) => (entry.objects?.length ?? 0) > 0 || entry.sharedObjectIds !== undefined)\n const inlineEntries = referencesShared\n ? entries.map((entry) => {\n if (entry.objects === undefined) return entry\n const { objects, ...rest } = entry\n void objects\n return { ...rest, sharedObjectIds: objects.map((object) => object.id) }\n })\n : entries\n const bundle: SyncSessionBundle = {\n protocolVersion: 1,\n instanceId,\n entries: inlineEntries,\n skipped,\n ...(referencesShared ? { objects: sharedObjects } : {}),\n digest: '',\n }\n bundle.digest = bundleDigest(bundle)\n if (Buffer.byteLength(JSON.stringify(bundle), 'utf8') > MAX_SYNC_TRANSFER_BYTES) {\n throw new SyncSessionError('bundle-too-large', 'session bundle exceeds the transfer limit')\n }\n return bundle\n }\n const bundle: SyncSessionBundle = { protocolVersion: 1, instanceId, entries, skipped, digest: '' }\n bundle.digest = bundleDigest(bundle)\n if (Buffer.byteLength(JSON.stringify(bundle), 'utf8') > MAX_SYNC_TRANSFER_BYTES) {\n throw new SyncSessionError('bundle-too-large', 'session bundle exceeds the transfer limit')\n }\n return bundle\n}\n\nexport function syncSessionEntryKey(entry: Pick<SyncSessionManifestEntry, 'metadata' | 'branchId'>): string {\n return entry.branchId ?? sessionOriginKey(entry.metadata)\n}\n\nfunction withEventTail(entry: SyncSessionEntry, prefix?: SyncSessionEventPrefix): SyncSessionEntry {\n if (!prefix || entry.metadata.deleted || entry.branchId || !entry.events || entry.events.length === 0 ||\n prefix.eventCount === 0 || prefix.eventCount > entry.events.length ||\n prefix.inheritedEventCount !== entry.inheritedEventCount) return entry\n const baseEvents = entry.events.slice(0, prefix.eventCount)\n if (sessionEventListDigest(baseEvents) !== prefix.eventDigest) return entry\n const fullEventDigest = entry.eventDigest !== undefined && entry.eventCount === entry.events.length\n ? entry.eventDigest\n : sessionEventListDigest(entry.events)\n return {\n ...entry,\n eventDelta: {\n baseEventCount: prefix.eventCount,\n baseEventDigest: prefix.eventDigest,\n baseInheritedEventCount: prefix.inheritedEventCount,\n fullEventCount: entry.events.length,\n fullEventDigest,\n },\n events: entry.events.slice(prefix.eventCount),\n }\n}\n\nfunction sessionManifestDigest(manifest: Pick<SyncSessionManifest, 'instanceId' | 'entries' | 'skipped'>): string {\n const entries = manifest.entries.map((entry) => ({\n key: syncSessionEntryKey(entry),\n metadata: entry.metadata,\n eventCount: entry.eventCount,\n eventDigest: entry.eventDigest,\n inheritedEventCount: entry.inheritedEventCount,\n }))\n .sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0)\n const skipped = manifest.skipped.map((entry) => ({ sessionId: entry.sessionId, reason: entry.reason }))\n .sort((a, b) => a.sessionId < b.sessionId ? -1 : a.sessionId > b.sessionId ? 1 : 0)\n return sha256(canonicalJson({ instanceId: manifest.instanceId, entries, skipped }))\n}\n\nexport function makeSyncSessionManifest(\n instanceId: string,\n entries: readonly SyncSessionManifestEntry[],\n skipped: Array<{ sessionId: string; reason: string }> = [],\n): SyncSessionManifest {\n const manifest: SyncSessionManifest = {\n protocolVersion: 1,\n instanceId,\n entries: entries.map((entry) => ({\n metadata: entry.metadata,\n ...(entry.branchId ? { branchId: entry.branchId } : {}),\n ...(entry.eventCount === undefined ? {} : { eventCount: entry.eventCount }),\n ...(entry.eventDigest === undefined ? {} : { eventDigest: entry.eventDigest }),\n ...(entry.inheritedEventCount === undefined ? {} : { inheritedEventCount: entry.inheritedEventCount }),\n })),\n skipped,\n digest: '',\n }\n manifest.digest = sessionManifestDigest(manifest)\n if (Buffer.byteLength(JSON.stringify(manifest), 'utf8') > MAX_SYNC_TRANSFER_BYTES) {\n throw new SyncSessionError('bundle-too-large', 'session manifest exceeds the transfer limit')\n }\n return manifest\n}\n\nexport function validateSyncSessionManifest(value: unknown): SyncSessionManifest {\n if (!isRecord(value) || value.protocolVersion !== 1 || typeof value.instanceId !== 'string' ||\n !/^i-[a-f0-9]{32}$/.test(value.instanceId) || !Array.isArray(value.entries) || typeof value.digest !== 'string') {\n throw new SyncSessionError('manifest-invalid', 'session manifest header is invalid')\n }\n const skipped = value.skipped === undefined ? [] : value.skipped\n if (!Array.isArray(skipped) || skipped.some((item) =>\n !isRecord(item) || typeof item.sessionId !== 'string' || typeof item.reason !== 'string'\n )) throw new SyncSessionError('manifest-invalid', 'session manifest skip report is invalid')\n if (value.entries.length > MAX_SYNC_SESSIONS) throw new SyncSessionError('manifest-invalid', 'session manifest contains too many records')\n const entries = value.entries.map(validateManifestEntry)\n const keys = entries.map(syncSessionEntryKey)\n if (new Set(keys).size !== keys.length) throw new SyncSessionError('manifest-invalid', 'session manifest contains duplicate records')\n const manifest: SyncSessionManifest = {\n protocolVersion: 1,\n instanceId: value.instanceId,\n entries,\n skipped: skipped as Array<{ sessionId: string; reason: string }>,\n digest: value.digest,\n }\n if (sessionManifestDigest(manifest) !== manifest.digest) {\n throw new SyncSessionError('manifest-digest', 'session manifest digest does not match')\n }\n if (Buffer.byteLength(JSON.stringify(manifest), 'utf8') > MAX_SYNC_TRANSFER_BYTES) {\n throw new SyncSessionError('bundle-too-large', 'session manifest exceeds the transfer limit')\n }\n return manifest\n}\n\nfunction emptyApplyResult(): SyncSessionApplyResult {\n return { created: 0, updated: 0, archived: 0, deleted: 0, skipped: 0, unmapped: 0 }\n}\n\nfunction isNodeRemoteType(type: NodeType): boolean {\n return type === 'remote-ssh' || type === 'remote-docker'\n}\n\nfunction branchIdFor(metadata: SyncRecordMetadata): string {\n return `b-${createHash('sha256').update(canonicalJson({\n originInstanceId: metadata.originInstanceId,\n originEntityId: metadata.originEntityId,\n contentDigest: metadata.contentDigest,\n })).digest('hex').slice(0, 32)}`\n}\n\nfunction sessionTombstoneDigest(metadata: Pick<SyncRecordMetadata, 'originInstanceId' | 'originEntityId'>): string {\n return sha256(canonicalJson({\n kind: 'session',\n originInstanceId: metadata.originInstanceId,\n originEntityId: metadata.originEntityId,\n deleted: true,\n }))\n}\n\nfunction validateOrigin(value: unknown): SyncOrigin {\n if (!isRecord(value) || typeof value.originInstanceId !== 'string' || !value.originInstanceId ||\n typeof value.originEntityId !== 'string' || !value.originEntityId ||\n value.originInstanceId.length > 512 || value.originEntityId.length > 512 ||\n /[\\u0000-\\u001f\\u007f]/.test(value.originInstanceId) || /[\\u0000-\\u001f\\u007f]/.test(value.originEntityId)) {\n throw new SyncSessionError('manifest-invalid', 'session origin reference is invalid')\n }\n return { originInstanceId: value.originInstanceId, originEntityId: value.originEntityId }\n}\n\nfunction validateInstructionSnapshot(value: unknown): SyncSessionInstructionSnapshot {\n if (!isRecord(value) || typeof value.text !== 'string' ||\n Buffer.byteLength(value.text, 'utf8') > INSTRUCTION_MAX_BYTES ||\n typeof value.capturedAt !== 'string' || value.capturedAt.length > 64) {\n throw new SyncSessionError('manifest-invalid', 'session instruction snapshot is invalid')\n }\n if (value.workspaceRevision !== undefined && !isNonNegativeSafeInteger(value.workspaceRevision)) {\n throw new SyncSessionError('manifest-invalid', 'instruction workspace revision is invalid')\n }\n if (value.digest !== undefined && (typeof value.digest !== 'string' || !/^[a-f0-9]{64}$/.test(value.digest))) {\n throw new SyncSessionError('manifest-invalid', 'instruction digest is invalid')\n }\n if (value.workspaceRemotePath !== undefined && (\n typeof value.workspaceRemotePath !== 'string' || !posix.isAbsolute(value.workspaceRemotePath) ||\n posix.normalize(value.workspaceRemotePath) !== value.workspaceRemotePath\n )) throw new SyncSessionError('manifest-invalid', 'instruction workspace path is invalid')\n return {\n text: value.text,\n capturedAt: value.capturedAt,\n ...(value.workspaceOrigin === undefined ? {} : { workspaceOrigin: validateOrigin(value.workspaceOrigin) }),\n ...(value.workspaceRemotePath === undefined ? {} : { workspaceRemotePath: value.workspaceRemotePath as string }),\n ...(value.workspaceRevision === undefined ? {} : { workspaceRevision: value.workspaceRevision as number }),\n ...(value.digest === undefined ? {} : { digest: value.digest as string }),\n ...(value.inheritedFromOrigin === undefined ? {} : { inheritedFromOrigin: validateOrigin(value.inheritedFromOrigin) }),\n }\n}\n\nfunction importedSessionId(metadata: SyncRecordMetadata): SessionId {\n const identity = canonicalJson({\n originInstanceId: metadata.originInstanceId,\n originEntityId: metadata.originEntityId,\n contentDigest: metadata.contentDigest,\n })\n return makeSessionId(`session-sync-${createHash('sha256').update(identity).digest('hex').slice(0, 32)}`)\n}\n\nfunction archivedSessionId(branchId: string): SessionId {\n return makeSessionId(`session-archive-${createHash('sha256').update(branchId).digest('hex').slice(0, 32)}`)\n}\n\nfunction tombstoneDigest(metadata: Pick<SyncRecordMetadata, 'originInstanceId' | 'originEntityId'>): string {\n return sha256(canonicalJson({ kind: 'session', originInstanceId: metadata.originInstanceId, originEntityId: metadata.originEntityId, deleted: true }))\n}\n\nfunction arrayBuffer(data: string): Buffer {\n const value = Buffer.from(data, 'base64')\n if (value.toString('base64') !== data) throw new SyncSessionError('object-invalid', 'session object is not canonical base64')\n return value\n}\n\nfunction instructionsForSession(\n store: SessionInstructionSnapshotStore,\n sessionId: string,\n stateIndex: SessionStateIndex,\n preferredWorkspaceOrigin?: SyncOrigin,\n): SyncSessionInstructionSnapshot | undefined {\n const snapshot = store.get(sessionId)\n if (!snapshot) return undefined\n const workspaceMappings = snapshot.workspaceId\n ? stateIndex.workspacesByLocalId.get(snapshot.workspaceId) ?? []\n : []\n const workspaceMapping = preferredWorkspaceOrigin\n ? workspaceMappings.find((mapping) => mapping.originInstanceId === preferredWorkspaceOrigin.originInstanceId &&\n mapping.originWorkspaceId === preferredWorkspaceOrigin.originEntityId) ??\n (workspaceMappings.length === 1 ? workspaceMappings[0] : undefined)\n : workspaceMappings.length === 1 ? workspaceMappings[0] : undefined\n const inheritedFrom = snapshot.inheritedFromSessionId\n ? stateIndex.recordsByLocalId.get(snapshot.inheritedFromSessionId)\n : undefined\n const inheritedFromOrigin = inheritedFrom\n ? { originInstanceId: inheritedFrom.originInstanceId, originEntityId: inheritedFrom.originEntityId }\n : undefined\n return {\n text: snapshot.text,\n capturedAt: snapshot.capturedAt,\n ...(workspaceMapping ? {\n workspaceOrigin: { originInstanceId: workspaceMapping.originInstanceId, originEntityId: workspaceMapping.originWorkspaceId },\n workspaceRemotePath: workspaceMapping.remotePath,\n } : {}),\n ...(snapshot.workspaceRevision === undefined ? {} : { workspaceRevision: snapshot.workspaceRevision }),\n ...(snapshot.digest === undefined ? {} : { digest: snapshot.digest }),\n ...(inheritedFromOrigin ? { inheritedFromOrigin } : {}),\n }\n}\n\nexport class SyncSessionService {\n private operationTail: Promise<void> = Promise.resolve()\n private readonly exportCache = new Map<string, SessionExportCacheEntry>()\n private readonly exportCacheStore: SyncSessionExportCacheStore\n private readonly manifestPayloadCache = new Map<string, SessionManifestPayloadCache>()\n private manifestPayloadCacheBytes = 0\n\n constructor(\n private readonly state: SyncStateStore,\n private readonly nodes: SyncNodeService,\n private readonly registry: NodeRegistry,\n private readonly bindings: WorkspaceBindingsStore,\n private readonly getWorkspaces: () => WorkspaceRegistryLike | undefined,\n private readonly getPersistence: () => SessionPersistenceLike | undefined,\n private readonly getAttachments: () => AttachmentStoreLike | undefined,\n private readonly getSpills: () => SpillStoreLike | undefined,\n private readonly instructions: SessionInstructionSnapshotStore,\n private readonly journal = new SyncSessionJournalStore(),\n private readonly now: () => number = Date.now,\n home?: string,\n ) {\n this.exportCacheStore = new SyncSessionExportCacheStore(home)\n for (const [key, entry] of this.exportCacheStore.entries()) {\n if (!this.exportCache.has(key)) {\n this.exportCache.set(key, entry)\n }\n }\n }\n\n exportBundle(): Promise<SyncSessionBundle> {\n return this.serializeMutation(() => this.exportBundleNow())\n }\n\n exportManifest(): Promise<SyncSessionManifest> {\n return this.serializeMutation(async () => {\n const payloadCache: SessionManifestPayloadCache = {\n instanceId: this.state.instanceId(),\n entries: new Map(),\n bytes: 0,\n }\n const bundle = await this.exportBundleNow({ manifestOnly: true, payloadCache })\n const manifest = makeSyncSessionManifest(bundle.instanceId, bundle.entries, bundle.skipped)\n this.rememberManifestPayloads(manifest.digest, payloadCache)\n return manifest\n })\n }\n\n exportEntries(\n keys: readonly string[],\n manifestDigest?: string,\n prefixes: readonly SyncSessionEventPrefix[] = [],\n options: { sharedObjects?: boolean } = {},\n ): Promise<SyncSessionBundle> {\n return this.serializeMutation(async () => {\n if (keys.length > MAX_SYNC_SESSIONS || keys.some((key) => typeof key !== 'string' || key.length > 2048) ||\n new Set(keys).size !== keys.length) {\n throw new SyncSessionError('manifest-invalid', 'session entry selection is invalid')\n }\n if (manifestDigest !== undefined && !/^sha256:[a-f0-9]{64}$/.test(manifestDigest)) {\n throw new SyncSessionError('manifest-invalid', 'session manifest digest is invalid')\n }\n const selectedKeys = new Set(keys)\n const prefixesByKey = new Map<string, SyncSessionEventPrefix>()\n for (const prefix of prefixes) {\n if (!selectedKeys.has(prefix.key) || prefixesByKey.has(prefix.key) ||\n !isNonNegativeSafeInteger(prefix.eventCount) || prefix.eventCount > MAX_SYNC_SESSIONS * 100 ||\n !/^sha256:[a-f0-9]{64}$/.test(prefix.eventDigest) ||\n !isNonNegativeSafeInteger(prefix.inheritedEventCount) || prefix.inheritedEventCount > prefix.eventCount) {\n throw new SyncSessionError('manifest-invalid', 'session event prefix is invalid')\n }\n prefixesByKey.set(prefix.key, prefix)\n }\n let bundle: SyncSessionBundle\n const payloadCache = manifestDigest ? this.manifestPayloadCache.get(manifestDigest) : undefined\n if (payloadCache) {\n const cachedEntries = keys.flatMap((key) => {\n const entry = payloadCache.entries.get(key)\n return entry ? [entry] : []\n })\n const cachedKeys = new Set(cachedEntries.map(syncSessionEntryKey))\n const missingKeys = keys.filter((key) => !cachedKeys.has(key))\n const additional = missingKeys.length > 0\n ? await this.exportBundleNow({ selectedKeys: new Set(missingKeys) })\n : makeSyncSessionBundle(payloadCache.instanceId, [])\n bundle = makeSyncSessionBundle(payloadCache.instanceId, [...cachedEntries, ...additional.entries], additional.skipped)\n } else {\n bundle = await this.exportBundleNow({ selectedKeys, sharedObjects: options.sharedObjects === true })\n }\n const withTails = bundle.entries.map((entry) => withEventTail(entry, prefixesByKey.get(syncSessionEntryKey(entry))))\n if (bundle.objects !== undefined) {\n return makeSyncSessionBundle(bundle.instanceId, withTails, bundle.skipped, bundle.objects)\n }\n const inlineEntries = withTails.map((entry) => {\n if (entry.sharedObjectIds === undefined) return entry\n const { sharedObjectIds, ...rest } = entry\n void sharedObjectIds\n return rest\n })\n const sharedObjects = options.sharedObjects === true ? this.dedupeBundleObjects(inlineEntries) : undefined\n return makeSyncSessionBundle(bundle.instanceId, inlineEntries, bundle.skipped, sharedObjects)\n })\n }\n\n private rememberManifestPayloads(digest: string, payloads: SessionManifestPayloadCache): void {\n if (payloads.entries.size === 0 || payloads.bytes > MAX_MANIFEST_PAYLOAD_CACHE_BYTES) return\n const previous = this.manifestPayloadCache.get(digest)\n if (previous) {\n this.manifestPayloadCacheBytes -= previous.bytes\n this.manifestPayloadCache.delete(digest)\n }\n while (this.manifestPayloadCache.size >= MAX_MANIFEST_PAYLOAD_CACHE_COUNT ||\n this.manifestPayloadCacheBytes + payloads.bytes > MAX_MANIFEST_PAYLOAD_CACHE_BYTES) {\n const oldest = this.manifestPayloadCache.entries().next().value as [string, SessionManifestPayloadCache] | undefined\n if (!oldest) return\n this.manifestPayloadCache.delete(oldest[0])\n this.manifestPayloadCacheBytes -= oldest[1].bytes\n }\n this.manifestPayloadCache.set(digest, payloads)\n this.manifestPayloadCacheBytes += payloads.bytes\n }\n\n applyBundle(\n value: unknown,\n sourceName: string,\n peerId = 'p-000000000000000000000000',\n options: SyncSessionApplyOptions = {},\n ): Promise<SyncSessionApplyResult> {\n return this.serializeMutation(() => this.applyBundleNow(value, sourceName, peerId, options))\n }\n\n preflightBundle(value: unknown, options: SyncSessionApplyOptions = {}): void {\n const bundle = validateSyncSessionBundle(value)\n if (bundle.instanceId === this.state.instanceId() && !options.allowSameInstance) {\n throw new SyncSessionError('same-instance', 'cannot import sessions from this instance')\n }\n const state = this.state.read()\n for (const entry of bundle.entries) {\n if (entry.metadata.deleted) {\n const current = state.records[sessionOriginKey(entry.metadata)]\n if (!current) continue\n const comparison = compareSyncRevision(entry.metadata.revision, current.revision)\n if (comparison === 0 && (entry.metadata.contentDigest !== current.contentDigest || !current.deleted)) {\n throw new SyncSessionError('revision-conflict', 'Equal session revisions contain different tombstone state')\n }\n continue\n }\n if (entry.branchId) {\n const current = state.archives[entry.branchId]\n if (!current) continue\n const comparison = compareSyncRevision(entry.metadata.revision, current.revision)\n if (comparison === 0 && (entry.metadata.contentDigest !== current.contentDigest || entry.metadata.stateDigest !== current.stateDigest)) {\n throw new SyncSessionError('revision-conflict', 'Equal archive revisions contain different content')\n }\n if (comparison > 0 && entry.metadata.contentDigest !== current.contentDigest) {\n throw new SyncSessionError('archive-conflict', 'A session archive ID was reused for different content')\n }\n continue\n }\n const current = state.records[sessionOriginKey(entry.metadata)]\n if (!current || current.deleted) continue\n const comparison = compareSyncRevision(entry.metadata.revision, current.revision)\n if (comparison === 0 && (entry.metadata.contentDigest !== current.contentDigest || entry.metadata.stateDigest !== current.stateDigest)) {\n throw new SyncSessionError('revision-conflict', 'Equal session revisions contain different content')\n }\n }\n }\n\n pendingPeerIds(): string[] {\n return this.journal.pendingPeerIds()\n }\n\n async recoverPending(): Promise<void> {\n const failures: unknown[] = []\n for (const batch of this.journal.pendingBatches()) {\n try {\n const bundle = this.journal.readBundle(batch.batchId)\n if (bundle === undefined) throw new SyncSessionError('journal-missing-bundle', '未完成的会话 journal 缺少 bundle')\n const validatedBundle = validateSyncSessionBundle(bundle)\n if (validatedBundle.digest !== batch.bundleDigest) {\n throw new SyncSessionError('journal-bundle-mismatch', '会话 journal bundle 摘要不匹配')\n }\n await this.serializeMutation(() => this.applyBundleNow(bundle, batch.sourceName, batch.peerId, {\n importedVia: batch.importedVia,\n allowSameInstance: batch.allowSameInstance,\n }, batch))\n } catch (error) {\n failures.push(error)\n }\n }\n if (failures.length > 0) {\n throw new AggregateError(failures, 'One or more sync session batches remain pending')\n }\n }\n\n cleanupOrphanedStaging(): void {\n this.journal.cleanupOrphanedStaging()\n }\n\n listArchives(): SyncSessionArchive[] {\n return Object.values(this.state.read().archives).sort((a, b) => a.archivedAt.localeCompare(b.archivedAt))\n }\n\n restoreArchive(branchId: string): Promise<SessionId> {\n return this.serializeMutation(() => this.restoreArchiveNow(branchId))\n }\n\n private async reuseCachedManifestEntry(\n persistence: SessionPersistenceLike,\n workspace: WorkspaceLike,\n descriptor: SyncSessionWorkspace,\n workspacePosition: number,\n sessionId: SessionId,\n firstSnapshot: SessionSnapshotLike,\n pinned: boolean,\n current: SyncRecordMetadata | undefined,\n stateIndex: SessionStateIndex,\n ): Promise<SyncSessionEntry | undefined> {\n if (!current || current.deleted || !current.workspaceOrigin) return undefined\n const cache = this.exportCache.get(sessionExportCacheKey(String(sessionId)))\n if (!cache || cache.metadata.contentDigest !== current.contentDigest ||\n cache.metadata.originInstanceId !== current.originInstanceId || cache.metadata.originEntityId !== current.originEntityId ||\n current.workspaceOrigin.originInstanceId !== descriptor.originInstanceId ||\n current.workspaceOrigin.originEntityId !== descriptor.originWorkspaceId ||\n current.stateDigest !== sessionStateDigest(descriptor, workspacePosition, false, pinned)) return undefined\n\n const stable = await readStableSessionMetadata(persistence, sessionId, firstSnapshot)\n if (!stable || !stable.header.cwd || posix.normalize(stable.header.cwd) !== posix.normalize(workspace.path)) return undefined\n const parentMetadata = stable.header.parentSession\n ? stateIndex.recordsByLocalId.get(String(stable.header.parentSession))\n : undefined\n const parentOrigin = parentMetadata\n ? { originInstanceId: parentMetadata.originInstanceId, originEntityId: parentMetadata.originEntityId }\n : undefined\n const instructionSnapshot = instructionsForSession(\n this.instructions,\n String(sessionId),\n stateIndex,\n { originInstanceId: descriptor.originInstanceId, originEntityId: descriptor.originWorkspaceId },\n )\n const fingerprint = sessionExportFingerprint({\n revision: stable.snapshot.revision,\n header: stable.header,\n inheritedEventCount: stable.inheritedEventCount,\n workspace: descriptor,\n instructionSnapshot,\n parentOrigin,\n })\n if (!fingerprint || fingerprint !== cache.fingerprint) return undefined\n return {\n metadata: current,\n eventCount: cache.eventCount,\n eventDigest: cache.eventDigest,\n inheritedEventCount: cache.inheritedEventCount,\n }\n }\n\n private async exportBundleNow(options: SessionExportOptions = {}): Promise<SyncSessionBundle> {\n const { manifestOnly = false, selectedKeys, sharedObjects: useSharedObjects = false } = options\n const persistence = this.requirePersistence()\n const workspaceRegistry = this.getWorkspaces()\n if (!workspaceRegistry) throw new SyncSessionError('workspace-unavailable', '工作区注册表不可用')\n await persistence.flush()\n\n const stateIndex = createSessionStateIndex(this.state.read())\n const instanceId = this.state.instanceId()\n const bindings = this.bindings.list()\n const bindingByMirrorPath = new Map<string, (typeof bindings)[number]>()\n for (const binding of bindings) {\n const key = normalizeHostPath(binding.mirrorPath)\n if (!bindingByMirrorPath.has(key)) bindingByMirrorPath.set(key, binding)\n }\n const workspaces = workspaceRegistry.list()\n const archivedIds = new Set(workspaceRegistry.archivedSessionIds.map(String))\n const pinnedIds = new Set((workspaceRegistry.pinnedSessionIds ?? []).map(String))\n const entries: SyncSessionEntry[] = []\n const skipped: Array<{ sessionId: string; reason: string }> = []\n const eligibleLocalIds = new Set<string>()\n const workspaceById = new Map<string, WorkspaceLike>()\n const archivedBranchSessionIds = new Set(Object.values(stateIndex.state.archives).map((archive) => archive.localSessionId))\n const objectCache: ExportObjectCache = new Map()\n const descriptorCache = new Map<string, SyncSessionWorkspace>()\n const getWorkspaceDescriptor = (\n workspace: WorkspaceLike,\n binding: (typeof bindings)[number],\n nodeOrigin: SyncOrigin,\n preferredOrigin?: SyncOrigin,\n ): SyncSessionWorkspace => {\n const key = canonicalJson({\n workspace: { id: String(workspace.id), path: workspace.path, title: workspace.title },\n binding: { mirrorPath: normalizeHostPath(binding.mirrorPath), nodeId: binding.nodeId, remotePath: posix.normalize(binding.remotePath) },\n nodeOrigin,\n preferredOrigin,\n })\n const cached = descriptorCache.get(key)\n if (cached) return cached\n const descriptor = this.workspaceDescriptor(workspace, binding, nodeOrigin, preferredOrigin, stateIndex)\n descriptorCache.set(key, descriptor)\n return descriptor\n }\n\n for (const workspace of workspaces) {\n workspaceById.set(String(workspace.id), workspace)\n const binding = bindingByMirrorPath.get(workspaceCandidateKey(workspace))\n if (!binding) continue\n const node = this.registry.get(binding.nodeId)\n if (!node || !isNodeRemoteType(node.type)) continue\n const nodeOrigin = this.nodes.originForLocalNode(node.id)\n if (!nodeOrigin) continue\n\n for (let position = 0; position < workspace.sessionIds.length; position += 1) {\n const sessionId = String(workspace.sessionIds[position])\n if (archivedBranchSessionIds.has(sessionId)) continue\n const currentSession = stateIndex.recordsByLocalId.get(sessionId)\n if (currentSession?.deleted) continue\n const localKey = currentSession\n ? syncSessionEntryKey({ metadata: currentSession })\n : syncRecordKey('session', { originInstanceId: instanceId, originEntityId: sessionId })\n if (selectedKeys && !selectedKeys.has(localKey)) continue\n const descriptor = getWorkspaceDescriptor(workspace, binding, nodeOrigin, currentSession?.workspaceOrigin)\n const snapshot = await persistence.stat(makeSessionId(sessionId))\n if (!snapshot) continue\n if (snapshot.formatStatus === 'migration-required') {\n throw new SyncSessionError('session-format', '会话格式需要由当前 DSH 版本迁移')\n }\n if (manifestOnly) {\n const cached = await this.reuseCachedManifestEntry(\n persistence,\n workspace,\n descriptor,\n position,\n makeSessionId(sessionId),\n snapshot,\n pinnedIds.has(sessionId),\n currentSession,\n stateIndex,\n )\n if (cached) {\n entries.push(cached)\n eligibleLocalIds.add(sessionId)\n continue\n }\n }\n const exported = await this.exportSessionEntry(\n persistence,\n workspace,\n descriptor,\n position,\n makeSessionId(sessionId),\n snapshot,\n archivedIds.has(sessionId),\n pinnedIds.has(sessionId),\n undefined,\n stateIndex,\n objectCache,\n )\n if (exported) {\n const { entry } = exported\n if (manifestOnly && options.payloadCache) {\n const key = syncSessionEntryKey(entry)\n const size = estimateJsonBytes(entry, MAX_MANIFEST_PAYLOAD_CACHE_BYTES - options.payloadCache.bytes)\n if (size !== undefined) {\n options.payloadCache.entries.set(key, entry)\n options.payloadCache.bytes += size\n }\n }\n entries.push(manifestOnly\n ? {\n metadata: entry.metadata,\n ...(entry.branchId ? { branchId: entry.branchId } : {}),\n eventCount: exported.eventCount,\n eventDigest: exported.eventDigest,\n inheritedEventCount: exported.inheritedEventCount,\n }\n : entry)\n eligibleLocalIds.add(sessionId)\n } else skipped.push({ sessionId, reason: 'workspace-cwd-mismatch' })\n }\n }\n\n const initial = stateIndex.state\n for (const metadata of Object.values(initial.records)) {\n if (\n metadata.kind !== 'session' || archivedBranchSessionIds.has(metadata.localEntityId)\n ) continue\n if (selectedKeys && !selectedKeys.has(syncSessionEntryKey({ metadata }))) continue\n if (metadata.deleted) {\n entries.push({ metadata })\n const tombstoneKey = sessionExportCacheKey(metadata.localEntityId)\n this.exportCache.delete(tombstoneKey)\n this.exportCacheStore.delete(tombstoneKey)\n continue\n }\n if (eligibleLocalIds.has(metadata.localEntityId)) continue\n const tombstone: SyncRecordMetadata = {\n ...metadata,\n revision: this.state.nextRevision(this.now()),\n contentDigest: tombstoneDigest(metadata),\n deleted: true,\n }\n this.state.update((state) => {\n state.records[sessionOriginKey(metadata)] = tombstone\n })\n indexSessionRecord(stateIndex, tombstone)\n const tombstoneKey = sessionExportCacheKey(metadata.localEntityId)\n this.exportCache.delete(tombstoneKey)\n this.exportCacheStore.delete(tombstoneKey)\n entries.push({ metadata: tombstone })\n }\n\n for (const archive of Object.values(stateIndex.state.archives)) {\n if (selectedKeys && !selectedKeys.has(archive.branchId)) continue\n const workspace = archive.workspaceId ? workspaceById.get(archive.workspaceId) : undefined\n if (!workspace) continue\n const binding = bindingByMirrorPath.get(workspaceCandidateKey(workspace))\n const node = binding ? this.registry.get(binding.nodeId) : undefined\n if (!binding || !node || !isNodeRemoteType(node.type)) continue\n const nodeOrigin = this.nodes.originForLocalNode(node.id)\n if (!nodeOrigin) continue\n const archivedMetadata = stateIndex.archivesByLocalSessionId.get(archive.localSessionId)\n const descriptor = getWorkspaceDescriptor(workspace, binding, nodeOrigin, archivedMetadata?.workspaceOrigin)\n const snapshot = await persistence.stat(makeSessionId(archive.localSessionId))\n if (!snapshot) continue\n const exported = await this.exportSessionEntry(\n persistence,\n workspace,\n descriptor,\n archive.workspacePosition,\n makeSessionId(archive.localSessionId),\n snapshot,\n true,\n false,\n archive,\n stateIndex,\n objectCache,\n )\n if (exported) {\n const { entry } = exported\n if (manifestOnly && options.payloadCache) {\n const key = syncSessionEntryKey(entry)\n const size = estimateJsonBytes(entry, MAX_MANIFEST_PAYLOAD_CACHE_BYTES - options.payloadCache.bytes)\n if (size !== undefined) {\n options.payloadCache.entries.set(key, entry)\n options.payloadCache.bytes += size\n }\n }\n entries.push(manifestOnly\n ? {\n metadata: entry.metadata,\n ...(entry.branchId ? { branchId: entry.branchId } : {}),\n eventCount: exported.eventCount,\n eventDigest: exported.eventDigest,\n inheritedEventCount: exported.inheritedEventCount,\n }\n : entry)\n } else skipped.push({ sessionId: archive.localSessionId, reason: 'archive-workspace-cwd-mismatch' })\n }\n\n const bundleSharedObjects = useSharedObjects && entries.some((entry) => (entry.objects?.length ?? 0) > 0)\n ? this.dedupeBundleObjects(entries)\n : undefined\n this.exportCacheStore.flush()\n return makeSyncSessionBundle(instanceId, entries, skipped, bundleSharedObjects)\n }\n\n private dedupeBundleObjects(entries: SyncSessionEntry[]): SyncSessionObject[] {\n const shared = new Map<string, SyncSessionObject>()\n for (const entry of entries) {\n for (const object of entry.objects ?? []) {\n const current = shared.get(object.id)\n if (current === undefined) shared.set(object.id, object)\n else if (current.digest !== object.digest || current.bytes !== object.bytes) {\n throw new SyncSessionError('object-invalid', 'the same object id carries different payloads')\n }\n }\n }\n return [...shared.values()]\n }\n\n private async applyBundleNow(\n value: unknown,\n sourceName: string,\n peerId: string,\n options: SyncSessionApplyOptions,\n recoveryBatch?: SyncSessionJournalBatch,\n ): Promise<SyncSessionApplyResult> {\n const transferredBundle = validateSyncSessionBundle(value)\n const importedVia = recoveryBatch?.importedVia ?? options.importedVia ?? 'peer'\n if (importedVia !== 'peer' && transferredBundle.entries.some((entry) => entry.eventDelta)) {\n throw new SyncSessionError('manifest-invalid', 'event tail deltas are only accepted from sync peers')\n }\n let pendingBatch = recoveryBatch ?? this.journal.findBatch(peerId, transferredBundle.digest)\n if (pendingBatch && !transferredBundle.entries.some((entry) => entry.eventDelta) &&\n (pendingBatch.bundleDigest !== transferredBundle.digest || pendingBatch.peerId !== peerId)) {\n throw new SyncSessionError('journal-bundle-mismatch', '会话 journal batch 与 bundle 不匹配')\n }\n if (!pendingBatch) await this.exportBundleNow({ manifestOnly: true })\n const bundle = await this.expandEventDeltas(transferredBundle)\n pendingBatch ??= recoveryBatch ?? this.journal.findBatch(peerId, bundle.digest)\n if (pendingBatch && (pendingBatch.bundleDigest !== bundle.digest || pendingBatch.peerId !== peerId)) {\n throw new SyncSessionError('journal-bundle-mismatch', '会话 journal batch 与 bundle 不匹配')\n }\n const resolvedImportedVia = pendingBatch?.importedVia ?? importedVia\n const allowSameInstance = pendingBatch?.allowSameInstance ?? options.allowSameInstance ?? false\n const localInstanceId = this.state.instanceId()\n if (bundle.instanceId === localInstanceId && !allowSameInstance) {\n throw new SyncSessionError('same-instance', 'cannot import sessions from this instance')\n }\n this.preflightBundle(bundle, { importedVia: resolvedImportedVia, allowSameInstance })\n const safeSourceName = (pendingBatch?.sourceName ?? sourceName).replace(/[\\u0000-\\u001f\\u007f]/g, ' ').trim().slice(0, 128) || 'sync peer'\n const recordKeys = bundle.entries.map((entry) => entry.branchId ?? sessionOriginKey(entry.metadata))\n const batchId = pendingBatch?.batchId ?? this.journal.beginWithBundle(\n peerId,\n safeSourceName,\n bundle.digest,\n recordKeys,\n bundle,\n new Date(this.now()).toISOString(),\n resolvedImportedVia,\n allowSameInstance,\n )\n const result = emptyApplyResult()\n const attachmentImportCache = new Map<string, ImportedSessionObjectRef>()\n result.skipped += bundle.skipped.length\n result.unmapped += bundle.skipped.length\n const workspaceOrders = new Map<string, Array<{ id: SessionId; position: number }>>()\n const plannedSessionIds = new Map<string, SessionId>()\n for (const entry of bundle.entries) {\n if (!entry.metadata.deleted && !entry.branchId) {\n const current = this.state.read().records[sessionOriginKey(entry.metadata)]\n const localId = current && !current.deleted && current.contentDigest === entry.metadata.contentDigest\n ? makeSessionId(current.localEntityId)\n : importedSessionId(entry.metadata)\n plannedSessionIds.set(sessionOriginKey(entry.metadata), localId)\n }\n }\n const workspaceResolutions = new Map<string, Promise<WorkspaceLike | undefined>>()\n const resolveWorkspace = (entry: SyncSessionEntry): Promise<WorkspaceLike | undefined> => {\n const descriptor = entry.workspace\n if (!descriptor) return Promise.resolve(undefined)\n const workspaceKey = syncWorkspaceKey(descriptor.originInstanceId, descriptor.originWorkspaceId, descriptor.remotePath)\n let resolution = workspaceResolutions.get(workspaceKey)\n if (!resolution) {\n resolution = this.ensureWorkspace(descriptor).catch((error: unknown) => {\n if (error instanceof SyncSessionError && error.code === 'workspace-unmapped') return undefined\n throw error\n })\n workspaceResolutions.set(workspaceKey, resolution)\n }\n return resolution\n }\n\n try {\n const queueWorkspaceOrder = (workspaceId: string, id: SessionId, position: number): void => {\n const order = workspaceOrders.get(workspaceId) ?? []\n order.push({ id, position })\n workspaceOrders.set(workspaceId, order)\n }\n const entries = [...bundle.entries].sort((a, b) => {\n if (a.branchId || b.branchId) return (a.branchId ?? '').localeCompare(b.branchId ?? '')\n if (a.workspace?.originWorkspaceId !== b.workspace?.originWorkspaceId) {\n return (a.workspace?.originWorkspaceId ?? '').localeCompare(b.workspace?.originWorkspaceId ?? '')\n }\n return (b.workspacePosition ?? 0) - (a.workspacePosition ?? 0)\n })\n\n for (const entry of entries) {\n const key = entry.branchId ?? sessionOriginKey(entry.metadata)\n if (entry.metadata.deleted) {\n const changed = await this.applyTombstone(entry.metadata)\n if (changed) result.deleted += 1\n else result.skipped += 1\n continue\n }\n const entryWorkspace = await resolveWorkspace(entry)\n if (!entryWorkspace) {\n result.skipped += 1\n result.unmapped += 1\n continue\n }\n\n const currentState = this.state.read()\n const currentArchive = entry.branchId ? currentState.archives[entry.branchId] : undefined\n if (entry.branchId && currentArchive) {\n const comparison = compareSyncRevision(entry.metadata.revision, currentArchive.revision)\n if (comparison < 0) {\n result.skipped += 1\n continue\n }\n if (comparison === 0) {\n if (entry.metadata.contentDigest !== currentArchive.contentDigest || entry.metadata.stateDigest !== currentArchive.stateDigest) {\n throw new SyncSessionError('revision-conflict', 'Equal archive revisions contain different content')\n }\n const sessionId = makeSessionId(currentArchive.localSessionId)\n const snapshot = await this.requirePersistence().stat(sessionId)\n if (snapshot && normalizeHostPath(snapshot.header.cwd ?? '') === normalizeHostPath(entryWorkspace.path)) {\n await entryWorkspace.attachSession(sessionId)\n queueWorkspaceOrder(entryWorkspace.id, sessionId, entry.workspacePosition ?? currentArchive.workspacePosition)\n }\n result.skipped += 1\n continue\n }\n if (entry.metadata.contentDigest !== currentArchive.contentDigest) {\n throw new SyncSessionError('archive-conflict', 'A session archive ID was reused for different content')\n }\n await this.applyArchiveStateOnly(entry, currentArchive, entryWorkspace)\n result.updated += 1\n queueWorkspaceOrder(entryWorkspace.id, makeSessionId(currentArchive.localSessionId), entry.workspacePosition ?? 0)\n continue\n }\n const current = entry.branchId ? undefined : currentState.records[sessionOriginKey(entry.metadata)]\n if (current) {\n const comparison = compareSyncRevision(entry.metadata.revision, current.revision)\n if (comparison < 0) {\n result.skipped += 1\n continue\n }\n if (comparison === 0) {\n if (current.deleted || entry.metadata.contentDigest !== current.contentDigest || entry.metadata.stateDigest !== current.stateDigest) {\n throw new SyncSessionError('revision-conflict', 'Equal session revisions contain different content')\n }\n const sessionId = makeSessionId(current.localEntityId)\n const snapshot = await this.requirePersistence().stat(sessionId)\n if (snapshot && normalizeHostPath(snapshot.header.cwd ?? '') === normalizeHostPath(entryWorkspace.path)) {\n await entryWorkspace.attachSession(sessionId)\n queueWorkspaceOrder(entryWorkspace.id, sessionId, entry.workspacePosition ?? 0)\n }\n result.skipped += 1\n continue\n }\n if (!current.deleted && entry.metadata.contentDigest === current.contentDigest && (await this.requirePersistence().stat(makeSessionId(current.localEntityId)))) {\n await this.applyMembershipOnly(entry, current, safeSourceName, entryWorkspace, resolvedImportedVia)\n result.updated += 1\n queueWorkspaceOrder(entryWorkspace.id, makeSessionId(current.localEntityId), entry.workspacePosition ?? 0)\n continue\n }\n }\n\n let preparedValue = this.journal.readPrepared(batchId, key)\n let prepared: PreparedSyncSession\n if (preparedValue === undefined) {\n try {\n prepared = await this.prepareEntry(entry, safeSourceName, plannedSessionIds, entryWorkspace, resolvedImportedVia, attachmentImportCache)\n } catch (error) {\n if (error instanceof SyncSessionError && error.code === 'workspace-unmapped') {\n result.skipped += 1\n result.unmapped += 1\n continue\n }\n throw error\n }\n this.journal.writePrepared(batchId, key, prepared)\n preparedValue = prepared\n }\n prepared = this.validatePrepared(preparedValue)\n\n if (current && !current.deleted && current.localEntityId !== prepared.localSessionId) {\n if (await this.archiveCurrent(current)) result.archived += 1\n }\n\n const existed = (await this.requirePersistence().stat(prepared.localSessionId)) !== undefined\n await this.applyPrepared(prepared)\n if (prepared.branchId) result.archived += 1\n else if (existed) result.updated += 1\n else result.created += 1\n\n queueWorkspaceOrder(prepared.workspaceId, prepared.localSessionId, prepared.workspacePosition)\n }\n\n await this.orderWorkspaceSessions(workspaceOrders)\n this.journal.complete(batchId)\n this.exportCacheStore.flush()\n return result\n } catch (error) {\n if (error instanceof SyncSessionError) throw error\n throw new SyncSessionError('session-apply-failed', '会话同步应用失败', error)\n }\n }\n\n private async expandEventDeltas(bundle: SyncSessionBundle): Promise<SyncSessionBundle> {\n if (!bundle.entries.some((entry) => entry.eventDelta)) return bundle\n const persistence = this.requirePersistence()\n const state = this.state.read()\n const entries: SyncSessionEntry[] = []\n for (const entry of bundle.entries) {\n const delta = entry.eventDelta\n if (!delta) {\n entries.push(entry)\n continue\n }\n const current = state.records[sessionOriginKey(entry.metadata)]\n if (!current || current.deleted) throw new SyncSessionError('session-delta-prefix', 'event delta base session is missing')\n const snapshot = await persistence.stat(makeSessionId(current.localEntityId))\n if (!snapshot) throw new SyncSessionError('session-delta-prefix', 'event delta base session is missing')\n const stable = await this.readStableSession(persistence, makeSessionId(current.localEntityId), snapshot)\n if (stable.events.length !== delta.baseEventCount ||\n stable.inheritedEventCount !== delta.baseInheritedEventCount ||\n sessionEventListDigest(stable.events) !== delta.baseEventDigest) {\n throw new SyncSessionError('session-delta-prefix', 'event delta base prefix no longer matches')\n }\n const events = [...stable.events, ...(entry.events ?? [])]\n if (events.length !== delta.fullEventCount || sessionEventListDigest(events) !== delta.fullEventDigest) {\n throw new SyncSessionError('manifest-invalid', 'expanded event delta digest does not match')\n }\n const fullEntry: SyncSessionEntry = { ...entry, events }\n delete fullEntry.eventDelta\n entries.push(fullEntry)\n }\n return validateSyncSessionBundle(makeSyncSessionBundle(bundle.instanceId, entries, bundle.skipped))\n }\n\n private async prepareEntry(\n entry: SyncSessionEntry,\n sourceName: string,\n plannedSessionIds: ReadonlyMap<string, SessionId>,\n workspace: WorkspaceLike,\n importedVia: SyncImportMethod,\n attachmentImportCache?: Map<string, ImportedSessionObjectRef>,\n ): Promise<PreparedSyncSession> {\n if (!entry.header || !entry.events || !entry.workspace || !entry.objects) {\n throw new SyncSessionError('manifest-invalid', 'active session entry is incomplete')\n }\n const sessionId = entry.branchId ? archivedSessionId(entry.branchId) : importedSessionId(entry.metadata)\n const sourceHeader = entry.header\n const headerWithoutLocalFields = { ...sourceHeader } as Record<string, unknown>\n delete headerWithoutLocalFields.id\n delete headerWithoutLocalFields.cwd\n delete headerWithoutLocalFields.parentSession\n const parentSession = (entry.parentOrigin\n ? plannedSessionIds.get(syncRecordKey('session', entry.parentOrigin)) ?? this.localSessionIdForOrigin(entry.parentOrigin)\n : undefined) ?? sourceHeader.parentSession\n const header: SessionHeader = {\n ...headerWithoutLocalFields,\n id: sessionId,\n cwd: workspace.path,\n ...(parentSession ? { parentSession } : {}),\n } as SessionHeader\n const inheritedEventCount = entry.inheritedEventCount ?? 0\n const persistence = this.requirePersistence()\n if (await persistence.stat(sessionId)) {\n const handle = await persistence.open(sessionId, 'read')\n try {\n if (canonicalJson(handle.header) !== canonicalJson(header) || handle.inheritedEventCount !== inheritedEventCount) {\n throw new SyncSessionError('session-id-conflict', '目标 session ID 已被其他 header 占用')\n }\n } finally {\n await handle.close()\n }\n }\n const objectMap = await this.importObjects(entry.objects, sessionId, attachmentImportCache)\n const events = this.rewriteEvents(entry.events, entry.objects, objectMap, sessionId, String(entry.header.id))\n const validatedEvents = validateStoredEvents(header, events)\n assertContiguous(sessionId, validatedEvents, 0)\n const instructionWorkspaceId = entry.instructionSnapshot?.workspaceOrigin\n ? this.localWorkspaceIdForOrigin(entry.instructionSnapshot.workspaceOrigin, entry.instructionSnapshot.workspaceRemotePath)\n : undefined\n const instructionSnapshot: SessionInstructionSnapshot | undefined = entry.instructionSnapshot\n ? {\n sessionId,\n ...(instructionWorkspaceId ? { workspaceId: instructionWorkspaceId } : {}),\n ...(entry.instructionSnapshot.workspaceRevision === undefined ? {} : { workspaceRevision: entry.instructionSnapshot.workspaceRevision }),\n ...(entry.instructionSnapshot.digest === undefined ? {} : { digest: entry.instructionSnapshot.digest }),\n text: entry.instructionSnapshot.text,\n capturedAt: entry.instructionSnapshot.capturedAt,\n ...(parentSession ? { inheritedFromSessionId: parentSession } : {}),\n }\n : undefined\n return {\n metadata: entry.metadata,\n ...(entry.branchId ? { branchId: entry.branchId } : {}),\n localSessionId: sessionId,\n header,\n inheritedEventCount,\n events: [...validatedEvents],\n workspaceId: workspace.id,\n workspacePath: workspace.path,\n workspace: entry.workspace,\n workspacePosition: entry.workspacePosition ?? 0,\n archived: Boolean(entry.archived || entry.branchId),\n pinned: Boolean(entry.pinned && !entry.archived && !entry.branchId),\n sourceName,\n importedVia,\n ...(instructionSnapshot ? { instructionSnapshot } : {}),\n }\n }\n\n private async ensureWorkspace(descriptor: SyncSessionWorkspace): Promise<WorkspaceLike> {\n const workspaceRegistry = this.getWorkspaces()\n if (!workspaceRegistry) throw new SyncSessionError('workspace-unavailable', '工作区注册表不可用')\n const key = syncWorkspaceKey(descriptor.originInstanceId, descriptor.originWorkspaceId, descriptor.remotePath)\n const committedWorkspace = await this.nodes.withAvailableRemoteNode(descriptor.nodeOrigin, async (activeNodeId) => {\n const node = this.registry.get(activeNodeId)\n if (!node || !isNodeRemoteType(node.type)) return undefined\n const latest = this.state.read().workspaces[key]\n const latestComparison = latest ? compareSyncRevision(descriptor.revision, latest.revision) : 1\n if (latest && latestComparison === 0 && latest.contentDigest !== descriptor.contentDigest) {\n throw new SyncSessionError('workspace-conflict', 'Equal workspace revisions contain different content')\n }\n const latestTitle = latest && latestComparison < 0 ? latest.title : descriptor.title\n let binding = this.bindings.list().find((item) =>\n item.nodeId === activeNodeId && posix.normalize(item.remotePath) === descriptor.remotePath,\n )\n let workspace = latest ? workspaceRegistry.get(latest.localWorkspaceId) : undefined\n if (!workspace && binding) {\n workspace = workspaceRegistry.list().find((item) => normalizeHostPath(item.path) === normalizeHostPath(binding!.mirrorPath))\n }\n if (!workspace) {\n const mirrorPath = latest?.localPath ?? binding?.mirrorPath ??\n this.bindings.mirrorRoot(activeNodeId, `sync-${createHash('sha256').update(key).digest('hex').slice(0, 20)}`)\n mkdirSync(mirrorPath, { recursive: true, mode: 0o700 })\n workspace = await workspaceRegistry.create(mirrorPath, latestTitle)\n }\n if (workspace.title !== latestTitle) await workspace.setTitle(latestTitle)\n\n let activeBinding = binding ?? this.bindings.list().find((item) =>\n normalizeHostPath(item.mirrorPath) === normalizeHostPath(workspace!.path),\n )\n if (!activeBinding || activeBinding.nodeId !== activeNodeId || posix.normalize(activeBinding.remotePath) !== descriptor.remotePath) {\n activeBinding = {\n mirrorPath: workspace!.path,\n nodeId: activeNodeId,\n remotePath: descriptor.remotePath,\n workspaceId: workspace!.id,\n }\n this.bindings.add(activeBinding)\n }\n const localMappingChanged = !latest || latest.localWorkspaceId !== workspace!.id ||\n latest.localPath !== workspace!.path || latest.localNodeId !== activeNodeId\n if (!latest || latestComparison > 0 || localMappingChanged) {\n const mapping: SyncWorkspaceMapping = {\n ...descriptor,\n title: latestTitle,\n ...(latest && latestComparison < 0 ? { revision: latest.revision, contentDigest: latest.contentDigest } : {}),\n localWorkspaceId: workspace!.id,\n localPath: workspace!.path,\n localNodeId: activeNodeId,\n }\n this.state.update((state) => { state.workspaces[key] = mapping })\n }\n return workspace\n })\n if (!committedWorkspace) throw new SyncSessionError('workspace-unmapped', '目标实例没有对应的可用远程节点')\n return committedWorkspace\n }\n\n private async importObjects(\n objects: readonly SyncSessionObject[],\n sessionId: SessionId,\n attachmentImportCache?: Map<string, ImportedSessionObjectRef>,\n ): Promise<Map<string, ImportedSessionObjectRef>> {\n const attachments = objects.some((object) => object.kind === 'image' || object.kind === 'file')\n ? this.getAttachments()\n : undefined\n const spills = objects.some((object) => object.kind === 'spill' && !object.unavailable) ? this.getSpills() : undefined\n if (objects.some((object) => object.kind === 'image' || object.kind === 'file') && !attachments) {\n throw new SyncSessionError('attachments-unavailable', '目标实例的附件存储服务不可用')\n }\n if (objects.some((object) => object.kind === 'spill' && !object.unavailable) && !spills) {\n throw new SyncSessionError('spill-transfer-unavailable', '目标实例没有 owner-scoped spill transfer API')\n }\n const output = new Map<string, ImportedSessionObjectRef>()\n for (const object of objects) {\n if (object.kind === 'spill' && object.unavailable) continue\n if (object.kind !== 'spill') {\n const cached = attachmentImportCache?.get(object.id)\n if (cached) { output.set(object.id, cached); continue }\n }\n const data = arrayBuffer(object.data)\n if (data.byteLength !== object.bytes || sha256(data) !== object.digest) {\n throw new SyncSessionError('object-integrity', 'session object failed digest validation')\n }\n if (object.kind === 'image') {\n const ref = await attachments!.saveImage({\n data,\n mediaType: object.ref.mediaType,\n ...(object.ref.name === undefined ? {} : { name: object.ref.name }),\n })\n output.set(object.id, ref)\n attachmentImportCache?.set(object.id, ref)\n } else if (object.kind === 'file') {\n const ref = await attachments!.saveFileStream({\n data: oneChunk(data),\n name: object.ref.name,\n })\n output.set(object.id, ref)\n attachmentImportCache?.set(object.id, ref)\n } else {\n const ref = await saveSpillTransfer(spills!, {\n owner: { sessionId },\n source: object.reference.source,\n suggestedName: object.reference.suggestedName,\n transferId: object.id,\n bytes: object.bytes,\n digest: object.digest,\n data,\n })\n output.set(object.id, ref)\n }\n }\n return output\n }\n\n private rewriteEvents(\n events: readonly SessionEvent[],\n objects: readonly SyncSessionObject[],\n importedRefs: ReadonlyMap<string, ImportedSessionObjectRef>,\n sessionId: SessionId,\n sourceSessionId: string,\n ): SessionEvent[] {\n const spillReferencesByLocator = new Map<string, { source: SpillTransferReference; target?: SpillTransferReference['ref'] }>()\n for (const object of objects) {\n if (object.kind !== 'spill') continue\n if (object.unavailable) {\n spillReferencesByLocator.set(object.reference.ref.locator, { source: object.reference })\n continue\n }\n const target = importedRefs.get(object.id)\n if (!target || !('locator' in target)) throw new SyncSessionError('spill-reference-missing', '目标 spill reference 未创建')\n spillReferencesByLocator.set(object.reference.ref.locator, { source: object.reference, target })\n }\n\n const rewrite = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(rewrite)\n if (!isRecord(value)) return value\n if (value.type === 'image' && isImageRef(value.attachment)) {\n const target = importedRefs.get(attachmentKey('image', value.attachment))\n if (!target || !('mediaType' in target)) throw new SyncSessionError('attachment-reference-missing', '目标图片附件未创建')\n return { ...value, attachment: target }\n }\n if (value.type === 'file' && isFileRef(value.attachment)) {\n const target = importedRefs.get(attachmentKey('file', value.attachment))\n if (!target || !('name' in target)) throw new SyncSessionError('attachment-reference-missing', '目标文件附件未创建')\n return { ...value, attachment: target }\n }\n if (value.type === 'session-log-deepseek/delivery-accepted' && isRecord(value.data) && value.data.sessionId === sourceSessionId) {\n // Inherited markers keep their ancestor ID; current-session markers follow the imported header ID.\n return { ...value, data: { ...value.data, sessionId } }\n }\n const output: Record<string, unknown> = {}\n for (const [key, child] of Object.entries(value)) {\n if (key === SPILL_ARTIFACT_META_KEY && isRecord(child) && Array.isArray(child.references)) {\n const filteredReferences = child.references.filter((entry) => {\n if (!isRecord(entry) || !isRecord(entry.owner) || !isRecord(entry.ref)) return false\n const reference = entry as unknown as SpillTransferReference\n const mapped = spillReferencesByLocator.get(reference.ref.locator)\n return mapped?.target !== undefined\n })\n if (filteredReferences.length === 0) continue\n output[key] = {\n version: child.version,\n references: filteredReferences.map((entry) => {\n const reference = entry as unknown as SpillTransferReference\n const mapped = spillReferencesByLocator.get(reference.ref.locator)\n if (!mapped?.target) throw new SyncSessionError('spill-reference-missing', '目标 spill reference 未创建')\n return { ...reference, owner: { sessionId }, ref: mapped.target }\n }),\n }\n } else if (key === 'text' && typeof child === 'string') {\n let text = child\n for (const { source, target } of spillReferencesByLocator.values()) {\n if (!target) continue\n text = text.replaceAll(\n `Full formatted result stored at: ${source.ref.locator}. ${source.ref.retrievalHint}`,\n `Full formatted result stored at: ${target.locator}. ${target.retrievalHint}`,\n )\n }\n output[key] = text\n } else {\n output[key] = rewrite(child)\n }\n }\n return output\n }\n return events.map((event) => snapshotSessionEvent(rewrite(structuredClone(event)) as SessionEvent))\n }\n\n private validatePrepared(value: unknown): PreparedSyncSession {\n if (\n !isRecord(value) || !isRecord(value.metadata) || value.metadata.kind !== 'session' ||\n typeof value.localSessionId !== 'string' || !isRecord(value.header) || value.header.id !== value.localSessionId ||\n typeof value.workspaceId !== 'string' || typeof value.workspacePath !== 'string' ||\n !Array.isArray(value.events) || typeof value.workspacePosition !== 'number' ||\n typeof value.archived !== 'boolean' || typeof value.pinned !== 'boolean' || typeof value.sourceName !== 'string' ||\n (value.importedVia !== 'peer' && value.importedVia !== 'offline')\n ) throw new SyncSessionError('journal-invalid', 'prepared session record is invalid')\n const header = value.header as unknown as SessionHeader\n if (header.version !== SESSION_FORMAT_VERSION) throw new SyncSessionError('session-format', 'prepared session format is unsupported')\n const events = validateStoredEvents(header, structuredClone(value.events) as SessionEvent[])\n assertContiguous(header.id, events, 0)\n if (\n !Number.isSafeInteger(value.workspacePosition) || value.workspacePosition < 0 ||\n typeof value.inheritedEventCount !== 'number' || !Number.isSafeInteger(value.inheritedEventCount) || value.inheritedEventCount < 0 ||\n !isRecord(value.workspace)\n ) throw new SyncSessionError('journal-invalid', 'prepared session metadata is invalid')\n return {\n metadata: value.metadata as unknown as SyncRecordMetadata,\n ...(typeof value.branchId === 'string' ? { branchId: value.branchId } : {}),\n localSessionId: makeSessionId(value.localSessionId),\n header,\n inheritedEventCount: value.inheritedEventCount,\n events: [...events],\n workspaceId: value.workspaceId,\n workspacePath: value.workspacePath,\n workspace: value.workspace as unknown as SyncSessionWorkspace,\n workspacePosition: value.workspacePosition,\n archived: value.archived,\n pinned: value.pinned,\n sourceName: value.sourceName,\n importedVia: value.importedVia,\n ...(isRecord(value.instructionSnapshot) ? { instructionSnapshot: value.instructionSnapshot as unknown as SessionInstructionSnapshot } : {}),\n }\n }\n\n private async applyPrepared(prepared: PreparedSyncSession): Promise<boolean> {\n const sessionId = prepared.localSessionId\n const existed = await this.writeSession(prepared)\n\n if (prepared.instructionSnapshot) this.instructions.restore(prepared.instructionSnapshot)\n const registry = this.getWorkspaces()\n const workspace = registry?.get(prepared.workspaceId)\n if (!registry || !workspace || normalizeHostPath(workspace.path) !== normalizeHostPath(prepared.workspacePath)) {\n throw new SyncSessionError('workspace-unmapped', '导入 session 的目标工作区不可用')\n }\n await workspace.attachSession(sessionId)\n if (prepared.archived) await registry.archiveSession(sessionId, { stopActivity: true })\n else await registry.unarchiveSession(sessionId)\n if (prepared.pinned && !prepared.archived) await registry.pinSession?.(sessionId)\n else await registry.unpinSession?.(sessionId)\n\n this.state.observeRevision(prepared.metadata.revision, this.now())\n const binding = this.bindings.list().find((item) => normalizeHostPath(item.mirrorPath) === normalizeHostPath(prepared.workspacePath))\n if (!binding) throw new SyncSessionError('workspace-unmapped', '导入 session 的节点绑定不可用')\n const activeMetadata: SyncRecordMetadata = {\n ...prepared.metadata,\n localEntityId: String(sessionId),\n importedVia: prepared.importedVia,\n sourceName: prepared.sourceName,\n stateDigest: prepared.metadata.stateDigest ?? sessionStateDigest(prepared.workspace, prepared.workspacePosition, prepared.archived, prepared.pinned),\n workspaceOrigin: {\n originInstanceId: prepared.workspace.originInstanceId,\n originEntityId: prepared.workspace.originWorkspaceId,\n },\n deleted: false,\n pendingRemoval: false,\n }\n const key = sessionOriginKey(prepared.metadata)\n this.state.update((state) => {\n const mappingKey = syncWorkspaceKey(\n prepared.workspace.originInstanceId,\n prepared.workspace.originWorkspaceId,\n prepared.workspace.remotePath,\n )\n state.workspaces[mappingKey] = {\n ...prepared.workspace,\n localWorkspaceId: prepared.workspaceId,\n localPath: prepared.workspacePath,\n localNodeId: binding.nodeId,\n }\n if (prepared.branchId) {\n state.archives[prepared.branchId] = {\n branchId: prepared.branchId,\n originInstanceId: prepared.metadata.originInstanceId,\n originSessionId: prepared.metadata.originEntityId,\n localSessionId: String(sessionId),\n revision: prepared.metadata.revision,\n contentDigest: prepared.metadata.contentDigest,\n stateDigest: prepared.metadata.stateDigest ?? sessionStateDigest(prepared.workspace, prepared.workspacePosition, true, false),\n workspacePosition: prepared.workspacePosition,\n workspaceId: prepared.workspaceId,\n workspaceOrigin: {\n originInstanceId: prepared.workspace.originInstanceId,\n originEntityId: prepared.workspace.originWorkspaceId,\n },\n archivedAt: new Date(this.now()).toISOString(),\n }\n } else {\n state.records[key] = activeMetadata\n }\n })\n return existed\n }\n\n private async applyMembershipOnly(\n entry: SyncSessionEntry,\n current: SyncRecordMetadata,\n sourceName: string,\n workspace: WorkspaceLike,\n importedVia: SyncImportMethod,\n ): Promise<void> {\n const descriptor = entry.workspace\n const stateDigest = entry.metadata.stateDigest\n if (!descriptor || !stateDigest) throw new SyncSessionError('manifest-invalid', 'session state entry is incomplete')\n const registry = this.getWorkspaces()\n if (!registry) throw new SyncSessionError('workspace-unavailable', '工作区注册表不可用')\n const sessionId = makeSessionId(current.localEntityId)\n const snapshot = await this.requirePersistence().stat(sessionId)\n if (!snapshot || normalizeHostPath(snapshot.header.cwd ?? '') !== normalizeHostPath(workspace.path)) {\n throw new SyncSessionError('session-workspace-mismatch', '既有 session 的本地 cwd 与目标 workspace 不一致')\n }\n await workspace.attachSession(sessionId)\n if (entry.archived) await registry.archiveSession(sessionId, { stopActivity: true })\n else await registry.unarchiveSession(sessionId)\n if (entry.pinned && !entry.archived) await registry.pinSession?.(sessionId)\n else await registry.unpinSession?.(sessionId)\n if (entry.instructionSnapshot) {\n const inheritedFromSessionId = entry.parentOrigin ? this.localSessionIdForOrigin(entry.parentOrigin) : undefined\n const instructionWorkspaceId = entry.instructionSnapshot.workspaceOrigin\n ? this.localWorkspaceIdForOrigin(entry.instructionSnapshot.workspaceOrigin, entry.instructionSnapshot.workspaceRemotePath)\n : undefined\n const snapshot: SessionInstructionSnapshot = {\n sessionId,\n ...(instructionWorkspaceId ? { workspaceId: instructionWorkspaceId } : {}),\n ...(entry.instructionSnapshot.workspaceRevision === undefined ? {} : { workspaceRevision: entry.instructionSnapshot.workspaceRevision }),\n ...(entry.instructionSnapshot.digest === undefined ? {} : { digest: entry.instructionSnapshot.digest }),\n text: entry.instructionSnapshot.text,\n capturedAt: entry.instructionSnapshot.capturedAt,\n ...(inheritedFromSessionId ? { inheritedFromSessionId } : {}),\n }\n this.instructions.restore(snapshot)\n }\n this.state.observeRevision(entry.metadata.revision, this.now())\n const metadata: SyncRecordMetadata = {\n ...entry.metadata,\n localEntityId: current.localEntityId,\n importedVia,\n sourceName,\n stateDigest,\n deleted: false,\n pendingRemoval: false,\n workspaceOrigin: {\n originInstanceId: descriptor.originInstanceId,\n originEntityId: descriptor.originWorkspaceId,\n },\n }\n this.state.update((state) => { state.records[sessionOriginKey(metadata)] = metadata })\n }\n\n private async applyArchiveStateOnly(\n entry: SyncSessionEntry,\n current: SyncSessionArchive,\n workspace: WorkspaceLike,\n ): Promise<void> {\n const branchId = entry.branchId\n const descriptor = entry.workspace\n const stateDigest = entry.metadata.stateDigest\n if (!branchId || !descriptor || !stateDigest) {\n throw new SyncSessionError('manifest-invalid', 'archive state entry is incomplete')\n }\n const registry = this.getWorkspaces()\n if (!registry) throw new SyncSessionError('workspace-unavailable', '工作区注册表不可用')\n const sessionId = makeSessionId(current.localSessionId)\n const snapshot = await this.requirePersistence().stat(sessionId)\n if (!snapshot || normalizeHostPath(snapshot.header.cwd ?? '') !== normalizeHostPath(workspace.path)) {\n throw new SyncSessionError('session-workspace-mismatch', '归档 session 的本地 cwd 与目标 workspace 不一致')\n }\n await workspace.attachSession(sessionId)\n await registry.archiveSession(sessionId, { stopActivity: true })\n await registry.unpinSession?.(sessionId)\n this.state.observeRevision(entry.metadata.revision, this.now())\n this.state.update((state) => {\n state.archives[branchId] = {\n ...current,\n revision: entry.metadata.revision,\n stateDigest,\n workspacePosition: entry.workspacePosition ?? current.workspacePosition,\n workspaceId: workspace.id,\n workspaceOrigin: {\n originInstanceId: descriptor.originInstanceId,\n originEntityId: descriptor.originWorkspaceId,\n },\n }\n })\n }\n\n private async archiveCurrent(metadata: SyncRecordMetadata): Promise<string | undefined> {\n if (metadata.deleted || metadata.kind !== 'session') return undefined\n const branchId = branchIdFor(metadata)\n const state = this.state.read()\n if (state.archives[branchId]) return branchId\n const sessionId = makeSessionId(metadata.localEntityId)\n const persistence = this.requirePersistence()\n if (!(await persistence.stat(sessionId))) return undefined\n await persistence.flush()\n const registry = this.getWorkspaces()\n if (!registry) throw new SyncSessionError('workspace-unavailable', '工作区注册表不可用')\n const workspace = registry?.list().find((candidate) => candidate.sessionIds.some((id) => String(id) === String(sessionId)))\n const binding = workspace\n ? this.bindings.list().find((item) => normalizeHostPath(item.mirrorPath) === normalizeHostPath(workspace.path))\n : undefined\n const nodeOrigin = binding ? this.nodes.originForLocalNode(binding.nodeId) : undefined\n const descriptor = workspace && binding && nodeOrigin\n ? this.workspaceDescriptor(workspace, binding, nodeOrigin, metadata.workspaceOrigin)\n : undefined\n const workspacePosition = workspace?.sessionIds.findIndex((id) => String(id) === String(sessionId)) ?? 0\n await registry.archiveSession(sessionId, { stopActivity: true })\n await persistence.flush()\n this.state.update((draft) => {\n draft.archives[branchId] = {\n branchId,\n originInstanceId: metadata.originInstanceId,\n originSessionId: metadata.originEntityId,\n localSessionId: String(sessionId),\n revision: metadata.revision,\n contentDigest: metadata.contentDigest,\n stateDigest: descriptor ? sessionStateDigest(descriptor, Math.max(0, workspacePosition), true, false) : metadata.stateDigest ?? metadata.contentDigest,\n workspacePosition: Math.max(0, workspacePosition),\n ...(workspace ? { workspaceId: workspace.id } : {}),\n ...(descriptor ? { workspaceOrigin: { originInstanceId: descriptor.originInstanceId, originEntityId: descriptor.originWorkspaceId } } :\n metadata.workspaceOrigin ? { workspaceOrigin: metadata.workspaceOrigin } : {}),\n archivedAt: new Date(this.now()).toISOString(),\n }\n })\n return branchId\n }\n\n private async applyTombstone(metadata: SyncRecordMetadata): Promise<boolean> {\n const key = sessionOriginKey(metadata)\n const current = this.state.read().records[key]\n if (current) {\n const comparison = compareSyncRevision(metadata.revision, current.revision)\n if (comparison < 0) return false\n if (comparison === 0) {\n if (metadata.contentDigest !== current.contentDigest || !current.deleted) {\n throw new SyncSessionError('revision-conflict', 'Equal session revisions contain different tombstone state')\n }\n return false\n }\n if (!current.deleted) await this.archiveCurrent(current)\n }\n const localEntityId = current?.localEntityId ?? String(importedSessionId(metadata))\n const tombstone = { ...metadata, kind: 'session' as const, localEntityId, deleted: true }\n this.state.observeRevision(metadata.revision, this.now())\n this.state.update((state) => { state.records[key] = tombstone })\n return true\n }\n\n private async restoreArchiveNow(branchId: string): Promise<SessionId> {\n if (!/^b-[a-f0-9]{32}$/.test(branchId)) throw new SyncSessionError('archive-not-found', '会话归档不存在')\n const archive = this.state.read().archives[branchId]\n if (!archive) throw new SyncSessionError('archive-not-found', '会话归档不存在')\n const registry = this.getWorkspaces()\n const sessionId = makeSessionId(archive.localSessionId)\n const session = await this.requirePersistence().stat(sessionId)\n if (!registry || !session) throw new SyncSessionError('archive-not-found', '会话归档日志不存在')\n const key = syncRecordKey('session', { originInstanceId: archive.originInstanceId, originEntityId: archive.originSessionId })\n const current = this.state.read().records[key]\n if (current && !current.deleted && current.localEntityId !== archive.localSessionId) await this.archiveCurrent(current)\n await registry.unarchiveSession(sessionId)\n const revision = this.state.nextRevision(this.now())\n const restored: SyncRecordMetadata = {\n kind: 'session',\n originInstanceId: archive.originInstanceId,\n originEntityId: archive.originSessionId,\n localEntityId: archive.localSessionId,\n revision,\n contentDigest: archive.contentDigest,\n stateDigest: archive.stateDigest,\n importedVia: 'peer',\n ...(archive.workspaceOrigin ? { workspaceOrigin: archive.workspaceOrigin } : {}),\n }\n this.state.update((state) => {\n delete state.archives[branchId]\n state.records[key] = restored\n })\n return sessionId\n }\n\n private async orderWorkspaceSessions(orders: Map<string, Array<{ id: SessionId; position: number }>>): Promise<void> {\n const registry = this.getWorkspaces()\n if (!registry) return\n for (const [workspaceId, incoming] of orders) {\n const workspace = registry.get(workspaceId)\n if (!workspace) continue\n const current = [...workspace.sessionIds]\n const incomingIds = new Set(incoming.map((item) => String(item.id)))\n const desired = [...incoming]\n .sort((a, b) => a.position - b.position || String(a.id).localeCompare(String(b.id)))\n .map((item) => item.id)\n .filter((id, index, all) => current.some((existing) => String(existing) === String(id)) && all.findIndex((candidate) => String(candidate) === String(id)) === index)\n const target = [...desired, ...current.filter((id) => !incomingIds.has(String(id)))]\n if (target.length === current.length && target.every((id, index) => String(id) === String(current[index]))) continue\n let before: SessionId | undefined\n for (const id of target.reverse()) {\n await workspace.insertSessionBefore(id, before)\n before = id\n }\n }\n }\n\n private localSessionIdForOrigin(origin: SyncOrigin): SessionId | undefined {\n const state = this.state.read()\n const active = state.records[syncRecordKey('session', origin)]\n if (active && !active.deleted) return makeSessionId(active.localEntityId)\n const archive = Object.values(state.archives)\n .filter((entry) => entry.originInstanceId === origin.originInstanceId && entry.originSessionId === origin.originEntityId)\n .sort((a, b) => compareSyncRevision(b.revision, a.revision))[0]\n return archive ? makeSessionId(archive.localSessionId) : undefined\n }\n\n private localWorkspaceIdForOrigin(origin: SyncOrigin, remotePath?: string): string | undefined {\n const mappings = Object.values(this.state.read().workspaces).filter((mapping) =>\n mapping.originInstanceId === origin.originInstanceId && mapping.originWorkspaceId === origin.originEntityId &&\n (remotePath === undefined || mapping.remotePath === remotePath),\n )\n return mappings.length === 1 ? mappings[0]?.localWorkspaceId : undefined\n }\n\n private async writeSession(prepared: PreparedSyncSession): Promise<boolean> {\n const persistence = this.requirePersistence()\n const existed = await persistence.stat(prepared.localSessionId)\n const handle = existed\n ? await persistence.open(prepared.localSessionId, 'write')\n : await persistence.create(prepared.header, prepared.header.isSeeded ? { inheritedEventCount: prepared.inheritedEventCount } : undefined)\n try {\n if (canonicalJson(handle.header) !== canonicalJson(prepared.header) || handle.inheritedEventCount !== prepared.inheritedEventCount) {\n throw new SyncSessionError('session-id-conflict', '目标 session ID 已被其他 header 占用')\n }\n const existing: SessionEvent[] = []\n for (let offset = 0; ; ) {\n const page = await handle.read(offset, SESSION_READ_PAGE_SIZE)\n if (page.events.length === 0) break\n existing.push(...page.events)\n offset += page.events.length\n if (page.events.length < SESSION_READ_PAGE_SIZE) break\n }\n if (existing.length > prepared.events.length) throw new SyncSessionError('session-prefix-conflict', `目标 session ${prepared.localSessionId} 前缀比导入记录更长(本地 ${existing.length},导入 ${prepared.events.length})`)\n for (let index = 0; index < existing.length; index += 1) {\n if (canonicalJson(existing[index]) !== canonicalJson(prepared.events[index])) {\n throw new SyncSessionError('session-prefix-conflict', `目标 session ${prepared.localSessionId} 的已提交事件与导入前缀不同(首个差异位置 seq=${existing[index]?.seq},本地 ${existing.length} 事件,导入 ${prepared.events.length} 事件)`)\n }\n }\n for (let offset = existing.length; offset < prepared.events.length; offset += SESSION_READ_PAGE_SIZE) {\n await handle.append(prepared.events.slice(offset, Math.min(offset + SESSION_READ_PAGE_SIZE, prepared.events.length)))\n }\n await handle.flush()\n } finally {\n await handle.close()\n }\n return existed !== undefined\n }\n\n private workspaceDescriptor(\n workspace: WorkspaceLike,\n binding: { mirrorPath: string; nodeId: string; remotePath: string; workspaceId?: string },\n nodeOrigin: SyncOrigin,\n preferredOrigin?: SyncOrigin,\n stateIndex = createSessionStateIndex(this.state.read()),\n ): SyncSessionWorkspace {\n const state = stateIndex.state\n const workspaceMappings = stateIndex.workspacesByLocalId.get(String(workspace.id)) ?? []\n const matchingMappings = workspaceMappings.filter((mapping) =>\n mapping.localNodeId === binding.nodeId &&\n posix.normalize(mapping.remotePath) === posix.normalize(binding.remotePath),\n )\n const preferredMapping = preferredOrigin\n ? workspaceMappings.find((mapping) =>\n mapping.originInstanceId === preferredOrigin.originInstanceId &&\n mapping.originWorkspaceId === preferredOrigin.originEntityId &&\n mapping.localNodeId === binding.nodeId,\n )\n : undefined\n const prior = preferredMapping ?? (matchingMappings.length === 1 ? matchingMappings[0] : undefined)\n const originInstanceId = preferredOrigin?.originInstanceId ?? prior?.originInstanceId ?? this.state.instanceId()\n const originWorkspaceId = preferredOrigin?.originEntityId ?? prior?.originWorkspaceId ?? workspace.id\n const base = { originInstanceId, originWorkspaceId, nodeOrigin, remotePath: posix.normalize(binding.remotePath), title: workspace.title }\n const digest = workspaceDigest(base)\n const key = syncWorkspaceKey(originInstanceId, originWorkspaceId, base.remotePath)\n const current = state.workspaces[key]\n const revision = current && current.contentDigest === digest ? current.revision : this.state.nextRevision(this.now())\n const mapping: SyncWorkspaceMapping = {\n originInstanceId,\n originWorkspaceId,\n localWorkspaceId: workspace.id,\n localPath: workspace.path,\n localNodeId: binding.nodeId,\n remotePath: base.remotePath,\n title: workspace.title,\n revision,\n contentDigest: digest,\n }\n if (!current || canonicalJson(current) !== canonicalJson(mapping)) {\n this.state.update((draft) => {\n draft.workspaces[key] = mapping\n })\n indexWorkspaceMapping(stateIndex, key, mapping)\n }\n return { ...base, revision, contentDigest: digest }\n }\n\n private async exportSessionEntry(\n persistence: SessionPersistenceLike,\n workspace: WorkspaceLike,\n descriptor: SyncSessionWorkspace,\n workspacePosition: number,\n sessionId: SessionId,\n firstSnapshot: SessionSnapshotLike,\n archived: boolean,\n pinned: boolean,\n archive?: SyncSessionArchive,\n stateIndex?: SessionStateIndex,\n objectCache?: ExportObjectCache,\n ): Promise<SessionExportResult | undefined> {\n const { header, inheritedEventCount, events, revision: sourceRevision } = await this.readStableSession(persistence, sessionId, firstSnapshot)\n const localSessionId = String(sessionId)\n const cacheKey = sessionExportCacheKey(localSessionId)\n if (!header.cwd || posix.normalize(header.cwd) !== posix.normalize(workspace.path)) {\n this.exportCache.delete(cacheKey)\n this.exportCacheStore.delete(cacheKey)\n return undefined\n }\n const index = stateIndex ?? createSessionStateIndex(this.state.read())\n const state = index.state\n const parentMetadata = header.parentSession ? index.recordsByLocalId.get(String(header.parentSession)) : undefined\n const parentOrigin = parentMetadata\n ? { originInstanceId: parentMetadata.originInstanceId, originEntityId: parentMetadata.originEntityId }\n : undefined\n const syncInstructions = instructionsForSession(\n this.instructions,\n String(sessionId),\n index,\n { originInstanceId: descriptor.originInstanceId, originEntityId: descriptor.originWorkspaceId },\n )\n const eventDigest = sessionEventListDigest(events)\n const objects = await this.exportObjects(events, localSessionId, objectCache)\n const digest = sessionEventDigest(\n header,\n inheritedEventCount,\n events,\n descriptor,\n syncInstructions,\n objects,\n parentOrigin,\n )\n const current = archive\n ? undefined\n : index.recordsByLocalId.get(localSessionId) ?? state.records[syncRecordKey('session', {\n originInstanceId: this.state.instanceId(),\n originEntityId: localSessionId,\n })]\n const originInstanceId = archive?.originInstanceId ?? current?.originInstanceId ?? this.state.instanceId()\n const originEntityId = archive?.originSessionId ?? current?.originEntityId ?? localSessionId\n const workspaceOrigin = { originInstanceId: descriptor.originInstanceId, originEntityId: descriptor.originWorkspaceId }\n const workspaceOriginChanged = Boolean(current?.workspaceOrigin &&\n (current.workspaceOrigin.originInstanceId !== workspaceOrigin.originInstanceId || current.workspaceOrigin.originEntityId !== workspaceOrigin.originEntityId))\n const stateDigest = sessionStateDigest(descriptor, workspacePosition, archived, pinned)\n const sessionStateChanged = Boolean(current && current.stateDigest !== stateDigest)\n let revision = archive?.revision ?? current?.revision\n let contentDigest = digest\n let outputBranchId = archive?.branchId\n if (archive) {\n if (archive.contentDigest !== digest || archive.stateDigest !== stateDigest || archive.workspacePosition !== workspacePosition) {\n const nextRevision = this.state.nextRevision(this.now())\n revision = nextRevision\n const contentChanged = archive.contentDigest !== digest\n const branchId = contentChanged\n ? branchIdFor({ originInstanceId, originEntityId, revision: nextRevision, contentDigest: digest } as SyncRecordMetadata)\n : archive.branchId\n const updatedArchive = {\n ...archive,\n branchId,\n revision: nextRevision,\n contentDigest: digest,\n stateDigest,\n workspacePosition,\n workspaceOrigin,\n }\n this.state.update((draft) => {\n delete draft.archives[archive.branchId]\n draft.archives[branchId] = updatedArchive\n })\n indexArchive(index, archive.branchId, updatedArchive)\n outputBranchId = branchId\n } else contentDigest = archive.contentDigest\n } else if (!current || current.contentDigest !== digest || current.deleted || workspaceOriginChanged || !current.workspaceOrigin || sessionStateChanged) {\n revision = this.state.nextRevision(this.now())\n }\n const metadata: SyncRecordMetadata = {\n kind: 'session',\n originInstanceId,\n originEntityId,\n localEntityId: localSessionId,\n revision: revision ?? this.state.nextRevision(this.now()),\n contentDigest,\n stateDigest,\n workspaceOrigin,\n ...(archive ? {} : current?.importedVia ? { importedVia: current.importedVia } : {}),\n ...(archive ? {} : current?.sourceName ? { sourceName: current.sourceName } : {}),\n }\n if (!archive && (!current || current.contentDigest !== digest || current.deleted || workspaceOriginChanged || !current.workspaceOrigin || sessionStateChanged)) {\n this.state.update((draft) => {\n draft.records[sessionOriginKey(metadata)] = metadata\n })\n indexSessionRecord(index, metadata)\n }\n // Spill payloads can change outside the session log revision.\n if (!archive && !objects.some((object) => object.kind === 'spill')) {\n const fingerprint = sessionExportFingerprint({\n revision: sourceRevision,\n header,\n inheritedEventCount,\n workspace: descriptor,\n instructionSnapshot: syncInstructions,\n parentOrigin,\n })\n if (fingerprint) {\n const entry: SessionExportCacheEntry = {\n fingerprint,\n metadata,\n eventCount: events.length,\n eventDigest,\n inheritedEventCount,\n }\n this.exportCache.set(cacheKey, entry)\n this.exportCacheStore.set(cacheKey, entry)\n } else {\n this.exportCache.delete(cacheKey)\n this.exportCacheStore.delete(cacheKey)\n }\n } else {\n this.exportCache.delete(cacheKey)\n this.exportCacheStore.delete(cacheKey)\n }\n return {\n entry: {\n metadata,\n ...(outputBranchId ? { branchId: outputBranchId } : {}),\n sourceLocalSessionId: localSessionId,\n header,\n inheritedEventCount,\n ...(parentOrigin ? { parentOrigin } : {}),\n workspace: descriptor,\n workspacePosition,\n archived,\n pinned,\n ...(syncInstructions ? { instructionSnapshot: syncInstructions } : {}),\n events: [...events],\n objects,\n eventCount: events.length,\n eventDigest,\n },\n eventCount: events.length,\n eventDigest,\n inheritedEventCount,\n }\n }\n\n private async readStableSession(\n persistence: SessionPersistenceLike,\n sessionId: SessionId,\n firstSnapshot: SessionSnapshotLike,\n ): Promise<{ header: SessionHeader; inheritedEventCount: number; events: SessionEvent[]; revision: unknown }> {\n let snapshot = firstSnapshot\n for (let attempt = 0; attempt < 2; attempt += 1) {\n if (snapshot.formatStatus === 'migration-required') throw new SyncSessionError('session-format', '会话格式需要由当前 DSH 版本迁移')\n const handle = await persistence.open(sessionId, 'read')\n try {\n const events: SessionEvent[] = []\n let offset = 0\n for (;;) {\n const page = await handle.read(offset, SESSION_READ_PAGE_SIZE)\n if (page.events.length === 0) break\n events.push(...structuredClone(page.events))\n offset += page.events.length\n if (events.length > MAX_SYNC_SESSIONS * 100) throw new SyncSessionError('session-too-large', '会话事件数超过限制')\n if (page.events.length < SESSION_READ_PAGE_SIZE) break\n }\n const validated = validateStoredEvents(handle.header, events)\n assertContiguous(sessionId, validated, 0)\n const after = await persistence.stat(sessionId)\n if (!after) throw new SyncSessionError('session-missing', '会话在导出期间消失')\n if (\n canonicalJson(snapshot.revision) === canonicalJson(after.revision) &&\n canonicalJson(snapshot.header) === canonicalJson(after.header) &&\n canonicalJson(handle.header) === canonicalJson(after.header)\n ) {\n return {\n header: handle.header,\n inheritedEventCount: Number(handle.inheritedEventCount),\n events: [...validated],\n revision: after.revision,\n }\n }\n snapshot = after\n } finally {\n await handle.close()\n }\n }\n throw new SyncSessionError('session-changing', '会话在导出期间持续变化,请稍后重试')\n }\n\n private async exportObjects(\n events: readonly SessionEvent[],\n sessionId: string,\n objectCache?: ExportObjectCache,\n ): Promise<SyncSessionObject[]> {\n const attachments = attachmentReferences(events)\n const spills = spillReferences(events)\n const structuredSpills = new Set(spills.map(spillKey))\n for (const reference of legacySpillReferences(events, sessionId)) {\n if (!structuredSpills.has(spillKey(reference))) spills.push(reference)\n }\n const payloads = new Map<string, SyncSessionObject>()\n const attachmentStore = (attachments.images.length + attachments.files.length) > 0 ? this.getAttachments() : undefined\n if ((attachments.images.length + attachments.files.length) > 0 && !attachmentStore) {\n throw new SyncSessionError('attachments-unavailable', '附件存储服务不可用')\n }\n for (const ref of attachments.images) {\n const key = attachmentKey('image', ref)\n const cached = objectCache?.get(key)?.object\n if (cached?.kind === 'image' && canonicalJson(cached.ref) === canonicalJson(ref)) {\n payloads.set(key, cached)\n continue\n }\n const stored = await attachmentStore!.readImage(ref)\n const digest = sha256(stored.data)\n const object: SyncSessionObject = {\n id: key,\n kind: 'image',\n ref: stored.ref,\n bytes: stored.data.byteLength,\n digest,\n data: Buffer.from(stored.data).toString('base64'),\n }\n payloads.set(key, object)\n objectCache?.set(key, { object })\n }\n for (const ref of attachments.files) {\n const key = attachmentKey('file', ref)\n const cached = objectCache?.get(key)?.object\n if (cached?.kind === 'file' && canonicalJson(cached.ref) === canonicalJson(ref)) {\n payloads.set(key, cached)\n continue\n }\n const data = await collectBytes(attachmentStore!.readFileStream(ref))\n const object: SyncSessionObject = {\n id: key,\n kind: 'file',\n ref,\n bytes: data.byteLength,\n digest: sha256(data),\n data: data.toString('base64'),\n }\n payloads.set(key, object)\n objectCache?.set(key, { object })\n }\n if (spills.length > 0) {\n const store = this.getSpills()\n const untransferred: SpillTransferReference[] = []\n for (const reference of spills) {\n if (!store) { untransferred.push(reference); continue }\n const key = spillKey(reference)\n const cached = objectCache?.get(key)?.object\n if (cached?.kind === 'spill' && canonicalJson(cached.reference) === canonicalJson(reference) &&\n (reference.ref.bytes === undefined || cached.bytes === reference.ref.bytes)) {\n payloads.set(key, cached)\n continue\n }\n try {\n const data = await collectBytes(readSpillStream(store, reference))\n if (reference.ref.bytes !== undefined && data.byteLength !== reference.ref.bytes) {\n untransferred.push(reference); continue\n }\n try {\n new TextDecoder('utf-8', { fatal: true }).decode(data)\n } catch {\n untransferred.push(reference); continue\n }\n const object: SyncSessionObject = {\n id: key,\n kind: 'spill',\n reference,\n bytes: data.byteLength,\n digest: sha256(data),\n data: data.toString('base64'),\n }\n payloads.set(key, object)\n objectCache?.set(key, { object })\n } catch {\n untransferred.push(reference)\n }\n }\n for (const reference of untransferred) {\n const key = spillKey(reference)\n payloads.set(key, {\n id: key,\n kind: 'spill',\n reference,\n bytes: 0,\n digest: sha256(Buffer.alloc(0)),\n data: '',\n unavailable: true,\n })\n }\n }\n return [...payloads.values()]\n }\n\n private requirePersistence(): SessionPersistenceLike {\n const persistence = this.getPersistence()\n if (!persistence) throw new SyncSessionError('session-persistence-unavailable', '会话持久化服务不可用')\n return persistence\n }\n\n private serializeMutation<T>(operation: () => Promise<T>): Promise<T> {\n const result = this.operationTail.then(operation)\n this.operationTail = result.then(() => undefined, () => undefined)\n return result\n }\n}\n"],"x_google_ignoreList":[0,1],"mappings":";;;;;;;;;;;;;;;;;;AAYA,SAAS,UAAU,IAAI;CACtB,OAAO,YAAY,EAAE;AACtB;;;;;;;;;;;;;;;;;;;;;AAgEA,MAAM,4CAA4B,IAAI,IAAI;CACzC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC;;;;;;;;;;;AAeD,MAAM,sCAAsB,IAAI,IAAI;CACnC;CACA;CACA;CACA;CACA;AACD,CAAC;;;;;;AAMD,SAAS,sBAAsB,MAAM;CACpC,OAAO,oBAAoB,IAAI,IAAI;AACpC;;AA6DA,SAAS,SAAS,OAAO;CACxB,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC3E;;;;;;;;AAQA,SAAS,yBAAyB,OAAO,SAAS;CACjD,MAAM,OAAO,MAAM;CACnB,IAAI,oBAAoB,IAAI,MAAM,IAAI,KAAK,SAAS,IAAI,GAAG;EAC1D,MAAM,UAAU,MAAM,SAAS,iBAAiB,OAAO,KAAK;EAC5D,IAAI,SAAS,OAAO,GAAG;GACtB,IAAI,MAAM,SAAS,yBAAyB,QAAQ,YAAY,cAAc,MAAM,IAAI,MAAM,GAAG,QAAQ,0DAA0D;GACnK,IAAI,QAAQ,YAAY,eAAe,MAAM,QAAQ,QAAQ,UAAU,KAAK,QAAQ,UAAU,CAAC,MAAM,UAAU,SAAS,KAAK,MAAM,MAAM,YAAY,mBAAmB,MAAM,YAAY,eAAe,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,2CAA2C;GAClR,IAAI,MAAM,SAAS,uBAAuB,MAAM,QAAQ,QAAQ,UAAU,GAAG;IAC5E,IAAI,eAAe;IACnB,KAAK,MAAM,SAAS,QAAQ,YAAY;KACvC,IAAI,CAAC,SAAS,KAAK,KAAK,MAAM,YAAY,mBAAmB,MAAM,YAAY,gBAAgB;KAC/F,IAAI,OAAO,MAAM,gBAAgB,YAAY,MAAM,WAAW,CAAC,WAAW,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,GAAG,MAAM,QAAQ,8BAA8B;KACvJ,IAAI,MAAM,YAAY,iBAAiB;MACtC,eAAe;MACf,IAAI,OAAO,OAAO,OAAO,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,iDAAiD;KAC/G;IACD;IACA,IAAI,eAAe,CAAC,WAAW,KAAK,YAAY,IAAI,OAAO,OAAO,MAAM,WAAW,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,4DAA4D;GAC9K;EACD;CACD;CACA,IAAI,MAAM,SAAS,kBAAkB;EACpC,IAAI,CAAC,SAAS,IAAI,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,wBAAwB;EACxE,MAAM,SAAS,KAAK;EACpB,IAAI,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,0BAA0B;EAC5E,IAAI,OAAO,OAAO,QAAQ,QAAQ,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,6CAA6C;EAC7G,IAAI,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO,QAAQ,CAAC,WAAW,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,uBAAuB;EACtH,MAAM,WAAW,OAAO;EACxB,IAAI,SAAS,QAAQ,KAAK,OAAO,KAAK,QAAQ,CAAC,CAAC,WAAW,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,iCAAiC;CAC3H,OAAO,IAAI,MAAM,SAAS,eAAe;EACxC,IAAI,CAAC,SAAS,IAAI,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,wBAAwB;EACxE,IAAI,KAAK,aAAa,KAAK,GAAG;EAC9B,MAAM,UAAU,KAAK;EACrB,IAAI,CAAC,SAAS,OAAO,KAAK,QAAQ,eAAe,MAAM,MAAM,IAAI,MAAM,GAAG,QAAQ,yCAAyC;CAC5H;AACD;;AAYA,SAAS,WAAW,OAAO;CAC1B,OAAO,OAAO,UAAU,YAAY,OAAO,cAAc,KAAK,KAAK,SAAS,KAAK,CAAC,OAAO,GAAG,OAAO,EAAE;AACtG;;AAEA,SAAS,YAAY,OAAO;CAC3B,MAAM,KAAK;CACX,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,WAAW,KAAK,OAAO,OAAO,IAAI,IAAI,KAAK,OAAO,OAAO,IAAI,UAAU,KAAK,OAAO,OAAO,IAAI,QAAQ,KAAK,GAAG,UAAU,aAAa,WAAW,GAAG,WAAW,KAAK,WAAW,GAAG,SAAS;AAClN;;AAEA,SAAS,YAAY,OAAO;CAC3B,MAAM,MAAM;CACZ,IAAI,CAAC,sBAAsB,MAAM,IAAI,GAAG;EACvC,IAAI,CAAC,0BAA0B,IAAI,MAAM,IAAI,KAAK,MAAM,cAAc,MAAM;EAC5E,IAAI,IAAI,cAAc,KAAK,GAAG,MAAM,IAAI,MAAM,kBAAkB,MAAM,KAAK,qDAAqD;EAChI,IAAI,IAAI,oBAAoB,KAAK,GAAG,MAAM,IAAI,MAAM,kBAAkB,MAAM,KAAK,2DAA2D;EAC5I;CACD;CACA,MAAM,KAAK,IAAI;CACf,IAAI,OAAO,KAAK,GAAG,MAAM,IAAI,MAAM,kBAAkB,MAAM,KAAK,sDAAsD;CACtH,IAAI,OAAO,UAAU,OAAO;CAC5B,IAAI,OAAO,QAAQ,OAAO,OAAO,YAAY,MAAM,QAAQ,EAAE,GAAG,MAAM,IAAI,MAAM,kBAAkB,MAAM,KAAK,+BAA+B;CAC5I,IAAI,CAAC,YAAY,EAAE,GAAG,MAAM,IAAI,MAAM,kBAAkB,MAAM,KAAK,uCAAuC;CAC1G,OAAO;AACR;;AAEA,SAAS,4BAA4B,OAAO,cAAc;CACzD,MAAM,MAAM,MAAM;CAClB,IAAI,MAAM,SAAS,uBAAuB,QAAQ,KAAK,GAAG,MAAM,IAAI,MAAM,6EAA6E;CACvJ,MAAM,0BAA0B,IAAI,IAAI;CACxC,IAAI,QAAQ,KAAK,GAAG;EACnB,IAAI,CAAC,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,MAAM,mCAAmC,MAAM,IAAI,+BAA+B;EACrH,IAAI,IAAI,WAAW,GAAG,MAAM,IAAI,MAAM,mCAAmC;EACzE,IAAI;EACJ,KAAK,MAAM,UAAU,KAAK;GACzB,IAAI,CAAC,WAAW,MAAM,GAAG,MAAM,IAAI,MAAM,kBAAkB,MAAM,KAAK,kEAAkE;GACxI,QAAQ,IAAI,MAAM;GAClB,IAAI,qBAAqB,KAAK,KAAK,UAAU,MAAM,KAAK,mBAAmB;EAC5E;EACA,IAAI,QAAQ,SAAS,IAAI,QAAQ,MAAM,IAAI,MAAM,6CAA6C;EAC9F,IAAI,qBAAqB,KAAK,GAAG,MAAM,IAAI,MAAM,kDAAkD,iBAAiB,kBAAkB,MAAM,KAAK;CAClJ;CACA,MAAM,UAAU,aAAa,QAAQ,QAAQ,CAAC,QAAQ,IAAI,GAAG,CAAC;CAC9D,IAAI,QAAQ,SAAS,GAAG,MAAM,IAAI,MAAM,sFAAsF,QAAQ,KAAK,IAAI,GAAG;AACnJ;;;;;;;;AAyBA,SAAS,wBAAwB,OAAO;CACvC,MAAM,KAAK,YAAY,KAAK;CAC5B,IAAI,OAAO,KAAK,KAAK,OAAO,aAAa,GAAG,YAAY,MAAM,OAAO,GAAG,UAAU,MAAM,MAAM,MAAM,IAAI,MAAM,0BAA0B,MAAM,IAAI,oDAAoD;CACtM,IAAI,OAAO,KAAK,GAAG,4BAA4B,OAAO,CAAC,CAAC;CACxD,OAAO;AACR;;;;;;;;;;AAotBA,SAAS,kBAAkB,OAAO;CACjC,yBAAyB,OAAO,wBAAwB,MAAM,KAAK;CACnE,wBAAwB,KAAK;CAC7B,wBAAwB,OAAO,wBAAwB,MAAM,KAAK;CAClE,QAAQ,MAAM,MAAd;EACC,KAAK;GACJ,WAAW,MAAM,IAAI;GACrB;EACD,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,eACJ,WAAW,MAAM,KAAK,OAAO;CAG/B;CACA,OAAO;AACR;;;;;;AAMA,SAAS,qBAAqB,OAAO;CACpC,OAAO,kBAAkB,gBAAgB,KAAK,CAAC;AAChD;;AAwEA,SAAS,mBAAmB,MAAM;CACjC,OAAO,SAAS,uBAAuB,SAAS,oBAAoB,SAAS,kBAAkB,SAAS,uBAAuB,SAAS;AACzI;AACA,MAAM,uBAAuB;CAC5B,kBAAkB;CAClB,qBAAqB;CACrB,gBAAgB;CAChB,qBAAqB;CACrB,eAAe;AAChB;;AAEA,SAAS,wBAAwB,OAAO,SAAS;CAChD,MAAM,OAAO,MAAM;CACnB,IAAI,CAAC,mBAAmB,IAAI,GAAG;CAC/B,MAAM,OAAO,MAAM;CACnB,MAAM,SAAS,OAAO,SAAS,YAAY,SAAS,OAAO,OAAO,KAAK;CACvE,MAAM,UAAU,SAAS,iBAAiB,SAAS,SAAS;CAC5D,IAAI,OAAO,YAAY,YAAY,YAAY,QAAQ,OAAO,QAAQ,UAAU,YAAY,QAAQ,UAAU,IAAI,MAAM,IAAI,MAAM,GAAG,QAAQ,6BAA6B;CAC1K,MAAM,gBAAgB;CACtB,MAAM,eAAe,qBAAqB;CAC1C,IAAI,cAAc,YAAY,cAAc,MAAM,IAAI,MAAM,GAAG,QAAQ,2BAA2B,aAAa,EAAE;CACjH,MAAM,SAAS,cAAc;CAC7B,IAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,OAAO,OAAO,YAAY,YAAY,OAAO,YAAY,IAAI,MAAM,IAAI,MAAM,GAAG,QAAQ,4BAA4B;CACzK,IAAI,CAAC,MAAM,QAAQ,cAAc,UAAU,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,6BAA6B;CACtG,MAAM,eAAe;CACrB,IAAI,SAAS,kBAAkB;EAC9B,IAAI,aAAa,YAAY,iBAAiB,MAAM,IAAI,MAAM,GAAG,QAAQ,wCAAwC;EACjH;CACD;CACA,IAAI,SAAS,qBAAqB;EACjC,IAAI,aAAa,YAAY,WAAW,CAAC,iBAAiB,YAAY,GAAG,MAAM,IAAI,MAAM,GAAG,QAAQ,gCAAgC;EACpI;CACD;CACA,IAAI,SAAS,eAAe;CAC5B,IAAI,aAAa,YAAY,UAAU,OAAO,aAAa,cAAc,YAAY,aAAa,cAAc,IAAI,MAAM,IAAI,MAAM,GAAG,QAAQ,+BAA+B;CAC9K,IAAI,cAAc,kBAAkB,aAAa,WAAW,MAAM,IAAI,MAAM,GAAG,QAAQ,sCAAsC;AAC9H;;AAEA,SAAS,iBAAiB,OAAO;CAChC,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,OAAO;CACb,OAAO,OAAO,KAAK,gBAAgB,YAAY,KAAK,WAAW,CAAC,SAAS,KAAK,OAAO,KAAK,aAAa,YAAY,KAAK,QAAQ,CAAC,SAAS;AAC3I;;;;ACxmCA,IAAI,oCAAoC,cAAc,MAAM;;;;;CAK3D,YAAY,SAAS,SAAS;EAC7B,MAAM,SAAS,OAAO;EACtB,KAAK,OAAO;CACb;AACD;;;;;;;;AAQA,IAAI,gCAAgC,cAAc,MAAM;CACvD;;;;;;CAMA,YAAY,SAAS,UAAU;EAC9B,MAAM,OAAO;EACb,KAAK,WAAW;EAChB,KAAK,OAAO;CACb;AACD;;;;;;;;AAuBA,SAAS,YAAY,QAAQ,UAAU;CACtC,OAAO,IAAI,8BAA8B,aAAa,KAAK,IAAI,SAAS,GAAG,OAAO,aAAa,SAAS,KAAK,IAAI,QAAQ;AAC1H;;;;;;;;;;;;;;;AA+BA,SAAS,qBAAqB,MAAM,QAAQ,UAAU;CACrD,KAAK,MAAM,SAAS,QAAQ;EAC3B,IAAI,CAAC,0BAA0B,IAAI,MAAM,IAAI,KAAK,MAAM,cAAc,MAAM,MAAM,YAAY,YAAY,KAAK,GAAG,yBAAyB,MAAM,KAAK,SAAS,MAAM,IAAI,+HAA+H,QAAQ;EAChT,IAAI,MAAM,SAAS,kBAAkB;GACpC,MAAM,OAAO,MAAM;GACnB,IAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,KAAK,cAAc,YAAY,MAAM,YAAY,YAAY,KAAK,GAAG,yCAAyC,MAAM,IAAI,mIAAmI,QAAQ;EACrT;CACD;CACA,IAAI;EACH,KAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,GAAG,OAAO,SAAS,kBAAkB,KAAK;CACvF,SAAS,OAAO;EACf,IAAI,iBAAiB,+BAA+B,MAAM;EAC1D,MAAM,IAAI,kCAAkC,mBAAmB,KAAK,GAAG,uBAAuB,OAAO,KAAK,KAAK,EAAE,OAAO,MAAM,CAAC;CAChI;CACA,OAAO;AACR;;;;;;;AAgCA,SAAS,iBAAiB,IAAI,QAAQ,QAAQ;CAC7C,KAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,GAAG,IAAI,MAAM,QAAQ,SAAS,OAAO,MAAM,IAAI,MAAM,4BAA4B,GAAG,cAAc,SAAS,MAAM,YAAY,MAAM,QAAQ,MAAM,KAAK;AACnM;;;AC/NA,MAAM,8BAA8B;AAepC,SAAS,UAAU,MAAuB;CACxC,OAAO,QAAQ,QAAQ,IAAI,YAAY,KAAK,QAAQ,GAAG,MAAM;AAC/D;AAEA,SAAS,YAAY,MAAc,SAAuB;CACxD,MAAM,MAAM,QAAQ,IAAI;CACxB,UAAU,KAAK;EAAE,WAAW;EAAM,MAAM;CAAM,CAAC;CAC/C,MAAM,YAAY,GAAG,KAAK,GAAG,QAAQ,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,SAAS,KAAK,EAAE;CAC3E,IAAI;CACJ,IAAI;EACF,KAAK,SAAS,WAAW,MAAM,GAAK;EACpC,cAAc,IAAI,SAAS,MAAM;EACjC,UAAU,EAAE;EACZ,UAAU,EAAE;EACZ,KAAK,KAAA;EACL,WAAW,WAAW,IAAI;EAC1B,UAAU,MAAM,GAAK;CACvB,SAAS,OAAO;EACd,IAAI,OAAO,KAAA,GAAW,UAAU,EAAE;EAClC,IAAI;GACF,WAAW,SAAS;EACtB,QAAQ,CAAC;EACT,MAAM;CACR;AACF;AAEA,SAAS,cAAc,OAAyB;CAC9C,OAAOA,WAAS,KAAK,KAAK,yBAAyB,MAAM,cAAc,KACrE,yBAAyB,MAAM,cAAc,KAAK,OAAO,MAAM,qBAAqB,YAAY,CAAC,CAAC,MAAM;AAC5G;AAEA,SAAS,WAAW,OAA2D;CAC7E,IAAI,CAACA,WAAS,KAAK,KAAK,OAAO,MAAM,gBAAgB,YAAY,CAAC,wBAAwB,KAAK,MAAM,WAAW,KAC9G,CAACA,WAAS,MAAM,QAAQ,KAAK,OAAO,MAAM,SAAS,kBAAkB,YAAY,CAAC,cAAc,MAAM,SAAS,QAAQ,KACvH,CAAC,yBAAyB,MAAM,UAAU,KAAK,OAAO,MAAM,gBAAgB,YAC5E,CAAC,wBAAwB,KAAK,MAAM,WAAW,KAAK,CAAC,yBAAyB,MAAM,mBAAmB,GACvG,OAAO;CAET,OAAO;AACT;AAEA,IAAa,8BAAb,MAAyC;CACvC;CACA;CACA,QAAgB;CAEhB,YAAY,MAAe;EACzB,KAAK,WAAW,KAAK,UAAU,IAAI,GAAG,QAAQ,wBAAwB;CACxE;CAEA,IAAI,KAA2D;EAC7D,OAAO,KAAK,KAAK,CAAC,CAAC,QAAQ;CAC7B;CAEA,IAAI,KAAa,OAA+C;EAC9D,IAAI,CAAC,WAAW,KAAK,GAAG;EACxB,KAAK,KAAK,CAAC,CAAC,QAAQ,OAAO;EAC3B,KAAK,QAAQ;CACf;CAEA,OAAO,KAAmB;EACxB,IAAI,EAAE,OAAO,KAAK,KAAK,CAAC,CAAC,UAAU;EACnC,OAAO,KAAK,KAAK,CAAC,CAAC,QAAQ;EAC3B,KAAK,QAAQ;CACf;CAEA,QAAc;EACZ,IAAI,CAAC,KAAK,SAAS,CAAC,KAAK,MAAM;EAC/B,KAAK,QAAQ;EACb,IAAI;GACF,YAAY,KAAK,UAAU,GAAG,KAAK,UAAU,KAAK,IAAI,EAAE,GAAG;EAC7D,QAAQ;GACN,KAAK,QAAQ;EACf;CACF;CAEA,UAAgE;EAC9D,OAAO,OAAO,QAAQ,KAAK,KAAK,CAAC,CAAC,OAAO;CAC3C;CAEA,OAAqC;EACnC,IAAI,KAAK,MAAM,OAAO,KAAK;EAC3B,IAAI,WAAiC;GAAE,SAAS;GAAG,SAAS,CAAC;EAAE;EAC/D,IAAI;GACF,MAAM,MAAM,aAAa,KAAK,UAAU,MAAM;GAC9C,IAAI,IAAI,UAAU,6BAA6B;IAC7C,MAAM,SAAkB,KAAK,MAAM,GAAG;IACtC,IAAIA,WAAS,MAAM,KAAK,OAAO,YAAY,KAAKA,WAAS,OAAO,OAAO,GAAG;KACxE,MAAM,UAA4D,CAAC;KACnE,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,OAAO,GACtD,IAAI,2BAA2B,KAAK,GAAG,KAAK,WAAW,KAAK,GAAG,QAAQ,OAAO;KAEhF,WAAW;MAAE,SAAS;MAAG;KAAQ;IACnC;GACF;EACF,QAAQ,CAAC;EACT,KAAK,OAAO;EACZ,OAAO;CACT;AACF;;;ACvFA,MAAM,yBAAyB;AAC/B,MAAM,oBAAoB;AAC1B,MAAM,mCAAmC;AACzC,MAAM,mCAAmC;AAEzC,MAAM,+BAA+B;AACrC,MAAM,qBAAqB;AAC3B,MAAM,0BAA0B;AAShC,MAAM,0BAA0B;AAChC,MAAM,4BAA4B;AAClC,MAAM,4BAA4B,KAAK,wBAAwB;AAyK/D,IAAa,mBAAb,cAAsC,MAAM;CACrB;CAArB,YAAY,MAAuB,SAAiB,OAAiB;EACnE,MAAM,SAAS,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,MAAM,CAAC;EADvC,KAAA,OAAA;EAEnB,KAAK,OAAO;CACd;AACF;AAiCA,eAAe,0BACb,aACA,WACA,eAC8C;CAC9C,MAAM,SAAS,MAAM,YAAY,KAAK,WAAW,MAAM;CACvD,IAAI;EACF,MAAM,WAAW,MAAM,YAAY,KAAK,SAAS;EACjD,IAAI,CAAC,YAAY,SAAS,iBAAiB,sBAAsB,OAAO,KAAA;EACxE,IAAI;GACF,IACE,cAAc,cAAc,QAAQ,MAAM,cAAc,SAAS,QAAQ,KACzE,cAAc,cAAc,MAAM,MAAM,cAAc,SAAS,MAAM,KACrE,cAAc,OAAO,MAAM,MAAM,cAAc,SAAS,MAAM,GAC9D,OAAO,KAAA;EACX,QAAQ;GACN;EACF;EACA,MAAM,sBAAsB,OAAO,OAAO,mBAAmB;EAC7D,IAAI,CAAC,OAAO,cAAc,mBAAmB,KAAK,sBAAsB,GAAG,OAAO,KAAA;EAClF,OAAO;GAAE;GAAU,QAAQ,OAAO;GAAQ;EAAoB;CAChE,UAAU;EACR,MAAM,OAAO,MAAM;CACrB;AACF;AA6CA,SAAS,0BAA0B,WAA2B;CAC5D,OAAO,WAAW,WAAW,QAAQ,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE;AACpF;AAEA,SAAS,4BAA4B,OAAmC;CACtE,OAAO,IAAI,iBAAiB,mBAAmB,kDAAkD,KAAK;AACxG;AAEA,gBAAgB,mBACd,gBACA,WAC4B;CAC5B,MAAM,WAAW,QAAQ,UAAU,IAAI,OAAO;CAC9C,MAAM,mBAAmB,QAAQ,QAAQ;CACzC,MAAM,OAAO,QAAQ,gBAAgB;CACrC,MAAM,2BAA2B,0BAA0B,UAAU,MAAM,SAAS;CACpF,MAAM,OAAO,SAAS,QAAQ;CAC9B,IACE,aAAa,UAAU,IAAI,WAAW,SAAS,gBAAgB,MAAM,4BACrE,CAAC,8CAA8C,KAAK,IAAI,GACxD,MAAM,4BAA4B;CAEpC,MAAM,iBAAiB,QAAQ,IAAI;CAEnC,IAAI,oBAD6B,mBAAmB,KAAA,IAAY,KAAA,IAAY,QAAQ,cAAc,IACjD;EAC/C,MAAM,WAAW,QAAQ,OAAO,CAAC;EACjC,IAAI,QAAQ,cAAc,MAAM,YAAY,CAAC,SAAS,cAAc,CAAC,CAAC,WAAW,YAAY,GAC3F,MAAM,4BAA4B;CAEtC;CAEA,IAAI;CACJ,IAAI;EACF,MAAM,WAAW,MAAM,SAAS,cAAc;EAC9C,MAAM,oBAAoB,KAAK,UAAU,wBAAwB;EACjE,IAAI,MAAM,SAAS,gBAAgB,MAAM,mBAAmB,MAAM,4BAA4B;EAC9F,MAAM,gBAAgB,MAAM,MAAM,gBAAgB;EAClD,MAAM,YAAY,MAAM,MAAM,QAAQ;EACtC,MAAM,gBAAgB,UAAU,IAAI,SAAS,UAAU;EACvD,IACE,cAAc,eAAe,KAAK,CAAC,cAAc,YAAY,KAC7D,UAAU,eAAe,KAAK,CAAC,UAAU,OAAO,KAAK,UAAU,SAAS,iBACxE,CAAC,OAAO,cAAc,aAAa,KAAK,gBAAgB,KACvD,QAAQ,aAAa,aAAa,cAAc,OAAO,QAAW,MAAM,UAAU,OAAO,QAAW,IACrG,MAAM,4BAA4B;EAEpC,MAAM,WAAW,OAAOC,UAAY,eAAe,WAAWA,UAAY,aAAa;EACvF,SAAS,MAAM,KAAK,UAAUA,UAAY,WAAW,QAAQ;EAC7D,MAAM,aAAa,MAAM,OAAO,KAAK;EACrC,IACE,CAAC,WAAW,OAAO,KAAK,WAAW,SAAS,iBAC3C,UAAU,QAAQ,KAAK,WAAW,QAAQ,KAAK,UAAU,QAAQ,WAAW,OAC5E,UAAU,QAAQ,KAAK,WAAW,QAAQ,KAAK,UAAU,QAAQ,WAAW,KAC7E,MAAM,4BAA4B;EAEpC,IAAI,QAAQ;EACZ,SAAS;GACP,MAAM,SAAS,OAAO,YAAY,KAAS;GAC3C,MAAM,EAAE,cAAc,MAAM,OAAO,KAAK,QAAQ,GAAG,OAAO,YAAY,IAAI;GAC1E,IAAI,cAAc,GAAG;GACrB,SAAS;GACT,IAAI,QAAQ,eAAe,MAAM,4BAA4B;GAC7D,MAAM,OAAO,SAAS,GAAG,SAAS;EACpC;EACA,MAAM,YAAY,MAAM,OAAO,KAAK;EACpC,IAAI,UAAU,iBAAiB,UAAU,SAAS,iBAAiB,UAAU,YAAY,WAAW,SAClG,MAAM,4BAA4B;CAEtC,SAAS,OAAO;EACd,IAAI,iBAAiB,kBAAkB,MAAM;EAC7C,MAAM,4BAA4B,KAAK;CACzC,UAAU;EACR,IAAI,QAAQ,MAAM,OAAO,MAAM;CACjC;AACF;AAEA,SAAS,mBAAmB,OAAyB;CACnD,OAAO,iBAAiB,SAAS,MAAM,SAAS,oBAC9C,UAAU,SAAU,MAAqC,SAAS;AACtE;AAEA,gBAAgB,gBAAgB,OAAuB,WAA+D;CACpH,IAAI,MAAM,gBACR,IAAI;EACF,OAAO,MAAM,eAAe;GAAE,OAAO,EAAE,WAAWC,UAAc,UAAU,MAAM,SAAS,EAAE;GAAG,KAAK,UAAU;EAAI,CAAC;EAClH;CACF,SAAS,OAAO;EACd,IAAI,CAAC,mBAAmB,KAAK,GAAG,MAAM;CACxC;CAEF,OAAO,mBAAmB,MAAM,MAAM,SAAS;AACjD;AAEA,eAAe,wBACb,MACA,OAOwC;CACxC,IAAI,CAAC,MAAM,cAAc,MAAM,WAAW,SAAS,QAAQ,MAAM,UAAU,MAAM,KAAK,cAAc,OAAO,MAAM,IAAI,MAAM,MAAM,QAC/H,MAAM,IAAI,iBAAiB,mBAAmB,oCAAoC;CAEpF,IAAI;EACF,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,MAAM,IAAI;CAC7D,SAAS,OAAO;EACd,MAAM,IAAI,iBAAiB,mBAAmB,oCAAoC,KAAK;CACzF;CAEA,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM,YAAY,OAAO,MAAM,MAAM,SAAS;CAC9C,IAAI;EACF,MAAM,MAAM,QAAQ,IAAI,GAAG;GAAE,WAAW;GAAM,MAAM;EAAM,CAAC;EAC3D,WAAW,MAAM,SAAS,QAAQ,IAAI,CAAC;EACvC,YAAY,KAAK,UAAU,0BAA0B,SAAS,CAAC;EAC/D,MAAM,MAAM,WAAW;GAAE,WAAW;GAAM,MAAM;EAAM,CAAC;EACvD,IAAI,MAAM,SAAS,SAAS,MAAM,WAAW,MAAM,4BAA4B;EAC/E,MAAM,gBAAgB,MAAM,MAAM,SAAS;EAC3C,IACE,cAAc,eAAe,KAAK,CAAC,cAAc,YAAY,KAC5D,QAAQ,aAAa,YAAY,cAAc,OAAO,QAAW,GAClE,MAAM,4BAA4B;EACpC,WAAW,KAAK,WAAW,YAAY,WAAW,QAAQ,CAAC,CAAC,OAAO,MAAM,UAAU,CAAC,CAAC,OAAO,KAAK,GAAG;CACtG,SAAS,OAAO;EACd,IAAI,iBAAiB,kBAAkB,MAAM;EAC7C,MAAM,4BAA4B,KAAK;CACzC;CAEA,MAAM,MAAqC;EACzC,SAAS;EACT,OAAO,MAAM;EACb,eAAe;CACjB;CACA,IAAI;CACJ,IAAI;EACF,SAAS,MAAM,KAAK,UAAU,MAAM,GAAK;CAC3C,SAAS,OAAO;EACd,IAAI,iBAAiB,SAAS,UAAU,SAAU,MAAgC,SAAS,UAAU;GACnG,MAAM,WAAW,MAAM,aAAa,mBAAmB,UAAU;IAAE,OAAO,EAAE,UAAU;IAAG,QAAQ;KAAE,UAAU;KAAQ,QAAQ,MAAM;KAAY,OAAO;IAAQ;IAAG,eAAe;IAAa;GAAI,CAAC,CAAC;GACnM,IAAI,SAAS,eAAe,MAAM,SAAS,OAAO,QAAQ,MAAM,MAAM,QAAQ,OAAO;GACrF,MAAM,IAAI,iBAAiB,2BAA2B,yDAAyD,KAAK;EACtH;EACA,MAAM,4BAA4B,KAAK;CACzC;CAEA,IAAI;EACF,IAAI,SAAS;EACb,OAAO,SAAS,MAAM,KAAK,YAAY;GACrC,MAAM,EAAE,iBAAiB,MAAM,OAAO,MAAM,MAAM,MAAM,QAAQ,MAAM,KAAK,aAAa,QAAQ,IAAI;GACpG,IAAI,iBAAiB,GAAG,MAAM,4BAA4B;GAC1D,UAAU;EACZ;EACA,MAAM,OAAO,KAAK;EAClB,MAAM,OAAO,MAAM,OAAO,KAAK;EAC/B,IAAI,CAAC,KAAK,OAAO,KAAK,KAAK,SAAS,MAAM,SAAU,QAAQ,aAAa,YAAY,KAAK,OAAO,QAAW,GAC1G,MAAM,4BAA4B;CAEtC,SAAS,OAAO;EACd,MAAM,OAAO,MAAM;EACnB,SAAS,KAAA;EACT,IAAI;GACF,MAAM,OAAO,QAAQ;EACvB,QAAQ,CAAC;EACT,IAAI,iBAAiB,kBAAkB,MAAM;EAC7C,MAAM,4BAA4B,KAAK;CACzC,UAAU;EACR,IAAI,QAAQ,MAAM,OAAO,MAAM;CACjC;CACA,OAAO;AACT;AAEA,eAAe,kBACb,OACA,OASwC;CACxC,IAAI,MAAM,gBACR,OAAO,MAAM,eAAe;EAC1B,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,eAAe,MAAM;EACrB,YAAY,MAAM;EAClB,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,SAAS,SAAS,MAAM,IAAI;CAC9B,CAAC;CAEH,IAAI,OAAO,MAAM,SAAS,UAAU,OAAO,wBAAwB,MAAM,MAAM,KAAK;CACpF,MAAM,IAAI,iBAAiB,8BAA8B,8BAA8B;AACzF;AAUA,SAAS,cAAc,OAAwB;CAC7C,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO,KAAK,UAAU,KAAK;CAC5E,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,IAAI,MAAM,IAAI,aAAa,CAAC,CAAC,KAAK,GAAG,EAAE;CACxE,MAAM,SAAS;CACf,OAAO,IAAI,OAAO,KAAK,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,QAAQ,GAAG,KAAK,UAAU,GAAG,EAAE,GAAG,cAAc,OAAO,IAAI,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE;AACvH;AAEA,SAAS,OAAO,OAAoC;CAClD,OAAO,UAAU,WAAW,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,KAAK;AAClE;AAEA,SAAS,UAAU,MAAiC,IAAoB;CACtE,OAAO,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC;AAClC;AAEA,SAAS,cAAc,MAAwB,KAAqD;CAClG,OAAO,UAAU,MAAM,GAAG,IAAI,aAAa,IAAI,IAAI,QAAQ,IAAI;AACjE;AAEA,SAAS,SAAS,WAA2C;CAC3D,OAAO,UAAU,SAAS,GAAG,UAAU,MAAM,UAAU,IAAI,UAAU,IAAI,SAAS;AACpF;AAEA,SAAS,iBAAiB,UAAsC;CAC9D,OAAO,cAAc,WAAW,QAAQ;AAC1C;AAEA,SAAS,WAAW,OAA6C;CAC/D,OAAOC,WAAS,KAAK,KAAK,OAAO,MAAM,iBAAiB,YAAY,OAAO,MAAM,cAAc,YAC7F,yBAAyB,MAAM,KAAK,KAAK,yBAAyB,MAAM,KAAK,KAAK,yBAAyB,MAAM,MAAM;AAC3H;AAEA,SAAS,UAAU,OAA4C;CAC7D,OAAOA,WAAS,KAAK,KAAK,OAAO,MAAM,iBAAiB,YAAY,OAAO,MAAM,SAAS,YACxF,yBAAyB,MAAM,KAAK,KAAK,MAAM,cAAc,KAAA;AACjE;AAEA,SAAS,gBAAgB,OAA0C;CACjE,MAAM,SAAmC,CAAC;CAC1C,MAAM,SAAS,YAA2B;EACxC,IAAI,MAAM,QAAQ,OAAO,GAAG;GAC1B,KAAK,MAAM,SAAS,SAAS,MAAM,KAAK;GACxC;EACF;EACA,IAAI,CAACA,WAAS,OAAO,GAAG;EACxB,MAAM,YAAY,QAAQ;EAC1B,IAAI,cAAc,KAAA,GAAW;GAC3B,IACE,CAACA,WAAS,SAAS,KAAK,UAAU,YAAY,sBAAsB,CAAC,MAAM,QAAQ,UAAU,UAAU,GACvG,MAAM,IAAI,iBAAiB,0BAA0B,8BAA8B;GACrF,KAAK,MAAM,aAAa,UAAU,YAAY;IAC5C,IACE,CAACA,WAAS,SAAS,KAAK,CAACA,WAAS,UAAU,KAAK,KAAK,OAAO,UAAU,MAAM,cAAc,YAC3F,CAACA,WAAS,UAAU,MAAM,KAAK,OAAO,UAAU,OAAO,aAAa,YACpE,OAAO,UAAU,OAAO,WAAW,YAAY,OAAO,UAAU,OAAO,UAAU,YACjF,OAAO,UAAU,kBAAkB,YAAY,CAACA,WAAS,UAAU,GAAG,KACtE,OAAO,UAAU,IAAI,YAAY,YAChC,UAAU,IAAI,UAAU,KAAA,KAAa,CAAC,yBAAyB,UAAU,IAAI,KAAK,KACnF,OAAO,UAAU,IAAI,kBAAkB,UACvC,MAAM,IAAI,iBAAiB,0BAA0B,oCAAoC;IAC3F,OAAO,KAAK,SAA8C;GAC5D;EACF;EACA,KAAK,MAAM,SAAS,OAAO,OAAO,OAAO,GAAG,MAAM,KAAK;CACzD;CACA,MAAM,KAAK;CACX,OAAO;AACT;AAEA,SAAS,sBAAsB,QAAiC,WAA6C;CAC3G,MAAM,4BAAY,IAAI,IAAoB;CAC1C,KAAK,MAAM,SAAS,QAAsD;EACxE,IAAI,MAAM,SAAS,aAAa;EAChC,MAAM,OAAOA,WAAS,MAAM,IAAI,IAAI,MAAM,OAA6C,CAAC;EACxF,IAAI,OAAO,KAAK,WAAW,YAAY,OAAO,KAAK,SAAS,UAAU,UAAU,IAAI,KAAK,QAAQ,KAAK,IAAI;CAC5G;CACA,MAAM,wBAAQ,IAAI,IAAoC;CACtD,MAAM,QAAQ,OAAgB,WAAmD;EAC/E,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,KAAK,MAAM,SAAS,OAAO,KAAK,OAAO,MAAM;GAC7C;EACF;EACA,IAAI,CAACA,WAAS,KAAK,GAAG;EACtB,IAAI,MAAM,SAAS,UAAU,OAAO,MAAM,SAAS,UAAU;GAC3D,IAAI,QAAQ,MAAM,KAAK,QAAQ,yBAAyB;GACxD,OAAO,SAAS,GAAG;IACjB,MAAM,eAAe,QAAQ;IAC7B,MAAM,MAAM,MAAM,KAAK,QAAQ,2BAA2B,YAAY;IACtE,IAAI,MAAM,GAAG,MAAM,IAAI,iBAAiB,4BAA4B,oBAAoB;IACxF,MAAM,UAAU,MAAM,KAAK,MAAM,cAAc,GAAG;IAClD,IAAI,CAAC,WAAW,QAAQ,SAAS,QAAQ,wBAAwB,KAAK,OAAO,GAC3E,MAAM,IAAI,iBAAiB,4BAA4B,oBAAoB;IAE7E,MAAM,YAAoC;KACxC,OAAO,EAAE,UAAU;KACnB;KACA,eAAe,GAAG,OAAO,SAAS;KAClC,KAAK;MAAE;MAAS,eAAe;KAAwB;IACzD;IACA,MAAM,IAAI,SAAS,SAAS,GAAG,SAAS;IACxC,QAAQ,MAAM,KAAK,QAAQ,2BAA2B,MAAM,0BAA0B,MAAM;GAC9F;EACF;EACA,KAAK,MAAM,SAAS,OAAO,OAAO,KAAK,GAAG,KAAK,OAAO,MAAM;CAC9D;CAEA,KAAK,MAAM,SAAS,QAClB,IAAI,MAAM,SAAS,eAAe;EAChC,MAAM,OAAOA,WAAS,MAAM,IAAI,IAAI,MAAM,OAAO,CAAC;EAClD,MAAM,UAAUA,WAAS,KAAK,OAAO,IAAI,KAAK,UAAiE,CAAC;EAChH,MAAM,SAAS,QAAQ,QAAQ;EAC/B,IAAI,OAAO,WAAW,UACpB,KAAK,QAAQ,SAAS;GAAE,UAAU,UAAU,IAAI,MAAM,KAAK;GAAW;GAAQ,OAAO;EAAS,CAAC;CAEnG,OAAO,IAAI,MAAM,SAAS,sBAAsB;EAC9C,MAAM,OAAOA,WAAS,MAAM,IAAI,IAAI,MAAM,OAAmE,CAAC;EAC9G,IAAI,OAAO,KAAK,SAAS,YAAY,OAAO,KAAK,cAAc,UAC7D,KAAK,KAAK,SAAS;GAAE,UAAU,KAAK;GAAM,QAAQ,KAAK;GAAW,OAAO;EAAW,CAAC;CAEzF;CAEF,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC;AAC3B;AAEA,SAAS,qBAAqB,QAA+F;CAC3H,MAAM,yBAAS,IAAI,IAAgC;CACnD,MAAM,wBAAQ,IAAI,IAA+B;CACjD,MAAM,SAAS,UAAyB;EACtC,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,KAAK,MAAM,SAAS,OAAO,MAAM,KAAK;GACtC;EACF;EACA,IAAI,CAACA,WAAS,KAAK,GAAG;EACtB,IAAI,MAAM,SAAS,WAAW,WAAW,MAAM,UAAU,GAAG,OAAO,IAAI,cAAc,SAAS,MAAM,UAAU,GAAG,MAAM,UAAU;EACjI,IAAI,MAAM,SAAS,UAAU,UAAU,MAAM,UAAU,GAAG,MAAM,IAAI,cAAc,QAAQ,MAAM,UAAU,GAAG,MAAM,UAAU;EAC7H,KAAK,MAAM,SAAS,OAAO,OAAO,KAAK,GAAG,MAAM,KAAK;CACvD;CACA,KAAK,MAAM,SAAS,QAAQ,MAAM,KAAK;CACvC,OAAO;EAAE,QAAQ,CAAC,GAAG,OAAO,OAAO,CAAC;EAAG,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC;CAAE;AACpE;AAEA,SAAS,mBACP,QACA,qBACA,QACA,WACA,qBACA,SACA,cACQ;CACR,MAAM,+BAAe,IAAI,IAA+B;CACxD,MAAM,8BAAc,IAAI,IAA+B;CACvD,MAAM,+BAAe,IAAI,IAA+B;CACxD,KAAK,MAAM,UAAU,SACnB,IAAI,OAAO,SAAS,SAAS,aAAa,IAAI,cAAc,SAAS,OAAO,GAAG,GAAG,MAAM;MACnF,IAAI,OAAO,SAAS,QAAQ,YAAY,IAAI,cAAc,QAAQ,OAAO,GAAG,GAAG,MAAM;MACrF,aAAa,IAAI,SAAS,OAAO,SAAS,GAAG,MAAM;CAG1D,MAAM,aAAa,UAA4B;EAC7C,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,IAAI,SAAS;EACpD,IAAI,CAACA,WAAS,KAAK,GAAG,OAAO;EAC7B,IAAI,MAAM,SAAS,WAAW,WAAW,MAAM,UAAU,GAAG;GAC1D,MAAM,SAAS,aAAa,IAAI,cAAc,SAAS,MAAM,UAAU,CAAC;GACxE,OAAO,SACH;IAAE,MAAM;IAAS,QAAQ,OAAO;IAAQ,GAAI,MAAM,WAAW,OAAO,EAAE,MAAM,MAAM,WAAW,KAAK,IAAI,CAAC;GAAG,IAC1G;IAAE,MAAM;IAAS,SAAS,MAAM,WAAW;GAAa;EAC9D;EACA,IAAI,MAAM,SAAS,UAAU,UAAU,MAAM,UAAU,GAAG;GACxD,MAAM,SAAS,YAAY,IAAI,cAAc,QAAQ,MAAM,UAAU,CAAC;GACtE,OAAO,SAAS;IAAE,MAAM;IAAQ,QAAQ,OAAO;IAAQ,MAAM,MAAM,WAAW;GAAK,IAAI;IAAE,MAAM;IAAQ,SAAS,MAAM,WAAW;GAAa;EAChJ;EACA,MAAM,SAAkC,CAAC;EACzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAC7C,IAAI,QAAQ,2BAA2BA,WAAS,KAAK,KAAK,MAAM,QAAQ,MAAM,UAAU,GACtF,OAAO,OAAO;GACZ,SAAS,MAAM;GACf,YAAY,MAAM,WAAW,KAAK,cAAc;IAC9C,IAAI,CAACA,WAAS,SAAS,KAAK,CAACA,WAAS,UAAU,GAAG,GAAG,OAAO;IAC7D,MAAM,QAAQ,aAAa,IAAI,SAAS,SAA8C,CAAC;IACvF,OAAO,QACH;KAAE,QAAQ,UAAU;KAAQ,eAAe,UAAU;KAAe,QAAQ,MAAM;KAAQ,OAAO,MAAM;IAAM,IAC7G;KAAE,QAAQ,UAAU;KAAQ,eAAe,UAAU;KAAe,SAAS,UAAU,IAAI;IAAQ;GACzG,CAAC;EACH;OACK,IAAI,QAAQ,UAAU,OAAO,UAAU,UAAU;GACtD,IAAI,OAAO;GACX,KAAK,MAAM,UAAU,SAAS;IAC5B,IAAI,OAAO,SAAS,SAAS;IAC7B,MAAM,MAAM,OAAO,UAAU;IAC7B,OAAO,KAAK,WACV,oCAAoC,IAAI,QAAQ,IAAI,IAAI,iBACxD,oCAAoC,OAAO,OAAO,EACpD;GACF;GACA,OAAO,OAAO;EAChB,OACE,OAAO,OAAO,UAAU,KAAK;EAGjC,OAAO;CACT;CAEA,MAAM,EAAE,IAAI,KAAK,KAAK,MAAM,eAAe,SAAS,GAAG,iBAAiB;CAIxE,OAAO,OAAO,cAAc;EAC1B,QAAQ;EACR;EACA,QAAQ,OAAO,IAAI,SAAS;EAC5B,WAAW;GACT,kBAAkB,UAAU;GAC5B,mBAAmB,UAAU;GAC7B,YAAY,UAAU;GACtB,YAAY,UAAU;EACxB;EACA;EACA,qBAAqB,sBAAsB;GACzC,MAAM,oBAAoB;GAC1B,YAAY,oBAAoB;GAChC,iBAAiB,oBAAoB;GACrC,qBAAqB,oBAAoB;GACzC,mBAAmB,oBAAoB;GACvC,QAAQ,oBAAoB;GAC5B,qBAAqB,oBAAoB;EAC3C,IAAI,KAAA;CACN,CAAC,CAAC;AACJ;AAEA,SAAgB,uBAAuB,QAAyC;CAC9E,OAAO,OAAO,cAAc,MAAM,CAAC;AACrC;AAEA,SAAS,mBACP,WACA,mBACA,UACA,QACQ;CACR,OAAO,OAAO,cAAc;EAC1B,WAAW;GACT,kBAAkB,UAAU;GAC5B,mBAAmB,UAAU;GAC7B,YAAY,UAAU;GACtB,YAAY,UAAU;GACtB,OAAO,UAAU;GACjB,UAAU,UAAU;GACpB,eAAe,UAAU;EAC3B;EACA;EACA;EACA;CACF,CAAC,CAAC;AACJ;AAEA,SAAS,yBAAyB,OAOX;CACrB,IAAI,MAAM,aAAa,KAAA,GAAW,OAAO,KAAA;CACzC,IAAI;EACF,OAAO,OAAO,cAAc;GAAE,SAAS;GAA8B,GAAG;EAAM,CAAC,CAAC;CAClF,QAAQ;EACN;CACF;AACF;AAEA,SAAS,sBAAsB,WAAmB,UAA2B;CAC3E,OAAO,KAAK,UAAU,CAAC,WAAW,YAAY,IAAI,CAAC;AACrD;AAEA,SAAS,kBAAkB,OAAgB,OAAmC;CAC5E,MAAM,yBAAS,IAAI,QAAgB;CACnC,MAAM,WAAW,SAA0B;EACzC,IAAI,SAAS,MAAM,OAAO;EAC1B,IAAI,OAAO,SAAS,UAAU;GAC5B,MAAM,QAAQ,OAAO,WAAW,MAAM,MAAM;GAC5C,OAAO,QAAQ,QAAQ,IAAI,QAAQ,IAAI,QAAQ,IAAI;EACrD;EACA,IAAI,OAAO,SAAS,UAAU,OAAO,OAAO,SAAS,IAAI,IAAI,OAAO,IAAI,CAAC,CAAC,SAAS;EACnF,IAAI,OAAO,SAAS,WAAW,OAAO,OAAO,IAAI;EACjD,IAAI,SAAS,KAAA,KAAa,OAAO,SAAS,cAAc,OAAO,SAAS,UAAU,OAAO;EACzF,IAAI,OAAO,SAAS,UAAU,OAAO,QAAQ;EAC7C,IAAI,MAAM,QAAQ,IAAI,GAAG;GACvB,IAAI,OAAO,IAAI,IAAI,GAAG,OAAO,QAAQ;GACrC,OAAO,IAAI,IAAI;GACf,IAAI,QAAQ;GACZ,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;IACnD,IAAI,QAAQ,GAAG,SAAS;IACxB,SAAS,QAAQ,KAAK,MAAM;IAC5B,IAAI,QAAQ,OAAO;GACrB;GACA,OAAO,OAAO,IAAI;GAClB,OAAO;EACT;EACA,IAAI,OAAO,SAAS,UAAU;GAC5B,IAAI,OAAO,IAAI,IAAI,GAAG,OAAO,QAAQ;GACrC,MAAM,YAAY,OAAO,eAAe,IAAI;GAC5C,IAAI,cAAc,OAAO,aAAa,cAAc,MAAM,OAAO,QAAQ;GACzE,OAAO,IAAI,IAAI;GACf,IAAI,QAAQ;GACZ,IAAI,QAAQ;GACZ,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,GAAG;IAC/C,IAAI,UAAU,KAAA,KAAa,OAAO,UAAU,cAAc,OAAO,UAAU,UAAU;IACrF,IAAI,CAAC,OAAO,SAAS;IACrB,QAAQ;IACR,SAAS,OAAO,WAAW,KAAK,MAAM,IAAI,IAAI,IAAI,QAAQ,KAAK;IAC/D,IAAI,QAAQ,OAAO;GACrB;GACA,OAAO,OAAO,IAAI;GAClB,OAAO;EACT;EACA,OAAO,QAAQ;CACjB;CACA,IAAI;EACF,MAAM,QAAQ,QAAQ,KAAK;EAC3B,OAAO,SAAS,QAAQ,QAAQ,KAAA;CAClC,QAAQ;EACN;CACF;AACF;AAEA,SAAgB,qBACd,WACA,cACA,eACyB;CACzB,MAAM,UAA8B,CAAC;CACrC,MAAM,WAA+B,CAAC;CACtC,MAAM,SAAS,UAAoC,MAAM,YAAY,iBAAiB,MAAM,QAAQ;CACpG,MAAM,aAAa,IAAI,IAAI,aAAa,KAAK,UAAU,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC;CAC7E,MAAM,cAAc,IAAI,IAAI,cAAc,KAAK,UAAU,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC;CAC/E,IAAI,cAAc,QAAQ;EACxB,IAAI,UAAU;EACd,KAAK,MAAM,CAAC,KAAK,WAAW,aAAa;GACvC,MAAM,QAAQ,WAAW,IAAI,GAAG;GAChC,IAAI,CAAC,OAAO;IACV,QAAQ,KAAK,MAAM;IACnB;GACF;GACA,MAAM,aAAa,oBAAoB,MAAM,SAAS,UAAU,OAAO,SAAS,QAAQ;GACxF,IAAI,aAAa,GAAG,QAAQ,KAAK,MAAM;QAClC,IAAI,eAAe,GAAG;IACzB,IACE,MAAM,SAAS,kBAAkB,OAAO,SAAS,iBACjD,MAAM,SAAS,gBAAgB,OAAO,SAAS,eAC/C,QAAQ,MAAM,SAAS,OAAO,MAAM,QAAQ,OAAO,SAAS,OAAO,GACnE,MAAM,IAAI,iBAAiB,qBAAqB,mDAAmD;IACrG,WAAW;GACb,OAAO,WAAW;EACpB;EACA,OAAO;GAAE;GAAS;GAAU;EAAQ;CACtC;CACA,MAAM,uBAAO,IAAI,IAAI,CAAC,GAAG,WAAW,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC;CAClE,IAAI,UAAU;CACd,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,QAAQ,WAAW,IAAI,GAAG;EAChC,MAAM,SAAS,YAAY,IAAI,GAAG;EAClC,IAAI,CAAC,OAAO;GAAE,QAAQ,KAAK,MAAO;GAAG;EAAS;EAC9C,IAAI,CAAC,QAAQ;GAAE,SAAS,KAAK,KAAK;GAAG;EAAS;EAC9C,MAAM,aAAa,oBAAoB,MAAM,SAAS,UAAU,OAAO,SAAS,QAAQ;EACxF,IAAI,aAAa,GAAG,SAAS,KAAK,KAAK;OAClC,IAAI,aAAa,GAAG,QAAQ,KAAK,MAAM;OACvC,IACH,MAAM,SAAS,kBAAkB,OAAO,SAAS,iBACjD,MAAM,SAAS,gBAAgB,OAAO,SAAS,eAC/C,QAAQ,MAAM,SAAS,OAAO,MAAM,QAAQ,OAAO,SAAS,OAAO,GACnE,WAAW;OACR,MAAM,IAAI,iBAAiB,qBAAqB,mDAAmD;CAC1G;CACA,OAAO;EAAE;EAAS;EAAU;CAAQ;AACtC;AAEA,eAAe,aAAa,QAAmC,WAAW,yBAA0C;CAClH,MAAM,SAAmB,CAAC;CAC1B,IAAI,OAAO;CACX,WAAW,MAAM,SAAS,QAAQ;EAChC,IAAI,EAAE,iBAAiB,aAAa,MAAM,IAAI,iBAAiB,kBAAkB,iDAAiD;EAClI,QAAQ,MAAM;EACd,IAAI,OAAO,UAAU,MAAM,IAAI,iBAAiB,oBAAoB,2CAA2C;EAC/G,OAAO,KAAK,OAAO,KAAK,KAAK,CAAC;CAChC;CACA,OAAO,OAAO,OAAO,QAAQ,IAAI;AACnC;AAEA,gBAAgB,SAAS,MAA6C;CACpE,MAAM;AACR;AAeA,SAAS,wBAAwB,OAAqC;CACpE,MAAM,QAA2B;EAC/B;EACA,kCAAkB,IAAI,IAAI;EAC1B,qCAAqB,IAAI,IAAI;EAC7B,0CAA0B,IAAI,IAAI;CACpC;CACA,KAAK,MAAM,YAAY,OAAO,OAAO,MAAM,OAAO,GAAG;EACnD,IAAI,SAAS,SAAS,WAAW;EACjC,MAAM,UAAU,MAAM,iBAAiB,IAAI,SAAS,aAAa;EACjE,IAAI,CAAC,WAAW,oBAAoB,SAAS,UAAU,QAAQ,QAAQ,IAAI,GACzE,MAAM,iBAAiB,IAAI,SAAS,eAAe,QAAQ;CAE/D;CACA,KAAK,MAAM,WAAW,OAAO,OAAO,MAAM,UAAU,GAAG;EACrD,MAAM,WAAW,MAAM,oBAAoB,IAAI,QAAQ,gBAAgB,KAAK,CAAC;EAC7E,SAAS,KAAK,OAAO;EACrB,MAAM,oBAAoB,IAAI,QAAQ,kBAAkB,QAAQ;CAClE;CACA,KAAK,MAAM,WAAW,OAAO,OAAO,MAAM,QAAQ,GAChD,IAAI,CAAC,MAAM,yBAAyB,IAAI,QAAQ,cAAc,GAC5D,MAAM,yBAAyB,IAAI,QAAQ,gBAAgB,OAAO;CAGtE,OAAO;AACT;AAEA,SAAS,mBAAmB,OAA0B,UAAoC;CACxF,MAAM,MAAM,iBAAiB,QAAQ;CACrC,MAAM,WAAW,MAAM,MAAM,QAAQ;CACrC,IAAI,YAAY,SAAS,kBAAkB,SAAS,iBAClD,MAAM,iBAAiB,IAAI,SAAS,aAAa,MAAM,UAAU;EACjE,OAAO,MAAM,MAAM,QAAQ;EAC3B,MAAM,iBAAiB,OAAO,SAAS,aAAa;EACpD,KAAK,MAAM,aAAa,OAAO,OAAO,MAAM,MAAM,OAAO,GAAG;GAC1D,IAAI,UAAU,SAAS,aAAa,UAAU,kBAAkB,SAAS,eAAe;GACxF,MAAM,UAAU,MAAM,iBAAiB,IAAI,SAAS,aAAa;GACjE,IAAI,CAAC,WAAW,oBAAoB,UAAU,UAAU,QAAQ,QAAQ,IAAI,GAC1E,MAAM,iBAAiB,IAAI,SAAS,eAAe,SAAS;EAEhE;CACF;CACA,MAAM,MAAM,QAAQ,OAAO;CAC3B,MAAM,UAAU,MAAM,iBAAiB,IAAI,SAAS,aAAa;CACjE,IAAI,YAAY,YAAY,CAAC,WAAW,oBAAoB,SAAS,UAAU,QAAQ,QAAQ,IAAI,GACjG,MAAM,iBAAiB,IAAI,SAAS,eAAe,QAAQ;AAE/D;AAEA,SAAS,sBAAsB,OAA0B,KAAa,SAAqC;CACzG,MAAM,WAAW,MAAM,MAAM,WAAW;CACxC,IAAI,UAAU;EACZ,MAAM,WAAW,MAAM,oBAAoB,IAAI,SAAS,gBAAgB;EACxE,MAAM,gBAAgB,UAAU,WAAW,SACzC,iBAAiB,KAAK,kBAAkB,KAAK,mBAAmB,KAAK,UAAU,MAAM,GACvF,KAAK;EACL,IAAI,YAAY,kBAAkB,MAAM,SAAS,qBAAqB,QAAQ,kBAAkB;GAC9F,MAAM,MAAM,WAAW,OAAO;GAC9B,SAAS,iBAAiB;GAC1B;EACF;EACA,IAAI,YAAY,kBAAkB,IAAI,SAAS,OAAO,eAAe,CAAC;EACtE,IAAI,UAAU,WAAW,GAAG,MAAM,oBAAoB,OAAO,SAAS,gBAAgB;CACxF;CACA,MAAM,MAAM,WAAW,OAAO;CAC9B,MAAM,WAAW,MAAM,oBAAoB,IAAI,QAAQ,gBAAgB,KAAK,CAAC;CAC7E,SAAS,KAAK,OAAO;CACrB,MAAM,oBAAoB,IAAI,QAAQ,kBAAkB,QAAQ;AAClE;AAEA,SAAS,aAAa,OAA0B,kBAA0B,SAAmC;CAC3G,OAAO,MAAM,MAAM,SAAS;CAC5B,MAAM,MAAM,SAAS,QAAQ,YAAY;CACzC,MAAM,yBAAyB,MAAM;CACrC,KAAK,MAAM,SAAS,OAAO,OAAO,MAAM,MAAM,QAAQ,GACpD,IAAI,CAAC,MAAM,yBAAyB,IAAI,MAAM,cAAc,GAC1D,MAAM,yBAAyB,IAAI,MAAM,gBAAgB,KAAK;AAGpE;AAWA,SAAS,gBAAgB,WAA6E;CACpG,OAAO,OAAO,cAAc,SAAS,CAAC;AACxC;AAEA,SAAS,sBAAsB,WAAkC;CAC/D,OAAOC,UAAkB,UAAU,IAAI;AACzC;AAEA,SAAS,sBAAsB,QAAoC;CACjE,IAAI,CAACD,WAAS,MAAM,KAAK,OAAO,OAAO,OAAO,YAAY,CAAC,OAAO,MAAM,OAAO,OAAO,WAAW,YAC/F,CAAC,wBAAwB,KAAK,OAAO,MAAM,KAAK,CAAC,yBAAyB,OAAO,KAAK,KAAK,OAAO,OAAO,SAAS,UAClH,MAAM,IAAI,iBAAiB,kBAAkB,oCAAoC;CAGnF,IAAI,EADuB,OAAO,SAAS,WAAW,OAAO,gBAAgB,QAAQ,OAAO,UAAU,KAAK,OAAO,SAAS,KAClG;EACvB,MAAM,QAAQ,OAAO,KAAK,OAAO,MAAM,QAAQ;EAC/C,IAAI,MAAM,SAAS,QAAQ,MAAM,OAAO,QAAQ,MAAM,eAAe,OAAO,SAAS,OAAO,KAAK,MAAM,OAAO,QAC5G,MAAM,IAAI,iBAAiB,kBAAkB,8CAA8C;CAE/F;CACA,IAAI,OAAO,SAAS,WAAW,WAAW,OAAO,GAAG,KAAK,OAAO,OAAO,cAAc,SAAS,OAAO,GAAG,GACtG,OAAO;CAET,IAAI,OAAO,SAAS,UAAU,UAAU,OAAO,GAAG,KAAK,OAAO,OAAO,cAAc,QAAQ,OAAO,GAAG,GACnG,OAAO;CAET,IACE,OAAO,SAAS,WAAWA,WAAS,OAAO,SAAS,KAAKA,WAAS,OAAO,UAAU,KAAK,KACxF,OAAO,OAAO,UAAU,MAAM,cAAc,YAAYA,WAAS,OAAO,UAAU,GAAG,KACrF,OAAO,OAAO,UAAU,IAAI,YAAY,YAAY,OAAO,OAAO,SAAS,OAAO,SAA8C,GAEhI,OAAO;CAET,MAAM,IAAI,iBAAiB,kBAAkB,6CAA6C;AAC5F;AAEA,SAAS,mBAAmB,OAAuC;CACjE,IAAI,CAACA,WAAS,KAAK,KAAK,CAAC,yBAAyB,MAAM,cAAc,KACpE,OAAO,MAAM,oBAAoB,YAAY,CAAC,wBAAwB,KAAK,MAAM,eAAe,KAChG,CAAC,yBAAyB,MAAM,uBAAuB,KACvD,CAAC,yBAAyB,MAAM,cAAc,KAAK,MAAM,iBAAiB,MAAM,kBAChF,OAAO,MAAM,oBAAoB,YAAY,CAAC,wBAAwB,KAAK,MAAM,eAAe,GAChG,MAAM,IAAI,iBAAiB,oBAAoB,yCAAyC;CAE1F,OAAO;EACL,gBAAgB,MAAM;EACtB,iBAAiB,MAAM;EACvB,yBAAyB,MAAM;EAC/B,gBAAgB,MAAM;EACtB,iBAAiB,MAAM;CACzB;AACF;AAEA,SAAS,cAAc,OAAkC;CACvD,IAAI,CAACA,WAAS,KAAK,KAAK,CAACA,WAAS,MAAM,QAAQ,KAAK,MAAM,SAAS,SAAS,WAC3E,MAAM,IAAI,iBAAiB,oBAAoB,mCAAmC;CAEpF,MAAM,WAAW,MAAM;CACvB,IACE,OAAO,SAAS,qBAAqB,YAAY,CAAC,SAAS,oBAAoB,SAAS,iBAAiB,SAAS,OAAO,wBAAwB,KAAK,SAAS,gBAAgB,KAC/K,OAAO,SAAS,mBAAmB,YAAY,CAAC,SAAS,kBAAkB,SAAS,eAAe,SAAS,OAAO,wBAAwB,KAAK,SAAS,cAAc,KACvK,OAAO,SAAS,kBAAkB,YAAY,CAAC,SAAS,iBAAiB,SAAS,cAAc,SAAS,OAAO,wBAAwB,KAAK,SAAS,aAAa,KACnK,OAAO,SAAS,kBAAkB,YAClC,CAAC,wBAAwB,KAAK,SAAS,aAAa,KAAK,CAAC,SAAS,YACnE,CAAC,yBAAyB,SAAS,SAAS,cAAc,KAC1D,CAAC,yBAAyB,SAAS,SAAS,cAAc,KAAK,OAAO,SAAS,SAAS,qBAAqB,YAC7G,CAAC,SAAS,SAAS,oBAAoB,wBAAwB,KAAK,SAAS,SAAS,gBAAgB,GACtG,MAAM,IAAI,iBAAiB,oBAAoB,2CAA2C;CAC5F,IAAI,SAAS,gBAAgB,KAAA,KAAa,CAAC,wBAAwB,KAAK,SAAS,WAAW,GAC1F,MAAM,IAAI,iBAAiB,oBAAoB,iCAAiC;CAElF,IAAI,SAAS,YAAY,KAAA,KAAa,OAAO,SAAS,YAAY,WAChE,MAAM,IAAI,iBAAiB,oBAAoB,mCAAmC;CAEpF,IAAI,MAAM,aAAa,KAAA,MAAc,OAAO,MAAM,aAAa,YAAY,CAAC,mBAAmB,KAAK,MAAM,QAAQ,IAChH,MAAM,IAAI,iBAAiB,oBAAoB,8BAA8B;CAE/E,IAAI,SAAS,oBAAoB,KAAA,GAAW,eAAe,SAAS,eAAe;CACnF,MAAM,aAAa,MAAM,eAAe,KAAA,IAAY,KAAA,IAAY,mBAAmB,MAAM,UAAU;CACnG,IAAI,SAAS,SAAS;EACpB,IAAI,YAAY,MAAM,IAAI,iBAAiB,oBAAoB,8CAA8C;EAC7G,IAAI,SAAS,kBAAkB,uBAAuB,QAAQ,GAAG,MAAM,IAAI,iBAAiB,oBAAoB,qCAAqC;EACrJ,OAAO;GAAE;GAAU,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAmB,IAAI,CAAC;EAAG;CACvF;CACA,MAAM,YAAYA,WAAS,MAAM,SAAS,IAAI,MAAM,YAAY,KAAA;CAChE,MAAM,oBAAoB,aAAaA,WAAS,UAAU,QAAQ,IAAI,UAAU,WAAW,KAAA;CAC3F,IACE,OAAO,MAAM,yBAAyB,YAAY,CAACA,WAAS,MAAM,MAAM,KACxE,OAAO,MAAM,wBAAwB,YAAY,CAAC,OAAO,cAAc,MAAM,mBAAmB,KAAK,MAAM,sBAAsB,KACjI,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,CAAC,aAAa,CAAC,MAAM,QAAQ,MAAM,OAAO,KAC1E,OAAO,UAAU,qBAAqB,YAAY,OAAO,UAAU,sBAAsB,YACzF,CAACA,WAAS,UAAU,UAAU,KAAK,OAAO,UAAU,WAAW,qBAAqB,YACpF,OAAO,UAAU,WAAW,mBAAmB,YAAY,OAAO,UAAU,eAAe,YAC3F,CAAC,MAAM,WAAW,UAAU,UAAU,KAAK,MAAM,UAAU,UAAU,UAAU,MAAM,UAAU,cAC/F,OAAO,UAAU,UAAU,YAAY,OAAO,UAAU,kBAAkB,YAC1E,CAAC,wBAAwB,KAAK,UAAU,aAAa,KACrD,CAAC,qBAAqB,CAAC,yBAAyB,kBAAkB,cAAc,KAChF,CAAC,yBAAyB,kBAAkB,cAAc,KAC1D,OAAO,kBAAkB,qBAAqB,YAC9C,OAAO,MAAM,sBAAsB,YAAY,CAAC,OAAO,cAAc,MAAM,iBAAiB,KAAK,MAAM,oBAAoB,KAC3H,OAAO,MAAM,aAAa,aAAa,OAAO,MAAM,WAAW,WAC/D,MAAM,IAAI,iBAAiB,oBAAoB,yCAAyC;CAC1F,IAAI,eAAe,MAAM,aAAa,KAAA,KAAa,MAAM,WACvD,MAAM,IAAI,iBAAiB,oBAAoB,uCAAuC;CAExF,IAAI,MAAM,OAAO,SAAS,oBAAoB,KAAK,MAAM,IAAI,iBAAiB,oBAAoB,mCAAmC;CACrI,MAAM,SAAS,MAAM;CACrB,IAAI,OAAO,YAAA,KAAsC,OAAO,OAAO,MAAM,sBACnE,MAAM,IAAI,iBAAiB,kBAAkB,wCAAwC;CAEvF,IAAI;CACJ,IAAI,YAAY;EACd,IAAI,WAAW,4BAA4B,MAAM,uBAC/C,WAAW,iBAAiB,oBAAoB,OAChD,WAAW,iBAAiB,WAAW,mBAAmB,MAAM,OAAO,QACvE,MAAM,IAAI,iBAAiB,oBAAoB,6CAA6C;EAE9F,SAAS,gBAAgB,MAAM,MAAM;EACrC,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,GAClD,IAAI,CAAC,yBAAyB,OAAO,MAAM,EAAE,GAAG,KAAK,OAAO,MAAM,EAAE,QAAQ,WAAW,iBAAiB,OACtG,MAAM,IAAI,iBAAiB,oBAAoB,yCAAyC;CAG9F,OAAO;EACL,SAAS,qBAAqB,QAAQ,gBAAgB,MAAM,MAAM,CAAmB;EACrF,iBAAiB,OAAO,IAAI,QAAQ,CAAC;CACvC;CACA,MAAM,UAAU,MAAM,QAAQ,IAAI,qBAAqB;CACvD,IAAI,IAAI,IAAI,QAAQ,KAAK,WAAW,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,QAAQ,QAC/D,MAAM,IAAI,iBAAiB,oBAAoB,0CAA0C;CAE3F,MAAM,iBAAiB;CAQvB,IAAI,gBAAgB;EANlB,kBAAkB,eAAe;EACjC,mBAAmB,eAAe;EAClC,YAAY,eAAe;EAC3B,YAAY,eAAe;EAC3B,OAAO,eAAe;CAEQ,CAAC,MAAM,eAAe,eACpD,MAAM,IAAI,iBAAiB,oBAAoB,qCAAqC;CAEtF,MAAM,sBAAsB,MAAM,wBAAwB,KAAA,IACtD,KAAA,IACA,4BAA4B,MAAM,mBAAmB;CACzD,MAAM,oCAAoB,IAAI,IAAY;CAC1C,MAAM,cAAc,qBAAqB,MAAM;CAC/C,KAAK,MAAM,OAAO,YAAY,QAAQ,kBAAkB,IAAI,cAAc,SAAS,GAAG,CAAC;CACvF,KAAK,MAAM,OAAO,YAAY,OAAO,kBAAkB,IAAI,cAAc,QAAQ,GAAG,CAAC;CACrF,KAAK,MAAM,aAAa,CAAC,GAAG,gBAAgB,MAAM,GAAG,GAAG,sBAAsB,QAAQ,OAAO,OAAO,EAAE,CAAC,CAAC,GACtG,kBAAkB,IAAI,SAAS,SAAS,CAAC;CAE3C,MAAM,YAAY,IAAI,IAAI,QAAQ,KAAK,WAAW,OAAO,EAAE,CAAC;CAC5D,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC,MAAM,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC,KACvD,CAAC,cAAc,CAAC,GAAG,SAAS,CAAC,CAAC,MAAM,OAAO,CAAC,kBAAkB,IAAI,EAAE,CAAC,GACtE,MAAM,IAAI,iBAAiB,oBAAoB,qDAAqD;CAEtG,MAAM,eAAe,MAAM,iBAAiB,KAAA,IAAY,KAAA,IAAY,eAAe,MAAM,YAAY;CACrG,IAAI,CAAC,YACmB;MAAA,mBACpB,QACA,MAAM,qBACN,QACA,gBACA,qBACA,SACA,YAEc,MAAM,SAAS,eAAe,MAAM,IAAI,iBAAiB,oBAAoB,mCAAmC;CAAA;CAElI,IAAI,SAAS,gBAAgB,mBAAmB,gBAAgB,MAAM,mBAA6B,MAAM,UAAqB,MAAM,MAAiB,GACnJ,MAAM,IAAI,iBAAiB,oBAAoB,iCAAiC;CAElF,OAAO;EACL;EACA,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAmB,IAAI,CAAC;EAC/D,sBAAsB,MAAM;EAC5B;EACA,qBAAqB,MAAM;EAC3B,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;EACvC,WAAW;EACX,mBAAmB,MAAM;EACzB,UAAU,MAAM;EAChB,QAAQ,MAAM;EACd,GAAI,sBAAsB,EAAE,oBAAoB,IAAI,CAAC;EACrD;EACA;EACA,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;CACrC;AACF;AAEA,SAAS,sBAAsB,OAA0C;CACvE,IAAI,CAACA,WAAS,KAAK,KAAK,CAACA,WAAS,MAAM,QAAQ,KAAK,MAAM,SAAS,SAAS,WAC3E,MAAM,IAAI,iBAAiB,oBAAoB,4CAA4C;CAE7F,MAAM,WAAW,MAAM;CACvB,IACE,OAAO,SAAS,qBAAqB,YAAY,CAAC,SAAS,oBAAoB,SAAS,iBAAiB,SAAS,OAAO,wBAAwB,KAAK,SAAS,gBAAgB,KAC/K,OAAO,SAAS,mBAAmB,YAAY,CAAC,SAAS,kBAAkB,SAAS,eAAe,SAAS,OAAO,wBAAwB,KAAK,SAAS,cAAc,KACvK,OAAO,SAAS,kBAAkB,YAAY,CAAC,SAAS,iBAAiB,SAAS,cAAc,SAAS,OAAO,wBAAwB,KAAK,SAAS,aAAa,KACnK,OAAO,SAAS,kBAAkB,YAAY,CAAC,wBAAwB,KAAK,SAAS,aAAa,KAAK,CAAC,SAAS,YACjH,CAAC,yBAAyB,SAAS,SAAS,cAAc,KAC1D,CAAC,yBAAyB,SAAS,SAAS,cAAc,KAAK,OAAO,SAAS,SAAS,qBAAqB,YAC7G,CAAC,SAAS,SAAS,oBAAoB,wBAAwB,KAAK,SAAS,SAAS,gBAAgB,GACtG,MAAM,IAAI,iBAAiB,oBAAoB,8CAA8C;CAC/F,IAAI,SAAS,gBAAgB,KAAA,KAAa,CAAC,wBAAwB,KAAK,SAAS,WAAW,GAC1F,MAAM,IAAI,iBAAiB,oBAAoB,0CAA0C;CAE3F,IAAI,SAAS,YAAY,KAAA,KAAa,OAAO,SAAS,YAAY,WAChE,MAAM,IAAI,iBAAiB,oBAAoB,4CAA4C;CAE7F,MAAM,gBAAgB,MAAM,eAAe,KAAA;CAC3C,MAAM,iBAAiB,MAAM,gBAAgB,KAAA;CAC7C,MAAM,yBAAyB,MAAM,wBAAwB,KAAA;CAC7D,IAAI,iBAAiB,kBAAkB,wBACjC;MAAA,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,0BAA0B,SAAS,WAC3E,CAAC,yBAAyB,MAAM,UAAU,KAAK,MAAM,aAAa,oBAAoB,OACtF,OAAO,MAAM,gBAAgB,YAAY,CAAC,wBAAwB,KAAK,MAAM,WAAW,KACxF,CAAC,yBAAyB,MAAM,mBAAmB,KAAK,MAAM,sBAAsB,MAAM,YAC1F,MAAM,IAAI,iBAAiB,oBAAoB,kCAAkC;CAAA;CAGrF,IAAI,MAAM,aAAa,KAAA,MAAc,OAAO,MAAM,aAAa,YAAY,CAAC,mBAAmB,KAAK,MAAM,QAAQ,IAChH,MAAM,IAAI,iBAAiB,oBAAoB,uCAAuC;CAExF,IAAI,SAAS,oBAAoB,KAAA,GAAW,eAAe,SAAS,eAAe;CACnF,IAAI,SAAS,WAAW,SAAS,kBAAkB,uBAAuB,QAAQ,GAChF,MAAM,IAAI,iBAAiB,oBAAoB,8CAA8C;CAE/F,OAAO;EACL;EACA,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAmB,IAAI,CAAC;EAC/D,GAAI,gBAAgB,EAAE,YAAY,MAAM,WAAqB,IAAI,CAAC;EAClE,GAAI,iBAAiB,EAAE,aAAa,MAAM,YAAsB,IAAI,CAAC;EACrE,GAAI,yBAAyB,EAAE,qBAAqB,MAAM,oBAA8B,IAAI,CAAC;CAC/F;AACF;AAEA,SAAS,aAAa,QAA2F;CAC/G,MAAM,gBAAgB,IAAI,KAAK,OAAO,WAAW,CAAC,EAAA,CAAG,KAAK,WAAW,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC;CACzF,MAAM,WAAW,OAAO,QAAQ,KAAK,WAAW;EAC9C,KAAK,MAAM,YAAY,iBAAiB,MAAM,QAAQ;EACtD,UAAU,MAAM,SAAS;EACzB,eAAe,MAAM,SAAS;EAC9B,aAAa,MAAM,SAAS;EAC5B,SAAS,QAAQ,MAAM,SAAS,OAAO;EACvC,UAAU,MAAM,YAAY,MAAM,mBAAmB,CAAC,EAAA,CAAG,KAAK,OAAO;GACnE,MAAM,SAAS,cAAc,IAAI,EAAE;GACnC,IAAI,CAAC,QAAQ,MAAM,IAAI,iBAAiB,oBAAoB,qCAAqC;GACjG,OAAO;EACT,CAAC,EAAA,CAAG,KAAK,YAAY;GAAE,IAAI,OAAO;GAAI,QAAQ,OAAO;GAAQ,OAAO,OAAO;EAAM,EAAE,CAAC,CACjF,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;EACxD,YAAY,MAAM,eAAe,KAAA,IAAY,KAAA,IAAY;GACvD,GAAG,MAAM;GACT,cAAc,uBAAuB,MAAM,UAAU,CAAC,CAAC;EACzD;CACF,EAAE,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;CAC7D,MAAM,UAAU,OAAO,QAAQ,KAAK,WAAW;EAAE,WAAW,MAAM;EAAW,QAAQ,MAAM;CAAO,EAAE,CAAC,CAClG,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,YAAY,KAAK,EAAE,YAAY,EAAE,YAAY,IAAI,CAAC;CACpF,OAAO,OAAO,cAAc;EAAE,YAAY,OAAO;EAAY,SAAS;EAAU;CAAQ,CAAC,CAAC;AAC5F;AAEA,SAAS,yBAAyB,QAGC;CACjC,MAAM,SAAS,OAAO,YAAY,KAAA,oBAAY,IAAI,IAA+B,IAAI,IAAI,IACvF,OAAO,QAAQ,KAAK,WAAW;EAC7B,MAAM,YAAY,sBAAsB,MAAM;EAC9C,OAAO,CAAC,UAAU,IAAI,SAAS;CACjC,CAAC,CACH;CACA,IAAI,OAAO,UAAU,OAAO,SAAS,UAAU,IAC7C,MAAM,IAAI,iBAAiB,oBAAoB,kDAAkD;CAEnG,KAAK,MAAM,SAAS,OAAO,SAAS;EAClC,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU;EACzC,IAAI,MAAM,oBAAoB,KAAA,MAAc,CAAC,MAAM,QAAQ,MAAM,eAAe,KAC9E,IAAI,IAAI,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,gBAAgB,UAC9D,MAAM,gBAAgB,MAAM,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,IAClD,MAAM,IAAI,iBAAiB,oBAAoB,oDAAoD;CAEvG;CACA,OAAO;AACT;AAEA,SAAgB,0BAA0B,OAAmC;CAC3E,IAAI,CAACA,WAAS,KAAK,KAAK,MAAM,oBAAoB,KAAK,OAAO,MAAM,eAAe,YACjF,CAAC,mBAAmB,KAAK,MAAM,UAAU,KAAK,CAAC,MAAM,QAAQ,MAAM,OAAO,KAAK,OAAO,MAAM,WAAW,UACvG,MAAM,IAAI,iBAAiB,oBAAoB,kCAAkC;CAEnF,IAAI,MAAM,YAAY,KAAA,MAAc,CAAC,MAAM,QAAQ,MAAM,OAAO,KAAK,MAAM,QAAQ,MAAM,WAAW,CAACA,WAAS,MAAM,CAAC,IACnH,MAAM,IAAI,iBAAiB,oBAAoB,+CAA+C;CAEhG,MAAM,gBAAgB,yBAAyB;EAC7C,GAAI,MAAM,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAA+B;EACvF,SAAS,MAAM;CACjB,CAAC;CACD,MAAM,UAAU,MAAM,YAAY,KAAA,IAAY,CAAC,IAAI,MAAM;CACzD,IAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,MAAM,SAC3C,CAACA,WAAS,IAAI,KAAK,OAAO,KAAK,cAAc,YAAY,OAAO,KAAK,WAAW,QAClF,GAAG,MAAM,IAAI,iBAAiB,oBAAoB,uCAAuC;CACzF,IAAI,MAAM,QAAQ,SAAS,mBAAmB,MAAM,IAAI,iBAAiB,oBAAoB,0CAA0C;CACvI,MAAM,UAAU,MAAM,QAAQ,KAAK,UAAU;EAC3C,MAAM,eAAiC,EAAE,GAAG,MAAM;EAClD,IAAI,aAAa,oBAAoB,KAAA,GAAW;GAC9C,IAAI,aAAa,YAAY,KAAA,GAC3B,MAAM,IAAI,iBAAiB,oBAAoB,sDAAsD;GAEvG,aAAa,UAAU,aAAa,gBAAgB,KAAK,OAAO,cAAc,IAAI,EAAE,CAAE;EACxF;EACA,OAAO,cAAc,YAAY;CACnC,CAAC;CACD,MAAM,OAAO,QAAQ,KAAK,UAAU,MAAM,YAAY,iBAAiB,MAAM,QAAQ,CAAC;CACtF,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,SAAS,KAAK,QAAQ,MAAM,IAAI,iBAAiB,oBAAoB,2CAA2C;CAClI,MAAM,SAA4B;EAChC,iBAAiB;EACjB,YAAY,MAAM;EAClB;EACS;EACT,GAAI,MAAM,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAA+B;EACvF,QAAQ,MAAM;CAChB;CACA,IAAI,aAAa,MAAM,MAAM,OAAO,QAAQ,MAAM,IAAI,iBAAiB,mBAAmB,sCAAsC;CAChI,IAAI,OAAO,WAAW,KAAK,UAAU,MAAM,GAAG,MAAM,IAAA,cAClD,MAAM,IAAI,iBAAiB,oBAAoB,2CAA2C;CAE5F,OAAO;AACT;AAEA,SAAgB,sBACd,YACA,SACA,UAAwD,CAAC,GACzD,eACmB;CACnB,IAAI,kBAAkB,KAAA,GAAW;EAC/B,MAAM,mBAAmB,QAAQ,MAAM,WAAW,MAAM,SAAS,UAAU,KAAK,KAAK,MAAM,oBAAoB,KAAA,CAAS;EASxH,MAAM,SAA4B;GAChC,iBAAiB;GACjB;GACA,SAXoB,mBAClB,QAAQ,KAAK,UAAU;IACrB,IAAI,MAAM,YAAY,KAAA,GAAW,OAAO;IACxC,MAAM,EAAE,SAAS,GAAG,SAAS;IAE7B,OAAO;KAAE,GAAG;KAAM,iBAAiB,QAAQ,KAAK,WAAW,OAAO,EAAE;IAAE;GACxE,CAAC,IACD;GAKF;GACA,GAAI,mBAAmB,EAAE,SAAS,cAAc,IAAI,CAAC;GACrD,QAAQ;EACV;EACA,OAAO,SAAS,aAAa,MAAM;EACnC,IAAI,OAAO,WAAW,KAAK,UAAU,MAAM,GAAG,MAAM,IAAA,cAClD,MAAM,IAAI,iBAAiB,oBAAoB,2CAA2C;EAE5F,OAAO;CACT;CACA,MAAM,SAA4B;EAAE,iBAAiB;EAAG;EAAY;EAAS;EAAS,QAAQ;CAAG;CACjG,OAAO,SAAS,aAAa,MAAM;CACnC,IAAI,OAAO,WAAW,KAAK,UAAU,MAAM,GAAG,MAAM,IAAA,cAClD,MAAM,IAAI,iBAAiB,oBAAoB,2CAA2C;CAE5F,OAAO;AACT;AAEA,SAAgB,oBAAoB,OAAwE;CAC1G,OAAO,MAAM,YAAY,iBAAiB,MAAM,QAAQ;AAC1D;AAEA,SAAS,cAAc,OAAyB,QAAmD;CACjG,IAAI,CAAC,UAAU,MAAM,SAAS,WAAW,MAAM,YAAY,CAAC,MAAM,UAAU,MAAM,OAAO,WAAW,KAClG,OAAO,eAAe,KAAK,OAAO,aAAa,MAAM,OAAO,UAC5D,OAAO,wBAAwB,MAAM,qBAAqB,OAAO;CAEnE,IAAI,uBADe,MAAM,OAAO,MAAM,GAAG,OAAO,UACZ,CAAC,MAAM,OAAO,aAAa,OAAO;CACtE,MAAM,kBAAkB,MAAM,gBAAgB,KAAA,KAAa,MAAM,eAAe,MAAM,OAAO,SACzF,MAAM,cACN,uBAAuB,MAAM,MAAM;CACvC,OAAO;EACL,GAAG;EACH,YAAY;GACV,gBAAgB,OAAO;GACvB,iBAAiB,OAAO;GACxB,yBAAyB,OAAO;GAChC,gBAAgB,MAAM,OAAO;GAC7B;EACF;EACA,QAAQ,MAAM,OAAO,MAAM,OAAO,UAAU;CAC9C;AACF;AAEA,SAAS,sBAAsB,UAAmF;CAChH,MAAM,UAAU,SAAS,QAAQ,KAAK,WAAW;EAC/C,KAAK,oBAAoB,KAAK;EAC9B,UAAU,MAAM;EAChB,YAAY,MAAM;EAClB,aAAa,MAAM;EACnB,qBAAqB,MAAM;CAC7B,EAAE,CAAC,CACA,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;CAC5D,MAAM,UAAU,SAAS,QAAQ,KAAK,WAAW;EAAE,WAAW,MAAM;EAAW,QAAQ,MAAM;CAAO,EAAE,CAAC,CACpG,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,YAAY,KAAK,EAAE,YAAY,EAAE,YAAY,IAAI,CAAC;CACpF,OAAO,OAAO,cAAc;EAAE,YAAY,SAAS;EAAY;EAAS;CAAQ,CAAC,CAAC;AACpF;AAEA,SAAgB,wBACd,YACA,SACA,UAAwD,CAAC,GACpC;CACrB,MAAM,WAAgC;EACpC,iBAAiB;EACjB;EACA,SAAS,QAAQ,KAAK,WAAW;GAC/B,UAAU,MAAM;GAChB,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;GACrD,GAAI,MAAM,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY,MAAM,WAAW;GACzE,GAAI,MAAM,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,MAAM,YAAY;GAC5E,GAAI,MAAM,wBAAwB,KAAA,IAAY,CAAC,IAAI,EAAE,qBAAqB,MAAM,oBAAoB;EACtG,EAAE;EACF;EACA,QAAQ;CACV;CACA,SAAS,SAAS,sBAAsB,QAAQ;CAChD,IAAI,OAAO,WAAW,KAAK,UAAU,QAAQ,GAAG,MAAM,IAAA,cACpD,MAAM,IAAI,iBAAiB,oBAAoB,6CAA6C;CAE9F,OAAO;AACT;AAEA,SAAgB,4BAA4B,OAAqC;CAC/E,IAAI,CAACA,WAAS,KAAK,KAAK,MAAM,oBAAoB,KAAK,OAAO,MAAM,eAAe,YACjF,CAAC,mBAAmB,KAAK,MAAM,UAAU,KAAK,CAAC,MAAM,QAAQ,MAAM,OAAO,KAAK,OAAO,MAAM,WAAW,UACvG,MAAM,IAAI,iBAAiB,oBAAoB,oCAAoC;CAErF,MAAM,UAAU,MAAM,YAAY,KAAA,IAAY,CAAC,IAAI,MAAM;CACzD,IAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,MAAM,SAC3C,CAACA,WAAS,IAAI,KAAK,OAAO,KAAK,cAAc,YAAY,OAAO,KAAK,WAAW,QAClF,GAAG,MAAM,IAAI,iBAAiB,oBAAoB,yCAAyC;CAC3F,IAAI,MAAM,QAAQ,SAAS,mBAAmB,MAAM,IAAI,iBAAiB,oBAAoB,4CAA4C;CACzI,MAAM,UAAU,MAAM,QAAQ,IAAI,qBAAqB;CACvD,MAAM,OAAO,QAAQ,IAAI,mBAAmB;CAC5C,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,SAAS,KAAK,QAAQ,MAAM,IAAI,iBAAiB,oBAAoB,6CAA6C;CACpI,MAAM,WAAgC;EACpC,iBAAiB;EACjB,YAAY,MAAM;EAClB;EACS;EACT,QAAQ,MAAM;CAChB;CACA,IAAI,sBAAsB,QAAQ,MAAM,SAAS,QAC/C,MAAM,IAAI,iBAAiB,mBAAmB,wCAAwC;CAExF,IAAI,OAAO,WAAW,KAAK,UAAU,QAAQ,GAAG,MAAM,IAAA,cACpD,MAAM,IAAI,iBAAiB,oBAAoB,6CAA6C;CAE9F,OAAO;AACT;AAEA,SAAS,mBAA2C;CAClD,OAAO;EAAE,SAAS;EAAG,SAAS;EAAG,UAAU;EAAG,SAAS;EAAG,SAAS;EAAG,UAAU;CAAE;AACpF;AAEA,SAAS,iBAAiB,MAAyB;CACjD,OAAO,SAAS,gBAAgB,SAAS;AAC3C;AAEA,SAAS,YAAY,UAAsC;CACzD,OAAO,KAAK,WAAW,QAAQ,CAAC,CAAC,OAAO,cAAc;EACpD,kBAAkB,SAAS;EAC3B,gBAAgB,SAAS;EACzB,eAAe,SAAS;CAC1B,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE;AAC/B;AAEA,SAAS,uBAAuB,UAAmF;CACjH,OAAO,OAAO,cAAc;EAC1B,MAAM;EACN,kBAAkB,SAAS;EAC3B,gBAAgB,SAAS;EACzB,SAAS;CACX,CAAC,CAAC;AACJ;AAEA,SAAS,eAAe,OAA4B;CAClD,IAAI,CAACA,WAAS,KAAK,KAAK,OAAO,MAAM,qBAAqB,YAAY,CAAC,MAAM,oBAC3E,OAAO,MAAM,mBAAmB,YAAY,CAAC,MAAM,kBACnD,MAAM,iBAAiB,SAAS,OAAO,MAAM,eAAe,SAAS,OACrE,wBAAwB,KAAK,MAAM,gBAAgB,KAAK,wBAAwB,KAAK,MAAM,cAAc,GACzG,MAAM,IAAI,iBAAiB,oBAAoB,qCAAqC;CAEtF,OAAO;EAAE,kBAAkB,MAAM;EAAkB,gBAAgB,MAAM;CAAe;AAC1F;AAEA,SAAS,4BAA4B,OAAgD;CACnF,IAAI,CAACA,WAAS,KAAK,KAAK,OAAO,MAAM,SAAS,YAC5C,OAAO,WAAW,MAAM,MAAM,MAAM,IAAA,SACpC,OAAO,MAAM,eAAe,YAAY,MAAM,WAAW,SAAS,IAClE,MAAM,IAAI,iBAAiB,oBAAoB,yCAAyC;CAE1F,IAAI,MAAM,sBAAsB,KAAA,KAAa,CAAC,yBAAyB,MAAM,iBAAiB,GAC5F,MAAM,IAAI,iBAAiB,oBAAoB,2CAA2C;CAE5F,IAAI,MAAM,WAAW,KAAA,MAAc,OAAO,MAAM,WAAW,YAAY,CAAC,iBAAiB,KAAK,MAAM,MAAM,IACxG,MAAM,IAAI,iBAAiB,oBAAoB,+BAA+B;CAEhF,IAAI,MAAM,wBAAwB,KAAA,MAChC,OAAO,MAAM,wBAAwB,YAAY,CAAC,MAAM,WAAW,MAAM,mBAAmB,KAC5F,MAAM,UAAU,MAAM,mBAAmB,MAAM,MAAM,sBACpD,MAAM,IAAI,iBAAiB,oBAAoB,uCAAuC;CACzF,OAAO;EACL,MAAM,MAAM;EACZ,YAAY,MAAM;EAClB,GAAI,MAAM,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,eAAe,MAAM,eAAe,EAAE;EACxG,GAAI,MAAM,wBAAwB,KAAA,IAAY,CAAC,IAAI,EAAE,qBAAqB,MAAM,oBAA8B;EAC9G,GAAI,MAAM,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,MAAM,kBAA4B;EACxG,GAAI,MAAM,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,OAAiB;EACvE,GAAI,MAAM,wBAAwB,KAAA,IAAY,CAAC,IAAI,EAAE,qBAAqB,eAAe,MAAM,mBAAmB,EAAE;CACtH;AACF;AAEA,SAAS,kBAAkB,UAAyC;CAClE,MAAM,WAAW,cAAc;EAC7B,kBAAkB,SAAS;EAC3B,gBAAgB,SAAS;EACzB,eAAe,SAAS;CAC1B,CAAC;CACD,OAAOD,UAAc,gBAAgB,WAAW,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE,GAAG;AACzG;AAEA,SAAS,kBAAkB,UAA6B;CACtD,OAAOA,UAAc,mBAAmB,WAAW,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE,GAAG;AAC5G;AAEA,SAAS,gBAAgB,UAAmF;CAC1G,OAAO,OAAO,cAAc;EAAE,MAAM;EAAW,kBAAkB,SAAS;EAAkB,gBAAgB,SAAS;EAAgB,SAAS;CAAK,CAAC,CAAC;AACvJ;AAEA,SAAS,YAAY,MAAsB;CACzC,MAAM,QAAQ,OAAO,KAAK,MAAM,QAAQ;CACxC,IAAI,MAAM,SAAS,QAAQ,MAAM,MAAM,MAAM,IAAI,iBAAiB,kBAAkB,wCAAwC;CAC5H,OAAO;AACT;AAEA,SAAS,uBACP,OACA,WACA,YACA,0BAC4C;CAC5C,MAAM,WAAW,MAAM,IAAI,SAAS;CACpC,IAAI,CAAC,UAAU,OAAO,KAAA;CACtB,MAAM,oBAAoB,SAAS,cAC/B,WAAW,oBAAoB,IAAI,SAAS,WAAW,KAAK,CAAC,IAC7D,CAAC;CACL,MAAM,mBAAmB,2BACrB,kBAAkB,MAAM,YAAY,QAAQ,qBAAqB,yBAAyB,oBAC1F,QAAQ,sBAAsB,yBAAyB,cAAc,MACpE,kBAAkB,WAAW,IAAI,kBAAkB,KAAK,KAAA,KACzD,kBAAkB,WAAW,IAAI,kBAAkB,KAAK,KAAA;CAC5D,MAAM,gBAAgB,SAAS,yBAC3B,WAAW,iBAAiB,IAAI,SAAS,sBAAsB,IAC/D,KAAA;CACJ,MAAM,sBAAsB,gBACxB;EAAE,kBAAkB,cAAc;EAAkB,gBAAgB,cAAc;CAAe,IACjG,KAAA;CACJ,OAAO;EACL,MAAM,SAAS;EACf,YAAY,SAAS;EACrB,GAAI,mBAAmB;GACrB,iBAAiB;IAAE,kBAAkB,iBAAiB;IAAkB,gBAAgB,iBAAiB;GAAkB;GAC3H,qBAAqB,iBAAiB;EACxC,IAAI,CAAC;EACL,GAAI,SAAS,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,SAAS,kBAAkB;EACpG,GAAI,SAAS,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,SAAS,OAAO;EACnE,GAAI,sBAAsB,EAAE,oBAAoB,IAAI,CAAC;CACvD;AACF;AAEA,IAAa,qBAAb,MAAgC;CAQX;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAjBnB,gBAAuC,QAAQ,QAAQ;CACvD,8BAA+B,IAAI,IAAqC;CACxE;CACA,uCAAwC,IAAI,IAAyC;CACrF,4BAAoC;CAEpC,YACE,OACA,OACA,UACA,UACA,eACA,gBACA,gBACA,WACA,cACA,UAA2B,IAAI,wBAAwB,GACvD,MAAqC,KAAK,KAC1C,MACA;EAZiB,KAAA,QAAA;EACA,KAAA,QAAA;EACA,KAAA,WAAA;EACA,KAAA,WAAA;EACA,KAAA,gBAAA;EACA,KAAA,iBAAA;EACA,KAAA,iBAAA;EACA,KAAA,YAAA;EACA,KAAA,eAAA;EACA,KAAA,UAAA;EACA,KAAA,MAAA;EAGjB,KAAK,mBAAmB,IAAI,4BAA4B,IAAI;EAC5D,KAAK,MAAM,CAAC,KAAK,UAAU,KAAK,iBAAiB,QAAQ,GACvD,IAAI,CAAC,KAAK,YAAY,IAAI,GAAG,GAC3B,KAAK,YAAY,IAAI,KAAK,KAAK;CAGrC;CAEA,eAA2C;EACzC,OAAO,KAAK,wBAAwB,KAAK,gBAAgB,CAAC;CAC5D;CAEA,iBAA+C;EAC7C,OAAO,KAAK,kBAAkB,YAAY;GACxC,MAAM,eAA4C;IAChD,YAAY,KAAK,MAAM,WAAW;IAClC,yBAAS,IAAI,IAAI;IACjB,OAAO;GACT;GACA,MAAM,SAAS,MAAM,KAAK,gBAAgB;IAAE,cAAc;IAAM;GAAa,CAAC;GAC9E,MAAM,WAAW,wBAAwB,OAAO,YAAY,OAAO,SAAS,OAAO,OAAO;GAC1F,KAAK,yBAAyB,SAAS,QAAQ,YAAY;GAC3D,OAAO;EACT,CAAC;CACH;CAEA,cACE,MACA,gBACA,WAA8C,CAAC,GAC/C,UAAuC,CAAC,GACZ;EAC5B,OAAO,KAAK,kBAAkB,YAAY;GACxC,IAAI,KAAK,SAAS,qBAAqB,KAAK,MAAM,QAAQ,OAAO,QAAQ,YAAY,IAAI,SAAS,IAAI,KACpG,IAAI,IAAI,IAAI,CAAC,CAAC,SAAS,KAAK,QAC5B,MAAM,IAAI,iBAAiB,oBAAoB,oCAAoC;GAErF,IAAI,mBAAmB,KAAA,KAAa,CAAC,wBAAwB,KAAK,cAAc,GAC9E,MAAM,IAAI,iBAAiB,oBAAoB,oCAAoC;GAErF,MAAM,eAAe,IAAI,IAAI,IAAI;GACjC,MAAM,gCAAgB,IAAI,IAAoC;GAC9D,KAAK,MAAM,UAAU,UAAU;IAC7B,IAAI,CAAC,aAAa,IAAI,OAAO,GAAG,KAAK,cAAc,IAAI,OAAO,GAAG,KAC/D,CAAC,yBAAyB,OAAO,UAAU,KAAK,OAAO,aAAa,oBAAoB,OACxF,CAAC,wBAAwB,KAAK,OAAO,WAAW,KAChD,CAAC,yBAAyB,OAAO,mBAAmB,KAAK,OAAO,sBAAsB,OAAO,YAC7F,MAAM,IAAI,iBAAiB,oBAAoB,iCAAiC;IAElF,cAAc,IAAI,OAAO,KAAK,MAAM;GACtC;GACA,IAAI;GACJ,MAAM,eAAe,iBAAiB,KAAK,qBAAqB,IAAI,cAAc,IAAI,KAAA;GACtF,IAAI,cAAc;IAChB,MAAM,gBAAgB,KAAK,SAAS,QAAQ;KAC1C,MAAM,QAAQ,aAAa,QAAQ,IAAI,GAAG;KAC1C,OAAO,QAAQ,CAAC,KAAK,IAAI,CAAC;IAC5B,CAAC;IACD,MAAM,aAAa,IAAI,IAAI,cAAc,IAAI,mBAAmB,CAAC;IACjE,MAAM,cAAc,KAAK,QAAQ,QAAQ,CAAC,WAAW,IAAI,GAAG,CAAC;IAC7D,MAAM,aAAa,YAAY,SAAS,IACpC,MAAM,KAAK,gBAAgB,EAAE,cAAc,IAAI,IAAI,WAAW,EAAE,CAAC,IACjE,sBAAsB,aAAa,YAAY,CAAC,CAAC;IACrD,SAAS,sBAAsB,aAAa,YAAY,CAAC,GAAG,eAAe,GAAG,WAAW,OAAO,GAAG,WAAW,OAAO;GACvH,OACE,SAAS,MAAM,KAAK,gBAAgB;IAAE;IAAc,eAAe,QAAQ,kBAAkB;GAAK,CAAC;GAErG,MAAM,YAAY,OAAO,QAAQ,KAAK,UAAU,cAAc,OAAO,cAAc,IAAI,oBAAoB,KAAK,CAAC,CAAC,CAAC;GACnH,IAAI,OAAO,YAAY,KAAA,GACrB,OAAO,sBAAsB,OAAO,YAAY,WAAW,OAAO,SAAS,OAAO,OAAO;GAE3F,MAAM,gBAAgB,UAAU,KAAK,UAAU;IAC7C,IAAI,MAAM,oBAAoB,KAAA,GAAW,OAAO;IAChD,MAAM,EAAE,iBAAiB,GAAG,SAAS;IAErC,OAAO;GACT,CAAC;GACD,MAAM,gBAAgB,QAAQ,kBAAkB,OAAO,KAAK,oBAAoB,aAAa,IAAI,KAAA;GACjG,OAAO,sBAAsB,OAAO,YAAY,eAAe,OAAO,SAAS,aAAa;EAC9F,CAAC;CACH;CAEA,yBAAiC,QAAgB,UAA6C;EAC5F,IAAI,SAAS,QAAQ,SAAS,KAAK,SAAS,QAAQ,kCAAkC;EACtF,MAAM,WAAW,KAAK,qBAAqB,IAAI,MAAM;EACrD,IAAI,UAAU;GACZ,KAAK,6BAA6B,SAAS;GAC3C,KAAK,qBAAqB,OAAO,MAAM;EACzC;EACA,OAAO,KAAK,qBAAqB,QAAQ,oCACvC,KAAK,4BAA4B,SAAS,QAAQ,kCAAkC;GACpF,MAAM,SAAS,KAAK,qBAAqB,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC;GAC1D,IAAI,CAAC,QAAQ;GACb,KAAK,qBAAqB,OAAO,OAAO,EAAE;GAC1C,KAAK,6BAA6B,OAAO,EAAE,CAAC;EAC9C;EACA,KAAK,qBAAqB,IAAI,QAAQ,QAAQ;EAC9C,KAAK,6BAA6B,SAAS;CAC7C;CAEA,YACE,OACA,YACA,SAAS,8BACT,UAAmC,CAAC,GACH;EACjC,OAAO,KAAK,wBAAwB,KAAK,eAAe,OAAO,YAAY,QAAQ,OAAO,CAAC;CAC7F;CAEA,gBAAgB,OAAgB,UAAmC,CAAC,GAAS;EAC3E,MAAM,SAAS,0BAA0B,KAAK;EAC9C,IAAI,OAAO,eAAe,KAAK,MAAM,WAAW,KAAK,CAAC,QAAQ,mBAC5D,MAAM,IAAI,iBAAiB,iBAAiB,2CAA2C;EAEzF,MAAM,QAAQ,KAAK,MAAM,KAAK;EAC9B,KAAK,MAAM,SAAS,OAAO,SAAS;GAClC,IAAI,MAAM,SAAS,SAAS;IAC1B,MAAM,UAAU,MAAM,QAAQ,iBAAiB,MAAM,QAAQ;IAC7D,IAAI,CAAC,SAAS;IAEd,IADmB,oBAAoB,MAAM,SAAS,UAAU,QAAQ,QAC3D,MAAM,MAAM,MAAM,SAAS,kBAAkB,QAAQ,iBAAiB,CAAC,QAAQ,UAC1F,MAAM,IAAI,iBAAiB,qBAAqB,2DAA2D;IAE7G;GACF;GACA,IAAI,MAAM,UAAU;IAClB,MAAM,UAAU,MAAM,SAAS,MAAM;IACrC,IAAI,CAAC,SAAS;IACd,MAAM,aAAa,oBAAoB,MAAM,SAAS,UAAU,QAAQ,QAAQ;IAChF,IAAI,eAAe,MAAM,MAAM,SAAS,kBAAkB,QAAQ,iBAAiB,MAAM,SAAS,gBAAgB,QAAQ,cACxH,MAAM,IAAI,iBAAiB,qBAAqB,mDAAmD;IAErG,IAAI,aAAa,KAAK,MAAM,SAAS,kBAAkB,QAAQ,eAC7D,MAAM,IAAI,iBAAiB,oBAAoB,uDAAuD;IAExG;GACF;GACA,MAAM,UAAU,MAAM,QAAQ,iBAAiB,MAAM,QAAQ;GAC7D,IAAI,CAAC,WAAW,QAAQ,SAAS;GAEjC,IADmB,oBAAoB,MAAM,SAAS,UAAU,QAAQ,QAC3D,MAAM,MAAM,MAAM,SAAS,kBAAkB,QAAQ,iBAAiB,MAAM,SAAS,gBAAgB,QAAQ,cACxH,MAAM,IAAI,iBAAiB,qBAAqB,mDAAmD;EAEvG;CACF;CAEA,iBAA2B;EACzB,OAAO,KAAK,QAAQ,eAAe;CACrC;CAEA,MAAM,iBAAgC;EACpC,MAAM,WAAsB,CAAC;EAC7B,KAAK,MAAM,SAAS,KAAK,QAAQ,eAAe,GAC9C,IAAI;GACF,MAAM,SAAS,KAAK,QAAQ,WAAW,MAAM,OAAO;GACpD,IAAI,WAAW,KAAA,GAAW,MAAM,IAAI,iBAAiB,0BAA0B,0BAA0B;GAEzG,IADwB,0BAA0B,MAChC,CAAC,CAAC,WAAW,MAAM,cACnC,MAAM,IAAI,iBAAiB,2BAA2B,yBAAyB;GAEjF,MAAM,KAAK,wBAAwB,KAAK,eAAe,QAAQ,MAAM,YAAY,MAAM,QAAQ;IAC7F,aAAa,MAAM;IACnB,mBAAmB,MAAM;GAC3B,GAAG,KAAK,CAAC;EACX,SAAS,OAAO;GACd,SAAS,KAAK,KAAK;EACrB;EAEF,IAAI,SAAS,SAAS,GACpB,MAAM,IAAI,eAAe,UAAU,iDAAiD;CAExF;CAEA,yBAA+B;EAC7B,KAAK,QAAQ,uBAAuB;CACtC;CAEA,eAAqC;EACnC,OAAO,OAAO,OAAO,KAAK,MAAM,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,WAAW,cAAc,EAAE,UAAU,CAAC;CAC1G;CAEA,eAAe,UAAsC;EACnD,OAAO,KAAK,wBAAwB,KAAK,kBAAkB,QAAQ,CAAC;CACtE;CAEA,MAAc,yBACZ,aACA,WACA,YACA,mBACA,WACA,eACA,QACA,SACA,YACuC;EACvC,IAAI,CAAC,WAAW,QAAQ,WAAW,CAAC,QAAQ,iBAAiB,OAAO,KAAA;EACpE,MAAM,QAAQ,KAAK,YAAY,IAAI,sBAAsB,OAAO,SAAS,CAAC,CAAC;EAC3E,IAAI,CAAC,SAAS,MAAM,SAAS,kBAAkB,QAAQ,iBACrD,MAAM,SAAS,qBAAqB,QAAQ,oBAAoB,MAAM,SAAS,mBAAmB,QAAQ,kBAC1G,QAAQ,gBAAgB,qBAAqB,WAAW,oBACxD,QAAQ,gBAAgB,mBAAmB,WAAW,qBACtD,QAAQ,gBAAgB,mBAAmB,YAAY,mBAAmB,OAAO,MAAM,GAAG,OAAO,KAAA;EAEnG,MAAM,SAAS,MAAM,0BAA0B,aAAa,WAAW,aAAa;EACpF,IAAI,CAAC,UAAU,CAAC,OAAO,OAAO,OAAO,MAAM,UAAU,OAAO,OAAO,GAAG,MAAM,MAAM,UAAU,UAAU,IAAI,GAAG,OAAO,KAAA;EACpH,MAAM,iBAAiB,OAAO,OAAO,gBACjC,WAAW,iBAAiB,IAAI,OAAO,OAAO,OAAO,aAAa,CAAC,IACnE,KAAA;EACJ,MAAM,eAAe,iBACjB;GAAE,kBAAkB,eAAe;GAAkB,gBAAgB,eAAe;EAAe,IACnG,KAAA;EACJ,MAAM,sBAAsB,uBAC1B,KAAK,cACL,OAAO,SAAS,GAChB,YACA;GAAE,kBAAkB,WAAW;GAAkB,gBAAgB,WAAW;EAAkB,CAChG;EACA,MAAM,cAAc,yBAAyB;GAC3C,UAAU,OAAO,SAAS;GAC1B,QAAQ,OAAO;GACf,qBAAqB,OAAO;GAC5B,WAAW;GACX;GACA;EACF,CAAC;EACD,IAAI,CAAC,eAAe,gBAAgB,MAAM,aAAa,OAAO,KAAA;EAC9D,OAAO;GACL,UAAU;GACV,YAAY,MAAM;GAClB,aAAa,MAAM;GACnB,qBAAqB,MAAM;EAC7B;CACF;CAEA,MAAc,gBAAgB,UAAgC,CAAC,GAA+B;EAC5F,MAAM,EAAE,eAAe,OAAO,cAAc,eAAe,mBAAmB,UAAU;EACxF,MAAM,cAAc,KAAK,mBAAmB;EAC5C,MAAM,oBAAoB,KAAK,cAAc;EAC7C,IAAI,CAAC,mBAAmB,MAAM,IAAI,iBAAiB,yBAAyB,WAAW;EACvF,MAAM,YAAY,MAAM;EAExB,MAAM,aAAa,wBAAwB,KAAK,MAAM,KAAK,CAAC;EAC5D,MAAM,aAAa,KAAK,MAAM,WAAW;EACzC,MAAM,WAAW,KAAK,SAAS,KAAK;EACpC,MAAM,sCAAsB,IAAI,IAAuC;EACvE,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,MAAME,UAAkB,QAAQ,UAAU;GAChD,IAAI,CAAC,oBAAoB,IAAI,GAAG,GAAG,oBAAoB,IAAI,KAAK,OAAO;EACzE;EACA,MAAM,aAAa,kBAAkB,KAAK;EAC1C,MAAM,cAAc,IAAI,IAAI,kBAAkB,mBAAmB,IAAI,MAAM,CAAC;EAC5E,MAAM,YAAY,IAAI,KAAK,kBAAkB,oBAAoB,CAAC,EAAA,CAAG,IAAI,MAAM,CAAC;EAChF,MAAM,UAA8B,CAAC;EACrC,MAAM,UAAwD,CAAC;EAC/D,MAAM,mCAAmB,IAAI,IAAY;EACzC,MAAM,gCAAgB,IAAI,IAA2B;EACrD,MAAM,2BAA2B,IAAI,IAAI,OAAO,OAAO,WAAW,MAAM,QAAQ,CAAC,CAAC,KAAK,YAAY,QAAQ,cAAc,CAAC;EAC1H,MAAM,8BAAiC,IAAI,IAAI;EAC/C,MAAM,kCAAkB,IAAI,IAAkC;EAC9D,MAAM,0BACJ,WACA,SACA,YACA,oBACyB;GACzB,MAAM,MAAM,cAAc;IACxB,WAAW;KAAE,IAAI,OAAO,UAAU,EAAE;KAAG,MAAM,UAAU;KAAM,OAAO,UAAU;IAAM;IACpF,SAAS;KAAE,YAAYA,UAAkB,QAAQ,UAAU;KAAG,QAAQ,QAAQ;KAAQ,YAAY,MAAM,UAAU,QAAQ,UAAU;IAAE;IACtI;IACA;GACF,CAAC;GACD,MAAM,SAAS,gBAAgB,IAAI,GAAG;GACtC,IAAI,QAAQ,OAAO;GACnB,MAAM,aAAa,KAAK,oBAAoB,WAAW,SAAS,YAAY,iBAAiB,UAAU;GACvG,gBAAgB,IAAI,KAAK,UAAU;GACnC,OAAO;EACT;EAEA,KAAK,MAAM,aAAa,YAAY;GAClC,cAAc,IAAI,OAAO,UAAU,EAAE,GAAG,SAAS;GACjD,MAAM,UAAU,oBAAoB,IAAI,sBAAsB,SAAS,CAAC;GACxE,IAAI,CAAC,SAAS;GACd,MAAM,OAAO,KAAK,SAAS,IAAI,QAAQ,MAAM;GAC7C,IAAI,CAAC,QAAQ,CAAC,iBAAiB,KAAK,IAAI,GAAG;GAC3C,MAAM,aAAa,KAAK,MAAM,mBAAmB,KAAK,EAAE;GACxD,IAAI,CAAC,YAAY;GAEjB,KAAK,IAAI,WAAW,GAAG,WAAW,UAAU,WAAW,QAAQ,YAAY,GAAG;IAC5E,MAAM,YAAY,OAAO,UAAU,WAAW,SAAS;IACvD,IAAI,yBAAyB,IAAI,SAAS,GAAG;IAC7C,MAAM,iBAAiB,WAAW,iBAAiB,IAAI,SAAS;IAChE,IAAI,gBAAgB,SAAS;IAC7B,MAAM,WAAW,iBACb,oBAAoB,EAAE,UAAU,eAAe,CAAC,IAChD,cAAc,WAAW;KAAE,kBAAkB;KAAY,gBAAgB;IAAU,CAAC;IACxF,IAAI,gBAAgB,CAAC,aAAa,IAAI,QAAQ,GAAG;IACjD,MAAM,aAAa,uBAAuB,WAAW,SAAS,YAAY,gBAAgB,eAAe;IACzG,MAAM,WAAW,MAAM,YAAY,KAAKF,UAAc,SAAS,CAAC;IAChE,IAAI,CAAC,UAAU;IACf,IAAI,SAAS,iBAAiB,sBAC5B,MAAM,IAAI,iBAAiB,kBAAkB,oBAAoB;IAEnE,IAAI,cAAc;KAChB,MAAM,SAAS,MAAM,KAAK,yBACxB,aACA,WACA,YACA,UACAA,UAAc,SAAS,GACvB,UACA,UAAU,IAAI,SAAS,GACvB,gBACA,UACF;KACA,IAAI,QAAQ;MACV,QAAQ,KAAK,MAAM;MACnB,iBAAiB,IAAI,SAAS;MAC9B;KACF;IACF;IACA,MAAM,WAAW,MAAM,KAAK,mBAC1B,aACA,WACA,YACA,UACAA,UAAc,SAAS,GACvB,UACA,YAAY,IAAI,SAAS,GACzB,UAAU,IAAI,SAAS,GACvB,KAAA,GACA,YACA,WACF;IACA,IAAI,UAAU;KACZ,MAAM,EAAE,UAAU;KAClB,IAAI,gBAAgB,QAAQ,cAAc;MACxC,MAAM,MAAM,oBAAoB,KAAK;MACrC,MAAM,OAAO,kBAAkB,OAAO,mCAAmC,QAAQ,aAAa,KAAK;MACnG,IAAI,SAAS,KAAA,GAAW;OACtB,QAAQ,aAAa,QAAQ,IAAI,KAAK,KAAK;OAC3C,QAAQ,aAAa,SAAS;MAChC;KACF;KACA,QAAQ,KAAK,eACT;MACE,UAAU,MAAM;MAChB,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;MACrD,YAAY,SAAS;MACrB,aAAa,SAAS;MACtB,qBAAqB,SAAS;KAChC,IACA,KAAK;KACT,iBAAiB,IAAI,SAAS;IAChC,OAAO,QAAQ,KAAK;KAAE;KAAW,QAAQ;IAAyB,CAAC;GACrE;EACF;EAEA,MAAM,UAAU,WAAW;EAC3B,KAAK,MAAM,YAAY,OAAO,OAAO,QAAQ,OAAO,GAAG;GACrD,IACE,SAAS,SAAS,aAAa,yBAAyB,IAAI,SAAS,aAAa,GAClF;GACF,IAAI,gBAAgB,CAAC,aAAa,IAAI,oBAAoB,EAAE,SAAS,CAAC,CAAC,GAAG;GAC1E,IAAI,SAAS,SAAS;IACpB,QAAQ,KAAK,EAAE,SAAS,CAAC;IACzB,MAAM,eAAe,sBAAsB,SAAS,aAAa;IACjE,KAAK,YAAY,OAAO,YAAY;IACpC,KAAK,iBAAiB,OAAO,YAAY;IACzC;GACF;GACA,IAAI,iBAAiB,IAAI,SAAS,aAAa,GAAG;GAClD,MAAM,YAAgC;IACpC,GAAG;IACH,UAAU,KAAK,MAAM,aAAa,KAAK,IAAI,CAAC;IAC5C,eAAe,gBAAgB,QAAQ;IACvC,SAAS;GACX;GACA,KAAK,MAAM,QAAQ,UAAU;IAC3B,MAAM,QAAQ,iBAAiB,QAAQ,KAAK;GAC9C,CAAC;GACD,mBAAmB,YAAY,SAAS;GACxC,MAAM,eAAe,sBAAsB,SAAS,aAAa;GACjE,KAAK,YAAY,OAAO,YAAY;GACpC,KAAK,iBAAiB,OAAO,YAAY;GACzC,QAAQ,KAAK,EAAE,UAAU,UAAU,CAAC;EACtC;EAEA,KAAK,MAAM,WAAW,OAAO,OAAO,WAAW,MAAM,QAAQ,GAAG;GAC9D,IAAI,gBAAgB,CAAC,aAAa,IAAI,QAAQ,QAAQ,GAAG;GACzD,MAAM,YAAY,QAAQ,cAAc,cAAc,IAAI,QAAQ,WAAW,IAAI,KAAA;GACjF,IAAI,CAAC,WAAW;GAChB,MAAM,UAAU,oBAAoB,IAAI,sBAAsB,SAAS,CAAC;GACxE,MAAM,OAAO,UAAU,KAAK,SAAS,IAAI,QAAQ,MAAM,IAAI,KAAA;GAC3D,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,iBAAiB,KAAK,IAAI,GAAG;GACvD,MAAM,aAAa,KAAK,MAAM,mBAAmB,KAAK,EAAE;GACxD,IAAI,CAAC,YAAY;GAEjB,MAAM,aAAa,uBAAuB,WAAW,SAAS,YADrC,WAAW,yBAAyB,IAAI,QAAQ,cACgB,CAAC,EAAE,eAAe;GAC3G,MAAM,WAAW,MAAM,YAAY,KAAKA,UAAc,QAAQ,cAAc,CAAC;GAC7E,IAAI,CAAC,UAAU;GACf,MAAM,WAAW,MAAM,KAAK,mBAC1B,aACA,WACA,YACA,QAAQ,mBACRA,UAAc,QAAQ,cAAc,GACpC,UACA,MACA,OACA,SACA,YACA,WACF;GACA,IAAI,UAAU;IACZ,MAAM,EAAE,UAAU;IAClB,IAAI,gBAAgB,QAAQ,cAAc;KACxC,MAAM,MAAM,oBAAoB,KAAK;KACrC,MAAM,OAAO,kBAAkB,OAAO,mCAAmC,QAAQ,aAAa,KAAK;KACnG,IAAI,SAAS,KAAA,GAAW;MACtB,QAAQ,aAAa,QAAQ,IAAI,KAAK,KAAK;MAC3C,QAAQ,aAAa,SAAS;KAChC;IACF;IACA,QAAQ,KAAK,eACT;KACE,UAAU,MAAM;KAChB,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;KACrD,YAAY,SAAS;KACrB,aAAa,SAAS;KACtB,qBAAqB,SAAS;IAChC,IACA,KAAK;GACX,OAAO,QAAQ,KAAK;IAAE,WAAW,QAAQ;IAAgB,QAAQ;GAAiC,CAAC;EACrG;EAEA,MAAM,sBAAsB,oBAAoB,QAAQ,MAAM,WAAW,MAAM,SAAS,UAAU,KAAK,CAAC,IACpG,KAAK,oBAAoB,OAAO,IAChC,KAAA;EACJ,KAAK,iBAAiB,MAAM;EAC5B,OAAO,sBAAsB,YAAY,SAAS,SAAS,mBAAmB;CAChF;CAEA,oBAA4B,SAAkD;EAC5E,MAAM,yBAAS,IAAI,IAA+B;EAClD,KAAK,MAAM,SAAS,SAClB,KAAK,MAAM,UAAU,MAAM,WAAW,CAAC,GAAG;GACxC,MAAM,UAAU,OAAO,IAAI,OAAO,EAAE;GACpC,IAAI,YAAY,KAAA,GAAW,OAAO,IAAI,OAAO,IAAI,MAAM;QAClD,IAAI,QAAQ,WAAW,OAAO,UAAU,QAAQ,UAAU,OAAO,OACpE,MAAM,IAAI,iBAAiB,kBAAkB,+CAA+C;EAEhG;EAEF,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC;CAC5B;CAEA,MAAc,eACZ,OACA,YACA,QACA,SACA,eACiC;EACjC,MAAM,oBAAoB,0BAA0B,KAAK;EACzD,MAAM,cAAc,eAAe,eAAe,QAAQ,eAAe;EACzE,IAAI,gBAAgB,UAAU,kBAAkB,QAAQ,MAAM,UAAU,MAAM,UAAU,GACtF,MAAM,IAAI,iBAAiB,oBAAoB,qDAAqD;EAEtG,IAAI,eAAe,iBAAiB,KAAK,QAAQ,UAAU,QAAQ,kBAAkB,MAAM;EAC3F,IAAI,gBAAgB,CAAC,kBAAkB,QAAQ,MAAM,UAAU,MAAM,UAAU,MAC5E,aAAa,iBAAiB,kBAAkB,UAAU,aAAa,WAAW,SACnF,MAAM,IAAI,iBAAiB,2BAA2B,+BAA+B;EAEvF,IAAI,CAAC,cAAc,MAAM,KAAK,gBAAgB,EAAE,cAAc,KAAK,CAAC;EACpE,MAAM,SAAS,MAAM,KAAK,kBAAkB,iBAAiB;EAC7D,iBAAiB,iBAAiB,KAAK,QAAQ,UAAU,QAAQ,OAAO,MAAM;EAC9E,IAAI,iBAAiB,aAAa,iBAAiB,OAAO,UAAU,aAAa,WAAW,SAC1F,MAAM,IAAI,iBAAiB,2BAA2B,+BAA+B;EAEvF,MAAM,sBAAsB,cAAc,eAAe;EACzD,MAAM,oBAAoB,cAAc,qBAAqB,QAAQ,qBAAqB;EAC1F,MAAM,kBAAkB,KAAK,MAAM,WAAW;EAC9C,IAAI,OAAO,eAAe,mBAAmB,CAAC,mBAC5C,MAAM,IAAI,iBAAiB,iBAAiB,2CAA2C;EAEzF,KAAK,gBAAgB,QAAQ;GAAE,aAAa;GAAqB;EAAkB,CAAC;EACpF,MAAM,kBAAkB,cAAc,cAAc,WAAA,CAAY,QAAQ,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,GAAG,KAAK;EAC/H,MAAM,aAAa,OAAO,QAAQ,KAAK,UAAU,MAAM,YAAY,iBAAiB,MAAM,QAAQ,CAAC;EACnG,MAAM,UAAU,cAAc,WAAW,KAAK,QAAQ,gBACpD,QACA,gBACA,OAAO,QACP,YACA,QACA,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,GACjC,qBACA,iBACF;EACA,MAAM,SAAS,iBAAiB;EAChC,MAAM,wCAAwB,IAAI,IAAsC;EACxE,OAAO,WAAW,OAAO,QAAQ;EACjC,OAAO,YAAY,OAAO,QAAQ;EAClC,MAAM,kCAAkB,IAAI,IAAwD;EACpF,MAAM,oCAAoB,IAAI,IAAuB;EACrD,KAAK,MAAM,SAAS,OAAO,SACzB,IAAI,CAAC,MAAM,SAAS,WAAW,CAAC,MAAM,UAAU;GAC9C,MAAM,UAAU,KAAK,MAAM,KAAK,CAAC,CAAC,QAAQ,iBAAiB,MAAM,QAAQ;GACzE,MAAM,UAAU,WAAW,CAAC,QAAQ,WAAW,QAAQ,kBAAkB,MAAM,SAAS,gBACpFA,UAAc,QAAQ,aAAa,IACnC,kBAAkB,MAAM,QAAQ;GACpC,kBAAkB,IAAI,iBAAiB,MAAM,QAAQ,GAAG,OAAO;EACjE;EAEF,MAAM,uCAAuB,IAAI,IAAgD;EACjF,MAAM,oBAAoB,UAAgE;GACxF,MAAM,aAAa,MAAM;GACzB,IAAI,CAAC,YAAY,OAAO,QAAQ,QAAQ,KAAA,CAAS;GACjD,MAAM,eAAe,iBAAiB,WAAW,kBAAkB,WAAW,mBAAmB,WAAW,UAAU;GACtH,IAAI,aAAa,qBAAqB,IAAI,YAAY;GACtD,IAAI,CAAC,YAAY;IACf,aAAa,KAAK,gBAAgB,UAAU,CAAC,CAAC,OAAO,UAAmB;KACtE,IAAI,iBAAiB,oBAAoB,MAAM,SAAS,sBAAsB,OAAO,KAAA;KACrF,MAAM;IACR,CAAC;IACD,qBAAqB,IAAI,cAAc,UAAU;GACnD;GACA,OAAO;EACT;EAEA,IAAI;GACF,MAAM,uBAAuB,aAAqB,IAAe,aAA2B;IAC1F,MAAM,QAAQ,gBAAgB,IAAI,WAAW,KAAK,CAAC;IACnD,MAAM,KAAK;KAAE;KAAI;IAAS,CAAC;IAC3B,gBAAgB,IAAI,aAAa,KAAK;GACxC;GACA,MAAM,UAAU,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,MAAM,GAAG,MAAM;IACjD,IAAI,EAAE,YAAY,EAAE,UAAU,QAAQ,EAAE,YAAY,GAAA,CAAI,cAAc,EAAE,YAAY,EAAE;IACtF,IAAI,EAAE,WAAW,sBAAsB,EAAE,WAAW,mBAClD,QAAQ,EAAE,WAAW,qBAAqB,GAAA,CAAI,cAAc,EAAE,WAAW,qBAAqB,EAAE;IAElG,QAAQ,EAAE,qBAAqB,MAAM,EAAE,qBAAqB;GAC9D,CAAC;GAED,KAAK,MAAM,SAAS,SAAS;IAC3B,MAAM,MAAM,MAAM,YAAY,iBAAiB,MAAM,QAAQ;IAC7D,IAAI,MAAM,SAAS,SAAS;KAE1B,IAAI,MADkB,KAAK,eAAe,MAAM,QAAQ,GAC3C,OAAO,WAAW;UAC1B,OAAO,WAAW;KACvB;IACF;IACA,MAAM,iBAAiB,MAAM,iBAAiB,KAAK;IACnD,IAAI,CAAC,gBAAgB;KACnB,OAAO,WAAW;KAClB,OAAO,YAAY;KACnB;IACF;IAEA,MAAM,eAAe,KAAK,MAAM,KAAK;IACrC,MAAM,iBAAiB,MAAM,WAAW,aAAa,SAAS,MAAM,YAAY,KAAA;IAChF,IAAI,MAAM,YAAY,gBAAgB;KACpC,MAAM,aAAa,oBAAoB,MAAM,SAAS,UAAU,eAAe,QAAQ;KACvF,IAAI,aAAa,GAAG;MAClB,OAAO,WAAW;MAClB;KACF;KACA,IAAI,eAAe,GAAG;MACpB,IAAI,MAAM,SAAS,kBAAkB,eAAe,iBAAiB,MAAM,SAAS,gBAAgB,eAAe,aACjH,MAAM,IAAI,iBAAiB,qBAAqB,mDAAmD;MAErG,MAAM,YAAYA,UAAc,eAAe,cAAc;MAC7D,MAAM,WAAW,MAAM,KAAK,mBAAmB,CAAC,CAAC,KAAK,SAAS;MAC/D,IAAI,YAAYE,UAAkB,SAAS,OAAO,OAAO,EAAE,MAAMA,UAAkB,eAAe,IAAI,GAAG;OACvG,MAAM,eAAe,cAAc,SAAS;OAC5C,oBAAoB,eAAe,IAAI,WAAW,MAAM,qBAAqB,eAAe,iBAAiB;MAC/G;MACA,OAAO,WAAW;MAClB;KACF;KACA,IAAI,MAAM,SAAS,kBAAkB,eAAe,eAClD,MAAM,IAAI,iBAAiB,oBAAoB,uDAAuD;KAExG,MAAM,KAAK,sBAAsB,OAAO,gBAAgB,cAAc;KACtE,OAAO,WAAW;KAClB,oBAAoB,eAAe,IAAIF,UAAc,eAAe,cAAc,GAAG,MAAM,qBAAqB,CAAC;KACjH;IACF;IACA,MAAM,UAAU,MAAM,WAAW,KAAA,IAAY,aAAa,QAAQ,iBAAiB,MAAM,QAAQ;IACjG,IAAI,SAAS;KACX,MAAM,aAAa,oBAAoB,MAAM,SAAS,UAAU,QAAQ,QAAQ;KAChF,IAAI,aAAa,GAAG;MAClB,OAAO,WAAW;MAClB;KACF;KACA,IAAI,eAAe,GAAG;MACpB,IAAI,QAAQ,WAAW,MAAM,SAAS,kBAAkB,QAAQ,iBAAiB,MAAM,SAAS,gBAAgB,QAAQ,aACtH,MAAM,IAAI,iBAAiB,qBAAqB,mDAAmD;MAErG,MAAM,YAAYA,UAAc,QAAQ,aAAa;MACrD,MAAM,WAAW,MAAM,KAAK,mBAAmB,CAAC,CAAC,KAAK,SAAS;MAC/D,IAAI,YAAYE,UAAkB,SAAS,OAAO,OAAO,EAAE,MAAMA,UAAkB,eAAe,IAAI,GAAG;OACvG,MAAM,eAAe,cAAc,SAAS;OAC5C,oBAAoB,eAAe,IAAI,WAAW,MAAM,qBAAqB,CAAC;MAChF;MACA,OAAO,WAAW;MAClB;KACF;KACA,IAAI,CAAC,QAAQ,WAAW,MAAM,SAAS,kBAAkB,QAAQ,iBAAkB,MAAM,KAAK,mBAAmB,CAAC,CAAC,KAAKF,UAAc,QAAQ,aAAa,CAAC,GAAI;MAC9J,MAAM,KAAK,oBAAoB,OAAO,SAAS,gBAAgB,gBAAgB,mBAAmB;MAClG,OAAO,WAAW;MAClB,oBAAoB,eAAe,IAAIA,UAAc,QAAQ,aAAa,GAAG,MAAM,qBAAqB,CAAC;MACzG;KACF;IACF;IAEA,IAAI,gBAAgB,KAAK,QAAQ,aAAa,SAAS,GAAG;IAC1D,IAAI;IACJ,IAAI,kBAAkB,KAAA,GAAW;KAC/B,IAAI;MACF,WAAW,MAAM,KAAK,aAAa,OAAO,gBAAgB,mBAAmB,gBAAgB,qBAAqB,qBAAqB;KACzI,SAAS,OAAO;MACd,IAAI,iBAAiB,oBAAoB,MAAM,SAAS,sBAAsB;OAC5E,OAAO,WAAW;OAClB,OAAO,YAAY;OACnB;MACF;MACA,MAAM;KACR;KACA,KAAK,QAAQ,cAAc,SAAS,KAAK,QAAQ;KACjD,gBAAgB;IAClB;IACA,WAAW,KAAK,iBAAiB,aAAa;IAE9C,IAAI,WAAW,CAAC,QAAQ,WAAW,QAAQ,kBAAkB,SAAS,gBAChE;SAAA,MAAM,KAAK,eAAe,OAAO,GAAG,OAAO,YAAY;IAAA;IAG7D,MAAM,UAAW,MAAM,KAAK,mBAAmB,CAAC,CAAC,KAAK,SAAS,cAAc,MAAO,KAAA;IACpF,MAAM,KAAK,cAAc,QAAQ;IACjC,IAAI,SAAS,UAAU,OAAO,YAAY;SACrC,IAAI,SAAS,OAAO,WAAW;SAC/B,OAAO,WAAW;IAEvB,oBAAoB,SAAS,aAAa,SAAS,gBAAgB,SAAS,iBAAiB;GAC/F;GAEA,MAAM,KAAK,uBAAuB,eAAe;GACjD,KAAK,QAAQ,SAAS,OAAO;GAC7B,KAAK,iBAAiB,MAAM;GAC5B,OAAO;EACT,SAAS,OAAO;GACd,IAAI,iBAAiB,kBAAkB,MAAM;GAC7C,MAAM,IAAI,iBAAiB,wBAAwB,YAAY,KAAK;EACtE;CACF;CAEA,MAAc,kBAAkB,QAAuD;EACrF,IAAI,CAAC,OAAO,QAAQ,MAAM,UAAU,MAAM,UAAU,GAAG,OAAO;EAC9D,MAAM,cAAc,KAAK,mBAAmB;EAC5C,MAAM,QAAQ,KAAK,MAAM,KAAK;EAC9B,MAAM,UAA8B,CAAC;EACrC,KAAK,MAAM,SAAS,OAAO,SAAS;GAClC,MAAM,QAAQ,MAAM;GACpB,IAAI,CAAC,OAAO;IACV,QAAQ,KAAK,KAAK;IAClB;GACF;GACA,MAAM,UAAU,MAAM,QAAQ,iBAAiB,MAAM,QAAQ;GAC7D,IAAI,CAAC,WAAW,QAAQ,SAAS,MAAM,IAAI,iBAAiB,wBAAwB,qCAAqC;GACzH,MAAM,WAAW,MAAM,YAAY,KAAKA,UAAc,QAAQ,aAAa,CAAC;GAC5E,IAAI,CAAC,UAAU,MAAM,IAAI,iBAAiB,wBAAwB,qCAAqC;GACvG,MAAM,SAAS,MAAM,KAAK,kBAAkB,aAAaA,UAAc,QAAQ,aAAa,GAAG,QAAQ;GACvG,IAAI,OAAO,OAAO,WAAW,MAAM,kBACjC,OAAO,wBAAwB,MAAM,2BACrC,uBAAuB,OAAO,MAAM,MAAM,MAAM,iBAChD,MAAM,IAAI,iBAAiB,wBAAwB,2CAA2C;GAEhG,MAAM,SAAS,CAAC,GAAG,OAAO,QAAQ,GAAI,MAAM,UAAU,CAAC,CAAE;GACzD,IAAI,OAAO,WAAW,MAAM,kBAAkB,uBAAuB,MAAM,MAAM,MAAM,iBACrF,MAAM,IAAI,iBAAiB,oBAAoB,4CAA4C;GAE7F,MAAM,YAA8B;IAAE,GAAG;IAAO;GAAO;GACvD,OAAO,UAAU;GACjB,QAAQ,KAAK,SAAS;EACxB;EACA,OAAO,0BAA0B,sBAAsB,OAAO,YAAY,SAAS,OAAO,OAAO,CAAC;CACpG;CAEA,MAAc,aACZ,OACA,YACA,mBACA,WACA,aACA,uBAC8B;EAC9B,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,UAAU,CAAC,MAAM,aAAa,CAAC,MAAM,SAC/D,MAAM,IAAI,iBAAiB,oBAAoB,oCAAoC;EAErF,MAAM,YAAY,MAAM,WAAW,kBAAkB,MAAM,QAAQ,IAAI,kBAAkB,MAAM,QAAQ;EACvG,MAAM,eAAe,MAAM;EAC3B,MAAM,2BAA2B,EAAE,GAAG,aAAa;EACnD,OAAO,yBAAyB;EAChC,OAAO,yBAAyB;EAChC,OAAO,yBAAyB;EAChC,MAAM,iBAAiB,MAAM,eACzB,kBAAkB,IAAI,cAAc,WAAW,MAAM,YAAY,CAAC,KAAK,KAAK,wBAAwB,MAAM,YAAY,IACtH,KAAA,MAAc,aAAa;EAC/B,MAAM,SAAwB;GAC5B,GAAG;GACH,IAAI;GACJ,KAAK,UAAU;GACf,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;EAC3C;EACA,MAAM,sBAAsB,MAAM,uBAAuB;EACzD,MAAM,cAAc,KAAK,mBAAmB;EAC5C,IAAI,MAAM,YAAY,KAAK,SAAS,GAAG;GACrC,MAAM,SAAS,MAAM,YAAY,KAAK,WAAW,MAAM;GACvD,IAAI;IACF,IAAI,cAAc,OAAO,MAAM,MAAM,cAAc,MAAM,KAAK,OAAO,wBAAwB,qBAC3F,MAAM,IAAI,iBAAiB,uBAAuB,8BAA8B;GAEpF,UAAU;IACR,MAAM,OAAO,MAAM;GACrB;EACF;EACA,MAAM,YAAY,MAAM,KAAK,cAAc,MAAM,SAAS,WAAW,qBAAqB;EAE1F,MAAM,kBAAkB,qBAAqB,QAD9B,KAAK,cAAc,MAAM,QAAQ,MAAM,SAAS,WAAW,WAAW,OAAO,MAAM,OAAO,EAAE,CACtD,CAAM;EAC3D,iBAAiB,WAAW,iBAAiB,CAAC;EAC9C,MAAM,yBAAyB,MAAM,qBAAqB,kBACtD,KAAK,0BAA0B,MAAM,oBAAoB,iBAAiB,MAAM,oBAAoB,mBAAmB,IACvH,KAAA;EACJ,MAAM,sBAA8D,MAAM,sBACtE;GACE;GACA,GAAI,yBAAyB,EAAE,aAAa,uBAAuB,IAAI,CAAC;GACxE,GAAI,MAAM,oBAAoB,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,MAAM,oBAAoB,kBAAkB;GACtI,GAAI,MAAM,oBAAoB,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,oBAAoB,OAAO;GACrG,MAAM,MAAM,oBAAoB;GAChC,YAAY,MAAM,oBAAoB;GACtC,GAAI,gBAAgB,EAAE,wBAAwB,cAAc,IAAI,CAAC;EACnE,IACA,KAAA;EACJ,OAAO;GACL,UAAU,MAAM;GAChB,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;GACrD,gBAAgB;GAChB;GACA;GACA,QAAQ,CAAC,GAAG,eAAe;GAC3B,aAAa,UAAU;GACvB,eAAe,UAAU;GACzB,WAAW,MAAM;GACjB,mBAAmB,MAAM,qBAAqB;GAC9C,UAAU,QAAQ,MAAM,YAAY,MAAM,QAAQ;GAClD,QAAQ,QAAQ,MAAM,UAAU,CAAC,MAAM,YAAY,CAAC,MAAM,QAAQ;GAClE;GACA;GACA,GAAI,sBAAsB,EAAE,oBAAoB,IAAI,CAAC;EACvD;CACF;CAEA,MAAc,gBAAgB,YAA0D;EACtF,MAAM,oBAAoB,KAAK,cAAc;EAC7C,IAAI,CAAC,mBAAmB,MAAM,IAAI,iBAAiB,yBAAyB,WAAW;EACvF,MAAM,MAAM,iBAAiB,WAAW,kBAAkB,WAAW,mBAAmB,WAAW,UAAU;EAC7G,MAAM,qBAAqB,MAAM,KAAK,MAAM,wBAAwB,WAAW,YAAY,OAAO,iBAAiB;GACjH,MAAM,OAAO,KAAK,SAAS,IAAI,YAAY;GAC3C,IAAI,CAAC,QAAQ,CAAC,iBAAiB,KAAK,IAAI,GAAG,OAAO,KAAA;GAClD,MAAM,SAAS,KAAK,MAAM,KAAK,CAAC,CAAC,WAAW;GAC5C,MAAM,mBAAmB,SAAS,oBAAoB,WAAW,UAAU,OAAO,QAAQ,IAAI;GAC9F,IAAI,UAAU,qBAAqB,KAAK,OAAO,kBAAkB,WAAW,eAC1E,MAAM,IAAI,iBAAiB,sBAAsB,qDAAqD;GAExG,MAAM,cAAc,UAAU,mBAAmB,IAAI,OAAO,QAAQ,WAAW;GAC/E,IAAI,UAAU,KAAK,SAAS,KAAK,CAAC,CAAC,MAAM,SACvC,KAAK,WAAW,gBAAgB,MAAM,UAAU,KAAK,UAAU,MAAM,WAAW,UAClF;GACA,IAAI,YAAY,SAAS,kBAAkB,IAAI,OAAO,gBAAgB,IAAI,KAAA;GAC1E,IAAI,CAAC,aAAa,SAChB,YAAY,kBAAkB,KAAK,CAAC,CAAC,MAAM,SAASE,UAAkB,KAAK,IAAI,MAAMA,UAAkB,QAAS,UAAU,CAAC;GAE7H,IAAI,CAAC,WAAW;IACd,MAAM,aAAa,QAAQ,aAAa,SAAS,cAC/C,KAAK,SAAS,WAAW,cAAc,QAAQ,WAAW,QAAQ,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE,GAAG;IAC9G,UAAU,YAAY;KAAE,WAAW;KAAM,MAAM;IAAM,CAAC;IACtD,YAAY,MAAM,kBAAkB,OAAO,YAAY,WAAW;GACpE;GACA,IAAI,UAAU,UAAU,aAAa,MAAM,UAAU,SAAS,WAAW;GAEzE,IAAI,gBAAgB,WAAW,KAAK,SAAS,KAAK,CAAC,CAAC,MAAM,SACxDA,UAAkB,KAAK,UAAU,MAAMA,UAAkB,UAAW,IAAI,CAC1E;GACA,IAAI,CAAC,iBAAiB,cAAc,WAAW,gBAAgB,MAAM,UAAU,cAAc,UAAU,MAAM,WAAW,YAAY;IAClI,gBAAgB;KACd,YAAY,UAAW;KACvB,QAAQ;KACR,YAAY,WAAW;KACvB,aAAa,UAAW;IAC1B;IACA,KAAK,SAAS,IAAI,aAAa;GACjC;GACA,MAAM,sBAAsB,CAAC,UAAU,OAAO,qBAAqB,UAAW,MAC5E,OAAO,cAAc,UAAW,QAAQ,OAAO,gBAAgB;GACjE,IAAI,CAAC,UAAU,mBAAmB,KAAK,qBAAqB;IAC1D,MAAM,UAAgC;KACpC,GAAG;KACH,OAAO;KACP,GAAI,UAAU,mBAAmB,IAAI;MAAE,UAAU,OAAO;MAAU,eAAe,OAAO;KAAc,IAAI,CAAC;KAC3G,kBAAkB,UAAW;KAC7B,WAAW,UAAW;KACtB,aAAa;IACf;IACA,KAAK,MAAM,QAAQ,UAAU;KAAE,MAAM,WAAW,OAAO;IAAQ,CAAC;GAClE;GACA,OAAO;EACT,CAAC;EACD,IAAI,CAAC,oBAAoB,MAAM,IAAI,iBAAiB,sBAAsB,iBAAiB;EAC3F,OAAO;CACT;CAEA,MAAc,cACZ,SACA,WACA,uBACgD;EAChD,MAAM,cAAc,QAAQ,MAAM,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,MAAM,IAC1F,KAAK,eAAe,IACpB,KAAA;EACJ,MAAM,SAAS,QAAQ,MAAM,WAAW,OAAO,SAAS,WAAW,CAAC,OAAO,WAAW,IAAI,KAAK,UAAU,IAAI,KAAA;EAC7G,IAAI,QAAQ,MAAM,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,MAAM,KAAK,CAAC,aAClF,MAAM,IAAI,iBAAiB,2BAA2B,gBAAgB;EAExE,IAAI,QAAQ,MAAM,WAAW,OAAO,SAAS,WAAW,CAAC,OAAO,WAAW,KAAK,CAAC,QAC/E,MAAM,IAAI,iBAAiB,8BAA8B,wCAAwC;EAEnG,MAAM,yBAAS,IAAI,IAAsC;EACzD,KAAK,MAAM,UAAU,SAAS;GAC5B,IAAI,OAAO,SAAS,WAAW,OAAO,aAAa;GACnD,IAAI,OAAO,SAAS,SAAS;IAC3B,MAAM,SAAS,uBAAuB,IAAI,OAAO,EAAE;IACnD,IAAI,QAAQ;KAAE,OAAO,IAAI,OAAO,IAAI,MAAM;KAAG;IAAS;GACxD;GACA,MAAM,OAAO,YAAY,OAAO,IAAI;GACpC,IAAI,KAAK,eAAe,OAAO,SAAS,OAAO,IAAI,MAAM,OAAO,QAC9D,MAAM,IAAI,iBAAiB,oBAAoB,yCAAyC;GAE1F,IAAI,OAAO,SAAS,SAAS;IAC3B,MAAM,MAAM,MAAM,YAAa,UAAU;KACvC;KACA,WAAW,OAAO,IAAI;KACtB,GAAI,OAAO,IAAI,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,OAAO,IAAI,KAAK;IACnE,CAAC;IACD,OAAO,IAAI,OAAO,IAAI,GAAG;IACzB,uBAAuB,IAAI,OAAO,IAAI,GAAG;GAC3C,OAAO,IAAI,OAAO,SAAS,QAAQ;IACjC,MAAM,MAAM,MAAM,YAAa,eAAe;KAC5C,MAAM,SAAS,IAAI;KACnB,MAAM,OAAO,IAAI;IACnB,CAAC;IACD,OAAO,IAAI,OAAO,IAAI,GAAG;IACzB,uBAAuB,IAAI,OAAO,IAAI,GAAG;GAC3C,OAAO;IACL,MAAM,MAAM,MAAM,kBAAkB,QAAS;KAC3C,OAAO,EAAE,UAAU;KACnB,QAAQ,OAAO,UAAU;KACzB,eAAe,OAAO,UAAU;KAChC,YAAY,OAAO;KACnB,OAAO,OAAO;KACd,QAAQ,OAAO;KACf;IACF,CAAC;IACD,OAAO,IAAI,OAAO,IAAI,GAAG;GAC3B;EACF;EACA,OAAO;CACT;CAEA,cACE,QACA,SACA,cACA,WACA,iBACgB;EAChB,MAAM,2CAA2B,IAAI,IAAwF;EAC7H,KAAK,MAAM,UAAU,SAAS;GAC5B,IAAI,OAAO,SAAS,SAAS;GAC7B,IAAI,OAAO,aAAa;IACtB,yBAAyB,IAAI,OAAO,UAAU,IAAI,SAAS,EAAE,QAAQ,OAAO,UAAU,CAAC;IACvF;GACF;GACA,MAAM,SAAS,aAAa,IAAI,OAAO,EAAE;GACzC,IAAI,CAAC,UAAU,EAAE,aAAa,SAAS,MAAM,IAAI,iBAAiB,2BAA2B,wBAAwB;GACrH,yBAAyB,IAAI,OAAO,UAAU,IAAI,SAAS;IAAE,QAAQ,OAAO;IAAW;GAAO,CAAC;EACjG;EAEA,MAAM,WAAW,UAA4B;GAC3C,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,IAAI,OAAO;GAClD,IAAI,CAACD,WAAS,KAAK,GAAG,OAAO;GAC7B,IAAI,MAAM,SAAS,WAAW,WAAW,MAAM,UAAU,GAAG;IAC1D,MAAM,SAAS,aAAa,IAAI,cAAc,SAAS,MAAM,UAAU,CAAC;IACxE,IAAI,CAAC,UAAU,EAAE,eAAe,SAAS,MAAM,IAAI,iBAAiB,gCAAgC,WAAW;IAC/G,OAAO;KAAE,GAAG;KAAO,YAAY;IAAO;GACxC;GACA,IAAI,MAAM,SAAS,UAAU,UAAU,MAAM,UAAU,GAAG;IACxD,MAAM,SAAS,aAAa,IAAI,cAAc,QAAQ,MAAM,UAAU,CAAC;IACvE,IAAI,CAAC,UAAU,EAAE,UAAU,SAAS,MAAM,IAAI,iBAAiB,gCAAgC,WAAW;IAC1G,OAAO;KAAE,GAAG;KAAO,YAAY;IAAO;GACxC;GACA,IAAI,MAAM,SAAS,4CAA4CA,WAAS,MAAM,IAAI,KAAK,MAAM,KAAK,cAAc,iBAE9G,OAAO;IAAE,GAAG;IAAO,MAAM;KAAE,GAAG,MAAM;KAAM;IAAU;GAAE;GAExD,MAAM,SAAkC,CAAC;GACzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAC7C,IAAI,QAAQ,2BAA2BA,WAAS,KAAK,KAAK,MAAM,QAAQ,MAAM,UAAU,GAAG;IACzF,MAAM,qBAAqB,MAAM,WAAW,QAAQ,UAAU;KAC5D,IAAI,CAACA,WAAS,KAAK,KAAK,CAACA,WAAS,MAAM,KAAK,KAAK,CAACA,WAAS,MAAM,GAAG,GAAG,OAAO;KAC/E,MAAM,YAAY;KAElB,OADe,yBAAyB,IAAI,UAAU,IAAI,OAC9C,CAAC,EAAE,WAAW,KAAA;IAC5B,CAAC;IACD,IAAI,mBAAmB,WAAW,GAAG;IACrC,OAAO,OAAO;KACZ,SAAS,MAAM;KACf,YAAY,mBAAmB,KAAK,UAAU;MAC5C,MAAM,YAAY;MAClB,MAAM,SAAS,yBAAyB,IAAI,UAAU,IAAI,OAAO;MACjE,IAAI,CAAC,QAAQ,QAAQ,MAAM,IAAI,iBAAiB,2BAA2B,wBAAwB;MACnG,OAAO;OAAE,GAAG;OAAW,OAAO,EAAE,UAAU;OAAG,KAAK,OAAO;MAAO;KAClE,CAAC;IACH;GACF,OAAO,IAAI,QAAQ,UAAU,OAAO,UAAU,UAAU;IACtD,IAAI,OAAO;IACX,KAAK,MAAM,EAAE,QAAQ,YAAY,yBAAyB,OAAO,GAAG;KAClE,IAAI,CAAC,QAAQ;KACb,OAAO,KAAK,WACV,oCAAoC,OAAO,IAAI,QAAQ,IAAI,OAAO,IAAI,iBACtE,oCAAoC,OAAO,QAAQ,IAAI,OAAO,eAChE;IACF;IACA,OAAO,OAAO;GAChB,OACE,OAAO,OAAO,QAAQ,KAAK;GAG/B,OAAO;EACT;EACA,OAAO,OAAO,KAAK,UAAU,qBAAqB,QAAQ,gBAAgB,KAAK,CAAC,CAAiB,CAAC;CACpG;CAEA,iBAAyB,OAAqC;EAC5D,IACE,CAACA,WAAS,KAAK,KAAK,CAACA,WAAS,MAAM,QAAQ,KAAK,MAAM,SAAS,SAAS,aACzE,OAAO,MAAM,mBAAmB,YAAY,CAACA,WAAS,MAAM,MAAM,KAAK,MAAM,OAAO,OAAO,MAAM,kBACjG,OAAO,MAAM,gBAAgB,YAAY,OAAO,MAAM,kBAAkB,YACxE,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,OAAO,MAAM,sBAAsB,YACnE,OAAO,MAAM,aAAa,aAAa,OAAO,MAAM,WAAW,aAAa,OAAO,MAAM,eAAe,YACvG,MAAM,gBAAgB,UAAU,MAAM,gBAAgB,WACvD,MAAM,IAAI,iBAAiB,mBAAmB,oCAAoC;EACpF,MAAM,SAAS,MAAM;EACrB,IAAI,OAAO,YAAA,GAAoC,MAAM,IAAI,iBAAiB,kBAAkB,wCAAwC;EACpI,MAAM,SAAS,qBAAqB,QAAQ,gBAAgB,MAAM,MAAM,CAAmB;EAC3F,iBAAiB,OAAO,IAAI,QAAQ,CAAC;EACrC,IACE,CAAC,OAAO,cAAc,MAAM,iBAAiB,KAAK,MAAM,oBAAoB,KAC5E,OAAO,MAAM,wBAAwB,YAAY,CAAC,OAAO,cAAc,MAAM,mBAAmB,KAAK,MAAM,sBAAsB,KACjI,CAACA,WAAS,MAAM,SAAS,GACzB,MAAM,IAAI,iBAAiB,mBAAmB,sCAAsC;EACtF,OAAO;GACL,UAAU,MAAM;GAChB,GAAI,OAAO,MAAM,aAAa,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;GACzE,gBAAgBD,UAAc,MAAM,cAAc;GAClD;GACA,qBAAqB,MAAM;GAC3B,QAAQ,CAAC,GAAG,MAAM;GAClB,aAAa,MAAM;GACnB,eAAe,MAAM;GACrB,WAAW,MAAM;GACjB,mBAAmB,MAAM;GACzB,UAAU,MAAM;GAChB,QAAQ,MAAM;GACd,YAAY,MAAM;GAClB,aAAa,MAAM;GACnB,GAAIC,WAAS,MAAM,mBAAmB,IAAI,EAAE,qBAAqB,MAAM,oBAA6D,IAAI,CAAC;EAC3I;CACF;CAEA,MAAc,cAAc,UAAiD;EAC3E,MAAM,YAAY,SAAS;EAC3B,MAAM,UAAU,MAAM,KAAK,aAAa,QAAQ;EAEhD,IAAI,SAAS,qBAAqB,KAAK,aAAa,QAAQ,SAAS,mBAAmB;EACxF,MAAM,WAAW,KAAK,cAAc;EACpC,MAAM,YAAY,UAAU,IAAI,SAAS,WAAW;EACpD,IAAI,CAAC,YAAY,CAAC,aAAaC,UAAkB,UAAU,IAAI,MAAMA,UAAkB,SAAS,aAAa,GAC3G,MAAM,IAAI,iBAAiB,sBAAsB,sBAAsB;EAEzE,MAAM,UAAU,cAAc,SAAS;EACvC,IAAI,SAAS,UAAU,MAAM,SAAS,eAAe,WAAW,EAAE,cAAc,KAAK,CAAC;OACjF,MAAM,SAAS,iBAAiB,SAAS;EAC9C,IAAI,SAAS,UAAU,CAAC,SAAS,UAAU,MAAM,SAAS,aAAa,SAAS;OAC3E,MAAM,SAAS,eAAe,SAAS;EAE5C,KAAK,MAAM,gBAAgB,SAAS,SAAS,UAAU,KAAK,IAAI,CAAC;EACjE,MAAM,UAAU,KAAK,SAAS,KAAK,CAAC,CAAC,MAAM,SAASA,UAAkB,KAAK,UAAU,MAAMA,UAAkB,SAAS,aAAa,CAAC;EACpI,IAAI,CAAC,SAAS,MAAM,IAAI,iBAAiB,sBAAsB,qBAAqB;EACpF,MAAM,iBAAqC;GACzC,GAAG,SAAS;GACZ,eAAe,OAAO,SAAS;GAC/B,aAAa,SAAS;GACtB,YAAY,SAAS;GACrB,aAAa,SAAS,SAAS,eAAe,mBAAmB,SAAS,WAAW,SAAS,mBAAmB,SAAS,UAAU,SAAS,MAAM;GACnJ,iBAAiB;IACf,kBAAkB,SAAS,UAAU;IACrC,gBAAgB,SAAS,UAAU;GACrC;GACA,SAAS;GACT,gBAAgB;EAClB;EACA,MAAM,MAAM,iBAAiB,SAAS,QAAQ;EAC9C,KAAK,MAAM,QAAQ,UAAU;GAC3B,MAAM,aAAa,iBACjB,SAAS,UAAU,kBACnB,SAAS,UAAU,mBACnB,SAAS,UAAU,UACrB;GACA,MAAM,WAAW,cAAc;IAC7B,GAAG,SAAS;IACZ,kBAAkB,SAAS;IAC3B,WAAW,SAAS;IACpB,aAAa,QAAQ;GACvB;GACA,IAAI,SAAS,UACX,MAAM,SAAS,SAAS,YAAY;IAClC,UAAU,SAAS;IACnB,kBAAkB,SAAS,SAAS;IACpC,iBAAiB,SAAS,SAAS;IACnC,gBAAgB,OAAO,SAAS;IAChC,UAAU,SAAS,SAAS;IAC5B,eAAe,SAAS,SAAS;IACjC,aAAa,SAAS,SAAS,eAAe,mBAAmB,SAAS,WAAW,SAAS,mBAAmB,MAAM,KAAK;IAC5H,mBAAmB,SAAS;IAC5B,aAAa,SAAS;IACtB,iBAAiB;KACf,kBAAkB,SAAS,UAAU;KACrC,gBAAgB,SAAS,UAAU;IACrC;IACA,YAAY,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY;GAC/C;QAEA,MAAM,QAAQ,OAAO;EAEzB,CAAC;EACD,OAAO;CACT;CAEA,MAAc,oBACZ,OACA,SACA,YACA,WACA,aACe;EACf,MAAM,aAAa,MAAM;EACzB,MAAM,cAAc,MAAM,SAAS;EACnC,IAAI,CAAC,cAAc,CAAC,aAAa,MAAM,IAAI,iBAAiB,oBAAoB,mCAAmC;EACnH,MAAM,WAAW,KAAK,cAAc;EACpC,IAAI,CAAC,UAAU,MAAM,IAAI,iBAAiB,yBAAyB,WAAW;EAC9E,MAAM,YAAYF,UAAc,QAAQ,aAAa;EACrD,MAAM,WAAW,MAAM,KAAK,mBAAmB,CAAC,CAAC,KAAK,SAAS;EAC/D,IAAI,CAAC,YAAYE,UAAkB,SAAS,OAAO,OAAO,EAAE,MAAMA,UAAkB,UAAU,IAAI,GAChG,MAAM,IAAI,iBAAiB,8BAA8B,sCAAsC;EAEjG,MAAM,UAAU,cAAc,SAAS;EACvC,IAAI,MAAM,UAAU,MAAM,SAAS,eAAe,WAAW,EAAE,cAAc,KAAK,CAAC;OAC9E,MAAM,SAAS,iBAAiB,SAAS;EAC9C,IAAI,MAAM,UAAU,CAAC,MAAM,UAAU,MAAM,SAAS,aAAa,SAAS;OACrE,MAAM,SAAS,eAAe,SAAS;EAC5C,IAAI,MAAM,qBAAqB;GAC7B,MAAM,yBAAyB,MAAM,eAAe,KAAK,wBAAwB,MAAM,YAAY,IAAI,KAAA;GACvG,MAAM,yBAAyB,MAAM,oBAAoB,kBACrD,KAAK,0BAA0B,MAAM,oBAAoB,iBAAiB,MAAM,oBAAoB,mBAAmB,IACvH,KAAA;GACJ,MAAM,WAAuC;IAC3C;IACA,GAAI,yBAAyB,EAAE,aAAa,uBAAuB,IAAI,CAAC;IACxE,GAAI,MAAM,oBAAoB,sBAAsB,KAAA,IAAY,CAAC,IAAI,EAAE,mBAAmB,MAAM,oBAAoB,kBAAkB;IACtI,GAAI,MAAM,oBAAoB,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,oBAAoB,OAAO;IACrG,MAAM,MAAM,oBAAoB;IAChC,YAAY,MAAM,oBAAoB;IACtC,GAAI,yBAAyB,EAAE,uBAAuB,IAAI,CAAC;GAC7D;GACA,KAAK,aAAa,QAAQ,QAAQ;EACpC;EACA,KAAK,MAAM,gBAAgB,MAAM,SAAS,UAAU,KAAK,IAAI,CAAC;EAC9D,MAAM,WAA+B;GACnC,GAAG,MAAM;GACT,eAAe,QAAQ;GACvB;GACA;GACA;GACA,SAAS;GACT,gBAAgB;GAChB,iBAAiB;IACf,kBAAkB,WAAW;IAC7B,gBAAgB,WAAW;GAC7B;EACF;EACA,KAAK,MAAM,QAAQ,UAAU;GAAE,MAAM,QAAQ,iBAAiB,QAAQ,KAAK;EAAS,CAAC;CACvF;CAEA,MAAc,sBACZ,OACA,SACA,WACe;EACf,MAAM,WAAW,MAAM;EACvB,MAAM,aAAa,MAAM;EACzB,MAAM,cAAc,MAAM,SAAS;EACnC,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,aAC/B,MAAM,IAAI,iBAAiB,oBAAoB,mCAAmC;EAEpF,MAAM,WAAW,KAAK,cAAc;EACpC,IAAI,CAAC,UAAU,MAAM,IAAI,iBAAiB,yBAAyB,WAAW;EAC9E,MAAM,YAAYF,UAAc,QAAQ,cAAc;EACtD,MAAM,WAAW,MAAM,KAAK,mBAAmB,CAAC,CAAC,KAAK,SAAS;EAC/D,IAAI,CAAC,YAAYE,UAAkB,SAAS,OAAO,OAAO,EAAE,MAAMA,UAAkB,UAAU,IAAI,GAChG,MAAM,IAAI,iBAAiB,8BAA8B,sCAAsC;EAEjG,MAAM,UAAU,cAAc,SAAS;EACvC,MAAM,SAAS,eAAe,WAAW,EAAE,cAAc,KAAK,CAAC;EAC/D,MAAM,SAAS,eAAe,SAAS;EACvC,KAAK,MAAM,gBAAgB,MAAM,SAAS,UAAU,KAAK,IAAI,CAAC;EAC9D,KAAK,MAAM,QAAQ,UAAU;GAC3B,MAAM,SAAS,YAAY;IACzB,GAAG;IACH,UAAU,MAAM,SAAS;IACzB;IACA,mBAAmB,MAAM,qBAAqB,QAAQ;IACtD,aAAa,UAAU;IACvB,iBAAiB;KACf,kBAAkB,WAAW;KAC7B,gBAAgB,WAAW;IAC7B;GACF;EACF,CAAC;CACH;CAEA,MAAc,eAAe,UAA2D;EACtF,IAAI,SAAS,WAAW,SAAS,SAAS,WAAW,OAAO,KAAA;EAC5D,MAAM,WAAW,YAAY,QAAQ;EAErC,IADc,KAAK,MAAM,KACjB,CAAC,CAAC,SAAS,WAAW,OAAO;EACrC,MAAM,YAAYF,UAAc,SAAS,aAAa;EACtD,MAAM,cAAc,KAAK,mBAAmB;EAC5C,IAAI,CAAE,MAAM,YAAY,KAAK,SAAS,GAAI,OAAO,KAAA;EACjD,MAAM,YAAY,MAAM;EACxB,MAAM,WAAW,KAAK,cAAc;EACpC,IAAI,CAAC,UAAU,MAAM,IAAI,iBAAiB,yBAAyB,WAAW;EAC9E,MAAM,YAAY,UAAU,KAAK,CAAC,CAAC,MAAM,cAAc,UAAU,WAAW,MAAM,OAAO,OAAO,EAAE,MAAM,OAAO,SAAS,CAAC,CAAC;EAC1H,MAAM,UAAU,YACZ,KAAK,SAAS,KAAK,CAAC,CAAC,MAAM,SAASE,UAAkB,KAAK,UAAU,MAAMA,UAAkB,UAAU,IAAI,CAAC,IAC5G,KAAA;EACJ,MAAM,aAAa,UAAU,KAAK,MAAM,mBAAmB,QAAQ,MAAM,IAAI,KAAA;EAC7E,MAAM,aAAa,aAAa,WAAW,aACvC,KAAK,oBAAoB,WAAW,SAAS,YAAY,SAAS,eAAe,IACjF,KAAA;EACJ,MAAM,oBAAoB,WAAW,WAAW,WAAW,OAAO,OAAO,EAAE,MAAM,OAAO,SAAS,CAAC,KAAK;EACvG,MAAM,SAAS,eAAe,WAAW,EAAE,cAAc,KAAK,CAAC;EAC/D,MAAM,YAAY,MAAM;EACxB,KAAK,MAAM,QAAQ,UAAU;GAC3B,MAAM,SAAS,YAAY;IACzB;IACA,kBAAkB,SAAS;IAC3B,iBAAiB,SAAS;IAC1B,gBAAgB,OAAO,SAAS;IAChC,UAAU,SAAS;IACnB,eAAe,SAAS;IACxB,aAAa,aAAa,mBAAmB,YAAY,KAAK,IAAI,GAAG,iBAAiB,GAAG,MAAM,KAAK,IAAI,SAAS,eAAe,SAAS;IACzI,mBAAmB,KAAK,IAAI,GAAG,iBAAiB;IAChD,GAAI,YAAY,EAAE,aAAa,UAAU,GAAG,IAAI,CAAC;IACjD,GAAI,aAAa,EAAE,iBAAiB;KAAE,kBAAkB,WAAW;KAAkB,gBAAgB,WAAW;IAAkB,EAAE,IAClI,SAAS,kBAAkB,EAAE,iBAAiB,SAAS,gBAAgB,IAAI,CAAC;IAC9E,YAAY,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY;GAC/C;EACF,CAAC;EACD,OAAO;CACT;CAEA,MAAc,eAAe,UAAgD;EAC3E,MAAM,MAAM,iBAAiB,QAAQ;EACrC,MAAM,UAAU,KAAK,MAAM,KAAK,CAAC,CAAC,QAAQ;EAC1C,IAAI,SAAS;GACX,MAAM,aAAa,oBAAoB,SAAS,UAAU,QAAQ,QAAQ;GAC1E,IAAI,aAAa,GAAG,OAAO;GAC3B,IAAI,eAAe,GAAG;IACpB,IAAI,SAAS,kBAAkB,QAAQ,iBAAiB,CAAC,QAAQ,SAC/D,MAAM,IAAI,iBAAiB,qBAAqB,2DAA2D;IAE7G,OAAO;GACT;GACA,IAAI,CAAC,QAAQ,SAAS,MAAM,KAAK,eAAe,OAAO;EACzD;EACA,MAAM,gBAAgB,SAAS,iBAAiB,OAAO,kBAAkB,QAAQ,CAAC;EAClF,MAAM,YAAY;GAAE,GAAG;GAAU,MAAM;GAAoB;GAAe,SAAS;EAAK;EACxF,KAAK,MAAM,gBAAgB,SAAS,UAAU,KAAK,IAAI,CAAC;EACxD,KAAK,MAAM,QAAQ,UAAU;GAAE,MAAM,QAAQ,OAAO;EAAU,CAAC;EAC/D,OAAO;CACT;CAEA,MAAc,kBAAkB,UAAsC;EACpE,IAAI,CAAC,mBAAmB,KAAK,QAAQ,GAAG,MAAM,IAAI,iBAAiB,qBAAqB,SAAS;EACjG,MAAM,UAAU,KAAK,MAAM,KAAK,CAAC,CAAC,SAAS;EAC3C,IAAI,CAAC,SAAS,MAAM,IAAI,iBAAiB,qBAAqB,SAAS;EACvE,MAAM,WAAW,KAAK,cAAc;EACpC,MAAM,YAAYF,UAAc,QAAQ,cAAc;EACtD,MAAM,UAAU,MAAM,KAAK,mBAAmB,CAAC,CAAC,KAAK,SAAS;EAC9D,IAAI,CAAC,YAAY,CAAC,SAAS,MAAM,IAAI,iBAAiB,qBAAqB,WAAW;EACtF,MAAM,MAAM,cAAc,WAAW;GAAE,kBAAkB,QAAQ;GAAkB,gBAAgB,QAAQ;EAAgB,CAAC;EAC5H,MAAM,UAAU,KAAK,MAAM,KAAK,CAAC,CAAC,QAAQ;EAC1C,IAAI,WAAW,CAAC,QAAQ,WAAW,QAAQ,kBAAkB,QAAQ,gBAAgB,MAAM,KAAK,eAAe,OAAO;EACtH,MAAM,SAAS,iBAAiB,SAAS;EACzC,MAAM,WAAW,KAAK,MAAM,aAAa,KAAK,IAAI,CAAC;EACnD,MAAM,WAA+B;GACnC,MAAM;GACN,kBAAkB,QAAQ;GAC1B,gBAAgB,QAAQ;GACxB,eAAe,QAAQ;GACvB;GACA,eAAe,QAAQ;GACvB,aAAa,QAAQ;GACrB,aAAa;GACb,GAAI,QAAQ,kBAAkB,EAAE,iBAAiB,QAAQ,gBAAgB,IAAI,CAAC;EAChF;EACA,KAAK,MAAM,QAAQ,UAAU;GAC3B,OAAO,MAAM,SAAS;GACtB,MAAM,QAAQ,OAAO;EACvB,CAAC;EACD,OAAO;CACT;CAEA,MAAc,uBAAuB,QAAgF;EACnH,MAAM,WAAW,KAAK,cAAc;EACpC,IAAI,CAAC,UAAU;EACf,KAAK,MAAM,CAAC,aAAa,aAAa,QAAQ;GAC5C,MAAM,YAAY,SAAS,IAAI,WAAW;GAC1C,IAAI,CAAC,WAAW;GAChB,MAAM,UAAU,CAAC,GAAG,UAAU,UAAU;GACxC,MAAM,cAAc,IAAI,IAAI,SAAS,KAAK,SAAS,OAAO,KAAK,EAAE,CAAC,CAAC;GAKnE,MAAM,SAAS,CAAC,GAJA,CAAC,GAAG,QAAQ,CAAC,CAC1B,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,YAAY,OAAO,EAAE,EAAE,CAAC,CAAC,cAAc,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CACnF,KAAK,SAAS,KAAK,EAAE,CAAC,CACtB,QAAQ,IAAI,OAAO,QAAQ,QAAQ,MAAM,aAAa,OAAO,QAAQ,MAAM,OAAO,EAAE,CAAC,KAAK,IAAI,WAAW,cAAc,OAAO,SAAS,MAAM,OAAO,EAAE,CAAC,MAAM,KACvI,GAAG,GAAG,QAAQ,QAAQ,OAAO,CAAC,YAAY,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC;GACnF,IAAI,OAAO,WAAW,QAAQ,UAAU,OAAO,OAAO,IAAI,UAAU,OAAO,EAAE,MAAM,OAAO,QAAQ,MAAM,CAAC,GAAG;GAC5G,IAAI;GACJ,KAAK,MAAM,MAAM,OAAO,QAAQ,GAAG;IACjC,MAAM,UAAU,oBAAoB,IAAI,MAAM;IAC9C,SAAS;GACX;EACF;CACF;CAEA,wBAAgC,QAA2C;EACzE,MAAM,QAAQ,KAAK,MAAM,KAAK;EAC9B,MAAM,SAAS,MAAM,QAAQ,cAAc,WAAW,MAAM;EAC5D,IAAI,UAAU,CAAC,OAAO,SAAS,OAAOA,UAAc,OAAO,aAAa;EACxE,MAAM,UAAU,OAAO,OAAO,MAAM,QAAQ,CAAC,CAC1C,QAAQ,UAAU,MAAM,qBAAqB,OAAO,oBAAoB,MAAM,oBAAoB,OAAO,cAAc,CAAC,CACxH,MAAM,GAAG,MAAM,oBAAoB,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;EAC/D,OAAO,UAAUA,UAAc,QAAQ,cAAc,IAAI,KAAA;CAC3D;CAEA,0BAAkC,QAAoB,YAAyC;EAC7F,MAAM,WAAW,OAAO,OAAO,KAAK,MAAM,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,QAAQ,YACnE,QAAQ,qBAAqB,OAAO,oBAAoB,QAAQ,sBAAsB,OAAO,mBAC5F,eAAe,KAAA,KAAa,QAAQ,eAAe,WACtD;EACA,OAAO,SAAS,WAAW,IAAI,SAAS,EAAE,EAAE,mBAAmB,KAAA;CACjE;CAEA,MAAc,aAAa,UAAiD;EAC1E,MAAM,cAAc,KAAK,mBAAmB;EAC5C,MAAM,UAAU,MAAM,YAAY,KAAK,SAAS,cAAc;EAC9D,MAAM,SAAS,UACX,MAAM,YAAY,KAAK,SAAS,gBAAgB,OAAO,IACvD,MAAM,YAAY,OAAO,SAAS,QAAQ,SAAS,OAAO,WAAW,EAAE,qBAAqB,SAAS,oBAAoB,IAAI,KAAA,CAAS;EAC1I,IAAI;GACF,IAAI,cAAc,OAAO,MAAM,MAAM,cAAc,SAAS,MAAM,KAAK,OAAO,wBAAwB,SAAS,qBAC7G,MAAM,IAAI,iBAAiB,uBAAuB,8BAA8B;GAElF,MAAM,WAA2B,CAAC;GAClC,KAAK,IAAI,SAAS,KAAO;IACvB,MAAM,OAAO,MAAM,OAAO,KAAK,QAAQ,sBAAsB;IAC7D,IAAI,KAAK,OAAO,WAAW,GAAG;IAC9B,SAAS,KAAK,GAAG,KAAK,MAAM;IAC5B,UAAU,KAAK,OAAO;IACtB,IAAI,KAAK,OAAO,SAAS,wBAAwB;GACnD;GACA,IAAI,SAAS,SAAS,SAAS,OAAO,QAAQ,MAAM,IAAI,iBAAiB,2BAA2B,cAAc,SAAS,eAAe,gBAAgB,SAAS,OAAO,MAAM,SAAS,OAAO,OAAO,EAAE;GACzM,KAAK,IAAI,QAAQ,GAAG,QAAQ,SAAS,QAAQ,SAAS,GACpD,IAAI,cAAc,SAAS,MAAM,MAAM,cAAc,SAAS,OAAO,MAAM,GACzE,MAAM,IAAI,iBAAiB,2BAA2B,cAAc,SAAS,eAAe,4BAA4B,SAAS,MAAM,EAAE,IAAI,MAAM,SAAS,OAAO,SAAS,SAAS,OAAO,OAAO,KAAK;GAG5M,KAAK,IAAI,SAAS,SAAS,QAAQ,SAAS,SAAS,OAAO,QAAQ,UAAU,wBAC5E,MAAM,OAAO,OAAO,SAAS,OAAO,MAAM,QAAQ,KAAK,IAAI,SAAS,wBAAwB,SAAS,OAAO,MAAM,CAAC,CAAC;GAEtH,MAAM,OAAO,MAAM;EACrB,UAAU;GACR,MAAM,OAAO,MAAM;EACrB;EACA,OAAO,YAAY,KAAA;CACrB;CAEA,oBACE,WACA,SACA,YACA,iBACA,aAAa,wBAAwB,KAAK,MAAM,KAAK,CAAC,GAChC;EACtB,MAAM,QAAQ,WAAW;EACzB,MAAM,oBAAoB,WAAW,oBAAoB,IAAI,OAAO,UAAU,EAAE,CAAC,KAAK,CAAC;EACvF,MAAM,mBAAmB,kBAAkB,QAAQ,YACjD,QAAQ,gBAAgB,QAAQ,UAChC,MAAM,UAAU,QAAQ,UAAU,MAAM,MAAM,UAAU,QAAQ,UAAU,CAC5E;EAQA,MAAM,SAPmB,kBACrB,kBAAkB,MAAM,YACxB,QAAQ,qBAAqB,gBAAgB,oBAC7C,QAAQ,sBAAsB,gBAAgB,kBAC9C,QAAQ,gBAAgB,QAAQ,MAClC,IACE,KAAA,OAC+B,iBAAiB,WAAW,IAAI,iBAAiB,KAAK,KAAA;EACzF,MAAM,mBAAmB,iBAAiB,oBAAoB,OAAO,oBAAoB,KAAK,MAAM,WAAW;EAC/G,MAAM,oBAAoB,iBAAiB,kBAAkB,OAAO,qBAAqB,UAAU;EACnG,MAAM,OAAO;GAAE;GAAkB;GAAmB;GAAY,YAAY,MAAM,UAAU,QAAQ,UAAU;GAAG,OAAO,UAAU;EAAM;EACxI,MAAM,SAAS,gBAAgB,IAAI;EACnC,MAAM,MAAM,iBAAiB,kBAAkB,mBAAmB,KAAK,UAAU;EACjF,MAAM,UAAU,MAAM,WAAW;EACjC,MAAM,WAAW,WAAW,QAAQ,kBAAkB,SAAS,QAAQ,WAAW,KAAK,MAAM,aAAa,KAAK,IAAI,CAAC;EACpH,MAAM,UAAgC;GACpC;GACA;GACA,kBAAkB,UAAU;GAC5B,WAAW,UAAU;GACrB,aAAa,QAAQ;GACrB,YAAY,KAAK;GACjB,OAAO,UAAU;GACjB;GACA,eAAe;EACjB;EACA,IAAI,CAAC,WAAW,cAAc,OAAO,MAAM,cAAc,OAAO,GAAG;GACjE,KAAK,MAAM,QAAQ,UAAU;IAC3B,MAAM,WAAW,OAAO;GAC1B,CAAC;GACD,sBAAsB,YAAY,KAAK,OAAO;EAChD;EACA,OAAO;GAAE,GAAG;GAAM;GAAU,eAAe;EAAO;CACpD;CAEA,MAAc,mBACZ,aACA,WACA,YACA,mBACA,WACA,eACA,UACA,QACA,SACA,YACA,aAC0C;EAC1C,MAAM,EAAE,QAAQ,qBAAqB,QAAQ,UAAU,mBAAmB,MAAM,KAAK,kBAAkB,aAAa,WAAW,aAAa;EAC5I,MAAM,iBAAiB,OAAO,SAAS;EACvC,MAAM,WAAW,sBAAsB,cAAc;EACrD,IAAI,CAAC,OAAO,OAAO,MAAM,UAAU,OAAO,GAAG,MAAM,MAAM,UAAU,UAAU,IAAI,GAAG;GAClF,KAAK,YAAY,OAAO,QAAQ;GAChC,KAAK,iBAAiB,OAAO,QAAQ;GACrC;EACF;EACA,MAAM,QAAQ,cAAc,wBAAwB,KAAK,MAAM,KAAK,CAAC;EACrE,MAAM,QAAQ,MAAM;EACpB,MAAM,iBAAiB,OAAO,gBAAgB,MAAM,iBAAiB,IAAI,OAAO,OAAO,aAAa,CAAC,IAAI,KAAA;EACzG,MAAM,eAAe,iBACjB;GAAE,kBAAkB,eAAe;GAAkB,gBAAgB,eAAe;EAAe,IACnG,KAAA;EACJ,MAAM,mBAAmB,uBACvB,KAAK,cACL,OAAO,SAAS,GAChB,OACA;GAAE,kBAAkB,WAAW;GAAkB,gBAAgB,WAAW;EAAkB,CAChG;EACA,MAAM,cAAc,uBAAuB,MAAM;EACjD,MAAM,UAAU,MAAM,KAAK,cAAc,QAAQ,gBAAgB,WAAW;EAC5E,MAAM,SAAS,mBACb,QACA,qBACA,QACA,YACA,kBACA,SACA,YACF;EACA,MAAM,UAAU,UACZ,KAAA,IACA,MAAM,iBAAiB,IAAI,cAAc,KAAK,MAAM,QAAQ,cAAc,WAAW;GACnF,kBAAkB,KAAK,MAAM,WAAW;GACxC,gBAAgB;EAClB,CAAC;EACL,MAAM,mBAAmB,SAAS,oBAAoB,SAAS,oBAAoB,KAAK,MAAM,WAAW;EACzG,MAAM,iBAAiB,SAAS,mBAAmB,SAAS,kBAAkB;EAC9E,MAAM,kBAAkB;GAAE,kBAAkB,WAAW;GAAkB,gBAAgB,WAAW;EAAkB;EACtH,MAAM,yBAAyB,QAAQ,SAAS,oBAC7C,QAAQ,gBAAgB,qBAAqB,gBAAgB,oBAAoB,QAAQ,gBAAgB,mBAAmB,gBAAgB,eAAe;EAC9J,MAAM,cAAc,mBAAmB,YAAY,mBAAmB,UAAU,MAAM;EACtF,MAAM,sBAAsB,QAAQ,WAAW,QAAQ,gBAAgB,WAAW;EAClF,IAAI,WAAW,SAAS,YAAY,SAAS;EAC7C,IAAI,gBAAgB;EACpB,IAAI,iBAAiB,SAAS;EAC9B,IAAI,SAAS;GACX,IAAI,QAAQ,kBAAkB,UAAU,QAAQ,gBAAgB,eAAe,QAAQ,sBAAsB,mBAAmB;IAC9H,MAAM,eAAe,KAAK,MAAM,aAAa,KAAK,IAAI,CAAC;IACvD,WAAW;IAEX,MAAM,WADiB,QAAQ,kBAAkB,SAE7C,YAAY;KAAE;KAAkB;KAAgB,UAAU;KAAc,eAAe;IAAO,CAAuB,IACrH,QAAQ;IACZ,MAAM,iBAAiB;KACrB,GAAG;KACH;KACA,UAAU;KACV,eAAe;KACf;KACA;KACA;IACF;IACA,KAAK,MAAM,QAAQ,UAAU;KAC3B,OAAO,MAAM,SAAS,QAAQ;KAC9B,MAAM,SAAS,YAAY;IAC7B,CAAC;IACD,aAAa,OAAO,QAAQ,UAAU,cAAc;IACpD,iBAAiB;GACnB,OAAO,gBAAgB,QAAQ;EACjC,OAAO,IAAI,CAAC,WAAW,QAAQ,kBAAkB,UAAU,QAAQ,WAAW,0BAA0B,CAAC,QAAQ,mBAAmB,qBAClI,WAAW,KAAK,MAAM,aAAa,KAAK,IAAI,CAAC;EAE/C,MAAM,WAA+B;GACnC,MAAM;GACN;GACA;GACA,eAAe;GACf,UAAU,YAAY,KAAK,MAAM,aAAa,KAAK,IAAI,CAAC;GACxD;GACA;GACA;GACA,GAAI,UAAU,CAAC,IAAI,SAAS,cAAc,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;GAClF,GAAI,UAAU,CAAC,IAAI,SAAS,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;EACjF;EACA,IAAI,CAAC,YAAY,CAAC,WAAW,QAAQ,kBAAkB,UAAU,QAAQ,WAAW,0BAA0B,CAAC,QAAQ,mBAAmB,sBAAsB;GAC9J,KAAK,MAAM,QAAQ,UAAU;IAC3B,MAAM,QAAQ,iBAAiB,QAAQ,KAAK;GAC9C,CAAC;GACD,mBAAmB,OAAO,QAAQ;EACpC;EAEA,IAAI,CAAC,WAAW,CAAC,QAAQ,MAAM,WAAW,OAAO,SAAS,OAAO,GAAG;GAClE,MAAM,cAAc,yBAAyB;IAC3C,UAAU;IACV;IACA;IACA,WAAW;IACX,qBAAqB;IACrB;GACF,CAAC;GACD,IAAI,aAAa;IACf,MAAM,QAAiC;KACrC;KACA;KACA,YAAY,OAAO;KACnB;KACA;IACF;IACA,KAAK,YAAY,IAAI,UAAU,KAAK;IACpC,KAAK,iBAAiB,IAAI,UAAU,KAAK;GAC3C,OAAO;IACL,KAAK,YAAY,OAAO,QAAQ;IAChC,KAAK,iBAAiB,OAAO,QAAQ;GACvC;EACF,OAAO;GACL,KAAK,YAAY,OAAO,QAAQ;GAChC,KAAK,iBAAiB,OAAO,QAAQ;EACvC;EACA,OAAO;GACL,OAAO;IACL;IACA,GAAI,iBAAiB,EAAE,UAAU,eAAe,IAAI,CAAC;IACrD,sBAAsB;IACtB;IACA;IACA,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;IACvC,WAAW;IACX;IACA;IACA;IACA,GAAI,mBAAmB,EAAE,qBAAqB,iBAAiB,IAAI,CAAC;IACpE,QAAQ,CAAC,GAAG,MAAM;IAClB;IACA,YAAY,OAAO;IACnB;GACF;GACA,YAAY,OAAO;GACnB;GACA;EACF;CACF;CAEA,MAAc,kBACZ,aACA,WACA,eAC4G;EAC5G,IAAI,WAAW;EACf,KAAK,IAAI,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG;GAC/C,IAAI,SAAS,iBAAiB,sBAAsB,MAAM,IAAI,iBAAiB,kBAAkB,oBAAoB;GACrH,MAAM,SAAS,MAAM,YAAY,KAAK,WAAW,MAAM;GACvD,IAAI;IACF,MAAM,SAAyB,CAAC;IAChC,IAAI,SAAS;IACb,SAAS;KACP,MAAM,OAAO,MAAM,OAAO,KAAK,QAAQ,sBAAsB;KAC7D,IAAI,KAAK,OAAO,WAAW,GAAG;KAC9B,OAAO,KAAK,GAAG,gBAAgB,KAAK,MAAM,CAAC;KAC3C,UAAU,KAAK,OAAO;KACtB,IAAI,OAAO,SAAS,oBAAoB,KAAK,MAAM,IAAI,iBAAiB,qBAAqB,WAAW;KACxG,IAAI,KAAK,OAAO,SAAS,wBAAwB;IACnD;IACA,MAAM,YAAY,qBAAqB,OAAO,QAAQ,MAAM;IAC5D,iBAAiB,WAAW,WAAW,CAAC;IACxC,MAAM,QAAQ,MAAM,YAAY,KAAK,SAAS;IAC9C,IAAI,CAAC,OAAO,MAAM,IAAI,iBAAiB,mBAAmB,WAAW;IACrE,IACE,cAAc,SAAS,QAAQ,MAAM,cAAc,MAAM,QAAQ,KACjE,cAAc,SAAS,MAAM,MAAM,cAAc,MAAM,MAAM,KAC7D,cAAc,OAAO,MAAM,MAAM,cAAc,MAAM,MAAM,GAE3D,OAAO;KACL,QAAQ,OAAO;KACf,qBAAqB,OAAO,OAAO,mBAAmB;KACtD,QAAQ,CAAC,GAAG,SAAS;KACrB,UAAU,MAAM;IAClB;IAEF,WAAW;GACb,UAAU;IACR,MAAM,OAAO,MAAM;GACrB;EACF;EACA,MAAM,IAAI,iBAAiB,oBAAoB,mBAAmB;CACpE;CAEA,MAAc,cACZ,QACA,WACA,aAC8B;EAC9B,MAAM,cAAc,qBAAqB,MAAM;EAC/C,MAAM,SAAS,gBAAgB,MAAM;EACrC,MAAM,mBAAmB,IAAI,IAAI,OAAO,IAAI,QAAQ,CAAC;EACrD,KAAK,MAAM,aAAa,sBAAsB,QAAQ,SAAS,GAC7D,IAAI,CAAC,iBAAiB,IAAI,SAAS,SAAS,CAAC,GAAG,OAAO,KAAK,SAAS;EAEvE,MAAM,2BAAW,IAAI,IAA+B;EACpD,MAAM,kBAAmB,YAAY,OAAO,SAAS,YAAY,MAAM,SAAU,IAAI,KAAK,eAAe,IAAI,KAAA;EAC7G,IAAK,YAAY,OAAO,SAAS,YAAY,MAAM,SAAU,KAAK,CAAC,iBACjE,MAAM,IAAI,iBAAiB,2BAA2B,WAAW;EAEnE,KAAK,MAAM,OAAO,YAAY,QAAQ;GACpC,MAAM,MAAM,cAAc,SAAS,GAAG;GACtC,MAAM,SAAS,aAAa,IAAI,GAAG,CAAC,EAAE;GACtC,IAAI,QAAQ,SAAS,WAAW,cAAc,OAAO,GAAG,MAAM,cAAc,GAAG,GAAG;IAChF,SAAS,IAAI,KAAK,MAAM;IACxB;GACF;GACA,MAAM,SAAS,MAAM,gBAAiB,UAAU,GAAG;GACnD,MAAM,SAAS,OAAO,OAAO,IAAI;GACjC,MAAM,SAA4B;IAChC,IAAI;IACJ,MAAM;IACN,KAAK,OAAO;IACZ,OAAO,OAAO,KAAK;IACnB;IACA,MAAM,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,SAAS,QAAQ;GAClD;GACA,SAAS,IAAI,KAAK,MAAM;GACxB,aAAa,IAAI,KAAK,EAAE,OAAO,CAAC;EAClC;EACA,KAAK,MAAM,OAAO,YAAY,OAAO;GACnC,MAAM,MAAM,cAAc,QAAQ,GAAG;GACrC,MAAM,SAAS,aAAa,IAAI,GAAG,CAAC,EAAE;GACtC,IAAI,QAAQ,SAAS,UAAU,cAAc,OAAO,GAAG,MAAM,cAAc,GAAG,GAAG;IAC/E,SAAS,IAAI,KAAK,MAAM;IACxB;GACF;GACA,MAAM,OAAO,MAAM,aAAa,gBAAiB,eAAe,GAAG,CAAC;GACpE,MAAM,SAA4B;IAChC,IAAI;IACJ,MAAM;IACN;IACA,OAAO,KAAK;IACZ,QAAQ,OAAO,IAAI;IACnB,MAAM,KAAK,SAAS,QAAQ;GAC9B;GACA,SAAS,IAAI,KAAK,MAAM;GACxB,aAAa,IAAI,KAAK,EAAE,OAAO,CAAC;EAClC;EACA,IAAI,OAAO,SAAS,GAAG;GACrB,MAAM,QAAQ,KAAK,UAAU;GAC7B,MAAM,gBAA0C,CAAC;GACjD,KAAK,MAAM,aAAa,QAAQ;IAC9B,IAAI,CAAC,OAAO;KAAE,cAAc,KAAK,SAAS;KAAG;IAAS;IACtD,MAAM,MAAM,SAAS,SAAS;IAC9B,MAAM,SAAS,aAAa,IAAI,GAAG,CAAC,EAAE;IACtC,IAAI,QAAQ,SAAS,WAAW,cAAc,OAAO,SAAS,MAAM,cAAc,SAAS,MACxF,UAAU,IAAI,UAAU,KAAA,KAAa,OAAO,UAAU,UAAU,IAAI,QAAQ;KAC7E,SAAS,IAAI,KAAK,MAAM;KACxB;IACF;IACA,IAAI;KACF,MAAM,OAAO,MAAM,aAAa,gBAAgB,OAAO,SAAS,CAAC;KACjE,IAAI,UAAU,IAAI,UAAU,KAAA,KAAa,KAAK,eAAe,UAAU,IAAI,OAAO;MAChF,cAAc,KAAK,SAAS;MAAG;KACjC;KACA,IAAI;MACF,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,IAAI;KACvD,QAAQ;MACN,cAAc,KAAK,SAAS;MAAG;KACjC;KACA,MAAM,SAA4B;MAChC,IAAI;MACJ,MAAM;MACN;MACA,OAAO,KAAK;MACZ,QAAQ,OAAO,IAAI;MACnB,MAAM,KAAK,SAAS,QAAQ;KAC9B;KACA,SAAS,IAAI,KAAK,MAAM;KACxB,aAAa,IAAI,KAAK,EAAE,OAAO,CAAC;IAClC,QAAQ;KACN,cAAc,KAAK,SAAS;IAC9B;GACF;GACA,KAAK,MAAM,aAAa,eAAe;IACrC,MAAM,MAAM,SAAS,SAAS;IAC9B,SAAS,IAAI,KAAK;KAChB,IAAI;KACJ,MAAM;KACN;KACA,OAAO;KACP,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC;KAC9B,MAAM;KACN,aAAa;IACf,CAAC;GACH;EACF;EACA,OAAO,CAAC,GAAG,SAAS,OAAO,CAAC;CAC9B;CAEA,qBAAqD;EACnD,MAAM,cAAc,KAAK,eAAe;EACxC,IAAI,CAAC,aAAa,MAAM,IAAI,iBAAiB,mCAAmC,YAAY;EAC5F,OAAO;CACT;CAEA,kBAA6B,WAAyC;EACpE,MAAM,SAAS,KAAK,cAAc,KAAK,SAAS;EAChD,KAAK,gBAAgB,OAAO,WAAW,KAAA,SAAiB,KAAA,CAAS;EACjE,OAAO;CACT;AACF"}
|