memeloop 0.2.8 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-NVJCRIEK.js → chunk-34B7MUI6.js} +2 -2
- package/dist/{chunk-DACM5AMS.js → chunk-7W4FMKMO.js} +190 -56
- package/dist/chunk-7W4FMKMO.js.map +1 -0
- package/dist/{chunk-OD6U6VAR.js → chunk-GH5RDPLJ.js} +2 -2
- package/dist/{chunk-OD6U6VAR.js.map → chunk-GH5RDPLJ.js.map} +1 -1
- package/dist/device-network/cloudDeviceFetchClient.d.ts +9 -7
- package/dist/device-network/cloudDeviceFetchClient.d.ts.map +1 -1
- package/dist/device-network/deviceCloudConnectionCoordinator.d.ts +5 -5
- package/dist/device-network/deviceCloudConnectionCoordinator.d.ts.map +1 -1
- package/dist/device-network/deviceOrchestrationTransport.d.ts +7 -0
- package/dist/device-network/deviceOrchestrationTransport.d.ts.map +1 -1
- package/dist/device-network/standardDeviceCloudConnectionAdapter.d.ts +16 -8
- package/dist/device-network/standardDeviceCloudConnectionAdapter.d.ts.map +1 -1
- package/dist/device-network/types.d.ts +4 -2
- package/dist/device-network/types.d.ts.map +1 -1
- package/dist/device-network-portable.cjs +190 -55
- package/dist/device-network-portable.cjs.map +1 -1
- package/dist/device-network-portable.js +189 -55
- package/dist/device-network-portable.js.map +1 -1
- package/dist/device-network.cjs +190 -55
- package/dist/device-network.cjs.map +1 -1
- package/dist/device-network.js +4 -2
- package/dist/index.cjs +488 -180
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +302 -127
- package/dist/index.js.map +1 -1
- package/dist/loop-api.cjs +1 -1
- package/dist/loop-api.cjs.map +1 -1
- package/dist/loop-api.js +1 -1
- package/dist/mobile.cjs.map +1 -1
- package/dist/orchestration/externalOrchestrationController.d.ts.map +1 -1
- package/dist/orchestration/workloadExecutionController.d.ts.map +1 -1
- package/dist/plugin/loader.d.ts +1 -1
- package/package.json +2 -1
- package/dist/chunk-DACM5AMS.js.map +0 -1
- /package/dist/{chunk-NVJCRIEK.js.map → chunk-34B7MUI6.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/device-network-portable.ts","../src/encoding/canonicalJson.ts","../src/storage/conversationPaging.ts","../src/conversation/compactionBoundary.ts","../src/conversation/events.ts","../src/runState.ts","../src/userMessageAdmission.ts","../src/device-network/attachmentUpload.ts","../src/device-network/scheduledTaskRpc.ts","../src/device-network/agentDeviceRpc.ts","../src/device-network/agentDeviceRpcClient.ts","../src/device-network/deviceGrantMessages.ts","../src/device-network/cloudDeviceFetchClient.ts","../src/device-network/deviceCloudConnectionCoordinator.ts","../src/device-network/deviceHeartbeat.ts","../src/orchestration/errors.ts","../src/device-network/jsonFrame.ts","../src/device-network/deviceOrchestrationTransport.ts","../src/device-network/libp2pSyncProtocol.ts","../src/device-network/libp2pDeviceSyncTransport.ts","../src/device-network/libp2pRpcProtocol.ts","../src/device-network/localTrustDeviceAuthorizer.ts","../src/device-network/mutableDeviceAuthorizer.ts","../src/device-network/pairingInvite.ts","../src/device-network/reconcileCloudDeviceDirectory.ts","../src/device-network/standardDeviceCloudConnectionAdapter.ts","../src/device-network/types.ts","../src/sync/attachmentRpcCodec.ts","../src/sync/protocol.ts","../src/sync/chatSyncEngine.ts","../src/sync/peerNodeAdapter.ts"],"sourcesContent":["/**\n * Browser and React Native-safe device networking surface.\n *\n * Host adapters, orchestration controllers, and deployable script loading are\n * deliberately excluded from this graph.\n */\nexport { assertCanonicalConversationEvents, canonicalConversationEventBytes, conversationEventAttachmentReferences, isConversationEvent } from './conversation/events.js';\nexport type { ConversationEvent, ConversationEventCursor } from './conversation/events.js';\nexport * from './device-network/agentDeviceRpc.js';\nexport * from './device-network/agentDeviceRpcClient.js';\nexport * from './device-network/attachmentUpload.js';\nexport * from './device-network/cloudDeviceFetchClient.js';\nexport * from './device-network/deviceCloudConnectionCoordinator.js';\nexport * from './device-network/deviceGrantMessages.js';\nexport * from './device-network/deviceHeartbeat.js';\nexport * from './device-network/deviceOrchestrationTransport.js';\nexport * from './device-network/jsonFrame.js';\nexport * from './device-network/libp2pDeviceSyncTransport.js';\nexport * from './device-network/libp2pRpcProtocol.js';\nexport * from './device-network/libp2pSyncProtocol.js';\nexport * from './device-network/localTrustDeviceAuthorizer.js';\nexport * from './device-network/mutableDeviceAuthorizer.js';\nexport * from './device-network/pairingInvite.js';\nexport * from './device-network/reconcileCloudDeviceDirectory.js';\nexport * from './device-network/scheduledTaskRpc.js';\nexport * from './device-network/standardDeviceCloudConnectionAdapter.js';\nexport * from './device-network/types.js';\nexport type { ConversationEventPage, MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from './storage/ports.js';\nexport { decodeAttachmentBlobRpc } from './sync/attachmentRpcCodec.js';\nexport * from './sync/chatSyncEngine.js';\nexport * from './sync/peerNodeAdapter.js';\nexport * from './sync/protocol.js';\nexport type { IAgentStorage } from './types.js';\n","/** Resource bounds enforced while traversing and encoding canonical JSON. */\nexport interface CanonicalJsonLimits {\n /** Root is depth zero; every nested array/object member increments depth. */\n maxDepth: number;\n /** Counts every JSON value and every object key. */\n maxNodes: number;\n /** Per string/key bound checked before JSON escaping allocates an encoded copy. */\n maxStringCodeUnits: number;\n /** Per string/key UTF-8 bound. */\n maxStringBytes: number;\n /** Maximum UTF-8 bytes in the final canonical representation. */\n maxBytes: number;\n}\n\nexport const DEFAULT_CANONICAL_JSON_LIMITS: Readonly<CanonicalJsonLimits> = Object.freeze({\n maxDepth: 64,\n maxNodes: 100_000,\n maxStringCodeUnits: 1_048_576,\n maxStringBytes: 1_048_576,\n maxBytes: 1_048_576,\n});\n\nexport type CanonicalJsonErrorCode =\n | 'accessor_property'\n | 'array_property'\n | 'cycle'\n | 'dangerous_key'\n | 'invalid_unicode'\n | 'invalid_limit'\n | 'invalid_number'\n | 'max_bytes'\n | 'max_depth'\n | 'max_nodes'\n | 'max_string_bytes'\n | 'max_string_code_units'\n | 'non_enumerable_property'\n | 'non_plain_object'\n | 'sparse_array'\n | 'symbol_property'\n | 'unsupported_type';\n\n/** Stable fail-closed error surfaced by every canonical JSON entry point. */\nexport class CanonicalJsonError extends Error {\n public constructor(public readonly code: CanonicalJsonErrorCode, cause?: unknown) {\n super(`canonical_json_${code}`, cause === undefined ? undefined : { cause });\n this.name = 'CanonicalJsonError';\n }\n}\n\nconst DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\nconst ARRAY_INDEX = /^(?:0|[1-9]\\d*)$/u;\nconst LIMIT_KEYS = [\n 'maxDepth',\n 'maxNodes',\n 'maxStringCodeUnits',\n 'maxStringBytes',\n 'maxBytes',\n] as const satisfies ReadonlyArray<keyof CanonicalJsonLimits>;\nconst LIMIT_KEY_SET: ReadonlySet<string> = new Set(LIMIT_KEYS);\n\n/** Encode strict JSON with object keys sorted by UTF-16 code-unit order. */\nexport function canonicalJsonString(\n value: unknown,\n limits?: Partial<CanonicalJsonLimits>,\n): string {\n return new CanonicalJsonEncoder(resolveLimits(limits)).encode(value);\n}\n\n/** UTF-8 bytes of {@link canonicalJsonString}. */\nexport function canonicalJsonBytes(\n value: unknown,\n limits?: Partial<CanonicalJsonLimits>,\n): Uint8Array {\n return new TextEncoder().encode(canonicalJsonString(value, limits));\n}\n\n/**\n * Encode an unambiguous domain-separated envelope. Both the domain and payload\n * are JSON values inside `{\"domain\":...,\"payload\":...}`; no delimiter can be\n * injected to make two `(domain, payload)` pairs share bytes.\n */\nexport function domainSeparatedCanonicalJsonBytes(\n domain: string,\n payload: unknown,\n limits?: Partial<CanonicalJsonLimits>,\n): Uint8Array {\n if (typeof domain !== 'string' || domain.length === 0) {\n throw new CanonicalJsonError('unsupported_type');\n }\n return canonicalJsonBytes({ domain, payload }, limits);\n}\n\nclass CanonicalJsonEncoder {\n private readonly chunks: string[] = [];\n private readonly activeObjects = new Set<object>();\n private bytes = 0;\n private nodes = 0;\n\n public constructor(private readonly limits: CanonicalJsonLimits) {}\n\n public encode(value: unknown): string {\n this.writeValue(value, 0);\n return this.chunks.join('');\n }\n\n private writeValue(value: unknown, depth: number): void {\n if (depth > this.limits.maxDepth) this.fail('max_depth');\n this.consumeNode();\n if (value === null) {\n this.append('null');\n return;\n }\n switch (typeof value) {\n case 'string':\n this.writeString(value);\n return;\n case 'boolean':\n this.append(value ? 'true' : 'false');\n return;\n case 'number':\n this.writeNumber(value);\n return;\n case 'object':\n this.writeStructuredValue(value, depth);\n return;\n default:\n this.fail('unsupported_type');\n }\n }\n\n private writeNumber(value: number): void {\n if (!Number.isFinite(value) || (Number.isInteger(value) && !Number.isSafeInteger(value))) {\n this.fail('invalid_number');\n }\n this.append(JSON.stringify(value));\n }\n\n private writeString(value: string): void {\n const rawBytes = this.assertStringBounds(value);\n // JSON string encoding never uses fewer bytes than the raw valid UTF-8\n // plus its two quotes. Reject before JSON.stringify allocates an escaped\n // copy when even that lower bound cannot fit.\n if (rawBytes + 2 > this.limits.maxBytes - this.bytes) this.fail('max_bytes');\n this.append(JSON.stringify(value));\n }\n\n private writeStructuredValue(value: object, depth: number): void {\n this.withActiveObject(value, () => {\n let isArray: boolean;\n try {\n isArray = Array.isArray(value);\n } catch (error) {\n throw new CanonicalJsonError('non_plain_object', error);\n }\n if (isArray) this.writeArray(value as unknown[], depth);\n else this.writeObject(value, depth);\n });\n }\n\n private writeArray(value: unknown[], depth: number): void {\n if (this.readPrototype(value) !== Array.prototype) this.fail('non_plain_object');\n const properties = this.readProperties(value);\n const lengthProperty = properties.find(([key]) => key === 'length')?.[1];\n if (\n !lengthProperty || 'get' in lengthProperty || 'set' in lengthProperty ||\n !('value' in lengthProperty) || lengthProperty.enumerable ||\n typeof lengthProperty.value !== 'number' || !Number.isSafeInteger(lengthProperty.value) ||\n lengthProperty.value < 0\n ) this.fail('array_property');\n const length = lengthProperty.value;\n if (length > this.limits.maxNodes) this.fail('max_nodes');\n this.assertMinimumArrayBytes(length);\n const values = new Map<number, unknown>();\n for (const [key, descriptor] of properties) {\n if (key === 'length') continue;\n this.assertStringBounds(key);\n if (!ARRAY_INDEX.test(key)) this.fail('array_property');\n const index = Number(key);\n if (!Number.isSafeInteger(index) || index < 0 || index >= length) {\n this.fail('array_property');\n }\n this.assertDataProperty(descriptor);\n values.set(index, descriptor.value);\n }\n if (values.size !== length) this.fail('sparse_array');\n\n this.append('[');\n for (let index = 0; index < length; index += 1) {\n if (index > 0) this.append(',');\n this.writeValue(values.get(index), depth + 1);\n }\n this.append(']');\n }\n\n private writeObject(value: object, depth: number): void {\n const prototype = this.readPrototype(value);\n if (prototype !== Object.prototype && prototype !== null) this.fail('non_plain_object');\n const properties = this.readProperties(value);\n const entries: Array<[key: string, value: unknown, encodedKey: string]> = [];\n let minimumBytes = 2;\n for (const [key, descriptor] of properties) {\n if (DANGEROUS_KEYS.has(key)) this.fail('dangerous_key');\n this.consumeNode();\n const rawKeyBytes = this.assertStringBounds(key);\n this.assertDataProperty(descriptor);\n const entrySyntaxBytes = entries.length === 0 ? 2 : 3;\n minimumBytes = this.addMinimumBytes(\n minimumBytes,\n rawKeyBytes + 2 + entrySyntaxBytes,\n );\n const encodedKey = JSON.stringify(key);\n // One comma after the first entry, one colon, and at least one byte for\n // the value. This prevents sorting a huge key set that cannot possibly\n // fit in the configured output bound.\n const escapedExtraBytes = utf8ByteLength(encodedKey) - (rawKeyBytes + 2);\n minimumBytes = this.addMinimumBytes(minimumBytes, escapedExtraBytes);\n entries.push([key, descriptor.value, encodedKey]);\n }\n entries.sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0);\n\n this.append('{');\n entries.forEach(([, item, encodedKey], index) => {\n if (index > 0) this.append(',');\n this.append(encodedKey);\n this.append(':');\n this.writeValue(item, depth + 1);\n });\n this.append('}');\n }\n\n private readPrototype(value: object): object | null {\n try {\n return Object.getPrototypeOf(value) as object | null;\n } catch (error) {\n throw new CanonicalJsonError('non_plain_object', error);\n }\n }\n\n private readProperties(value: object): Array<[string, PropertyDescriptor]> {\n let keys: Array<string | symbol>;\n try {\n keys = Reflect.ownKeys(value);\n } catch (error) {\n throw new CanonicalJsonError('non_plain_object', error);\n }\n if (keys.length > this.limits.maxNodes + 1) this.fail('max_nodes');\n if (keys.some(key => typeof key === 'symbol')) this.fail('symbol_property');\n return keys.map((key) => {\n let descriptor: PropertyDescriptor | undefined;\n try {\n descriptor = Object.getOwnPropertyDescriptor(value, key);\n } catch (error) {\n throw new CanonicalJsonError('non_plain_object', error);\n }\n if (!descriptor) this.fail('non_plain_object');\n return [key as string, descriptor];\n });\n }\n\n private assertDataProperty(descriptor: PropertyDescriptor): asserts descriptor is PropertyDescriptor & {\n value: unknown;\n } {\n if ('get' in descriptor || 'set' in descriptor) this.fail('accessor_property');\n if (!descriptor.enumerable) this.fail('non_enumerable_property');\n if (!('value' in descriptor)) this.fail('accessor_property');\n }\n\n private withActiveObject(value: object, operation: () => void): void {\n if (this.activeObjects.has(value)) this.fail('cycle');\n this.activeObjects.add(value);\n try {\n operation();\n } finally {\n this.activeObjects.delete(value);\n }\n }\n\n private assertStringBounds(value: string): number {\n if (value.length > this.limits.maxStringCodeUnits) {\n this.fail('max_string_code_units');\n }\n const bytes = strictUtf8ByteLength(value, () => this.fail('invalid_unicode'));\n if (bytes > this.limits.maxStringBytes) {\n this.fail('max_string_bytes');\n }\n return bytes;\n }\n\n private assertMinimumArrayBytes(length: number): void {\n const remaining = this.limits.maxBytes - this.bytes;\n if (length === 0) {\n if (remaining < 2) this.fail('max_bytes');\n return;\n }\n // `[0]` is the shortest non-empty array and every additional value costs\n // at least one comma plus one value byte: 2 * length + 1.\n if (remaining < 1 || length > Math.floor((remaining - 1) / 2)) {\n this.fail('max_bytes');\n }\n }\n\n private addMinimumBytes(current: number, additional: number): number {\n const remaining = this.limits.maxBytes - this.bytes;\n if (current > remaining || additional > remaining - current) this.fail('max_bytes');\n return current + additional;\n }\n\n private consumeNode(): void {\n this.nodes += 1;\n if (this.nodes > this.limits.maxNodes) this.fail('max_nodes');\n }\n\n private append(value: string): void {\n const valueBytes = utf8ByteLength(value);\n if (valueBytes > this.limits.maxBytes - this.bytes) this.fail('max_bytes');\n this.bytes += valueBytes;\n this.chunks.push(value);\n }\n\n private fail(code: CanonicalJsonErrorCode): never {\n throw new CanonicalJsonError(code);\n }\n}\n\nfunction resolveLimits(overrides?: Partial<CanonicalJsonLimits>): CanonicalJsonLimits {\n const limits: CanonicalJsonLimits = { ...DEFAULT_CANONICAL_JSON_LIMITS };\n if (overrides === undefined) return limits;\n if (overrides === null || typeof overrides !== 'object') {\n throw new CanonicalJsonError('invalid_limit');\n }\n let prototype: object | null;\n let keys: Array<string | symbol>;\n try {\n prototype = Object.getPrototypeOf(overrides) as object | null;\n keys = Reflect.ownKeys(overrides);\n } catch (error) {\n throw new CanonicalJsonError('invalid_limit', error);\n }\n if (prototype !== Object.prototype && prototype !== null) {\n throw new CanonicalJsonError('invalid_limit');\n }\n for (const key of keys) {\n if (typeof key !== 'string' || !LIMIT_KEY_SET.has(key)) {\n throw new CanonicalJsonError('invalid_limit');\n }\n let descriptor: PropertyDescriptor | undefined;\n try {\n descriptor = Object.getOwnPropertyDescriptor(overrides, key);\n } catch (error) {\n throw new CanonicalJsonError('invalid_limit', error);\n }\n if (\n !descriptor || 'get' in descriptor || 'set' in descriptor ||\n !descriptor.enumerable || !('value' in descriptor) ||\n !Number.isSafeInteger(descriptor.value) || descriptor.value < 0\n ) {\n throw new CanonicalJsonError('invalid_limit');\n }\n limits[key as keyof CanonicalJsonLimits] = descriptor.value as number;\n }\n return limits;\n}\n\nfunction utf8ByteLength(value: string): number {\n let bytes = 0;\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 0x7f) {\n bytes += 1;\n } else if (code <= 0x7ff) {\n bytes += 2;\n } else if (code >= 0xd800 && code <= 0xdbff) {\n const next = value.charCodeAt(index + 1);\n if (next >= 0xdc00 && next <= 0xdfff) {\n bytes += 4;\n index += 1;\n } else {\n bytes += 3;\n }\n } else {\n bytes += 3;\n }\n }\n return bytes;\n}\n\nfunction strictUtf8ByteLength(value: string, invalidUnicode: () => never): number {\n let bytes = 0;\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 0x7f) {\n bytes += 1;\n } else if (code <= 0x7ff) {\n bytes += 2;\n } else if (code >= 0xd800 && code <= 0xdbff) {\n if (index + 1 >= value.length) invalidUnicode();\n const next = value.charCodeAt(index + 1);\n if (next < 0xdc00 || next > 0xdfff) invalidUnicode();\n bytes += 4;\n index += 1;\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n invalidUnicode();\n } else {\n bytes += 3;\n }\n }\n return bytes;\n}\n","import {\n assertCanonicalChatMessageProjection,\n assertCanonicalConversationEvent,\n type ConversationEvent,\n conversationEventToMessage,\n type ConversationMessageEvent,\n} from '../conversation/events.js';\nimport type { ChatMessage } from '../conversation/types.js';\nimport { canonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type {\n ConversationEventStore,\n ConversationMessageCursor,\n ConversationMessagePage,\n ConversationMessagePageSuccess,\n ConversationMessageWindowResult,\n ConversationMessageWindowSuccess,\n ConversationReadCallOptions,\n ConversationTimelineCompactionEntry,\n ConversationTimelineEntry,\n ConversationTimelinePage,\n ConversationTimelinePageCallOptions,\n ConversationTimelinePageSuccess,\n ConversationTimelineParticipantPreview,\n ConversationTimelineTurnEntry,\n GetConversationMessageWindowAroundOptions,\n GetConversationTimelinePageOptions,\n GetMessagePageOptions,\n} from './ports.js';\n\n/** One shared interactive row ceiling across local, RPC, browser, and native hosts. */\nexport const DEFAULT_MESSAGE_PAGE_SIZE = 50;\nexport const MAX_MESSAGE_PAGE_SIZE = 50;\nexport const MAX_CONVERSATION_TIMELINE_PAGE_SIZE = 50;\n/** Opening or navigating a conversation never transfers a multi-megabyte page. */\nexport const MAX_CONVERSATION_TIMELINE_PAGE_BYTES = 256 * 1_024;\nexport const MAX_CONVERSATION_TIMELINE_PREVIEW_LENGTH = 240;\nexport const MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS = 4;\nexport const MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH = 160;\nexport const MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS_BYTES = 1_024;\nexport const MAX_CONVERSATION_TIMELINE_TURN_ENTRY_BYTES = 1_024;\nexport const MAX_CONVERSATION_MESSAGE_WINDOW_SIZE = 50;\nexport const MAX_CONVERSATION_MESSAGE_WINDOW_BYTES = 256 * 1_024;\n\nexport type ConversationMessageListProjection =\n & Omit<\n ChatMessage,\n 'parts' | 'toolCalls' | 'attachments' | 'reasoning_content'\n >\n & {\n parts?: never;\n toolCalls?: never;\n attachments?: never;\n reasoning_content?: never;\n };\n\nexport interface ConversationMessageDisplayTruncation {\n truncated: true;\n originalCharacterCount: number;\n originalEstimatedBytes: number;\n originalEstimatedRenderRows: number;\n contentTruncated: boolean;\n omittedFields: Array<'parts' | 'toolCalls' | 'attachments' | 'reasoning_content'>;\n capability: 'detail' | 'export';\n}\n\n/**\n * The single portable on-demand/list projector used by storage and RPC hosts.\n * It never retains heavy structured fields, preserves detailRef/agentRunError,\n * and fits the complete canonical projection within the caller's byte budget.\n */\nexport function projectConversationMessageForList(\n message: ChatMessage,\n maximumBytes: number,\n): ConversationMessageListProjection {\n if (!Number.isSafeInteger(maximumBytes) || maximumBytes < 1) {\n throw new Error('invalid_conversation_message_projection_byte_budget');\n }\n const {\n attachments,\n parts,\n reasoning_content: reasoningContent,\n toolCalls,\n ...lightweight\n } = message;\n const omittedFields: ConversationMessageDisplayTruncation['omittedFields'] = [\n ...(parts === undefined ? [] : ['parts' as const]),\n ...(toolCalls === undefined ? [] : ['toolCalls' as const]),\n ...(attachments === undefined ? [] : ['attachments' as const]),\n ...(reasoningContent === undefined ? [] : ['reasoning_content' as const]),\n ];\n const originalBytes = new TextEncoder().encode(message.content).byteLength;\n let originalCharacters = 0;\n for (const _character of message.content) originalCharacters += 1;\n let originalRows = 1;\n for (let index = 0; index < message.content.length; index += 1) {\n if (message.content.charCodeAt(index) === 10) originalRows += 1;\n }\n const marker = (contentTruncated: boolean): ConversationMessageDisplayTruncation => ({\n truncated: true,\n originalCharacterCount: originalCharacters,\n originalEstimatedBytes: originalBytes,\n originalEstimatedRenderRows: originalRows,\n contentTruncated,\n omittedFields,\n capability: 'detail',\n });\n const metadata = omittedFields.length === 0\n ? message.metadata\n : { ...message.metadata, displayTruncation: marker(false) };\n const initial: ConversationMessageListProjection = {\n ...lightweight,\n ...(metadata === undefined ? {} : { metadata }),\n };\n if (conversationMessageProjectionFits(initial, maximumBytes)) return initial;\n\n const agentRunError = message.metadata?.agentRunError;\n const fallbackMetadata = {\n ...(agentRunError === undefined ? {} : { agentRunError }),\n displayTruncation: marker(true),\n };\n const base: ConversationMessageListProjection = {\n ...lightweight,\n content: '',\n metadata: fallbackMetadata,\n };\n if (!conversationMessageProjectionFits(base, maximumBytes)) {\n throw new Error('conversation_message_projection_item_exceeds_byte_budget');\n }\n const encoded = new TextEncoder().encode(message.content);\n let lower = 0;\n let upper = encoded.byteLength;\n let best = '';\n while (lower <= upper) {\n const middle = Math.floor((lower + upper) / 2);\n const content = utf8ProjectionPrefix(encoded, middle);\n const candidate = { ...base, content };\n if (conversationMessageProjectionFits(candidate, maximumBytes)) {\n best = content;\n lower = middle + 1;\n } else {\n upper = middle - 1;\n }\n }\n return { ...base, content: best };\n}\n\nfunction conversationMessageProjectionFits(value: unknown, maximumBytes: number): boolean {\n try {\n canonicalJsonBytes(value, {\n maxBytes: maximumBytes,\n maxDepth: 32,\n maxNodes: 10_000,\n maxStringBytes: maximumBytes,\n maxStringCodeUnits: maximumBytes,\n });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction utf8ProjectionPrefix(encoded: Uint8Array, maximumBytes: number): string {\n const decoder = new TextDecoder('utf-8', { fatal: true });\n for (let end = Math.min(maximumBytes, encoded.byteLength); end >= Math.max(0, maximumBytes - 3); end -= 1) {\n try {\n return decoder.decode(encoded.subarray(0, end));\n } catch {\n // Only a partial trailing code point can fail; UTF-8 code points are at most four bytes.\n }\n }\n return '';\n}\n\nexport function messageCursor(message: ChatMessage): ConversationMessageCursor {\n return {\n timestamp: message.timestamp,\n lamportClock: message.lamportClock,\n originNodeId: message.originNodeId,\n messageId: message.messageId,\n };\n}\n\nexport function compareMessageCursor(\n left: ConversationMessageCursor,\n right: ConversationMessageCursor,\n): number {\n return left.timestamp - right.timestamp ||\n left.lamportClock - right.lamportClock ||\n compareUtf8Text(left.originNodeId, right.originNodeId) ||\n compareUtf8Text(left.messageId, right.messageId);\n}\n\n/**\n * SQLite's default BINARY collation compares UTF-8 bytes. Comparing Unicode\n * code points gives the same order for valid strings and, unlike\n * `localeCompare`, is independent of the host locale.\n */\nfunction compareUtf8Text(left: string, right: string): number {\n const leftIterator = left[Symbol.iterator]();\n const rightIterator = right[Symbol.iterator]();\n for (;;) {\n const leftItem = leftIterator.next();\n const rightItem = rightIterator.next();\n if (leftItem.done || rightItem.done) {\n if (leftItem.done && rightItem.done) return 0;\n return leftItem.done ? -1 : 1;\n }\n const difference = leftItem.value.codePointAt(0)! - rightItem.value.codePointAt(0)!;\n if (difference !== 0) return difference;\n }\n}\n\nexport function normalizeMessagePageLimit(limit: number): number {\n if (!Number.isSafeInteger(limit) || limit <= 0) return DEFAULT_MESSAGE_PAGE_SIZE;\n return Math.min(limit, MAX_MESSAGE_PAGE_SIZE);\n}\n\n/** Read a bounded page from a storage host without any full-history fallback. */\nexport async function readConversationMessagePage(\n storage: ConversationEventStore,\n conversationId: string,\n options: GetMessagePageOptions,\n callOptions: ConversationReadCallOptions = {},\n): Promise<ConversationMessagePage> {\n const normalized = { ...options, limit: normalizeMessagePageLimit(options.limit) };\n assertMessagePageOptions(normalized);\n callOptions.signal?.throwIfAborted();\n const result = await storage.getMessagePage(conversationId, normalized, callOptions);\n callOptions.signal?.throwIfAborted();\n assertConversationMessagePage(result, conversationId, normalized);\n return result;\n}\n\n/** O(n) memory-host helper; persistent hosts select the same window transactionally. */\nexport function buildConversationMessagePage(\n sourceMessages: readonly ChatMessage[],\n conversationId: string,\n options: GetMessagePageOptions,\n currentRevision: string,\n): ConversationMessagePage {\n assertMessagePageOptions(options);\n assertOpaqueTimelineValue(currentRevision, 'revision');\n if (options.expectedRevision !== undefined && options.expectedRevision !== currentRevision) {\n return { reset: true, conversationId, revision: currentRevision };\n }\n const messages = sourceMessages\n .filter(message => message.conversationId === conversationId)\n .sort((left, right) => compareMessageCursor(messageCursor(left), messageCursor(right)));\n let start = 0;\n let end = messages.length;\n if (options.before) {\n const index = messages.findIndex(message => compareMessageCursor(messageCursor(message), options.before!) === 0);\n if (index < 0) return { reset: true, conversationId, revision: currentRevision };\n end = index;\n start = Math.max(0, end - options.limit);\n } else if (options.after) {\n const index = messages.findIndex(message => compareMessageCursor(messageCursor(message), options.after!) === 0);\n if (index < 0) return { reset: true, conversationId, revision: currentRevision };\n start = index + 1;\n end = Math.min(messages.length, start + options.limit);\n } else {\n start = Math.max(0, messages.length - options.limit);\n }\n const projectOnDemand = options.mode === 'on-demand' || options.mode === 'metadata-only';\n let items = messages.slice(start, end).map(message =>\n projectOnDemand\n ? projectConversationMessageForList(message, Math.max(1, options.maxBytes - 4_096))\n : message\n );\n let result = messagePageSuccess(conversationId, currentRevision, messages.length, start, items);\n while (!messageWindowFits(result, options.maxBytes)) {\n if (items.length <= 1) throw new Error('conversation_message_page_exceeds_byte_budget');\n if (options.after) items = items.slice(0, -1);\n else {\n items = items.slice(1);\n start += 1;\n }\n result = messagePageSuccess(conversationId, currentRevision, messages.length, start, items);\n }\n assertConversationMessagePage(result, conversationId, options);\n return result;\n}\n\nfunction messagePageSuccess(\n conversationId: string,\n revision: string,\n total: number,\n start: number,\n items: ChatMessage[],\n): ConversationMessagePageSuccess {\n const first = items[0];\n const last = items.at(-1);\n return {\n reset: false,\n conversationId,\n revision,\n items,\n hasMoreBefore: start > 0,\n hasMoreAfter: start + items.length < total,\n ...(first ? { startCursor: messageCursor(first) } : {}),\n ...(last ? { endCursor: messageCursor(last) } : {}),\n };\n}\n\nfunction assertMessagePageOptions(options: GetMessagePageOptions): void {\n if (\n !options ||\n !Number.isSafeInteger(options.limit) ||\n options.limit < 1 ||\n options.limit > MAX_MESSAGE_PAGE_SIZE ||\n !Number.isSafeInteger(options.maxBytes) ||\n options.maxBytes < 1 ||\n options.maxBytes > MAX_CONVERSATION_MESSAGE_WINDOW_BYTES ||\n (options.before !== undefined && options.after !== undefined)\n ) throw new Error('invalid_conversation_message_page_options');\n if ((options.before || options.after) && options.expectedRevision === undefined) {\n throw new Error('conversation_message_cursor_requires_revision');\n }\n if (options.expectedRevision !== undefined) {\n assertOpaqueTimelineValue(options.expectedRevision, 'expected_revision');\n }\n}\n\nexport function assertConversationMessagePage(\n value: unknown,\n conversationId: string,\n options: GetMessagePageOptions,\n): asserts value is ConversationMessagePage {\n assertMessagePageOptions(options);\n if (!messageWindowFits(value, options.maxBytes) || value === null || typeof value !== 'object') {\n throw new Error('invalid_conversation_message_page');\n }\n const result = value as ConversationMessagePage;\n if (result.conversationId !== conversationId || !isNonEmptyText(result.revision)) {\n throw new Error('invalid_conversation_message_page_scope');\n }\n if (result.reset) {\n assertWindowExactKeys(result, ['reset', 'conversationId', 'revision']);\n if (options.expectedRevision === undefined) {\n throw new Error('invalid_conversation_message_page_reset');\n }\n return;\n }\n assertWindowExactKeys(result, [\n 'reset',\n 'conversationId',\n 'revision',\n 'items',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startCursor',\n 'endCursor',\n ]);\n if (\n result.reset ||\n (options.expectedRevision !== undefined && result.revision !== options.expectedRevision) ||\n !Array.isArray(result.items) ||\n result.items.length > options.limit ||\n typeof result.hasMoreBefore !== 'boolean' ||\n typeof result.hasMoreAfter !== 'boolean'\n ) throw new Error('invalid_conversation_message_page');\n for (let index = 0; index < result.items.length; index += 1) {\n assertWindowMessage(result.items[index], conversationId);\n if (\n index > 0 &&\n compareMessageCursor(messageCursor(result.items[index - 1]), messageCursor(result.items[index])) >= 0\n ) throw new Error('invalid_conversation_message_page_order');\n }\n const first = result.items[0];\n const last = result.items.at(-1);\n if (\n (first && (!result.startCursor || compareMessageCursor(result.startCursor, messageCursor(first)) !== 0)) ||\n (last && (!result.endCursor || compareMessageCursor(result.endCursor, messageCursor(last)) !== 0)) ||\n (!first && (result.startCursor !== undefined || result.endCursor !== undefined ||\n result.hasMoreBefore || result.hasMoreAfter))\n ) throw new Error('invalid_conversation_message_page_cursor');\n}\n\n/** Strict bounded list/live projection; structured heavy fields are detail-only. */\nexport function assertConversationMessageProjection(\n value: unknown,\n conversationId?: string,\n): asserts value is ChatMessage {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('invalid_conversation_message_projection');\n }\n const message = value as ChatMessage;\n assertWindowExactKeys(message, [\n 'messageId',\n 'turnId',\n 'conversationId',\n 'originNodeId',\n 'originSequence',\n 'timestamp',\n 'lamportClock',\n 'role',\n 'content',\n 'detailRef',\n 'contentType',\n 'hidden',\n 'duration',\n 'metadata',\n ]);\n try {\n assertCanonicalChatMessageProjection(message, conversationId);\n } catch (error) {\n throw new Error('invalid_conversation_message_projection', { cause: error });\n }\n}\n\nfunction preview(content: string, maxLength: number): string {\n let lineStart = 0;\n while (lineStart <= content.length) {\n const newline = content.indexOf('\\n', lineStart);\n const lineEnd = newline < 0 ? content.length : newline;\n let start = lineStart;\n while (start < lineEnd && isPreviewWhitespace(content[start])) start += 1;\n let end = lineEnd;\n while (end > start && isPreviewWhitespace(content[end - 1])) end -= 1;\n if (end > start) {\n const length = end - start;\n if (length <= maxLength) return content.slice(start, end);\n if (maxLength === 1) return '…';\n let prefixEnd = start + maxLength - 1;\n const previous = content.charCodeAt(prefixEnd - 1);\n const next = content.charCodeAt(prefixEnd);\n if (\n previous >= 0xD800 && previous <= 0xDBFF &&\n next >= 0xDC00 && next <= 0xDFFF\n ) prefixEnd -= 1;\n return `${content.slice(start, prefixEnd)}…`;\n }\n if (newline < 0) break;\n lineStart = newline + 1;\n }\n return '';\n}\n\nfunction timelineParticipantPreview(\n message: ConversationMessageEvent['message'],\n originNodeId: string,\n requestedPreviewLength: number,\n): ConversationTimelineParticipantPreview {\n if (message.role !== 'assistant' && message.role !== 'agent') {\n throw new Error('invalid_conversation_timeline_participant_role');\n }\n const metadata = message.metadata;\n const actorId = boundedParticipantIdentity(\n metadataText(metadata, 'actorId') ?? metadataText(metadata, 'agentId') ?? originNodeId,\n );\n const actorLabel = boundedParticipantIdentity(\n metadataText(metadata, 'actorLabel') ?? metadataText(metadata, 'agentName') ?? actorId,\n );\n return {\n actorId,\n actorLabel,\n role: message.role,\n preview: preview(\n message.content,\n Math.min(requestedPreviewLength, MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH),\n ),\n };\n}\n\nfunction metadataText(\n metadata: Readonly<Record<string, unknown>> | undefined,\n key: string,\n): string | undefined {\n const value = metadata?.[key];\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction boundedParticipantIdentity(value: string): string {\n return preview(value, 64) || 'unknown';\n}\n\nfunction boundedParticipantPreviewSample(\n responses: readonly ConversationTimelineParticipantPreview[],\n): ConversationTimelineParticipantPreview[] {\n const sample = responses.length <= MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS\n ? [...responses]\n : [...responses.slice(0, 2), ...responses.slice(-2)];\n return sample;\n}\n\nfunction participantPreviewsFit(value: unknown): boolean {\n try {\n canonicalJsonBytes(value, {\n maxBytes: MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS_BYTES,\n maxDepth: 4,\n maxNodes: 64,\n maxStringBytes: MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS_BYTES,\n maxStringCodeUnits: MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS_BYTES,\n });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function boundConversationTimelineTurnEntry(\n source: ConversationTimelineTurnEntry,\n): ConversationTimelineTurnEntry {\n const entry: ConversationTimelineTurnEntry = {\n ...source,\n participantPreviews: source.participantPreviews.map(item => ({\n actorId: preview(item.actorId, MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH),\n actorLabel: preview(item.actorLabel, MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH),\n role: item.role,\n preview: preview(item.preview, MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH),\n })),\n };\n while (\n !timelineTurnEntryFits(entry) &&\n entry.participantPreviews.some(item => item.preview.length > 1)\n ) {\n entry.participantPreviews = entry.participantPreviews.map(item => ({\n ...item,\n preview: preview(item.preview, Math.max(1, Math.floor(item.preview.length / 2))),\n }));\n }\n while (\n !timelineTurnEntryFits(entry) &&\n entry.participantPreviews.some(item => item.actorId.length > 16 || item.actorLabel.length > 16)\n ) {\n entry.participantPreviews = entry.participantPreviews.map(item => ({\n ...item,\n actorId: preview(item.actorId, Math.max(16, Math.floor(item.actorId.length / 2))),\n actorLabel: preview(item.actorLabel, Math.max(16, Math.floor(item.actorLabel.length / 2))),\n }));\n }\n while (!timelineTurnEntryFits(entry) && entry.userPreview.length > 1) {\n entry.userPreview = preview(entry.userPreview, Math.max(1, Math.floor(entry.userPreview.length / 2)));\n }\n if (!timelineTurnEntryFits(entry)) {\n throw new Error('conversation_timeline_turn_entry_exceeds_byte_budget');\n }\n return entry;\n}\n\nfunction timelineTurnEntryFits(value: unknown): boolean {\n try {\n canonicalJsonBytes(value, {\n maxBytes: MAX_CONVERSATION_TIMELINE_TURN_ENTRY_BYTES,\n maxDepth: 6,\n maxNodes: 128,\n maxStringBytes: MAX_CONVERSATION_TIMELINE_TURN_ENTRY_BYTES,\n maxStringCodeUnits: MAX_CONVERSATION_TIMELINE_TURN_ENTRY_BYTES,\n });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction assertTimelineParticipantPreview(value: unknown): asserts value is ConversationTimelineParticipantPreview {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('invalid_conversation_timeline_participant_preview');\n }\n const participant = value as ConversationTimelineParticipantPreview;\n assertExactKeys(participant, ['actorId', 'actorLabel', 'role', 'preview'], 'participant_preview');\n if (\n !isNonEmptyText(participant.actorId) ||\n participant.actorId.length > MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH ||\n !isNonEmptyText(participant.actorLabel) ||\n participant.actorLabel.length > MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH ||\n (participant.role !== 'assistant' && participant.role !== 'agent') ||\n typeof participant.preview !== 'string' ||\n participant.preview.length > MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH\n ) throw new Error('invalid_conversation_timeline_participant_preview');\n}\n\nfunction isPreviewWhitespace(value: string): boolean {\n return value.trim().length === 0;\n}\n\nfunction normalizeTimelinePreviewLength(requested: number | undefined): number {\n return Math.max(\n 1,\n Math.min(\n Number.isSafeInteger(requested) ? requested! : 96,\n MAX_CONVERSATION_TIMELINE_PREVIEW_LENGTH,\n ),\n );\n}\n\n/** Read the required revisioned projection with no getMessages fallback. */\nexport async function readConversationTimelinePage(\n storage: ConversationEventStore,\n conversationId: string,\n options: GetConversationTimelinePageOptions,\n callOptions: ConversationTimelinePageCallOptions = {},\n): Promise<ConversationTimelinePage> {\n assertTimelinePageOptions(options);\n callOptions.signal?.throwIfAborted();\n if (typeof storage.getConversationTimelinePage !== 'function') {\n throw new Error('conversation timeline page reader unavailable');\n }\n const page = await storage.getConversationTimelinePage(conversationId, options, callOptions);\n callOptions.signal?.throwIfAborted();\n assertConversationTimelinePage(page, conversationId, options);\n return page;\n}\n\n/** Explicit full-array builder for memory-only hosts; currentRevision is host-owned. */\nexport function buildConversationTimelinePage(\n sourceEvents: readonly ConversationEvent[],\n conversationId: string,\n options: GetConversationTimelinePageOptions,\n currentRevision: string,\n): ConversationTimelinePage {\n assertTimelinePageOptions(options);\n assertOpaqueTimelineValue(currentRevision, 'revision');\n if (\n options.expectedRevision !== undefined &&\n options.expectedRevision !== currentRevision\n ) return boundedTimelineReset(currentRevision, options.maxBytes);\n\n const materialized = materializeTimeline(\n sourceEvents,\n conversationId,\n normalizeTimelinePreviewLength(options.previewLength),\n );\n const { entries, messageEvents, totalTurns: turnIndex } = materialized;\n const range = timelinePageRange(entries, options);\n if (range === null) return boundedTimelineReset(currentRevision, options.maxBytes);\n let items = entries.slice(range.start, range.end);\n let page = timelineSuccessPage(items, messageEvents.length, turnIndex, entries.length, currentRevision, range);\n while (!timelinePageFits(page, options.maxBytes)) {\n if (items.length === 0) throw new Error('conversation_timeline_page_exceeds_byte_budget');\n items = trimTimelineItems(items, options);\n if (items.length === 0) throw new Error('conversation_timeline_entry_exceeds_byte_budget');\n page = timelineSuccessPage(items, messageEvents.length, turnIndex, entries.length, currentRevision, range);\n }\n assertConversationTimelinePage(page, conversationId, options);\n return page;\n}\n\ninterface MaterializedTimeline {\n events: ConversationEvent[];\n messageEvents: ConversationMessageEvent[];\n entries: ConversationTimelineEntry[];\n totalTurns: number;\n}\n\nfunction materializeTimeline(\n sourceEvents: readonly ConversationEvent[],\n conversationId: string,\n previewLength: number,\n): MaterializedTimeline {\n for (const event of sourceEvents) assertCanonicalConversationEvent(event);\n const events = [...sourceEvents]\n .filter(event => event.conversationId === conversationId)\n .sort(compareTimelineEvents);\n const tombstonedTurnIds = new Set(\n events.filter(event => event.kind === 'tombstone').map(event => event.targetTurnId),\n );\n const messageEvents = events.filter((event): event is ConversationMessageEvent =>\n event.kind === 'message' &&\n event.message.hidden !== true &&\n !tombstonedTurnIds.has(event.message.turnId)\n );\n const visibleMessageEventIds = new Set(messageEvents.map(event => event.eventId));\n const entries: ConversationTimelineEntry[] = [];\n const turnsById = new Map<string, ConversationTimelineTurnEntry>();\n const compactionEventIds = new Set<string>();\n let turnIndex = 0;\n for (const event of events) {\n if (\n event.kind === 'compaction' &&\n event.mode === 'summary' &&\n !tombstonedTurnIds.has(event.summary.turnId) &&\n preview(event.summary.content, previewLength).length > 0\n ) {\n const entry: ConversationTimelineCompactionEntry = {\n kind: 'compaction',\n entryId: event.eventId,\n conversationId,\n timestamp: event.timestamp,\n lamportClock: event.lamportClock,\n originNodeId: event.originNodeId,\n cursor: memoryTimelineCursor(event),\n entryIndex: entries.length,\n turnIndex,\n summaryPreview: preview(event.summary.content, previewLength),\n compactedMessageCount: event.boundary.droppedMessageCount,\n compactedTurnCount: event.boundary.droppedTurnCount,\n };\n entries.push(entry);\n compactionEventIds.add(event.eventId);\n continue;\n }\n if (event.kind !== 'message' || !visibleMessageEventIds.has(event.eventId)) continue;\n const message = event.message;\n if (\n message.role !== 'user' ||\n message.messageId !== message.turnId ||\n turnsById.has(message.turnId)\n ) continue;\n const entry: ConversationTimelineTurnEntry = {\n kind: 'turn',\n entryId: message.messageId,\n messageId: message.messageId,\n conversationId,\n timestamp: event.timestamp,\n lamportClock: event.lamportClock,\n originNodeId: event.originNodeId,\n cursor: memoryTimelineCursor(event),\n entryIndex: entries.length,\n turnIndex,\n turnId: message.turnId,\n userPreview: preview(message.content, previewLength),\n participantPreviews: [],\n responseCount: 0,\n };\n entries.push(entry);\n turnsById.set(message.turnId, entry);\n turnIndex += 1;\n }\n for (const event of messageEvents) {\n const message = event.message;\n if (\n compactionEventIds.has(event.eventId) ||\n (message.role !== 'assistant' && message.role !== 'agent')\n ) continue;\n const entry = turnsById.get(message.turnId);\n if (!entry) continue;\n entry.responseCount += 1;\n entry.participantPreviews.push(timelineParticipantPreview(\n message,\n event.originNodeId,\n previewLength,\n ));\n }\n for (const entry of turnsById.values()) {\n entry.participantPreviews = boundedParticipantPreviewSample(entry.participantPreviews);\n Object.assign(entry, boundConversationTimelineTurnEntry(entry));\n }\n\n return { events, messageEvents, entries, totalTurns: turnIndex };\n}\n\n/** Required single-read wrapper; never composes timeline and message pages client-side. */\nexport async function readConversationMessageWindowAround(\n storage: ConversationEventStore,\n conversationId: string,\n options: GetConversationMessageWindowAroundOptions,\n callOptions: ConversationTimelinePageCallOptions = {},\n): Promise<ConversationMessageWindowResult> {\n assertMessageWindowOptions(options);\n callOptions.signal?.throwIfAborted();\n const result = await storage.getMessageWindowAround(conversationId, options, callOptions);\n callOptions.signal?.throwIfAborted();\n assertConversationMessageWindowResult(result, conversationId, options);\n return result;\n}\n\n/** Explicit O(n) memory-host builder. Persistent hosts use indexed transactional reads. */\nexport function buildConversationMessageWindowAround(\n sourceEvents: readonly ConversationEvent[],\n conversationId: string,\n options: GetConversationMessageWindowAroundOptions,\n currentRevision: string,\n): ConversationMessageWindowResult {\n assertMessageWindowOptions(options);\n assertOpaqueTimelineValue(currentRevision, 'revision');\n if (options.expectedRevision !== currentRevision) {\n const reset = boundedMessageWindowReset(conversationId, currentRevision, options.maxBytes);\n assertConversationMessageWindowResult(reset, conversationId, options);\n return reset;\n }\n const materialized = materializeTimeline(sourceEvents, conversationId, 96);\n const requestedFocus = options.focus;\n const requestedEntry = requestedFocus.kind === 'timeline-entry'\n ? materialized.entries.find(entry => entry.entryId === requestedFocus.entryId && entry.cursor === requestedFocus.cursor)\n : materialized.entries.find(entry =>\n entry.kind === 'turn' &&\n entry.turnId === requestedFocus.turnId &&\n (requestedFocus.cursor === undefined || entry.cursor === requestedFocus.cursor)\n );\n if (!requestedEntry) {\n const reset = boundedMessageWindowReset(conversationId, currentRevision, options.maxBytes);\n assertConversationMessageWindowResult(reset, conversationId, options);\n return reset;\n }\n\n let focus: ConversationMessageWindowSuccess['focus'];\n let anchorTurnId: string | undefined;\n if (requestedEntry.kind === 'turn') {\n anchorTurnId = requestedEntry.turnId;\n focus = {\n kind: 'turn',\n turnId: requestedEntry.turnId,\n ...(options.focus.kind === 'timeline-entry'\n ? { entryId: requestedEntry.entryId, cursor: requestedEntry.cursor }\n : options.focus.cursor === undefined\n ? {}\n : { cursor: requestedEntry.cursor }),\n };\n } else {\n const nearest = nearestTimelineTurn(materialized.entries, requestedEntry.entryIndex);\n anchorTurnId = nearest?.entry.turnId;\n focus = {\n kind: 'compaction',\n entry: requestedEntry,\n ...(nearest\n ? { nearestPosition: nearest.position, nearestTurnId: nearest.entry.turnId }\n : { nearestPosition: 'none' }),\n };\n }\n\n const messages = materialized.messageEvents.map(event =>\n projectConversationMessageForList(\n conversationEventToMessage(event),\n Math.max(1, options.maxBytes - 4_096),\n )\n );\n const anchorIndex = anchorTurnId === undefined\n ? -1\n : messages.findIndex(message => message.turnId === anchorTurnId);\n let start = anchorIndex < 0\n ? 0\n : Math.max(\n 0,\n Math.min(\n anchorIndex - Math.floor(options.maxMessages / 2),\n Math.max(0, messages.length - options.maxMessages),\n ),\n );\n let end = anchorIndex < 0 ? 0 : Math.min(messages.length, start + options.maxMessages);\n let result = messageWindowSuccess(\n conversationId,\n currentRevision,\n focus,\n messages,\n start,\n end,\n );\n while (!messageWindowFits(result, options.maxBytes)) {\n if (end <= start + 1) throw new Error('conversation_message_window_focus_exceeds_byte_budget');\n const distanceBefore = anchorIndex - start;\n const distanceAfter = end - 1 - anchorIndex;\n if (distanceAfter > distanceBefore) end -= 1;\n else start += 1;\n result = messageWindowSuccess(\n conversationId,\n currentRevision,\n focus,\n messages,\n start,\n end,\n );\n }\n assertConversationMessageWindowResult(result, conversationId, options);\n return result;\n}\n\nfunction nearestTimelineTurn(\n entries: readonly ConversationTimelineEntry[],\n focusEntryIndex: number,\n): { entry: ConversationTimelineTurnEntry; position: 'before' | 'after' } | undefined {\n let before: ConversationTimelineTurnEntry | undefined;\n let after: ConversationTimelineTurnEntry | undefined;\n for (let index = focusEntryIndex - 1; index >= 0; index -= 1) {\n const entry = entries[index];\n if (entry?.kind === 'turn') {\n before = entry;\n break;\n }\n }\n for (let index = focusEntryIndex + 1; index < entries.length; index += 1) {\n const entry = entries[index];\n if (entry?.kind === 'turn') {\n after = entry;\n break;\n }\n }\n if (!before) return after ? { entry: after, position: 'after' } : undefined;\n if (!after) return { entry: before, position: 'before' };\n return after.entryIndex - focusEntryIndex <= focusEntryIndex - before.entryIndex\n ? { entry: after, position: 'after' }\n : { entry: before, position: 'before' };\n}\n\nfunction messageWindowSuccess(\n conversationId: string,\n revision: string,\n focus: ConversationMessageWindowSuccess['focus'],\n allMessages: readonly ChatMessage[],\n start: number,\n end: number,\n): ConversationMessageWindowSuccess {\n const items = allMessages.slice(start, end);\n const first = items[0];\n const last = items.at(-1);\n return {\n reset: false,\n conversationId,\n revision,\n focus,\n items,\n hasMoreBefore: start > 0,\n hasMoreAfter: end < allMessages.length,\n ...(first ? { startCursor: messageCursor(first) } : {}),\n ...(last ? { endCursor: messageCursor(last) } : {}),\n };\n}\n\nfunction boundedMessageWindowReset(\n conversationId: string,\n revision: string,\n maxBytes: number,\n): ConversationMessageWindowResult {\n const reset = { reset: true as const, conversationId, revision };\n if (!messageWindowFits(reset, maxBytes)) {\n throw new Error('conversation_message_window_exceeds_byte_budget');\n }\n return reset;\n}\n\nfunction assertMessageWindowOptions(options: GetConversationMessageWindowAroundOptions): void {\n if (\n !options ||\n !Number.isSafeInteger(options.maxMessages) ||\n options.maxMessages < 1 ||\n options.maxMessages > MAX_CONVERSATION_MESSAGE_WINDOW_SIZE\n ) throw new Error('invalid_conversation_message_window_limit');\n if (\n !Number.isSafeInteger(options.maxBytes) ||\n options.maxBytes < 1 ||\n options.maxBytes > MAX_CONVERSATION_MESSAGE_WINDOW_BYTES\n ) throw new Error('invalid_conversation_message_window_byte_budget');\n assertOpaqueTimelineValue(options.expectedRevision, 'expected_revision');\n if (!options.focus || !isNonEmptyText(options.focus.kind)) {\n throw new Error('invalid_conversation_message_window_focus');\n }\n if (options.focus.kind === 'turn') {\n if (!isNonEmptyText(options.focus.turnId)) {\n throw new Error('invalid_conversation_message_window_focus');\n }\n if (options.focus.cursor !== undefined) {\n assertOpaqueTimelineValue(options.focus.cursor, 'focus.cursor');\n }\n return;\n }\n if (\n options.focus.kind !== 'timeline-entry' ||\n !isNonEmptyText(options.focus.entryId)\n ) throw new Error('invalid_conversation_message_window_focus');\n assertOpaqueTimelineValue(options.focus.cursor, 'focus.cursor');\n}\n\nfunction messageWindowFits(value: unknown, maxBytes: number): boolean {\n try {\n canonicalJsonBytes(value, {\n maxBytes,\n maxDepth: 32,\n maxNodes: 100_000,\n maxStringBytes: maxBytes,\n maxStringCodeUnits: maxBytes,\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Strict storage/wire assertion shared by hosts and the device RPC boundary. */\nexport function assertConversationMessageWindowResult(\n value: unknown,\n conversationId: string,\n options: GetConversationMessageWindowAroundOptions,\n): asserts value is ConversationMessageWindowResult {\n assertMessageWindowOptions(options);\n if (!messageWindowFits(value, options.maxBytes)) {\n throw new Error('conversation_message_window_exceeds_byte_budget');\n }\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('invalid_conversation_message_window');\n }\n const result = value as ConversationMessageWindowResult;\n if (result.conversationId !== conversationId) {\n throw new Error('invalid_conversation_message_window_scope');\n }\n assertOpaqueTimelineValue(result.revision, 'message_window_revision');\n if (result.reset) {\n assertWindowExactKeys(result, ['reset', 'conversationId', 'revision']);\n return;\n }\n assertWindowExactKeys(result, [\n 'reset',\n 'conversationId',\n 'revision',\n 'focus',\n 'items',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startCursor',\n 'endCursor',\n ]);\n if (\n result.reset ||\n result.revision !== options.expectedRevision ||\n !Array.isArray(result.items) ||\n result.items.length > options.maxMessages ||\n typeof result.hasMoreBefore !== 'boolean' ||\n typeof result.hasMoreAfter !== 'boolean'\n ) throw new Error('invalid_conversation_message_window');\n const ids = new Set<string>();\n for (let index = 0; index < result.items.length; index += 1) {\n const message = result.items[index];\n assertWindowMessage(message, conversationId);\n if (ids.has(message.messageId)) throw new Error('invalid_conversation_message_window_items');\n ids.add(message.messageId);\n if (\n index > 0 &&\n compareMessageCursor(messageCursor(result.items[index - 1]), messageCursor(message)) >= 0\n ) throw new Error('invalid_conversation_message_window_order');\n }\n const first = result.items[0];\n const last = result.items.at(-1);\n if (\n (first && (!result.startCursor || compareMessageCursor(result.startCursor, messageCursor(first)) !== 0)) ||\n (last && (!result.endCursor || compareMessageCursor(result.endCursor, messageCursor(last)) !== 0)) ||\n (!first && (result.startCursor !== undefined || result.endCursor !== undefined ||\n result.hasMoreBefore || result.hasMoreAfter))\n ) throw new Error('invalid_conversation_message_window_cursor');\n assertResolvedWindowFocus(result, options);\n}\n\nfunction assertResolvedWindowFocus(\n result: ConversationMessageWindowSuccess,\n options: GetConversationMessageWindowAroundOptions,\n): void {\n const focus = result.focus;\n if (focus.kind === 'turn') {\n assertWindowExactKeys(focus, ['kind', 'turnId', 'entryId', 'cursor']);\n if (\n !isNonEmptyText(focus.turnId) ||\n !result.items.some(message => message.turnId === focus.turnId) ||\n (options.focus.kind === 'turn' && (\n focus.turnId !== options.focus.turnId ||\n focus.entryId !== undefined ||\n focus.cursor !== options.focus.cursor\n )) ||\n (options.focus.kind === 'timeline-entry' && (\n focus.entryId !== options.focus.entryId || focus.cursor !== options.focus.cursor\n ))\n ) throw new Error('invalid_conversation_message_window_focus');\n return;\n }\n assertWindowExactKeys(focus, ['kind', 'entry', 'nearestPosition', 'nearestTurnId']);\n if (options.focus.kind !== 'timeline-entry' || focus.kind !== 'compaction') {\n throw new Error('invalid_conversation_message_window_focus');\n }\n const entry = focus.entry;\n assertConversationTimelineCompactionEntry(entry, {\n conversationId: result.conversationId,\n });\n if (\n entry.entryId !== options.focus.entryId ||\n entry.cursor !== options.focus.cursor\n ) throw new Error('invalid_conversation_message_window_compaction');\n if (focus.nearestPosition === 'none') {\n if (focus.nearestTurnId !== undefined || result.items.length !== 0) {\n throw new Error('invalid_conversation_message_window_compaction');\n }\n return;\n }\n if (\n (focus.nearestPosition !== 'before' && focus.nearestPosition !== 'after') ||\n !isNonEmptyText(focus.nearestTurnId) ||\n !result.items.some(message => message.turnId === focus.nearestTurnId)\n ) throw new Error('invalid_conversation_message_window_compaction');\n}\n\n/** Exact standalone compaction-entry validator reused by storage and RPC focus envelopes. */\nexport function assertConversationTimelineCompactionEntry(\n value: unknown,\n options: { conversationId?: string; maximumPreview?: number } = {},\n): asserts value is ConversationTimelineCompactionEntry {\n const page: ConversationTimelinePageSuccess = {\n reset: false,\n items: [],\n revision: 'validation',\n totalMessages: Number.MAX_SAFE_INTEGER,\n totalTurns: Number.MAX_SAFE_INTEGER,\n totalEntries: Number.MAX_SAFE_INTEGER,\n hasMoreBefore: false,\n hasMoreAfter: false,\n };\n assertTimelineEntryShape(\n value,\n page,\n options.maximumPreview ?? MAX_CONVERSATION_TIMELINE_PREVIEW_LENGTH,\n );\n if (\n value.kind !== 'compaction' ||\n (options.conversationId !== undefined && value.conversationId !== options.conversationId)\n ) throw new Error('invalid_conversation_timeline_compaction');\n}\n\nfunction assertWindowMessage(message: ChatMessage, conversationId: string): void {\n try {\n assertCanonicalChatMessageProjection(message, conversationId);\n } catch (error) {\n throw new Error('invalid_conversation_message_window_message', { cause: error });\n }\n}\n\nfunction assertWindowExactKeys(value: object, allowed: readonly string[]): void {\n const keys = Reflect.ownKeys(value);\n if (keys.some(key => typeof key !== 'string' || !allowed.includes(key))) {\n throw new Error('invalid_conversation_message_window');\n }\n}\n\nfunction assertTimelinePageOptions(options: GetConversationTimelinePageOptions): void {\n if (\n !options ||\n !Number.isSafeInteger(options.limit) ||\n options.limit < 1 ||\n options.limit > MAX_CONVERSATION_TIMELINE_PAGE_SIZE\n ) throw new Error('invalid_conversation_timeline_page_limit');\n if (\n !Number.isSafeInteger(options.maxBytes) ||\n options.maxBytes < 1 ||\n options.maxBytes > MAX_CONVERSATION_TIMELINE_PAGE_BYTES\n ) {\n throw new Error('invalid_conversation_timeline_page_byte_budget');\n }\n if (\n options.previewLength !== undefined &&\n (!Number.isSafeInteger(options.previewLength) || options.previewLength < 1)\n ) throw new Error('invalid_conversation_timeline_preview_length');\n const cursors = [options.beforeCursor, options.afterCursor, options.aroundEntryIndex]\n .filter(value => value !== undefined);\n if (cursors.length > 1) throw new Error('conversation_timeline_page_cursor_conflict');\n if (options.beforeCursor !== undefined) assertOpaqueTimelineValue(options.beforeCursor, 'before_cursor');\n if (options.afterCursor !== undefined) assertOpaqueTimelineValue(options.afterCursor, 'after_cursor');\n if (\n (options.beforeCursor !== undefined || options.afterCursor !== undefined) &&\n options.expectedRevision === undefined\n ) throw new Error('conversation_timeline_cursor_requires_revision');\n if (\n options.aroundEntryIndex !== undefined &&\n (!Number.isSafeInteger(options.aroundEntryIndex) || options.aroundEntryIndex < 0)\n ) throw new Error('invalid_conversation_timeline_page_cursor');\n if (options.expectedRevision !== undefined) {\n assertOpaqueTimelineValue(options.expectedRevision, 'expected_revision');\n }\n}\n\nfunction timelinePageRange(\n entries: readonly ConversationTimelineEntry[],\n options: GetConversationTimelinePageOptions,\n): { start: number; end: number } | null {\n if (options.beforeCursor !== undefined) {\n const cursorIndex = entries.findIndex(entry => entry.cursor === options.beforeCursor);\n if (cursorIndex < 0) return null;\n return { start: Math.max(0, cursorIndex - options.limit), end: cursorIndex };\n }\n if (options.afterCursor !== undefined) {\n const cursorIndex = entries.findIndex(entry => entry.cursor === options.afterCursor);\n if (cursorIndex < 0) return null;\n const start = cursorIndex + 1;\n return { start, end: Math.min(entries.length, start + options.limit) };\n }\n if (options.aroundEntryIndex !== undefined) {\n const maximumStart = Math.max(0, entries.length - options.limit);\n const start = Math.max(\n 0,\n Math.min(options.aroundEntryIndex - Math.floor(options.limit / 2), maximumStart),\n );\n return { start, end: Math.min(entries.length, start + options.limit) };\n }\n return {\n start: Math.max(0, entries.length - options.limit),\n end: entries.length,\n };\n}\n\nfunction timelineSuccessPage(\n items: ConversationTimelineEntry[],\n totalMessages: number,\n totalTurns: number,\n totalEntries: number,\n revision: string,\n requestedRange: { start: number; end: number },\n): ConversationTimelinePageSuccess {\n const first = items[0];\n const last = items.at(-1);\n const conceptualStart = first?.entryIndex ?? requestedRange.start;\n const conceptualEnd = last ? last.entryIndex + 1 : requestedRange.end;\n return {\n reset: false,\n items,\n revision,\n totalMessages,\n totalTurns,\n totalEntries,\n hasMoreBefore: conceptualStart > 0,\n hasMoreAfter: conceptualEnd < totalEntries,\n ...(first\n ? { startEntryIndex: first.entryIndex, startCursor: first.cursor }\n : {}),\n ...(last\n ? { endEntryIndex: last.entryIndex, endCursor: last.cursor }\n : {}),\n };\n}\n\nfunction trimTimelineItems(\n items: readonly ConversationTimelineEntry[],\n options: GetConversationTimelinePageOptions,\n): ConversationTimelineEntry[] {\n if (options.afterCursor !== undefined) return items.slice(0, -1);\n if (options.aroundEntryIndex !== undefined && items.length > 1) {\n const firstDistance = Math.abs(items[0].entryIndex - options.aroundEntryIndex);\n const lastDistance = Math.abs(items.at(-1)!.entryIndex - options.aroundEntryIndex);\n return firstDistance > lastDistance ? items.slice(1) : items.slice(0, -1);\n }\n return items.slice(1);\n}\n\nfunction boundedTimelineReset(revision: string, maxBytes: number): ConversationTimelinePage {\n const reset = { reset: true as const, revision };\n if (!timelinePageFits(reset, maxBytes)) {\n throw new Error('conversation_timeline_page_exceeds_byte_budget');\n }\n return reset;\n}\n\nfunction timelinePageFits(page: ConversationTimelinePage, maxBytes: number): boolean {\n try {\n canonicalJsonBytes(page, {\n maxBytes,\n maxDepth: 12,\n maxNodes: 10_000,\n maxStringBytes: maxBytes,\n maxStringCodeUnits: maxBytes,\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Strict storage/wire envelope assertion shared by RPC and persistent hosts. */\nexport function assertConversationTimelinePageEnvelope(\n value: unknown,\n options: Pick<GetConversationTimelinePageOptions, 'limit' | 'maxBytes' | 'previewLength'>,\n): asserts value is ConversationTimelinePage {\n assertTimelinePageOptions({ ...options });\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('invalid_conversation_timeline_page');\n }\n const page = value as ConversationTimelinePage;\n if (!timelinePageFits(page, options.maxBytes)) {\n throw new Error('conversation_timeline_page_exceeds_byte_budget');\n }\n if (page.reset) {\n assertExactKeys(page, ['reset', 'revision'], 'reset');\n assertOpaqueTimelineValue(page.revision, 'revision');\n return;\n }\n assertExactKeys(page, [\n 'reset',\n 'items',\n 'revision',\n 'totalMessages',\n 'totalTurns',\n 'totalEntries',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startEntryIndex',\n 'endEntryIndex',\n 'startCursor',\n 'endCursor',\n ], 'page');\n if (\n page.reset ||\n !Array.isArray(page.items) ||\n page.items.length > options.limit ||\n !Number.isSafeInteger(page.totalMessages) ||\n page.totalMessages < 0 ||\n !Number.isSafeInteger(page.totalTurns) ||\n page.totalTurns < 0 ||\n !Number.isSafeInteger(page.totalEntries) ||\n page.totalEntries < 0 ||\n page.totalTurns > page.totalMessages ||\n typeof page.hasMoreBefore !== 'boolean' ||\n typeof page.hasMoreAfter !== 'boolean'\n ) throw new Error('invalid_conversation_timeline_page');\n assertOpaqueTimelineValue(page.revision, 'revision');\n const maximumPreview = normalizeTimelinePreviewLength(options.previewLength);\n const cursors = new Set<string>();\n let previousEntryIndex = -1;\n let expectedTurnIndex: number | undefined;\n for (const entry of page.items) {\n assertTimelineEntryShape(entry, page, maximumPreview);\n expectedTurnIndex ??= entry.turnIndex;\n if (\n entry.entryIndex <= previousEntryIndex ||\n (previousEntryIndex >= 0 && entry.entryIndex !== previousEntryIndex + 1) ||\n entry.turnIndex !== expectedTurnIndex ||\n cursors.has(entry.cursor)\n ) throw new Error('invalid_conversation_timeline_entry_order');\n previousEntryIndex = entry.entryIndex;\n cursors.add(entry.cursor);\n if (entry.kind === 'turn') expectedTurnIndex += 1;\n }\n assertTimelineBounds(page);\n}\n\n/** Full request-correlated assertion used after a persistent/RPC page read. */\nexport function assertConversationTimelinePage(\n page: unknown,\n conversationId: string,\n options: GetConversationTimelinePageOptions,\n): asserts page is ConversationTimelinePage {\n assertConversationTimelinePageEnvelope(page, options);\n if (page.reset) {\n return;\n }\n if (\n options.expectedRevision !== undefined &&\n page.revision !== options.expectedRevision\n ) throw new Error('conversation_timeline_revision_mismatch');\n for (const entry of page.items) {\n if (entry.conversationId !== conversationId) {\n throw new Error('invalid_conversation_timeline_entry');\n }\n }\n assertTimelineEmptyBoundsForRequest(page, options);\n}\n\nfunction assertTimelineBounds(\n page: ConversationTimelinePageSuccess,\n): void {\n const first = page.items[0];\n const last = page.items.at(-1);\n if (\n page.startEntryIndex !== first?.entryIndex ||\n page.endEntryIndex !== last?.entryIndex ||\n page.startCursor !== first?.cursor ||\n page.endCursor !== last?.cursor ||\n (first && page.hasMoreBefore !== (first.entryIndex > 0)) ||\n (last && page.hasMoreAfter !== (last.entryIndex + 1 < page.totalEntries)) ||\n (!first && (\n page.startEntryIndex !== undefined ||\n page.endEntryIndex !== undefined ||\n page.startCursor !== undefined ||\n page.endCursor !== undefined\n ))\n ) throw new Error('invalid_conversation_timeline_page_bounds');\n}\n\nfunction assertTimelineEmptyBoundsForRequest(\n page: ConversationTimelinePageSuccess,\n options: Pick<GetConversationTimelinePageOptions, 'beforeCursor' | 'afterCursor'>,\n): void {\n if (page.items.length > 0) return;\n const valid = options.beforeCursor !== undefined\n ? !page.hasMoreBefore && page.hasMoreAfter === (page.totalEntries > 0)\n : options.afterCursor !== undefined\n ? page.hasMoreBefore === (page.totalEntries > 0) && !page.hasMoreAfter\n : page.totalEntries === 0 && !page.hasMoreBefore && !page.hasMoreAfter;\n if (!valid) throw new Error('invalid_conversation_timeline_page_bounds');\n}\n\nfunction assertTimelineEntryShape(\n value: unknown,\n page: ConversationTimelinePageSuccess,\n maximumPreview: number,\n): asserts value is ConversationTimelineEntry {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('invalid_conversation_timeline_entry');\n }\n const entry = value as ConversationTimelineEntry;\n const common = [\n 'kind',\n 'entryId',\n 'conversationId',\n 'timestamp',\n 'lamportClock',\n 'originNodeId',\n 'cursor',\n 'entryIndex',\n 'turnIndex',\n ] as const;\n if (entry.kind === 'turn') {\n assertExactKeys(entry, [\n ...common,\n 'messageId',\n 'turnId',\n 'userPreview',\n 'participantPreviews',\n 'responseCount',\n ], 'turn');\n } else if (entry.kind === 'compaction') {\n assertExactKeys(entry, [\n ...common,\n 'summaryPreview',\n 'compactedMessageCount',\n 'compactedTurnCount',\n ], 'compaction');\n } else {\n throw new Error('invalid_conversation_timeline_entry');\n }\n if (\n !isNonEmptyText(entry.conversationId) ||\n !isNonEmptyText(entry.entryId) ||\n !isNonEmptyText(entry.originNodeId) ||\n !Number.isSafeInteger(entry.timestamp) ||\n entry.timestamp < 0 ||\n !Number.isSafeInteger(entry.lamportClock) ||\n entry.lamportClock < 0 ||\n !Number.isSafeInteger(entry.entryIndex) ||\n entry.entryIndex < 0 ||\n entry.entryIndex >= page.totalEntries ||\n !Number.isSafeInteger(entry.turnIndex) ||\n entry.turnIndex < 0 ||\n entry.turnIndex > page.totalTurns\n ) throw new Error('invalid_conversation_timeline_entry');\n assertOpaqueTimelineValue(entry.cursor, 'cursor');\n if (entry.kind === 'turn') {\n if (\n !isNonEmptyText(entry.messageId) ||\n !isNonEmptyText(entry.turnId) ||\n entry.entryId !== entry.messageId ||\n entry.messageId !== entry.turnId ||\n typeof entry.userPreview !== 'string' ||\n entry.userPreview.length > maximumPreview ||\n !Array.isArray(entry.participantPreviews) ||\n entry.participantPreviews.length > MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS ||\n !Number.isSafeInteger(entry.responseCount) ||\n entry.responseCount < entry.participantPreviews.length ||\n !participantPreviewsFit(entry.participantPreviews) ||\n !timelineTurnEntryFits(entry)\n ) throw new Error('invalid_conversation_timeline_turn');\n for (const participant of entry.participantPreviews) {\n assertTimelineParticipantPreview(participant);\n }\n return;\n }\n if (\n entry.kind !== 'compaction' ||\n entry.entryId.length === 0 ||\n typeof entry.summaryPreview !== 'string' ||\n entry.summaryPreview.length === 0 ||\n entry.summaryPreview.length > maximumPreview ||\n !Number.isSafeInteger(entry.compactedMessageCount) ||\n entry.compactedMessageCount < 0 ||\n !Number.isSafeInteger(entry.compactedTurnCount) ||\n entry.compactedTurnCount < 0\n ) throw new Error('invalid_conversation_timeline_compaction');\n}\n\nfunction assertExactKeys(\n value: object,\n allowed: readonly string[],\n kind: string,\n): void {\n const keys = Reflect.ownKeys(value);\n if (\n keys.some(key => typeof key !== 'string' || !allowed.includes(key)) ||\n allowed.some(key => {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n return descriptor !== undefined && (!descriptor.enumerable || !('value' in descriptor));\n })\n ) throw new Error(`invalid_conversation_timeline_${kind}`);\n}\n\nfunction memoryTimelineCursor(event: ConversationEvent): string {\n return `timeline-v2:${encodeURIComponent(event.originNodeId)}:${event.originSequence}:${encodeURIComponent(event.eventId)}`;\n}\n\nfunction compareTimelineEvents(left: ConversationEvent, right: ConversationEvent): number {\n return left.timestamp - right.timestamp ||\n left.lamportClock - right.lamportClock ||\n compareUtf8Text(left.originNodeId, right.originNodeId) ||\n compareUtf8Text(left.eventId, right.eventId);\n}\n\nfunction assertOpaqueTimelineValue(value: unknown, field: string): asserts value is string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.length > 2_048 ||\n value !== value.trim() ||\n hasAsciiControlToken(value)\n ) throw new Error(`invalid_conversation_timeline_${field}`);\n}\n\nfunction hasAsciiControlToken(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) return true;\n }\n return false;\n}\n\nfunction isNonEmptyText(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n","import { compareMessageCursor, messageCursor } from '../storage/conversationPaging.js';\nimport type { ChatMessage } from './types.js';\n\nexport const CONTEXT_COMPACTION_METADATA_KEY = 'contextCompaction';\n\n/** Durable, gap-safe semantic coverage for an append-only distributed log. */\nexport interface ContextCompactionBoundaryV2 {\n version: 2;\n /** Highest contiguous originSequence summarized for each origin. */\n coveredVersion: Record<string, number>;\n /** Exact visible message membership below each per-origin frontier. */\n coveredMessageCountByOrigin: Record<string, number>;\n /** Exact user-rooted turn membership below each per-origin frontier. */\n coveredUserTurnCountByOrigin: Record<string, number>;\n droppedMessageCount: number;\n droppedTurnCount: number;\n previousSummaryMessageIds?: string[];\n}\n\nexport interface ContextCompactionCoverage {\n coveredVersion: Record<string, number>;\n coveredMessageCountByOrigin: Record<string, number>;\n coveredUserTurnCountByOrigin: Record<string, number>;\n}\n\n/**\n * Content-free progress for one bounded compaction slice. Hosts may persist or\n * display this value and use it to schedule a later background slice without\n * receiving any conversation content.\n */\nexport interface ContextCompactionProgress {\n readonly checkpointRevision?: string;\n readonly processedMessages: number;\n readonly remainingEstimate?: number;\n readonly providerCalls: number;\n readonly workPages: number;\n}\n\nconst MAX_PREVIOUS_SUMMARY_IDS = 32;\n\nfunction isCoveredVersion(value: unknown): value is Record<string, number> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n return Object.values(value).every(sequence => typeof sequence === 'number' && Number.isSafeInteger(sequence) && sequence > 0);\n}\n\nfunction isCountMap(value: unknown): value is Record<string, number> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n return Object.values(value).every(count => typeof count === 'number' && Number.isSafeInteger(count) && count >= 0);\n}\n\nfunction sumCounts(counts: Readonly<Record<string, number>>): number {\n return Object.values(counts).reduce((total, count) => total + count, 0);\n}\n\nexport function isContextCompactionBoundaryV2(\n value: unknown,\n): value is ContextCompactionBoundaryV2 {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const boundary = value as Partial<ContextCompactionBoundaryV2> & Record<string, unknown>;\n const allowedKeys = new Set([\n 'version',\n 'coveredVersion',\n 'coveredMessageCountByOrigin',\n 'coveredUserTurnCountByOrigin',\n 'droppedMessageCount',\n 'droppedTurnCount',\n 'previousSummaryMessageIds',\n ]);\n if (Object.keys(boundary).some(key => !allowedKeys.has(key))) return false;\n if (\n boundary.version !== 2 ||\n !isCoveredVersion(boundary.coveredVersion) ||\n Object.keys(boundary.coveredVersion).length === 0 ||\n !isCountMap(boundary.coveredMessageCountByOrigin) ||\n !isCountMap(boundary.coveredUserTurnCountByOrigin)\n ) return false;\n const origins = new Set(Object.keys(boundary.coveredVersion));\n if (\n Object.keys(boundary.coveredMessageCountByOrigin).some(origin => !origins.has(origin)) ||\n Object.keys(boundary.coveredUserTurnCountByOrigin).some(origin => !origins.has(origin)) ||\n Object.entries(boundary.coveredUserTurnCountByOrigin).some(([origin, count]) => count > (boundary.coveredMessageCountByOrigin?.[origin] ?? 0))\n ) return false;\n const messageCount = sumCounts(boundary.coveredMessageCountByOrigin);\n const turnCount = sumCounts(boundary.coveredUserTurnCountByOrigin);\n if (\n messageCount < 0 ||\n boundary.droppedMessageCount !== messageCount ||\n boundary.droppedTurnCount !== turnCount\n ) return false;\n const previous = boundary.previousSummaryMessageIds;\n return previous === undefined ||\n Array.isArray(previous) &&\n previous.length > 0 &&\n previous.length <= MAX_PREVIOUS_SUMMARY_IDS &&\n new Set(previous).size === previous.length &&\n previous.every(id => typeof id === 'string' && id.length > 0 && id.length <= 256);\n}\n\nexport function getContextCompactionBoundary(\n message: ChatMessage,\n): ContextCompactionBoundaryV2 | undefined {\n const value = message.metadata?.[CONTEXT_COMPACTION_METADATA_KEY];\n return isContextCompactionBoundaryV2(value) ? value : undefined;\n}\n\nexport function isContextCompactionSummary(message: ChatMessage): boolean {\n return getContextCompactionBoundary(message) !== undefined;\n}\n\nfunction coverageDominates(left: Record<string, number>, right: Record<string, number>): boolean {\n return Object.entries(right).every(([originNodeId, sequence]) => (left[originNodeId] ?? 0) >= sequence);\n}\n\nfunction mergeCoverage(boundaries: readonly ContextCompactionBoundaryV2[]): Record<string, number> {\n const merged: Record<string, number> = {};\n for (const boundary of boundaries) {\n for (const [originNodeId, sequence] of Object.entries(boundary.coveredVersion)) {\n merged[originNodeId] = Math.max(merged[originNodeId] ?? 0, sequence);\n }\n }\n return merged;\n}\n\nfunction mergeExactCoverage(\n boundaries: readonly ContextCompactionBoundaryV2[],\n): ContextCompactionCoverage {\n const result: ContextCompactionCoverage = {\n coveredVersion: {},\n coveredMessageCountByOrigin: {},\n coveredUserTurnCountByOrigin: {},\n };\n for (const boundary of boundaries) {\n for (const [origin, sequence] of Object.entries(boundary.coveredVersion)) {\n const previousSequence = result.coveredVersion[origin] ?? 0;\n const nextMessageCount = boundary.coveredMessageCountByOrigin[origin] ?? 0;\n const nextTurnCount = boundary.coveredUserTurnCountByOrigin[origin] ?? 0;\n if (sequence < previousSequence) continue;\n if (sequence === previousSequence && sequence > 0) {\n if (\n nextMessageCount !== (result.coveredMessageCountByOrigin[origin] ?? 0) ||\n nextTurnCount !== (result.coveredUserTurnCountByOrigin[origin] ?? 0)\n ) throw new Error(`conflicting compaction counts for ${origin}@${sequence}`);\n continue;\n }\n result.coveredVersion[origin] = sequence;\n result.coveredMessageCountByOrigin[origin] = nextMessageCount;\n result.coveredUserTurnCountByOrigin[origin] = nextTurnCount;\n }\n }\n return result;\n}\n\nexport function contextCompactionCoverageFromSummaries(\n summaries: readonly ChatMessage[],\n): ContextCompactionCoverage {\n const boundaries = summaries.map(summary => {\n const boundary = getContextCompactionBoundary(summary);\n if (!boundary) throw new Error(`message ${summary.messageId} is not a v2 compaction summary`);\n return boundary;\n });\n return mergeExactCoverage(boundaries);\n}\n\nexport function createContextCompactionBoundaryFromCoverage(\n coverage: ContextCompactionCoverage,\n previousSummaryMessageIds: readonly string[] = [],\n): ContextCompactionBoundaryV2 {\n // Provenance is diagnostic, while coverage is the semantic truth. Concurrent\n // devices can legitimately produce more summaries than fit in one event, so\n // keep a deterministic bounded sample instead of making compaction wedge.\n const uniquePrevious = [...new Set(previousSummaryMessageIds)].sort().slice(0, MAX_PREVIOUS_SUMMARY_IDS);\n const boundary: ContextCompactionBoundaryV2 = {\n version: 2,\n coveredVersion: { ...coverage.coveredVersion },\n coveredMessageCountByOrigin: { ...coverage.coveredMessageCountByOrigin },\n coveredUserTurnCountByOrigin: { ...coverage.coveredUserTurnCountByOrigin },\n droppedMessageCount: sumCounts(coverage.coveredMessageCountByOrigin),\n droppedTurnCount: sumCounts(coverage.coveredUserTurnCountByOrigin),\n ...(uniquePrevious.length > 0 ? { previousSummaryMessageIds: uniquePrevious } : {}),\n };\n if (!isContextCompactionBoundaryV2(boundary)) {\n throw new Error('invalid exact compaction coverage');\n }\n return boundary;\n}\n\n/**\n * Project the audit log into model context. A dominating summary replaces the\n * summaries it semantically includes. Concurrent incomparable summaries are\n * both retained until a later compaction explicitly merges their contents.\n */\nexport function effectiveConversationHistory(messages: readonly ChatMessage[]): ChatMessage[] {\n const summaries = messages.filter(isContextCompactionSummary);\n if (summaries.length === 0) return [...messages];\n const retainedSummaries = summaries.filter(candidate => {\n const candidateBoundary = getContextCompactionBoundary(candidate)!;\n return !summaries.some(other => {\n if (other.messageId === candidate.messageId) return false;\n const otherBoundary = getContextCompactionBoundary(other)!;\n if (!coverageDominates(otherBoundary.coveredVersion, candidateBoundary.coveredVersion)) {\n return false;\n }\n const equivalent = coverageDominates(\n candidateBoundary.coveredVersion,\n otherBoundary.coveredVersion,\n );\n return !equivalent || compareMessageCursor(messageCursor(candidate), messageCursor(other)) < 0;\n });\n }).sort((left, right) => compareMessageCursor(messageCursor(left), messageCursor(right)));\n const coveredVersion = mergeCoverage(\n retainedSummaries.map(summary => getContextCompactionBoundary(summary)!),\n );\n const tail = messages.filter(message => {\n if (isContextCompactionSummary(message)) return false;\n const sequence = message.originSequence;\n if (typeof sequence !== 'number' || !Number.isSafeInteger(sequence) || sequence <= 0) {\n return true;\n }\n return sequence > (coveredVersion[message.originNodeId] ?? 0);\n });\n return [...retainedSummaries, ...tail];\n}\n\nexport function createContextCompactionBoundary(\n dropped: readonly ChatMessage[],\n): ContextCompactionBoundaryV2 | undefined {\n if (dropped.length === 0) return undefined;\n const previousSummaries = dropped.filter(isContextCompactionSummary);\n const previousBoundaries = previousSummaries.map(summary => getContextCompactionBoundary(summary)!);\n const coverage = mergeExactCoverage(previousBoundaries);\n const coveredVersion = coverage.coveredVersion;\n const previousVersion = { ...coveredVersion };\n const candidates = new Map<string, Set<number>>();\n for (const message of dropped) {\n if (isContextCompactionSummary(message)) continue;\n const sequence = message.originSequence;\n if (typeof sequence !== 'number' || !Number.isSafeInteger(sequence) || sequence <= 0) continue;\n const sequences = candidates.get(message.originNodeId) ?? new Set<number>();\n sequences.add(sequence);\n candidates.set(message.originNodeId, sequences);\n }\n for (const [originNodeId, sequences] of candidates) {\n let frontier = coveredVersion[originNodeId] ?? 0;\n while (sequences.has(frontier + 1)) frontier += 1;\n if (frontier > 0) coveredVersion[originNodeId] = frontier;\n }\n if (Object.keys(coveredVersion).length === 0) return undefined;\n\n const newlyCovered = dropped.filter(message => {\n if (isContextCompactionSummary(message)) return false;\n const sequence = message.originSequence;\n return typeof sequence === 'number' &&\n sequence > (previousVersion[message.originNodeId] ?? 0) &&\n sequence <= (coveredVersion[message.originNodeId] ?? 0);\n });\n for (const message of newlyCovered) {\n coverage.coveredMessageCountByOrigin[message.originNodeId] = (coverage.coveredMessageCountByOrigin[message.originNodeId] ?? 0) + 1;\n if (message.role === 'user') {\n coverage.coveredUserTurnCountByOrigin[message.originNodeId] = (coverage.coveredUserTurnCountByOrigin[message.originNodeId] ?? 0) + 1;\n }\n }\n return createContextCompactionBoundaryFromCoverage(\n coverage,\n previousSummaries.map(summary => summary.messageId),\n );\n}\n","import { canonicalJsonBytes, CanonicalJsonError } from '../encoding/canonicalJson.js';\nimport { type ContextCompactionBoundaryV2, isContextCompactionBoundaryV2 } from './compactionBoundary.js';\nimport type { AttachmentReference, ChatMessage, ChatMessagePart, ChatRole, DetailReference, ToolCall } from './types.js';\n\n/** 15 MiB leaves one MiB for sync/RPC framing under the 16 MiB frame ceiling. */\nexport const MAX_CONVERSATION_EVENT_BYTES = 15 * 1024 * 1024;\nconst MAX_CONVERSATION_EVENT_NODES = 200_000;\n\n/** Frozen wire/storage limits shared by every canonical event ingress. */\nexport const CONVERSATION_EVENT_LIMITS = Object.freeze(\n {\n identifierBytes: 512,\n referenceBytes: 2_048,\n sourceStringBytes: 512,\n titleBytes: 64 * 1_024,\n textBytes: 8 * 1_024 * 1_024,\n metadataStringBytes: 1 * 1_024 * 1_024,\n metadataKeyBytes: 512,\n metadataDepth: 16,\n metadataKeysPerObject: 256,\n metadataArrayItems: 4_096,\n messageParts: 2_048,\n toolCalls: 256,\n attachments: 256,\n compactionOrigins: 4_096,\n filenameBytes: 1_024,\n mimeTypeBytes: 256,\n attachmentBytes: 64 * 1_024 * 1_024,\n } as const,\n);\n\nconst ATTACHMENT_CONTENT_HASH_PATTERN = /^sha256:[\\da-f]{64}$/;\nconst MIME_TYPE_PATTERN = /^[!#$%&'*+.^_`|~\\dA-Za-z-]+\\/[!#$%&'*+.^_`|~\\dA-Za-z-]+$/;\nconst utf8Encoder = new TextEncoder();\n\nexport interface ConversationEventBase {\n eventId: string;\n conversationId: string;\n originNodeId: string;\n /** Contiguous, atomically allocated in the conversation+origin domain. */\n originSequence: number;\n lamportClock: number;\n timestamp: number;\n}\n\nexport interface ConversationMessagePayload {\n messageId: string;\n turnId: string;\n role: ChatRole;\n content: string;\n parts?: ChatMessagePart[];\n toolCalls?: ToolCall[];\n attachments?: ChatMessage['attachments'];\n detailRef?: DetailReference;\n reasoning_content?: string;\n contentType?: string;\n hidden?: boolean;\n duration?: number | null;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ConversationMessageEvent extends ConversationEventBase {\n kind: 'message';\n message: ConversationMessagePayload;\n}\n\nexport interface ConversationTombstoneEvent extends ConversationEventBase {\n kind: 'tombstone';\n targetTurnId: string;\n reason?: 'user-delete' | 'retention' | 'redaction';\n digest?: string;\n}\n\nexport interface ConversationCompactionSummaryEvent extends ConversationEventBase {\n kind: 'compaction';\n mode: 'summary';\n boundary: ContextCompactionBoundaryV2;\n summary: {\n turnId: string;\n content: string;\n parts?: Array<Exclude<ChatMessagePart, { type: 'attachment' }>>;\n };\n}\n\n/** Causal coverage checkpoint with no semantic text or ChatMessage projection. */\nexport interface ConversationCompactionCoverageEvent extends ConversationEventBase {\n kind: 'compaction';\n mode: 'coverage-only';\n boundary: ContextCompactionBoundaryV2;\n summary: null;\n}\n\nexport type ConversationCompactionEvent =\n | ConversationCompactionSummaryEvent\n | ConversationCompactionCoverageEvent;\n\nexport interface ConversationMetadataPatchFields {\n title?: string;\n definitionId?: string;\n instanceDelta?: Record<string, unknown>;\n isUserInitiated?: boolean;\n sourceChannel?: {\n channelId: string;\n platform: string;\n imUserId: string;\n } | null;\n}\n\nexport interface ConversationMetadataPatchEvent extends ConversationEventBase {\n kind: 'metadataPatch';\n patch: ConversationMetadataPatchFields;\n}\n\nexport type ConversationEvent =\n | ConversationMessageEvent\n | ConversationTombstoneEvent\n | ConversationCompactionEvent\n | ConversationMetadataPatchEvent;\n\ntype WithoutAssignedIdentity<Event extends ConversationEvent> = Omit<\n Event,\n 'originSequence' | 'lamportClock'\n>;\n\nexport type ConversationEventDraft = ConversationEvent extends infer Event ? Event extends ConversationEvent ? WithoutAssignedIdentity<Event>\n : never\n : never;\n\nexport interface ConversationEventCursor {\n originNodeId: string;\n originSequence: number;\n eventId: string;\n}\n\nexport function conversationEventToMessage(event: ConversationMessageEvent): ChatMessage {\n return {\n ...event.message,\n conversationId: event.conversationId,\n originNodeId: event.originNodeId,\n originSequence: event.originSequence,\n lamportClock: event.lamportClock,\n timestamp: event.timestamp,\n };\n}\n\nexport function messageToConversationEvent(message: ChatMessage): ConversationMessageEvent {\n const {\n messageId,\n turnId,\n conversationId,\n originNodeId,\n originSequence,\n lamportClock,\n timestamp,\n ...payload\n } = message;\n return {\n eventId: messageId,\n conversationId,\n originNodeId,\n originSequence,\n lamportClock,\n timestamp,\n kind: 'message',\n message: { messageId, turnId, ...payload },\n };\n}\n\n/** Strict shared validator for message projections returned by storage/RPC hosts. */\nexport function assertCanonicalChatMessageProjection(\n value: unknown,\n conversationId?: string,\n): asserts value is ChatMessage {\n try {\n canonicalJsonBytes(value, {\n maxDepth: 64,\n maxNodes: MAX_CONVERSATION_EVENT_NODES,\n maxStringCodeUnits: MAX_CONVERSATION_EVENT_BYTES,\n maxStringBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxBytes: MAX_CONVERSATION_EVENT_BYTES,\n });\n const event = normalizeCanonicalConversationEvent(messageToConversationEvent(value as ChatMessage));\n if (\n event.kind !== 'message' ||\n (conversationId !== undefined && event.conversationId !== conversationId)\n ) {\n throw new Error('invalid canonical chat message projection scope');\n }\n } catch (error) {\n throw new Error('invalid canonical chat message projection', { cause: error });\n }\n}\n\n/** Binary bodies are referenced only by message events, never control events. */\nexport function conversationEventAttachmentReferences(\n event: ConversationEvent,\n): AttachmentReference[] {\n if (event.kind !== 'message') return [];\n const references = new Map<string, AttachmentReference>();\n for (const reference of event.message.attachments ?? []) {\n references.set(reference.contentHash, reference);\n }\n for (const part of event.message.parts ?? []) {\n if (part.type === 'attachment') {\n references.set(part.attachment.contentHash, part.attachment);\n }\n }\n return [...references.values()];\n}\n\nexport function isConversationEvent(value: unknown): value is ConversationEvent {\n if (!isEventBase(value)) return false;\n const event = value as ConversationEvent & Record<string, unknown>;\n switch (event.kind) {\n case 'message':\n return hasOnlyKeys(event, [...eventBaseKeys, 'kind', 'message']) &&\n isMessagePayload(event.message) && event.eventId === event.message.messageId;\n case 'tombstone':\n return hasOnlyKeys(event, [...eventBaseKeys, 'kind', 'targetTurnId', 'reason', 'digest']) &&\n isIdentifier(event.targetTurnId) &&\n (event.reason === undefined ||\n event.reason === 'user-delete' || event.reason === 'retention' || event.reason === 'redaction') &&\n (event.digest === undefined || isBoundedSourceString(event.digest, true));\n case 'compaction':\n return hasOnlyKeys(event, [...eventBaseKeys, 'kind', 'mode', 'boundary', 'summary']) &&\n isContextCompactionBoundaryV2(event.boundary) &&\n isCompactionBoundaryWithinEventLimits(event.boundary) &&\n (event.mode === 'coverage-only' && event.summary === null ||\n event.mode === 'summary' && isCompactionSummary(event.summary));\n case 'metadataPatch':\n return hasOnlyKeys(event, [...eventBaseKeys, 'kind', 'patch']) &&\n isMetadataPatch(event.patch);\n default:\n return false;\n }\n}\n\n/**\n * Validate the exact event schema and its deep JSON graph before a storage or\n * sync boundary. Known optional schema fields explicitly set to `undefined`\n * are normalized as absent; arbitrary metadata/tool arguments remain strict.\n */\nexport function assertCanonicalConversationEvent(\n value: unknown,\n): asserts value is ConversationEvent {\n normalizeCanonicalConversationEvent(value);\n}\n\n/**\n * Return the exact schema-normalized event that must cross a storage boundary.\n * Callers must persist/project/return this value rather than the pre-validation\n * input so known optional `undefined` fields cannot diverge across hosts.\n */\nexport function normalizeCanonicalConversationEvent(value: unknown): ConversationEvent {\n let normalized: unknown;\n try {\n normalized = normalizeKnownOptionalEventFields(value);\n canonicalJsonBytes(normalized, {\n maxDepth: 64,\n maxNodes: MAX_CONVERSATION_EVENT_NODES,\n maxStringCodeUnits: MAX_CONVERSATION_EVENT_BYTES,\n maxStringBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxBytes: MAX_CONVERSATION_EVENT_BYTES,\n });\n } catch (error) {\n throw new Error('invalid canonical conversation event', { cause: error });\n }\n if (!isConversationEvent(normalized)) {\n throw new Error('invalid canonical conversation event schema');\n }\n return normalized;\n}\n\n/** Validate an entire remote/local batch before the caller starts a transaction. */\nexport function assertCanonicalConversationEvents(\n values: readonly unknown[],\n): asserts values is readonly ConversationEvent[] {\n for (const value of values) assertCanonicalConversationEvent(value);\n}\n\n/** Normalize a complete batch before any member is projected or persisted. */\nexport function normalizeCanonicalConversationEvents(\n values: readonly unknown[],\n): ConversationEvent[] {\n return values.map(value => normalizeCanonicalConversationEvent(value));\n}\n\n/**\n * Validate a local draft before opening a write transaction or allocating a\n * causal sequence. Worst-case safe-integer coordinates reserve enough bytes\n * for every value the allocator may assign later.\n */\nexport function assertCanonicalConversationEventDraft(\n value: unknown,\n): asserts value is ConversationEventDraft {\n const normalized = normalizeKnownOptionalEventFields(value);\n if (\n !isPlainObject(normalized) ||\n Object.hasOwn(normalized, 'originSequence') ||\n Object.hasOwn(normalized, 'lamportClock')\n ) {\n throw new Error('invalid canonical conversation event draft schema');\n }\n const candidate = Object.assign(Object.create(null) as Record<string, unknown>, normalized, {\n originSequence: Number.MAX_SAFE_INTEGER,\n lamportClock: Number.MAX_SAFE_INTEGER,\n });\n assertCanonicalConversationEvent(candidate);\n}\n\nexport function assertCanonicalConversationEventDrafts(\n values: readonly unknown[],\n): asserts values is readonly ConversationEventDraft[] {\n for (const value of values) assertCanonicalConversationEventDraft(value);\n}\n\n/** Canonical conflict/digest bytes using the same normalization as the boundary validator. */\nexport function canonicalConversationEventBytes(value: unknown): Uint8Array {\n const normalized = normalizeCanonicalConversationEvent(value);\n return canonicalJsonBytes(normalized, {\n maxDepth: 64,\n maxNodes: MAX_CONVERSATION_EVENT_NODES,\n maxStringCodeUnits: MAX_CONVERSATION_EVENT_BYTES,\n maxStringBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxBytes: MAX_CONVERSATION_EVENT_BYTES,\n });\n}\n\nfunction isEventBase(value: unknown): value is ConversationEventBase & { kind: unknown } {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const event = value as Partial<ConversationEventBase> & { kind?: unknown };\n return isIdentifier(event.eventId) &&\n isIdentifier(event.conversationId) &&\n isIdentifier(event.originNodeId) &&\n typeof event.originSequence === 'number' && Number.isSafeInteger(event.originSequence) &&\n event.originSequence > 0 && typeof event.lamportClock === 'number' &&\n Number.isSafeInteger(event.lamportClock) && event.lamportClock > 0 &&\n typeof event.timestamp === 'number' &&\n Number.isSafeInteger(event.timestamp) && event.timestamp >= 0 && typeof event.kind === 'string';\n}\n\nfunction normalizeKnownOptionalEventFields(value: unknown): unknown {\n const event = copyOptionalRecord(value, eventOptionalFields(value));\n if (!isPlainObject(event)) return event;\n if (event.kind === 'message') {\n event.message = normalizeMessagePayload(event.message);\n } else if (event.kind === 'compaction') {\n if (event.mode === 'summary') event.summary = normalizeCompactionSummary(event.summary);\n } else if (event.kind === 'metadataPatch') {\n event.patch = normalizeMetadataPatch(event.patch);\n }\n return event;\n}\n\nfunction eventOptionalFields(value: unknown): ReadonlySet<string> {\n const kind = safeDataProperty(value, 'kind');\n return kind === 'tombstone' ? new Set(['reason', 'digest']) : new Set();\n}\n\nfunction normalizeMessagePayload(value: unknown): unknown {\n const message = copyOptionalRecord(\n value,\n new Set([\n 'parts',\n 'toolCalls',\n 'attachments',\n 'detailRef',\n 'reasoning_content',\n 'contentType',\n 'hidden',\n 'duration',\n 'metadata',\n ]),\n );\n if (!isPlainObject(message)) return message;\n if (message.parts !== undefined) {\n message.parts = normalizeArray(message.parts, normalizeMessagePartOptionals);\n }\n if (message.detailRef !== undefined) {\n message.detailRef = normalizeDetailReference(message.detailRef);\n }\n return message;\n}\n\nfunction normalizeMessagePartOptionals(value: unknown): unknown {\n const type = safeDataProperty(value, 'type');\n if (type !== 'tool-result') return copyOptionalRecord(value, new Set());\n const part = copyOptionalRecord(\n value,\n new Set([\n 'toolCallId',\n 'parameters',\n 'isError',\n 'payload',\n 'detailRef',\n ]),\n );\n if (isPlainObject(part) && part.detailRef !== undefined) {\n part.detailRef = normalizeDetailReference(part.detailRef);\n }\n return part;\n}\n\nfunction normalizeDetailReference(value: unknown): unknown {\n return copyOptionalRecord(\n value,\n new Set([\n 'runId',\n 'conversationId',\n 'sessionId',\n 'nodeId',\n 'fileUri',\n 'exitCode',\n 'resourceVersion',\n ]),\n );\n}\n\nfunction normalizeCompactionSummary(value: unknown): unknown {\n const summary = copyOptionalRecord(value, new Set(['parts']));\n if (isPlainObject(summary) && summary.parts !== undefined) {\n summary.parts = normalizeArray(summary.parts, normalizeMessagePartOptionals);\n }\n return summary;\n}\n\nfunction normalizeMetadataPatch(value: unknown): unknown {\n return copyOptionalRecord(\n value,\n new Set([\n 'title',\n 'definitionId',\n 'instanceDelta',\n 'isUserInitiated',\n 'sourceChannel',\n ]),\n );\n}\n\nfunction copyOptionalRecord(value: unknown, optional: ReadonlySet<string>): unknown {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return value;\n let prototype: object | null;\n let keys: Array<string | symbol>;\n try {\n prototype = Object.getPrototypeOf(value) as object | null;\n keys = Reflect.ownKeys(value);\n } catch (error) {\n throw new CanonicalJsonError('non_plain_object', error);\n }\n if (prototype !== Object.prototype && prototype !== null) return value;\n if (keys.length > MAX_CONVERSATION_EVENT_NODES) {\n throw new CanonicalJsonError('max_nodes');\n }\n const copy = Object.create(null) as Record<string, unknown>;\n for (const key of keys) {\n if (typeof key === 'symbol') throw new CanonicalJsonError('symbol_property');\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (!descriptor) throw new CanonicalJsonError('non_plain_object');\n if ('get' in descriptor || 'set' in descriptor) {\n throw new CanonicalJsonError('accessor_property');\n }\n if (!descriptor.enumerable) throw new CanonicalJsonError('non_enumerable_property');\n if (optional.has(key) && descriptor.value === undefined) continue;\n copy[key] = descriptor.value;\n }\n return copy;\n}\n\nfunction normalizeArray(\n value: unknown,\n normalizeItem: (item: unknown) => unknown,\n): unknown {\n if (!Array.isArray(value)) return value;\n if (Object.getPrototypeOf(value) !== Array.prototype || value.length > MAX_CONVERSATION_EVENT_NODES) {\n return value;\n }\n const normalized: unknown[] = [];\n for (let index = 0; index < value.length; index += 1) {\n const descriptor = Object.getOwnPropertyDescriptor(value, String(index));\n if (!descriptor || 'get' in descriptor || 'set' in descriptor) {\n throw new CanonicalJsonError(descriptor ? 'accessor_property' : 'sparse_array');\n }\n normalized.push(normalizeItem(descriptor.value));\n }\n return normalized;\n}\n\nfunction safeDataProperty(value: unknown, key: string): unknown {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return undefined;\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (!descriptor || 'get' in descriptor || 'set' in descriptor) return undefined;\n return descriptor.value;\n}\n\nfunction isMessagePayload(value: unknown): value is ConversationMessagePayload {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const message = value as Partial<ConversationMessagePayload> & Record<string, unknown>;\n if (!hasOnlyKeys(message, messagePayloadKeys)) return false;\n return isIdentifier(message.messageId) &&\n isIdentifier(message.turnId) &&\n (message.role !== 'user' || message.messageId === message.turnId) &&\n (message.role === 'user' || message.role === 'assistant' || message.role === 'tool' ||\n message.role === 'agent' || message.role === 'error') &&\n isBoundedText(message.content, CONVERSATION_EVENT_LIMITS.textBytes, true) &&\n (message.parts === undefined || Array.isArray(message.parts) &&\n message.parts.length <= CONVERSATION_EVENT_LIMITS.messageParts &&\n message.parts.every(isMessagePart)) &&\n (message.toolCalls === undefined || Array.isArray(message.toolCalls) &&\n message.toolCalls.length <= CONVERSATION_EVENT_LIMITS.toolCalls &&\n message.toolCalls.every(isToolCall)) &&\n (message.attachments === undefined || Array.isArray(message.attachments) &&\n message.attachments.length <= CONVERSATION_EVENT_LIMITS.attachments &&\n message.attachments.every(isAttachmentReference)) &&\n (message.detailRef === undefined || isDetailReference(message.detailRef)) &&\n (message.reasoning_content === undefined ||\n isBoundedText(message.reasoning_content, CONVERSATION_EVENT_LIMITS.textBytes, true)) &&\n (message.contentType === undefined || isBoundedSourceString(message.contentType, false)) &&\n (message.hidden === undefined || typeof message.hidden === 'boolean') &&\n (message.duration === undefined || message.duration === null ||\n typeof message.duration === 'number' && Number.isSafeInteger(message.duration) &&\n message.duration >= 0) &&\n (message.metadata === undefined || isBoundedJsonRecord(message.metadata));\n}\n\nfunction isCompactionSummary(value: unknown): boolean {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const summary = value as Record<string, unknown>;\n return hasOnlyKeys(summary, ['turnId', 'content', 'parts']) &&\n isIdentifier(summary.turnId) &&\n isBoundedText(summary.content, CONVERSATION_EVENT_LIMITS.textBytes, true) &&\n (summary.parts === undefined || Array.isArray(summary.parts) &&\n summary.parts.length <= CONVERSATION_EVENT_LIMITS.messageParts &&\n summary.parts.every(part => isMessagePart(part) && part.type !== 'attachment'));\n}\n\nfunction isMetadataPatch(value: unknown): value is ConversationMetadataPatchFields {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const patch = value as Record<string, unknown>;\n const allowed = new Set(['title', 'definitionId', 'instanceDelta', 'isUserInitiated', 'sourceChannel']);\n if (Object.keys(patch).length === 0 || Object.keys(patch).some(key => !allowed.has(key))) return false;\n if (\n patch.title !== undefined &&\n !isBoundedText(patch.title, CONVERSATION_EVENT_LIMITS.titleBytes, true)\n ) return false;\n if (patch.definitionId !== undefined && !isIdentifier(patch.definitionId)) return false;\n if (patch.instanceDelta !== undefined && !isBoundedJsonRecord(patch.instanceDelta)) return false;\n if (patch.isUserInitiated !== undefined && typeof patch.isUserInitiated !== 'boolean') return false;\n if (patch.sourceChannel !== undefined && patch.sourceChannel !== null) {\n if (!isPlainObject(patch.sourceChannel)) return false;\n const source = patch.sourceChannel;\n if (\n !hasOnlyKeys(source, ['channelId', 'platform', 'imUserId']) ||\n !isBoundedSourceString(source.channelId, false) ||\n !isBoundedSourceString(source.platform, false) ||\n !isBoundedSourceString(source.imUserId, false)\n ) return false;\n }\n return true;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const prototype = Object.getPrototypeOf(value) as object | null;\n return prototype === Object.prototype || prototype === null;\n}\n\nconst eventBaseKeys = [\n 'eventId',\n 'conversationId',\n 'originNodeId',\n 'originSequence',\n 'lamportClock',\n 'timestamp',\n] as const;\n\nconst messagePayloadKeys = [\n 'messageId',\n 'turnId',\n 'role',\n 'content',\n 'parts',\n 'toolCalls',\n 'attachments',\n 'detailRef',\n 'reasoning_content',\n 'contentType',\n 'hidden',\n 'duration',\n 'metadata',\n] as const;\n\nfunction hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {\n const keys = new Set(allowed);\n return Object.keys(value).every(key => keys.has(key));\n}\n\nfunction isAttachmentReference(value: unknown): boolean {\n if (!isPlainObject(value) || !hasOnlyKeys(value, ['contentHash', 'filename', 'mimeType', 'size'])) {\n return false;\n }\n return typeof value.contentHash === 'string' &&\n ATTACHMENT_CONTENT_HASH_PATTERN.test(value.contentHash) &&\n isSafeFilename(value.filename) && isSafeMimeType(value.mimeType) &&\n typeof value.size === 'number' && Number.isSafeInteger(value.size) && value.size >= 0 &&\n value.size <= CONVERSATION_EVENT_LIMITS.attachmentBytes;\n}\n\nfunction isToolCall(value: unknown): boolean {\n return isPlainObject(value) && hasOnlyKeys(value, ['id', 'toolName', 'arguments']) &&\n isIdentifier(value.id) && isToolName(value.toolName) &&\n Object.hasOwn(value, 'arguments') && isBoundedJsonFragment(value.arguments);\n}\n\nfunction isDetailReference(value: unknown): boolean {\n if (\n !isPlainObject(value) || !hasOnlyKeys(value, [\n 'type',\n 'runId',\n 'conversationId',\n 'sessionId',\n 'nodeId',\n 'fileUri',\n 'exitCode',\n 'resourceVersion',\n ])\n ) return false;\n if (value.type !== 'agent-run' && value.type !== 'terminal-session' && value.type !== 'file') {\n return false;\n }\n if (\n !['runId', 'conversationId', 'sessionId', 'nodeId', 'resourceVersion']\n .every(key => value[key] === undefined || isIdentifier(value[key])) ||\n value.fileUri !== undefined &&\n !isBoundedText(value.fileUri, CONVERSATION_EVENT_LIMITS.referenceBytes, false)\n ) return false;\n if (\n value.exitCode !== undefined &&\n (typeof value.exitCode !== 'number' || !Number.isSafeInteger(value.exitCode))\n ) return false;\n if (value.type === 'agent-run') {\n return value.runId !== undefined || value.conversationId !== undefined;\n }\n if (value.type === 'terminal-session') return value.sessionId !== undefined;\n return value.fileUri !== undefined;\n}\n\nfunction isMessagePart(value: unknown): value is ChatMessagePart {\n if (!isPlainObject(value) || typeof value.type !== 'string') return false;\n switch (value.type) {\n case 'text':\n case 'reasoning':\n return hasOnlyKeys(value, ['type', 'text']) &&\n isBoundedText(value.text, CONVERSATION_EVENT_LIMITS.textBytes, true);\n case 'tool-call':\n return hasOnlyKeys(value, ['type', 'toolCallId', 'toolName', 'arguments']) &&\n isIdentifier(value.toolCallId) && isToolName(value.toolName) &&\n Object.hasOwn(value, 'arguments') && isBoundedJsonFragment(value.arguments);\n case 'attachment':\n return hasOnlyKeys(value, ['type', 'attachment']) && isAttachmentReference(value.attachment);\n case 'tool-result':\n return hasOnlyKeys(value, [\n 'type',\n 'toolCallId',\n 'toolName',\n 'parameters',\n 'result',\n 'isError',\n 'payload',\n 'detailRef',\n ]) && (value.toolCallId === undefined || isIdentifier(value.toolCallId)) &&\n isToolName(value.toolName) &&\n isBoundedText(value.result, CONVERSATION_EVENT_LIMITS.textBytes, true) &&\n (value.parameters === undefined || isBoundedJsonFragment(value.parameters)) &&\n (value.isError === undefined || typeof value.isError === 'boolean') &&\n (value.payload === undefined || isBoundedJsonFragment(value.payload)) &&\n (value.detailRef === undefined || isDetailReference(value.detailRef));\n default:\n return false;\n }\n}\n\nfunction isCompactionBoundaryWithinEventLimits(boundary: ContextCompactionBoundaryV2): boolean {\n const maps = [\n boundary.coveredVersion,\n boundary.coveredMessageCountByOrigin,\n boundary.coveredUserTurnCountByOrigin,\n ];\n if (maps.some(map => Object.keys(map).length > CONVERSATION_EVENT_LIMITS.compactionOrigins)) {\n return false;\n }\n if (maps.some(map => Object.keys(map).some(key => !isIdentifier(key)))) return false;\n return boundary.previousSummaryMessageIds?.every(isIdentifier) ?? true;\n}\n\nfunction isIdentifier(value: unknown): value is string {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.identifierBytes, false) &&\n !hasAsciiControl(value);\n}\n\nfunction isToolName(value: unknown): value is string {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.sourceStringBytes, false) &&\n !hasAsciiControl(value);\n}\n\nfunction isBoundedSourceString(value: unknown, allowEmpty: boolean): value is string {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.sourceStringBytes, allowEmpty) &&\n !hasAsciiControl(value);\n}\n\nfunction isBoundedText(value: unknown, maxBytes: number, allowEmpty: boolean): value is string {\n return typeof value === 'string' && (allowEmpty || value.length > 0) &&\n utf8Encoder.encode(value).byteLength <= maxBytes;\n}\n\nfunction isSafeFilename(value: unknown): value is string {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.filenameBytes, false) &&\n value !== '.' && value !== '..' && !hasAsciiControl(value) &&\n !value.includes('/') && !value.includes('\\\\');\n}\n\nfunction isSafeMimeType(value: unknown): value is string {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.mimeTypeBytes, false) &&\n MIME_TYPE_PATTERN.test(value);\n}\n\nfunction hasAsciiControl(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const codeUnit = value.charCodeAt(index);\n if (codeUnit < 0x20 || codeUnit === 0x7f) return true;\n }\n return false;\n}\n\ninterface JsonFragmentValidationState {\n active: WeakSet<object>;\n nodes: number;\n}\n\nfunction isBoundedJsonRecord(value: unknown): value is Record<string, unknown> {\n return isPlainObject(value) && isBoundedJsonFragment(value);\n}\n\nfunction isBoundedJsonFragment(\n value: unknown,\n depth = 0,\n state: JsonFragmentValidationState = { active: new WeakSet(), nodes: 0 },\n): boolean {\n state.nodes += 1;\n if (state.nodes > MAX_CONVERSATION_EVENT_NODES || depth > CONVERSATION_EVENT_LIMITS.metadataDepth) {\n return false;\n }\n if (value === null || typeof value === 'boolean') return true;\n if (typeof value === 'string') {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.metadataStringBytes, true);\n }\n if (typeof value === 'number') {\n return Number.isFinite(value) && (!Number.isInteger(value) || Number.isSafeInteger(value));\n }\n if (typeof value !== 'object') return false;\n if (state.active.has(value)) return false;\n state.active.add(value);\n let valid = false;\n if (Array.isArray(value)) {\n valid = Object.getPrototypeOf(value) === Array.prototype &&\n value.length <= CONVERSATION_EVENT_LIMITS.metadataArrayItems &&\n value.every(item => isBoundedJsonFragment(item, depth + 1, state));\n } else if (isPlainObject(value)) {\n const keys = Reflect.ownKeys(value);\n valid = keys.length <= CONVERSATION_EVENT_LIMITS.metadataKeysPerObject && keys.every(key => {\n if (\n typeof key !== 'string' ||\n !isBoundedText(key, CONVERSATION_EVENT_LIMITS.metadataKeyBytes, false)\n ) return false;\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n return descriptor !== undefined && descriptor.enumerable &&\n !('get' in descriptor) && !('set' in descriptor) &&\n isBoundedJsonFragment(descriptor.value, depth + 1, state);\n });\n }\n state.active.delete(value);\n return valid;\n}\n","export type AgentRunState =\n | 'accepted'\n | 'queued'\n | 'running'\n | 'completed'\n | 'failed'\n | 'cancelled';\n\nexport const AGENT_RUN_ERROR_CODES = Object.freeze(\n [\n 'CANCELLED',\n 'INTERRUPTED',\n 'INVALID_REQUEST',\n 'USER_MESSAGE_TOO_LARGE',\n 'MODEL_NOT_FOUND',\n 'PROVIDER_AUTH_MISSING',\n 'PROVIDER_CONFIGURATION_MISSING',\n 'PROVIDER_UNAVAILABLE',\n 'RATE_LIMITED',\n 'RUNNER_UNAVAILABLE',\n 'STORAGE_UNAVAILABLE',\n 'DEVICE_AUTH_REQUIRED',\n 'DEVICE_PERMISSION_DENIED',\n 'NETWORK_UNAVAILABLE',\n 'CONTEXT_COMPACTION_PENDING',\n 'CONTEXT_COMPACTION_FAILED',\n 'CONTEXT_BUDGET_EXCEEDED',\n 'INTERNAL',\n ] as const,\n);\n\nexport type AgentRunErrorCode = typeof AGENT_RUN_ERROR_CODES[number];\n\nexport const AGENT_RUN_ERROR_MESSAGE_KEYS = Object.freeze(\n {\n CANCELLED: 'agent.run.error.cancelled',\n INTERRUPTED: 'agent.run.error.interrupted',\n INVALID_REQUEST: 'agent.run.error.invalidRequest',\n USER_MESSAGE_TOO_LARGE: 'agent.run.error.userMessageTooLarge',\n MODEL_NOT_FOUND: 'agent.run.error.modelNotFound',\n PROVIDER_AUTH_MISSING: 'agent.run.error.providerAuthMissing',\n PROVIDER_CONFIGURATION_MISSING: 'agent.run.error.providerConfigurationMissing',\n PROVIDER_UNAVAILABLE: 'agent.run.error.providerUnavailable',\n RATE_LIMITED: 'agent.run.error.rateLimited',\n RUNNER_UNAVAILABLE: 'agent.run.error.runnerUnavailable',\n STORAGE_UNAVAILABLE: 'agent.run.error.storageUnavailable',\n DEVICE_AUTH_REQUIRED: 'agent.run.error.deviceAuthRequired',\n DEVICE_PERMISSION_DENIED: 'agent.run.error.devicePermissionDenied',\n NETWORK_UNAVAILABLE: 'agent.run.error.networkUnavailable',\n CONTEXT_COMPACTION_PENDING: 'agent.run.error.contextCompactionPending',\n CONTEXT_COMPACTION_FAILED: 'agent.run.error.contextCompactionFailed',\n CONTEXT_BUDGET_EXCEEDED: 'agent.run.error.contextBudgetExceeded',\n INTERNAL: 'agent.run.error.internal',\n } satisfies Readonly<Record<AgentRunErrorCode, string>>,\n);\n\nexport type AgentRunErrorMessageKey = typeof AGENT_RUN_ERROR_MESSAGE_KEYS[AgentRunErrorCode];\n\nexport const AGENT_RUN_PROVIDER_SETTING_FIELDS = Object.freeze(\n [\n 'apiKey',\n 'baseUrl',\n 'model',\n 'apiMode',\n ] as const,\n);\n\nexport type AgentRunProviderSettingField = typeof AGENT_RUN_PROVIDER_SETTING_FIELDS[number];\n\nexport interface AgentRunErrorLocalizationParameters {\n providerId?: string;\n modelId?: string;\n settingField?: AgentRunProviderSettingField;\n retryAfterMs?: number;\n requested?: number;\n limit?: number;\n /** Content-free durable compaction checkpoint identity. */\n checkpointRevision?: string;\n /** Total messages causally covered by the durable checkpoint. */\n processedMessages?: number;\n /** Optional storage-supplied estimate; absence means unknown, never zero. */\n remainingEstimate?: number;\n}\n\nexport type AgentRunErrorSettingTarget =\n | {\n kind: 'provider';\n providerId: string;\n field: AgentRunProviderSettingField;\n }\n | { kind: 'model'; providerId: string; modelId: string }\n | { kind: 'runtime'; section: 'agent' | 'network' | 'storage' };\n\n/**\n * Public, restart-safe error metadata. This type intentionally has no message,\n * cause, provider body, credential, or arbitrary metadata escape hatch.\n */\nexport interface AgentRunError {\n code: AgentRunErrorCode;\n messageKey: AgentRunErrorMessageKey;\n retryable: boolean;\n /** Opaque support correlation identifier; never a provider request body or credential. */\n diagnosticId: string;\n providerId?: string;\n modelId?: string;\n localizedParams?: AgentRunErrorLocalizationParameters;\n settingTarget?: AgentRunErrorSettingTarget;\n}\n\nexport const AGENT_RUN_ERROR_LIMITS = Object.freeze(\n {\n maxTotalBytes: 4_096,\n maxDepth: 3,\n maxNodes: 3,\n maxProperties: 24,\n maxIdentifierBytes: 256,\n maxDiagnosticIdBytes: 128,\n } as const,\n);\n\nexport class AgentRunErrorValidationError extends Error {\n constructor() {\n super('invalid agent run error');\n this.name = 'AgentRunErrorValidationError';\n }\n}\n\n/** Durable identity and lifecycle state for one accepted agent run. */\nexport interface AgentRunRecord {\n runId: string;\n conversationId: string;\n definitionId: string;\n /** User-rooted turn identity shared by all message events produced by this run. */\n turnId: string;\n requestPeerId: string;\n requestId: string;\n /** SHA-256 of the canonical execution payload for idempotency drift detection. */\n payloadDigest: string;\n /** Present only for a durable retry; binds the replacement run to its original user-root turn. */\n retrySourceTurnId?: string;\n state: AgentRunState;\n acceptedAt: number;\n updatedAt: number;\n startedAt?: number;\n finishedAt?: number;\n cancelRequestedAt?: number;\n error?: AgentRunError;\n}\n\nconst AGENT_RUN_ERROR_CODE_SET = new Set<AgentRunErrorCode>(AGENT_RUN_ERROR_CODES);\nconst AGENT_RUN_PROVIDER_SETTING_FIELD_SET = new Set<AgentRunProviderSettingField>(\n AGENT_RUN_PROVIDER_SETTING_FIELDS,\n);\nconst ROOT_ERROR_KEYS = new Set([\n 'code',\n 'messageKey',\n 'retryable',\n 'diagnosticId',\n 'providerId',\n 'modelId',\n 'localizedParams',\n 'settingTarget',\n]);\nconst LOCALIZATION_PARAM_KEYS = new Set([\n 'providerId',\n 'modelId',\n 'settingField',\n 'retryAfterMs',\n 'requested',\n 'limit',\n 'checkpointRevision',\n 'processedMessages',\n 'remainingEstimate',\n]);\nconst SECRET_SHAPE =\n /(?:\\b(?:bearer|basic)\\s+[a-z0-9._~+/=-]+|\\b(?:sk|gsk|xai)-[a-z0-9_-]{12,}|\\bAIza[\\w-]{20,}|\\bAKIA[A-Z0-9]{12,}|eyJ[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\.|-----BEGIN [A-Z ]*PRIVATE KEY-----)/u;\nconst LONE_SURROGATE = /[\\ud800-\\udbff](?![\\udc00-\\udfff])|(?<![\\ud800-\\udbff])[\\udc00-\\udfff]/u;\nconst DIAGNOSTIC_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u;\nconst textEncoder = new TextEncoder();\nlet diagnosticSequence = 0;\n\ninterface DescriptorReadState {\n readonly seen: Set<object>;\n nodes: number;\n properties: number;\n}\n\nfunction invalidAgentRunError(): never {\n throw new AgentRunErrorValidationError();\n}\n\nfunction readDescriptorRecord(\n value: unknown,\n state: DescriptorReadState,\n depth: number,\n): Record<string, unknown> {\n if (\n value === null ||\n typeof value !== 'object' ||\n Array.isArray(value) ||\n depth > AGENT_RUN_ERROR_LIMITS.maxDepth\n ) invalidAgentRunError();\n const prototype = Object.getPrototypeOf(value) as unknown;\n if (prototype !== Object.prototype && prototype !== null) invalidAgentRunError();\n if (state.seen.has(value)) invalidAgentRunError();\n state.nodes += 1;\n if (state.nodes > AGENT_RUN_ERROR_LIMITS.maxNodes) invalidAgentRunError();\n state.seen.add(value);\n const keys = Reflect.ownKeys(value);\n state.properties += keys.length;\n if (state.properties > AGENT_RUN_ERROR_LIMITS.maxProperties) invalidAgentRunError();\n const record: Record<string, unknown> = {};\n for (const key of keys) {\n if (typeof key !== 'string') invalidAgentRunError();\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (!descriptor?.enumerable || !('value' in descriptor)) invalidAgentRunError();\n record[key] = descriptor.value as unknown;\n }\n return record;\n}\n\nfunction exactKeys(record: Record<string, unknown>, allowed: ReadonlySet<string>): void {\n if (Object.keys(record).some(key => !allowed.has(key))) invalidAgentRunError();\n}\n\nfunction boundedSafeText(\n value: unknown,\n maximumBytes: number,\n options: { diagnostic?: boolean } = {},\n): value is string {\n return typeof value === 'string' &&\n value.length > 0 &&\n value.trim() === value &&\n textEncoder.encode(value).byteLength <= maximumBytes &&\n !hasControlCharacter(value) &&\n !LONE_SURROGATE.test(value) &&\n !SECRET_SHAPE.test(value) &&\n (!options.diagnostic || DIAGNOSTIC_ID.test(value));\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 0x1F || code === 0x7F) return true;\n }\n return false;\n}\n\nfunction safeFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' &&\n Number.isFinite(value) &&\n Math.abs(value) <= Number.MAX_SAFE_INTEGER;\n}\n\nfunction isAgentRunProviderSettingField(\n value: unknown,\n): value is AgentRunProviderSettingField {\n return AGENT_RUN_PROVIDER_SETTING_FIELD_SET.has(value as AgentRunProviderSettingField);\n}\n\nfunction normalizeAgentRunErrorLocalizationParameters(\n value: unknown,\n state: DescriptorReadState,\n): Readonly<AgentRunErrorLocalizationParameters> | undefined {\n if (value === undefined) return undefined;\n const input = readDescriptorRecord(value, state, 2);\n exactKeys(input, LOCALIZATION_PARAM_KEYS);\n if (\n input.providerId !== undefined &&\n !boundedSafeText(input.providerId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) ||\n input.modelId !== undefined &&\n !boundedSafeText(input.modelId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) ||\n input.settingField !== undefined && !isAgentRunProviderSettingField(input.settingField) ||\n input.retryAfterMs !== undefined &&\n (!safeFiniteNumber(input.retryAfterMs) || input.retryAfterMs < 0) ||\n input.requested !== undefined &&\n (!safeFiniteNumber(input.requested) || input.requested < 0) ||\n input.limit !== undefined && (!safeFiniteNumber(input.limit) || input.limit < 0) ||\n input.checkpointRevision !== undefined &&\n !boundedSafeText(input.checkpointRevision, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) ||\n input.processedMessages !== undefined &&\n (!safeFiniteNumber(input.processedMessages) ||\n !Number.isSafeInteger(input.processedMessages) || input.processedMessages < 0) ||\n input.remainingEstimate !== undefined &&\n (!safeFiniteNumber(input.remainingEstimate) ||\n !Number.isSafeInteger(input.remainingEstimate) || input.remainingEstimate < 1)\n ) invalidAgentRunError();\n const normalized: AgentRunErrorLocalizationParameters = {};\n if (typeof input.providerId === 'string') normalized.providerId = input.providerId;\n if (typeof input.modelId === 'string') normalized.modelId = input.modelId;\n if (isAgentRunProviderSettingField(input.settingField)) {\n normalized.settingField = input.settingField;\n }\n if (typeof input.retryAfterMs === 'number') normalized.retryAfterMs = input.retryAfterMs;\n if (typeof input.requested === 'number') normalized.requested = input.requested;\n if (typeof input.limit === 'number') normalized.limit = input.limit;\n if (typeof input.checkpointRevision === 'string') {\n normalized.checkpointRevision = input.checkpointRevision;\n }\n if (typeof input.processedMessages === 'number') {\n normalized.processedMessages = input.processedMessages;\n }\n if (typeof input.remainingEstimate === 'number') {\n normalized.remainingEstimate = input.remainingEstimate;\n }\n return Object.freeze(normalized);\n}\n\n/** Strictly validate and clone safe public error metadata. */\nexport function normalizeAgentRunError(value: unknown): AgentRunError {\n const state: DescriptorReadState = { seen: new Set(), nodes: 0, properties: 0 };\n const input = readDescriptorRecord(value, state, 1);\n exactKeys(input, ROOT_ERROR_KEYS);\n if (\n !AGENT_RUN_ERROR_CODE_SET.has(input.code as AgentRunErrorCode) ||\n input.messageKey !== AGENT_RUN_ERROR_MESSAGE_KEYS[input.code as AgentRunErrorCode] ||\n typeof input.retryable !== 'boolean' ||\n !boundedSafeText(\n input.diagnosticId,\n AGENT_RUN_ERROR_LIMITS.maxDiagnosticIdBytes,\n { diagnostic: true },\n ) ||\n input.providerId !== undefined &&\n !boundedSafeText(input.providerId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) ||\n input.modelId !== undefined &&\n !boundedSafeText(input.modelId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes)\n ) invalidAgentRunError();\n const localizedParameters = normalizeAgentRunErrorLocalizationParameters(\n input.localizedParams,\n state,\n );\n const settingTarget = normalizeAgentRunErrorSettingTarget(input.settingTarget, state);\n if (\n localizedParameters?.providerId !== undefined &&\n localizedParameters.providerId !== input.providerId ||\n localizedParameters?.modelId !== undefined && localizedParameters.modelId !== input.modelId ||\n settingTarget?.kind !== undefined &&\n settingTarget.kind !== 'runtime' && settingTarget.providerId !== input.providerId ||\n settingTarget?.kind === 'model' && settingTarget.modelId !== input.modelId ||\n settingTarget?.kind === 'provider' &&\n localizedParameters?.settingField !== undefined &&\n localizedParameters.settingField !== settingTarget.field\n ) invalidAgentRunError();\n const normalized: AgentRunError = {\n code: input.code as AgentRunErrorCode,\n messageKey: input.messageKey,\n retryable: input.retryable,\n diagnosticId: input.diagnosticId,\n };\n if (typeof input.providerId === 'string') normalized.providerId = input.providerId;\n if (typeof input.modelId === 'string') normalized.modelId = input.modelId;\n if (localizedParameters) normalized.localizedParams = localizedParameters;\n if (settingTarget) normalized.settingTarget = settingTarget;\n if (textEncoder.encode(JSON.stringify(normalized)).byteLength > AGENT_RUN_ERROR_LIMITS.maxTotalBytes) {\n invalidAgentRunError();\n }\n return Object.freeze(normalized);\n}\n\nfunction normalizeAgentRunErrorSettingTarget(\n value: unknown,\n state: DescriptorReadState,\n): AgentRunErrorSettingTarget | undefined {\n if (value === undefined) return undefined;\n const target = readDescriptorRecord(value, state, 2);\n if (\n target.kind === 'provider' &&\n boundedSafeText(target.providerId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) &&\n isAgentRunProviderSettingField(target.field) &&\n Object.keys(target).every(\n key => key === 'kind' || key === 'providerId' || key === 'field',\n )\n ) {\n return Object.freeze({\n kind: 'provider' as const,\n providerId: target.providerId,\n field: target.field,\n });\n }\n if (\n target.kind === 'model' &&\n boundedSafeText(target.providerId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) &&\n boundedSafeText(target.modelId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) &&\n Object.keys(target).every(key => key === 'kind' || key === 'providerId' || key === 'modelId')\n ) {\n return Object.freeze({\n kind: 'model' as const,\n providerId: target.providerId,\n modelId: target.modelId,\n });\n }\n if (\n target.kind === 'runtime' &&\n (target.section === 'agent' || target.section === 'network' || target.section === 'storage') &&\n Object.keys(target).every(key => key === 'kind' || key === 'section')\n ) return Object.freeze({ kind: 'runtime' as const, section: target.section });\n return invalidAgentRunError();\n}\n\nexport function assertAgentRunError(value: unknown): asserts value is AgentRunError {\n normalizeAgentRunError(value);\n}\n\nexport function isAgentRunError(value: unknown): value is AgentRunError {\n try {\n normalizeAgentRunError(value);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Throwable carrier whose Error message is always the stable public code. */\nexport class AgentRunFailure extends Error {\n readonly agentRunError: AgentRunError;\n\n constructor(agentRunError: AgentRunError) {\n const normalized = normalizeAgentRunError(agentRunError);\n super(normalized.code);\n this.name = 'AgentRunFailure';\n this.agentRunError = normalized;\n }\n}\n\nexport function isAgentRunFailure(value: unknown): value is AgentRunFailure {\n return value instanceof AgentRunFailure;\n}\n\n/** Extracts only a strict public contract; accessors and malformed wrappers are ignored. */\nexport function extractAgentRunError(value: unknown): AgentRunError | undefined {\n try {\n return normalizeAgentRunError(value);\n } catch {\n // Try an own descriptor-backed typed failure wrapper.\n }\n if (value === null || typeof value !== 'object') return undefined;\n const descriptor = Object.getOwnPropertyDescriptor(value, 'agentRunError');\n if (!descriptor || !('value' in descriptor)) return undefined;\n try {\n return normalizeAgentRunError(descriptor.value);\n } catch {\n return undefined;\n }\n}\n\nexport function createAgentRunDiagnosticId(): string {\n try {\n if (typeof globalThis.crypto?.randomUUID === 'function') {\n return `agent-${globalThis.crypto.randomUUID()}`;\n }\n } catch {\n // Fall through to the portable monotonic fallback.\n }\n diagnosticSequence = (diagnosticSequence + 1) % Number.MAX_SAFE_INTEGER;\n return `agent-${Date.now().toString(36)}-${diagnosticSequence.toString(36)}`;\n}\n\nexport type CreateAgentRunErrorInput = Omit<AgentRunError, 'diagnosticId'> & {\n diagnosticId?: string;\n};\n\nexport function createAgentRunError(input: CreateAgentRunErrorInput): AgentRunError {\n const state: DescriptorReadState = { seen: new Set(), nodes: 0, properties: 0 };\n const descriptorInput = readDescriptorRecord(input, state, 1);\n exactKeys(descriptorInput, ROOT_ERROR_KEYS);\n return normalizeAgentRunError({\n ...descriptorInput,\n diagnosticId: descriptorInput.diagnosticId ?? createAgentRunDiagnosticId(),\n });\n}\n\nexport interface CreateMissingProviderSettingAgentRunErrorInput {\n providerId: string;\n field: AgentRunProviderSettingField;\n modelId?: string;\n diagnosticId?: string;\n}\n\n/** Creates safe settings-navigation metadata without accepting a setting value. */\nexport function createMissingProviderSettingAgentRunError(\n input: CreateMissingProviderSettingAgentRunErrorInput,\n): AgentRunError {\n const state: DescriptorReadState = { seen: new Set(), nodes: 0, properties: 0 };\n const descriptorInput = readDescriptorRecord(input, state, 1);\n exactKeys(descriptorInput, new Set(['providerId', 'field', 'modelId', 'diagnosticId']));\n const code: AgentRunErrorCode = descriptorInput.field === 'apiKey'\n ? 'PROVIDER_AUTH_MISSING'\n : 'PROVIDER_CONFIGURATION_MISSING';\n return createAgentRunError({\n code,\n messageKey: AGENT_RUN_ERROR_MESSAGE_KEYS[code],\n retryable: false,\n providerId: descriptorInput.providerId as string,\n ...(descriptorInput.modelId === undefined\n ? {}\n : { modelId: descriptorInput.modelId as string }),\n localizedParams: {\n providerId: descriptorInput.providerId as string,\n ...(descriptorInput.modelId === undefined\n ? {}\n : { modelId: descriptorInput.modelId as string }),\n settingField: descriptorInput.field as AgentRunProviderSettingField,\n },\n settingTarget: {\n kind: 'provider',\n providerId: descriptorInput.providerId as string,\n field: descriptorInput.field as AgentRunProviderSettingField,\n },\n ...(descriptorInput.diagnosticId === undefined\n ? {}\n : { diagnosticId: descriptorInput.diagnosticId as string }),\n });\n}\n\nexport type CreateMissingApiKeyAgentRunErrorInput = Omit<\n CreateMissingProviderSettingAgentRunErrorInput,\n 'field'\n>;\n\nexport function createMissingApiKeyAgentRunError(\n input: CreateMissingApiKeyAgentRunErrorInput,\n): AgentRunError {\n const state: DescriptorReadState = { seen: new Set(), nodes: 0, properties: 0 };\n const descriptorInput = readDescriptorRecord(input, state, 1);\n exactKeys(descriptorInput, new Set(['providerId', 'modelId', 'diagnosticId']));\n return createMissingProviderSettingAgentRunError({\n providerId: descriptorInput.providerId as string,\n ...(descriptorInput.modelId === undefined\n ? {}\n : { modelId: descriptorInput.modelId as string }),\n ...(descriptorInput.diagnosticId === undefined\n ? {}\n : { diagnosticId: descriptorInput.diagnosticId as string }),\n field: 'apiKey',\n });\n}\n\n/** Fail-closed conversion that never persists raw exception messages/bodies. */\nexport function agentRunErrorFromUnknown(error: unknown): AgentRunError {\n const extracted = extractAgentRunError(error);\n if (extracted) return extracted;\n if (error instanceof Error) {\n const descriptor = Object.getOwnPropertyDescriptor(error, 'message');\n const message = descriptor && 'value' in descriptor\n ? descriptor.value as unknown\n : undefined;\n if (typeof message === 'string' && message.startsWith('RUNNER_UNAVAILABLE:')) {\n return createAgentRunError({\n code: 'RUNNER_UNAVAILABLE',\n messageKey: AGENT_RUN_ERROR_MESSAGE_KEYS.RUNNER_UNAVAILABLE,\n retryable: false,\n });\n }\n }\n return createAgentRunError({\n code: 'INTERNAL',\n messageKey: AGENT_RUN_ERROR_MESSAGE_KEYS.INTERNAL,\n retryable: false,\n });\n}\n\nexport interface AgentRunPruneOptions {\n finishedBefore: number;\n maxRecords: number;\n}\n\n/**\n * Durable lifecycle/idempotency port. `createOrGet` atomically owns the\n * unique `(requestPeerId, requestId)` key, returns an existing record only\n * when its payload digest matches, and rejects payload drift.\n */\nexport interface AgentRunStateStore {\n createOrGet(record: AgentRunRecord): Promise<AgentRunRecord>;\n get(runId: string): Promise<AgentRunRecord | undefined>;\n /** Indexed replay lookup for the durable idempotency key. */\n getByRequest(requestPeerId: string, requestId: string): Promise<AgentRunRecord | undefined>;\n getByTurn(\n conversationId: string,\n turnId: string,\n requestPeerId: string,\n ): Promise<AgentRunRecord | undefined>;\n /** Atomic lifecycle CAS. Terminal records must never transition again. */\n transition(\n runId: string,\n expectedStates: readonly AgentRunState[],\n next: AgentRunRecord,\n ): Promise<boolean>;\n listActive(): Promise<AgentRunRecord[]>;\n prune(options: AgentRunPruneOptions): Promise<void>;\n}\n\nexport class AgentRunRequestConflictError extends Error {\n constructor(requestPeerId: string, requestId: string) {\n super(`Run request payload drift for ${requestPeerId}/${requestId}`);\n this.name = 'AgentRunRequestConflictError';\n }\n}\n\n/** Test/embedder fallback. Production hosts should inject a durable store. */\nexport class MemoryAgentRunStateStore implements AgentRunStateStore {\n private readonly records = new Map<string, AgentRunRecord>();\n private readonly requestIndex = new Map<string, string>();\n\n private requestKey(requestPeerId: string, requestId: string): string {\n return JSON.stringify([requestPeerId, requestId]);\n }\n\n async createOrGet(record: AgentRunRecord): Promise<AgentRunRecord> {\n const normalized = cloneAgentRunRecord(record);\n const key = this.requestKey(normalized.requestPeerId, normalized.requestId);\n const existingId = this.requestIndex.get(key);\n if (existingId) {\n const existing = this.records.get(existingId);\n if (!existing) throw new Error(`Run request index is corrupt: ${existingId}`);\n if (existing.payloadDigest !== normalized.payloadDigest) {\n throw new AgentRunRequestConflictError(normalized.requestPeerId, normalized.requestId);\n }\n return cloneAgentRunRecord(existing);\n }\n this.records.set(normalized.runId, normalized);\n this.requestIndex.set(key, normalized.runId);\n return cloneAgentRunRecord(normalized);\n }\n\n async get(runId: string): Promise<AgentRunRecord | undefined> {\n const record = this.records.get(runId);\n return record ? cloneAgentRunRecord(record) : undefined;\n }\n\n async getByRequest(\n requestPeerId: string,\n requestId: string,\n ): Promise<AgentRunRecord | undefined> {\n const runId = this.requestIndex.get(this.requestKey(requestPeerId, requestId));\n if (!runId) return undefined;\n const record = this.records.get(runId);\n if (!record) throw new Error(`Run request index is corrupt: ${runId}`);\n return cloneAgentRunRecord(record);\n }\n\n async getByTurn(\n conversationId: string,\n turnId: string,\n requestPeerId: string,\n ): Promise<AgentRunRecord | undefined> {\n const record = [...this.records.values()].find(candidate =>\n candidate.conversationId === conversationId &&\n candidate.turnId === turnId &&\n candidate.requestPeerId === requestPeerId\n );\n return record ? cloneAgentRunRecord(record) : undefined;\n }\n\n async transition(\n runId: string,\n expectedStates: readonly AgentRunState[],\n record: AgentRunRecord,\n ): Promise<boolean> {\n const normalized = cloneAgentRunRecord(record);\n const existing = this.records.get(record.runId);\n if (!existing || runId !== record.runId || !expectedStates.includes(existing.state)) return false;\n const legalNext: Record<'accepted' | 'queued' | 'running', readonly AgentRunState[]> = {\n accepted: ['queued', 'failed', 'cancelled'],\n queued: ['running', 'failed', 'cancelled'],\n running: ['completed', 'failed', 'cancelled'],\n };\n if (\n (existing.state === 'completed' || existing.state === 'failed' || existing.state === 'cancelled') ||\n !legalNext[existing.state].includes(record.state)\n ) return false;\n if (\n existing.requestPeerId !== record.requestPeerId ||\n existing.requestId !== record.requestId ||\n existing.payloadDigest !== record.payloadDigest ||\n existing.retrySourceTurnId !== record.retrySourceTurnId ||\n existing.conversationId !== record.conversationId ||\n existing.definitionId !== record.definitionId ||\n existing.turnId !== record.turnId\n ) {\n throw new Error(`Cannot change immutable run identity: ${record.runId}`);\n }\n this.records.set(record.runId, normalized);\n this.requestIndex.set(this.requestKey(record.requestPeerId, record.requestId), record.runId);\n return true;\n }\n\n async listActive(): Promise<AgentRunRecord[]> {\n return [...this.records.values()]\n .filter(record => record.state === 'accepted' || record.state === 'queued' || record.state === 'running')\n .map(record => cloneAgentRunRecord(record));\n }\n\n async prune(options: AgentRunPruneOptions): Promise<void> {\n for (const [runId, record] of this.records) {\n if (record.finishedAt !== undefined && record.finishedAt < options.finishedBefore) {\n this.deleteRecord(runId, record);\n }\n }\n const terminal = [...this.records.values()]\n .filter(record => record.finishedAt !== undefined)\n .sort((left, right) => left.updatedAt - right.updatedAt);\n while (this.records.size > options.maxRecords && terminal.length > 0) {\n const record = terminal.shift();\n if (record) this.deleteRecord(record.runId, record);\n }\n }\n\n private deleteRecord(runId: string, record: AgentRunRecord): void {\n this.records.delete(runId);\n this.requestIndex.delete(this.requestKey(record.requestPeerId, record.requestId));\n }\n}\n\nfunction cloneAgentRunRecord(record: AgentRunRecord): AgentRunRecord {\n return {\n ...record,\n ...(record.error ? { error: normalizeAgentRunError(record.error) } : {}),\n };\n}\n","import {\n assertCanonicalChatMessageProjection,\n canonicalConversationEventBytes,\n type ChatMessage,\n conversationEventToMessage,\n type ConversationMessagePayload,\n MAX_CONVERSATION_EVENT_BYTES,\n messageToConversationEvent,\n normalizeCanonicalConversationEvent,\n} from './conversation/index.js';\nimport { canonicalJsonBytes } from './encoding/canonicalJson.js';\nimport { AGENT_RUN_ERROR_MESSAGE_KEYS, AgentRunFailure, createAgentRunError } from './runState.js';\n\n/**\n * One user root must fit an ordinary 256 KiB message page including its page\n * envelope. Larger bodies belong in attachment/detail storage and are linked\n * from the bounded root event.\n */\nexport const CONVERSATION_MESSAGE_ADMISSION_LIMITS = Object.freeze(\n {\n canonicalMessageBytes: 248 * 1024,\n canonicalEventBytes: 252 * 1024,\n pagingEnvelopeBytes: 256 * 1024,\n } as const,\n);\n\nexport const AGENT_USER_MESSAGE_LIMITS = Object.freeze(\n {\n contentBytes: 240 * 1024,\n ...CONVERSATION_MESSAGE_ADMISSION_LIMITS,\n } as const,\n);\n\nexport type AgentUserMessageLimitKind = 'content' | 'canonical-message' | 'canonical-event';\n\nexport class AgentUserMessageLimitError extends AgentRunFailure {\n public readonly kind: AgentUserMessageLimitKind;\n public readonly requestedBytes: number;\n public readonly limitBytes: number;\n\n public constructor(kind: AgentUserMessageLimitKind, requestedBytes: number, limitBytes: number) {\n super(createAgentRunError({\n code: 'USER_MESSAGE_TOO_LARGE',\n messageKey: AGENT_RUN_ERROR_MESSAGE_KEYS.USER_MESSAGE_TOO_LARGE,\n retryable: false,\n localizedParams: { requested: requestedBytes, limit: limitBytes },\n }));\n this.name = 'AgentUserMessageLimitError';\n this.kind = kind;\n this.requestedBytes = requestedBytes;\n this.limitBytes = limitBytes;\n }\n}\n\nexport function assertAgentUserMessageContentWithinLimits(content: unknown): asserts content is string {\n if (typeof content !== 'string') throw new Error('invalid agent user message content');\n const contentBytes = new TextEncoder().encode(content).byteLength;\n if (contentBytes > AGENT_USER_MESSAGE_LIMITS.contentBytes) {\n throw new AgentUserMessageLimitError(\n 'content',\n contentBytes,\n AGENT_USER_MESSAGE_LIMITS.contentBytes,\n );\n }\n}\n\nexport function assertPendingAgentUserMessageWithinLimits(input: {\n readonly conversationId: string;\n readonly originNodeId: string;\n readonly timestamp: number;\n readonly message: ConversationMessagePayload;\n}): void {\n normalizeAgentUserMessageForAdmission({\n ...input.message,\n conversationId: input.conversationId,\n originNodeId: input.originNodeId,\n // Allocate against the largest legal coordinate representation. The\n // eventual durable event can only be equal or smaller.\n originSequence: Number.MAX_SAFE_INTEGER,\n lamportClock: Number.MAX_SAFE_INTEGER,\n timestamp: input.timestamp,\n });\n}\n\nexport function assertPendingConversationMessageWithinLimits(input: {\n readonly conversationId: string;\n readonly originNodeId: string;\n readonly timestamp: number;\n readonly message: ConversationMessagePayload;\n}): void {\n const candidate = {\n ...input.message,\n conversationId: input.conversationId,\n originNodeId: input.originNodeId,\n originSequence: Number.MAX_SAFE_INTEGER,\n lamportClock: Number.MAX_SAFE_INTEGER,\n timestamp: input.timestamp,\n };\n if (input.message.role === 'user') normalizeAgentUserMessageForAdmission(candidate);\n else normalizeConversationMessageForPagingAdmission(candidate);\n}\n\n/**\n * Normalize a locally generated assistant/tool payload before persistence.\n * Exact legacy/parts duplicates are removed first. If genuinely oversized,\n * a bounded Unicode-safe durable projection is stored with an explicit loss\n * marker; untrusted synced messages never use this projector.\n */\nexport function normalizeGeneratedConversationMessageForAdmission(input: {\n readonly conversationId: string;\n readonly originNodeId: string;\n readonly timestamp: number;\n readonly message: ConversationMessagePayload;\n}): ConversationMessagePayload {\n if (input.message.role === 'user') {\n assertPendingAgentUserMessageWithinLimits(input);\n return input.message;\n }\n const deduplicated = compactRedundantMessagePartsForPersistence(input.message);\n try {\n assertPendingConversationMessageWithinLimits({ ...input, message: deduplicated });\n return deduplicated;\n } catch (error) {\n if (!(error instanceof AgentUserMessageLimitError)) throw error;\n }\n\n const originalContentBytes = new TextEncoder().encode(deduplicated.content).byteLength;\n const structuredParts = (deduplicated.parts ?? []).filter(\n part => part.type !== 'text' && part.type !== 'reasoning',\n );\n const metadataVariants = projectedMetadataVariants(deduplicated.metadata);\n const maximumItemVariants = structuredParts.length > 0 || (deduplicated.toolCalls?.length ?? 0) > 0\n ? [2, 1]\n : [0];\n for (const maximumStructuredItems of maximumItemVariants) {\n const projectedParts = sampleEdges(structuredParts, maximumStructuredItems).map(part => {\n if (part.type !== 'tool-result') return part;\n return {\n type: 'tool-result' as const,\n ...(part.toolCallId === undefined ? {} : { toolCallId: part.toolCallId }),\n toolName: part.toolName,\n result: truncateUtf8(part.result, 24 * 1024),\n isError: part.isError,\n ...(part.detailRef === undefined ? {} : { detailRef: part.detailRef }),\n };\n });\n const projectedToolCalls = sampleEdges(\n deduplicated.toolCalls ?? [],\n maximumStructuredItems,\n );\n for (const metadataVariant of metadataVariants) {\n const projected: ConversationMessagePayload = {\n messageId: deduplicated.messageId,\n turnId: deduplicated.turnId,\n role: deduplicated.role,\n content: truncateUtf8(deduplicated.content, 48 * 1024),\n ...(projectedParts.length === 0 ? {} : { parts: projectedParts }),\n ...(projectedToolCalls.length === 0 ? {} : { toolCalls: projectedToolCalls }),\n ...(deduplicated.reasoning_content === undefined\n ? {}\n : { reasoning_content: truncateUtf8(deduplicated.reasoning_content, 12 * 1024) }),\n ...(deduplicated.attachments === undefined\n ? {}\n : { attachments: deduplicated.attachments.slice(0, 32) }),\n ...(deduplicated.detailRef === undefined ? {} : { detailRef: deduplicated.detailRef }),\n ...(deduplicated.contentType === undefined ? {} : { contentType: deduplicated.contentType }),\n metadata: {\n ...metadataVariant.value,\n durableProjection: {\n version: 1,\n originalContentBytes,\n contentTruncated: originalContentBytes > 48 * 1024,\n omittedStructuredParts: Math.max(0, structuredParts.length - projectedParts.length),\n omittedToolCalls: Math.max(\n 0,\n (deduplicated.toolCalls?.length ?? 0) - projectedToolCalls.length,\n ),\n ...(metadataVariant.omitted ? { omittedMetadata: true } : {}),\n capability: 'not-retained',\n },\n },\n };\n try {\n assertPendingConversationMessageWithinLimits({ ...input, message: projected });\n return projected;\n } catch (error) {\n if (!(error instanceof AgentUserMessageLimitError)) throw error;\n }\n }\n }\n throw new AgentUserMessageLimitError(\n 'canonical-message',\n CONVERSATION_MESSAGE_ADMISSION_LIMITS.canonicalMessageBytes + 1,\n CONVERSATION_MESSAGE_ADMISSION_LIMITS.canonicalMessageBytes,\n );\n}\n\nexport function compactRedundantMessagePartsForPersistence(\n message: ConversationMessagePayload,\n): ConversationMessagePayload {\n if (message.parts === undefined) return message;\n const matchingToolCalls = new Map(\n (message.toolCalls ?? []).map(call => [call.id, call]),\n );\n const matchingAttachments = new Map(\n (message.attachments ?? []).map(attachment => [attachment.contentHash, attachment]),\n );\n const parts = message.parts.filter(part =>\n !(part.type === 'text' && part.text === message.content) &&\n !(part.type === 'reasoning' && part.text === message.reasoning_content) &&\n !(part.type === 'tool-call' && (() => {\n const legacy = matchingToolCalls.get(part.toolCallId);\n return legacy !== undefined && legacy.toolName === part.toolName &&\n canonicalValuesEqual(legacy.arguments, part.arguments);\n })()) &&\n !(part.type === 'attachment' && (() => {\n const legacy = matchingAttachments.get(part.attachment.contentHash);\n return legacy !== undefined && canonicalValuesEqual(legacy, part.attachment);\n })())\n );\n const { parts: _parts, ...withoutParts } = message;\n return parts.length === 0 ? withoutParts : { ...withoutParts, parts };\n}\n\nfunction canonicalValuesEqual(left: unknown, right: unknown): boolean {\n try {\n const leftBytes = canonicalJsonBytes(left, {\n maxBytes: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n maxDepth: 32,\n maxNodes: 4_096,\n maxStringBytes: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n maxStringCodeUnits: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n });\n const rightBytes = canonicalJsonBytes(right, {\n maxBytes: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n maxDepth: 32,\n maxNodes: 4_096,\n maxStringBytes: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n maxStringCodeUnits: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n });\n if (leftBytes.byteLength !== rightBytes.byteLength) return false;\n return leftBytes.every((byte, index) => byte === rightBytes[index]);\n } catch {\n return false;\n }\n}\n\nfunction sampleEdges<Value>(values: readonly Value[], maximum: number): Value[] {\n if (maximum <= 0) return [];\n if (values.length <= maximum) return [...values];\n if (maximum === 1) return values.slice(0, 1);\n const head = Math.ceil(maximum / 2);\n return [...values.slice(0, head), ...values.slice(values.length - (maximum - head))];\n}\n\nfunction projectedMetadataVariants(\n metadata: Record<string, unknown> | undefined,\n): Array<{ value: Record<string, unknown>; omitted: boolean }> {\n if (metadata === undefined) return [{ value: {}, omitted: false }];\n const full = descriptorSafeMetadataSubset(metadata, Reflect.ownKeys(metadata));\n const stable = descriptorSafeMetadataSubset(metadata, [\n 'modelUsage',\n 'containsToolCall',\n 'provenance',\n 'actorId',\n 'actorLabel',\n 'agentId',\n 'agentName',\n 'participantId',\n 'participantLabel',\n ]);\n return [\n { value: full, omitted: false },\n { value: stable, omitted: Object.keys(stable).length !== Object.keys(full).length },\n { value: {}, omitted: Object.keys(full).length > 0 },\n ];\n}\n\nfunction descriptorSafeMetadataSubset(\n metadata: Record<string, unknown>,\n keys: readonly PropertyKey[],\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key of keys) {\n if (typeof key !== 'string') continue;\n const descriptor = Object.getOwnPropertyDescriptor(metadata, key);\n if (!descriptor?.enumerable || !('value' in descriptor)) continue;\n result[key] = descriptor.value;\n }\n return result;\n}\n\nfunction truncateUtf8(value: string, maximumBytes: number): string {\n const encoded = new TextEncoder().encode(value);\n if (encoded.byteLength <= maximumBytes) return value;\n const decoder = new TextDecoder('utf-8', { fatal: true });\n for (let end = maximumBytes; end >= Math.max(0, maximumBytes - 3); end -= 1) {\n try {\n return decoder.decode(encoded.subarray(0, end));\n } catch {\n // Only a trailing partial code point can fail; UTF-8 code points use at most four bytes.\n }\n }\n return '';\n}\n\n/**\n * Strictly normalize and admit one user-root event. This validates content,\n * structured parts and metadata together so no alternate field can bypass the\n * paging/compaction ceiling.\n */\nexport function normalizeAgentUserMessageForAdmission(value: unknown): ChatMessage {\n const normalizedMessage = normalizeConversationMessageForPagingAdmission(value);\n if (normalizedMessage.role !== 'user' || normalizedMessage.messageId !== normalizedMessage.turnId) {\n throw new Error('invalid canonical user-root message');\n }\n assertAgentUserMessageContentWithinLimits(normalizedMessage.content);\n return normalizedMessage;\n}\n\n/** Admit every role before it can enter a 256 KiB full-content page. */\nexport function normalizeConversationMessageForPagingAdmission(value: unknown): ChatMessage {\n // Reject accessors, cycles and an unbounded object graph before schema code\n // observes any property.\n canonicalJsonBytes(value, {\n maxBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxDepth: 64,\n maxNodes: 200_000,\n maxStringBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxStringCodeUnits: MAX_CONVERSATION_EVENT_BYTES,\n });\n assertCanonicalChatMessageProjection(value);\n const normalizedEvent = normalizeCanonicalConversationEvent(messageToConversationEvent(value));\n if (normalizedEvent.kind !== 'message') throw new Error('invalid canonical conversation message event');\n const normalizedMessage = conversationEventToMessage(normalizedEvent);\n const messageBytes = canonicalJsonBytes(normalizedMessage, {\n maxBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxDepth: 64,\n maxNodes: 200_000,\n maxStringBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxStringCodeUnits: MAX_CONVERSATION_EVENT_BYTES,\n }).byteLength;\n if (messageBytes > AGENT_USER_MESSAGE_LIMITS.canonicalMessageBytes) {\n throw new AgentUserMessageLimitError(\n 'canonical-message',\n messageBytes,\n AGENT_USER_MESSAGE_LIMITS.canonicalMessageBytes,\n );\n }\n const eventBytes = canonicalConversationEventBytes(normalizedEvent).byteLength;\n if (eventBytes > AGENT_USER_MESSAGE_LIMITS.canonicalEventBytes) {\n throw new AgentUserMessageLimitError(\n 'canonical-event',\n eventBytes,\n AGENT_USER_MESSAGE_LIMITS.canonicalEventBytes,\n );\n }\n return normalizedMessage;\n}\n\nexport function assertAgentUserMessageWithinLimits(value: unknown): asserts value is ChatMessage {\n normalizeAgentUserMessageForAdmission(value);\n}\n\nexport function assertConversationMessageWithinPagingLimits(value: unknown): asserts value is ChatMessage {\n normalizeConversationMessageForPagingAdmission(value);\n}\n","import type { AttachmentReference } from '../conversation/types.js';\n\nexport const ATTACHMENT_UPLOAD_RPC_METHODS = Object.freeze(\n {\n begin: 'memeloop.chat.beginAttachmentUpload',\n chunk: 'memeloop.chat.uploadAttachmentChunk',\n commit: 'memeloop.chat.commitAttachmentUpload',\n } as const,\n);\n\nexport const ATTACHMENT_UPLOAD_LIMITS = Object.freeze(\n {\n totalBytes: 64 * 1_024 * 1_024,\n chunkBytes: 3 * 1_024 * 1_024,\n chunkBase64Characters: 4 * 1_024 * 1_024,\n identifierCharacters: 512,\n filenameCharacters: 1_024,\n mimeTypeCharacters: 256,\n } as const,\n);\n\nexport const ATTACHMENT_UPLOAD_SHA256_PATTERN = /^sha256:[\\da-f]{64}$/u;\n\nexport type AttachmentUploadRpcMethod = typeof ATTACHMENT_UPLOAD_RPC_METHODS[keyof typeof ATTACHMENT_UPLOAD_RPC_METHODS];\n\nexport type AttachmentUploadStage = 'begin' | 'chunk' | 'commit';\n\ninterface AttachmentUploadOperationIdentity {\n /** Caller-generated durable idempotency key. Reuse it for transport retries. */\n requestId: string;\n /** Mandatory authorization and storage scope for every upload operation. */\n conversationId: string;\n}\n\nexport interface BeginAttachmentUploadRequest extends AttachmentUploadOperationIdentity {\n filename: string;\n mimeType: string;\n totalBytes: number;\n}\n\nexport interface BeginAttachmentUploadResponse extends AttachmentUploadOperationIdentity {\n ok: true;\n /** Durable opaque handle; callers must not parse or synthesize it. */\n uploadId: string;\n totalBytes: number;\n maxChunkBytes: number;\n}\n\nexport interface UploadAttachmentChunkRequest extends AttachmentUploadOperationIdentity {\n uploadId: string;\n offset: number;\n /** Must equal the strictly decoded byte count, not the base64 character count. */\n byteLength: number;\n encoding: 'base64';\n data: string;\n /** Optional integrity check over this decoded chunk. */\n sha256?: string;\n}\n\nexport interface UploadAttachmentChunkResponse extends AttachmentUploadOperationIdentity {\n ok: true;\n uploadId: string;\n offset: number;\n byteLength: number;\n}\n\nexport interface CommitAttachmentUploadRequest extends AttachmentUploadOperationIdentity {\n uploadId: string;\n /** Exact final byte count, checked against begin and persisted chunks. */\n size: number;\n /** Exact final digest and resulting content-addressed attachment hash. */\n sha256: string;\n}\n\nexport interface CommitAttachmentUploadResponse extends AttachmentUploadOperationIdentity {\n ok: true;\n uploadId: string;\n attachment: AttachmentReference;\n}\n\nexport interface AttachmentUploadRpcContract {\n [ATTACHMENT_UPLOAD_RPC_METHODS.begin]: {\n request: BeginAttachmentUploadRequest;\n response: BeginAttachmentUploadResponse;\n };\n [ATTACHMENT_UPLOAD_RPC_METHODS.chunk]: {\n request: UploadAttachmentChunkRequest;\n response: UploadAttachmentChunkResponse;\n };\n [ATTACHMENT_UPLOAD_RPC_METHODS.commit]: {\n request: CommitAttachmentUploadRequest;\n response: CommitAttachmentUploadResponse;\n };\n}\n\nexport type AttachmentUploadRpcRequest<M extends AttachmentUploadRpcMethod> = AttachmentUploadRpcContract[M]['request'];\n\nexport type AttachmentUploadRpcResponse<M extends AttachmentUploadRpcMethod> = AttachmentUploadRpcContract[M]['response'];\n\nexport class AttachmentUploadProtocolError extends Error {\n readonly code = 'invalid_attachment_upload' as const;\n\n constructor(readonly field: string) {\n super(`Invalid attachment upload ${field}`);\n this.name = 'AttachmentUploadProtocolError';\n }\n}\n\n/** Raised by a durable store when an idempotency key or chunk offset drifts. */\nexport class AttachmentUploadConflictError extends Error {\n readonly code = 'attachment_upload_conflict' as const;\n\n constructor(\n readonly stage: AttachmentUploadStage,\n readonly requestId: string,\n ) {\n super(`Attachment upload ${stage} request conflicts with an existing operation`);\n this.name = 'AttachmentUploadConflictError';\n }\n}\n\nexport interface AttachmentUploadStoreContext {\n /** Authenticated transport principal; never sourced from caller parameters. */\n ownerPeerId: string;\n signal?: AbortSignal;\n}\n\nexport interface AttachmentUploadIdempotencyRecord {\n stage: AttachmentUploadStage;\n ownerPeerId: string;\n conversationId: string;\n requestId: string;\n fingerprint: string;\n}\n\nexport interface PersistAttachmentUploadChunkInput extends Omit<UploadAttachmentChunkRequest, 'encoding' | 'data'> {\n /** Strictly decoded and, when requested, SHA-256 verified bytes. */\n data: Uint8Array;\n}\n\n/**\n * Durable streaming upload port. Implementations must not buffer a complete\n * upload in process memory. They must scope uploadId to conversationId and\n * the authenticated `ownerPeerId`, account quota/expiry to that owner, and\n * atomically enforce these idempotency rules:\n *\n * - the same `(stage, conversationId, requestId)` and operation fingerprint\n * returns the stored result;\n * - reusing that key with another fingerprint throws\n * `AttachmentUploadConflictError`;\n * - the same chunk operation at `(conversationId, uploadId, offset)` returns\n * the same result, while a different request, bytes, or length conflicts;\n * - a repeated identical commit returns its original attachment, while size\n * or digest drift conflicts.\n */\nexport interface AttachmentUploadStore {\n beginAttachmentUpload(\n request: BeginAttachmentUploadRequest,\n context: AttachmentUploadStoreContext,\n ): Promise<BeginAttachmentUploadResponse>;\n writeAttachmentUploadChunk(\n request: PersistAttachmentUploadChunkInput,\n context: AttachmentUploadStoreContext,\n ): Promise<UploadAttachmentChunkResponse>;\n commitAttachmentUpload(\n request: CommitAttachmentUploadRequest,\n context: AttachmentUploadStoreContext,\n ): Promise<CommitAttachmentUploadResponse>;\n}\n\nexport interface AttachmentUploadRpcCallOptions {\n signal?: AbortSignal;\n}\n\nexport type AttachmentUploadRpcCall = <M extends AttachmentUploadRpcMethod>(\n method: M,\n request: AttachmentUploadRpcRequest<M>,\n options?: AttachmentUploadRpcCallOptions,\n) => Promise<unknown>;\n\nexport interface AttachmentUploadRpcClientOptions {\n call: AttachmentUploadRpcCall;\n}\n\n/**\n * Typed browser/mobile client over an injected RPC call. This only streams\n * bounded chunks; it intentionally provides no full-file buffering fallback.\n */\nexport function createAttachmentUploadRpcClient(\n options: AttachmentUploadRpcClientOptions,\n) {\n async function request<M extends AttachmentUploadRpcMethod>(\n method: M,\n parameters: AttachmentUploadRpcRequest<M>,\n callOptions: AttachmentUploadRpcCallOptions = {},\n ): Promise<AttachmentUploadRpcResponse<M>> {\n callOptions.signal?.throwIfAborted();\n assertAttachmentUploadRpcRequest(method, parameters);\n if (method === ATTACHMENT_UPLOAD_RPC_METHODS.chunk) {\n await decodeAttachmentUploadChunk(parameters as UploadAttachmentChunkRequest);\n }\n callOptions.signal?.throwIfAborted();\n const raw = await options.call(method, parameters, callOptions);\n const response = parseAttachmentUploadRpcResponse(method, raw);\n assertAttachmentUploadRpcResponseCorrelation(method, parameters, response);\n return response;\n }\n\n return {\n begin: (\n parameters: BeginAttachmentUploadRequest,\n callOptions: AttachmentUploadRpcCallOptions = {},\n ) => request(ATTACHMENT_UPLOAD_RPC_METHODS.begin, parameters, callOptions),\n chunk: (\n parameters: UploadAttachmentChunkRequest,\n callOptions: AttachmentUploadRpcCallOptions = {},\n ) => request(ATTACHMENT_UPLOAD_RPC_METHODS.chunk, parameters, callOptions),\n commit: (\n parameters: CommitAttachmentUploadRequest,\n callOptions: AttachmentUploadRpcCallOptions = {},\n ) => request(ATTACHMENT_UPLOAD_RPC_METHODS.commit, parameters, callOptions),\n };\n}\n\nexport type AttachmentUploadRpcClient = ReturnType<typeof createAttachmentUploadRpcClient>;\n\n/** Validate an untrusted request, including actual base64 decoding for chunks. */\nexport function assertAttachmentUploadRpcRequest<M extends AttachmentUploadRpcMethod>(\n method: M,\n value: unknown,\n): asserts value is AttachmentUploadRpcRequest<M> {\n const record = asRecord(value, 'request');\n assertOperationIdentity(record, 'request');\n switch (method) {\n case ATTACHMENT_UPLOAD_RPC_METHODS.begin:\n assertExactKeys(record, [\n 'requestId',\n 'conversationId',\n 'filename',\n 'mimeType',\n 'totalBytes',\n ], 'request');\n assertText(record.filename, 'request.filename', ATTACHMENT_UPLOAD_LIMITS.filenameCharacters);\n assertText(record.mimeType, 'request.mimeType', ATTACHMENT_UPLOAD_LIMITS.mimeTypeCharacters);\n assertInteger(record.totalBytes, 'request.totalBytes', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n return;\n case ATTACHMENT_UPLOAD_RPC_METHODS.chunk: {\n assertExactKeys(record, [\n 'requestId',\n 'conversationId',\n 'uploadId',\n 'offset',\n 'byteLength',\n 'encoding',\n 'data',\n 'sha256',\n ], 'request');\n assertIdentifier(record.uploadId, 'request.uploadId');\n assertInteger(record.offset, 'request.offset', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n assertInteger(record.byteLength, 'request.byteLength', 1, ATTACHMENT_UPLOAD_LIMITS.chunkBytes);\n if (\n record.offset + record.byteLength >\n ATTACHMENT_UPLOAD_LIMITS.totalBytes\n ) fail('request.offset');\n if (record.encoding !== 'base64') fail('request.encoding');\n if (typeof record.data !== 'string') fail('request.data');\n const bytes = attachmentUploadBase64ToBytes(record.data);\n if (bytes.byteLength !== record.byteLength) fail('request.byteLength');\n if (record.sha256 !== undefined) assertSha256(record.sha256, 'request.sha256');\n return;\n }\n case ATTACHMENT_UPLOAD_RPC_METHODS.commit:\n assertExactKeys(record, [\n 'requestId',\n 'conversationId',\n 'uploadId',\n 'size',\n 'sha256',\n ], 'request');\n assertIdentifier(record.uploadId, 'request.uploadId');\n assertInteger(record.size, 'request.size', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n assertSha256(record.sha256, 'request.sha256');\n return;\n }\n}\n\n/** Parse and bound an untrusted successful response. */\nexport function parseAttachmentUploadRpcResponse<M extends AttachmentUploadRpcMethod>(\n method: M,\n value: unknown,\n): AttachmentUploadRpcResponse<M> {\n const record = asRecord(value, 'response');\n if (record.ok !== true) fail('response.ok');\n assertOperationIdentity(record, 'response');\n switch (method) {\n case ATTACHMENT_UPLOAD_RPC_METHODS.begin:\n assertExactKeys(record, [\n 'ok',\n 'requestId',\n 'conversationId',\n 'uploadId',\n 'totalBytes',\n 'maxChunkBytes',\n ], 'response');\n assertIdentifier(record.uploadId, 'response.uploadId');\n assertInteger(record.totalBytes, 'response.totalBytes', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n assertInteger(record.maxChunkBytes, 'response.maxChunkBytes', 1, ATTACHMENT_UPLOAD_LIMITS.chunkBytes);\n break;\n case ATTACHMENT_UPLOAD_RPC_METHODS.chunk:\n assertExactKeys(record, [\n 'ok',\n 'requestId',\n 'conversationId',\n 'uploadId',\n 'offset',\n 'byteLength',\n ], 'response');\n assertIdentifier(record.uploadId, 'response.uploadId');\n assertInteger(record.offset, 'response.offset', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n assertInteger(record.byteLength, 'response.byteLength', 1, ATTACHMENT_UPLOAD_LIMITS.chunkBytes);\n break;\n case ATTACHMENT_UPLOAD_RPC_METHODS.commit:\n assertExactKeys(record, [\n 'ok',\n 'requestId',\n 'conversationId',\n 'uploadId',\n 'attachment',\n ], 'response');\n assertIdentifier(record.uploadId, 'response.uploadId');\n assertAttachmentReference(record.attachment, 'response.attachment');\n break;\n }\n return value as AttachmentUploadRpcResponse<M>;\n}\n\n/** Reject a valid-shaped response from another upload operation or scope. */\nexport function assertAttachmentUploadRpcResponseCorrelation<M extends AttachmentUploadRpcMethod>(\n method: M,\n request: AttachmentUploadRpcRequest<M>,\n response: AttachmentUploadRpcResponse<M>,\n): void {\n if (\n response.requestId !== request.requestId ||\n response.conversationId !== request.conversationId\n ) fail('response');\n switch (method) {\n case ATTACHMENT_UPLOAD_RPC_METHODS.begin: {\n const beginRequest = request as BeginAttachmentUploadRequest;\n const beginResponse = response as BeginAttachmentUploadResponse;\n if (beginResponse.totalBytes !== beginRequest.totalBytes) fail('response.totalBytes');\n return;\n }\n case ATTACHMENT_UPLOAD_RPC_METHODS.chunk: {\n const chunkRequest = request as UploadAttachmentChunkRequest;\n const chunkResponse = response as UploadAttachmentChunkResponse;\n if (\n chunkResponse.uploadId !== chunkRequest.uploadId ||\n chunkResponse.offset !== chunkRequest.offset ||\n chunkResponse.byteLength !== chunkRequest.byteLength\n ) fail('response');\n return;\n }\n case ATTACHMENT_UPLOAD_RPC_METHODS.commit: {\n const commitRequest = request as CommitAttachmentUploadRequest;\n const commitResponse = response as CommitAttachmentUploadResponse;\n if (\n commitResponse.uploadId !== commitRequest.uploadId ||\n commitResponse.attachment.contentHash !== commitRequest.sha256 ||\n commitResponse.attachment.size !== commitRequest.size\n ) fail('response.attachment');\n return;\n }\n }\n}\n\n/**\n * Strictly decode a chunk and verify its optional SHA-256 before storage. The\n * returned bytes are independently owned and safe to pass to an async store.\n */\nexport async function decodeAttachmentUploadChunk(\n request: UploadAttachmentChunkRequest,\n): Promise<Uint8Array> {\n assertAttachmentUploadRpcRequest(ATTACHMENT_UPLOAD_RPC_METHODS.chunk, request);\n const bytes = attachmentUploadBase64ToBytes(request.data);\n if (request.sha256 !== undefined && await sha256AttachmentUploadBytes(bytes) !== request.sha256) {\n fail('request.sha256');\n }\n return bytes;\n}\n\nexport interface BuildAttachmentUploadChunkRequestInput extends Omit<UploadAttachmentChunkRequest, 'encoding' | 'data' | 'byteLength' | 'sha256'> {\n data: Uint8Array;\n /** Include a portable WebCrypto SHA-256 integrity check for this chunk. */\n includeSha256?: boolean;\n}\n\n/** Encode already-bounded bytes into the canonical chunk wire request. */\nexport async function buildAttachmentUploadChunkRequest(\n input: BuildAttachmentUploadChunkRequestInput,\n): Promise<UploadAttachmentChunkRequest> {\n const normalized = normalizeBuildAttachmentUploadChunkRequestInput(input);\n const data = normalizePortableUint8Array(\n normalized.data,\n 'request.data',\n 1,\n ATTACHMENT_UPLOAD_LIMITS.chunkBytes,\n 'request.byteLength',\n );\n const request: UploadAttachmentChunkRequest = {\n requestId: normalized.requestId,\n conversationId: normalized.conversationId,\n uploadId: normalized.uploadId,\n offset: normalized.offset,\n byteLength: data.byteLength,\n encoding: 'base64',\n data: encodeAttachmentUploadOwnedBytes(data),\n ...(normalized.includeSha256\n ? { sha256: await sha256OwnedAttachmentUploadBytes(data) }\n : {}),\n };\n assertAttachmentUploadRpcRequest(ATTACHMENT_UPLOAD_RPC_METHODS.chunk, request);\n return request;\n}\n\n/** Canonical operation digest suitable for a durable idempotency record. */\nexport async function fingerprintAttachmentUploadOperation<M extends AttachmentUploadRpcMethod>(\n method: M,\n request: AttachmentUploadRpcRequest<M>,\n): Promise<string> {\n assertAttachmentUploadRpcRequest(method, request);\n const canonical = method === ATTACHMENT_UPLOAD_RPC_METHODS.begin\n ? canonicalBegin(request as BeginAttachmentUploadRequest)\n : method === ATTACHMENT_UPLOAD_RPC_METHODS.chunk\n ? canonicalChunk(request as UploadAttachmentChunkRequest)\n : canonicalCommit(request as CommitAttachmentUploadRequest);\n return sha256AttachmentUploadBytes(new TextEncoder().encode(canonical));\n}\n\n/** Build the small durable record used to compare a retry with its first operation. */\nexport async function buildAttachmentUploadIdempotencyRecord<M extends AttachmentUploadRpcMethod>(\n method: M,\n request: AttachmentUploadRpcRequest<M>,\n ownerPeerId: string,\n): Promise<AttachmentUploadIdempotencyRecord> {\n assertIdentifier(ownerPeerId, 'ownerPeerId');\n return {\n stage: attachmentUploadStage(method),\n ownerPeerId,\n conversationId: request.conversationId,\n requestId: request.requestId,\n fingerprint: await fingerprintAttachmentUploadOperation(method, request),\n };\n}\n\n/** Accept an identical retry or throw the standard conflict for any drift. */\nexport async function assertAttachmentUploadIdempotentReplay<M extends AttachmentUploadRpcMethod>(\n existing: AttachmentUploadIdempotencyRecord,\n method: M,\n request: AttachmentUploadRpcRequest<M>,\n ownerPeerId: string,\n): Promise<void> {\n const next = await buildAttachmentUploadIdempotencyRecord(method, request, ownerPeerId);\n if (\n existing.stage !== next.stage ||\n existing.ownerPeerId !== next.ownerPeerId ||\n existing.conversationId !== next.conversationId ||\n existing.requestId !== next.requestId ||\n existing.fingerprint !== next.fingerprint\n ) {\n throw new AttachmentUploadConflictError(next.stage, next.requestId);\n }\n}\n\nexport async function sha256AttachmentUploadBytes(bytes: Uint8Array): Promise<string> {\n const owned = normalizePortableUint8Array(\n bytes,\n 'sha256.input',\n 0,\n ATTACHMENT_UPLOAD_LIMITS.totalBytes,\n 'sha256.input',\n );\n return sha256OwnedAttachmentUploadBytes(owned);\n}\n\nasync function sha256OwnedAttachmentUploadBytes(owned: Uint8Array<ArrayBuffer>): Promise<string> {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) fail('sha256.unavailable');\n const digest = new Uint8Array(await subtle.digest('SHA-256', owned));\n return `sha256:${[...digest].map(byte => byte.toString(16).padStart(2, '0')).join('')}`;\n}\n\n/** Strict canonical RFC 4648 base64 decoder with no Node Buffer dependency. */\nexport function attachmentUploadBase64ToBytes(value: string): Uint8Array {\n if (\n value.length === 0 ||\n value.length > ATTACHMENT_UPLOAD_LIMITS.chunkBase64Characters ||\n value.length % 4 !== 0 ||\n !/^(?:[A-Za-z\\d+/]{4})*(?:[A-Za-z\\d+/]{2}==|[A-Za-z\\d+/]{3}=)?$/u.test(value)\n ) fail('request.data');\n const padding = value.endsWith('==') ? 2 : value.endsWith('=') ? 1 : 0;\n const byteLength = (value.length / 4) * 3 - padding;\n if (byteLength <= 0 || byteLength > ATTACHMENT_UPLOAD_LIMITS.chunkBytes) {\n fail('request.data');\n }\n const result = new Uint8Array(byteLength);\n let writeOffset = 0;\n for (let offset = 0; offset < value.length; offset += 4) {\n const bits = (base64Value(value.charCodeAt(offset)) << 18) |\n (base64Value(value.charCodeAt(offset + 1)) << 12) |\n (value[offset + 2] === '=' ? 0 : base64Value(value.charCodeAt(offset + 2)) << 6) |\n (value[offset + 3] === '=' ? 0 : base64Value(value.charCodeAt(offset + 3)));\n if (writeOffset < byteLength) result[writeOffset++] = (bits >>> 16) & 0xFF;\n if (writeOffset < byteLength) result[writeOffset++] = (bits >>> 8) & 0xFF;\n if (writeOffset < byteLength) result[writeOffset++] = bits & 0xFF;\n }\n if (encodeAttachmentUploadOwnedBytes(result) !== value) fail('request.data');\n return result;\n}\n\n/** Canonical RFC 4648 base64 encoder with no Node Buffer/btoa dependency. */\nexport function attachmentUploadBytesToBase64(bytes: Uint8Array): string {\n const owned = normalizePortableUint8Array(\n bytes,\n 'request.data',\n 0,\n ATTACHMENT_UPLOAD_LIMITS.chunkBytes,\n 'request.byteLength',\n );\n return encodeAttachmentUploadOwnedBytes(owned);\n}\n\nfunction encodeAttachmentUploadOwnedBytes(bytes: Uint8Array): string {\n const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n let encoded = '';\n for (let offset = 0; offset < bytes.length; offset += 3) {\n const remaining = bytes.length - offset;\n const bits = (bytes[offset] << 16) |\n ((remaining > 1 ? bytes[offset + 1] : 0) << 8) |\n (remaining > 2 ? bytes[offset + 2] : 0);\n encoded += alphabet[(bits >>> 18) & 63];\n encoded += alphabet[(bits >>> 12) & 63];\n encoded += remaining > 1 ? alphabet[(bits >>> 6) & 63] : '=';\n encoded += remaining > 2 ? alphabet[bits & 63] : '=';\n }\n return encoded;\n}\n\nfunction canonicalBegin(request: BeginAttachmentUploadRequest): string {\n return JSON.stringify({\n method: ATTACHMENT_UPLOAD_RPC_METHODS.begin,\n requestId: request.requestId,\n conversationId: request.conversationId,\n filename: request.filename,\n mimeType: request.mimeType,\n totalBytes: request.totalBytes,\n });\n}\n\nfunction canonicalChunk(request: UploadAttachmentChunkRequest): string {\n return JSON.stringify({\n method: ATTACHMENT_UPLOAD_RPC_METHODS.chunk,\n requestId: request.requestId,\n conversationId: request.conversationId,\n uploadId: request.uploadId,\n offset: request.offset,\n byteLength: request.byteLength,\n encoding: request.encoding,\n data: request.data,\n ...(request.sha256 === undefined ? {} : { sha256: request.sha256 }),\n });\n}\n\nfunction canonicalCommit(request: CommitAttachmentUploadRequest): string {\n return JSON.stringify({\n method: ATTACHMENT_UPLOAD_RPC_METHODS.commit,\n requestId: request.requestId,\n conversationId: request.conversationId,\n uploadId: request.uploadId,\n size: request.size,\n sha256: request.sha256,\n });\n}\n\nfunction attachmentUploadStage(method: AttachmentUploadRpcMethod): AttachmentUploadStage {\n if (method === ATTACHMENT_UPLOAD_RPC_METHODS.begin) return 'begin';\n if (method === ATTACHMENT_UPLOAD_RPC_METHODS.chunk) return 'chunk';\n return 'commit';\n}\n\ninterface NormalizedBuildAttachmentUploadChunkRequestInput {\n requestId: string;\n conversationId: string;\n uploadId: string;\n offset: number;\n data: unknown;\n includeSha256: boolean;\n}\n\nfunction normalizeBuildAttachmentUploadChunkRequestInput(\n value: unknown,\n): NormalizedBuildAttachmentUploadChunkRequestInput {\n const descriptors = readPlainDataDescriptors(\n value,\n ['requestId', 'conversationId', 'uploadId', 'offset', 'data'],\n ['includeSha256'],\n 'request',\n );\n const requestId = readDescriptorValue(descriptors, 'requestId', 'request.requestId');\n const conversationId = readDescriptorValue(descriptors, 'conversationId', 'request.conversationId');\n const uploadId = readDescriptorValue(descriptors, 'uploadId', 'request.uploadId');\n const offset = readDescriptorValue(descriptors, 'offset', 'request.offset');\n const data = readDescriptorValue(descriptors, 'data', 'request.data');\n const includeSha256 = Object.prototype.hasOwnProperty.call(descriptors, 'includeSha256')\n ? readDescriptorValue(descriptors, 'includeSha256', 'request.includeSha256')\n : false;\n assertIdentifier(requestId, 'request.requestId');\n assertIdentifier(conversationId, 'request.conversationId');\n assertIdentifier(uploadId, 'request.uploadId');\n assertInteger(offset, 'request.offset', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n if (typeof includeSha256 !== 'boolean') fail('request.includeSha256');\n return { requestId, conversationId, uploadId, offset, data, includeSha256 };\n}\n\ntype OwnDescriptorRecord = Readonly<Record<PropertyKey, PropertyDescriptor>>;\n\nfunction readPlainDataDescriptors(\n value: unknown,\n required: readonly string[],\n optional: readonly string[],\n field: string,\n): OwnDescriptorRecord {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) fail(field);\n let descriptors: PropertyDescriptorMap;\n try {\n const prototype = Object.getPrototypeOf(value) as object | null;\n if (!isPlainObjectPrototype(prototype)) fail(field);\n descriptors = Object.getOwnPropertyDescriptors(value);\n } catch (error) {\n if (error instanceof AttachmentUploadProtocolError) throw error;\n fail(field);\n }\n const allowed = new Set([...required, ...optional]);\n const keys = Reflect.ownKeys(descriptors);\n if (\n keys.some(key => typeof key !== 'string' || !allowed.has(key)) ||\n required.some(key => !Object.prototype.hasOwnProperty.call(descriptors, key))\n ) fail(field);\n for (const key of keys) {\n const descriptor = descriptors[key];\n if (!descriptor?.enumerable || !('value' in descriptor)) fail(field);\n }\n return descriptors;\n}\n\nfunction readDescriptorValue(\n descriptors: OwnDescriptorRecord,\n key: string,\n field: string,\n): unknown {\n const descriptor = descriptors[key];\n if (!descriptor || !('value' in descriptor)) fail(field);\n return descriptor.value;\n}\n\nfunction isPlainObjectPrototype(prototype: object | null): boolean {\n if (prototype === null || prototype === Object.prototype) return true;\n try {\n if (Object.getPrototypeOf(prototype) !== null) return false;\n const constructor = Object.getOwnPropertyDescriptor(prototype, 'constructor');\n const constructorValue: unknown = constructor && 'value' in constructor\n ? constructor.value as unknown\n : undefined;\n return typeof constructorValue === 'function' && constructorValue.name === 'Object';\n } catch {\n return false;\n }\n}\n\n/**\n * Brand-check a cross-realm Uint8Array using the unforgeable typed-array\n * intrinsic tag getter, then copy through its ordinary ArrayBuffer slots.\n * Object#toString, constructors, species, and caller properties are ignored.\n */\nfunction normalizePortableUint8Array(\n value: unknown,\n field: string,\n minimumBytes: number,\n maximumBytes: number,\n sizeField: string,\n): Uint8Array<ArrayBuffer> {\n if (!ArrayBuffer.isView(value)) fail(field);\n try {\n if (readTypedArrayIntrinsic(value, Symbol.toStringTag) !== 'Uint8Array') fail(field);\n const buffer = readTypedArrayIntrinsic(value, 'buffer');\n const byteOffset = readTypedArrayIntrinsic(value, 'byteOffset');\n const byteLength = readTypedArrayIntrinsic(value, 'byteLength');\n if (\n buffer === null ||\n typeof buffer !== 'object' ||\n typeof byteOffset !== 'number' ||\n !Number.isSafeInteger(byteOffset) ||\n byteOffset < 0 ||\n typeof byteLength !== 'number' ||\n !Number.isSafeInteger(byteLength) ||\n byteLength < minimumBytes ||\n byteLength > maximumBytes\n ) fail(sizeField);\n assertOrdinaryArrayBuffer(buffer);\n // A current-realm view avoids caller iterator/species/property access; the\n // second construction owns a detached-independent byte copy.\n return new Uint8Array(new Uint8Array(buffer as ArrayBuffer, byteOffset, byteLength));\n } catch (error) {\n if (error instanceof AttachmentUploadProtocolError) throw error;\n fail(field);\n }\n}\n\nfunction readTypedArrayIntrinsic(value: object, key: PropertyKey): unknown {\n const typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype) as object | null;\n if (!typedArrayPrototype) fail('request.data');\n const descriptor = Object.getOwnPropertyDescriptor(typedArrayPrototype, key);\n const getter: unknown = descriptor === undefined ? undefined : Reflect.get(descriptor, 'get');\n if (typeof getter !== 'function') fail('request.data');\n return Reflect.apply(getter, value, []);\n}\n\nfunction assertOrdinaryArrayBuffer(value: object): void {\n const descriptor = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, 'byteLength');\n const getter: unknown = descriptor === undefined ? undefined : Reflect.get(descriptor, 'get');\n if (typeof getter !== 'function') fail('request.data');\n // The ArrayBuffer intrinsic rejects SharedArrayBuffer and forged objects.\n Reflect.apply(getter, value, []);\n}\n\nfunction asRecord(value: unknown, field: string): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) fail(field);\n return value as Record<string, unknown>;\n}\n\nfunction assertExactKeys(\n record: Record<string, unknown>,\n keys: readonly string[],\n field: string,\n): void {\n const actual = Object.keys(record);\n if (actual.some(key => !keys.includes(key))) fail(field);\n}\n\nfunction assertOperationIdentity(record: Record<string, unknown>, field: string): void {\n assertIdentifier(record.requestId, `${field}.requestId`);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n}\n\nfunction assertIdentifier(value: unknown, field: string): asserts value is string {\n assertText(value, field, ATTACHMENT_UPLOAD_LIMITS.identifierCharacters);\n}\n\nfunction assertText(\n value: unknown,\n field: string,\n maximumCharacters: number,\n): asserts value is string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.length > maximumCharacters ||\n value !== value.trim()\n ) fail(field);\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) fail(field);\n }\n}\n\nfunction assertInteger(\n value: unknown,\n field: string,\n minimum: number,\n maximum: number,\n): asserts value is number {\n if (!Number.isSafeInteger(value) || (value as number) < minimum || (value as number) > maximum) {\n fail(field);\n }\n}\n\nfunction assertSha256(value: unknown, field: string): asserts value is string {\n if (typeof value !== 'string' || !ATTACHMENT_UPLOAD_SHA256_PATTERN.test(value)) fail(field);\n}\n\nfunction assertAttachmentReference(\n value: unknown,\n field: string,\n): asserts value is AttachmentReference {\n const record = asRecord(value, field);\n assertExactKeys(record, ['contentHash', 'filename', 'mimeType', 'size'], field);\n assertSha256(record.contentHash, `${field}.contentHash`);\n assertText(record.filename, `${field}.filename`, ATTACHMENT_UPLOAD_LIMITS.filenameCharacters);\n assertText(record.mimeType, `${field}.mimeType`, ATTACHMENT_UPLOAD_LIMITS.mimeTypeCharacters);\n assertInteger(record.size, `${field}.size`, 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n}\n\nfunction base64Value(code: number): number {\n if (code >= 65 && code <= 90) return code - 65;\n if (code >= 97 && code <= 122) return code - 71;\n if (code >= 48 && code <= 57) return code + 4;\n if (code === 43) return 62;\n if (code === 47) return 63;\n fail('request.data');\n}\n\nfunction fail(field: string): never {\n throw new AttachmentUploadProtocolError(field);\n}\n","import type { CreateScheduledTaskInput, ListScheduledTasksOptions, ScheduledTask, ScheduledTaskClient, ScheduledTaskState } from '../agent-management/types.js';\nimport { canonicalJsonBytes } from '../encoding/canonicalJson.js';\n\nexport const SCHEDULED_TASK_RPC_METHODS = Object.freeze(\n {\n list: 'memeloop.schedule.list',\n get: 'memeloop.schedule.get',\n create: 'memeloop.schedule.create',\n update: 'memeloop.schedule.update',\n delete: 'memeloop.schedule.delete',\n cronPreview: 'memeloop.schedule.cronPreview',\n } as const,\n);\n\nexport type ScheduledTaskRpcMethod = typeof SCHEDULED_TASK_RPC_METHODS[keyof typeof SCHEDULED_TASK_RPC_METHODS];\n\nexport const SCHEDULED_TASK_RPC_LIMITS = Object.freeze(\n {\n identifierCharacters: 512,\n nameCharacters: 256,\n labelCharacters: 256,\n creatorCharacters: 256,\n cronExpressionCharacters: 256,\n timezoneCharacters: 128,\n messageCharacters: 32 * 1024,\n cursorCharacters: 2_048,\n listPage: 100,\n listPageDefaultBytes: 256 * 1024,\n listPageMaxBytes: 256 * 1024,\n executionNodeFilters: 64,\n cronPreviewDates: 10,\n } as const,\n);\n\nexport type ScheduledTaskRpcSchedule = CreateScheduledTaskInput['schedule'];\n\nexport interface ScheduledTaskRpcCreateInput {\n agentInstanceId: string;\n agentDefinitionId: string;\n name: string;\n schedule: ScheduledTaskRpcSchedule;\n payload?: { message: string };\n activeHoursStart?: string;\n activeHoursEnd?: string;\n createdBy?: string;\n enabled?: boolean;\n /** Must equal the authenticated node receiving this RPC. */\n executionNodeId: string;\n executionNodeLabel?: string;\n}\n\nexport interface ScheduledTaskRpcUpdatePatch {\n name?: string;\n schedule?: ScheduledTaskRpcSchedule;\n payload?: { message: string } | null;\n activeHoursStart?: string | null;\n activeHoursEnd?: string | null;\n enabled?: boolean;\n /** Repeated deliberately so a transfer cannot be hidden in an update. */\n executionNodeId?: string;\n executionNodeLabel?: string | null;\n}\n\nexport interface ScheduledTaskRpcListRequest {\n /** Agent instances are conversation-scoped resources. */\n agentInstanceId: string;\n /** Per-device RPCs may enumerate only the authenticated execution node. */\n executionNodeId: string;\n states?: ScheduledTaskState[];\n cursor?: string;\n limit?: number;\n /** Required storage and transport scan budget for the complete response. */\n maxBytes: number;\n}\n\nexport interface ScheduledTaskRpcListResponse {\n items: ScheduledTask[];\n nextCursor?: string;\n hasMoreAfter: boolean;\n}\n\nexport interface ScheduledTaskRpcScopedTaskRequest {\n taskId: string;\n agentInstanceId: string;\n agentDefinitionId: string;\n executionNodeId: string;\n}\n\nexport type ScheduledTaskRpcGetRequest = ScheduledTaskRpcScopedTaskRequest;\n\nexport interface ScheduledTaskRpcGetResponse {\n task: ScheduledTask | null;\n}\n\nexport interface ScheduledTaskRpcCreateRequest {\n input: ScheduledTaskRpcCreateInput;\n}\n\nexport interface ScheduledTaskRpcCreateResponse {\n task: ScheduledTask;\n}\n\nexport interface ScheduledTaskRpcUpdateRequest extends ScheduledTaskRpcScopedTaskRequest {\n patch: ScheduledTaskRpcUpdatePatch;\n}\n\nexport interface ScheduledTaskRpcUpdateResponse {\n task: ScheduledTask;\n}\n\nexport type ScheduledTaskRpcDeleteRequest = ScheduledTaskRpcScopedTaskRequest;\n\nexport interface ScheduledTaskRpcDeleteResponse {\n deleted: true;\n taskId: string;\n}\n\nexport interface ScheduledTaskRpcCronPreviewRequest {\n expression: string;\n timezone?: string;\n count?: number;\n}\n\nexport interface ScheduledTaskRpcCronPreviewResponse {\n dates: string[];\n}\n\nexport interface ScheduledTaskRpcContract {\n [SCHEDULED_TASK_RPC_METHODS.list]: {\n request: ScheduledTaskRpcListRequest;\n response: ScheduledTaskRpcListResponse;\n };\n [SCHEDULED_TASK_RPC_METHODS.get]: {\n request: ScheduledTaskRpcGetRequest;\n response: ScheduledTaskRpcGetResponse;\n };\n [SCHEDULED_TASK_RPC_METHODS.create]: {\n request: ScheduledTaskRpcCreateRequest;\n response: ScheduledTaskRpcCreateResponse;\n };\n [SCHEDULED_TASK_RPC_METHODS.update]: {\n request: ScheduledTaskRpcUpdateRequest;\n response: ScheduledTaskRpcUpdateResponse;\n };\n [SCHEDULED_TASK_RPC_METHODS.delete]: {\n request: ScheduledTaskRpcDeleteRequest;\n response: ScheduledTaskRpcDeleteResponse;\n };\n [SCHEDULED_TASK_RPC_METHODS.cronPreview]: {\n request: ScheduledTaskRpcCronPreviewRequest;\n response: ScheduledTaskRpcCronPreviewResponse;\n };\n}\n\nexport type ScheduledTaskRpcRequest<M extends ScheduledTaskRpcMethod> = ScheduledTaskRpcContract[M]['request'];\nexport type ScheduledTaskRpcResponse<M extends ScheduledTaskRpcMethod> = ScheduledTaskRpcContract[M]['response'];\n\nconst SCHEDULED_TASK_RPC_METHOD_SET = new Set<string>(\n Object.values(SCHEDULED_TASK_RPC_METHODS),\n);\n\nexport function isScheduledTaskRpcMethod(value: unknown): value is ScheduledTaskRpcMethod {\n return typeof value === 'string' && SCHEDULED_TASK_RPC_METHOD_SET.has(value);\n}\n\nexport class ScheduledTaskRpcProtocolError extends Error {\n readonly code = 'invalid_scheduled_task_rpc' as const;\n\n constructor(readonly field: string) {\n super(`Invalid scheduled task RPC ${field}`);\n this.name = 'ScheduledTaskRpcProtocolError';\n }\n}\n\n/** Validate every caller-controlled request before authorization or dispatch. */\nexport function assertScheduledTaskRpcRequest<M extends ScheduledTaskRpcMethod>(\n method: M,\n value: unknown,\n): asserts value is ScheduledTaskRpcRequest<M> {\n const request = asRecord(value, 'request');\n switch (method) {\n case SCHEDULED_TASK_RPC_METHODS.list:\n assertOnlyKeys(request, [\n 'agentInstanceId',\n 'executionNodeId',\n 'states',\n 'cursor',\n 'limit',\n 'maxBytes',\n ], 'request');\n assertIdentifier(request.agentInstanceId, 'request.agentInstanceId');\n assertIdentifier(request.executionNodeId, 'request.executionNodeId');\n optionalStateList(request.states, 'request.states');\n optionalBoundedString(\n request.cursor,\n 'request.cursor',\n SCHEDULED_TASK_RPC_LIMITS.cursorCharacters,\n );\n optionalInteger(\n request.limit,\n 'request.limit',\n 1,\n SCHEDULED_TASK_RPC_LIMITS.listPage,\n );\n if (request.maxBytes === undefined) fail('request.maxBytes');\n optionalInteger(\n request.maxBytes,\n 'request.maxBytes',\n 64,\n SCHEDULED_TASK_RPC_LIMITS.listPageMaxBytes,\n );\n return;\n case SCHEDULED_TASK_RPC_METHODS.get:\n case SCHEDULED_TASK_RPC_METHODS.delete:\n assertScopedTaskRequest(request, 'request');\n return;\n case SCHEDULED_TASK_RPC_METHODS.create:\n assertOnlyKeys(request, ['input'], 'request');\n assertCreateInput(request.input, 'request.input');\n return;\n case SCHEDULED_TASK_RPC_METHODS.update:\n assertOnlyKeys(request, [\n 'taskId',\n 'agentInstanceId',\n 'agentDefinitionId',\n 'executionNodeId',\n 'patch',\n ], 'request');\n assertIdentifier(request.taskId, 'request.taskId');\n assertIdentifier(request.agentInstanceId, 'request.agentInstanceId');\n assertIdentifier(request.agentDefinitionId, 'request.agentDefinitionId');\n assertIdentifier(request.executionNodeId, 'request.executionNodeId');\n assertUpdatePatch(request.patch, 'request.patch');\n return;\n case SCHEDULED_TASK_RPC_METHODS.cronPreview:\n assertOnlyKeys(request, ['expression', 'timezone', 'count'], 'request');\n assertBoundedString(\n request.expression,\n 'request.expression',\n SCHEDULED_TASK_RPC_LIMITS.cronExpressionCharacters,\n );\n optionalBoundedString(\n request.timezone,\n 'request.timezone',\n SCHEDULED_TASK_RPC_LIMITS.timezoneCharacters,\n );\n optionalInteger(\n request.count,\n 'request.count',\n 1,\n SCHEDULED_TASK_RPC_LIMITS.cronPreviewDates,\n );\n return;\n }\n}\n\n/** Parse and bound every untrusted server/store response. */\nexport function parseScheduledTaskRpcResponse<M extends ScheduledTaskRpcMethod>(\n method: M,\n value: unknown,\n): ScheduledTaskRpcResponse<M> {\n const response = asRecord(value, 'response');\n switch (method) {\n case SCHEDULED_TASK_RPC_METHODS.list:\n assertOnlyKeys(response, ['items', 'nextCursor', 'hasMoreAfter'], 'response');\n assertArray(response.items, 'response.items');\n if (response.items.length > SCHEDULED_TASK_RPC_LIMITS.listPage) {\n fail('response.items');\n }\n for (const task of response.items) assertScheduledTask(task, 'response.items[]');\n optionalBoundedString(\n response.nextCursor,\n 'response.nextCursor',\n SCHEDULED_TASK_RPC_LIMITS.cursorCharacters,\n );\n if (\n typeof response.hasMoreAfter !== 'boolean' ||\n response.hasMoreAfter !== (response.nextCursor !== undefined)\n ) fail('response.hasMoreAfter');\n break;\n case SCHEDULED_TASK_RPC_METHODS.get:\n assertOnlyKeys(response, ['task'], 'response');\n if (response.task !== null) assertScheduledTask(response.task, 'response.task');\n break;\n case SCHEDULED_TASK_RPC_METHODS.create:\n case SCHEDULED_TASK_RPC_METHODS.update:\n assertOnlyKeys(response, ['task'], 'response');\n assertScheduledTask(response.task, 'response.task');\n break;\n case SCHEDULED_TASK_RPC_METHODS.delete:\n assertOnlyKeys(response, ['deleted', 'taskId'], 'response');\n if (response.deleted !== true) fail('response.deleted');\n assertIdentifier(response.taskId, 'response.taskId');\n break;\n case SCHEDULED_TASK_RPC_METHODS.cronPreview:\n assertOnlyKeys(response, ['dates'], 'response');\n assertArray(response.dates, 'response.dates');\n if (response.dates.length > SCHEDULED_TASK_RPC_LIMITS.cronPreviewDates) {\n fail('response.dates');\n }\n assertCanonicalDates(response.dates, 'response.dates');\n break;\n }\n return response as unknown as ScheduledTaskRpcResponse<M>;\n}\n\nexport interface ScheduledTaskRpcGrantResources {\n conversationId?: string;\n definitionId?: string;\n /** This is a transport target check, never a Cloud-grant authority claim. */\n executionNodeId?: string;\n}\n\n/** Validate and extract the resource tuple consumed by the shared grant check. */\nexport function parseScheduledTaskRpcGrantResources(\n method: string,\n parameters: unknown,\n): ScheduledTaskRpcGrantResources {\n if (!isScheduledTaskRpcMethod(method)) fail('method');\n assertScheduledTaskRpcRequest(method, parameters);\n const request = parameters as unknown as Record<string, unknown>;\n switch (method) {\n case SCHEDULED_TASK_RPC_METHODS.list:\n return {\n conversationId: request.agentInstanceId as string,\n executionNodeId: request.executionNodeId as string,\n };\n case SCHEDULED_TASK_RPC_METHODS.get:\n case SCHEDULED_TASK_RPC_METHODS.delete:\n return scopedTaskResources(request);\n case SCHEDULED_TASK_RPC_METHODS.create: {\n const input = request.input as ScheduledTaskRpcCreateInput;\n return {\n conversationId: input.agentInstanceId,\n definitionId: input.agentDefinitionId,\n executionNodeId: input.executionNodeId,\n };\n }\n case SCHEDULED_TASK_RPC_METHODS.update:\n return scopedTaskResources(request);\n case SCHEDULED_TASK_RPC_METHODS.cronPreview:\n return {};\n }\n}\n\nexport interface ScheduledTaskRpcStoreContext {\n /** Authenticated libp2p caller; stores must use this as origin on create. */\n remotePeerId: string;\n /** Authenticated node handling and executing this task. */\n localPeerId: string;\n /**\n * End-to-end RPC cancellation. Durable adapters must observe this before\n * committing a write and must stop bounded reads as soon as it aborts.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Narrow durable port. Update/delete implementations MUST atomically match the\n * complete taskId+agentInstanceId+agentDefinitionId+executionNodeId tuple.\n */\nexport interface ScheduledAgentTaskStore {\n /** Keyset read that must stop scanning before `request.maxBytes` is exceeded. */\n list(\n request: ScheduledTaskRpcListRequest,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<ScheduledTaskRpcListResponse>;\n get(\n request: ScheduledTaskRpcGetRequest,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<ScheduledTask | undefined>;\n create(\n input: ScheduledTaskRpcCreateInput,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<ScheduledTask>;\n update(\n request: ScheduledTaskRpcUpdateRequest,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<ScheduledTask>;\n delete(\n request: ScheduledTaskRpcDeleteRequest,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<void>;\n}\n\nexport interface ScheduledTaskCronPreviewer {\n preview(\n request: ScheduledTaskRpcCronPreviewRequest,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<readonly string[]>;\n}\n\nexport interface ScheduledTaskRpcHandlerOptions {\n localPeerId: string;\n store?: ScheduledAgentTaskStore;\n cronPreviewer?: ScheduledTaskCronPreviewer;\n}\n\nexport interface ScheduledTaskRpcHandlerInput {\n remotePeerId: string;\n method: ScheduledTaskRpcMethod;\n parameters: unknown;\n signal?: AbortSignal;\n}\n\n/** Optional adapter used by the main RPC handler after its shared grant check. */\nexport function createScheduledTaskRpcHandler(options: ScheduledTaskRpcHandlerOptions) {\n assertIdentifier(options.localPeerId, 'options.localPeerId');\n return async (input: ScheduledTaskRpcHandlerInput): Promise<unknown> => {\n input.signal?.throwIfAborted();\n assertIdentifier(input.remotePeerId, 'input.remotePeerId');\n assertScheduledTaskRpcRequest(input.method, input.parameters);\n const resources = parseScheduledTaskRpcGrantResources(input.method, input.parameters);\n if (\n resources.executionNodeId !== undefined &&\n resources.executionNodeId !== options.localPeerId\n ) {\n throw new Error('scheduled_task_execution_target_mismatch');\n }\n const context: ScheduledTaskRpcStoreContext = {\n remotePeerId: input.remotePeerId,\n localPeerId: options.localPeerId,\n ...(input.signal === undefined ? {} : { signal: input.signal }),\n };\n let response: unknown;\n switch (input.method) {\n case SCHEDULED_TASK_RPC_METHODS.list:\n response = await requireStore(options).list(\n input.parameters as ScheduledTaskRpcListRequest,\n context,\n );\n break;\n case SCHEDULED_TASK_RPC_METHODS.get: {\n const task = await requireStore(options).get(\n input.parameters as ScheduledTaskRpcGetRequest,\n context,\n );\n response = { task: task ?? null };\n break;\n }\n case SCHEDULED_TASK_RPC_METHODS.create: {\n const request = input.parameters as ScheduledTaskRpcCreateRequest;\n response = { task: await requireStore(options).create(request.input, context) };\n break;\n }\n case SCHEDULED_TASK_RPC_METHODS.update:\n response = {\n task: await requireStore(options).update(\n input.parameters as ScheduledTaskRpcUpdateRequest,\n context,\n ),\n };\n break;\n case SCHEDULED_TASK_RPC_METHODS.delete: {\n const request = input.parameters as ScheduledTaskRpcDeleteRequest;\n await requireStore(options).delete(request, context);\n response = { deleted: true, taskId: request.taskId };\n break;\n }\n case SCHEDULED_TASK_RPC_METHODS.cronPreview: {\n if (!options.cronPreviewer) {\n throw new Error('scheduled_task_cron_previewer_unavailable');\n }\n const dates = await options.cronPreviewer.preview(\n input.parameters as ScheduledTaskRpcCronPreviewRequest,\n context,\n );\n response = { dates: [...dates] };\n break;\n }\n }\n input.signal?.throwIfAborted();\n const parsed = parseScheduledTaskRpcResponse(input.method, response);\n assertScheduledTaskRpcResponseCorrelation(input.method, input.parameters, parsed);\n if (\n input.method === SCHEDULED_TASK_RPC_METHODS.create &&\n (parsed as ScheduledTaskRpcCreateResponse).task.originNodeId !== input.remotePeerId\n ) {\n throw new Error('scheduled_task_origin_peer_mismatch');\n }\n return parsed;\n };\n}\n\nexport interface ScheduledTaskRpcCallOptions {\n signal?: AbortSignal;\n}\n\nexport type ScheduledTaskRpcCall = <M extends ScheduledTaskRpcMethod>(\n method: M,\n parameters: ScheduledTaskRpcRequest<M>,\n options?: ScheduledTaskRpcCallOptions,\n) => Promise<unknown>;\n\nexport function createScheduledTaskRpcClient(options: { call: ScheduledTaskRpcCall }) {\n async function request<M extends ScheduledTaskRpcMethod>(\n method: M,\n parameters: ScheduledTaskRpcRequest<M>,\n callOptions: ScheduledTaskRpcCallOptions = {},\n ): Promise<ScheduledTaskRpcResponse<M>> {\n callOptions.signal?.throwIfAborted();\n assertScheduledTaskRpcRequest(method, parameters);\n const untrustedResponse = await options.call(method, parameters, callOptions);\n callOptions.signal?.throwIfAborted();\n const response = parseScheduledTaskRpcResponse(method, untrustedResponse);\n assertScheduledTaskRpcResponseCorrelation(method, parameters, response);\n return response;\n }\n\n return {\n request,\n list: (\n parameters: ScheduledTaskRpcListRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => request(SCHEDULED_TASK_RPC_METHODS.list, parameters, callOptions),\n get: async (\n parameters: ScheduledTaskRpcGetRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => (await request(SCHEDULED_TASK_RPC_METHODS.get, parameters, callOptions)).task,\n create: async (\n parameters: ScheduledTaskRpcCreateRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => (await request(SCHEDULED_TASK_RPC_METHODS.create, parameters, callOptions)).task,\n update: async (\n parameters: ScheduledTaskRpcUpdateRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => (await request(SCHEDULED_TASK_RPC_METHODS.update, parameters, callOptions)).task,\n delete: async (\n parameters: ScheduledTaskRpcDeleteRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => request(SCHEDULED_TASK_RPC_METHODS.delete, parameters, callOptions),\n cronPreview: async (\n parameters: ScheduledTaskRpcCronPreviewRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => (await request(SCHEDULED_TASK_RPC_METHODS.cronPreview, parameters, callOptions)).dates,\n };\n}\n\nexport type ScheduledTaskRpcClient = ReturnType<typeof createScheduledTaskRpcClient>;\n\n/**\n * Adapt the typed RPC client to the existing editor contract. Task-scoped\n * writes require a task previously returned by list/create/update, so a bare\n * attacker-controlled task id can never become an authorization hint.\n */\nexport function createScheduledTaskClientFromRpc(options: {\n rpc: ScheduledTaskRpcClient;\n executionNodeId: string;\n originNodeId: string;\n}): ScheduledTaskClient {\n assertIdentifier(options.executionNodeId, 'options.executionNodeId');\n assertIdentifier(options.originNodeId, 'options.originNodeId');\n const knownTasks = new Map<string, ScheduledTask>();\n\n const remember = (task: ScheduledTask): ScheduledTask => {\n knownTasks.set(task.id, task);\n return task;\n };\n\n return {\n async listScheduledTasksForAgent(\n agentInstanceId: string,\n listOptions: ListScheduledTasksOptions = {},\n ) {\n listOptions.signal?.throwIfAborted();\n if (listOptions.executionNodeIds !== undefined) {\n if (\n listOptions.executionNodeIds.length > 64 ||\n new Set(listOptions.executionNodeIds).size !== listOptions.executionNodeIds.length\n ) throw new ScheduledTaskRpcProtocolError('options.executionNodeIds');\n for (const executionNodeId of listOptions.executionNodeIds) {\n assertIdentifier(executionNodeId, 'options.executionNodeIds[]');\n }\n }\n if (\n listOptions.executionNodeIds !== undefined &&\n !listOptions.executionNodeIds.includes(options.executionNodeId)\n ) {\n return {\n items: [],\n hasMoreAfter: false,\n partial: false,\n sources: [],\n };\n }\n if (\n listOptions.executionNodeIds?.some(nodeId => nodeId !== options.executionNodeId)\n ) {\n throw new ScheduledTaskRpcProtocolError('options.executionNodeIds');\n }\n const request: ScheduledTaskRpcListRequest = {\n agentInstanceId,\n executionNodeId: options.executionNodeId,\n states: listOptions.states ?? ['active', 'paused'],\n ...(listOptions.cursor === undefined ? {} : { cursor: listOptions.cursor }),\n limit: listOptions.limit ?? SCHEDULED_TASK_RPC_LIMITS.listPage,\n maxBytes: listOptions.maxBytes ?? SCHEDULED_TASK_RPC_LIMITS.listPageDefaultBytes,\n };\n const response = listOptions.signal === undefined\n ? await options.rpc.list(request)\n : await options.rpc.list(request, { signal: listOptions.signal });\n listOptions.signal?.throwIfAborted();\n for (const task of response.items) remember(task);\n return {\n ...response,\n partial: false,\n sources: [{ executionNodeId: options.executionNodeId, state: 'online', fromCache: false }],\n };\n },\n\n async createScheduledTask(input: CreateScheduledTaskInput, callOptions = {}): Promise<ScheduledTask> {\n callOptions.signal?.throwIfAborted();\n assertEditorInputIdentity(input, options);\n const request = { input: createInputFromEditor(input) };\n const task = callOptions.signal === undefined\n ? await options.rpc.create(request)\n : await options.rpc.create(request, callOptions);\n callOptions.signal?.throwIfAborted();\n return remember(task);\n },\n\n async updateScheduledTask(\n taskId: string,\n input: Partial<CreateScheduledTaskInput>,\n callOptions = {},\n ): Promise<ScheduledTask> {\n callOptions.signal?.throwIfAborted();\n const task = requireKnownTask(knownTasks, taskId);\n assertEditorPatchIdentity(input, task, options);\n const patch = updatePatchFromEditor(input);\n const request = {\n taskId,\n agentInstanceId: task.agentInstanceId,\n agentDefinitionId: task.agentDefinitionId,\n executionNodeId: task.executionNodeId,\n patch,\n };\n return remember(\n callOptions.signal === undefined\n ? await options.rpc.update(request)\n : await options.rpc.update(request, callOptions),\n );\n },\n\n async deleteScheduledTask(taskId: string, callOptions = {}): Promise<void> {\n callOptions.signal?.throwIfAborted();\n const task = requireKnownTask(knownTasks, taskId);\n const request = {\n taskId,\n agentInstanceId: task.agentInstanceId,\n agentDefinitionId: task.agentDefinitionId,\n executionNodeId: task.executionNodeId,\n };\n if (callOptions.signal === undefined) await options.rpc.delete(request);\n else await options.rpc.delete(request, callOptions);\n callOptions.signal?.throwIfAborted();\n knownTasks.delete(taskId);\n },\n\n getCronPreviewDates: (expression, timezone, count, callOptions) => options.rpc.cronPreview({ expression, timezone, count }, callOptions),\n };\n}\n\nexport function assertScheduledTaskRpcResponseCorrelation(\n method: ScheduledTaskRpcMethod,\n requestValue: unknown,\n responseValue: unknown,\n): void {\n assertScheduledTaskRpcRequest(method, requestValue);\n const response = parseScheduledTaskRpcResponse(method, responseValue);\n const request = requestValue as unknown as Record<string, unknown>;\n switch (method) {\n case SCHEDULED_TASK_RPC_METHODS.list: {\n const listRequest = requestValue as ScheduledTaskRpcListRequest;\n const listResponse = response as ScheduledTaskRpcListResponse;\n const limit = listRequest.limit ?? SCHEDULED_TASK_RPC_LIMITS.listPage;\n if (listResponse.items.length > limit) fail('response.items');\n try {\n canonicalJsonBytes(listResponse, {\n maxDepth: 16,\n maxNodes: 20_000,\n maxStringCodeUnits: SCHEDULED_TASK_RPC_LIMITS.messageCharacters,\n maxStringBytes: SCHEDULED_TASK_RPC_LIMITS.messageCharacters * 4,\n maxBytes: listRequest.maxBytes,\n });\n } catch {\n fail('response.maxBytes');\n }\n const seen = new Set<string>();\n for (const task of listResponse.items) {\n if (\n task.agentInstanceId !== listRequest.agentInstanceId ||\n task.executionNodeId !== listRequest.executionNodeId ||\n (listRequest.states !== undefined && !listRequest.states.includes(task.state)) ||\n seen.has(task.id)\n ) fail('response.items');\n seen.add(task.id);\n }\n return;\n }\n case SCHEDULED_TASK_RPC_METHODS.get: {\n const task = (response as ScheduledTaskRpcGetResponse).task;\n if (task) assertTaskMatchesScopedRequest(task, request, 'response.task');\n return;\n }\n case SCHEDULED_TASK_RPC_METHODS.create: {\n const input = request.input as ScheduledTaskRpcCreateInput;\n const task = (response as ScheduledTaskRpcCreateResponse).task;\n if (\n task.agentInstanceId !== input.agentInstanceId ||\n task.agentDefinitionId !== input.agentDefinitionId ||\n task.executionNodeId !== input.executionNodeId\n ) fail('response.task');\n return;\n }\n case SCHEDULED_TASK_RPC_METHODS.update:\n assertTaskMatchesScopedRequest(\n (response as ScheduledTaskRpcUpdateResponse).task,\n request,\n 'response.task',\n );\n return;\n case SCHEDULED_TASK_RPC_METHODS.delete:\n if ((response as ScheduledTaskRpcDeleteResponse).taskId !== request.taskId) {\n fail('response.taskId');\n }\n return;\n case SCHEDULED_TASK_RPC_METHODS.cronPreview: {\n const previewRequest = requestValue as ScheduledTaskRpcCronPreviewRequest;\n if (\n (response as ScheduledTaskRpcCronPreviewResponse).dates.length >\n (previewRequest.count ?? 3)\n ) fail('response.dates');\n return;\n }\n }\n}\n\nfunction requireStore(options: ScheduledTaskRpcHandlerOptions): ScheduledAgentTaskStore {\n if (!options.store) throw new Error('scheduled_task_store_unavailable');\n return options.store;\n}\n\nfunction scopedTaskResources(request: Record<string, unknown>): ScheduledTaskRpcGrantResources {\n return {\n conversationId: request.agentInstanceId as string,\n definitionId: request.agentDefinitionId as string,\n executionNodeId: request.executionNodeId as string,\n };\n}\n\nfunction assertScopedTaskRequest(value: Record<string, unknown>, field: string): void {\n assertOnlyKeys(value, [\n 'taskId',\n 'agentInstanceId',\n 'agentDefinitionId',\n 'executionNodeId',\n ], field);\n assertIdentifier(value.taskId, `${field}.taskId`);\n assertIdentifier(value.agentInstanceId, `${field}.agentInstanceId`);\n assertIdentifier(value.agentDefinitionId, `${field}.agentDefinitionId`);\n assertIdentifier(value.executionNodeId, `${field}.executionNodeId`);\n}\n\nfunction assertCreateInput(value: unknown, field: string): asserts value is ScheduledTaskRpcCreateInput {\n const input = asRecord(value, field);\n assertOnlyKeys(input, [\n 'agentInstanceId',\n 'agentDefinitionId',\n 'name',\n 'schedule',\n 'payload',\n 'activeHoursStart',\n 'activeHoursEnd',\n 'createdBy',\n 'enabled',\n 'executionNodeId',\n 'executionNodeLabel',\n ], field);\n assertIdentifier(input.agentInstanceId, `${field}.agentInstanceId`);\n assertIdentifier(input.agentDefinitionId, `${field}.agentDefinitionId`);\n assertBoundedString(input.name, `${field}.name`, SCHEDULED_TASK_RPC_LIMITS.nameCharacters);\n assertSchedule(input.schedule, `${field}.schedule`);\n optionalPayload(input.payload, `${field}.payload`, false);\n optionalActiveHour(input.activeHoursStart, `${field}.activeHoursStart`, false);\n optionalActiveHour(input.activeHoursEnd, `${field}.activeHoursEnd`, false);\n optionalBoundedString(\n input.createdBy,\n `${field}.createdBy`,\n SCHEDULED_TASK_RPC_LIMITS.creatorCharacters,\n );\n optionalBoolean(input.enabled, `${field}.enabled`);\n assertIdentifier(input.executionNodeId, `${field}.executionNodeId`);\n optionalBoundedString(\n input.executionNodeLabel,\n `${field}.executionNodeLabel`,\n SCHEDULED_TASK_RPC_LIMITS.labelCharacters,\n );\n}\n\nfunction assertUpdatePatch(value: unknown, field: string): asserts value is ScheduledTaskRpcUpdatePatch {\n const patch = asRecord(value, field);\n assertOnlyKeys(patch, [\n 'name',\n 'schedule',\n 'payload',\n 'activeHoursStart',\n 'activeHoursEnd',\n 'enabled',\n 'executionNodeId',\n 'executionNodeLabel',\n ], field);\n if (Object.keys(patch).length === 0) fail(field);\n optionalBoundedString(\n patch.name,\n `${field}.name`,\n SCHEDULED_TASK_RPC_LIMITS.nameCharacters,\n );\n if (patch.schedule !== undefined) assertSchedule(patch.schedule, `${field}.schedule`);\n optionalPayload(patch.payload, `${field}.payload`, true);\n optionalActiveHour(patch.activeHoursStart, `${field}.activeHoursStart`, true);\n optionalActiveHour(patch.activeHoursEnd, `${field}.activeHoursEnd`, true);\n optionalBoolean(patch.enabled, `${field}.enabled`);\n if (patch.executionNodeId !== undefined) {\n assertIdentifier(patch.executionNodeId, `${field}.executionNodeId`);\n }\n optionalNullableBoundedString(\n patch.executionNodeLabel,\n `${field}.executionNodeLabel`,\n SCHEDULED_TASK_RPC_LIMITS.labelCharacters,\n );\n}\n\nfunction assertScheduledTask(value: unknown, field: string): asserts value is ScheduledTask {\n const task = asRecord(value, field);\n assertOnlyKeys(task, [\n 'id',\n 'agentInstanceId',\n 'agentDefinitionId',\n 'name',\n 'schedule',\n 'payload',\n 'activeHoursStart',\n 'activeHoursEnd',\n 'enabled',\n 'createdBy',\n 'state',\n 'executionNodeId',\n 'executionNodeLabel',\n 'originNodeId',\n 'updatedAt',\n 'nextRunAt',\n 'lastRunAt',\n 'lastRunStatus',\n 'lastError',\n 'lastFailureAt',\n 'consecutiveFailures',\n 'nextRetryAt',\n 'runCount',\n 'maxRuns',\n 'deleteAfterRun',\n 'executionRevision',\n 'occurrenceId',\n 'occurrenceScheduledFor',\n 'occurrenceAttempt',\n ], field);\n assertIdentifier(task.id, `${field}.id`);\n assertIdentifier(task.agentInstanceId, `${field}.agentInstanceId`);\n assertIdentifier(task.agentDefinitionId, `${field}.agentDefinitionId`);\n assertBoundedString(task.name, `${field}.name`, SCHEDULED_TASK_RPC_LIMITS.nameCharacters);\n assertSchedule(task.schedule, `${field}.schedule`);\n optionalPayload(task.payload, `${field}.payload`, false, true);\n optionalActiveHour(task.activeHoursStart, `${field}.activeHoursStart`, false);\n optionalActiveHour(task.activeHoursEnd, `${field}.activeHoursEnd`, false);\n if (typeof task.enabled !== 'boolean') fail(`${field}.enabled`);\n optionalBoundedString(\n task.createdBy,\n `${field}.createdBy`,\n SCHEDULED_TASK_RPC_LIMITS.creatorCharacters,\n );\n assertState(task.state, `${field}.state`);\n assertIdentifier(task.executionNodeId, `${field}.executionNodeId`);\n optionalBoundedString(\n task.executionNodeLabel,\n `${field}.executionNodeLabel`,\n SCHEDULED_TASK_RPC_LIMITS.labelCharacters,\n );\n assertIdentifier(task.originNodeId, `${field}.originNodeId`);\n if (task.updatedAt !== undefined) assertCanonicalDate(task.updatedAt, `${field}.updatedAt`);\n if (task.nextRunAt !== undefined) assertCanonicalDate(task.nextRunAt, `${field}.nextRunAt`);\n if (task.lastRunAt !== undefined) assertCanonicalDate(task.lastRunAt, `${field}.lastRunAt`);\n if (task.lastFailureAt !== undefined) assertCanonicalDate(task.lastFailureAt, `${field}.lastFailureAt`);\n if (task.nextRetryAt !== undefined) assertCanonicalDate(task.nextRetryAt, `${field}.nextRetryAt`);\n if (\n task.lastRunStatus !== undefined &&\n task.lastRunStatus !== 'succeeded' &&\n task.lastRunStatus !== 'failed'\n ) fail(`${field}.lastRunStatus`);\n optionalBoundedString(task.lastError, `${field}.lastError`, 1_024);\n optionalInteger(task.consecutiveFailures, `${field}.consecutiveFailures`, 0, 1_000_000);\n optionalInteger(task.runCount, `${field}.runCount`, 0, Number.MAX_SAFE_INTEGER);\n optionalInteger(task.maxRuns, `${field}.maxRuns`, 1, Number.MAX_SAFE_INTEGER);\n optionalBoolean(task.deleteAfterRun, `${field}.deleteAfterRun`);\n optionalInteger(task.executionRevision, `${field}.executionRevision`, 0, Number.MAX_SAFE_INTEGER);\n optionalBoundedString(task.occurrenceId, `${field}.occurrenceId`, 128);\n if (task.occurrenceScheduledFor !== undefined) {\n assertCanonicalDate(task.occurrenceScheduledFor, `${field}.occurrenceScheduledFor`);\n }\n optionalInteger(task.occurrenceAttempt, `${field}.occurrenceAttempt`, 0, 1_000_000);\n}\n\nfunction assertSchedule(value: unknown, field: string): asserts value is ScheduledTaskRpcSchedule {\n const schedule = asRecord(value, field);\n if (schedule.kind === 'cron') {\n assertOnlyKeys(schedule, ['kind', 'expression', 'timezone'], field);\n assertBoundedString(\n schedule.expression,\n `${field}.expression`,\n SCHEDULED_TASK_RPC_LIMITS.cronExpressionCharacters,\n );\n optionalBoundedString(\n schedule.timezone,\n `${field}.timezone`,\n SCHEDULED_TASK_RPC_LIMITS.timezoneCharacters,\n );\n return;\n }\n if (schedule.kind === 'at') {\n assertOnlyKeys(schedule, ['kind', 'wakeAtISO'], field);\n assertCanonicalDate(schedule.wakeAtISO, `${field}.wakeAtISO`);\n return;\n }\n fail(`${field}.kind`);\n}\n\nfunction optionalPayload(\n value: unknown,\n field: string,\n nullable: boolean,\n optionalMessage = false,\n): void {\n if (value === undefined || nullable && value === null) return;\n const payload = asRecord(value, field);\n assertOnlyKeys(payload, ['message'], field);\n if (optionalMessage && payload.message === undefined) return;\n assertBoundedString(\n payload.message,\n `${field}.message`,\n SCHEDULED_TASK_RPC_LIMITS.messageCharacters,\n true,\n );\n}\n\nfunction optionalActiveHour(value: unknown, field: string, nullable: boolean): void {\n if (value === undefined || nullable && value === null) return;\n if (typeof value !== 'string' || !/^(?:[01]\\d|2[0-3]):[0-5]\\d$/u.test(value)) fail(field);\n}\n\nfunction optionalStateList(value: unknown, field: string): void {\n if (value === undefined) return;\n assertArray(value, field);\n if (value.length === 0 || value.length > 5) fail(field);\n const seen = new Set<string>();\n for (const item of value) {\n assertState(item, `${field}[]`);\n if (seen.has(item)) fail(field);\n seen.add(item);\n }\n}\n\nfunction assertState(value: unknown, field: string): asserts value is ScheduledTaskState {\n if (\n value !== 'active' &&\n value !== 'paused' &&\n value !== 'completed' &&\n value !== 'cancelled' &&\n value !== 'archived'\n ) fail(field);\n}\n\nfunction assertCanonicalDates(values: unknown[], field: string): void {\n let previous: string | undefined;\n for (const value of values) {\n assertCanonicalDate(value, `${field}[]`);\n if (previous !== undefined && previous >= value) fail(field);\n previous = value;\n }\n}\n\nfunction assertCanonicalDate(value: unknown, field: string): asserts value is string {\n if (typeof value !== 'string' || value.length > 64) fail(field);\n let canonical: string;\n try {\n canonical = new Date(value).toISOString();\n } catch {\n fail(field);\n }\n if (canonical !== value) fail(field);\n}\n\nfunction assertTaskMatchesScopedRequest(\n task: ScheduledTask,\n request: Record<string, unknown>,\n field: string,\n): void {\n if (\n task.id !== request.taskId ||\n task.agentInstanceId !== request.agentInstanceId ||\n task.agentDefinitionId !== request.agentDefinitionId ||\n task.executionNodeId !== request.executionNodeId\n ) fail(field);\n}\n\nfunction assertEditorInputIdentity(\n input: CreateScheduledTaskInput,\n options: { executionNodeId: string; originNodeId: string },\n): void {\n if (input.executionNodeId !== options.executionNodeId) {\n throw new ScheduledTaskRpcProtocolError('input.executionNodeId');\n }\n if (input.originNodeId !== options.originNodeId) {\n throw new ScheduledTaskRpcProtocolError('input.originNodeId');\n }\n if (input.scheduleKind !== input.schedule.kind) {\n throw new ScheduledTaskRpcProtocolError('input.scheduleKind');\n }\n}\n\nfunction assertEditorPatchIdentity(\n input: Partial<CreateScheduledTaskInput>,\n task: ScheduledTask,\n options: { executionNodeId: string; originNodeId: string },\n): void {\n if (input.agentInstanceId !== undefined && input.agentInstanceId !== task.agentInstanceId) {\n throw new ScheduledTaskRpcProtocolError('input.agentInstanceId');\n }\n if (input.agentDefinitionId !== undefined && input.agentDefinitionId !== task.agentDefinitionId) {\n throw new ScheduledTaskRpcProtocolError('input.agentDefinitionId');\n }\n if (input.executionNodeId !== undefined && input.executionNodeId !== options.executionNodeId) {\n throw new ScheduledTaskRpcProtocolError('input.executionNodeId');\n }\n if (input.originNodeId !== undefined && input.originNodeId !== options.originNodeId) {\n throw new ScheduledTaskRpcProtocolError('input.originNodeId');\n }\n if (\n input.scheduleKind !== undefined &&\n input.schedule !== undefined &&\n input.scheduleKind !== input.schedule.kind\n ) {\n throw new ScheduledTaskRpcProtocolError('input.scheduleKind');\n }\n}\n\nfunction createInputFromEditor(input: CreateScheduledTaskInput): ScheduledTaskRpcCreateInput {\n return {\n agentInstanceId: input.agentInstanceId,\n agentDefinitionId: input.agentDefinitionId,\n name: input.name,\n schedule: input.schedule,\n payload: input.payload,\n activeHoursStart: input.activeHoursStart,\n activeHoursEnd: input.activeHoursEnd,\n createdBy: input.createdBy,\n enabled: input.enabled,\n executionNodeId: input.executionNodeId,\n executionNodeLabel: input.executionNodeLabel,\n };\n}\n\nfunction updatePatchFromEditor(\n input: Partial<CreateScheduledTaskInput>,\n): ScheduledTaskRpcUpdatePatch {\n const patch: ScheduledTaskRpcUpdatePatch = {};\n if (hasOwn(input, 'name')) patch.name = input.name;\n if (hasOwn(input, 'schedule')) patch.schedule = input.schedule;\n if (hasOwn(input, 'payload')) patch.payload = input.payload ?? null;\n if (hasOwn(input, 'activeHoursStart')) {\n patch.activeHoursStart = input.activeHoursStart ?? null;\n }\n if (hasOwn(input, 'activeHoursEnd')) patch.activeHoursEnd = input.activeHoursEnd ?? null;\n if (hasOwn(input, 'enabled')) patch.enabled = input.enabled;\n if (hasOwn(input, 'executionNodeId')) patch.executionNodeId = input.executionNodeId;\n if (hasOwn(input, 'executionNodeLabel')) {\n patch.executionNodeLabel = input.executionNodeLabel ?? null;\n }\n assertUpdatePatch(patch, 'request.patch');\n return patch;\n}\n\nfunction requireKnownTask(tasks: Map<string, ScheduledTask>, taskId: string): ScheduledTask {\n assertIdentifier(taskId, 'taskId');\n const task = tasks.get(taskId);\n if (!task) throw new Error('scheduled_task_scope_unavailable');\n return task;\n}\n\nfunction hasOwn(value: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(value, key);\n}\n\nfunction asRecord(value: unknown, field: string): Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) fail(field);\n return value as Record<string, unknown>;\n}\n\nfunction assertOnlyKeys(\n value: Record<string, unknown>,\n allowed: readonly string[],\n field: string,\n): void {\n const allowedSet = new Set(allowed);\n if (Object.keys(value).some(key => !allowedSet.has(key))) fail(field);\n}\n\nfunction assertArray(value: unknown, field: string): asserts value is unknown[] {\n if (!Array.isArray(value)) fail(field);\n}\n\nfunction assertIdentifier(value: unknown, field: string): asserts value is string {\n assertBoundedString(\n value,\n field,\n SCHEDULED_TASK_RPC_LIMITS.identifierCharacters,\n );\n}\n\nfunction assertBoundedString(\n value: unknown,\n field: string,\n maximum: number,\n allowEmpty = false,\n): asserts value is string {\n if (\n typeof value !== 'string' ||\n (!allowEmpty && value.length === 0) ||\n value.length > maximum ||\n value.includes('\\0')\n ) fail(field);\n}\n\nfunction optionalBoundedString(\n value: unknown,\n field: string,\n maximum: number,\n): void {\n if (value !== undefined) assertBoundedString(value, field, maximum);\n}\n\nfunction optionalNullableBoundedString(\n value: unknown,\n field: string,\n maximum: number,\n): void {\n if (value !== undefined && value !== null) assertBoundedString(value, field, maximum);\n}\n\nfunction optionalBoolean(value: unknown, field: string): void {\n if (value !== undefined && typeof value !== 'boolean') fail(field);\n}\n\nfunction optionalInteger(\n value: unknown,\n field: string,\n minimum: number,\n maximum: number,\n): void {\n if (\n value !== undefined &&\n (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum || value > maximum)\n ) fail(field);\n}\n\nfunction fail(field: string): never {\n throw new ScheduledTaskRpcProtocolError(field);\n}\n","import type { AgentDefinition } from '../agent/types.js';\nimport {\n assertCanonicalChatMessageProjection,\n conversationEventToMessage,\n type ConversationMessageEvent,\n type ConversationTombstoneEvent,\n isConversationEvent,\n MAX_CONVERSATION_EVENT_BYTES,\n} from '../conversation/events.js';\nimport type { AttachmentReference, ChatMessage } from '../conversation/types.js';\nimport { canonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type { PendingLocalChatMessage } from '../loopAPI/types.js';\nimport { normalizeAgentRunError } from '../runState.js';\nimport type { MemeLoopRunState, MemeLoopRunStatus } from '../runtime.js';\nimport {\n assertConversationMessageProjection,\n assertConversationTimelineCompactionEntry,\n assertConversationTimelinePage,\n assertConversationTimelinePageEnvelope,\n MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n MAX_CONVERSATION_MESSAGE_WINDOW_SIZE,\n MAX_CONVERSATION_TIMELINE_PAGE_BYTES,\n MAX_CONVERSATION_TIMELINE_PAGE_SIZE,\n MAX_MESSAGE_PAGE_SIZE,\n} from '../storage/conversationPaging.js';\nimport type {\n ConversationMessageWindowFocus,\n ConversationMessageWindowResolvedFocus,\n ConversationQueryMode,\n ConversationTimelineEntry,\n ConversationTimelinePage,\n ConversationTimelineParticipantPreview,\n} from '../storage/ports.js';\nimport type { ConversationMeta } from '../sync/protocol.js';\nimport { AGENT_USER_MESSAGE_LIMITS, assertAgentUserMessageWithinLimits } from '../userMessageAdmission.js';\nimport {\n assertAttachmentUploadRpcRequest,\n assertAttachmentUploadRpcResponseCorrelation,\n ATTACHMENT_UPLOAD_LIMITS,\n ATTACHMENT_UPLOAD_RPC_METHODS,\n ATTACHMENT_UPLOAD_SHA256_PATTERN,\n type AttachmentUploadRpcMethod,\n type AttachmentUploadRpcRequest,\n type AttachmentUploadRpcResponse,\n type BeginAttachmentUploadRequest,\n type BeginAttachmentUploadResponse,\n type CommitAttachmentUploadRequest,\n type CommitAttachmentUploadResponse,\n parseAttachmentUploadRpcResponse,\n type UploadAttachmentChunkRequest,\n type UploadAttachmentChunkResponse,\n} from './attachmentUpload.js';\nimport {\n assertScheduledTaskRpcRequest,\n assertScheduledTaskRpcResponseCorrelation,\n isScheduledTaskRpcMethod,\n parseScheduledTaskRpcGrantResources,\n parseScheduledTaskRpcResponse,\n SCHEDULED_TASK_RPC_METHODS,\n type ScheduledTaskRpcContract,\n type ScheduledTaskRpcMethod,\n type ScheduledTaskRpcRequest,\n type ScheduledTaskRpcResponse,\n} from './scheduledTaskRpc.js';\n\nexport * from './attachmentUpload.js';\nexport * from './scheduledTaskRpc.js';\n\n/** Portable limits shared by RPC handlers and every browser/mobile client. */\nexport const AGENT_DEVICE_RPC_LIMITS = Object.freeze(\n {\n conversationListPage: 100,\n conversationListBytes: 1024 * 1024,\n turnListPage: MAX_CONVERSATION_MESSAGE_WINDOW_SIZE,\n turnDetailPage: 50,\n turnDetailDefaultBytes: 256 * 1024,\n projectionPageDefaultBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n projectionPageMaxBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n projectionPageMinBytes: 64 * 1024,\n turnProjectionBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n turnRenderLines: 20_000,\n definitions: 256,\n definitionsBytes: 2 * 1024 * 1024,\n messagePage: MAX_MESSAGE_PAGE_SIZE,\n timelinePage: MAX_CONVERSATION_TIMELINE_PAGE_SIZE,\n /** Timeline has a storage-aligned budget independent of chat detail pages. */\n timelinePageDefaultBytes: MAX_CONVERSATION_TIMELINE_PAGE_BYTES,\n timelinePageMaxBytes: MAX_CONVERSATION_TIMELINE_PAGE_BYTES,\n timelinePreviewCharacters: 240,\n loadAroundMessages: MAX_CONVERSATION_MESSAGE_WINDOW_SIZE,\n loadAroundDefaultBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n loadAroundMaxBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n messageProjectionBytes: 128 * 1024,\n messagePageBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n detailChunkBytes: 3 * 1024 * 1024,\n messageDetailBytes: 64 * 1024 * 1024,\n attachmentChunkBytes: 3 * 1024 * 1024,\n runLogPage: 50,\n runLogContentCharacters: 32 * 1024,\n runLogPageBytes: 256 * 1024,\n identifierCharacters: 512,\n cursorCharacters: 2_048,\n userMessageAttachments: 32,\n userMessageBytes: AGENT_USER_MESSAGE_LIMITS.canonicalMessageBytes,\n } as const,\n);\n\nexport const AGENT_DEVICE_RPC_METHODS = Object.freeze(\n {\n getDefinitions: 'memeloop.agent.getDefinitions',\n create: 'memeloop.agent.create',\n send: 'memeloop.agent.send',\n runTurn: 'memeloop.agent.runTurn',\n getRunStatus: 'memeloop.agent.getRunStatus',\n cancel: 'memeloop.agent.cancel',\n deleteTurn: 'memeloop.chat.deleteTurn',\n retryTurn: 'memeloop.chat.retryTurn',\n listConversations: 'memeloop.chat.listConversations',\n getConversationMeta: 'memeloop.chat.getConversationMeta',\n listTurns: 'memeloop.chat.listTurns',\n getTurnDetail: 'memeloop.chat.getTurnDetail',\n getMessagePage: 'memeloop.chat.getMessagePage',\n getConversationTimelinePage: 'memeloop.chat.getConversationTimelinePage',\n loadAround: 'memeloop.chat.loadAround',\n getMessageDetail: 'memeloop.chat.getMessageDetail',\n getAttachmentChunk: 'memeloop.chat.getAttachmentChunk',\n beginAttachmentUpload: ATTACHMENT_UPLOAD_RPC_METHODS.begin,\n uploadAttachmentChunk: ATTACHMENT_UPLOAD_RPC_METHODS.chunk,\n commitAttachmentUpload: ATTACHMENT_UPLOAD_RPC_METHODS.commit,\n pullAgentRunLog: 'memeloop.chat.pullAgentRunLog',\n scheduleList: SCHEDULED_TASK_RPC_METHODS.list,\n scheduleGet: SCHEDULED_TASK_RPC_METHODS.get,\n scheduleCreate: SCHEDULED_TASK_RPC_METHODS.create,\n scheduleUpdate: SCHEDULED_TASK_RPC_METHODS.update,\n scheduleDelete: SCHEDULED_TASK_RPC_METHODS.delete,\n scheduleCronPreview: SCHEDULED_TASK_RPC_METHODS.cronPreview,\n } as const,\n);\n\nexport type AgentDeviceRpcMethod = typeof AGENT_DEVICE_RPC_METHODS[keyof typeof AGENT_DEVICE_RPC_METHODS];\n\nconst AGENT_DEVICE_RPC_METHOD_SET = new Set<string>(Object.values(AGENT_DEVICE_RPC_METHODS));\n\nexport function isAgentDeviceRpcMethod(value: unknown): value is AgentDeviceRpcMethod {\n return typeof value === 'string' && AGENT_DEVICE_RPC_METHOD_SET.has(value);\n}\n\nexport interface AgentDeviceRpcGrantResources {\n conversationId?: string;\n definitionId?: string;\n /** Resolve this durable run before authorizing; parameters alone are insufficient. */\n runId?: string;\n}\n\n/**\n * Validate parameters and extract only caller-asserted scope hints. `runId`\n * methods must still replace these hints with the durable run record before\n * calling the shared grant authorizer.\n */\nexport function parseAgentDeviceRpcGrantResources(\n method: string,\n parameters: unknown,\n): AgentDeviceRpcGrantResources {\n if (!isAgentDeviceRpcMethod(method)) throw new AgentDeviceRpcProtocolError('method');\n assertAgentDeviceRpcRequest(method, parameters);\n const record = parameters as Record<string, unknown>;\n switch (method) {\n case AGENT_DEVICE_RPC_METHODS.getDefinitions:\n case AGENT_DEVICE_RPC_METHODS.listConversations:\n return {};\n case AGENT_DEVICE_RPC_METHODS.create:\n return {\n definitionId: record.definitionId as string,\n ...(record.conversationId === undefined ? {} : { conversationId: record.conversationId as string }),\n };\n case AGENT_DEVICE_RPC_METHODS.send:\n return {\n conversationId: record.conversationId as string,\n ...(record.definitionId === undefined ? {} : { definitionId: record.definitionId as string }),\n };\n case AGENT_DEVICE_RPC_METHODS.runTurn:\n return {\n conversationId: record.conversationId as string,\n definitionId: record.definitionId as string,\n };\n case AGENT_DEVICE_RPC_METHODS.getRunStatus:\n case AGENT_DEVICE_RPC_METHODS.cancel:\n return { runId: record.runId as string };\n case AGENT_DEVICE_RPC_METHODS.pullAgentRunLog:\n return {\n conversationId: record.conversationId as string,\n runId: record.runId as string,\n };\n case AGENT_DEVICE_RPC_METHODS.retryTurn:\n return {\n conversationId: record.conversationId as string,\n ...(record.definitionId === undefined ? {} : { definitionId: record.definitionId as string }),\n };\n case AGENT_DEVICE_RPC_METHODS.beginAttachmentUpload:\n case AGENT_DEVICE_RPC_METHODS.uploadAttachmentChunk:\n case AGENT_DEVICE_RPC_METHODS.commitAttachmentUpload:\n return { conversationId: record.conversationId as string };\n case AGENT_DEVICE_RPC_METHODS.deleteTurn:\n case AGENT_DEVICE_RPC_METHODS.getConversationMeta:\n case AGENT_DEVICE_RPC_METHODS.listTurns:\n case AGENT_DEVICE_RPC_METHODS.getTurnDetail:\n case AGENT_DEVICE_RPC_METHODS.getMessagePage:\n case AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage:\n case AGENT_DEVICE_RPC_METHODS.loadAround:\n case AGENT_DEVICE_RPC_METHODS.getMessageDetail:\n case AGENT_DEVICE_RPC_METHODS.getAttachmentChunk:\n return { conversationId: record.conversationId as string };\n case AGENT_DEVICE_RPC_METHODS.scheduleList:\n case AGENT_DEVICE_RPC_METHODS.scheduleGet:\n case AGENT_DEVICE_RPC_METHODS.scheduleCreate:\n case AGENT_DEVICE_RPC_METHODS.scheduleUpdate:\n case AGENT_DEVICE_RPC_METHODS.scheduleDelete:\n case AGENT_DEVICE_RPC_METHODS.scheduleCronPreview: {\n const resources = parseScheduledTaskRpcGrantResources(method, parameters);\n return {\n ...(resources.conversationId === undefined ? {} : { conversationId: resources.conversationId }),\n ...(resources.definitionId === undefined ? {} : { definitionId: resources.definitionId }),\n };\n }\n }\n}\n\nexport type AgentDeviceRpcGetDefinitionsRequest = Record<string, never>;\n\nexport interface AgentDeviceRpcGetDefinitionsResponse {\n definitions: AgentDefinition[];\n}\n\nexport interface AgentDeviceRpcCreateRequest {\n definitionId: string;\n initialMessage?: string;\n conversationId?: string;\n}\n\nexport interface AgentDeviceRpcCreateResponse {\n conversationId: string;\n}\n\nexport interface AgentDeviceRpcSendRequest {\n /** Caller-generated durable idempotency key. Reuse it for transport retries. */\n requestId: string;\n /** Stable logical turn identity, independent of its individual messages. */\n turnId: string;\n conversationId: string;\n message: string;\n definitionId?: string;\n /** Local-event payload only; the server allocates origin sequence and Lamport identity. */\n userMessage?: AgentDeviceRpcPendingUserMessage;\n}\n\nexport type AgentDeviceRpcPendingUserMessage = Omit<\n PendingLocalChatMessage,\n 'messageId' | 'turnId' | 'originNodeId' | 'timestamp'\n>;\n\nexport interface AgentDeviceRpcRunTurnRequest extends AgentDeviceRpcSendRequest {\n definitionId: string;\n conversation?: ConversationMeta;\n}\n\nexport interface AgentDeviceRpcTurnAcceptedResponse {\n ok: true;\n runId: string;\n requestId: string;\n turnId: string;\n conversationId: string;\n state: 'accepted';\n}\n\nexport interface AgentDeviceRpcGetRunStatusRequest {\n runId: string;\n}\n\nexport interface AgentDeviceRpcGetRunStatusResponse {\n status: AgentDeviceRpcRunStatus | null;\n}\n\nexport interface AgentDeviceRpcCancelRequest {\n runId: string;\n}\n\nexport interface AgentDeviceRpcCancelResponse {\n ok: boolean;\n status: AgentDeviceRpcRunStatus | null;\n}\n\nexport interface AgentDeviceRpcRunStatus extends MemeLoopRunStatus {\n requestId: string;\n turnId: string;\n}\n\nexport interface AgentDeviceRpcDeleteTurnRequest {\n conversationId: string;\n turnId: string;\n requestId: string;\n reason?: ConversationTombstoneEvent['reason'];\n}\n\n/** Deletion is an auditable append; implementations must never remove rows. */\nexport interface AgentDeviceRpcDeleteTurnResponse {\n ok: true;\n conversationId: string;\n turnId: string;\n requestId: string;\n tombstone: ConversationTombstoneEvent;\n}\n\nexport interface AgentDeviceRpcRetryTurnRequest {\n conversationId: string;\n /** Existing turn hidden by the atomically appended tombstone. */\n turnId: string;\n requestId: string;\n /** New stable turn identity; must differ from turnId. */\n newTurnId: string;\n definitionId?: string;\n}\n\n/** Atomic retry result: tombstone(old), user event(new), then one durable run. */\nexport interface AgentDeviceRpcRetryTurnResponse extends AgentDeviceRpcTurnAcceptedResponse {\n tombstone: ConversationTombstoneEvent;\n userEvent: ConversationMessageEvent;\n}\n\nexport interface AgentDeviceRpcListConversationsRequest {\n limit?: number;\n /** Opaque stable keyset cursor. Callers must never parse or synthesize it. */\n cursor?: string;\n /** Ask the server whether a previously rendered cursor is still retained. */\n seenCursor?: string;\n direction?: 'backward' | 'forward';\n}\n\nexport interface AgentDeviceRpcListConversationsResponse {\n items: ConversationMeta[];\n nextCursor?: string;\n previousCursor?: string;\n hasMoreBefore: boolean;\n hasMoreAfter: boolean;\n seenCursorFound?: boolean;\n}\n\nexport interface AgentDeviceRpcGetConversationMetaRequest {\n conversationId: string;\n}\n\nexport interface AgentDeviceRpcGetConversationMetaResponse {\n meta: ConversationMeta | null;\n}\n\nexport type AgentDeviceRpcTurnDetailState = 'summary' | 'full' | 'notLoaded';\n\nexport interface AgentDeviceRpcTurnSummary {\n turnId: string;\n conversationId: string;\n /** Opaque navigation cursor supplied back to list/load APIs unchanged. */\n cursor: string;\n startedAt: number;\n updatedAt: number;\n userPreview: string;\n participantPreviews: ConversationTimelineParticipantPreview[];\n responseCount: number;\n runState?: MemeLoopRunState;\n isCompaction: boolean;\n compactedMessageCount?: number;\n isTombstone: boolean;\n detailState: AgentDeviceRpcTurnDetailState;\n /** Present only when the bounded list projection could include the whole turn. */\n messages?: ChatMessage[];\n}\n\nexport interface AgentDeviceRpcListTurnsRequest {\n conversationId: string;\n cursor?: string;\n seenCursor?: string;\n direction?: 'backward' | 'forward';\n limit?: number;\n byteBudget?: number;\n renderLineBudget?: number;\n}\n\nexport interface AgentDeviceRpcListTurnsResponse {\n items: AgentDeviceRpcTurnSummary[];\n nextCursor?: string;\n previousCursor?: string;\n hasMoreBefore: boolean;\n hasMoreAfter: boolean;\n seenCursorFound?: boolean;\n budget: {\n bytes: number;\n renderLines: number;\n truncated: boolean;\n };\n}\n\nexport interface AgentDeviceRpcGetTurnDetailRequest {\n conversationId: string;\n turnId: string;\n cursor?: string;\n seenCursor?: string;\n direction?: 'backward' | 'forward';\n limit?: number;\n maxBytes?: number;\n}\n\nexport interface AgentDeviceRpcGetTurnDetailResponse {\n turnId: string;\n items: ChatMessage[];\n nextCursor?: string;\n previousCursor?: string;\n hasMoreBefore: boolean;\n hasMoreAfter: boolean;\n seenCursorFound?: boolean;\n}\n\nexport interface AgentDeviceRpcGetMessagePageRequest {\n conversationId: string;\n limit?: number;\n /** Opaque item cursor; the server owns its storage/keyset encoding. */\n cursor?: string;\n /** Required when replaying a revision-scoped cursor returned by loadAround. */\n expectedRevision?: string;\n seenCursor?: string;\n direction?: 'backward' | 'forward';\n mode?: ConversationQueryMode;\n /** UTF-8 JSON response budget. Defaults to and cannot exceed 256 KiB. */\n maxBytes?: number;\n}\n\nexport type AgentDeviceRpcGetMessagePageResponse =\n | { reset: true; conversationId: string; revision: string }\n | {\n reset: false;\n conversationId: string;\n revision: string;\n items: ChatMessage[];\n hasMoreBefore: boolean;\n hasMoreAfter: boolean;\n nextCursor?: string;\n previousCursor?: string;\n seenCursorFound?: boolean;\n };\n\nexport interface AgentDeviceRpcGetConversationTimelinePageRequest {\n conversationId: string;\n limit?: number;\n maxBytes?: number;\n expectedRevision?: string;\n /** At most one navigation selector; none reads the latest page. */\n beforeCursor?: string;\n afterCursor?: string;\n aroundEntryIndex?: number;\n}\n\nexport type AgentDeviceRpcTimelineEntry = ConversationTimelineEntry;\nexport type AgentDeviceRpcGetConversationTimelinePageResponse = ConversationTimelinePage;\n\nexport interface AgentDeviceRpcLoadAroundRequest {\n conversationId: string;\n focus: ConversationMessageWindowFocus;\n expectedRevision: string;\n maxMessages?: number;\n maxBytes?: number;\n}\n\nexport type AgentDeviceRpcLoadAroundResponse =\n | {\n reset: true;\n conversationId: string;\n revision: string;\n }\n | {\n reset: false;\n conversationId: string;\n revision: string;\n focus: ConversationMessageWindowResolvedFocus;\n items: ChatMessage[];\n hasMoreBefore: boolean;\n hasMoreAfter: boolean;\n /** Opaque cursor for a backward getMessagePage read. */\n previousCursor?: string;\n /** Opaque cursor for a forward getMessagePage read. */\n nextCursor?: string;\n };\n\nexport interface AgentDeviceRpcGetMessageDetailRequest {\n conversationId: string;\n messageId: string;\n offset?: number;\n}\n\nexport type AgentDeviceRpcGetMessageDetailResponse =\n | { found: false }\n | AgentDeviceRpcJsonChunk;\n\nexport interface AgentDeviceRpcJsonChunk {\n found: true;\n encoding: 'base64-json';\n data: string;\n offset: number;\n totalBytes: number;\n nextOffset?: number;\n}\n\nexport interface AgentDeviceRpcGetAttachmentChunkRequest {\n /** Required for resource-scope authorization; a hash alone is enumerable. */\n conversationId: string;\n contentHash: string;\n offset?: number;\n}\n\nexport type AgentDeviceRpcGetAttachmentChunkResponse =\n | { found: false }\n | AgentDeviceRpcAttachmentChunk;\n\nexport interface AgentDeviceRpcAttachmentChunk {\n found: true;\n reference: AttachmentReference;\n encoding: 'base64';\n data: string;\n offset: number;\n totalBytes: number;\n nextOffset?: number;\n}\n\nexport interface AgentDeviceRpcPullAgentRunLogRequest {\n conversationId: string;\n runId: string;\n cursor?: string;\n limit?: number;\n maxBytes?: number;\n}\n\nexport interface AgentDeviceRpcRunLogMessage {\n messageId: string;\n role: ChatMessage['role'];\n content: string;\n}\n\nexport interface AgentDeviceRpcPullAgentRunLogResponse {\n messages: AgentDeviceRpcRunLogMessage[];\n nextCursor?: string;\n hasMoreAfter: boolean;\n runStatus: AgentDeviceRpcRunStatus | null;\n}\n\nexport interface AgentDeviceRpcContract {\n [AGENT_DEVICE_RPC_METHODS.getDefinitions]: {\n request: AgentDeviceRpcGetDefinitionsRequest;\n response: AgentDeviceRpcGetDefinitionsResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.create]: {\n request: AgentDeviceRpcCreateRequest;\n response: AgentDeviceRpcCreateResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.send]: {\n request: AgentDeviceRpcSendRequest;\n response: AgentDeviceRpcTurnAcceptedResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.runTurn]: {\n request: AgentDeviceRpcRunTurnRequest;\n response: AgentDeviceRpcTurnAcceptedResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getRunStatus]: {\n request: AgentDeviceRpcGetRunStatusRequest;\n response: AgentDeviceRpcGetRunStatusResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.cancel]: {\n request: AgentDeviceRpcCancelRequest;\n response: AgentDeviceRpcCancelResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.deleteTurn]: {\n request: AgentDeviceRpcDeleteTurnRequest;\n response: AgentDeviceRpcDeleteTurnResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.retryTurn]: {\n request: AgentDeviceRpcRetryTurnRequest;\n response: AgentDeviceRpcRetryTurnResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.listConversations]: {\n request: AgentDeviceRpcListConversationsRequest;\n response: AgentDeviceRpcListConversationsResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getConversationMeta]: {\n request: AgentDeviceRpcGetConversationMetaRequest;\n response: AgentDeviceRpcGetConversationMetaResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.listTurns]: {\n request: AgentDeviceRpcListTurnsRequest;\n response: AgentDeviceRpcListTurnsResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getTurnDetail]: {\n request: AgentDeviceRpcGetTurnDetailRequest;\n response: AgentDeviceRpcGetTurnDetailResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getMessagePage]: {\n request: AgentDeviceRpcGetMessagePageRequest;\n response: AgentDeviceRpcGetMessagePageResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage]: {\n request: AgentDeviceRpcGetConversationTimelinePageRequest;\n response: AgentDeviceRpcGetConversationTimelinePageResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.loadAround]: {\n request: AgentDeviceRpcLoadAroundRequest;\n response: AgentDeviceRpcLoadAroundResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getMessageDetail]: {\n request: AgentDeviceRpcGetMessageDetailRequest;\n response: AgentDeviceRpcGetMessageDetailResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getAttachmentChunk]: {\n request: AgentDeviceRpcGetAttachmentChunkRequest;\n response: AgentDeviceRpcGetAttachmentChunkResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.pullAgentRunLog]: {\n request: AgentDeviceRpcPullAgentRunLogRequest;\n response: AgentDeviceRpcPullAgentRunLogResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.beginAttachmentUpload]: {\n request: BeginAttachmentUploadRequest;\n response: BeginAttachmentUploadResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.uploadAttachmentChunk]: {\n request: UploadAttachmentChunkRequest;\n response: UploadAttachmentChunkResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.commitAttachmentUpload]: {\n request: CommitAttachmentUploadRequest;\n response: CommitAttachmentUploadResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.scheduleList]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.list];\n [AGENT_DEVICE_RPC_METHODS.scheduleGet]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.get];\n [AGENT_DEVICE_RPC_METHODS.scheduleCreate]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.create];\n [AGENT_DEVICE_RPC_METHODS.scheduleUpdate]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.update];\n [AGENT_DEVICE_RPC_METHODS.scheduleDelete]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.delete];\n [AGENT_DEVICE_RPC_METHODS.scheduleCronPreview]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.cronPreview];\n}\n\nexport type AgentDeviceRpcRequest<M extends AgentDeviceRpcMethod> = AgentDeviceRpcContract[M]['request'];\nexport type AgentDeviceRpcResponse<M extends AgentDeviceRpcMethod> = AgentDeviceRpcContract[M]['response'];\n\nexport class AgentDeviceRpcProtocolError extends Error {\n readonly code = 'invalid_agent_device_rpc' as const;\n\n constructor(readonly field: string) {\n super(`Invalid Agent device RPC ${field}`);\n this.name = 'AgentDeviceRpcProtocolError';\n }\n}\n\n/** Validate untrusted inbound parameters before dispatching to the local runtime. */\nexport function assertAgentDeviceRpcRequest<M extends AgentDeviceRpcMethod>(\n method: M,\n value: unknown,\n): asserts value is AgentDeviceRpcRequest<M> {\n assertJsonBytes(value, 8 * 1024 * 1024, 'request');\n const record = asRecord(value, 'request');\n switch (method) {\n case AGENT_DEVICE_RPC_METHODS.getDefinitions:\n assertOnlyKeys(record, [], 'request');\n return;\n case AGENT_DEVICE_RPC_METHODS.create:\n assertOnlyKeys(record, ['definitionId', 'initialMessage', 'conversationId'], 'request');\n assertIdentifier(record.definitionId, 'request.definitionId');\n optionalString(record.initialMessage, 'request.initialMessage');\n optionalIdentifier(record.conversationId, 'request.conversationId');\n return;\n case AGENT_DEVICE_RPC_METHODS.send:\n assertOnlyKeys(record, ['requestId', 'turnId', 'conversationId', 'message', 'definitionId', 'userMessage'], 'request');\n assertSendRequest(record, false);\n return;\n case AGENT_DEVICE_RPC_METHODS.runTurn:\n assertOnlyKeys(record, [\n 'requestId',\n 'turnId',\n 'conversationId',\n 'message',\n 'definitionId',\n 'userMessage',\n 'conversation',\n ], 'request');\n assertSendRequest(record, true);\n optionalConversationMeta(record.conversation, 'request.conversation');\n return;\n case AGENT_DEVICE_RPC_METHODS.getRunStatus:\n case AGENT_DEVICE_RPC_METHODS.cancel:\n assertOnlyKeys(record, ['runId'], 'request');\n assertIdentifier(record.runId, 'request.runId');\n return;\n case AGENT_DEVICE_RPC_METHODS.deleteTurn:\n assertOnlyKeys(record, ['conversationId', 'turnId', 'requestId', 'reason'], 'request');\n assertTurnControlIdentity(record);\n if (\n record.reason !== undefined &&\n record.reason !== 'user-delete' &&\n record.reason !== 'retention' &&\n record.reason !== 'redaction'\n ) fail('request.reason');\n return;\n case AGENT_DEVICE_RPC_METHODS.retryTurn:\n assertOnlyKeys(record, [\n 'conversationId',\n 'turnId',\n 'requestId',\n 'newTurnId',\n 'definitionId',\n ], 'request');\n assertTurnControlIdentity(record);\n assertIdentifier(record.newTurnId, 'request.newTurnId');\n if (record.newTurnId === record.turnId) fail('request.newTurnId');\n optionalIdentifier(record.definitionId, 'request.definitionId');\n return;\n case AGENT_DEVICE_RPC_METHODS.listConversations:\n assertOnlyKeys(record, ['limit', 'cursor', 'seenCursor', 'direction'], 'request');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.conversationListPage);\n optionalCursorString(record.cursor, 'request.cursor');\n optionalCursorString(record.seenCursor, 'request.seenCursor');\n optionalDirection(record.direction, 'request.direction');\n return;\n case AGENT_DEVICE_RPC_METHODS.getConversationMeta:\n assertOnlyKeys(record, ['conversationId'], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n return;\n case AGENT_DEVICE_RPC_METHODS.listTurns:\n assertOnlyKeys(record, [\n 'conversationId',\n 'cursor',\n 'seenCursor',\n 'direction',\n 'limit',\n 'byteBudget',\n 'renderLineBudget',\n ], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n optionalCursorString(record.cursor, 'request.cursor');\n optionalCursorString(record.seenCursor, 'request.seenCursor');\n optionalDirection(record.direction, 'request.direction');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.turnListPage);\n optionalBoundedInteger(record.byteBudget, 'request.byteBudget', 1, AGENT_DEVICE_RPC_LIMITS.turnProjectionBytes);\n optionalBoundedInteger(record.renderLineBudget, 'request.renderLineBudget', 1, AGENT_DEVICE_RPC_LIMITS.turnRenderLines);\n return;\n case AGENT_DEVICE_RPC_METHODS.getTurnDetail:\n assertOnlyKeys(record, [\n 'conversationId',\n 'turnId',\n 'cursor',\n 'seenCursor',\n 'direction',\n 'limit',\n 'maxBytes',\n ], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertIdentifier(record.turnId, 'request.turnId');\n optionalCursorString(record.cursor, 'request.cursor');\n optionalCursorString(record.seenCursor, 'request.seenCursor');\n optionalDirection(record.direction, 'request.direction');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.turnDetailPage);\n optionalBoundedInteger(\n record.maxBytes,\n 'request.maxBytes',\n AGENT_DEVICE_RPC_LIMITS.projectionPageMinBytes,\n AGENT_DEVICE_RPC_LIMITS.runLogPageBytes,\n );\n return;\n case AGENT_DEVICE_RPC_METHODS.getMessagePage:\n assertOnlyKeys(record, [\n 'conversationId',\n 'limit',\n 'cursor',\n 'expectedRevision',\n 'seenCursor',\n 'direction',\n 'mode',\n 'maxBytes',\n ], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.messagePage);\n optionalCursorString(record.cursor, 'request.cursor');\n optionalCursorString(record.expectedRevision, 'request.expectedRevision');\n optionalCursorString(record.seenCursor, 'request.seenCursor');\n optionalDirection(record.direction, 'request.direction');\n optionalQueryMode(record.mode, 'request.mode');\n optionalProjectionPageBytes(record.maxBytes, 'request.maxBytes');\n if (record.cursor !== undefined && record.expectedRevision === undefined) {\n fail('request.expectedRevision');\n }\n return;\n case AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage: {\n assertOnlyKeys(record, [\n 'conversationId',\n 'limit',\n 'maxBytes',\n 'expectedRevision',\n 'beforeCursor',\n 'afterCursor',\n 'aroundEntryIndex',\n ], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.timelinePage);\n optionalTimelinePageBytes(record.maxBytes, 'request.maxBytes');\n optionalCursorString(record.expectedRevision, 'request.expectedRevision');\n optionalCursorString(record.beforeCursor, 'request.beforeCursor');\n optionalCursorString(record.afterCursor, 'request.afterCursor');\n optionalBoundedInteger(record.aroundEntryIndex, 'request.aroundEntryIndex', 0, Number.MAX_SAFE_INTEGER);\n if (\n [record.beforeCursor, record.afterCursor, record.aroundEntryIndex]\n .filter(value => value !== undefined).length > 1\n ) fail('request.navigation');\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.loadAround:\n assertOnlyKeys(record, ['conversationId', 'focus', 'expectedRevision', 'maxMessages', 'maxBytes'], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertMessageWindowFocus(record.focus, 'request.focus');\n optionalCursorString(record.expectedRevision, 'request.expectedRevision');\n if (record.expectedRevision === undefined) fail('request.expectedRevision');\n optionalBoundedInteger(record.maxMessages, 'request.maxMessages', 1, AGENT_DEVICE_RPC_LIMITS.loadAroundMessages);\n optionalLoadAroundBytes(record.maxBytes, 'request.maxBytes');\n return;\n case AGENT_DEVICE_RPC_METHODS.getMessageDetail:\n assertOnlyKeys(record, ['conversationId', 'messageId', 'offset'], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertIdentifier(record.messageId, 'request.messageId');\n optionalBoundedInteger(record.offset, 'request.offset', 0, Number.MAX_SAFE_INTEGER);\n return;\n case AGENT_DEVICE_RPC_METHODS.getAttachmentChunk:\n assertOnlyKeys(record, ['conversationId', 'contentHash', 'offset'], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertIdentifier(record.contentHash, 'request.contentHash');\n optionalBoundedInteger(record.offset, 'request.offset', 0, Number.MAX_SAFE_INTEGER);\n return;\n case AGENT_DEVICE_RPC_METHODS.pullAgentRunLog:\n assertOnlyKeys(record, ['conversationId', 'runId', 'cursor', 'limit', 'maxBytes'], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertIdentifier(record.runId, 'request.runId');\n optionalCursorString(record.cursor, 'request.cursor');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.runLogPage);\n optionalProjectionPageBytes(record.maxBytes, 'request.maxBytes');\n return;\n case AGENT_DEVICE_RPC_METHODS.beginAttachmentUpload:\n case AGENT_DEVICE_RPC_METHODS.uploadAttachmentChunk:\n case AGENT_DEVICE_RPC_METHODS.commitAttachmentUpload:\n assertAttachmentUploadRpcRequest(method, value);\n return;\n case AGENT_DEVICE_RPC_METHODS.scheduleList:\n case AGENT_DEVICE_RPC_METHODS.scheduleGet:\n case AGENT_DEVICE_RPC_METHODS.scheduleCreate:\n case AGENT_DEVICE_RPC_METHODS.scheduleUpdate:\n case AGENT_DEVICE_RPC_METHODS.scheduleDelete:\n case AGENT_DEVICE_RPC_METHODS.scheduleCronPreview:\n assertScheduledTaskRpcRequest(method, value);\n return;\n }\n}\n\n/** Validate an untrusted response and return its method-specific type. */\nexport function parseAgentDeviceRpcResponse<M extends AgentDeviceRpcMethod>(\n method: M,\n value: unknown,\n): AgentDeviceRpcResponse<M> {\n // Traverse descriptors before reading a field: accessors, toJSON hooks,\n // exotic prototypes and non-canonical values must never execute here.\n assertJsonBytes(value, 16 * 1024 * 1024, 'response');\n const record = asRecord(value, 'response');\n switch (method) {\n case AGENT_DEVICE_RPC_METHODS.getDefinitions:\n assertOnlyKeys(record, ['definitions'], 'response');\n assertArray(record.definitions, 'response.definitions');\n if (record.definitions.length > AGENT_DEVICE_RPC_LIMITS.definitions) fail('response.definitions');\n for (const definition of record.definitions) assertAgentDefinition(definition, 'response.definitions[]');\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.definitionsBytes, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.create:\n assertOnlyKeys(record, ['conversationId'], 'response');\n assertIdentifier(record.conversationId, 'response.conversationId');\n break;\n case AGENT_DEVICE_RPC_METHODS.send:\n case AGENT_DEVICE_RPC_METHODS.runTurn:\n assertOnlyKeys(record, ['ok', 'runId', 'requestId', 'turnId', 'conversationId', 'state'], 'response');\n assertTurnAcceptedResponse(record);\n break;\n case AGENT_DEVICE_RPC_METHODS.getRunStatus:\n assertOnlyKeys(record, ['status'], 'response');\n nullableRunStatus(record.status, 'response.status');\n break;\n case AGENT_DEVICE_RPC_METHODS.cancel:\n assertOnlyKeys(record, ['ok', 'status'], 'response');\n if (typeof record.ok !== 'boolean') fail('response.ok');\n nullableRunStatus(record.status, 'response.status');\n break;\n case AGENT_DEVICE_RPC_METHODS.deleteTurn:\n assertOnlyKeys(record, ['ok', 'conversationId', 'turnId', 'requestId', 'tombstone'], 'response');\n assertTurnControlResponse(record, false);\n break;\n case AGENT_DEVICE_RPC_METHODS.retryTurn:\n assertOnlyKeys(record, [\n 'ok',\n 'runId',\n 'requestId',\n 'turnId',\n 'conversationId',\n 'state',\n 'tombstone',\n 'userEvent',\n ], 'response');\n assertTurnAcceptedResponse(record);\n assertTurnControlResponse(record, true);\n assertConversationMessageEvent(record.userEvent, 'response.userEvent');\n break;\n case AGENT_DEVICE_RPC_METHODS.listConversations:\n assertOnlyKeys(record, [\n 'items',\n 'nextCursor',\n 'previousCursor',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'seenCursorFound',\n ], 'response');\n assertArray(record.items, 'response.items');\n if (record.items.length > AGENT_DEVICE_RPC_LIMITS.conversationListPage) fail('response.items');\n for (const meta of record.items) assertConversationMeta(meta, 'response.items[]');\n optionalCursorString(record.nextCursor, 'response.nextCursor');\n optionalCursorString(record.previousCursor, 'response.previousCursor');\n if (typeof record.hasMoreBefore !== 'boolean') fail('response.hasMoreBefore');\n if (typeof record.hasMoreAfter !== 'boolean') fail('response.hasMoreAfter');\n optionalBoolean(record.seenCursorFound, 'response.seenCursorFound');\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.conversationListBytes, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getConversationMeta:\n assertOnlyKeys(record, ['meta'], 'response');\n if (!('meta' in record)) fail('response.meta');\n optionalConversationMeta(record.meta, 'response.meta', true);\n break;\n case AGENT_DEVICE_RPC_METHODS.listTurns:\n assertOnlyKeys(record, [\n 'items',\n 'nextCursor',\n 'previousCursor',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'seenCursorFound',\n 'budget',\n ], 'response');\n assertTurnList(record, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getTurnDetail:\n assertOnlyKeys(record, [\n 'turnId',\n 'items',\n 'nextCursor',\n 'previousCursor',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'seenCursorFound',\n ], 'response');\n assertTurnDetail(record, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getMessagePage:\n if (record.reset === true) {\n assertOnlyKeys(record, ['reset', 'conversationId', 'revision'], 'response');\n assertIdentifier(record.conversationId, 'response.conversationId');\n optionalCursorString(record.revision, 'response.revision');\n if (record.revision === undefined) fail('response.revision');\n } else {\n assertOnlyKeys(record, [\n 'reset',\n 'conversationId',\n 'revision',\n 'items',\n 'nextCursor',\n 'previousCursor',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'seenCursorFound',\n ], 'response');\n if (record.reset !== false) fail('response.reset');\n assertIdentifier(record.conversationId, 'response.conversationId');\n optionalCursorString(record.revision, 'response.revision');\n if (record.revision === undefined) fail('response.revision');\n assertMessagePage(record, AGENT_DEVICE_RPC_LIMITS.messagePage, 'response');\n }\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.messagePageBytes, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage:\n if (record.reset === true) {\n assertOnlyKeys(record, ['reset', 'revision'], 'response');\n optionalCursorString(record.revision, 'response.revision');\n if (record.revision === undefined) fail('response.revision');\n } else {\n assertOnlyKeys(record, [\n 'reset',\n 'items',\n 'totalEntries',\n 'totalMessages',\n 'totalTurns',\n 'revision',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startEntryIndex',\n 'endEntryIndex',\n 'startCursor',\n 'endCursor',\n ], 'response');\n assertTimeline(record, 'response');\n }\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.timelinePageMaxBytes, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.loadAround:\n assertMessageWindowResponse(record, 'response');\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.loadAroundMaxBytes, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getMessageDetail:\n assertOnlyKeys(\n record,\n record.found === false\n ? ['found']\n : ['found', 'encoding', 'data', 'offset', 'totalBytes', 'nextOffset'],\n 'response',\n );\n assertDetailChunk(record, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getAttachmentChunk:\n assertOnlyKeys(\n record,\n record.found === false\n ? ['found']\n : ['found', 'reference', 'encoding', 'data', 'offset', 'totalBytes', 'nextOffset'],\n 'response',\n );\n assertAttachmentChunk(record, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.pullAgentRunLog:\n assertOnlyKeys(record, ['messages', 'nextCursor', 'hasMoreAfter', 'runStatus'], 'response');\n assertRunLog(record, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.beginAttachmentUpload:\n case AGENT_DEVICE_RPC_METHODS.uploadAttachmentChunk:\n case AGENT_DEVICE_RPC_METHODS.commitAttachmentUpload:\n return parseAttachmentUploadRpcResponse(method, value) as AgentDeviceRpcResponse<M>;\n case AGENT_DEVICE_RPC_METHODS.scheduleList:\n case AGENT_DEVICE_RPC_METHODS.scheduleGet:\n case AGENT_DEVICE_RPC_METHODS.scheduleCreate:\n case AGENT_DEVICE_RPC_METHODS.scheduleUpdate:\n case AGENT_DEVICE_RPC_METHODS.scheduleDelete:\n case AGENT_DEVICE_RPC_METHODS.scheduleCronPreview:\n return parseScheduledTaskRpcResponse(method, value) as AgentDeviceRpcResponse<M>;\n }\n return value as AgentDeviceRpcResponse<M>;\n}\n\n/** Reject valid-shaped responses that do not belong to the originating request. */\nexport function assertAgentDeviceRpcResponseCorrelation<M extends AgentDeviceRpcMethod>(\n method: M,\n request: AgentDeviceRpcRequest<M>,\n response: AgentDeviceRpcResponse<M>,\n): void {\n const requestRecord = request as Record<string, unknown>;\n const responseRecord = response as Record<string, unknown>;\n if (\n requestRecord.seenCursor !== undefined &&\n typeof responseRecord.seenCursorFound !== 'boolean'\n ) fail('response.seenCursorFound');\n switch (method) {\n case AGENT_DEVICE_RPC_METHODS.create:\n if (\n requestRecord.conversationId !== undefined &&\n responseRecord.conversationId !== requestRecord.conversationId\n ) fail('response.conversationId');\n return;\n case AGENT_DEVICE_RPC_METHODS.send:\n case AGENT_DEVICE_RPC_METHODS.runTurn:\n for (const field of ['requestId', 'turnId', 'conversationId']) {\n if (responseRecord[field] !== requestRecord[field]) fail(`response.${field}`);\n }\n return;\n case AGENT_DEVICE_RPC_METHODS.getRunStatus:\n case AGENT_DEVICE_RPC_METHODS.cancel: {\n const status = responseRecord.status as AgentDeviceRpcRunStatus | null;\n if (status && status.runId !== requestRecord.runId) fail('response.status.runId');\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.deleteTurn: {\n assertTurnControlCorrelation(requestRecord, responseRecord);\n const tombstone = responseRecord.tombstone as ConversationTombstoneEvent;\n if (requestRecord.reason !== undefined && tombstone.reason !== requestRecord.reason) {\n fail('response.tombstone.reason');\n }\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.retryTurn: {\n if (\n responseRecord.requestId !== requestRecord.requestId ||\n responseRecord.turnId !== requestRecord.newTurnId ||\n responseRecord.conversationId !== requestRecord.conversationId\n ) fail('response');\n const tombstone = responseRecord.tombstone as ConversationTombstoneEvent;\n if (\n tombstone.conversationId !== requestRecord.conversationId ||\n tombstone.targetTurnId !== requestRecord.turnId\n ) fail('response.tombstone');\n const userEvent = responseRecord.userEvent as ConversationMessageEvent;\n if (\n userEvent.conversationId !== requestRecord.conversationId ||\n userEvent.message.messageId !== requestRecord.newTurnId ||\n userEvent.message.turnId !== requestRecord.newTurnId ||\n userEvent.message.role !== 'user'\n ) fail('response.userEvent');\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.getConversationMeta: {\n const meta = responseRecord.meta as ConversationMeta | null;\n if (meta && meta.conversationId !== requestRecord.conversationId) fail('response.meta.conversationId');\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.listConversations:\n assertRequestedPageLimit(requestRecord, responseRecord, AGENT_DEVICE_RPC_LIMITS.conversationListPage);\n return;\n case AGENT_DEVICE_RPC_METHODS.listTurns: {\n assertRequestedPageLimit(requestRecord, responseRecord, AGENT_DEVICE_RPC_LIMITS.turnListPage);\n const budget = responseRecord.budget as AgentDeviceRpcListTurnsResponse['budget'];\n if (budget.bytes > (requestRecord.byteBudget as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes)) {\n fail('response.budget.bytes');\n }\n if (\n jsonByteLength(responseRecord) >\n (requestRecord.byteBudget as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes)\n ) fail('response');\n if (\n budget.renderLines >\n (requestRecord.renderLineBudget as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.turnRenderLines)\n ) fail('response.budget.renderLines');\n if (\n turnRenderLines(responseRecord.items) >\n (requestRecord.renderLineBudget as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.turnRenderLines)\n ) fail('response.items');\n assertConversationItems(responseRecord, requestRecord.conversationId as string);\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.getMessagePage:\n if (responseRecord.conversationId !== requestRecord.conversationId) {\n fail('response.conversationId');\n }\n assertRequestedByteBudget(requestRecord, responseRecord);\n if (responseRecord.reset === true) return;\n if (\n requestRecord.expectedRevision !== undefined &&\n responseRecord.revision !== requestRecord.expectedRevision\n ) fail('response.revision');\n assertRequestedPageLimit(requestRecord, responseRecord, AGENT_DEVICE_RPC_LIMITS.messagePage);\n assertConversationItems(responseRecord, requestRecord.conversationId as string);\n return;\n case AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage:\n assertTimelinePageCorrelation(requestRecord, responseRecord);\n if (responseRecord.reset === true) {\n assertRequestedByteBudget(\n requestRecord,\n responseRecord,\n AGENT_DEVICE_RPC_LIMITS.timelinePageDefaultBytes,\n );\n return;\n }\n if (\n (responseRecord.items as unknown[]).length >\n (requestRecord.limit as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.timelinePage)\n ) fail('response.items');\n assertConversationItems(responseRecord, requestRecord.conversationId as string);\n assertRequestedByteBudget(\n requestRecord,\n responseRecord,\n AGENT_DEVICE_RPC_LIMITS.timelinePageDefaultBytes,\n );\n return;\n case AGENT_DEVICE_RPC_METHODS.getTurnDetail:\n assertRequestedPageLimit(requestRecord, responseRecord, AGENT_DEVICE_RPC_LIMITS.turnDetailPage);\n if (responseRecord.turnId !== requestRecord.turnId) fail('response.turnId');\n for (const item of responseRecord.items as ChatMessage[]) {\n if (item.conversationId !== requestRecord.conversationId || item.turnId !== requestRecord.turnId) {\n fail('response.items');\n }\n }\n assertRequestedByteBudget(requestRecord, responseRecord);\n return;\n case AGENT_DEVICE_RPC_METHODS.loadAround:\n assertMessageWindowCorrelation(\n requestRecord as unknown as AgentDeviceRpcLoadAroundRequest,\n responseRecord as unknown as AgentDeviceRpcLoadAroundResponse,\n );\n return;\n case AGENT_DEVICE_RPC_METHODS.getAttachmentChunk: {\n if (responseRecord.found === true) {\n const reference = responseRecord.reference as AttachmentReference;\n if (reference.contentHash !== requestRecord.contentHash) fail('response.reference.contentHash');\n }\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.pullAgentRunLog: {\n assertRequestedPageLimit(requestRecord, responseRecord, AGENT_DEVICE_RPC_LIMITS.runLogPage, 'messages');\n const status = responseRecord.runStatus as AgentDeviceRpcRunStatus | null;\n if (status && status.runId !== requestRecord.runId) fail('response.runStatus.runId');\n assertRequestedByteBudget(requestRecord, responseRecord);\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.beginAttachmentUpload:\n case AGENT_DEVICE_RPC_METHODS.uploadAttachmentChunk:\n case AGENT_DEVICE_RPC_METHODS.commitAttachmentUpload:\n assertEmbeddedAttachmentUploadCorrelation(\n method as AttachmentUploadRpcMethod,\n request,\n response,\n );\n return;\n case AGENT_DEVICE_RPC_METHODS.scheduleList:\n case AGENT_DEVICE_RPC_METHODS.scheduleGet:\n case AGENT_DEVICE_RPC_METHODS.scheduleCreate:\n case AGENT_DEVICE_RPC_METHODS.scheduleUpdate:\n case AGENT_DEVICE_RPC_METHODS.scheduleDelete:\n case AGENT_DEVICE_RPC_METHODS.scheduleCronPreview:\n assertEmbeddedScheduledTaskCorrelation(method, request, response);\n return;\n case AGENT_DEVICE_RPC_METHODS.getDefinitions:\n case AGENT_DEVICE_RPC_METHODS.getMessageDetail:\n return;\n }\n}\n\nfunction assertEmbeddedScheduledTaskCorrelation(\n method: ScheduledTaskRpcMethod,\n request: unknown,\n response: unknown,\n): void {\n if (!isScheduledTaskRpcMethod(method)) fail('method');\n assertScheduledTaskRpcResponseCorrelation(\n method,\n request as ScheduledTaskRpcRequest<typeof method>,\n response as ScheduledTaskRpcResponse<typeof method>,\n );\n}\n\nfunction assertEmbeddedAttachmentUploadCorrelation(\n method: AttachmentUploadRpcMethod,\n request: unknown,\n response: unknown,\n): void {\n switch (method) {\n case ATTACHMENT_UPLOAD_RPC_METHODS.begin:\n assertAttachmentUploadRpcResponseCorrelation(\n method,\n request as AttachmentUploadRpcRequest<typeof method>,\n response as AttachmentUploadRpcResponse<typeof method>,\n );\n return;\n case ATTACHMENT_UPLOAD_RPC_METHODS.chunk:\n assertAttachmentUploadRpcResponseCorrelation(\n method,\n request as AttachmentUploadRpcRequest<typeof method>,\n response as AttachmentUploadRpcResponse<typeof method>,\n );\n return;\n case ATTACHMENT_UPLOAD_RPC_METHODS.commit:\n assertAttachmentUploadRpcResponseCorrelation(\n method,\n request as AttachmentUploadRpcRequest<typeof method>,\n response as AttachmentUploadRpcResponse<typeof method>,\n );\n }\n}\n\nfunction assertConversationItems(response: Record<string, unknown>, conversationId: string): void {\n for (const item of response.items as Array<{ conversationId: string }>) {\n if (item.conversationId !== conversationId) fail('response.items.conversationId');\n }\n}\n\nfunction assertTimelinePageCorrelation(\n request: Record<string, unknown>,\n response: Record<string, unknown>,\n): void {\n try {\n assertConversationTimelinePage(\n response,\n request.conversationId as string,\n {\n limit: request.limit as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.timelinePage,\n maxBytes: request.maxBytes as number | undefined ??\n AGENT_DEVICE_RPC_LIMITS.timelinePageDefaultBytes,\n ...(request.expectedRevision === undefined\n ? {}\n : { expectedRevision: request.expectedRevision as string }),\n ...(request.beforeCursor === undefined\n ? {}\n : { beforeCursor: request.beforeCursor as string }),\n ...(request.afterCursor === undefined\n ? {}\n : { afterCursor: request.afterCursor as string }),\n ...(request.aroundEntryIndex === undefined\n ? {}\n : { aroundEntryIndex: request.aroundEntryIndex as number }),\n },\n );\n } catch {\n fail('response');\n }\n if (response.reset) return;\n const items = response.items;\n if (\n request.aroundEntryIndex !== undefined &&\n (request.aroundEntryIndex as number) < (response.totalEntries) &&\n !items.some(item => item.entryIndex === request.aroundEntryIndex)\n ) fail('response.items.entryIndex');\n}\n\nfunction assertRequestedPageLimit(\n request: Record<string, unknown>,\n response: Record<string, unknown>,\n defaultLimit: number,\n itemsField = 'items',\n): void {\n if ((response[itemsField] as unknown[]).length > (request.limit as number | undefined ?? defaultLimit)) {\n fail(`response.${itemsField}`);\n }\n}\n\nfunction assertRequestedByteBudget(\n request: Record<string, unknown>,\n response: Record<string, unknown>,\n defaultBytes = AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes,\n): void {\n const maximum = request.maxBytes as number | undefined ?? defaultBytes;\n if (jsonByteLength(response) > maximum) fail('response');\n}\n\nfunction assertSendRequest(record: Record<string, unknown>, requireDefinition: boolean): void {\n assertIdentifier(record.requestId, 'request.requestId');\n assertIdentifier(record.turnId, 'request.turnId');\n assertIdentifier(record.conversationId, 'request.conversationId');\n if (typeof record.message !== 'string') fail('request.message');\n if (requireDefinition) assertIdentifier(record.definitionId, 'request.definitionId');\n else optionalIdentifier(record.definitionId, 'request.definitionId');\n if (record.userMessage !== undefined) {\n assertPendingLocalUserMessage(record.userMessage, record.turnId);\n const userMessage = record.userMessage as AgentDeviceRpcPendingUserMessage;\n if (userMessage.content !== undefined && userMessage.content !== record.message) {\n fail('request.userMessage.content');\n }\n }\n}\n\nfunction assertPendingLocalUserMessage(value: unknown, turnId: string): void {\n const record = asRecord(value, 'request.userMessage');\n assertOnlyKeys(record, [\n 'content',\n 'parts',\n 'toolCalls',\n 'attachments',\n 'detailRef',\n 'reasoning_content',\n 'contentType',\n 'hidden',\n 'duration',\n 'metadata',\n ], 'request.userMessage');\n const event = {\n eventId: turnId,\n conversationId: 'rpc-validation',\n originNodeId: 'rpc-validation',\n originSequence: 1,\n lamportClock: 1,\n timestamp: 0,\n kind: 'message',\n message: {\n messageId: turnId,\n turnId,\n role: 'user',\n content: record.content ?? '',\n ...record,\n },\n };\n assertConversationMessageEvent(event, 'request.userMessage');\n try {\n assertAgentUserMessageWithinLimits(conversationEventToMessage(event));\n } catch {\n fail('request.userMessage');\n }\n const references: AttachmentReference[] = [\n ...((record.attachments as AttachmentReference[] | undefined) ?? []),\n ...((record.parts as Array<{ type: string; attachment?: AttachmentReference }> | undefined) ?? [])\n .filter(part => part.type === 'attachment' && part.attachment !== undefined)\n .map(part => part.attachment!),\n ];\n if (references.length > AGENT_DEVICE_RPC_LIMITS.userMessageAttachments) {\n fail('request.userMessage.attachments');\n }\n for (const reference of references) {\n if (\n !ATTACHMENT_UPLOAD_SHA256_PATTERN.test(reference.contentHash) ||\n reference.size > ATTACHMENT_UPLOAD_LIMITS.totalBytes ||\n reference.filename.length > ATTACHMENT_UPLOAD_LIMITS.filenameCharacters ||\n reference.mimeType.length > ATTACHMENT_UPLOAD_LIMITS.mimeTypeCharacters\n ) fail('request.userMessage.attachments');\n }\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.userMessageBytes, 'request.userMessage');\n}\n\nfunction assertTurnControlIdentity(record: Record<string, unknown>): void {\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertIdentifier(record.turnId, 'request.turnId');\n assertIdentifier(record.requestId, 'request.requestId');\n}\n\nfunction assertTurnControlResponse(record: Record<string, unknown>, retry: boolean): void {\n if (record.ok !== true) fail('response.ok');\n assertIdentifier(record.conversationId, 'response.conversationId');\n assertIdentifier(record.turnId, 'response.turnId');\n assertIdentifier(record.requestId, 'response.requestId');\n assertConversationTombstoneEvent(record.tombstone, 'response.tombstone');\n if (!retry && record.tombstone.targetTurnId !== record.turnId) fail('response.tombstone.targetTurnId');\n}\n\nfunction assertTurnControlCorrelation(\n request: Record<string, unknown>,\n response: Record<string, unknown>,\n): void {\n if (\n response.requestId !== request.requestId ||\n response.turnId !== request.turnId ||\n response.conversationId !== request.conversationId\n ) fail('response');\n const tombstone = response.tombstone as ConversationTombstoneEvent;\n if (\n tombstone.conversationId !== request.conversationId ||\n tombstone.targetTurnId !== request.turnId\n ) fail('response.tombstone');\n}\n\nfunction assertConversationTombstoneEvent(\n value: unknown,\n field: string,\n): asserts value is ConversationTombstoneEvent {\n if (!isConversationEvent(value) || value.kind !== 'tombstone') fail(field);\n assertJsonBytes(value, MAX_CONVERSATION_EVENT_BYTES, field);\n}\n\nfunction assertConversationMessageEvent(\n value: unknown,\n field: string,\n): asserts value is ConversationMessageEvent {\n if (!isConversationEvent(value) || value.kind !== 'message') fail(field);\n assertJsonBytes(value, MAX_CONVERSATION_EVENT_BYTES, field);\n}\n\nfunction assertTurnAcceptedResponse(record: Record<string, unknown>): void {\n if (record.ok !== true || record.state !== 'accepted') fail('response.state');\n assertIdentifier(record.runId, 'response.runId');\n assertIdentifier(record.requestId, 'response.requestId');\n assertIdentifier(record.turnId, 'response.turnId');\n assertIdentifier(record.conversationId, 'response.conversationId');\n}\n\nfunction assertMessagePage(\n record: Record<string, unknown>,\n maximum: number,\n field: string,\n allowDuplicates = false,\n): void {\n assertArray(record.items, `${field}.items`);\n if (record.items.length > maximum) fail(`${field}.items`);\n const messageIds = new Set<string>();\n for (const message of record.items) {\n try {\n assertConversationMessageProjection(message);\n assertJsonBytes(message, AGENT_DEVICE_RPC_LIMITS.messageProjectionBytes, `${field}.items[]`);\n } catch {\n fail(`${field}.items[]`);\n }\n if (!allowDuplicates && messageIds.has(message.messageId)) fail(`${field}.items[].messageId`);\n messageIds.add(message.messageId);\n }\n if (typeof record.hasMoreBefore !== 'boolean') fail(`${field}.hasMoreBefore`);\n if (typeof record.hasMoreAfter !== 'boolean') fail(`${field}.hasMoreAfter`);\n optionalCursorString(record.nextCursor, `${field}.nextCursor`);\n optionalCursorString(record.previousCursor, `${field}.previousCursor`);\n optionalBoolean(record.seenCursorFound, `${field}.seenCursorFound`);\n}\n\nfunction assertTimeline(record: Record<string, unknown>, field: string): void {\n try {\n assertConversationTimelinePageEnvelope(record, {\n limit: AGENT_DEVICE_RPC_LIMITS.timelinePage,\n maxBytes: AGENT_DEVICE_RPC_LIMITS.timelinePageMaxBytes,\n previewLength: AGENT_DEVICE_RPC_LIMITS.timelinePreviewCharacters,\n });\n } catch {\n fail(field);\n }\n}\n\nfunction assertTurnList(record: Record<string, unknown>, field: string): void {\n assertArray(record.items, `${field}.items`);\n if (record.items.length > AGENT_DEVICE_RPC_LIMITS.turnListPage) fail(`${field}.items`);\n const turnIds = new Set<string>();\n for (const value of record.items) {\n assertTurnSummary(value, `${field}.items[]`);\n if (turnIds.has(value.turnId)) fail(`${field}.items[].turnId`);\n turnIds.add(value.turnId);\n }\n assertPageNavigation(record, field);\n const budget = asRecord(record.budget, `${field}.budget`);\n assertBoundedInteger(budget.bytes, `${field}.budget.bytes`, 0, AGENT_DEVICE_RPC_LIMITS.turnProjectionBytes);\n assertBoundedInteger(budget.renderLines, `${field}.budget.renderLines`, 0, AGENT_DEVICE_RPC_LIMITS.turnRenderLines);\n if (typeof budget.truncated !== 'boolean') fail(`${field}.budget.truncated`);\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.turnProjectionBytes, field);\n}\n\nfunction assertTurnDetail(record: Record<string, unknown>, field: string): void {\n assertIdentifier(record.turnId, `${field}.turnId`);\n assertArray(record.items, `${field}.items`);\n if (record.items.length > AGENT_DEVICE_RPC_LIMITS.turnDetailPage) fail(`${field}.items`);\n for (const message of record.items) {\n try {\n assertConversationMessageProjection(message);\n } catch {\n fail(`${field}.items[]`);\n }\n }\n assertPageNavigation(record, field);\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.messagePageBytes, field);\n}\n\nfunction assertMessageWindowFocus(\n value: unknown,\n field: string,\n): asserts value is ConversationMessageWindowFocus {\n const record = asRecord(value, field);\n if (record.kind === 'turn') {\n assertOnlyKeys(record, ['kind', 'turnId', 'cursor'], field);\n assertIdentifier(record.turnId, `${field}.turnId`);\n optionalCursorString(record.cursor, `${field}.cursor`);\n return;\n }\n if (record.kind === 'timeline-entry') {\n assertOnlyKeys(record, ['kind', 'entryId', 'cursor'], field);\n assertIdentifier(record.entryId, `${field}.entryId`);\n optionalCursorString(record.cursor, `${field}.cursor`);\n if (record.cursor === undefined) fail(`${field}.cursor`);\n return;\n }\n fail(`${field}.kind`);\n}\n\nfunction assertMessageWindowResponse(record: Record<string, unknown>, field: string): void {\n if (record.reset === true) {\n assertOnlyKeys(record, ['reset', 'conversationId', 'revision'], field);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n optionalCursorString(record.revision, `${field}.revision`);\n if (record.revision === undefined) fail(`${field}.revision`);\n return;\n }\n assertOnlyKeys(record, [\n 'reset',\n 'conversationId',\n 'revision',\n 'focus',\n 'items',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'previousCursor',\n 'nextCursor',\n ], field);\n if (record.reset !== false) fail(`${field}.reset`);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n optionalCursorString(record.revision, `${field}.revision`);\n if (record.revision === undefined) fail(`${field}.revision`);\n assertResolvedMessageWindowFocus(record.focus, `${field}.focus`);\n assertArray(record.items, `${field}.items`);\n if (record.items.length > AGENT_DEVICE_RPC_LIMITS.loadAroundMessages) fail(`${field}.items`);\n const messageIds = new Set<string>();\n for (const item of record.items) {\n try {\n assertConversationMessageProjection(item, record.conversationId);\n assertJsonBytes(item, AGENT_DEVICE_RPC_LIMITS.messageProjectionBytes, `${field}.items[]`);\n } catch {\n fail(`${field}.items[]`);\n }\n if (messageIds.has(item.messageId)) fail(`${field}.items[].messageId`);\n messageIds.add(item.messageId);\n }\n if (typeof record.hasMoreBefore !== 'boolean') fail(`${field}.hasMoreBefore`);\n if (typeof record.hasMoreAfter !== 'boolean') fail(`${field}.hasMoreAfter`);\n optionalCursorString(record.previousCursor, `${field}.previousCursor`);\n optionalCursorString(record.nextCursor, `${field}.nextCursor`);\n if (record.items.length === 0) {\n if (\n record.hasMoreBefore || record.hasMoreAfter ||\n record.previousCursor !== undefined || record.nextCursor !== undefined\n ) fail(`${field}.items`);\n return;\n }\n if (record.hasMoreBefore !== (record.previousCursor !== undefined)) fail(`${field}.previousCursor`);\n if (record.hasMoreAfter !== (record.nextCursor !== undefined)) fail(`${field}.nextCursor`);\n}\n\nfunction assertResolvedMessageWindowFocus(value: unknown, field: string): void {\n const record = asRecord(value, field);\n if (record.kind === 'turn') {\n assertOnlyKeys(record, ['kind', 'turnId', 'entryId', 'cursor'], field);\n assertIdentifier(record.turnId, `${field}.turnId`);\n optionalIdentifier(record.entryId, `${field}.entryId`);\n optionalCursorString(record.cursor, `${field}.cursor`);\n return;\n }\n if (record.kind !== 'compaction') fail(`${field}.kind`);\n assertOnlyKeys(record, ['kind', 'entry', 'nearestPosition', 'nearestTurnId'], field);\n try {\n assertConversationTimelineCompactionEntry(record.entry, {\n maximumPreview: AGENT_DEVICE_RPC_LIMITS.timelinePreviewCharacters,\n });\n } catch {\n fail(`${field}.entry`);\n }\n if (record.nearestPosition === 'none') {\n if (record.nearestTurnId !== undefined) fail(`${field}.nearestTurnId`);\n return;\n }\n if (record.nearestPosition !== 'before' && record.nearestPosition !== 'after') {\n fail(`${field}.nearestPosition`);\n }\n assertIdentifier(record.nearestTurnId, `${field}.nearestTurnId`);\n}\n\nfunction assertMessageWindowCorrelation(\n request: AgentDeviceRpcLoadAroundRequest,\n response: AgentDeviceRpcLoadAroundResponse,\n): void {\n if (response.conversationId !== request.conversationId) fail('response.conversationId');\n assertRequestedByteBudget(\n request as unknown as Record<string, unknown>,\n response as unknown as Record<string, unknown>,\n AGENT_DEVICE_RPC_LIMITS.loadAroundDefaultBytes,\n );\n if (response.reset) return;\n if (response.revision !== request.expectedRevision) fail('response.revision');\n if (response.items.length > (request.maxMessages ?? AGENT_DEVICE_RPC_LIMITS.loadAroundMessages)) {\n fail('response.items');\n }\n for (const item of response.items) {\n if (item.conversationId !== request.conversationId) fail('response.items');\n }\n if (request.focus.kind === 'turn') {\n if (\n response.focus.kind !== 'turn' ||\n response.focus.turnId !== request.focus.turnId ||\n response.focus.entryId !== undefined ||\n response.focus.cursor !== request.focus.cursor\n ) {\n fail('response.focus');\n }\n return;\n }\n if (response.focus.kind === 'turn') {\n if (\n response.focus.entryId !== request.focus.entryId ||\n response.focus.cursor !== request.focus.cursor\n ) fail('response.focus');\n return;\n }\n if (\n response.focus.entry.entryId !== request.focus.entryId ||\n response.focus.entry.cursor !== request.focus.cursor\n ) fail('response.focus');\n}\n\nfunction assertTurnSummary(value: unknown, field: string): asserts value is AgentDeviceRpcTurnSummary {\n const record = asRecord(value, field);\n assertIdentifier(record.turnId, `${field}.turnId`);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n optionalCursorString(record.cursor, `${field}.cursor`);\n if (record.cursor === undefined) fail(`${field}.cursor`);\n assertBoundedInteger(record.startedAt, `${field}.startedAt`, 0, Number.MAX_SAFE_INTEGER);\n assertBoundedInteger(record.updatedAt, `${field}.updatedAt`, 0, Number.MAX_SAFE_INTEGER);\n assertPreview(record.userPreview, `${field}.userPreview`);\n assertArray(record.participantPreviews, `${field}.participantPreviews`);\n if (record.participantPreviews.length > 4 || jsonByteLength(record.participantPreviews) > 1_024) {\n fail(`${field}.participantPreviews`);\n }\n for (const [index, participantValue] of record.participantPreviews.entries()) {\n const participant = asRecord(participantValue, `${field}.participantPreviews[${index}]`);\n if (\n Reflect.ownKeys(participant).some(key => typeof key !== 'string' || !['actorId', 'actorLabel', 'role', 'preview'].includes(key)) ||\n typeof participant.actorId !== 'string' || participant.actorId.length === 0 || participant.actorId.length > 160 ||\n typeof participant.actorLabel !== 'string' || participant.actorLabel.length === 0 || participant.actorLabel.length > 160 ||\n (participant.role !== 'assistant' && participant.role !== 'agent') ||\n typeof participant.preview !== 'string' || participant.preview.length > 160\n ) fail(`${field}.participantPreviews[${index}]`);\n }\n assertBoundedInteger(record.responseCount, `${field}.responseCount`, 0, Number.MAX_SAFE_INTEGER);\n if (record.responseCount < record.participantPreviews.length) fail(`${field}.responseCount`);\n if (\n record.runState !== undefined &&\n !['accepted', 'queued', 'running', 'completed', 'failed', 'cancelled'].includes(record.runState as string)\n ) fail(`${field}.runState`);\n if (typeof record.isCompaction !== 'boolean') fail(`${field}.isCompaction`);\n optionalBoundedInteger(record.compactedMessageCount, `${field}.compactedMessageCount`, 1, Number.MAX_SAFE_INTEGER);\n if (typeof record.isTombstone !== 'boolean') fail(`${field}.isTombstone`);\n if (record.detailState !== 'summary' && record.detailState !== 'full' && record.detailState !== 'notLoaded') {\n fail(`${field}.detailState`);\n }\n if (record.messages !== undefined) {\n if (record.detailState !== 'full') fail(`${field}.messages`);\n assertArray(record.messages, `${field}.messages`);\n if (record.messages.length > AGENT_DEVICE_RPC_LIMITS.turnDetailPage) fail(`${field}.messages`);\n for (const message of record.messages) assertChatMessage(message, `${field}.messages[]`);\n }\n}\n\nfunction assertPageNavigation(record: Record<string, unknown>, field: string, seen = true): void {\n if (typeof record.hasMoreBefore !== 'boolean') fail(`${field}.hasMoreBefore`);\n if (typeof record.hasMoreAfter !== 'boolean') fail(`${field}.hasMoreAfter`);\n optionalCursorString(record.nextCursor, `${field}.nextCursor`);\n optionalCursorString(record.previousCursor, `${field}.previousCursor`);\n if (seen) optionalBoolean(record.seenCursorFound, `${field}.seenCursorFound`);\n}\n\nfunction assertDetailChunk(record: Record<string, unknown>, field: string): void {\n if (record.found === false) return;\n if (record.found !== true || record.encoding !== 'base64-json') fail(`${field}.encoding`);\n assertChunk(record, AGENT_DEVICE_RPC_LIMITS.detailChunkBytes, field);\n}\n\nfunction assertAttachmentChunk(record: Record<string, unknown>, field: string): void {\n if (record.found === false) return;\n if (record.found !== true || record.encoding !== 'base64') fail(`${field}.encoding`);\n assertAttachmentReference(record.reference, `${field}.reference`);\n assertChunk(record, AGENT_DEVICE_RPC_LIMITS.attachmentChunkBytes, field);\n}\n\nfunction assertChunk(record: Record<string, unknown>, maximumBytes: number, field: string): void {\n if (typeof record.data !== 'string' || !isCanonicalBase64(record.data)) fail(`${field}.data`);\n const byteLength = decodedBase64ByteLength(record.data);\n if (byteLength > maximumBytes) fail(`${field}.data`);\n assertBoundedInteger(record.offset, `${field}.offset`, 0, Number.MAX_SAFE_INTEGER);\n assertBoundedInteger(record.totalBytes, `${field}.totalBytes`, 0, Number.MAX_SAFE_INTEGER);\n optionalBoundedInteger(record.nextOffset, `${field}.nextOffset`, 1, Number.MAX_SAFE_INTEGER);\n if (record.offset + byteLength > record.totalBytes) fail(`${field}.totalBytes`);\n const expectedNext = record.offset + byteLength;\n if (record.nextOffset !== undefined && record.nextOffset !== expectedNext) fail(`${field}.nextOffset`);\n if (record.nextOffset === undefined && expectedNext !== record.totalBytes) fail(`${field}.nextOffset`);\n}\n\nfunction assertRunLog(record: Record<string, unknown>, field: string): void {\n assertArray(record.messages, `${field}.messages`);\n if (record.messages.length > AGENT_DEVICE_RPC_LIMITS.runLogPage) fail(`${field}.messages`);\n for (const value of record.messages) {\n const message = asRecord(value, `${field}.messages[]`);\n assertIdentifier(message.messageId, `${field}.messages[].messageId`);\n assertChatRole(message.role, `${field}.messages[].role`);\n if (\n typeof message.content !== 'string' ||\n message.content.length > AGENT_DEVICE_RPC_LIMITS.runLogContentCharacters\n ) fail(`${field}.messages[].content`);\n }\n optionalCursorString(record.nextCursor, `${field}.nextCursor`);\n if (typeof record.hasMoreAfter !== 'boolean') fail(`${field}.hasMoreAfter`);\n nullableRunStatus(record.runStatus, `${field}.runStatus`);\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.runLogPageBytes, field);\n}\n\nfunction assertAgentDefinition(value: unknown, field: string): void {\n const record = asRecord(value, field);\n assertIdentifier(record.id, `${field}.id`);\n if (typeof record.name !== 'string' || typeof record.description !== 'string' || typeof record.systemPrompt !== 'string') fail(field);\n assertArray(record.tools, `${field}.tools`);\n if (!record.tools.every(tool => typeof tool === 'string')) fail(`${field}.tools`);\n if (typeof record.version !== 'string') fail(`${field}.version`);\n}\n\nfunction assertConversationMeta(value: unknown, field: string): asserts value is ConversationMeta {\n const record = asRecord(value, field);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n if (\n typeof record.title !== 'string' || record.title.length > 512 ||\n typeof record.lastMessagePreview !== 'string' || record.lastMessagePreview.length > 2_000 ||\n typeof record.originNodeId !== 'string' ||\n typeof record.definitionId !== 'string' ||\n typeof record.isUserInitiated !== 'boolean'\n ) fail(field);\n assertBoundedInteger(record.lastMessageTimestamp, `${field}.lastMessageTimestamp`, 0, Number.MAX_SAFE_INTEGER);\n assertBoundedInteger(record.messageCount, `${field}.messageCount`, 0, Number.MAX_SAFE_INTEGER);\n assertBoundedInteger(record.originClock, `${field}.originClock`, 0, Number.MAX_SAFE_INTEGER);\n}\n\nfunction optionalConversationMeta(value: unknown, field: string, nullable = false): void {\n if (value === undefined || (nullable && value === null)) return;\n assertConversationMeta(value, field);\n}\n\nfunction assertChatMessage(\n value: unknown,\n field: string,\n maximumBytes = AGENT_DEVICE_RPC_LIMITS.messageProjectionBytes,\n): asserts value is ChatMessage {\n try {\n assertCanonicalChatMessageProjection(value);\n assertJsonBytes(value, maximumBytes, field);\n } catch {\n fail(field);\n }\n}\n\n/** Parse the complete JSON object reconstructed from getMessageDetail chunks. */\nexport function parseAgentDeviceRpcMessageDetail(value: unknown): ChatMessage {\n assertChatMessage(value, 'response.data', AGENT_DEVICE_RPC_LIMITS.messageDetailBytes);\n return value;\n}\n\nfunction assertChatRole(value: unknown, field: string): void {\n if (value !== 'user' && value !== 'assistant' && value !== 'tool' && value !== 'agent' && value !== 'error') fail(field);\n}\n\nfunction assertAttachmentReference(value: unknown, field: string): void {\n const record = asRecord(value, field);\n assertIdentifier(record.contentHash, `${field}.contentHash`);\n if (typeof record.filename !== 'string' || typeof record.mimeType !== 'string') fail(field);\n assertBoundedInteger(record.size, `${field}.size`, 0, Number.MAX_SAFE_INTEGER);\n}\n\nfunction nullableRunStatus(value: unknown, field: string): void {\n if (value === null) return;\n const record = asRecord(value, field);\n assertOnlyKeys(record, [\n 'runId',\n 'conversationId',\n 'definitionId',\n 'turnId',\n 'requestPeerId',\n 'requestId',\n 'payloadDigest',\n 'state',\n 'acceptedAt',\n 'updatedAt',\n 'startedAt',\n 'finishedAt',\n 'cancelRequestedAt',\n 'error',\n ], field);\n assertIdentifier(record.runId, `${field}.runId`);\n assertIdentifier(record.requestId, `${field}.requestId`);\n assertIdentifier(record.turnId, `${field}.turnId`);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n assertIdentifier(record.definitionId, `${field}.definitionId`);\n assertIdentifier(record.requestPeerId, `${field}.requestPeerId`);\n assertIdentifier(record.payloadDigest, `${field}.payloadDigest`);\n if (!['accepted', 'queued', 'running', 'completed', 'failed', 'cancelled'].includes(record.state as string)) fail(`${field}.state`);\n assertBoundedInteger(record.acceptedAt, `${field}.acceptedAt`, 0, Number.MAX_SAFE_INTEGER);\n assertBoundedInteger(record.updatedAt, `${field}.updatedAt`, 0, Number.MAX_SAFE_INTEGER);\n optionalBoundedInteger(record.startedAt, `${field}.startedAt`, 0, Number.MAX_SAFE_INTEGER);\n optionalBoundedInteger(record.finishedAt, `${field}.finishedAt`, 0, Number.MAX_SAFE_INTEGER);\n optionalBoundedInteger(record.cancelRequestedAt, `${field}.cancelRequestedAt`, 0, Number.MAX_SAFE_INTEGER);\n if (record.error !== undefined) {\n try {\n normalizeAgentRunError(record.error);\n } catch {\n fail(`${field}.error`);\n }\n }\n}\n\nfunction asRecord(value: unknown, field: string): Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) fail(field);\n return value as Record<string, unknown>;\n}\n\nfunction assertOnlyKeys(\n record: Record<string, unknown>,\n allowed: readonly string[],\n field: string,\n): void {\n if (Object.keys(record).some(key => !allowed.includes(key))) fail(field);\n}\n\nfunction assertArray(value: unknown, field: string): asserts value is unknown[] {\n if (!Array.isArray(value)) fail(field);\n}\n\nfunction assertIdentifier(value: unknown, field: string): asserts value is string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.length > AGENT_DEVICE_RPC_LIMITS.identifierCharacters ||\n value !== value.trim() ||\n hasAsciiControlText(value)\n ) fail(field);\n}\n\nfunction optionalIdentifier(value: unknown, field: string): void {\n if (value !== undefined) assertIdentifier(value, field);\n}\n\nfunction optionalString(value: unknown, field: string): void {\n if (value !== undefined && typeof value !== 'string') fail(field);\n}\n\nfunction optionalProjectionPageBytes(value: unknown, field: string): void {\n optionalBoundedInteger(\n value,\n field,\n AGENT_DEVICE_RPC_LIMITS.projectionPageMinBytes,\n AGENT_DEVICE_RPC_LIMITS.projectionPageMaxBytes,\n );\n}\n\nfunction optionalTimelinePageBytes(value: unknown, field: string): void {\n optionalBoundedInteger(\n value,\n field,\n 1,\n AGENT_DEVICE_RPC_LIMITS.timelinePageMaxBytes,\n );\n}\n\nfunction optionalLoadAroundBytes(value: unknown, field: string): void {\n optionalBoundedInteger(\n value,\n field,\n 1,\n AGENT_DEVICE_RPC_LIMITS.loadAroundMaxBytes,\n );\n}\n\nfunction optionalBoolean(value: unknown, field: string): void {\n if (value !== undefined && typeof value !== 'boolean') fail(field);\n}\n\nfunction optionalCursorString(value: unknown, field: string): void {\n if (\n value !== undefined &&\n (typeof value !== 'string' ||\n value.length === 0 ||\n value.length > AGENT_DEVICE_RPC_LIMITS.cursorCharacters ||\n value !== value.trim() ||\n hasAsciiControlText(value))\n ) fail(field);\n}\n\nfunction assertPreview(value: unknown, field: string): void {\n if (typeof value !== 'string' || value.length > AGENT_DEVICE_RPC_LIMITS.timelinePreviewCharacters + 1) fail(field);\n}\n\nfunction hasAsciiControlText(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) return true;\n }\n return false;\n}\n\nfunction assertBoundedInteger(value: unknown, field: string, minimum: number, maximum: number): asserts value is number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum || value > maximum) fail(field);\n}\n\nfunction optionalBoundedInteger(value: unknown, field: string, minimum: number, maximum: number): void {\n if (value !== undefined) assertBoundedInteger(value, field, minimum, maximum);\n}\n\nfunction optionalDirection(value: unknown, field: string): void {\n if (value !== undefined && value !== 'backward' && value !== 'forward') fail(field);\n}\n\nfunction optionalQueryMode(value: unknown, field: string): void {\n if (value !== undefined && value !== 'metadata-only' && value !== 'full-content' && value !== 'on-demand') fail(field);\n}\n\nfunction assertJsonBytes(value: unknown, maximum: number, field: string): void {\n if (jsonByteLength(value) > maximum) fail(field);\n}\n\nfunction jsonByteLength(value: unknown): number {\n try {\n return canonicalJsonBytes(value, {\n maxBytes: 16 * 1024 * 1024,\n maxStringBytes: 16 * 1024 * 1024,\n maxStringCodeUnits: 16 * 1024 * 1024,\n maxNodes: 200_000,\n }).byteLength;\n } catch {\n return Number.POSITIVE_INFINITY;\n }\n}\n\nfunction turnRenderLines(value: unknown): number {\n if (!Array.isArray(value)) return Number.POSITIVE_INFINITY;\n let lines = 0;\n for (const item of value) {\n const record = item as Record<string, unknown>;\n const userPreview = record.userPreview;\n if (typeof userPreview === 'string') lines += userPreview.split('\\n').length;\n if (Array.isArray(record.participantPreviews)) {\n for (const participant of record.participantPreviews) {\n const preview = (participant as Record<string, unknown>)?.preview;\n if (typeof preview === 'string') lines += preview.split('\\n').length;\n }\n }\n }\n return lines;\n}\n\nfunction isCanonicalBase64(value: string): boolean {\n return value.length % 4 === 0 && /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value);\n}\n\nfunction decodedBase64ByteLength(value: string): number {\n if (value.length === 0) return 0;\n const padding = value.endsWith('==') ? 2 : value.endsWith('=') ? 1 : 0;\n return value.length / 4 * 3 - padding;\n}\n\nfunction fail(field: string): never {\n throw new AgentDeviceRpcProtocolError(field);\n}\n","import type { ChatMessage } from '../conversation/types.js';\nimport {\n AGENT_DEVICE_RPC_LIMITS,\n AGENT_DEVICE_RPC_METHODS,\n type AgentDeviceRpcCancelRequest,\n type AgentDeviceRpcContract,\n type AgentDeviceRpcCreateRequest,\n type AgentDeviceRpcDeleteTurnRequest,\n type AgentDeviceRpcGetAttachmentChunkRequest,\n type AgentDeviceRpcGetConversationMetaRequest,\n type AgentDeviceRpcGetConversationTimelinePageRequest,\n type AgentDeviceRpcGetDefinitionsRequest,\n type AgentDeviceRpcGetMessageDetailRequest,\n type AgentDeviceRpcGetMessagePageRequest,\n type AgentDeviceRpcGetRunStatusRequest,\n type AgentDeviceRpcGetTurnDetailRequest,\n type AgentDeviceRpcListConversationsRequest,\n type AgentDeviceRpcListTurnsRequest,\n type AgentDeviceRpcLoadAroundRequest,\n type AgentDeviceRpcMethod,\n AgentDeviceRpcProtocolError,\n type AgentDeviceRpcPullAgentRunLogRequest,\n type AgentDeviceRpcRequest,\n type AgentDeviceRpcResponse,\n type AgentDeviceRpcRetryTurnRequest,\n type AgentDeviceRpcRunTurnRequest,\n type AgentDeviceRpcSendRequest,\n assertAgentDeviceRpcRequest,\n assertAgentDeviceRpcResponseCorrelation,\n parseAgentDeviceRpcMessageDetail,\n parseAgentDeviceRpcResponse,\n} from './agentDeviceRpc.js';\nimport { ATTACHMENT_UPLOAD_LIMITS, type AttachmentUploadRpcCall, createAttachmentUploadRpcClient } from './attachmentUpload.js';\nimport { createScheduledTaskRpcClient, type ScheduledTaskRpcCall } from './scheduledTaskRpc.js';\nimport type { DeviceConnectionGrant } from './types.js';\n\nexport type AgentDeviceRpcSend = (\n peerId: string,\n method: string,\n parameters: unknown,\n options?: AgentDeviceRpcTransportOptions,\n) => Promise<unknown>;\n\nexport interface AgentDeviceRpcTransportOptions {\n presentedGrant?: DeviceConnectionGrant;\n signal?: AbortSignal;\n}\n\nexport interface AgentDeviceRpcCallOptions {\n signal?: AbortSignal;\n}\n\nexport interface AgentDeviceRpcClientOptions {\n peerId: string;\n sendRpc: AgentDeviceRpcSend;\n presentedGrant?: DeviceConnectionGrant;\n /** Override only when the host's runtime needs a UUID polyfill. */\n createRequestId?: () => string;\n}\n\nexport type AgentDeviceRpcStartTurnRequest =\n | {\n kind: 'send';\n request: Omit<AgentDeviceRpcSendRequest, 'requestId' | 'turnId'> & { requestId?: string; turnId?: string };\n }\n | {\n kind: 'runTurn';\n request: Omit<AgentDeviceRpcRunTurnRequest, 'requestId' | 'turnId'> & { requestId?: string; turnId?: string };\n };\n\nexport type PreparedAgentDeviceRpcStartTurnRequest =\n | { kind: 'send'; request: AgentDeviceRpcSendRequest }\n | { kind: 'runTurn'; request: AgentDeviceRpcRunTurnRequest };\n\nexport interface AgentDeviceRpcReadAttachmentOptions extends AgentDeviceRpcCallOptions {\n /** A host policy bound; prevents a malicious peer from declaring unbounded data. */\n maxBytes: number;\n /** Whole multi-chunk operation deadline; defaults to 120 seconds. */\n deadlineMs?: number;\n}\n\nexport interface AgentDeviceRpcReadMessageDetailOptions extends AgentDeviceRpcCallOptions {\n /** Defaults to the portable 64 MiB safety ceiling and may only lower it. */\n maxBytes?: number;\n /** Whole multi-chunk operation deadline; defaults to 120 seconds. */\n deadlineMs?: number;\n}\n\n/**\n * Browser/mobile-safe typed facade. Host code supplies `sendRpc` once and no\n * longer embeds wire method strings or casts untrusted peer responses.\n */\nexport function createAgentDeviceRpcClient(options: AgentDeviceRpcClientOptions) {\n async function request<M extends AgentDeviceRpcMethod>(\n method: M,\n parameters: AgentDeviceRpcRequest<M>,\n callOptions: AgentDeviceRpcCallOptions = {},\n ): Promise<AgentDeviceRpcResponse<M>> {\n callOptions.signal?.throwIfAborted();\n assertAgentDeviceRpcRequest(method, parameters);\n const response = await options.sendRpc(\n options.peerId,\n method,\n parameters,\n { presentedGrant: options.presentedGrant, signal: callOptions.signal },\n );\n callOptions.signal?.throwIfAborted();\n const parsed = parseAgentDeviceRpcResponse(method, response);\n assertAgentDeviceRpcResponseCorrelation(method, parameters, parsed);\n return parsed;\n }\n\n async function getDefinitions(\n parameters: AgentDeviceRpcGetDefinitionsRequest = {},\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getDefinitions, parameters, callOptions);\n }\n\n async function createAgent(parameters: AgentDeviceRpcCreateRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.create, parameters, callOptions);\n }\n\n async function send(parameters: AgentDeviceRpcSendRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.send, parameters, callOptions);\n }\n\n async function runTurn(parameters: AgentDeviceRpcRunTurnRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.runTurn, parameters, callOptions);\n }\n\n function prepareStartTurn(parameters: AgentDeviceRpcStartTurnRequest): PreparedAgentDeviceRpcStartTurnRequest {\n const requestId = parameters.request.requestId ??\n (options.createRequestId ?? createAgentDeviceRpcRequestId)();\n const turnId = parameters.request.turnId ??\n (options.createRequestId ?? createAgentDeviceRpcRequestId)();\n return parameters.kind === 'send'\n ? { kind: 'send', request: { ...parameters.request, requestId, turnId } }\n : { kind: 'runTurn', request: { ...parameters.request, requestId, turnId } };\n }\n\n async function startTurn(\n parameters: PreparedAgentDeviceRpcStartTurnRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return parameters.kind === 'send'\n ? send(parameters.request, callOptions)\n : runTurn(parameters.request, callOptions);\n }\n\n async function getRunStatus(parameters: AgentDeviceRpcGetRunStatusRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.getRunStatus, parameters, callOptions);\n }\n\n async function cancel(parameters: AgentDeviceRpcCancelRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.cancel, parameters, callOptions);\n }\n\n async function deleteTurn(\n parameters: AgentDeviceRpcDeleteTurnRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.deleteTurn, parameters, callOptions);\n }\n\n async function retryTurn(\n parameters: AgentDeviceRpcRetryTurnRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.retryTurn, parameters, callOptions);\n }\n\n async function listConversations(\n parameters: AgentDeviceRpcListConversationsRequest = {},\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.listConversations, parameters, callOptions);\n }\n\n async function getConversationMeta(\n parameters: AgentDeviceRpcGetConversationMetaRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getConversationMeta, parameters, callOptions);\n }\n\n async function listTurns(parameters: AgentDeviceRpcListTurnsRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.listTurns, {\n ...parameters,\n byteBudget: parameters.byteBudget ?? AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes,\n }, callOptions);\n }\n\n async function getTurnDetail(\n parameters: AgentDeviceRpcGetTurnDetailRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getTurnDetail, {\n ...parameters,\n limit: parameters.limit ?? AGENT_DEVICE_RPC_LIMITS.turnDetailPage,\n maxBytes: parameters.maxBytes ?? AGENT_DEVICE_RPC_LIMITS.turnDetailDefaultBytes,\n }, callOptions);\n }\n\n async function getMessagePage(parameters: AgentDeviceRpcGetMessagePageRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.getMessagePage, {\n ...parameters,\n mode: parameters.mode ?? 'on-demand',\n maxBytes: parameters.maxBytes ?? AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes,\n }, callOptions);\n }\n\n async function getConversationTimelinePage(\n parameters: AgentDeviceRpcGetConversationTimelinePageRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage, {\n ...parameters,\n limit: parameters.limit ?? AGENT_DEVICE_RPC_LIMITS.timelinePage,\n maxBytes: parameters.maxBytes ?? AGENT_DEVICE_RPC_LIMITS.timelinePageDefaultBytes,\n }, callOptions);\n }\n\n async function loadAround(\n parameters: AgentDeviceRpcLoadAroundRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.loadAround, {\n ...parameters,\n maxMessages: parameters.maxMessages ?? AGENT_DEVICE_RPC_LIMITS.loadAroundMessages,\n maxBytes: parameters.maxBytes ?? AGENT_DEVICE_RPC_LIMITS.loadAroundDefaultBytes,\n }, callOptions);\n }\n\n async function getMessageDetail(\n parameters: AgentDeviceRpcGetMessageDetailRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getMessageDetail, parameters, callOptions);\n }\n\n async function readMessageDetail(\n parameters: Omit<AgentDeviceRpcGetMessageDetailRequest, 'offset'>,\n readOptions: AgentDeviceRpcReadMessageDetailOptions = {},\n ): Promise<ChatMessage | null> {\n const maxBytes = normalizeMaximumBytes(\n readOptions.maxBytes,\n AGENT_DEVICE_RPC_LIMITS.messageDetailBytes,\n );\n const bytes = await readChunks(\n async (offset, signal) => {\n const chunk = await getMessageDetail({ ...parameters, offset }, { signal });\n return chunk.found ? chunk : null;\n },\n maxBytes,\n readOptions,\n );\n if (bytes === null) return null;\n let value: unknown;\n try {\n value = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));\n } catch {\n throw new AgentDeviceRpcProtocolError('response.data');\n }\n return parseAgentDeviceRpcMessageDetail(value);\n }\n\n async function getAttachmentChunk(\n parameters: AgentDeviceRpcGetAttachmentChunkRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getAttachmentChunk, parameters, callOptions);\n }\n\n async function readAttachment(\n parameters: Omit<AgentDeviceRpcGetAttachmentChunkRequest, 'offset'>,\n readOptions: AgentDeviceRpcReadAttachmentOptions,\n ): Promise<Uint8Array | null> {\n const maxBytes = normalizeMaximumBytes(readOptions.maxBytes, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n return readChunks(\n async (offset, signal) => {\n const chunk = await getAttachmentChunk({ ...parameters, offset }, { signal });\n if (!chunk.found) return null;\n if (chunk.totalBytes > maxBytes) {\n throw new AgentDeviceRpcProtocolError('response.totalBytes');\n }\n return chunk;\n },\n maxBytes,\n readOptions,\n );\n }\n\n async function pullAgentRunLog(\n parameters: AgentDeviceRpcPullAgentRunLogRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.pullAgentRunLog, {\n ...parameters,\n maxBytes: parameters.maxBytes ?? AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes,\n }, callOptions);\n }\n\n const attachmentUpload = createAttachmentUploadRpcClient({\n call: ((method, parameters, callOptions) => request(method, parameters, callOptions)) as AttachmentUploadRpcCall,\n });\n const scheduledTasks = createScheduledTaskRpcClient({\n call: ((method, parameters, callOptions) => request(method, parameters, callOptions)) as ScheduledTaskRpcCall,\n });\n\n return {\n request,\n getDefinitions,\n createAgent,\n send,\n runTurn,\n prepareStartTurn,\n startTurn,\n getRunStatus,\n cancel,\n deleteTurn,\n retryTurn,\n listConversations,\n getConversationMeta,\n listTurns,\n getTurnDetail,\n getMessagePage,\n getConversationTimelinePage,\n loadAround,\n getMessageDetail,\n readMessageDetail,\n getAttachmentChunk,\n readAttachment,\n pullAgentRunLog,\n beginAttachmentUpload: attachmentUpload.begin,\n uploadAttachmentChunk: attachmentUpload.chunk,\n commitAttachmentUpload: attachmentUpload.commit,\n scheduledTasks,\n listScheduledTasks: scheduledTasks.list,\n getScheduledTask: scheduledTasks.get,\n createScheduledTask: scheduledTasks.create,\n updateScheduledTask: scheduledTasks.update,\n deleteScheduledTask: scheduledTasks.delete,\n previewScheduledTaskCron: scheduledTasks.cronPreview,\n };\n}\n\nexport type AgentDeviceRpcClient = ReturnType<typeof createAgentDeviceRpcClient>;\n\n/** Create a UUID request id without importing Node crypto into browser/mobile. */\nexport function createAgentDeviceRpcRequestId(): string {\n const bytes = new Uint8Array(16);\n const getRandomValues = globalThis.crypto?.getRandomValues.bind(globalThis.crypto);\n if (!getRandomValues) throw new AgentDeviceRpcProtocolError('requestIdGenerator');\n getRandomValues(bytes);\n bytes[6] = (bytes[6] & 0x0F) | 0x40;\n bytes[8] = (bytes[8] & 0x3F) | 0x80;\n const hex = [...bytes].map(byte => byte.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\ninterface ReadableChunk {\n data: string;\n offset: number;\n totalBytes: number;\n nextOffset?: number;\n}\n\nasync function readChunks(\n read: (offset: number, signal: AbortSignal) => Promise<ReadableChunk | null>,\n maxBytes: number,\n options: { signal?: AbortSignal; deadlineMs?: number },\n): Promise<Uint8Array | null> {\n const operation = createDeadlineSignal(options.signal, options.deadlineMs);\n let offset = 0;\n let expectedTotal: number | undefined;\n let result: Uint8Array | undefined;\n let chunkCount = 0;\n try {\n for (;;) {\n operation.signal.throwIfAborted();\n chunkCount += 1;\n if (chunkCount > MAX_DETAIL_CHUNKS) throw new AgentDeviceRpcProtocolError('response.chunkCount');\n const chunk = await read(offset, operation.signal);\n operation.signal.throwIfAborted();\n if (chunk === null) {\n if (offset !== 0) throw new AgentDeviceRpcProtocolError('response.found');\n return null;\n }\n if (chunk.totalBytes > maxBytes) throw new AgentDeviceRpcProtocolError('response.totalBytes');\n if (chunk.offset !== offset) throw new AgentDeviceRpcProtocolError('response.offset');\n if (expectedTotal !== undefined && chunk.totalBytes !== expectedTotal) {\n throw new AgentDeviceRpcProtocolError('response.totalBytes');\n }\n expectedTotal = chunk.totalBytes;\n result ??= new Uint8Array(expectedTotal);\n const bytes = base64ToBytes(chunk.data);\n if (offset + bytes.byteLength > expectedTotal) throw new AgentDeviceRpcProtocolError('response.data');\n result.set(bytes, offset);\n const nextOffset = offset + bytes.byteLength;\n if (chunk.nextOffset === undefined) {\n if (nextOffset !== expectedTotal) throw new AgentDeviceRpcProtocolError('response.nextOffset');\n return result;\n }\n if (bytes.byteLength === 0 || chunk.nextOffset !== nextOffset) {\n throw new AgentDeviceRpcProtocolError('response.nextOffset');\n }\n offset = chunk.nextOffset;\n }\n } finally {\n operation.dispose();\n }\n}\n\nconst DEFAULT_DETAIL_DEADLINE_MS = 120_000;\nconst MAX_DETAIL_DEADLINE_MS = 600_000;\nconst MAX_DETAIL_CHUNKS = 256;\n\nfunction createDeadlineSignal(parent: AbortSignal | undefined, requested: number | undefined): {\n signal: AbortSignal;\n dispose(): void;\n} {\n const deadlineMs = requested ?? DEFAULT_DETAIL_DEADLINE_MS;\n if (!Number.isSafeInteger(deadlineMs) || deadlineMs < 1 || deadlineMs > MAX_DETAIL_DEADLINE_MS) {\n throw new AgentDeviceRpcProtocolError('options.deadlineMs');\n }\n const controller = new AbortController();\n const abortFromParent = () => {\n controller.abort(parent?.reason);\n };\n if (parent?.aborted) abortFromParent();\n else parent?.addEventListener('abort', abortFromParent, { once: true });\n const timeout = setTimeout(() => {\n controller.abort(new Error('agent_device_rpc_detail_deadline'));\n }, deadlineMs);\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timeout);\n parent?.removeEventListener('abort', abortFromParent);\n },\n };\n}\n\nfunction normalizeMaximumBytes(value: number | undefined, ceiling: number): number {\n const result = value ?? ceiling;\n if (!Number.isSafeInteger(result) || result < 0 || result > ceiling) {\n throw new AgentDeviceRpcProtocolError('options.maxBytes');\n }\n return result;\n}\n\nfunction base64ToBytes(value: string): Uint8Array {\n const binary = atob(value);\n const result = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index);\n return result;\n}\n\n// Ensure mapped DTOs remain visible in generated declarations without forcing\n// hosts to import the contract map directly.\nexport type { AgentDeviceRpcContract };\n","import { domainSeparatedCanonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type { DeviceConnectionGrant, DeviceConnectionGrantStringScope, DeviceRelayReservationToken, MemeLoopProtocol } from './types.js';\n\nexport const DEVICE_BINDING_SIGNATURE_DOMAIN = 'memeloop-device-binding-v2';\nexport const DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN = 'memeloop-device-connection-grant-v2';\nexport const DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN = 'memeloop-device-relay-admission-v2';\nexport const DEVICE_CONNECTION_GRANT_MAX_PEERS = 256;\nexport const DEVICE_CONNECTION_GRANT_MAX_RPC_METHODS = 128;\nexport const DEVICE_CONNECTION_GRANT_MAX_RESOURCE_IDS = 256;\nexport const DEVICE_CONNECTION_GRANT_MAX_SCOPE_VALUE_LENGTH = 512;\nexport const DEVICE_CONNECTION_GRANT_MAX_TTL_MS = 10 * 60_000;\nexport const DEVICE_RELAY_RESERVATION_TOKEN_MAX_TTL_MS = 40 * 60_000;\nexport const DEVICE_GRANT_MAX_CLOCK_SKEW_MS = 30_000;\nexport const DEVICE_RELAY_RESERVATION_MAX_ADDRESSES = 64;\nexport const DEVICE_RELAY_RESERVATION_MAX_ADDRESS_LENGTH = 2_048;\n\nconst DEVICE_SIGNATURE_LIMITS = Object.freeze({\n maxDepth: 8,\n maxNodes: 2_048,\n maxStringCodeUnits: 4_096,\n maxStringBytes: 16 * 1_024,\n maxBytes: 1_048_576,\n});\n\nconst DEVICE_PROTOCOLS: ReadonlySet<string> = new Set<MemeLoopProtocol>([\n '/memeloop/orchestration/2.0.0',\n '/memeloop/pairing/2.0.0',\n '/memeloop/relay-admission/2.0.0',\n '/memeloop/rpc/2.0.0',\n '/memeloop/sync/2.0.0',\n]);\n\nexport function buildDeviceBindingMessage(input: {\n accountId: string;\n peerId: string;\n publicKeyMultibase: string;\n nonce: string;\n}): Uint8Array {\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_BINDING_SIGNATURE_DOMAIN,\n input,\n DEVICE_SIGNATURE_LIMITS,\n );\n}\n\nexport function buildDeviceConnectionGrantMessage(\n grant: Omit<DeviceConnectionGrant, 'signature'>,\n): Uint8Array {\n if (!hasCanonicalDeviceConnectionGrantClaims({ ...grant, signature: 'validation-signature' })) {\n throw new Error('invalid device connection grant claims');\n }\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN,\n grant,\n DEVICE_SIGNATURE_LIMITS,\n );\n}\n\n/** True only for the one canonical, bounded encoding accepted by v2 verifiers. */\nexport function hasCanonicalDeviceConnectionGrantClaims(\n value: unknown,\n): value is DeviceConnectionGrant {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const grant = value as Record<string, unknown>;\n return (\n hasOnlyKeys(grant, [\n 'issuer',\n 'accountId',\n 'subjectPeerId',\n 'allowedPeerIds',\n 'protocols',\n 'rpcMethodScope',\n 'conversationScope',\n 'definitionScope',\n 'issuedAt',\n 'expiresAt',\n 'signature',\n ]) &&\n grant.issuer === 'memeloop-cloud' &&\n canonicalScopeValue(grant.accountId) &&\n canonicalScopeValue(grant.subjectPeerId) &&\n canonicalStringList(grant.allowedPeerIds, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_PEERS,\n }) &&\n canonicalStringList(grant.protocols, {\n maxEntries: DEVICE_PROTOCOLS.size,\n allowedValues: DEVICE_PROTOCOLS,\n }) &&\n canonicalScope(grant.rpcMethodScope, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_RPC_METHODS,\n }) &&\n canonicalScope(grant.conversationScope, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_RESOURCE_IDS,\n }) &&\n canonicalScope(grant.definitionScope, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_RESOURCE_IDS,\n }) &&\n validLifetime(\n grant.issuedAt,\n grant.expiresAt,\n DEVICE_CONNECTION_GRANT_MAX_TTL_MS,\n ) &&\n canonicalScopeValue(grant.signature)\n );\n}\n\nfunction canonicalScopeValue(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 &&\n value.length <= DEVICE_CONNECTION_GRANT_MAX_SCOPE_VALUE_LENGTH &&\n hasPairedUtf16(value) && !value.includes(',') && !value.includes('\\n') &&\n !value.includes('\\r');\n}\n\nexport function deviceConnectionGrantAllowsProtocol(\n grant: DeviceConnectionGrant,\n protocol: MemeLoopProtocol,\n): boolean {\n return hasCanonicalDeviceConnectionGrantClaims(grant) && grant.protocols.includes(protocol);\n}\n\nexport function deviceConnectionGrantAllowsRpc(\n grant: DeviceConnectionGrant,\n input: { method: string; conversationId?: string; definitionId?: string },\n): boolean {\n if (!deviceConnectionGrantAllowsProtocol(grant, '/memeloop/rpc/2.0.0')) return false;\n if (!canonicalScopeValue(input.method)) return false;\n if (input.conversationId !== undefined && !canonicalScopeValue(input.conversationId)) return false;\n if (input.definitionId !== undefined && !canonicalScopeValue(input.definitionId)) return false;\n if (!scopeAllows(grant.rpcMethodScope, input.method)) return false;\n if (input.conversationId !== undefined && !scopeAllows(grant.conversationScope, input.conversationId)) {\n return false;\n }\n if (input.definitionId !== undefined && !scopeAllows(grant.definitionScope, input.definitionId)) {\n return false;\n }\n return true;\n}\n\nfunction scopeAllows(scope: DeviceConnectionGrantStringScope, value: string): boolean {\n return scope.mode === 'all' || (scope.mode === 'ids' && scope.ids.includes(value));\n}\n\nfunction canonicalScope(value: unknown, options: CanonicalStringListOptions): boolean {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const scope = value as Record<string, unknown>;\n if (scope.mode === 'none' || scope.mode === 'all') {\n return Object.keys(scope).length === 1;\n }\n return scope.mode === 'ids' && Object.keys(scope).length === 2 &&\n Object.hasOwn(scope, 'ids') && canonicalStringList(scope.ids, options) &&\n (scope.ids as unknown[]).length > 0;\n}\n\ninterface CanonicalStringListOptions {\n maxEntries: number;\n allowedValues?: ReadonlySet<string>;\n}\n\nfunction canonicalStringList(value: unknown, options: CanonicalStringListOptions): boolean {\n if (!Array.isArray(value) || value.length > options.maxEntries) return false;\n let previous: string | undefined;\n for (const entry of value) {\n if (\n !canonicalScopeValue(entry) ||\n (options.allowedValues && !options.allowedValues.has(entry)) ||\n (previous !== undefined && previous >= entry)\n ) return false;\n previous = entry;\n }\n return true;\n}\n\nexport function buildDeviceRelayReservationTokenMessage(\n token: Omit<DeviceRelayReservationToken, 'signature'>,\n): Uint8Array {\n if (\n !hasCanonicalDeviceRelayReservationTokenClaims({\n ...token,\n signature: 'validation-signature',\n })\n ) {\n throw new Error('invalid device relay reservation token claims');\n }\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN,\n token,\n DEVICE_SIGNATURE_LIMITS,\n );\n}\n\n/** Reject ambiguous/unbounded relay claims before signing or verification. */\nexport function hasCanonicalDeviceRelayReservationTokenClaims(\n value: unknown,\n): value is DeviceRelayReservationToken {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const token = value as Record<string, unknown>;\n return hasOnlyKeys(token, [\n 'issuer',\n 'accountId',\n 'peerId',\n 'relayMultiaddrs',\n 'bootstrapMultiaddrs',\n 'issuedAt',\n 'expiresAt',\n 'signature',\n ]) && token.issuer === 'memeloop-cloud' && canonicalScopeValue(token.accountId) &&\n canonicalScopeValue(token.peerId) && validLifetime(\n token.issuedAt,\n token.expiresAt,\n DEVICE_RELAY_RESERVATION_TOKEN_MAX_TTL_MS,\n ) &&\n canonicalAddressList(token.relayMultiaddrs, false) &&\n canonicalAddressList(token.bootstrapMultiaddrs, true) &&\n canonicalScopeValue(token.signature);\n}\n\nfunction canonicalAddressList(value: unknown, allowEmpty: boolean): boolean {\n if (!Array.isArray(value) || value.length > DEVICE_RELAY_RESERVATION_MAX_ADDRESSES) {\n return false;\n }\n if (!allowEmpty && value.length === 0) return false;\n let previous: string | undefined;\n for (const address of value) {\n if (\n typeof address !== 'string' || address.length === 0 ||\n address.length > DEVICE_RELAY_RESERVATION_MAX_ADDRESS_LENGTH ||\n address !== address.trim() || !hasPairedUtf16(address) || !address.startsWith('/') ||\n containsAsciiControlOrSpace(address) ||\n (previous !== undefined && previous >= address)\n ) return false;\n previous = address;\n }\n return true;\n}\n\nfunction validLifetime(issuedAt: unknown, expiresAt: unknown, maxTtlMs: number): boolean {\n return Number.isSafeInteger(issuedAt) && Number.isSafeInteger(expiresAt) &&\n (issuedAt as number) >= 0 && (expiresAt as number) > (issuedAt as number) &&\n (expiresAt as number) - (issuedAt as number) <= maxTtlMs;\n}\n\nfunction hasOnlyKeys(record: Record<string, unknown>, allowed: readonly string[]): boolean {\n const allowedKeys = new Set(allowed);\n return Object.keys(record).every(key => allowedKeys.has(key)) &&\n allowed.every(key => Object.hasOwn(record, key));\n}\n\nfunction hasPairedUtf16(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code >= 0xd800 && code <= 0xdbff) {\n const next = value.charCodeAt(index + 1);\n if (next < 0xdc00 || next > 0xdfff) return false;\n index += 1;\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n return false;\n }\n }\n return true;\n}\n\nfunction containsAsciiControlOrSpace(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 32 || code === 127) return true;\n }\n return false;\n}\n","import { hasCanonicalDeviceConnectionGrantClaims, hasCanonicalDeviceRelayReservationTokenClaims } from './deviceGrantMessages.js';\nimport type { CloudDeviceClient, CloudDeviceRecord, DeviceConnectionGrant, DeviceRelayReservationToken } from './types.js';\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst DEFAULT_RESPONSE_MAX_BYTES = 2 * 1024 * 1024;\nconst DEFAULT_ERROR_MAX_CHARACTERS = 4_096;\nconst DEFAULT_TOKEN_SAFETY_MARGIN_MS = 2 * 60_000;\nconst CLOUD_URL_MAX_CHARACTERS = 2_048;\nconst CLOUD_ACCESS_TOKEN_MAX_CHARACTERS = 16_384;\n\ntype Awaitable<T> = T | Promise<T>;\ntype ConnectionGrantRequest = Parameters<CloudDeviceClient['createConnectionGrant']>[0];\n\nexport type CloudDeviceFetch = (\n input: RequestInfo | URL,\n init?: RequestInit,\n) => Promise<Response>;\n\nexport type CloudDeviceAccessTokenSupplier = (\n signal: AbortSignal,\n) => Awaitable<string | undefined>;\n\nexport interface DeviceCloudTokenStorage {\n loadConnectionGrant(input: ConnectionGrantRequest): Awaitable<unknown>;\n saveConnectionGrant(\n input: ConnectionGrantRequest,\n grant: DeviceConnectionGrant,\n ): Awaitable<void>;\n loadRelayReservation(peerId: string): Awaitable<unknown>;\n saveRelayReservation(peerId: string, token: DeviceRelayReservationToken): Awaitable<void>;\n clear(): Awaitable<void>;\n}\n\nexport class MemoryDeviceCloudTokenStorage implements DeviceCloudTokenStorage {\n private readonly grants = new Map<string, DeviceConnectionGrant>();\n private readonly relayReservations = new Map<string, DeviceRelayReservationToken>();\n\n public loadConnectionGrant(input: ConnectionGrantRequest): DeviceConnectionGrant | undefined {\n return this.grants.get(connectionGrantCacheKey(input));\n }\n\n public saveConnectionGrant(\n input: ConnectionGrantRequest,\n grant: DeviceConnectionGrant,\n ): void {\n this.grants.set(connectionGrantCacheKey(input), grant);\n }\n\n public loadRelayReservation(peerId: string): DeviceRelayReservationToken | undefined {\n return this.relayReservations.get(peerId);\n }\n\n public saveRelayReservation(peerId: string, token: DeviceRelayReservationToken): void {\n this.relayReservations.set(peerId, token);\n }\n\n public clear(): void {\n this.grants.clear();\n this.relayReservations.clear();\n }\n}\n\nexport type CloudDeviceFetchErrorCode =\n | 'cloud_request_failed'\n | 'cloud_http_error'\n | 'cloud_response_invalid_json'\n | 'cloud_response_invalid_shape'\n | 'cloud_response_too_large';\n\nexport class CloudDeviceFetchError extends Error {\n public readonly code: CloudDeviceFetchErrorCode;\n public readonly status?: number;\n public readonly responseBody?: string;\n\n constructor(\n code: CloudDeviceFetchErrorCode,\n options?: { cause?: unknown; status?: number; responseBody?: string },\n ) {\n const detail = options?.status === undefined\n ? code\n : `${code}: ${options.status} ${(options.responseBody ?? '').trim()}`.trim();\n super(detail, options?.cause === undefined ? undefined : { cause: options.cause });\n this.name = 'CloudDeviceFetchError';\n this.code = code;\n this.status = options?.status;\n this.responseBody = options?.responseBody;\n }\n}\n\nexport interface CloudDeviceFetchClientOptions {\n baseUrl: string;\n fetch?: CloudDeviceFetch;\n accessToken?: string;\n getAccessToken?: CloudDeviceAccessTokenSupplier;\n credentials?: RequestCredentials;\n requestTimeoutMs?: number;\n responseMaxBytes?: number;\n errorMaxCharacters?: number;\n tokenStorage?: DeviceCloudTokenStorage;\n tokenSafetyMarginMs?: number;\n now?: () => number;\n onTokenStorageError?: (operation: 'load' | 'save', error: unknown) => void;\n}\n\n/** Browser/React Native-safe transport for the audited MemeLoop Cloud device API. */\nexport class CloudDeviceFetchClient implements CloudDeviceClient {\n public readonly baseUrl: string;\n private readonly fetchImplementation: CloudDeviceFetch;\n private readonly getAccessToken?: CloudDeviceAccessTokenSupplier;\n private readonly credentials: RequestCredentials;\n private readonly requestTimeoutMs: number;\n private readonly responseMaxBytes: number;\n private readonly errorMaxCharacters: number;\n private readonly tokenStorage: DeviceCloudTokenStorage;\n private readonly tokenSafetyMarginMs: number;\n private readonly now: () => number;\n\n constructor(private readonly options: CloudDeviceFetchClientOptions) {\n this.baseUrl = normalizeCloudDeviceBaseUrl(options.baseUrl);\n if (options.fetch) {\n this.fetchImplementation = options.fetch;\n } else if (typeof globalThis.fetch === 'function') {\n this.fetchImplementation = globalThis.fetch.bind(globalThis);\n } else {\n throw new TypeError('cloud_fetch_required');\n }\n if (options.accessToken !== undefined && options.getAccessToken !== undefined) {\n throw new TypeError('cloud_access_token_supplier_ambiguous');\n }\n if (options.accessToken !== undefined) {\n const accessToken = normalizeAccessToken(options.accessToken);\n this.getAccessToken = () => accessToken;\n } else {\n this.getAccessToken = options.getAccessToken;\n }\n this.credentials = options.credentials ?? 'omit';\n this.requestTimeoutMs = positiveFinite(\n options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n 'requestTimeoutMs',\n );\n this.responseMaxBytes = positiveFinite(\n options.responseMaxBytes ?? DEFAULT_RESPONSE_MAX_BYTES,\n 'responseMaxBytes',\n );\n this.errorMaxCharacters = positiveFinite(\n options.errorMaxCharacters ?? DEFAULT_ERROR_MAX_CHARACTERS,\n 'errorMaxCharacters',\n );\n this.tokenSafetyMarginMs = nonNegativeFinite(\n options.tokenSafetyMarginMs ?? DEFAULT_TOKEN_SAFETY_MARGIN_MS,\n 'tokenSafetyMarginMs',\n );\n this.tokenStorage = options.tokenStorage ?? new MemoryDeviceCloudTokenStorage();\n this.now = options.now ?? Date.now;\n }\n\n public async createBindingNonce(signal?: AbortSignal): Promise<{\n nonce: string;\n accountId: string;\n expiresAt: string;\n }> {\n const value = await this.request('/api/devices/binding/nonce', { method: 'POST' }, signal);\n if (\n !isRecord(value) || !nonEmptyString(value.nonce) || !nonEmptyString(value.accountId) ||\n !nonEmptyString(value.expiresAt)\n ) {\n throw invalidShape();\n }\n return { nonce: value.nonce, accountId: value.accountId, expiresAt: value.expiresAt };\n }\n\n public async registerDevice(\n input: Parameters<CloudDeviceClient['registerDevice']>[0],\n signal?: AbortSignal,\n ): Promise<{ ok: boolean; peerId: string }> {\n const value = await this.request('/api/devices/register', {\n method: 'POST',\n body: JSON.stringify({\n peerId: input.identity.peerId,\n publicKeyMultibase: input.identity.publicKeyMultibase,\n deviceName: input.identity.deviceName,\n platform: input.identity.platform,\n cloudNonce: input.cloudNonce,\n signature: input.signature,\n capabilities: input.capabilities,\n multiaddrs: input.multiaddrs,\n relayReservations: input.relayReservations,\n }),\n }, signal);\n if (!isRecord(value) || typeof value.ok !== 'boolean' || !nonEmptyString(value.peerId)) {\n throw invalidShape();\n }\n return { ok: value.ok, peerId: value.peerId };\n }\n\n public async listDevices(signal?: AbortSignal): Promise<CloudDeviceRecord[]> {\n const value = await this.request('/api/devices', { method: 'GET' }, signal);\n if (\n !isRecord(value) || !Array.isArray(value.devices) ||\n !value.devices.every(isCloudDeviceRecord)\n ) {\n throw invalidShape();\n }\n return value.devices;\n }\n\n public async getConnectionGrantPublicKey(signal?: AbortSignal): Promise<{\n issuer: 'memeloop-cloud';\n publicKeyMultibase: string;\n }> {\n const value = await this.request(\n '/api/devices/connection-grant/public-key',\n { method: 'GET' },\n signal,\n );\n if (\n !isRecord(value) || value.issuer !== 'memeloop-cloud' ||\n !nonEmptyString(value.publicKeyMultibase)\n ) {\n throw invalidShape();\n }\n return { issuer: value.issuer, publicKeyMultibase: value.publicKeyMultibase };\n }\n\n public async createConnectionGrant(\n input: ConnectionGrantRequest,\n signal?: AbortSignal,\n ): Promise<DeviceConnectionGrant> {\n if (!isCanonicalConnectionGrantRequest(input)) {\n throw new TypeError('invalid_connection_grant_scope');\n }\n const cacheInput = normalizedConnectionGrantRequest(input);\n const cached = await this.loadCachedGrant(cacheInput);\n throwIfAborted(signal);\n if (isUsableConnectionGrant(cached, cacheInput, this.now() + this.tokenSafetyMarginMs)) {\n return cached;\n }\n const value = await this.request('/api/devices/connection-grant', {\n method: 'POST',\n body: JSON.stringify(input),\n }, signal);\n if (!isUsableConnectionGrant(value, cacheInput, this.now())) throw invalidShape();\n await this.saveCachedGrant(cacheInput, value);\n return value;\n }\n\n public async createRelayReservation(\n input: { peerId: string },\n signal?: AbortSignal,\n ): Promise<DeviceRelayReservationToken> {\n const cached = await this.loadCachedRelayReservation(input.peerId);\n throwIfAborted(signal);\n if (isUsableRelayReservation(cached, input.peerId, this.now() + this.tokenSafetyMarginMs)) {\n return cached;\n }\n const value = await this.request('/api/devices/relay-reservation', {\n method: 'POST',\n body: JSON.stringify(input),\n }, signal);\n if (!isUsableRelayReservation(value, input.peerId, this.now())) throw invalidShape();\n await this.saveCachedRelayReservation(input.peerId, value);\n return value;\n }\n\n public async heartbeat(\n input: Parameters<CloudDeviceClient['heartbeat']>[0],\n signal?: AbortSignal,\n ): Promise<{ ok: boolean }> {\n const value = await this.request('/api/devices/heartbeat', {\n method: 'POST',\n body: JSON.stringify(input),\n }, signal);\n if (!isRecord(value) || typeof value.ok !== 'boolean') throw invalidShape();\n return { ok: value.ok };\n }\n\n /** Clear every grant/relay token owned by this client configuration. */\n public async clearCachedTokens(signal?: AbortSignal): Promise<void> {\n throwIfAborted(signal);\n try {\n await this.tokenStorage.clear();\n } catch (error) {\n this.options.onTokenStorageError?.('save', error);\n throw error;\n }\n throwIfAborted(signal);\n }\n\n private async request(path: string, init: RequestInit, signal?: AbortSignal): Promise<unknown> {\n const request = createRequestSignal(signal, this.requestTimeoutMs);\n try {\n throwIfAborted(request.signal);\n const accessToken = await this.getAccessToken?.(request.signal);\n throwIfAborted(request.signal);\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n if (accessToken !== undefined) {\n headers.authorization = `Bearer ${normalizeAccessToken(accessToken)}`;\n }\n let response: Response;\n try {\n response = await this.fetchImplementation(`${this.baseUrl}${path}`, {\n ...init,\n credentials: this.credentials,\n headers,\n redirect: 'error',\n signal: request.signal,\n });\n } catch (error) {\n if (request.signal.aborted) throw abortReason(request.signal);\n throw new CloudDeviceFetchError('cloud_request_failed', { cause: error });\n }\n const responseText = await readBoundedCloudResponse(\n response,\n this.responseMaxBytes,\n request.signal,\n );\n if (!response.ok) {\n const responseBody = responseText.slice(0, this.errorMaxCharacters);\n throw new CloudDeviceFetchError('cloud_http_error', {\n status: response.status,\n responseBody,\n });\n }\n try {\n return JSON.parse(responseText) as unknown;\n } catch (error) {\n throw new CloudDeviceFetchError('cloud_response_invalid_json', { cause: error });\n }\n } finally {\n request.dispose();\n }\n }\n\n private async loadCachedGrant(input: ConnectionGrantRequest): Promise<unknown> {\n try {\n return await this.tokenStorage.loadConnectionGrant(input);\n } catch (error) {\n this.options.onTokenStorageError?.('load', error);\n return undefined;\n }\n }\n\n private async saveCachedGrant(\n input: ConnectionGrantRequest,\n grant: DeviceConnectionGrant,\n ): Promise<void> {\n try {\n await this.tokenStorage.saveConnectionGrant(input, grant);\n } catch (error) {\n this.options.onTokenStorageError?.('save', error);\n }\n }\n\n private async loadCachedRelayReservation(peerId: string): Promise<unknown> {\n try {\n return await this.tokenStorage.loadRelayReservation(peerId);\n } catch (error) {\n this.options.onTokenStorageError?.('load', error);\n return undefined;\n }\n }\n\n private async saveCachedRelayReservation(\n peerId: string,\n token: DeviceRelayReservationToken,\n ): Promise<void> {\n try {\n await this.tokenStorage.saveRelayReservation(peerId, token);\n } catch (error) {\n this.options.onTokenStorageError?.('save', error);\n }\n }\n}\n\nexport function normalizeCloudDeviceBaseUrl(value: string): string {\n const baseUrl = value.trim();\n if (!baseUrl || baseUrl.length > CLOUD_URL_MAX_CHARACTERS) throw new Error('invalid_cloud_url');\n let parsed: URL;\n try {\n parsed = new URL(baseUrl);\n } catch {\n throw new Error('invalid_cloud_url');\n }\n const loopback = parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1' ||\n parsed.hostname === '[::1]';\n if (parsed.protocol !== 'https:' && !(parsed.protocol === 'http:' && loopback)) {\n throw new Error('cloud_url_requires_https');\n }\n if (\n parsed.username || parsed.password || parsed.search || parsed.hash ||\n (parsed.pathname !== '' && parsed.pathname !== '/')\n ) {\n throw new Error('invalid_cloud_url');\n }\n return parsed.origin;\n}\n\nfunction normalizeAccessToken(value: string): string {\n const accessToken = value.trim();\n if (!accessToken || accessToken.length > CLOUD_ACCESS_TOKEN_MAX_CHARACTERS) {\n throw new Error('invalid_cloud_access_token');\n }\n return accessToken;\n}\n\nfunction positiveFinite(value: number, name: string): number {\n if (!Number.isFinite(value) || value <= 0) throw new TypeError(`${name} must be positive and finite`);\n return value;\n}\n\nfunction nonNegativeFinite(value: number, name: string): number {\n if (!Number.isFinite(value) || value < 0) throw new TypeError(`${name} must be non-negative and finite`);\n return value;\n}\n\nfunction createRequestSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; dispose(): void } {\n const controller = new AbortController();\n const abortFromParent = (): void => {\n controller.abort(parent?.reason);\n };\n if (parent?.aborted) abortFromParent();\n else parent?.addEventListener('abort', abortFromParent, { once: true });\n const timeout = setTimeout(() => {\n controller.abort(new Error('cloud_request_timeout'));\n }, timeoutMs);\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timeout);\n parent?.removeEventListener('abort', abortFromParent);\n },\n };\n}\n\nasync function readBoundedCloudResponse(\n response: Response,\n maximumBytes: number,\n signal: AbortSignal,\n): Promise<string> {\n const declaredLength = Number(response.headers.get('content-length') ?? '0');\n if (Number.isFinite(declaredLength) && declaredLength > maximumBytes) {\n await response.body?.cancel('cloud_response_too_large');\n throw new CloudDeviceFetchError('cloud_response_too_large');\n }\n throwIfAborted(signal);\n if (!response.body || typeof response.body.getReader !== 'function') {\n const text = await awaitWithAbort(response.text(), signal);\n throwIfAborted(signal);\n if (new TextEncoder().encode(text).byteLength > maximumBytes) {\n throw new CloudDeviceFetchError('cloud_response_too_large');\n }\n return text;\n }\n const reader = response.body.getReader();\n const cancelReader = (): void => {\n void reader.cancel('cloud_request_aborted');\n };\n signal.addEventListener('abort', cancelReader, { once: true });\n const decoder = new TextDecoder('utf-8', { fatal: true });\n let totalBytes = 0;\n let text = '';\n try {\n for (;;) {\n throwIfAborted(signal);\n const { done, value } = await reader.read();\n if (done) break;\n totalBytes += value.byteLength;\n if (totalBytes > maximumBytes) {\n await reader.cancel('cloud_response_too_large');\n throw new CloudDeviceFetchError('cloud_response_too_large');\n }\n text += decoder.decode(value, { stream: true });\n }\n throwIfAborted(signal);\n return text + decoder.decode();\n } finally {\n signal.removeEventListener('abort', cancelReader);\n }\n}\n\nasync function awaitWithAbort<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n throwIfAborted(signal);\n let rejectAbort!: (reason: Error) => void;\n const aborted = new Promise<never>((_resolve, reject) => {\n rejectAbort = reject;\n });\n const onAbort = (): void => {\n rejectAbort(abortReason(signal));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n try {\n return await Promise.race([promise, aborted]);\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw abortReason(signal);\n}\n\nfunction abortReason(signal: AbortSignal): Error {\n return signal.reason instanceof Error ? signal.reason : new Error('cloud_request_aborted');\n}\n\nfunction invalidShape(): CloudDeviceFetchError {\n return new CloudDeviceFetchError('cloud_response_invalid_shape');\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction nonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n\nfunction stringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every(item => typeof item === 'string');\n}\n\nfunction isCloudDeviceRecord(value: unknown): value is CloudDeviceRecord {\n if (\n !isRecord(value) || !nonEmptyString(value.accountId) || !nonEmptyString(value.peerId) ||\n !nonEmptyString(value.publicKeyMultibase) || !nonEmptyString(value.deviceName) ||\n (value.platform !== 'desktop' && value.platform !== 'mobile' && value.platform !== 'cli' &&\n value.platform !== 'web') ||\n !isDeviceCapabilities(value.capabilities) ||\n !stringArray(value.multiaddrs) || !stringArray(value.relayReservations) ||\n typeof value.lastSeen !== 'number' || !Number.isFinite(value.lastSeen)\n ) {\n return false;\n }\n return value.revokedAt === undefined ||\n (typeof value.revokedAt === 'number' && Number.isFinite(value.revokedAt));\n}\n\nfunction isDeviceCapabilities(value: unknown): boolean {\n if (\n !isRecord(value) || !stringArray(value.tools) || !stringArray(value.mcpServers) ||\n typeof value.hasWiki !== 'boolean' || !stringArray(value.imChannels) ||\n !Array.isArray(value.wikis) ||\n (value.agentLoop !== undefined && typeof value.agentLoop !== 'boolean')\n ) {\n return false;\n }\n return value.wikis.every(wiki =>\n isRecord(wiki) && nonEmptyString(wiki.wikiId) &&\n (wiki.title === undefined || typeof wiki.title === 'string') &&\n (wiki.pathHint === undefined || typeof wiki.pathHint === 'string')\n );\n}\n\nfunction normalizedConnectionGrantRequest(input: ConnectionGrantRequest): ConnectionGrantRequest {\n return {\n subjectPeerId: input.subjectPeerId,\n allowedPeerIds: [...input.allowedPeerIds],\n protocols: [...input.protocols],\n rpcMethodScope: cloneScope(input.rpcMethodScope),\n conversationScope: cloneScope(input.conversationScope),\n definitionScope: cloneScope(input.definitionScope),\n };\n}\n\nfunction connectionGrantCacheKey(input: ConnectionGrantRequest): string {\n const normalized = normalizedConnectionGrantRequest(input);\n return JSON.stringify([\n normalized.subjectPeerId,\n normalized.allowedPeerIds,\n normalized.protocols,\n normalized.rpcMethodScope,\n normalized.conversationScope,\n normalized.definitionScope,\n ]);\n}\n\nfunction sameStringList(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\nfunction cloneScope<T extends ConnectionGrantRequest['rpcMethodScope']>(scope: T): T {\n return (scope.mode === 'ids' ? { mode: 'ids', ids: [...scope.ids] } : { mode: scope.mode }) as T;\n}\n\nfunction sameScope(\n left: ConnectionGrantRequest['rpcMethodScope'],\n right: ConnectionGrantRequest['rpcMethodScope'],\n): boolean {\n return left.mode === right.mode &&\n (left.mode !== 'ids' || (right.mode === 'ids' && sameStringList(left.ids, right.ids)));\n}\n\nfunction isCanonicalConnectionGrantRequest(input: ConnectionGrantRequest): boolean {\n return hasCanonicalDeviceConnectionGrantClaims({\n ...input,\n issuer: 'memeloop-cloud',\n accountId: 'validation-account',\n issuedAt: 0,\n expiresAt: 1,\n signature: 'validation-signature',\n });\n}\n\nfunction isUsableConnectionGrant(\n value: unknown,\n input: ConnectionGrantRequest,\n usableAfter: number,\n): value is DeviceConnectionGrant {\n if (!isRecord(value)) return false;\n const grant = value as unknown as DeviceConnectionGrant;\n if (!hasCanonicalDeviceConnectionGrantClaims(grant)) return false;\n return grant.issuer === 'memeloop-cloud' && grant.subjectPeerId === input.subjectPeerId &&\n nonEmptyString(grant.accountId) && sameStringList(grant.allowedPeerIds, input.allowedPeerIds) &&\n sameStringList(grant.protocols, input.protocols) &&\n sameScope(grant.rpcMethodScope, input.rpcMethodScope) &&\n sameScope(grant.conversationScope, input.conversationScope) &&\n sameScope(grant.definitionScope, input.definitionScope) &&\n typeof grant.issuedAt === 'number' && Number.isFinite(grant.issuedAt) &&\n typeof grant.expiresAt === 'number' && Number.isFinite(grant.expiresAt) &&\n grant.expiresAt > usableAfter && nonEmptyString(grant.signature);\n}\n\nfunction isUsableRelayReservation(\n value: unknown,\n peerId: string,\n usableAfter: number,\n): value is DeviceRelayReservationToken {\n if (!isRecord(value)) return false;\n const token = value as unknown as DeviceRelayReservationToken;\n return hasCanonicalDeviceRelayReservationTokenClaims(token) && token.peerId === peerId &&\n typeof value.issuedAt === 'number' && Number.isFinite(value.issuedAt) &&\n typeof value.expiresAt === 'number' && Number.isFinite(value.expiresAt) &&\n value.expiresAt > usableAfter && nonEmptyString(value.signature);\n}\n","import type { DeviceCloudCommitFence, SyncResult } from './types.js';\n\nexport type { DeviceCloudCommitFence } from './types.js';\n\nexport type DeviceCloudConnectionStatus =\n | 'not-configured'\n | 'connecting'\n | 'online'\n | 'degraded'\n | 'offline'\n | 'error';\n\nexport type DeviceCloudConnectionComponent =\n | 'authorizer'\n | 'registration'\n | 'relay'\n | 'heartbeat'\n | 'directory';\n\nexport type DeviceCloudComponentStatus = 'pending' | 'ready' | 'failed' | 'not-run';\n\nexport type DeviceCloudErrorClassification = 'offline' | 'error' | 'registration-invalid';\n\n/** A deliberately small, stable error safe to persist, render, and log. */\nexport interface DeviceCloudConnectionError {\n readonly code:\n | 'DEVICE_CLOUD_STEP_FAILED'\n | 'DEVICE_CLOUD_DISPOSE_FAILED'\n | 'DEVICE_CLOUD_OBSERVER_FAILED';\n readonly classification: DeviceCloudErrorClassification;\n readonly component?: DeviceCloudConnectionComponent;\n}\n\nexport interface DeviceCloudConnectionSnapshot {\n readonly status: DeviceCloudConnectionStatus;\n readonly generation: number;\n readonly components: Readonly<Record<DeviceCloudConnectionComponent, DeviceCloudComponentStatus>>;\n readonly lastError?: DeviceCloudConnectionError;\n readonly nextRetryAt?: number;\n}\n\nexport class DeviceCloudStaleGenerationError extends Error {\n public readonly code = 'DEVICE_CLOUD_STALE_GENERATION';\n\n constructor() {\n super('Device Cloud generation is stale');\n this.name = 'DeviceCloudStaleGenerationError';\n }\n}\n\nexport interface DeviceCloudStepResult {\n commit?: (fence: DeviceCloudCommitFence) => Promise<unknown>;\n}\n\nexport interface DeviceCloudConnectionAdapter<Configuration> {\n isConfigured(configuration: Configuration | undefined): configuration is Configuration;\n relayRequiredForOnline(configuration: Configuration): boolean;\n ensureAuthorizer(\n configuration: Configuration,\n signal: AbortSignal,\n ): Promise<DeviceCloudStepResult | undefined>;\n registerDevice(\n configuration: Configuration,\n signal: AbortSignal,\n ): Promise<DeviceCloudStepResult | undefined>;\n ensureRelay(\n configuration: Configuration,\n signal: AbortSignal,\n ): Promise<DeviceCloudStepResult | undefined>;\n heartbeat(\n configuration: Configuration,\n signal: AbortSignal,\n ): Promise<DeviceCloudStepResult | undefined>;\n syncDirectory(\n configuration: Configuration,\n signal: AbortSignal,\n ): Promise<DeviceCloudStepResult | undefined>;\n /**\n * Optional background anti-entropy hooks. The coordinator keeps one run per\n * peer and generation, retries incomplete bounded results, and aborts every\n * old-generation run before activating replacement configuration.\n */\n listBackgroundSyncPeerIds?(\n configuration: Configuration,\n signal: AbortSignal,\n ): readonly string[] | Promise<readonly string[]>;\n syncDevice?(\n configuration: Configuration,\n peerId: string,\n signal: AbortSignal,\n ): Promise<SyncResult>;\n /** Clear every generation-scoped authorizer, relay, token, trust, and address effect. */\n dispose?(configuration: Configuration, signal: AbortSignal): Promise<void>;\n classifyError?(error: unknown): DeviceCloudErrorClassification;\n}\n\nexport interface DeviceCloudConnectionCoordinatorOptions<Configuration> {\n adapter: DeviceCloudConnectionAdapter<Configuration>;\n configuration?: Configuration;\n heartbeatIntervalMs?: number;\n initialBackoffMs?: number;\n maxBackoffMs?: number;\n jitterRatio?: number;\n backgroundSyncInitialBackoffMs?: number;\n backgroundSyncMaxBackoffMs?: number;\n now?: () => number;\n random?: () => number;\n /** Async status persistence must use the fence at its final write point. */\n onStatus?: (\n snapshot: DeviceCloudConnectionSnapshot,\n fence: DeviceCloudCommitFence,\n ) => void | Promise<void>;\n logWarning?: (message: string, error: DeviceCloudConnectionError) => void | Promise<void>;\n}\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 60_000;\nconst DEFAULT_INITIAL_BACKOFF_MS = 1_000;\nconst DEFAULT_MAX_BACKOFF_MS = 60_000;\nconst DEFAULT_JITTER_RATIO = 0.2;\nconst DEFAULT_BACKGROUND_SYNC_INITIAL_BACKOFF_MS = 1_000;\nconst DEFAULT_BACKGROUND_SYNC_MAX_BACKOFF_MS = 60_000;\nconst MAX_BACKGROUND_SYNC_PEERS = 1_024;\nconst MAX_BACKGROUND_SYNC_PEER_ID_CHARACTERS = 512;\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n\nfunction emptyComponents(): Readonly<Record<DeviceCloudConnectionComponent, DeviceCloudComponentStatus>> {\n return Object.freeze({\n authorizer: 'not-run',\n registration: 'not-run',\n relay: 'not-run',\n heartbeat: 'not-run',\n directory: 'not-run',\n });\n}\n\nfunction assertPositiveFiniteDelay(value: number, name: string): void {\n if (!Number.isSafeInteger(value) || value <= 0 || value > MAX_TIMER_DELAY_MS) {\n throw new TypeError(`${name} must be a finite integer between 1 and ${MAX_TIMER_DELAY_MS}`);\n }\n}\n\nfunction normalizeBackgroundSyncPeerIds(peerIds: unknown): string[] {\n if (!Array.isArray(peerIds) || peerIds.length > MAX_BACKGROUND_SYNC_PEERS) {\n throw new TypeError('invalid_background_sync_peer_ids');\n }\n const normalized: unknown[] = [...new Set<unknown>(peerIds)];\n if (\n normalized.some(peerId =>\n typeof peerId !== 'string' || peerId.length === 0 ||\n peerId.length > MAX_BACKGROUND_SYNC_PEER_ID_CHARACTERS || peerId !== peerId.trim()\n )\n ) {\n throw new TypeError('invalid_background_sync_peer_ids');\n }\n return normalized.map(peerId => String(peerId)).sort();\n}\n\nasync function abortableDelay(delayMs: number, signal: AbortSignal): Promise<void> {\n signal.throwIfAborted();\n await new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n signal.removeEventListener('abort', onAbort);\n reject(signal.reason instanceof Error ? signal.reason : new Error('operation_aborted'));\n };\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, delayMs);\n signal.addEventListener('abort', onAbort, { once: true });\n if (signal.aborted) onAbort();\n });\n signal.throwIfAborted();\n}\n\nfunction safeError(\n code: DeviceCloudConnectionError['code'],\n classification: DeviceCloudErrorClassification,\n component?: DeviceCloudConnectionComponent,\n): DeviceCloudConnectionError {\n return Object.freeze(\n component === undefined\n ? { code, classification }\n : { code, classification, component },\n );\n}\n\nfunction freezeSnapshot(snapshot: DeviceCloudConnectionSnapshot): DeviceCloudConnectionSnapshot {\n return Object.freeze({\n ...snapshot,\n components: Object.freeze({ ...snapshot.components }),\n ...(snapshot.lastError === undefined ? {} : { lastError: Object.freeze({ ...snapshot.lastError }) }),\n });\n}\n\n/** Portable, generation-safe Cloud lifecycle shared by every MemeLoop host. */\nexport class DeviceCloudConnectionCoordinator<Configuration> {\n private configuration: Configuration | undefined;\n private desiredConfiguration: Configuration | undefined;\n private generation = 0;\n private requestedGeneration = 0;\n private transition?: Promise<void>;\n private controller = new AbortController();\n private timer?: ReturnType<typeof setTimeout>;\n private inFlight?: Promise<void>;\n private readonly backgroundSyncRuns = new Map<string, {\n generation: number;\n promise: Promise<void>;\n }>();\n private started = false;\n private generationActivated = false;\n private consecutiveFailures = 0;\n private snapshotValue: DeviceCloudConnectionSnapshot = freezeSnapshot({\n status: 'not-configured',\n generation: 0,\n components: emptyComponents(),\n });\n private readonly heartbeatIntervalMs: number;\n private readonly initialBackoffMs: number;\n private readonly maxBackoffMs: number;\n private readonly jitterRatio: number;\n private readonly backgroundSyncInitialBackoffMs: number;\n private readonly backgroundSyncMaxBackoffMs: number;\n private readonly now: () => number;\n private readonly random: () => number;\n\n constructor(private readonly options: DeviceCloudConnectionCoordinatorOptions<Configuration>) {\n this.configuration = options.configuration;\n this.desiredConfiguration = options.configuration;\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;\n this.initialBackoffMs = options.initialBackoffMs ?? DEFAULT_INITIAL_BACKOFF_MS;\n this.maxBackoffMs = options.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;\n this.jitterRatio = options.jitterRatio ?? DEFAULT_JITTER_RATIO;\n this.backgroundSyncInitialBackoffMs = options.backgroundSyncInitialBackoffMs ??\n DEFAULT_BACKGROUND_SYNC_INITIAL_BACKOFF_MS;\n this.backgroundSyncMaxBackoffMs = options.backgroundSyncMaxBackoffMs ??\n DEFAULT_BACKGROUND_SYNC_MAX_BACKOFF_MS;\n this.now = options.now ?? Date.now;\n this.random = options.random ?? Math.random;\n assertPositiveFiniteDelay(this.heartbeatIntervalMs, 'heartbeatIntervalMs');\n assertPositiveFiniteDelay(this.initialBackoffMs, 'initialBackoffMs');\n assertPositiveFiniteDelay(this.maxBackoffMs, 'maxBackoffMs');\n assertPositiveFiniteDelay(\n this.backgroundSyncInitialBackoffMs,\n 'backgroundSyncInitialBackoffMs',\n );\n assertPositiveFiniteDelay(\n this.backgroundSyncMaxBackoffMs,\n 'backgroundSyncMaxBackoffMs',\n );\n if (this.maxBackoffMs < this.initialBackoffMs) {\n throw new TypeError('maxBackoffMs must be greater than or equal to initialBackoffMs');\n }\n if (this.backgroundSyncMaxBackoffMs < this.backgroundSyncInitialBackoffMs) {\n throw new TypeError(\n 'backgroundSyncMaxBackoffMs must be greater than or equal to backgroundSyncInitialBackoffMs',\n );\n }\n if (!Number.isFinite(this.jitterRatio) || this.jitterRatio < 0 || this.jitterRatio > 1) {\n throw new TypeError('jitterRatio must be a finite number between 0 and 1');\n }\n this.resetSnapshot();\n }\n\n public get snapshot(): DeviceCloudConnectionSnapshot {\n return this.snapshotValue;\n }\n\n public async start(): Promise<void> {\n if (this.started) return this.runNow();\n this.started = true;\n const transition = this.transition;\n if (transition) {\n await transition;\n return;\n }\n await this.runCurrent();\n }\n\n public stop(): Promise<void> {\n if (\n !this.started && !this.inFlight && !this.transition && !this.generationActivated &&\n this.backgroundSyncRuns.size === 0\n ) {\n return Promise.resolve();\n }\n this.started = false;\n return this.requestTransition('device cloud coordinator stopped');\n }\n\n public setConfiguration(configuration: Configuration | undefined): Promise<void> {\n this.desiredConfiguration = configuration;\n return this.requestTransition('device cloud configuration changed');\n }\n\n public runNow(): Promise<void> {\n if (this.transition) {\n return this.started ? this.transition : this.transition.then(() => this.runCurrent());\n }\n return this.runCurrent();\n }\n\n private runCurrent(): Promise<void> {\n if (this.inFlight) return this.inFlight;\n if (!this.options.adapter.isConfigured(this.configuration)) {\n this.resetSnapshot();\n return Promise.resolve();\n }\n const generation = this.generation;\n const configuration = this.configuration;\n const signal = this.controller.signal;\n this.generationActivated = true;\n const run = this.maintain(configuration, generation, signal);\n const tracked = run.finally(() => {\n if (this.inFlight === tracked) this.inFlight = undefined;\n });\n this.inFlight = tracked;\n return tracked;\n }\n\n private requestTransition(reason: string): Promise<void> {\n this.requestedGeneration += 1;\n this.clearTimer();\n this.controller.abort(new Error(reason));\n if (!this.transition) {\n const transition = this.drainTransitions().finally(() => {\n if (this.transition === transition) this.transition = undefined;\n });\n this.transition = transition;\n }\n return this.transition;\n }\n\n private async drainTransitions(): Promise<void> {\n while (this.generation !== this.requestedGeneration) {\n const previousConfiguration = this.configuration;\n const previousRun = this.inFlight;\n await previousRun?.catch(() => undefined);\n await this.drainBackgroundSyncGeneration(this.generation);\n\n if (\n this.generationActivated &&\n this.options.adapter.isConfigured(previousConfiguration)\n ) {\n try {\n await this.options.adapter.dispose?.(previousConfiguration, new AbortController().signal);\n } catch {\n this.warn(\n 'Device Cloud generation cleanup failed',\n safeError('DEVICE_CLOUD_DISPOSE_FAILED', 'error'),\n );\n }\n }\n this.generationActivated = false;\n\n // Requests arriving while cleanup was in progress are deliberately\n // coalesced: only the newest desired configuration is ever activated.\n this.configuration = this.desiredConfiguration;\n this.generation = this.requestedGeneration;\n this.consecutiveFailures = 0;\n this.controller = new AbortController();\n if (this.inFlight === previousRun) this.inFlight = undefined;\n this.resetSnapshot();\n\n if (this.started && this.options.adapter.isConfigured(this.configuration)) {\n await this.runCurrent().catch((error: unknown) => {\n if (this.isCurrent(this.generation, this.controller.signal)) throw error;\n });\n }\n }\n }\n\n private async maintain(\n configuration: Configuration,\n generation: number,\n signal: AbortSignal,\n ): Promise<void> {\n if (!this.isCurrent(generation, signal)) return;\n await this.updateSnapshot(generation, {\n status: 'connecting',\n lastError: undefined,\n nextRetryAt: undefined,\n });\n\n let activeComponent: DeviceCloudConnectionComponent = 'authorizer';\n try {\n if (this.snapshotValue.components.authorizer !== 'ready') {\n activeComponent = 'authorizer';\n await this.runStep(activeComponent, generation, signal, () => this.options.adapter.ensureAuthorizer(configuration, signal));\n }\n if (this.snapshotValue.components.registration !== 'ready') {\n activeComponent = 'registration';\n await this.runStep(activeComponent, generation, signal, () => this.options.adapter.registerDevice(configuration, signal));\n }\n\n let relayFailure: DeviceCloudConnectionError | undefined;\n try {\n activeComponent = 'relay';\n await this.runStep(activeComponent, generation, signal, () => this.options.adapter.ensureRelay(configuration, signal));\n } catch (error) {\n const classification = this.classify(error);\n if (classification === 'registration-invalid') throw error;\n relayFailure = safeError('DEVICE_CLOUD_STEP_FAILED', classification, 'relay');\n this.warn('Device Cloud relay maintenance failed', relayFailure);\n }\n\n activeComponent = 'heartbeat';\n await this.runStep(activeComponent, generation, signal, () => this.options.adapter.heartbeat(configuration, signal));\n\n let directoryFailure: DeviceCloudConnectionError | undefined;\n try {\n activeComponent = 'directory';\n await this.runStep(activeComponent, generation, signal, () => this.options.adapter.syncDirectory(configuration, signal));\n } catch (error) {\n const classification = this.classify(error);\n if (classification === 'registration-invalid') throw error;\n directoryFailure = safeError('DEVICE_CLOUD_STEP_FAILED', classification, 'directory');\n this.warn('Device Cloud directory synchronization failed', directoryFailure);\n }\n\n if (!directoryFailure) this.startBackgroundSync(configuration, generation, signal);\n\n if (!this.isCurrent(generation, signal)) return;\n this.consecutiveFailures = 0;\n const relayRequired = this.options.adapter.relayRequiredForOnline(configuration);\n const nextRetryAt = this.retryAt(this.heartbeatIntervalMs);\n await this.updateSnapshot(generation, {\n status: directoryFailure || (relayRequired && relayFailure) ? 'degraded' : 'online',\n lastError: directoryFailure ?? relayFailure,\n nextRetryAt,\n });\n this.schedule(this.heartbeatIntervalMs, generation);\n } catch (error) {\n if (!this.isCurrent(generation, signal)) return;\n this.consecutiveFailures += 1;\n const classification = this.classify(error);\n if (classification === 'registration-invalid') {\n await this.setComponent('registration', 'not-run', generation);\n }\n const status = classification === 'error' ? 'error' : 'offline';\n const delay = this.backoffDelay();\n await this.updateSnapshot(generation, {\n status,\n lastError: safeError('DEVICE_CLOUD_STEP_FAILED', classification, activeComponent),\n nextRetryAt: this.retryAt(delay),\n });\n this.schedule(delay, generation);\n throw error;\n }\n }\n\n private async runStep(\n component: DeviceCloudConnectionComponent,\n generation: number,\n signal: AbortSignal,\n operation: () => Promise<DeviceCloudStepResult | undefined>,\n ): Promise<void> {\n if (!this.isCurrent(generation, signal)) return;\n await this.setComponent(component, 'pending', generation);\n try {\n const result = await operation();\n if (!this.isCurrent(generation, signal)) return;\n const fence = this.createCommitFence(generation, signal);\n await result?.commit?.(fence);\n if (!this.isCurrent(generation, signal)) return;\n await this.setComponent(component, 'ready', generation);\n } catch (error) {\n if (this.isCurrent(generation, signal)) await this.setComponent(component, 'failed', generation);\n throw error;\n }\n }\n\n private createCommitFence(generation: number, signal: AbortSignal): DeviceCloudCommitFence {\n return Object.freeze({\n generation,\n signal,\n isCurrent: () => this.isCurrent(generation, signal),\n throwIfStale: () => {\n if (!this.isCurrent(generation, signal)) throw new DeviceCloudStaleGenerationError();\n },\n commitSynchronous: <Result>(\n operation: () => Result extends PromiseLike<unknown> ? never : Result,\n ) => {\n if (!this.isCurrent(generation, signal)) return false;\n operation();\n return true;\n },\n });\n }\n\n private classify(error: unknown): DeviceCloudErrorClassification {\n try {\n const classification = this.options.adapter.classifyError?.(error) ?? 'offline';\n return classification === 'offline' || classification === 'error' || classification === 'registration-invalid'\n ? classification\n : 'error';\n } catch {\n return 'error';\n }\n }\n\n private backoffDelay(): number {\n const exponential = Math.min(\n this.maxBackoffMs,\n this.initialBackoffMs * 2 ** Math.max(0, this.consecutiveFailures - 1),\n );\n const random = this.random();\n if (!Number.isFinite(random) || random < 0 || random > 1) {\n throw new TypeError('random() must return a finite number between 0 and 1');\n }\n const jitter = exponential * this.jitterRatio * (random * 2 - 1);\n return Math.max(1, Math.min(MAX_TIMER_DELAY_MS, Math.round(exponential + jitter)));\n }\n\n private startBackgroundSync(\n configuration: Configuration,\n generation: number,\n signal: AbortSignal,\n ): void {\n const listBackgroundSyncPeerIds = this.options.adapter.listBackgroundSyncPeerIds?.bind(\n this.options.adapter,\n );\n const syncDevice = this.options.adapter.syncDevice?.bind(this.options.adapter);\n if (!listBackgroundSyncPeerIds || !syncDevice || !this.isCurrent(generation, signal)) return;\n void Promise.resolve()\n .then(async () => {\n const rawPeerIds = await listBackgroundSyncPeerIds(configuration, signal);\n if (!this.isCurrent(generation, signal)) return;\n const peerIds = normalizeBackgroundSyncPeerIds(rawPeerIds);\n for (const peerId of peerIds) {\n if (!this.isCurrent(generation, signal)) return;\n const existing = this.backgroundSyncRuns.get(peerId);\n if (existing?.generation === generation) continue;\n const run = this.runBackgroundSyncDevice(\n configuration,\n peerId,\n generation,\n signal,\n syncDevice,\n );\n const record = { generation, promise: run };\n this.backgroundSyncRuns.set(peerId, record);\n const release = (): void => {\n if (this.backgroundSyncRuns.get(peerId) === record) {\n this.backgroundSyncRuns.delete(peerId);\n }\n };\n void run.then(release, release);\n }\n })\n .catch((error: unknown) => {\n if (!this.isCurrent(generation, signal)) return;\n this.warn(\n 'Device Cloud background sync discovery failed',\n safeError('DEVICE_CLOUD_STEP_FAILED', this.classify(error)),\n );\n });\n }\n\n private async runBackgroundSyncDevice(\n configuration: Configuration,\n peerId: string,\n generation: number,\n signal: AbortSignal,\n syncDevice: NonNullable<DeviceCloudConnectionAdapter<Configuration>['syncDevice']>,\n ): Promise<void> {\n let attempt = 0;\n while (this.isCurrent(generation, signal)) {\n try {\n const result = await syncDevice(configuration, peerId, signal);\n if (!this.isCurrent(generation, signal) || result.complete) return;\n attempt = 0;\n } catch (error) {\n if (!this.isCurrent(generation, signal)) return;\n attempt += 1;\n this.warn(\n 'Device Cloud background sync failed',\n safeError('DEVICE_CLOUD_STEP_FAILED', this.classify(error)),\n );\n }\n const delay = this.backgroundSyncBackoffDelay(attempt);\n try {\n await abortableDelay(delay, signal);\n } catch {\n return;\n }\n }\n }\n\n private backgroundSyncBackoffDelay(attempt: number): number {\n const exponential = Math.min(\n this.backgroundSyncMaxBackoffMs,\n this.backgroundSyncInitialBackoffMs * 2 ** Math.max(0, attempt - 1),\n );\n const random = this.random();\n if (!Number.isFinite(random) || random < 0 || random > 1) {\n return this.backgroundSyncInitialBackoffMs;\n }\n const jitter = exponential * this.jitterRatio * (random * 2 - 1);\n return Math.max(1, Math.min(MAX_TIMER_DELAY_MS, Math.round(exponential + jitter)));\n }\n\n private async drainBackgroundSyncGeneration(generation: number): Promise<void> {\n const runs = [...this.backgroundSyncRuns.values()]\n .filter(run => run.generation === generation)\n .map(run => run.promise.catch(() => undefined));\n await Promise.all(runs);\n }\n\n private readNow(): number {\n const value = this.now();\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new TypeError('now() must return a finite non-negative safe integer timestamp');\n }\n return value;\n }\n\n private retryAt(delayMs: number): number {\n const now = this.readNow();\n if (now > Number.MAX_SAFE_INTEGER - delayMs) {\n throw new TypeError('now() plus delay must remain a safe integer timestamp');\n }\n return now + delayMs;\n }\n\n private schedule(delayMs: number, generation: number): void {\n if (!this.started || !this.isCurrent(generation, this.controller.signal)) return;\n this.clearTimer();\n this.timer = setTimeout(() => {\n if (!this.isCurrent(generation, this.controller.signal)) return;\n void this.runNow().catch(() => {\n this.warn(\n 'Device Cloud scheduled maintenance failed',\n safeError('DEVICE_CLOUD_STEP_FAILED', 'offline'),\n );\n });\n }, delayMs);\n }\n\n private clearTimer(): void {\n if (this.timer) clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n private isCurrent(generation: number, signal: AbortSignal): boolean {\n return generation === this.generation && generation === this.requestedGeneration && !signal.aborted;\n }\n\n private async setComponent(\n component: DeviceCloudConnectionComponent,\n status: DeviceCloudComponentStatus,\n generation: number,\n ): Promise<void> {\n if (generation !== this.generation || generation !== this.requestedGeneration) return;\n this.snapshotValue = freezeSnapshot({\n ...this.snapshotValue,\n components: { ...this.snapshotValue.components, [component]: status },\n });\n this.emit();\n }\n\n private async updateSnapshot(\n generation: number,\n update: Partial<Omit<DeviceCloudConnectionSnapshot, 'generation' | 'components'>>,\n ): Promise<void> {\n if (generation !== this.generation || generation !== this.requestedGeneration) return;\n const next: DeviceCloudConnectionSnapshot = {\n ...this.snapshotValue,\n ...update,\n ...(update.lastError === undefined ? { lastError: undefined } : {}),\n };\n this.snapshotValue = freezeSnapshot(next);\n this.emit();\n }\n\n private resetSnapshot(): void {\n this.snapshotValue = freezeSnapshot({\n status: this.options.adapter.isConfigured(this.configuration)\n ? 'offline'\n : 'not-configured',\n generation: this.generation,\n components: emptyComponents(),\n });\n this.emit();\n }\n\n /** Status observers are telemetry only: never part of a network transition. */\n private emit(): void {\n const snapshot = this.snapshotValue;\n const signal = this.controller.signal;\n void Promise.resolve()\n .then(async () => {\n if (!this.isCurrent(snapshot.generation, signal)) return;\n await this.options.onStatus?.(\n snapshot,\n this.createCommitFence(snapshot.generation, signal),\n );\n })\n .catch(() => {\n this.warn(\n 'Device Cloud status observer failed',\n safeError('DEVICE_CLOUD_OBSERVER_FAILED', 'error'),\n );\n });\n }\n\n private warn(message: string, error: DeviceCloudConnectionError): void {\n const boundedMessage = message.slice(0, 160);\n void Promise.resolve()\n .then(() => this.options.logWarning?.(boundedMessage, error))\n .catch(() => undefined);\n }\n}\n","import { domainSeparatedCanonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type { DeviceCapabilities } from './types.js';\n\n/** Domain separator for device heartbeat proof-of-possession signatures. */\nexport const DEVICE_HEARTBEAT_SIGNATURE_DOMAIN = 'memeloop-device-heartbeat-v2';\n\n/** The default amount of clock skew accepted on either side of a heartbeat timestamp. */\nexport const DEVICE_HEARTBEAT_DEFAULT_MAX_CLOCK_SKEW_MS = 60_000;\n\nexport const DEVICE_HEARTBEAT_LIMITS = Object.freeze({\n peerIdCharacters: 256,\n nonceCharacters: 256,\n signatureCharacters: 4_096,\n publicKeyCharacters: 4_096,\n capabilityItems: 128,\n capabilityItemCharacters: 512,\n wikiItems: 128,\n wikiIdCharacters: 512,\n wikiTitleCharacters: 512,\n wikiPathHintCharacters: 2_048,\n multiaddrs: 64,\n multiaddrCharacters: 2_048,\n relayReservations: 64,\n relayReservationCharacters: 4_096,\n canonicalPayloadBytes: 64 * 1_024,\n});\n\nexport interface DeviceHeartbeatUnsignedMessage {\n peerId: string;\n timestamp: number;\n nonce: string;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n}\n\nexport interface DeviceHeartbeatMessage extends DeviceHeartbeatUnsignedMessage {\n signature: string;\n}\n\nexport type DeviceHeartbeatSigner = (\n payload: Uint8Array,\n) => string | Promise<string>;\n\nexport interface DeviceHeartbeatSignOptions {\n sign: DeviceHeartbeatSigner;\n}\n\n/**\n * A host-provided portable identity verifier. Implementations MUST both derive\n * (or otherwise validate) `peerId` from `publicKeyMultibase` and verify that\n * `signature` authenticates `payload` with that public key.\n */\nexport interface DeviceHeartbeatIdentityVerifierInput {\n peerId: string;\n publicKeyMultibase: string;\n payload: Uint8Array;\n signature: string;\n}\n\nexport type DeviceHeartbeatIdentityVerifier = (\n input: DeviceHeartbeatIdentityVerifierInput,\n) => boolean | Promise<boolean>;\n\nexport interface DeviceHeartbeatNonceConsumptionInput {\n peerId: string;\n publicKeyMultibase: string;\n timestamp: number;\n nonce: string;\n}\n\n/**\n * Atomically consumes a nonce. `true` means this call consumed it; `false`\n * means it was already used or otherwise cannot be accepted.\n */\nexport type DeviceHeartbeatNonceConsumer = (\n input: DeviceHeartbeatNonceConsumptionInput,\n) => boolean | Promise<boolean>;\n\nexport interface VerifyDeviceHeartbeatOptions {\n /** Public key pinned by the registration record, never supplied by the heartbeat. */\n publicKeyMultibase: string;\n now?: number;\n maxClockSkewMs?: number;\n /** Preferred verifier name, matching the pairing identity-verifier contract. */\n verifyIdentity?: DeviceHeartbeatIdentityVerifier;\n /** Concise alias for hosts whose crypto adapter exposes `verify`. */\n verify?: DeviceHeartbeatIdentityVerifier;\n /** Required for acceptance so verification is fail-closed against replay. */\n consumeNonce?: DeviceHeartbeatNonceConsumer;\n}\n\ntype NormalizedHeartbeat = DeviceHeartbeatUnsignedMessage;\n\nconst unsignedKeys = [\n 'peerId',\n 'timestamp',\n 'nonce',\n 'capabilities',\n 'multiaddrs',\n 'relayReservations',\n] as const;\n\nconst capabilityKeys = [\n 'tools',\n 'mcpServers',\n 'hasWiki',\n 'agentLoop',\n 'imChannels',\n 'wikis',\n] as const;\n\nfunction invalid(field: string): never {\n throw new Error(`invalid device heartbeat ${field}`);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const prototype: unknown = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction assertExactKeys(\n value: Record<string, unknown>,\n allowed: readonly string[],\n location: string,\n): void {\n if (Object.keys(value).some(key => !allowed.includes(key))) invalid(location);\n}\n\nfunction boundedText(value: unknown, field: string, maxCharacters: number): string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.length > maxCharacters ||\n value !== value.trim()\n ) invalid(field);\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) invalid(field);\n }\n return value;\n}\n\nfunction normalizedStringSet(\n value: unknown,\n field: string,\n maxItems: number,\n maxCharacters: number,\n): string[] {\n if (!Array.isArray(value) || value.length > maxItems) invalid(field);\n const items = Array.from(value, item => boundedText(item, field, maxCharacters));\n if (new Set(items).size !== items.length) invalid(field);\n return items.sort(compareText);\n}\n\nfunction compareText(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction normalizeCapabilities(value: unknown): DeviceCapabilities {\n if (!isRecord(value)) invalid('capabilities');\n assertExactKeys(value, capabilityKeys, 'capabilities');\n if (typeof value.hasWiki !== 'boolean') invalid('capabilities.hasWiki');\n if (value.agentLoop !== undefined && typeof value.agentLoop !== 'boolean') {\n invalid('capabilities.agentLoop');\n }\n if (!Array.isArray(value.wikis) || value.wikis.length > DEVICE_HEARTBEAT_LIMITS.wikiItems) {\n invalid('capabilities.wikis');\n }\n\n const wikis = Array.from(value.wikis, (item) => {\n if (!isRecord(item)) invalid('capabilities.wikis');\n assertExactKeys(item, ['wikiId', 'title', 'pathHint'], 'capabilities.wikis');\n const wiki = {\n wikiId: boundedText(\n item.wikiId,\n 'capabilities.wikis.wikiId',\n DEVICE_HEARTBEAT_LIMITS.wikiIdCharacters,\n ),\n ...(item.title === undefined\n ? {}\n : {\n title: boundedText(\n item.title,\n 'capabilities.wikis.title',\n DEVICE_HEARTBEAT_LIMITS.wikiTitleCharacters,\n ),\n }),\n ...(item.pathHint === undefined\n ? {}\n : {\n pathHint: boundedText(\n item.pathHint,\n 'capabilities.wikis.pathHint',\n DEVICE_HEARTBEAT_LIMITS.wikiPathHintCharacters,\n ),\n }),\n };\n return wiki;\n });\n const wikiIds = wikis.map(wiki => wiki.wikiId);\n if (new Set(wikiIds).size !== wikiIds.length) invalid('capabilities.wikis');\n wikis.sort((left, right) =>\n compareText(left.wikiId, right.wikiId) ||\n compareText(left.title ?? '', right.title ?? '') ||\n compareText(left.pathHint ?? '', right.pathHint ?? '')\n );\n\n return {\n tools: normalizedStringSet(\n value.tools,\n 'capabilities.tools',\n DEVICE_HEARTBEAT_LIMITS.capabilityItems,\n DEVICE_HEARTBEAT_LIMITS.capabilityItemCharacters,\n ),\n mcpServers: normalizedStringSet(\n value.mcpServers,\n 'capabilities.mcpServers',\n DEVICE_HEARTBEAT_LIMITS.capabilityItems,\n DEVICE_HEARTBEAT_LIMITS.capabilityItemCharacters,\n ),\n hasWiki: value.hasWiki,\n ...(value.agentLoop === undefined ? {} : { agentLoop: value.agentLoop }),\n imChannels: normalizedStringSet(\n value.imChannels,\n 'capabilities.imChannels',\n DEVICE_HEARTBEAT_LIMITS.capabilityItems,\n DEVICE_HEARTBEAT_LIMITS.capabilityItemCharacters,\n ),\n wikis,\n };\n}\n\nfunction normalizeUnsignedMessage(value: unknown): NormalizedHeartbeat {\n if (!isRecord(value)) invalid('message');\n assertExactKeys(value, unsignedKeys, 'message');\n if (!Number.isSafeInteger(value.timestamp) || (value.timestamp as number) < 0) {\n invalid('timestamp');\n }\n return {\n peerId: boundedText(\n value.peerId,\n 'peerId',\n DEVICE_HEARTBEAT_LIMITS.peerIdCharacters,\n ),\n timestamp: value.timestamp as number,\n nonce: boundedText(\n value.nonce,\n 'nonce',\n DEVICE_HEARTBEAT_LIMITS.nonceCharacters,\n ),\n capabilities: normalizeCapabilities(value.capabilities),\n multiaddrs: normalizedStringSet(\n value.multiaddrs,\n 'multiaddrs',\n DEVICE_HEARTBEAT_LIMITS.multiaddrs,\n DEVICE_HEARTBEAT_LIMITS.multiaddrCharacters,\n ),\n relayReservations: normalizedStringSet(\n value.relayReservations,\n 'relayReservations',\n DEVICE_HEARTBEAT_LIMITS.relayReservations,\n DEVICE_HEARTBEAT_LIMITS.relayReservationCharacters,\n ),\n };\n}\n\nfunction canonicalBytes(message: NormalizedHeartbeat): Uint8Array {\n try {\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_HEARTBEAT_SIGNATURE_DOMAIN,\n message,\n {\n maxDepth: 8,\n maxNodes: 2_048,\n maxStringCodeUnits: DEVICE_HEARTBEAT_LIMITS.relayReservationCharacters,\n maxStringBytes: DEVICE_HEARTBEAT_LIMITS.relayReservationCharacters * 4,\n maxBytes: DEVICE_HEARTBEAT_LIMITS.canonicalPayloadBytes,\n },\n );\n } catch {\n invalid('payload');\n }\n}\n\n/** Build the deterministic, domain-separated bytes authenticated by a heartbeat signature. */\nexport function buildDeviceHeartbeatMessage(\n message: DeviceHeartbeatUnsignedMessage,\n): Uint8Array {\n return canonicalBytes(normalizeUnsignedMessage(message));\n}\n\n/** Validate, canonicalize, and sign a heartbeat without requiring Node APIs. */\nexport async function signDeviceHeartbeatMessage(\n message: DeviceHeartbeatUnsignedMessage,\n options: DeviceHeartbeatSignOptions | DeviceHeartbeatSigner,\n): Promise<DeviceHeartbeatMessage> {\n const normalized = normalizeUnsignedMessage(message);\n const sign = typeof options === 'function' ? options : options.sign;\n if (typeof sign !== 'function') invalid('signer');\n const signature = boundedText(\n await sign(canonicalBytes(normalized)),\n 'signature',\n DEVICE_HEARTBEAT_LIMITS.signatureCharacters,\n );\n return { ...normalized, signature };\n}\n\n/**\n * Verify identity binding, signature, freshness, and atomic nonce consumption.\n * Any malformed input, adapter error, or missing replay store fails closed.\n */\nexport async function verifyDeviceHeartbeatMessage(\n message: DeviceHeartbeatMessage,\n options: VerifyDeviceHeartbeatOptions,\n): Promise<boolean> {\n try {\n if (!isRecord(message)) return false;\n assertExactKeys(message, [...unsignedKeys, 'signature'], 'message');\n const signature = boundedText(\n message.signature,\n 'signature',\n DEVICE_HEARTBEAT_LIMITS.signatureCharacters,\n );\n const unsigned = Object.fromEntries(\n unsignedKeys.map(key => [key, message[key]]),\n ) as unknown as DeviceHeartbeatUnsignedMessage;\n const normalized = normalizeUnsignedMessage(unsigned);\n const publicKeyMultibase = boundedText(\n options.publicKeyMultibase,\n 'publicKeyMultibase',\n DEVICE_HEARTBEAT_LIMITS.publicKeyCharacters,\n );\n const now = options.now ?? Date.now();\n const maxClockSkewMs = options.maxClockSkewMs ??\n DEVICE_HEARTBEAT_DEFAULT_MAX_CLOCK_SKEW_MS;\n if (\n !Number.isSafeInteger(now) ||\n !Number.isSafeInteger(maxClockSkewMs) ||\n maxClockSkewMs < 0 ||\n Math.abs(normalized.timestamp - now) > maxClockSkewMs\n ) return false;\n\n const verifyIdentity = options.verifyIdentity ?? options.verify;\n if (typeof verifyIdentity !== 'function' || typeof options.consumeNonce !== 'function') {\n return false;\n }\n const payload = canonicalBytes(normalized);\n if (\n !await verifyIdentity({\n peerId: normalized.peerId,\n publicKeyMultibase,\n payload,\n signature,\n })\n ) return false;\n\n return await options.consumeNonce({\n peerId: normalized.peerId,\n publicKeyMultibase,\n timestamp: normalized.timestamp,\n nonce: normalized.nonce,\n });\n } catch {\n return false;\n }\n}\n","import { safeErrorMessageFromUnknown } from '../safeError.js';\n\nexport const ORCHESTRATION_ERROR_CODES = [\n 'UNSUPPORTED',\n 'FORBIDDEN',\n 'CONFLICT',\n 'STALE_EPOCH',\n 'NOT_FOUND',\n 'INVALID',\n 'EXHAUSTED',\n 'UNAVAILABLE',\n 'TIMEOUT',\n 'CANCELLED',\n 'UNKNOWN_EFFECT',\n 'WATCH_COMPACTED',\n 'INTERNAL',\n] as const;\n\nexport type OrchestrationErrorCode = typeof ORCHESTRATION_ERROR_CODES[number];\n\nexport interface OrchestrationErrorData {\n code: OrchestrationErrorCode;\n message: string;\n retryable: boolean;\n retryAfterMs?: number;\n reason?: string;\n details?: Record<string, unknown>;\n}\n\nexport class OrchestrationError extends Error {\n readonly code: OrchestrationErrorCode;\n readonly retryable: boolean;\n readonly retryAfterMs?: number;\n readonly reason?: string;\n readonly details?: Record<string, unknown>;\n\n constructor(data: OrchestrationErrorData) {\n super(data.message);\n this.name = 'OrchestrationError';\n this.code = data.code;\n this.retryable = data.retryable;\n this.retryAfterMs = data.retryAfterMs;\n this.reason = data.reason;\n this.details = data.details;\n }\n\n toJSON(): OrchestrationErrorData {\n return {\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n retryAfterMs: this.retryAfterMs,\n reason: this.reason,\n details: this.details,\n };\n }\n}\n\nexport function isOrchestrationError(error: unknown): error is OrchestrationError {\n return error instanceof OrchestrationError;\n}\n\nexport function toOrchestrationErrorData(\n error: unknown,\n fallback: Pick<OrchestrationErrorData, 'code' | 'retryable'> = {\n code: 'INTERNAL',\n retryable: false,\n },\n): OrchestrationErrorData {\n if (isOrchestrationError(error)) return error.toJSON();\n return {\n ...fallback,\n message: safeErrorMessageFromUnknown(error, { fallback: 'Orchestration request failed' }),\n };\n}\n","export type JsonFrameErrorCode =\n | 'FRAME_TOO_LARGE'\n | 'TRUNCATED_FRAME'\n | 'INVALID_UTF8'\n | 'INVALID_JSON'\n | 'IDLE_TIMEOUT'\n | 'TOTAL_TIMEOUT'\n | 'ABORTED';\n\nexport class JsonFrameError extends Error {\n public readonly code: JsonFrameErrorCode;\n\n constructor(code: JsonFrameErrorCode, message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'JsonFrameError';\n this.code = code;\n }\n}\n\nexport interface JsonFrameReaderOptions {\n maxPayloadBytes: number;\n idleTimeoutMs: number;\n totalTimeoutMs: number;\n signal?: AbortSignal;\n abort?: (error: JsonFrameError) => void | Promise<void>;\n}\n\nconst HEADER_BYTES = 4;\nconst MAX_UINT32 = 0xffff_ffff;\n\nfunction assertPositiveInteger(value: number, name: string): void {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new TypeError(`${name} must be a positive safe integer`);\n }\n}\n\nfunction validateMaxPayloadBytes(maxPayloadBytes: number): void {\n assertPositiveInteger(maxPayloadBytes, 'maxPayloadBytes');\n if (maxPayloadBytes > MAX_UINT32) {\n throw new TypeError('maxPayloadBytes must fit in an unsigned 32-bit frame length');\n }\n}\n\nexport function encodeJsonFrame(value: unknown, maxPayloadBytes = MAX_UINT32): Uint8Array {\n validateMaxPayloadBytes(maxPayloadBytes);\n let serialized: string | undefined;\n try {\n serialized = JSON.stringify(value);\n } catch (error) {\n throw new JsonFrameError('INVALID_JSON', 'JSON frame value cannot be serialized', {\n cause: error,\n });\n }\n if (serialized === undefined) {\n throw new JsonFrameError('INVALID_JSON', 'JSON frame value cannot be serialized');\n }\n const payload = new TextEncoder().encode(serialized);\n if (payload.byteLength > maxPayloadBytes) {\n throw new JsonFrameError(\n 'FRAME_TOO_LARGE',\n `JSON frame payload exceeds ${maxPayloadBytes} bytes`,\n );\n }\n const frame = new Uint8Array(HEADER_BYTES + payload.byteLength);\n new DataView(frame.buffer, frame.byteOffset, HEADER_BYTES).setUint32(0, payload.byteLength, false);\n frame.set(payload, HEADER_BYTES);\n return frame;\n}\n\nexport async function* encodeJsonFrames(\n values: AsyncIterable<unknown> | Iterable<unknown>,\n maxPayloadBytes = MAX_UINT32,\n): AsyncIterable<Uint8Array> {\n for await (const value of values) {\n yield encodeJsonFrame(value, maxPayloadBytes);\n }\n}\n\nfunction abortedError(signal?: AbortSignal): JsonFrameError {\n return new JsonFrameError('ABORTED', 'JSON frame reading was aborted', {\n cause: signal?.reason,\n });\n}\n\ninterface JsonFrameDeadline {\n at: number;\n code: 'IDLE_TIMEOUT' | 'TOTAL_TIMEOUT';\n message: string;\n}\n\n/**\n * Select the deadline that governs one iterator pull. The selection remains\n * stable for the lifetime of that pull: a delayed timer must report the first\n * deadline that was crossed, rather than whichever deadlines happen to be\n * expired when its callback runs. Total timeout wins an exact tie so a frame\n * whose idle and total budgets end together is classified deterministically.\n */\nfunction selectReadDeadline(\n idleDeadline: number,\n totalDeadline: number | undefined,\n): JsonFrameDeadline {\n if (totalDeadline !== undefined && totalDeadline <= idleDeadline) {\n return {\n at: totalDeadline,\n code: 'TOTAL_TIMEOUT',\n message: 'JSON frame total timeout expired',\n };\n }\n return {\n at: idleDeadline,\n code: 'IDLE_TIMEOUT',\n message: 'JSON frame idle timeout expired',\n };\n}\n\nasync function readNextChunk(\n iterator: AsyncIterator<Uint8Array>,\n idleDeadline: number,\n totalDeadline: number | undefined,\n signal: AbortSignal | undefined,\n): Promise<IteratorResult<Uint8Array>> {\n if (signal?.aborted) throw abortedError(signal);\n const now = Date.now();\n const deadline = selectReadDeadline(idleDeadline, totalDeadline);\n if (deadline.at <= now) {\n throw new JsonFrameError(deadline.code, deadline.message);\n }\n\n return new Promise<IteratorResult<Uint8Array>>((resolve, reject) => {\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const finish = (callback: () => void) => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n callback();\n };\n const onAbort = () => {\n finish(() => {\n reject(abortedError(signal));\n });\n };\n\n const onTimeout = () => {\n if (settled) return;\n const remainingMs = deadline.at - Date.now();\n if (remainingMs > 0) {\n // Node and browser timers may fire slightly early (and fractional\n // delays are truncated). Never turn that scheduler detail into a\n // timeout classification bug: wait until the selected absolute\n // deadline has actually elapsed.\n timer = setTimeout(onTimeout, Math.max(1, remainingMs));\n return;\n }\n finish(() => {\n reject(new JsonFrameError(deadline.code, deadline.message));\n });\n };\n\n timer = setTimeout(onTimeout, Math.max(1, deadline.at - now));\n signal?.addEventListener('abort', onAbort, { once: true });\n // Cover an abort racing between the entry check and listener attachment.\n if (signal?.aborted) {\n onAbort();\n return;\n }\n void iterator.next().then(\n (result) => {\n finish(() => {\n resolve(result);\n });\n },\n (error: unknown) => {\n finish(() => {\n reject(\n error instanceof Error ? error : new Error('JSON frame source failed', {\n cause: error,\n }),\n );\n });\n },\n );\n });\n}\n\n/**\n * Decode uint32be-length-prefixed, strict UTF-8 JSON frames from an arbitrary\n * chunked byte stream. Buffered remainder is retained so one chunk may contain\n * any number of complete or partial frames.\n */\nexport function createJsonFrameReader(\n source: AsyncIterable<Uint8Array>,\n options: JsonFrameReaderOptions,\n): AsyncIterable<unknown> {\n validateMaxPayloadBytes(options.maxPayloadBytes);\n assertPositiveInteger(options.idleTimeoutMs, 'idleTimeoutMs');\n assertPositiveInteger(options.totalTimeoutMs, 'totalTimeoutMs');\n\n return (async function* readFrames(): AsyncIterable<unknown> {\n const iterator = source[Symbol.asyncIterator]();\n const header = new Uint8Array(HEADER_BYTES);\n let headerBytes = 0;\n let payload: Uint8Array | undefined;\n let payloadBytes = 0;\n let expectedPayloadBytes: number | undefined;\n let idleDeadline = Date.now() + options.idleTimeoutMs;\n let totalDeadline: number | undefined;\n let abortCalled = false;\n let completed = false;\n\n const abortOnce = (error: JsonFrameError): void => {\n if (abortCalled) return;\n abortCalled = true;\n try {\n // Aborting is a notification/cancellation boundary, not part of error\n // delivery. A defective host abort implementation must never prevent\n // the framing error from reaching the caller.\n void Promise.resolve(options.abort?.(error)).catch(() => undefined);\n } catch {\n // A synchronous host error is intentionally isolated for the same\n // reason as a rejected abort promise.\n }\n };\n\n const decodePayload = (bytes: Uint8Array): unknown => {\n let text: string;\n try {\n text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch (error) {\n throw new JsonFrameError('INVALID_UTF8', 'JSON frame payload is not valid UTF-8', {\n cause: error,\n });\n }\n try {\n return JSON.parse(text) as unknown;\n } catch (error) {\n throw new JsonFrameError('INVALID_JSON', 'JSON frame payload is not valid JSON', {\n cause: error,\n });\n }\n };\n\n const onExternalAbort = (): void => {\n abortOnce(abortedError(options.signal));\n };\n options.signal?.addEventListener('abort', onExternalAbort, { once: true });\n if (options.signal?.aborted) onExternalAbort();\n\n try {\n for (;;) {\n const result = await readNextChunk(\n iterator,\n idleDeadline,\n totalDeadline,\n options.signal,\n );\n if (result.done) {\n if (headerBytes > 0 || expectedPayloadBytes !== undefined) {\n throw new JsonFrameError('TRUNCATED_FRAME', 'JSON frame stream ended mid-frame');\n }\n completed = true;\n return;\n }\n if (!(result.value instanceof Uint8Array)) {\n throw new TypeError('JSON frame source must yield Uint8Array chunks');\n }\n if (result.value.byteLength === 0) continue;\n const now = Date.now();\n idleDeadline = now + options.idleTimeoutMs;\n totalDeadline ??= now + options.totalTimeoutMs;\n\n // Retain at most the current source chunk and copy every frame byte\n // exactly once into the fixed header or exact-size payload allocation.\n // The source is not pulled again until this chunk is fully consumed,\n // so producers may safely reuse their buffer on the next pull while\n // byte-at-a-time input remains O(n).\n let chunkOffset = 0;\n while (chunkOffset < result.value.byteLength) {\n if (expectedPayloadBytes === undefined) {\n const headerRemaining = HEADER_BYTES - headerBytes;\n const copied = Math.min(headerRemaining, result.value.byteLength - chunkOffset);\n header.set(result.value.subarray(chunkOffset, chunkOffset + copied), headerBytes);\n headerBytes += copied;\n chunkOffset += copied;\n if (headerBytes < HEADER_BYTES) continue;\n\n expectedPayloadBytes = new DataView(\n header.buffer,\n header.byteOffset,\n HEADER_BYTES,\n ).getUint32(0, false);\n if (expectedPayloadBytes > options.maxPayloadBytes) {\n throw new JsonFrameError(\n 'FRAME_TOO_LARGE',\n `JSON frame payload exceeds ${options.maxPayloadBytes} bytes`,\n );\n }\n payload = new Uint8Array(expectedPayloadBytes);\n payloadBytes = 0;\n }\n\n const payloadRemaining = expectedPayloadBytes - payloadBytes;\n const copied = Math.min(payloadRemaining, result.value.byteLength - chunkOffset);\n if (copied > 0) {\n payload!.set(result.value.subarray(chunkOffset, chunkOffset + copied), payloadBytes);\n payloadBytes += copied;\n chunkOffset += copied;\n }\n if (payloadBytes < expectedPayloadBytes) continue;\n\n const value = decodePayload(payload!);\n headerBytes = 0;\n payload = undefined;\n payloadBytes = 0;\n expectedPayloadBytes = undefined;\n const hasRemainingChunkBytes = chunkOffset < result.value.byteLength;\n totalDeadline = undefined;\n yield value;\n if (options.signal?.aborted) throw abortedError(options.signal);\n // Consumer backpressure is neither source idleness nor time spent\n // receiving the next frame. Start both clocks only after the\n // consumer resumes and before processing coalesced remainder bytes.\n const resumedAt = Date.now();\n idleDeadline = resumedAt + options.idleTimeoutMs;\n if (hasRemainingChunkBytes) {\n totalDeadline = resumedAt + options.totalTimeoutMs;\n }\n }\n }\n } catch (error) {\n const frameError = error instanceof JsonFrameError\n ? error\n : new JsonFrameError('ABORTED', 'JSON frame source failed', { cause: error });\n abortOnce(frameError);\n throw frameError;\n } finally {\n options.signal?.removeEventListener('abort', onExternalAbort);\n if (!completed) abortOnce(abortedError(options.signal));\n // An async generator can be blocked in an uncooperative await. The\n // underlying stream abort above is the cancellation boundary; waiting\n // for iterator.return() here would let that source deadlock the caller.\n try {\n const returned = iterator.return?.();\n if (returned !== undefined) void Promise.resolve(returned).catch(() => undefined);\n } catch {\n // Iterator cleanup is best effort and must not replace a frame error.\n }\n }\n })();\n}\n","import { OrchestrationError } from '../orchestration/errors.js';\nimport type { RemoteOrchestrationRequest, RemoteOrchestrationResponse, RemoteOrchestrationTransport, RemoteOrchestrationTransportOptions } from '../orchestration/remoteClient.js';\nimport { createJsonFrameReader, encodeJsonFrames, JsonFrameError } from './jsonFrame.js';\nimport type { DeviceConnectionGrant, DeviceNetworkService, MemeLoopDuplexStream } from './types.js';\n\nexport const DEVICE_ORCHESTRATION_PROTOCOL = '/memeloop/orchestration/2.0.0' as const;\nconst DEFAULT_MAX_FRAME_BYTES = 1024 * 1024;\nconst REQUEST_IDLE_TIMEOUT_MS = 10_000;\nconst REQUEST_TOTAL_TIMEOUT_MS = 30_000;\nconst WATCH_IDLE_TIMEOUT_MS = 90_000;\nconst WATCH_BOOKMARK_INTERVAL_MS = 30_000;\n\nexport interface DeviceOrchestrationTransportOptions {\n deviceNetwork: Pick<DeviceNetworkService, 'openStream'>;\n peerId: string;\n grantProvider?: (\n peerId: string,\n signal?: AbortSignal,\n ) => DeviceConnectionGrant | undefined | Promise<DeviceConnectionGrant | undefined>;\n maxFrameBytes?: number;\n}\n\nexport interface DeviceOrchestrationStreamHandlerInput {\n remotePeerId: string;\n stream: MemeLoopDuplexStream;\n authorize?: (presentedGrant: DeviceConnectionGrant | undefined) => boolean | Promise<boolean>;\n}\n\nexport type RemoteOrchestrationHandler = {\n request(\n request: RemoteOrchestrationRequest,\n options?: RemoteOrchestrationTransportOptions,\n ): Promise<RemoteOrchestrationResponse>;\n watch(\n request: RemoteOrchestrationRequest,\n options?: RemoteOrchestrationTransportOptions,\n ): AsyncIterable<RemoteOrchestrationResponse>;\n};\n\nexport interface DeviceOrchestrationStreamHandlerOptions {\n resolveHandler: (\n remotePeerId: string,\n ) => RemoteOrchestrationHandler | Promise<RemoteOrchestrationHandler>;\n maxFrameBytes?: number;\n}\n\nexport type DeviceOrchestrationStreamHandler = (\n input: DeviceOrchestrationStreamHandlerInput,\n) => Promise<void>;\n\ninterface DeviceOrchestrationRequestEnvelope {\n type: 'memeloop-device-orchestration-request-v2';\n request: RemoteOrchestrationRequest;\n deadline?: string;\n grant?: DeviceConnectionGrant;\n}\n\nfunction orchestrationTransportError(\n code: 'CANCELLED' | 'EXHAUSTED' | 'INVALID' | 'UNAVAILABLE',\n message: string,\n): OrchestrationError {\n return new OrchestrationError({\n code,\n message,\n retryable: code === 'UNAVAILABLE',\n });\n}\n\nfunction assertFrameLimit(limit: number): void {\n if (!Number.isSafeInteger(limit) || limit < 256) {\n throw new TypeError('maxFrameBytes must be a safe integer of at least 256');\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw orchestrationTransportError('CANCELLED', 'device orchestration request was cancelled');\n }\n}\n\nasync function openAuthenticatedStream(\n options: DeviceOrchestrationTransportOptions,\n signal?: AbortSignal,\n): Promise<{\n stream: MemeLoopDuplexStream;\n grant: DeviceConnectionGrant | undefined;\n}> {\n const grant = await options.grantProvider?.(options.peerId, signal);\n return {\n stream: await options.deviceNetwork.openStream(\n options.peerId,\n DEVICE_ORCHESTRATION_PROTOCOL,\n {\n presentedGrant: grant,\n signal,\n },\n ),\n grant,\n };\n}\n\nasync function writeRequest(\n stream: MemeLoopDuplexStream,\n request: RemoteOrchestrationRequest,\n grant: DeviceConnectionGrant | undefined,\n deadline: string | undefined,\n maxFrameBytes: number,\n): Promise<void> {\n const envelope: DeviceOrchestrationRequestEnvelope = {\n type: 'memeloop-device-orchestration-request-v2',\n request,\n ...(deadline ? { deadline } : {}),\n ...(grant ? { grant } : {}),\n };\n await stream.sink(encodeJsonFrames([envelope], maxFrameBytes));\n}\n\nfunction abortStreamOnce(stream: MemeLoopDuplexStream): (error: Error) => Promise<void> {\n let aborted = false;\n return async (error) => {\n if (aborted) return;\n aborted = true;\n await stream.abort(error);\n };\n}\n\nfunction frameReader(\n stream: MemeLoopDuplexStream,\n maxFrameBytes: number,\n idleTimeoutMs: number,\n signal: AbortSignal | undefined,\n abort: (error: Error) => Promise<void>,\n): AsyncIterable<unknown> {\n return createJsonFrameReader(stream.source, {\n maxPayloadBytes: maxFrameBytes,\n idleTimeoutMs,\n totalTimeoutMs: REQUEST_TOTAL_TIMEOUT_MS,\n signal,\n abort,\n });\n}\n\nfunction mapFrameError(error: unknown): never {\n if (!(error instanceof JsonFrameError)) throw error;\n if (error.code === 'ABORTED') {\n throw orchestrationTransportError('CANCELLED', error.message);\n }\n if (error.code === 'FRAME_TOO_LARGE') {\n throw orchestrationTransportError('EXHAUSTED', error.message);\n }\n if (error.code === 'IDLE_TIMEOUT' || error.code === 'TOTAL_TIMEOUT') {\n throw orchestrationTransportError('UNAVAILABLE', error.message);\n }\n throw orchestrationTransportError('INVALID', error.message);\n}\n\n/**\n * Carry the portable resource protocol over an already authenticated and\n * encrypted device-network stream. No bearer credential crosses the link:\n * authorization is bound to the paired peer identity opening the protocol.\n */\nexport function createDeviceOrchestrationTransport(\n options: DeviceOrchestrationTransportOptions,\n): RemoteOrchestrationTransport {\n const maxFrameBytes = options.maxFrameBytes ?? DEFAULT_MAX_FRAME_BYTES;\n assertFrameLimit(maxFrameBytes);\n\n return {\n async request(request, transportOptions = {}) {\n throwIfAborted(transportOptions.signal);\n const deadline = transportOptions.deadline;\n const { stream, grant } = await openAuthenticatedStream(options, transportOptions.signal);\n const abort = abortStreamOnce(stream);\n const closeOnAbort = () => {\n void abort(orchestrationTransportError('CANCELLED', 'device orchestration request was cancelled'));\n };\n transportOptions.signal?.addEventListener('abort', closeOnAbort, {\n once: true,\n });\n try {\n await writeRequest(stream, request, grant, deadline, maxFrameBytes);\n let response: RemoteOrchestrationResponse | undefined;\n for await (\n const value of frameReader(\n stream,\n maxFrameBytes,\n REQUEST_IDLE_TIMEOUT_MS,\n transportOptions.signal,\n abort,\n )\n ) {\n if (response) {\n throw orchestrationTransportError(\n 'INVALID',\n 'device orchestration request returned multiple responses',\n );\n }\n response = value as RemoteOrchestrationResponse;\n }\n throwIfAborted(transportOptions.signal);\n if (!response) {\n throw orchestrationTransportError(\n 'UNAVAILABLE',\n 'device orchestration request returned no response',\n );\n }\n return response;\n } catch (error) {\n if (error instanceof JsonFrameError) await abort(error);\n mapFrameError(error);\n } finally {\n transportOptions.signal?.removeEventListener('abort', closeOnAbort);\n await stream.close().catch(() => undefined);\n }\n },\n async *watch(request, transportOptions = {}) {\n throwIfAborted(transportOptions.signal);\n const { stream, grant } = await openAuthenticatedStream(options, transportOptions.signal);\n const abort = abortStreamOnce(stream);\n const closeOnAbort = () => {\n void abort(orchestrationTransportError('CANCELLED', 'device orchestration watch was cancelled'));\n };\n transportOptions.signal?.addEventListener('abort', closeOnAbort, {\n once: true,\n });\n try {\n await writeRequest(\n stream,\n request,\n grant,\n transportOptions.deadline,\n maxFrameBytes,\n );\n for await (\n const value of frameReader(\n stream,\n maxFrameBytes,\n WATCH_IDLE_TIMEOUT_MS,\n transportOptions.signal,\n abort,\n )\n ) {\n throwIfAborted(transportOptions.signal);\n yield value as RemoteOrchestrationResponse;\n }\n throwIfAborted(transportOptions.signal);\n } catch (error) {\n if (error instanceof JsonFrameError) await abort(error);\n mapFrameError(error);\n } finally {\n transportOptions.signal?.removeEventListener('abort', closeOnAbort);\n await stream.close().catch(() => undefined);\n }\n },\n };\n}\n\nasync function readSingleRequest(\n stream: MemeLoopDuplexStream,\n maxFrameBytes: number,\n): Promise<DeviceOrchestrationRequestEnvelope> {\n const abort = abortStreamOnce(stream);\n let envelope: DeviceOrchestrationRequestEnvelope | undefined;\n for await (\n const value of frameReader(\n stream,\n maxFrameBytes,\n REQUEST_IDLE_TIMEOUT_MS,\n undefined,\n abort,\n )\n ) {\n if (envelope) {\n throw orchestrationTransportError(\n 'INVALID',\n 'device orchestration stream accepts exactly one request',\n );\n }\n if (\n value === null ||\n typeof value !== 'object' ||\n Array.isArray(value) ||\n (value as Record<string, unknown>).type !== 'memeloop-device-orchestration-request-v2' ||\n (value as Record<string, unknown>).request === null ||\n typeof (value as Record<string, unknown>).request !== 'object'\n ) {\n throw orchestrationTransportError(\n 'INVALID',\n 'device orchestration request envelope is invalid',\n );\n }\n envelope = value as DeviceOrchestrationRequestEnvelope;\n }\n if (!envelope) {\n throw orchestrationTransportError('INVALID', 'device orchestration request is missing');\n }\n return envelope;\n}\n\nasync function* withWatchBookmarks(\n source: AsyncIterable<RemoteOrchestrationResponse>,\n request: RemoteOrchestrationRequest,\n signal: AbortSignal,\n): AsyncIterable<RemoteOrchestrationResponse> {\n const iterator = source[Symbol.asyncIterator]();\n type WatchActivity =\n | { kind: 'value'; value: IteratorResult<RemoteOrchestrationResponse> }\n | { kind: 'error'; error: unknown }\n | { kind: 'aborted' };\n\n let activity: WatchActivity | undefined;\n let activityWaiter: ((value: WatchActivity | { kind: 'bookmark' }) => void) | undefined;\n let bookmarkTimer: ReturnType<typeof setTimeout> | undefined;\n let readInFlight = false;\n let lastResourceVersion = watchResourceVersion(request.payload.options) ?? '0';\n\n const clearBookmarkTimer = () => {\n if (bookmarkTimer !== undefined) clearTimeout(bookmarkTimer);\n bookmarkTimer = undefined;\n };\n const publishActivity = (value: WatchActivity) => {\n if (activityWaiter) {\n const resolve = activityWaiter;\n activityWaiter = undefined;\n clearBookmarkTimer();\n resolve(value);\n return;\n }\n activity = value;\n };\n const readNext = () => {\n if (readInFlight) return;\n readInFlight = true;\n void iterator.next().then(\n (value) => {\n readInFlight = false;\n publishActivity({ kind: 'value', value });\n },\n (error: unknown) => {\n readInFlight = false;\n publishActivity({ kind: 'error', error });\n },\n );\n };\n const waitForActivity = (): Promise<WatchActivity | { kind: 'bookmark' }> => {\n if (activity) {\n const value = activity;\n activity = undefined;\n return Promise.resolve(value);\n }\n if (signal.aborted) return Promise.resolve({ kind: 'aborted' });\n return new Promise((resolve) => {\n activityWaiter = resolve;\n bookmarkTimer = setTimeout(() => {\n bookmarkTimer = undefined;\n activityWaiter = undefined;\n resolve({ kind: 'bookmark' });\n }, WATCH_BOOKMARK_INTERVAL_MS);\n });\n };\n const onAbort = () => {\n publishActivity({ kind: 'aborted' });\n };\n\n signal.addEventListener('abort', onAbort, { once: true });\n readNext();\n try {\n for (;;) {\n const result = await waitForActivity();\n if (result.kind === 'aborted') return;\n if (result.kind === 'bookmark') {\n yield {\n protocol: request.protocol,\n requestId: request.requestId,\n ok: true,\n result: { type: 'BOOKMARK', resourceVersion: lastResourceVersion },\n };\n continue;\n }\n if (result.kind === 'error') throw result.error;\n if (result.value.done) return;\n const response = result.value.value;\n lastResourceVersion = response.ok\n ? watchResourceVersion(response.result) ?? lastResourceVersion\n : lastResourceVersion;\n yield response;\n readNext();\n }\n } finally {\n clearBookmarkTimer();\n activityWaiter = undefined;\n signal.removeEventListener('abort', onAbort);\n void iterator.return?.();\n }\n}\n\nfunction watchResourceVersion(value: unknown): string | undefined {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return undefined;\n const resourceVersion = (value as Record<string, unknown>).resourceVersion;\n return typeof resourceVersion === 'string' && resourceVersion.length > 0\n ? resourceVersion\n : undefined;\n}\n\n/** Bind a trusted peer identity to a policy-scoped orchestration handler. */\nexport function createDeviceOrchestrationStreamHandler(\n options: DeviceOrchestrationStreamHandlerOptions,\n): DeviceOrchestrationStreamHandler {\n const maxFrameBytes = options.maxFrameBytes ?? DEFAULT_MAX_FRAME_BYTES;\n assertFrameLimit(maxFrameBytes);\n return async ({ remotePeerId, stream, authorize }) => {\n const abort = new AbortController();\n try {\n const envelope = await readSingleRequest(stream, maxFrameBytes);\n if (authorize && !(await authorize(envelope.grant))) {\n throw orchestrationTransportError('UNAVAILABLE', 'device_not_trusted');\n }\n const request = envelope.request;\n const handler = await options.resolveHandler(remotePeerId);\n if (request.operation === 'watch') {\n await stream.sink(\n encodeJsonFrames(\n withWatchBookmarks(handler.watch(request, { signal: abort.signal }), request, abort.signal),\n maxFrameBytes,\n ),\n );\n } else {\n const response = await handler.request(request, {\n signal: stream.signal,\n deadline: envelope.deadline ?? new Date(Date.now() + REQUEST_TOTAL_TIMEOUT_MS).toISOString(),\n });\n if (stream.signal?.aborted) return;\n await stream.sink(encodeJsonFrames([response], maxFrameBytes));\n }\n } finally {\n abort.abort();\n await stream.close().catch(() => undefined);\n }\n };\n}\n","import type { DeviceConnectionGrant } from './types.js';\n\nexport const LIBP2P_SYNC_REQUEST_TYPE = 'memeloop-sync-request-v2';\nexport const LIBP2P_SYNC_RESPONSE_TYPE = 'memeloop-sync-response-v2';\n\nexport type Libp2pSyncMethod =\n | 'exchangeVersionFrontierPage'\n | 'pullMissingEvents'\n | 'pullAttachmentChunk'\n | 'pushEvents'\n | 'pushAttachmentChunk';\n\nexport interface Libp2pSyncRequest {\n type: typeof LIBP2P_SYNC_REQUEST_TYPE;\n id: string;\n method: Libp2pSyncMethod;\n params: unknown;\n grant?: DeviceConnectionGrant;\n}\n\nexport type Libp2pSyncResponse =\n | {\n type: typeof LIBP2P_SYNC_RESPONSE_TYPE;\n id: string;\n ok: true;\n result: unknown;\n }\n | {\n type: typeof LIBP2P_SYNC_RESPONSE_TYPE;\n id: string;\n ok: false;\n error: { code: string };\n };\n\nexport const MAX_SYNC_ATTACHMENT_CHUNK_BYTES = 3 * 1024 * 1024;\nexport const MAX_SYNC_ATTACHMENT_BYTES = 64 * 1024 * 1024;\n\nexport interface AttachmentChunkWire {\n dataBase64Url: string;\n byteLength: number;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n}\n\nconst syncMethods = new Set<Libp2pSyncMethod>([\n 'exchangeVersionFrontierPage',\n 'pullMissingEvents',\n 'pullAttachmentChunk',\n 'pushEvents',\n 'pushAttachmentChunk',\n]);\n\nexport function isLibp2pSyncRequest(value: unknown): value is Libp2pSyncRequest {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n hasOnlyKeys(record, ['type', 'id', 'method', 'params', 'grant']) &&\n record.type === LIBP2P_SYNC_REQUEST_TYPE &&\n typeof record.id === 'string' &&\n record.id.length > 0 && record.id.length <= 128 &&\n typeof record.method === 'string' &&\n syncMethods.has(record.method as Libp2pSyncMethod) &&\n 'params' in record\n );\n}\n\nexport function isLibp2pSyncResponse(value: unknown): value is Libp2pSyncResponse {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n if (\n record.type !== LIBP2P_SYNC_RESPONSE_TYPE || typeof record.id !== 'string' ||\n record.id.length === 0 || record.id.length > 128 || typeof record.ok !== 'boolean'\n ) return false;\n if (record.ok) return hasOnlyKeys(record, ['type', 'id', 'ok', 'result']);\n if (\n !hasOnlyKeys(record, ['type', 'id', 'ok', 'error']) ||\n record.error === null || typeof record.error !== 'object' || Array.isArray(record.error)\n ) {\n return false;\n }\n const error = record.error as Record<string, unknown>;\n return hasOnlyKeys(error, ['code']) && typeof error.code === 'string' &&\n /^[a-z][a-z\\d_]{0,63}$/u.test(error.code);\n}\n\nfunction isAttachmentChunkWire(value: unknown): value is AttachmentChunkWire {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n hasOnlyKeys(record, [\n 'dataBase64Url',\n 'byteLength',\n 'offset',\n 'totalSize',\n 'done',\n 'filename',\n 'mimeType',\n ]) &&\n typeof record.dataBase64Url === 'string' &&\n typeof record.byteLength === 'number' &&\n typeof record.offset === 'number' &&\n typeof record.totalSize === 'number' &&\n typeof record.done === 'boolean' &&\n typeof record.filename === 'string' &&\n typeof record.mimeType === 'string'\n );\n}\n\nfunction hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {\n const keys = new Set(allowed);\n return Object.keys(value).every(key => keys.has(key));\n}\n\nexport async function attachmentChunkFromWire(value: unknown): Promise<\n {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n } | null\n> {\n if (value === null) return null;\n if (\n !isAttachmentChunkWire(value) ||\n !Number.isSafeInteger(value.byteLength) || value.byteLength < 0 ||\n value.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n !Number.isSafeInteger(value.offset) || value.offset < 0 ||\n !Number.isSafeInteger(value.totalSize) || value.totalSize < 0 ||\n value.totalSize > MAX_SYNC_ATTACHMENT_BYTES ||\n value.offset + value.byteLength > value.totalSize ||\n value.done !== (value.offset + value.byteLength === value.totalSize) ||\n (!value.done && value.byteLength === 0) ||\n value.dataBase64Url.length > Math.ceil(MAX_SYNC_ATTACHMENT_CHUNK_BYTES / 3) * 4 + 4 ||\n value.filename.length > 512 || value.mimeType.length > 256\n ) {\n throw new Error('invalid_sync_attachment_chunk');\n }\n let data: Uint8Array;\n try {\n const base64 = value.dataBase64Url.replace(/-/g, '+').replace(/_/g, '/');\n const paddedBase64 = base64.padEnd(Math.ceil(base64.length / 4) * 4, '=');\n const binary = atob(paddedBase64);\n data = Uint8Array.from(binary, (character) => character.charCodeAt(0));\n } catch {\n throw new Error('invalid_sync_attachment_chunk');\n }\n if (data.byteLength !== value.byteLength) throw new Error('invalid_sync_attachment_chunk');\n return {\n data,\n offset: value.offset,\n totalSize: value.totalSize,\n done: value.done,\n filename: value.filename,\n mimeType: value.mimeType,\n };\n}\n\nexport function attachmentChunkToWire(value: {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n}): AttachmentChunkWire {\n if (\n value.data.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n !Number.isSafeInteger(value.offset) || value.offset < 0 ||\n !Number.isSafeInteger(value.totalSize) || value.totalSize < 0 ||\n value.totalSize > MAX_SYNC_ATTACHMENT_BYTES ||\n value.offset + value.data.byteLength > value.totalSize ||\n value.done !== (value.offset + value.data.byteLength === value.totalSize) ||\n (!value.done && value.data.byteLength === 0)\n ) {\n throw new Error('invalid_sync_attachment_chunk');\n }\n let binary = '';\n for (let offset = 0; offset < value.data.length; offset += 32_768) {\n binary += String.fromCharCode(...value.data.subarray(offset, offset + 32_768));\n }\n return {\n dataBase64Url: btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, ''),\n byteLength: value.data.byteLength,\n offset: value.offset,\n totalSize: value.totalSize,\n done: value.done,\n filename: value.filename,\n mimeType: value.mimeType,\n };\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport type { MessageVersionFrontier, MessageVersionFrontierCursor } from '../storage/ports.js';\nimport type { SyncIoOptions } from '../sync/chatSyncEngine.js';\nimport type { ConversationEventSyncPage, VersionRange } from '../sync/protocol.js';\nimport { createJsonFrameReader, encodeJsonFrames } from './jsonFrame.js';\nimport {\n attachmentChunkFromWire,\n attachmentChunkToWire,\n isLibp2pSyncResponse,\n LIBP2P_SYNC_REQUEST_TYPE,\n type Libp2pSyncMethod,\n type Libp2pSyncRequest,\n} from './libp2pSyncProtocol.js';\nimport type { AttachmentChunk, Device, DeviceConnectionGrant, DeviceNetworkService, DeviceSyncTransport, ExchangeVersionFrontierPageResult } from './types.js';\n\nexport interface Libp2pDeviceSyncTransportOptions {\n nodeId: string;\n deviceNetwork: Pick<DeviceNetworkService, 'listDevices' | 'openStream'>;\n grantProvider?: (peerId: string, signal?: AbortSignal) => Promise<DeviceConnectionGrant | undefined>;\n signal?: AbortSignal;\n}\n\nexport class Libp2pDeviceSyncTransport implements DeviceSyncTransport {\n public readonly nodeId: string;\n private readonly deviceNetwork: Pick<DeviceNetworkService, 'listDevices' | 'openStream'>;\n private readonly grantProvider?: (\n peerId: string,\n signal?: AbortSignal,\n ) => Promise<DeviceConnectionGrant | undefined>;\n private readonly signal?: AbortSignal;\n\n constructor(options: Libp2pDeviceSyncTransportOptions) {\n this.nodeId = options.nodeId;\n this.deviceNetwork = options.deviceNetwork;\n this.grantProvider = options.grantProvider;\n this.signal = options.signal;\n }\n\n public listPeers(): Promise<Device[]> {\n return this.deviceNetwork.listDevices();\n }\n\n public exchangeVersionFrontierPage(\n peerId: string,\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<ExchangeVersionFrontierPageResult> {\n return this.request(peerId, 'exchangeVersionFrontierPage', {\n localFrontiers,\n remoteAfter,\n includeRemotePage,\n conversationIds,\n }, options?.signal) as Promise<ExchangeVersionFrontierPageResult>;\n }\n\n public pullMissingEvents(\n peerId: string,\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage> {\n return this.request(peerId, 'pullMissingEvents', { conversationId, ranges, cursor }, options?.signal) as Promise<ConversationEventSyncPage>;\n }\n\n public async pullAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<AttachmentChunk | null> {\n const result = await this.request(\n peerId,\n 'pullAttachmentChunk',\n { conversationId, contentHash, offset, maxBytes },\n options?.signal,\n );\n return attachmentChunkFromWire(result);\n }\n\n public async pushEvents(\n peerId: string,\n events: ConversationEvent[],\n options?: SyncIoOptions,\n ): Promise<void> {\n await this.request(peerId, 'pushEvents', { events }, options?.signal);\n }\n\n public async pushAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void> {\n await this.request(peerId, 'pushAttachmentChunk', {\n conversationId,\n contentHash,\n chunk: attachmentChunkToWire(chunk),\n }, options?.signal);\n }\n\n private async request(\n peerId: string,\n method: Libp2pSyncMethod,\n parameters: unknown,\n operationSignal?: AbortSignal,\n ): Promise<unknown> {\n const signal = operationSignal ?? this.signal;\n const grant = await this.grantProvider?.(peerId, signal);\n const stream = await this.deviceNetwork.openStream(peerId, '/memeloop/sync/2.0.0', {\n presentedGrant: grant,\n signal,\n });\n let aborted = false;\n const abort = async (error: Error): Promise<void> => {\n if (aborted) return;\n aborted = true;\n await stream.abort(error);\n };\n const request: Libp2pSyncRequest = {\n type: LIBP2P_SYNC_REQUEST_TYPE,\n id: crypto.randomUUID(),\n method,\n params: parameters,\n grant,\n };\n try {\n await stream.sink(encodeJsonFrames([request], 16 * 1024 * 1024));\n let response: unknown;\n for await (\n const value of createJsonFrameReader(stream.source, {\n maxPayloadBytes: 16 * 1024 * 1024,\n idleTimeoutMs: 15_000,\n totalTimeoutMs: 120_000,\n signal,\n abort,\n })\n ) {\n if (response !== undefined) throw new Error('sync_response_multiple');\n response = value;\n }\n if (!isLibp2pSyncResponse(response)) throw new Error('invalid_sync_response');\n if (response.id !== request.id) throw new Error('sync_response_id_mismatch');\n if (!response.ok) throw new Error(response.error.code);\n return response.result;\n } catch (error) {\n await abort(error instanceof Error ? error : new Error('sync_transport_failed'));\n if (signal?.aborted) signal.throwIfAborted();\n throw error;\n } finally {\n await stream.close().catch(() => undefined);\n }\n }\n}\n","import { hasCanonicalDeviceConnectionGrantClaims } from './deviceGrantMessages.js';\nimport type { DeviceConnectionGrant } from './types.js';\n\nexport const LIBP2P_RPC_REQUEST_TYPE = 'memeloop-rpc-request-v2';\nexport const LIBP2P_RPC_RESPONSE_TYPE = 'memeloop-rpc-response-v2';\n\nexport interface Libp2pRpcRequest {\n type: typeof LIBP2P_RPC_REQUEST_TYPE;\n id: string;\n method: string;\n params: unknown;\n grant?: DeviceConnectionGrant;\n}\n\nexport type Libp2pRpcResponse =\n | {\n type: typeof LIBP2P_RPC_RESPONSE_TYPE;\n id: string;\n ok: true;\n result: unknown;\n }\n | {\n type: typeof LIBP2P_RPC_RESPONSE_TYPE;\n id: string;\n ok: false;\n error: { code: string };\n };\n\nconst MAX_RPC_ID_LENGTH = 128;\nconst MAX_RPC_METHOD_LENGTH = 256;\nconst RPC_ERROR_CODE_PATTERN = /^[a-z][a-z\\d_]{0,63}$/u;\n\nexport function isLibp2pRpcRequest(value: unknown): value is Libp2pRpcRequest {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n hasOnlyKeys(record, ['type', 'id', 'method', 'params', 'grant']) &&\n record.type === LIBP2P_RPC_REQUEST_TYPE &&\n typeof record.id === 'string' &&\n record.id.length > 0 && record.id.length <= MAX_RPC_ID_LENGTH &&\n typeof record.method === 'string' &&\n record.method.length > 0 && record.method.length <= MAX_RPC_METHOD_LENGTH &&\n 'params' in record &&\n (record.grant === undefined || hasCanonicalDeviceConnectionGrantClaims(record.grant))\n );\n}\n\nexport function isLibp2pRpcResponse(value: unknown): value is Libp2pRpcResponse {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n if (\n record.type !== LIBP2P_RPC_RESPONSE_TYPE || typeof record.id !== 'string' ||\n record.id.length === 0 || record.id.length > MAX_RPC_ID_LENGTH ||\n typeof record.ok !== 'boolean'\n ) return false;\n if (record.ok) return hasOnlyKeys(record, ['type', 'id', 'ok', 'result']);\n if (\n !hasOnlyKeys(record, ['type', 'id', 'ok', 'error']) ||\n record.error === null || typeof record.error !== 'object' || Array.isArray(record.error)\n ) return false;\n const error = record.error as Record<string, unknown>;\n return hasOnlyKeys(error, ['code']) && typeof error.code === 'string' &&\n RPC_ERROR_CODE_PATTERN.test(error.code);\n}\n\nfunction hasOnlyKeys(record: Record<string, unknown>, allowed: readonly string[]): boolean {\n const allowedKeys = new Set(allowed);\n return Object.keys(record).every(key => allowedKeys.has(key));\n}\n","import type { DeviceAuthorizer, MemeLoopProtocol, TrustedDeviceRecord } from './types.js';\n\nexport interface LocalTrustDeviceAuthorizerOptions {\n trustedDevices?: Iterable<TrustedDeviceRecord>;\n getTrustedDevice?: (peerId: string) => TrustedDeviceRecord | undefined;\n allowPairingProtocol?: boolean;\n}\n\nconst PAIRING_PROTOCOL: MemeLoopProtocol = '/memeloop/pairing/2.0.0';\n\nexport class LocalTrustDeviceAuthorizer implements DeviceAuthorizer {\n private readonly trustedDevices = new Map<string, TrustedDeviceRecord>();\n private readonly allowPairingProtocol: boolean;\n\n constructor(private readonly options: LocalTrustDeviceAuthorizerOptions = {}) {\n this.allowPairingProtocol = options.allowPairingProtocol ?? true;\n for (const record of options.trustedDevices ?? []) {\n this.trustedDevices.set(record.peerId, record);\n }\n }\n\n public setTrustedDevice(record: TrustedDeviceRecord): void {\n this.trustedDevices.set(record.peerId, record);\n }\n\n public removeTrustedDevice(peerId: string): void {\n this.trustedDevices.delete(peerId);\n }\n\n public async canOpenProtocol(input: {\n remotePeerId: string;\n protocol: MemeLoopProtocol;\n }): Promise<boolean> {\n const record = this.options.getTrustedDevice?.(input.remotePeerId) ?? this.trustedDevices.get(input.remotePeerId);\n if (record?.revokedAt !== undefined) return false;\n if (input.protocol === PAIRING_PROTOCOL) return this.allowPairingProtocol;\n // Cloud directory entries are discovery metadata, not local trust. Only\n // an explicit local pairing may authorize business protocols here;\n // cloud-account peers must be evaluated by CloudDeviceAuthorizer with a\n // current signed grant.\n return record?.trustMode === 'local-pairing';\n }\n}\n","import type { DeviceAuthorizer, DeviceCloudCommitFence } from './types.js';\n\n/**\n * Stable authorizer identity for long-lived network runtimes.\n *\n * Active-generation replacements are fenced. Reset is intentionally a\n * separate operation for the coordinator's serialized disposal phase, where\n * the old generation is already aborted and no active-generation fence can be\n * current.\n */\nexport class MutableDeviceAuthorizer implements DeviceAuthorizer {\n private delegate: DeviceAuthorizer;\n\n constructor(private readonly fallbackDelegate: DeviceAuthorizer) {\n this.delegate = fallbackDelegate;\n }\n\n /** Atomically install a delegate only while its Cloud generation is current. */\n public setDelegate(delegate: DeviceAuthorizer, fence: DeviceCloudCommitFence): boolean {\n return fence.commitSynchronous(() => {\n this.delegate = delegate;\n });\n }\n\n /** Restore the fail-closed/local-only delegate during serialized disposal. */\n public resetDelegate(signal: AbortSignal): void {\n signal.throwIfAborted();\n this.delegate = this.fallbackDelegate;\n signal.throwIfAborted();\n }\n\n public canOpenProtocol(input: Parameters<DeviceAuthorizer['canOpenProtocol']>[0]): Promise<boolean> {\n // Capture one delegate per authorization call. A generation switch cannot\n // split a single decision across two verification policies.\n const delegate = this.delegate;\n return delegate.canOpenProtocol(input);\n }\n}\n","import { canonicalJsonString, domainSeparatedCanonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type { Device } from './types.js';\n\nexport const DEVICE_PAIRING_INVITE_PROTOCOL = 'memeloop-device-pairing-v2';\nexport const DEVICE_PAIRING_INVITE_TTL_MS = 5 * 60_000;\nexport const DEVICE_PAIRING_INVITE_MAX_CLOCK_SKEW_MS = 30_000;\nconst MAX_INVITE_LENGTH = 16 * 1024;\nconst MAX_ADDRESSES = 8;\nconst PAIRING_CANONICAL_LIMITS = Object.freeze({\n maxDepth: 4,\n maxNodes: 64,\n maxStringCodeUnits: 4_096,\n maxStringBytes: 16 * 1_024,\n maxBytes: MAX_INVITE_LENGTH,\n});\n\nexport interface DevicePairingInvite {\n protocol: typeof DEVICE_PAIRING_INVITE_PROTOCOL;\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n multiaddrs: string[];\n createdAt: number;\n expiresAt: number;\n signature: string;\n}\n\nexport type DevicePairingInviteUnsignedPayload = Omit<DevicePairingInvite, 'signature'>;\n\nexport interface DevicePairingInviteIdentityVerifierInput {\n invite: DevicePairingInvite;\n payload: Uint8Array;\n}\n\nexport type DevicePairingInviteIdentityVerifier = (\n input: DevicePairingInviteIdentityVerifierInput,\n) => boolean | Promise<boolean>;\n\nexport interface CreateDevicePairingInviteOptions {\n now?: number;\n ttlMs?: number;\n sign(payload: Uint8Array): Promise<string>;\n}\n\nexport interface ParseDevicePairingInviteOptions {\n now?: number;\n /** Must bind publicKeyMultibase -> peerId and verify signature over payload. */\n verifyIdentity: DevicePairingInviteIdentityVerifier;\n}\n\nfunction requireText(value: string, name: string, maxLength: number): string {\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > maxLength) {\n throw new Error(`invalid device pairing invite ${name}`);\n }\n return trimmed;\n}\n\nfunction validatePeerBoundAddress(address: string, peerId: string): boolean {\n if (\n address.length === 0 || address.length > 2_048 || address !== address.trim() ||\n !address.startsWith('/') || address.endsWith('/') || address.includes('//') ||\n containsAsciiControlOrSpace(address)\n ) return false;\n const parts = address.split('/');\n const peerIndexes: number[] = [];\n const circuitIndexes: number[] = [];\n for (let index = 1; index < parts.length; index += 1) {\n if (!parts[index]) return false;\n if (parts[index] === 'p2p-circuit') circuitIndexes.push(index);\n if (parts[index] !== 'p2p') continue;\n const peerId = parts[index + 1];\n if (!peerId) return false;\n peerIndexes.push(index);\n index += 1;\n }\n const destinationIndex = peerIndexes.at(-1);\n if (destinationIndex !== parts.length - 2 || parts[destinationIndex + 1] !== peerId) {\n return false;\n }\n if (circuitIndexes.length === 0) return peerIndexes.length === 1;\n if (circuitIndexes.length !== 1 || peerIndexes.length !== 2) return false;\n return peerIndexes[0] < circuitIndexes[0] && circuitIndexes[0] < destinationIndex;\n}\n\nfunction containsAsciiControlOrSpace(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 32 || code === 127) return true;\n }\n return false;\n}\n\nfunction validateAddresses(addresses: readonly string[], peerId: string): string[] {\n const unique = [...new Set(addresses.map((address) => address.trim()))].filter(Boolean);\n if (\n unique.length === 0 ||\n unique.length > MAX_ADDRESSES ||\n unique.some(address => !validatePeerBoundAddress(address, peerId))\n ) {\n throw new Error('device pairing invite requires structurally valid PeerId-bound multiaddrs');\n }\n return unique;\n}\n\nfunction validateLifetime(createdAt: number, expiresAt: number, now: number): void {\n if (\n !Number.isSafeInteger(now) || now < 0 ||\n !Number.isSafeInteger(createdAt) ||\n !Number.isSafeInteger(expiresAt) ||\n createdAt < 0 ||\n expiresAt <= createdAt ||\n expiresAt - createdAt > DEVICE_PAIRING_INVITE_TTL_MS\n ) {\n throw new Error('invalid device pairing invite lifetime');\n }\n if (createdAt > now + DEVICE_PAIRING_INVITE_MAX_CLOCK_SKEW_MS) {\n throw new Error('device pairing invite is from the future');\n }\n if (expiresAt <= now) throw new Error('device pairing invite has expired');\n}\n\nfunction unsignedPayload(invite: DevicePairingInviteUnsignedPayload): DevicePairingInviteUnsignedPayload {\n const peerId = requireText(invite.peerId, 'peerId', 256);\n return {\n protocol: DEVICE_PAIRING_INVITE_PROTOCOL,\n peerId,\n publicKeyMultibase: requireText(invite.publicKeyMultibase, 'publicKeyMultibase', 4096),\n deviceName: requireText(invite.deviceName, 'deviceName', 256),\n multiaddrs: [...validateAddresses(invite.multiaddrs, peerId)].sort(),\n createdAt: invite.createdAt,\n expiresAt: invite.expiresAt,\n };\n}\n\nexport function canonicalDevicePairingInviteBytes(\n invite: DevicePairingInviteUnsignedPayload,\n): Uint8Array {\n const payload = unsignedPayload(invite);\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_PAIRING_INVITE_PROTOCOL,\n payload,\n PAIRING_CANONICAL_LIMITS,\n );\n}\n\nexport async function createDevicePairingInvite(\n device: Pick<Device, 'peerId' | 'displayName' | 'multiaddrs'> & {\n publicKeyMultibase: string;\n },\n options: CreateDevicePairingInviteOptions,\n): Promise<DevicePairingInvite> {\n const createdAt = options.now ?? Date.now();\n const ttlMs = options.ttlMs ?? DEVICE_PAIRING_INVITE_TTL_MS;\n if (!Number.isSafeInteger(createdAt) || !Number.isSafeInteger(ttlMs) || ttlMs <= 0) {\n throw new Error('invalid device pairing invite lifetime');\n }\n const payload = unsignedPayload({\n protocol: DEVICE_PAIRING_INVITE_PROTOCOL,\n peerId: device.peerId,\n publicKeyMultibase: device.publicKeyMultibase,\n deviceName: device.displayName,\n multiaddrs: device.multiaddrs ?? [],\n createdAt,\n expiresAt: createdAt + ttlMs,\n });\n validateLifetime(payload.createdAt, payload.expiresAt, createdAt);\n const signature = requireText(\n await options.sign(canonicalDevicePairingInviteBytes(payload)),\n 'signature',\n 4096,\n );\n return { ...payload, signature };\n}\n\nexport function encodeDevicePairingInvite(invite: DevicePairingInvite): string {\n const payload = unsignedPayload(invite);\n const signature = requireText(invite.signature, 'signature', 4096);\n return canonicalJsonString({ ...payload, signature }, PAIRING_CANONICAL_LIMITS);\n}\n\nexport async function parseDevicePairingInvite(\n serialized: string,\n options: ParseDevicePairingInviteOptions,\n): Promise<DevicePairingInvite> {\n if (!serialized || serialized.length > MAX_INVITE_LENGTH) {\n throw new Error('invalid device pairing invite length');\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(serialized);\n } catch {\n throw new Error('device pairing invite is not valid JSON');\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('invalid device pairing invite');\n }\n const record = parsed as Record<string, unknown>;\n const expectedKeys = [\n 'protocol',\n 'peerId',\n 'publicKeyMultibase',\n 'deviceName',\n 'multiaddrs',\n 'createdAt',\n 'expiresAt',\n 'signature',\n ];\n if (\n Object.keys(record).length !== expectedKeys.length ||\n expectedKeys.some(key => !Object.hasOwn(record, key)) ||\n record.protocol !== DEVICE_PAIRING_INVITE_PROTOCOL ||\n typeof record.peerId !== 'string' ||\n typeof record.publicKeyMultibase !== 'string' ||\n typeof record.deviceName !== 'string' ||\n !Array.isArray(record.multiaddrs) ||\n record.multiaddrs.some((address) => typeof address !== 'string') ||\n typeof record.createdAt !== 'number' ||\n typeof record.expiresAt !== 'number' ||\n typeof record.signature !== 'string'\n ) {\n throw new Error('invalid device pairing invite');\n }\n validateLifetime(record.createdAt, record.expiresAt, options.now ?? Date.now());\n const payload = unsignedPayload({\n protocol: DEVICE_PAIRING_INVITE_PROTOCOL,\n peerId: record.peerId,\n publicKeyMultibase: record.publicKeyMultibase,\n deviceName: record.deviceName,\n multiaddrs: record.multiaddrs as string[],\n createdAt: record.createdAt,\n expiresAt: record.expiresAt,\n });\n const invite: DevicePairingInvite = {\n ...payload,\n signature: requireText(record.signature, 'signature', 4096),\n };\n if (\n !await options.verifyIdentity({\n invite,\n payload: canonicalDevicePairingInviteBytes(payload),\n })\n ) {\n throw new Error('device pairing invite identity verification failed');\n }\n return invite;\n}\n","import type { CloudDeviceRecord, Device, DeviceTrustStore, TrustedDeviceRecord } from './types.js';\n\nconst DEFAULT_CLOUD_DEVICE_FRESHNESS_MS = 3 * 60_000;\n\ntype Awaitable<T> = T | Promise<T>;\n\n/**\n * Host-owned live address/discovery overlay. Implementations can bridge this\n * to libp2p, a browser transport, or a mobile transport without Core importing\n * any one of those concrete network stacks.\n */\nexport interface DeviceCloudLiveDirectoryCapability {\n listCloudDeviceAddressPeerIds(): Awaitable<readonly string[]>;\n setCloudDeviceAddresses(peerId: string, multiaddrs: readonly string[]): Awaitable<void>;\n removeCloudDeviceAddresses(peerId: string): Awaitable<void>;\n upsertCloudDiscoveredDevice?(device: Device): Awaitable<void>;\n removeCloudDiscoveredDevice?(peerId: string): Awaitable<void>;\n upsertCloudTrustedDevice?(record: TrustedDeviceRecord): Awaitable<void>;\n removeCloudTrustedDevice?(peerId: string): Awaitable<void>;\n}\n\nexport interface CloudDeviceDirectoryReconcileLogger {\n warn(message: string, details?: Record<string, unknown>): void;\n}\n\nexport interface CloudDeviceDirectoryReconcileResult {\n cloudDevices: CloudDeviceRecord[];\n devices: Device[];\n removedPeerIds: string[];\n}\n\n/** Reconcile a fetched Cloud snapshot into durable trust and a live address overlay. */\nexport async function reconcileCloudDeviceDirectory(input: {\n cloudDevices: readonly CloudDeviceRecord[];\n excludePeerIds?: Iterable<string>;\n freshnessMs?: number;\n liveDirectory: DeviceCloudLiveDirectoryCapability;\n logger?: CloudDeviceDirectoryReconcileLogger;\n now?: () => number;\n trustStore: DeviceTrustStore;\n}): Promise<CloudDeviceDirectoryReconcileResult> {\n const now = input.now?.() ?? Date.now();\n const freshnessMs = input.freshnessMs ?? DEFAULT_CLOUD_DEVICE_FRESHNESS_MS;\n if (!Number.isFinite(freshnessMs) || freshnessMs < 0) {\n throw new TypeError('freshnessMs must be finite and non-negative');\n }\n const existingRecords = await input.trustStore.loadTrustedDevices();\n const liveAddressPeerIds = await input.liveDirectory.listCloudDeviceAddressPeerIds();\n const existingByPeerId = new Map(existingRecords.map(record => [record.peerId, record]));\n const excludedPeerIds = new Set(input.excludePeerIds ?? []);\n const recordsByPeerId = new Map<string, CloudDeviceRecord>();\n for (const record of input.cloudDevices) {\n if (recordsByPeerId.has(record.peerId)) throw new Error('cloud_directory_duplicate_peer');\n recordsByPeerId.set(record.peerId, record);\n }\n const activeCloudDevices = [...recordsByPeerId.values()].filter(\n record => record.revokedAt === undefined && !excludedPeerIds.has(record.peerId),\n );\n const activePeerIds = new Set(activeCloudDevices.map(record => record.peerId));\n const removedPeerIds: string[] = [];\n\n const previousCloudPeerIds = new Set([\n ...existingRecords\n .filter(record => record.trustMode === 'cloud-account')\n .map(record => record.peerId),\n ...liveAddressPeerIds,\n ]);\n for (const peerId of previousCloudPeerIds) {\n if (activePeerIds.has(peerId)) continue;\n const existing = existingByPeerId.get(peerId);\n if (existing?.trustMode === 'cloud-account') {\n await input.trustStore.removeTrustedDevice(peerId);\n await input.liveDirectory.removeCloudTrustedDevice?.(peerId);\n }\n await input.liveDirectory.removeCloudDeviceAddresses(peerId);\n await input.liveDirectory.removeCloudDiscoveredDevice?.(peerId);\n removedPeerIds.push(peerId);\n }\n\n const devices: Device[] = [];\n for (const cloudDevice of activeCloudDevices) {\n const existing = existingByPeerId.get(cloudDevice.peerId);\n const trustMode = existing?.trustMode === 'local-pairing'\n ? 'local-pairing' as const\n : 'cloud-account' as const;\n let trustedRecord = existing;\n if (trustMode === 'cloud-account') {\n trustedRecord = {\n peerId: cloudDevice.peerId,\n publicKeyMultibase: cloudDevice.publicKeyMultibase,\n deviceName: cloudDevice.deviceName,\n platform: cloudDevice.platform,\n trustMode,\n accountId: cloudDevice.accountId,\n createdAt: existing?.createdAt ?? now,\n lastSeen: cloudDevice.lastSeen,\n revokedAt: cloudDevice.revokedAt,\n };\n if (\n existing?.trustMode === 'cloud-account' &&\n existing.publicKeyMultibase !== cloudDevice.publicKeyMultibase\n ) {\n input.logger?.warn(\n '[device-network] Cloud directory rotated a cloud-account device public key',\n { peerId: existing.peerId, accountId: existing.accountId },\n );\n }\n if (!existing || !sameTrustedDevice(existing, trustedRecord)) {\n await input.trustStore.saveTrustedDevice(trustedRecord);\n }\n await input.liveDirectory.upsertCloudTrustedDevice?.(trustedRecord);\n }\n\n const device = cloudRecordToDevice(cloudDevice, trustMode, now, freshnessMs);\n await input.liveDirectory.setCloudDeviceAddresses(\n device.peerId,\n device.multiaddrs ?? [],\n );\n await input.liveDirectory.upsertCloudDiscoveredDevice?.(device);\n devices.push(device);\n }\n\n return { cloudDevices: activeCloudDevices, devices, removedPeerIds };\n}\n\nexport function cloudRecordToDevice(\n cloudDevice: CloudDeviceRecord,\n trustMode: Device['trustMode'],\n now = Date.now(),\n freshnessMs = DEFAULT_CLOUD_DEVICE_FRESHNESS_MS,\n): Device {\n const directMultiaddrs = normalizedAddresses(cloudDevice.multiaddrs)\n .filter(address => !address.includes('/p2p-circuit'));\n const relayMultiaddrs = normalizedAddresses([\n ...cloudDevice.multiaddrs.filter(address => address.includes('/p2p-circuit')),\n ...cloudDevice.relayReservations,\n ]);\n const paths: Device['reachability']['paths'] = [\n ...(directMultiaddrs.length > 0 ? ['direct' as const] : []),\n ...(relayMultiaddrs.length > 0 ? ['relay' as const] : []),\n ];\n const fresh = Number.isFinite(cloudDevice.lastSeen) &&\n cloudDevice.lastSeen >= now - freshnessMs;\n return {\n peerId: cloudDevice.peerId,\n displayName: cloudDevice.deviceName,\n platform: cloudDevice.platform,\n trustMode,\n trusted: true,\n reachability: {\n state: fresh && paths.length > 0 ? 'online' : 'offline',\n paths: fresh ? paths : [],\n },\n capabilities: cloudDevice.capabilities,\n multiaddrs: normalizedAddresses([...directMultiaddrs, ...relayMultiaddrs]),\n lastSeen: cloudDevice.lastSeen,\n };\n}\n\nfunction normalizedAddresses(addresses: readonly string[]): string[] {\n return [...new Set(addresses.map(address => address.trim()).filter(Boolean))];\n}\n\nfunction sameTrustedDevice(left: TrustedDeviceRecord, right: TrustedDeviceRecord): boolean {\n return left.peerId === right.peerId &&\n left.publicKeyMultibase === right.publicKeyMultibase &&\n left.deviceName === right.deviceName &&\n left.platform === right.platform &&\n left.trustMode === right.trustMode &&\n left.accountId === right.accountId &&\n left.createdAt === right.createdAt &&\n left.lastSeen === right.lastSeen &&\n left.revokedAt === right.revokedAt;\n}\n","import { CloudDeviceFetchError } from './cloudDeviceFetchClient.js';\nimport type { DeviceCloudCommitFence, DeviceCloudConnectionAdapter, DeviceCloudStepResult } from './deviceCloudConnectionCoordinator.js';\nimport { buildDeviceHeartbeatMessage, DEVICE_HEARTBEAT_LIMITS } from './deviceHeartbeat.js';\nimport { type CloudDeviceDirectoryReconcileLogger, type DeviceCloudLiveDirectoryCapability, reconcileCloudDeviceDirectory } from './reconcileCloudDeviceDirectory.js';\nimport type {\n CloudDeviceClient,\n CloudDeviceRecord,\n DeviceCapabilities,\n DeviceRelayReservationToken,\n DeviceTrustStore,\n LocalDeviceIdentity,\n PublicDeviceIdentity,\n SyncResult,\n} from './types.js';\n\nconst DEFAULT_RELAY_TOKEN_SAFETY_MARGIN_MS = 2 * 60_000;\n\ntype Awaitable<T> = T | Promise<T>;\n\nexport interface StandardDeviceCloudNetworkCapability {\n getMultiaddrs(): readonly string[];\n /** Final host write must reject a stale fence at its durable commit point. */\n configureRelayReservation(\n token: DeviceRelayReservationToken,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Awaitable<void>;\n clearRelayReservation(signal: AbortSignal): Awaitable<void>;\n}\n\nexport interface StandardDeviceCloudConnectionAdapterOptions {\n capabilities: () => Awaitable<DeviceCapabilities>;\n /** Final host write must reject a stale fence at its durable commit point. */\n configureConnectionGrantPublicKey: (\n value: { issuer: 'memeloop-cloud'; publicKeyMultibase: string },\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ) => Awaitable<void>;\n /**\n * Atomically publish a fetched Cloud directory snapshot only when the\n * supplied generation is still current. Implementations backed by async\n * persistence must perform an expected-generation CAS in the same durable\n * transaction as the snapshot write; a check followed by an awaited write\n * is not sufficient.\n */\n commitCloudDirectorySnapshot: (\n input: {\n cloudDevices: readonly CloudDeviceRecord[];\n excludePeerIds: readonly string[];\n freshnessMs?: number;\n now: number;\n },\n fence: DeviceCloudCommitFence,\n ) => Awaitable<void>;\n clearConnectionGrantPublicKey: (signal: AbortSignal) => Awaitable<void>;\n clearTokenCache: (client: CloudDeviceClient, signal: AbortSignal) => Awaitable<void>;\n directoryFreshnessMs?: number;\n directoryLogger?: CloudDeviceDirectoryReconcileLogger;\n identity: LocalDeviceIdentity;\n liveDirectory: DeviceCloudLiveDirectoryCapability;\n network: StandardDeviceCloudNetworkCapability;\n now?: () => number;\n relayRequiredForOnline?: (multiaddrs: readonly string[]) => boolean;\n relayTokenSafetyMarginMs?: number;\n signDeviceBinding: (input: {\n accountId: string;\n identity: LocalDeviceIdentity;\n nonce: string;\n signal: AbortSignal;\n }) => Awaitable<string>;\n signHeartbeat: (input: {\n peerId: string;\n timestamp: number;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n signal: AbortSignal;\n }) => Awaitable<{ nonce: string; signature: string }>;\n /** Host wrapper obtains the scoped Cloud grant before entering libp2p sync. */\n syncDevice?: (\n client: CloudDeviceClient,\n peerId: string,\n signal: AbortSignal,\n ) => Promise<SyncResult>;\n trustStore: DeviceTrustStore;\n}\n\n/** Shared host adapter for Cloud registration, relay, heartbeat, and directory maintenance. */\nexport class StandardDeviceCloudConnectionAdapter implements DeviceCloudConnectionAdapter<CloudDeviceClient> {\n private relayReservation?: DeviceRelayReservationToken;\n private relayReservationClient?: CloudDeviceClient;\n private backgroundSyncPeerIds: string[] = [];\n private readonly now: () => number;\n private readonly relayTokenSafetyMarginMs: number;\n\n constructor(private readonly options: StandardDeviceCloudConnectionAdapterOptions) {\n this.now = options.now ?? Date.now;\n this.relayTokenSafetyMarginMs = options.relayTokenSafetyMarginMs ??\n DEFAULT_RELAY_TOKEN_SAFETY_MARGIN_MS;\n if (!Number.isFinite(this.relayTokenSafetyMarginMs) || this.relayTokenSafetyMarginMs < 0) {\n throw new TypeError('relayTokenSafetyMarginMs must be finite and non-negative');\n }\n }\n\n public isConfigured(\n configuration: CloudDeviceClient | undefined,\n ): configuration is CloudDeviceClient {\n return configuration !== undefined;\n }\n\n public relayRequiredForOnline(_configuration: CloudDeviceClient): boolean {\n const addresses = this.options.network.getMultiaddrs();\n return this.options.relayRequiredForOnline?.(addresses) ??\n !hasValidDirectCloudDeviceAddress(addresses);\n }\n\n public async ensureAuthorizer(\n client: CloudDeviceClient,\n signal: AbortSignal,\n ): Promise<DeviceCloudStepResult> {\n const publicKey = await client.getConnectionGrantPublicKey(signal);\n return {\n commit: async (fence) => {\n fence.throwIfStale();\n await this.options.configureConnectionGrantPublicKey(publicKey, signal, fence);\n fence.throwIfStale();\n },\n };\n }\n\n public async registerDevice(\n client: CloudDeviceClient,\n signal: AbortSignal,\n ): Promise<undefined> {\n const nonce = await client.createBindingNonce(signal);\n throwIfAborted(signal);\n const signature = await this.options.signDeviceBinding({\n accountId: nonce.accountId,\n identity: this.options.identity,\n nonce: nonce.nonce,\n signal,\n });\n throwIfAborted(signal);\n const capabilities = await this.options.capabilities();\n throwIfAborted(signal);\n const registration = await client.registerDevice({\n // Construct a fresh public projection at the capability boundary. A\n // custom CloudDeviceClient must never observe host-local key references\n // or serialized private-key material through structural typing.\n identity: toPublicDeviceIdentity(this.options.identity),\n cloudNonce: nonce.nonce,\n signature,\n capabilities,\n multiaddrs: [...this.options.network.getMultiaddrs()],\n relayReservations: this.currentRelayReservations(),\n }, signal);\n if (!registration.ok || registration.peerId !== this.options.identity.peerId) {\n throw new Error('cloud device registration rejected');\n }\n return undefined;\n }\n\n public async ensureRelay(\n client: CloudDeviceClient,\n signal: AbortSignal,\n ): Promise<DeviceCloudStepResult | undefined> {\n if (\n this.relayReservationClient === client &&\n this.relayReservation &&\n this.relayReservation.expiresAt > this.now() + this.relayTokenSafetyMarginMs\n ) {\n return undefined;\n }\n const relayReservation = await client.createRelayReservation(\n { peerId: this.options.identity.peerId },\n signal,\n );\n return {\n commit: async (fence) => {\n fence.throwIfStale();\n await this.options.network.configureRelayReservation(relayReservation, signal, fence);\n fence.throwIfStale();\n fence.commitSynchronous(() => {\n this.relayReservation = relayReservation;\n this.relayReservationClient = client;\n });\n },\n };\n }\n\n public async heartbeat(\n client: CloudDeviceClient,\n signal: AbortSignal,\n ): Promise<undefined> {\n throwIfAborted(signal);\n const capabilities = await this.options.capabilities();\n throwIfAborted(signal);\n const unsigned = {\n peerId: this.options.identity.peerId,\n timestamp: this.now(),\n capabilities,\n multiaddrs: [...this.options.network.getMultiaddrs()],\n relayReservations: this.currentRelayReservations(),\n };\n const proof = await this.options.signHeartbeat({ ...unsigned, signal });\n throwIfAborted(signal);\n const heartbeat = { ...unsigned, ...proof };\n void buildDeviceHeartbeatMessage({ ...unsigned, nonce: proof.nonce });\n if (!boundedProofSignature(heartbeat.signature)) {\n throw new Error('invalid device heartbeat signature');\n }\n const result = await client.heartbeat(heartbeat, signal);\n if (!result.ok) throw new Error('cloud device heartbeat rejected');\n return undefined;\n }\n\n public async dispose(client: CloudDeviceClient, signal: AbortSignal): Promise<void> {\n this.relayReservation = undefined;\n this.relayReservationClient = undefined;\n this.backgroundSyncPeerIds = [];\n const errors: unknown[] = [];\n await bestEffortCleanup(\n () => this.options.clearConnectionGrantPublicKey(signal),\n errors,\n );\n await bestEffortCleanup(\n () => this.options.network.clearRelayReservation(signal),\n errors,\n );\n await bestEffortCleanup(\n async () => {\n await reconcileCloudDeviceDirectory({\n cloudDevices: [],\n liveDirectory: this.options.liveDirectory,\n logger: this.options.directoryLogger,\n now: this.now,\n trustStore: this.options.trustStore,\n });\n },\n errors,\n );\n await bestEffortCleanup(\n () => this.options.clearTokenCache(client, signal),\n errors,\n );\n if (errors.length > 0) {\n throw new AggregateError(errors, 'device cloud generation cleanup failed');\n }\n }\n\n public async syncDirectory(\n client: CloudDeviceClient,\n signal: AbortSignal,\n ): Promise<DeviceCloudStepResult> {\n const cloudDevices = await client.listDevices(signal);\n return {\n commit: async (fence) => {\n fence.throwIfStale();\n await this.options.commitCloudDirectorySnapshot({\n cloudDevices,\n excludePeerIds: [this.options.identity.peerId],\n freshnessMs: this.options.directoryFreshnessMs,\n now: this.now(),\n }, fence);\n fence.throwIfStale();\n fence.commitSynchronous(() => {\n this.backgroundSyncPeerIds = cloudDevices\n .filter(device => device.peerId !== this.options.identity.peerId && device.revokedAt === undefined)\n .map(device => device.peerId);\n });\n },\n };\n }\n\n public listBackgroundSyncPeerIds(\n _client: CloudDeviceClient,\n signal: AbortSignal,\n ): readonly string[] {\n signal.throwIfAborted();\n return this.options.syncDevice ? [...this.backgroundSyncPeerIds] : [];\n }\n\n public syncDevice(\n client: CloudDeviceClient,\n peerId: string,\n signal: AbortSignal,\n ): Promise<SyncResult> {\n signal.throwIfAborted();\n if (!this.options.syncDevice) throw new Error('background_device_sync_not_configured');\n return this.options.syncDevice(client, peerId, signal);\n }\n\n public classifyError(error: unknown): 'offline' | 'error' {\n if (error instanceof CloudDeviceFetchError) {\n return error.code === 'cloud_request_failed' ? 'offline' : 'error';\n }\n return 'offline';\n }\n\n private currentRelayReservations(): string[] {\n const active = this.options.network.getMultiaddrs()\n .filter(address => address.includes('/p2p-circuit'));\n return active.length > 0 ? [...active] : [...(this.relayReservation?.relayMultiaddrs ?? [])];\n }\n}\n\nfunction toPublicDeviceIdentity(identity: LocalDeviceIdentity): PublicDeviceIdentity {\n return {\n peerId: identity.peerId,\n publicKeyMultibase: identity.publicKeyMultibase,\n createdAt: identity.createdAt,\n deviceName: identity.deviceName,\n platform: identity.platform,\n };\n}\n\n/** True only when another device can plausibly dial the address without a relay. */\nexport function hasValidDirectCloudDeviceAddress(addresses: readonly string[]): boolean {\n return addresses.some((address) => {\n if (address.includes('/p2p-circuit')) return false;\n const parts = address.split('/');\n const protocolIndex = parts.findIndex(part =>\n part === 'ip4' || part === 'ip6' || part === 'dns' ||\n part === 'dns4' || part === 'dns6'\n );\n if (protocolIndex < 0) return false;\n const host = parts[protocolIndex + 1]?.toLowerCase();\n if (!host) return false;\n const protocol = parts[protocolIndex];\n if (protocol === 'ip4') return isPublicIpv4(host);\n if (protocol === 'ip6') return isPublicIpv6(host);\n return isPlausiblePublicDnsHost(host);\n });\n}\n\nfunction isPublicIpv4(host: string): boolean {\n const octets = host.split('.').map(part => Number(part));\n if (octets.length !== 4 || octets.some(octet => !Number.isInteger(octet) || octet < 0 || octet > 255)) {\n return false;\n }\n const [first, second] = octets as [number, number, number, number];\n return first !== 0 && first !== 10 && first !== 127 && first < 224 &&\n !(first === 100 && second >= 64 && second <= 127) &&\n !(first === 169 && second === 254) &&\n !(first === 172 && second >= 16 && second <= 31) &&\n !(first === 192 && second === 0 && octets[2] === 0) &&\n !(first === 192 && second === 0 && octets[2] === 2) &&\n !(first === 192 && second === 88 && octets[2] === 99) &&\n !(first === 192 && second === 168) &&\n !(first === 198 && (second === 18 || second === 19)) &&\n !(first === 198 && second === 51 && octets[2] === 100) &&\n !(first === 203 && second === 0 && octets[2] === 113);\n}\n\nfunction isPublicIpv6(host: string): boolean {\n const groups = parseIpv6(host);\n if (!groups) return false;\n const [first, second] = groups;\n if ((first & 0xe000) !== 0x2000) return false;\n // Documentation-only addresses are valid syntax but never direct public paths.\n return !(first === 0x2001 && second === 0x0db8);\n}\n\nfunction parseIpv6(host: string): number[] | undefined {\n const normalized = host.toLowerCase();\n if (normalized.includes('%') || normalized.includes('.')) return undefined;\n const halves = normalized.split('::');\n if (halves.length > 2) return undefined;\n const parseHalf = (half: string): number[] | undefined => {\n if (half === '') return [];\n const parts = half.split(':');\n if (parts.some(part => !/^[0-9a-f]{1,4}$/u.test(part))) return undefined;\n return parts.map(part => Number.parseInt(part, 16));\n };\n const left = parseHalf(halves[0] ?? '');\n const right = parseHalf(halves[1] ?? '');\n if (!left || !right) return undefined;\n if (halves.length === 1) return left.length === 8 ? left : undefined;\n const missing = 8 - left.length - right.length;\n if (missing < 1) return undefined;\n return [...left, ...Array.from({ length: missing }, () => 0), ...right];\n}\n\nfunction isPlausiblePublicDnsHost(host: string): boolean {\n const normalized = host.endsWith('.') ? host.slice(0, -1) : host;\n if (isIpv4Syntax(normalized)) return isPublicIpv4(normalized);\n if (normalized.includes(':')) return isPublicIpv6(normalized);\n if (\n normalized === 'localhost' || normalized.endsWith('.localhost') ||\n normalized.endsWith('.local') || normalized.endsWith('.internal')\n ) return false;\n const labels = normalized.split('.');\n return labels.length > 1 && labels.every(label =>\n label.length > 0 && label.length <= 63 &&\n /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u.test(label)\n );\n}\n\nfunction isIpv4Syntax(host: string): boolean {\n return /^\\d{1,3}(?:\\.\\d{1,3}){3}$/u.test(host);\n}\n\nfunction boundedProofSignature(signature: unknown): signature is string {\n if (\n typeof signature !== 'string' || signature.length === 0 ||\n signature.length > DEVICE_HEARTBEAT_LIMITS.signatureCharacters ||\n signature !== signature.trim()\n ) {\n return false;\n }\n for (let index = 0; index < signature.length; index += 1) {\n const code = signature.charCodeAt(index);\n if (code <= 31 || code === 127) return false;\n }\n return true;\n}\n\nasync function bestEffortCleanup(\n operation: () => Awaitable<void>,\n errors: unknown[],\n): Promise<void> {\n try {\n await operation();\n } catch (error) {\n errors.push(error);\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal): void {\n if (!signal.aborted) return;\n throw signal.reason instanceof Error ? signal.reason : new Error('device_cloud_operation_aborted');\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport type { MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from '../storage/ports.js';\nimport type { SyncIoOptions } from '../sync/chatSyncEngine.js';\nimport type { ConversationEventSyncPage, VersionRange } from '../sync/protocol.js';\n\nexport type DevicePlatform = 'desktop' | 'mobile' | 'cli' | 'web';\nexport type DeviceTrustMode = 'local-pairing' | 'cloud-account';\nexport type DeviceReachabilityState = 'nearby' | 'online' | 'offline' | 'connecting';\nexport type DeviceNetworkPath = 'lan' | 'direct' | 'relay';\nexport type DeviceProtocolDirection = 'inbound' | 'outbound';\nexport type PairingSessionDirection = 'inbound' | 'outbound';\nexport type PairingSessionStatus = 'pending' | 'accepted' | 'rejected' | 'expired';\n\n/** Generation-scoped authority for a final synchronous host or persistence write. */\nexport interface DeviceCloudCommitFence {\n readonly generation: number;\n readonly signal: AbortSignal;\n isCurrent(): boolean;\n throwIfStale(): void;\n commitSynchronous<Result>(\n operation: () => Result extends PromiseLike<unknown> ? never : Result,\n ): boolean;\n}\n\nexport type MemeLoopProtocol =\n | '/memeloop/rpc/2.0.0'\n | '/memeloop/sync/2.0.0'\n | '/memeloop/pairing/2.0.0'\n | '/memeloop/orchestration/2.0.0'\n | '/memeloop/relay-admission/2.0.0';\n\nexport interface DeviceCapabilities {\n tools: string[];\n mcpServers: string[];\n hasWiki: boolean;\n agentLoop?: boolean;\n imChannels: string[];\n wikis: Array<{\n wikiId: string;\n title?: string;\n pathHint?: string;\n }>;\n}\n\n/** Device identity fields safe to disclose to Cloud and remote peers. */\nexport interface PublicDeviceIdentity {\n peerId: string;\n publicKeyMultibase: string;\n createdAt: number;\n deviceName: string;\n platform: DevicePlatform;\n}\n\n/** Host-local identity. Private-key material must never cross an adapter boundary. */\nexport interface LocalDeviceIdentity extends PublicDeviceIdentity {\n privateKeyRef: string;\n privateKeyPkcs8Base64Url?: string;\n privateKeyRawSeedBase64Url?: string;\n}\n\nexport interface DeviceNetworkListenOptions {\n addresses: string[];\n announce?: string[];\n}\n\nexport interface DeviceReachability {\n state: DeviceReachabilityState;\n paths: DeviceNetworkPath[];\n}\n\nexport interface Device {\n peerId: string;\n displayName: string;\n platform: DevicePlatform;\n trustMode: DeviceTrustMode;\n trusted?: boolean;\n reachability: DeviceReachability;\n capabilities: DeviceCapabilities;\n multiaddrs?: string[];\n lastSeen?: number;\n}\n\nexport interface TrustedDeviceRecord {\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n platform: DevicePlatform;\n trustMode: DeviceTrustMode;\n accountId?: string;\n createdAt: number;\n lastSeen?: number;\n revokedAt?: number;\n}\n\nexport interface DeviceTrustStore {\n loadTrustedDevices(): Promise<TrustedDeviceRecord[]>;\n saveTrustedDevice(record: TrustedDeviceRecord): Promise<void>;\n removeTrustedDevice(peerId: string): Promise<void>;\n}\n\nexport interface DeviceAccountBindingRequest {\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n platform: DevicePlatform;\n cloudNonce: string;\n signature: string;\n}\n\nexport interface CloudDeviceRecord {\n accountId: string;\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n platform: DevicePlatform;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n lastSeen: number;\n revokedAt?: number;\n}\n\nexport interface DeviceConnectionGrant {\n issuer: 'memeloop-cloud';\n accountId: string;\n subjectPeerId: string;\n allowedPeerIds: string[];\n protocols: MemeLoopProtocol[];\n rpcMethodScope: DeviceConnectionGrantStringScope;\n conversationScope: DeviceConnectionGrantStringScope;\n definitionScope: DeviceConnectionGrantStringScope;\n issuedAt: number;\n expiresAt: number;\n signature: string;\n}\n\nexport type DeviceConnectionGrantStringScope =\n | { mode: 'none' }\n | { mode: 'all' }\n | { mode: 'ids'; ids: string[] };\n\nexport interface DeviceConnectionGrantVerificationInput {\n grant: DeviceConnectionGrant;\n verificationPublicKeyMultibase: string;\n subjectPeerId?: string;\n allowedPeerId?: string;\n now?: number;\n}\n\nexport interface DeviceRelayReservationToken {\n issuer: 'memeloop-cloud';\n accountId: string;\n peerId: string;\n relayMultiaddrs: string[];\n bootstrapMultiaddrs: string[];\n issuedAt: number;\n expiresAt: number;\n signature: string;\n}\n\nexport interface DeviceRelayReservationTokenVerificationInput {\n token: DeviceRelayReservationToken;\n verificationPublicKeyMultibase: string;\n peerId?: string;\n now?: number;\n}\n\nexport interface PairingSession {\n sessionId: string;\n localPeerId: string;\n remotePeerId: string;\n remotePublicKeyMultibase: string;\n remoteDeviceName: string;\n remotePlatform: DevicePlatform;\n remoteCapabilities: DeviceCapabilities;\n remoteMultiaddrs: string[];\n direction: PairingSessionDirection;\n status: PairingSessionStatus;\n confirmCode: string;\n createdAt: number;\n expiresAt: number;\n}\n\nexport interface LocalPairingRequestOptions {\n multiaddrs?: string[];\n}\n\nexport interface SyncProgress {\n passes: number;\n peers: number;\n /** Bounded frontier metadata pages inspected while discovering transfer work. */\n frontierPages: number;\n /** Event/attachment transfer pages. */\n pages: number;\n events: number;\n bytes: number;\n elapsedMs: number;\n}\n\nexport interface SyncContinuation {\n reason: 'pass-limit' | 'time-limit';\n /**\n * Continuations never carry an authoritative cursor. A later call resumes\n * from the durable event frontier, so cancellation or process restart cannot\n * skip acknowledged work.\n */\n resumeFrom: 'durable-frontier';\n}\n\nexport interface SyncResult {\n /** The bounded operation itself succeeded, including an incomplete resumable result. */\n ok: true;\n peerId: string;\n syncedAt: number;\n complete: boolean;\n progress: SyncProgress;\n continuation?: SyncContinuation;\n}\n\nexport type DeviceNetworkUnavailableCode =\n | 'device_network_pairing_unavailable'\n | 'device_network_stream_unavailable'\n | 'device_network_sync_unavailable';\n\n/** Stable, non-secret error for an adapter that cannot perform a network operation. */\nexport class DeviceNetworkUnavailableError extends Error {\n public readonly code: DeviceNetworkUnavailableCode;\n\n constructor(code: DeviceNetworkUnavailableCode) {\n super(code);\n this.name = 'DeviceNetworkUnavailableError';\n this.code = code;\n }\n}\n\nexport interface MemeLoopDuplexStream {\n source: AsyncIterable<Uint8Array>;\n sink(source: AsyncIterable<Uint8Array>): Promise<void>;\n close(): Promise<void>;\n abort(error: Error): void | Promise<void>;\n /** Aborts when the underlying remote stream disconnects or is reset. */\n signal?: AbortSignal;\n}\n\nexport interface DeviceRpcHandlerInput {\n remotePeerId: string;\n method: string;\n parameters: unknown;\n presentedGrant?: DeviceConnectionGrant;\n /** Aborts when the authenticated transport request is cancelled or disconnected. */\n signal?: AbortSignal;\n}\n\nexport type DeviceRpcHandler = (input: DeviceRpcHandlerInput) => Promise<unknown>;\n\nexport interface DeviceStreamOptions {\n presentedGrant?: DeviceConnectionGrant;\n signal?: AbortSignal;\n}\n\nexport type AgentExecutionLocation = { kind: 'local' } | { kind: 'device'; peerId: string };\n\nexport type AgentExecutionState = 'idle' | 'running' | 'stopping';\n\nexport interface ConversationExecutionPlacement {\n conversationId: string;\n location: AgentExecutionLocation;\n state: AgentExecutionState;\n updatedAt: number;\n}\n\nexport interface DeviceAuthorizer {\n canOpenProtocol(input: {\n remotePeerId: string;\n protocol: MemeLoopProtocol;\n direction?: DeviceProtocolDirection;\n presentedGrant?: DeviceConnectionGrant;\n }): Promise<boolean>;\n}\n\nexport interface CloudDeviceClient {\n listDevices(signal?: AbortSignal): Promise<CloudDeviceRecord[]>;\n getConnectionGrantPublicKey(signal?: AbortSignal): Promise<{\n issuer: 'memeloop-cloud';\n publicKeyMultibase: string;\n }>;\n createConnectionGrant(input: {\n subjectPeerId: string;\n allowedPeerIds: string[];\n protocols: MemeLoopProtocol[];\n rpcMethodScope: DeviceConnectionGrantStringScope;\n conversationScope: DeviceConnectionGrantStringScope;\n definitionScope: DeviceConnectionGrantStringScope;\n }, signal?: AbortSignal): Promise<DeviceConnectionGrant>;\n createRelayReservation(\n input: { peerId: string },\n signal?: AbortSignal,\n ): Promise<DeviceRelayReservationToken>;\n createBindingNonce(signal?: AbortSignal): Promise<{\n nonce: string;\n accountId: string;\n expiresAt: string;\n }>;\n registerDevice(\n input: Pick<DeviceAccountBindingRequest, 'cloudNonce' | 'signature'> & {\n identity: PublicDeviceIdentity;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n },\n signal?: AbortSignal,\n ): Promise<{ ok: boolean; peerId: string }>;\n heartbeat(input: {\n peerId: string;\n timestamp: number;\n nonce: string;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n signature: string;\n }, signal?: AbortSignal): Promise<{ ok: boolean }>;\n}\n\nexport interface DeviceNetworkService {\n start(): Promise<void>;\n stop(): Promise<void>;\n getLocalDevice(): Promise<Device>;\n listDevices(): Promise<Device[]>;\n observeDevices(listener: (devices: Device[]) => void): () => void;\n listPairingSessions(): Promise<PairingSession[]>;\n observePairingSessions(listener: (sessions: PairingSession[]) => void): () => void;\n requestLocalPairing(\n peerId: string,\n options?: LocalPairingRequestOptions,\n ): Promise<PairingSession>;\n acceptPairing(sessionId: string): Promise<void>;\n rejectPairing(sessionId: string): Promise<void>;\n removeTrustedDevice(peerId: string): Promise<void>;\n openStream(\n peerId: string,\n protocol: MemeLoopProtocol,\n options?: DeviceStreamOptions,\n ): Promise<MemeLoopDuplexStream>;\n sendRpc<T>(\n peerId: string,\n method: string,\n parameters: unknown,\n options?: DeviceStreamOptions,\n ): Promise<T>;\n syncWithDevice(peerId: string, options?: DeviceSyncOptions): Promise<SyncResult>;\n\n /** Configure Cloud connection. When set, syncCloudDevices() and CloudDeviceAuthorizer become available. */\n configureCloud?(config: { cloudUrl: string; accessToken: string }): void;\n /** Apply a Cloud-signed private relay admission token and connect to advertised relay/bootstrap peers. */\n configureRelayReservation?(\n token: DeviceRelayReservationToken,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<void>;\n /** Fetch devices from Cloud directory and persist into local trust store. Returns synced devices. */\n syncCloudDevices?(): Promise<CloudDeviceRecord[]>;\n}\n\nexport interface DeviceSyncOptions {\n presentedGrant?: DeviceConnectionGrant;\n /** Restrict synchronization to active conversations; undefined syncs all. */\n conversationIds?: string[];\n signal?: AbortSignal;\n}\n\nexport interface ExchangeVersionFrontierPageResult {\n remotePage: MessageVersionFrontierPage;\n missingForRemote: VersionRange[];\n}\n\nexport interface AttachmentChunk {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n}\n\nexport interface DeviceSyncTransport {\n listPeers(): Promise<Device[]>;\n exchangeVersionFrontierPage(\n peerId: string,\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<ExchangeVersionFrontierPageResult>;\n pullMissingEvents(\n peerId: string,\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage>;\n pullAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<AttachmentChunk | null>;\n pushEvents(peerId: string, events: ConversationEvent[], options?: SyncIoOptions): Promise<void>;\n pushAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void>;\n}\n","/**\n * 将节点 RPC `memeloop.storage.getAttachmentBlob` 的返回值解码为同步引擎可用的 BLOB。\n */\n\nexport function decodeAttachmentBlobRpc(\n result: unknown,\n): { data: Uint8Array; filename: string; mimeType: string; size: number } | null {\n if (result == null || typeof result !== 'object') return null;\n const r = result as {\n found?: boolean;\n error?: string;\n dataBase64?: string;\n filename?: string;\n mimeType?: string;\n size?: number;\n };\n if (r.error || !r.found || typeof r.dataBase64 !== 'string') return null;\n let data: Uint8Array;\n try {\n const binary = atob(r.dataBase64);\n if (!binary.length) return null;\n data = Uint8Array.from(binary, (character) => character.charCodeAt(0));\n } catch {\n return null;\n }\n return {\n data,\n filename: typeof r.filename === 'string' ? r.filename : 'attachment',\n mimeType: typeof r.mimeType === 'string' ? r.mimeType : 'application/octet-stream',\n size: typeof r.size === 'number' && r.size > 0 ? r.size : data.byteLength,\n };\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\n\n/** Highest contiguous originSequence for each conversation+origin pair. */\nexport type VersionVector = Record<string, number>;\n\n/**\n * Version-vector entries are scoped to one conversation and one message\n * origin. Lamport clocks are allocated per conversation, so a node-wide key\n * would incorrectly hide a new short conversation after a long one was\n * acknowledged.\n */\nexport function versionVectorKey(conversationId: string, originNodeId: string): string {\n return JSON.stringify([conversationId, originNodeId]);\n}\n\nexport function parseVersionVectorKey(\n key: string,\n): { conversationId: string; originNodeId: string } | undefined {\n try {\n const value: unknown = JSON.parse(key);\n if (\n !Array.isArray(value) ||\n value.length !== 2 ||\n typeof value[0] !== 'string' ||\n value[0].length === 0 ||\n typeof value[1] !== 'string' ||\n value[1].length === 0\n ) return undefined;\n return { conversationId: value[0], originNodeId: value[1] };\n } catch {\n return undefined;\n }\n}\n\nexport interface ConversationMeta {\n conversationId: string;\n title: string;\n lastMessagePreview: string;\n lastMessageTimestamp: number;\n messageCount: number;\n originNodeId: string;\n /** Lamport clock of the origin metadata event; never substitute messageCount. */\n originClock: number;\n definitionId: string;\n instanceDelta?: Record<string, unknown>;\n isUserInitiated: boolean;\n sourceChannel?: {\n channelId: string;\n platform: string;\n imUserId: string;\n };\n}\n\nexport function isConversationMeta(value: unknown): value is ConversationMeta {\n if (value === null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return (\n typeof o.conversationId === 'string' &&\n typeof o.title === 'string' &&\n typeof o.originNodeId === 'string' &&\n typeof o.originClock === 'number' &&\n typeof o.definitionId === 'string' &&\n typeof o.messageCount === 'number' &&\n typeof o.lastMessageTimestamp === 'number' &&\n typeof o.isUserInitiated === 'boolean'\n );\n}\n\nexport interface VersionRange {\n conversationId: string;\n originNodeId: string;\n fromExclusive: number;\n toInclusive: number;\n}\n\nexport function computeMissingVersionRanges(\n currentVersion: VersionVector,\n availableVersion: VersionVector,\n): VersionRange[] {\n const ranges: VersionRange[] = [];\n for (const [key, availableClock] of Object.entries(availableVersion)) {\n const identity = parseVersionVectorKey(key);\n if (!identity) continue;\n const currentClock = currentVersion[key] ?? 0;\n if (availableClock > currentClock) {\n ranges.push({ ...identity, fromExclusive: currentClock, toInclusive: availableClock });\n }\n }\n return ranges.sort((left, right) =>\n compareCodeUnits(left.conversationId, right.conversationId) ||\n compareCodeUnits(left.originNodeId, right.originNodeId)\n );\n}\n\nexport function versionVectorCoversRange(\n vector: VersionVector,\n range: VersionRange,\n): boolean {\n const key = versionVectorKey(range.conversationId, range.originNodeId);\n return (vector[key] ?? 0) >= range.toInclusive;\n}\n\nfunction compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\n/** Bounded, forward-only raw event page used by peer anti-entropy. */\nexport interface ConversationEventSyncPage {\n items: ConversationEvent[];\n /** Cursor of the final returned matching event. */\n nextCursor?: ConversationEventCursor;\n}\n","import type { AttachmentReference, ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport {\n assertCanonicalConversationEvent,\n assertCanonicalConversationEvents,\n canonicalConversationEventBytes,\n conversationEventAttachmentReferences,\n} from '../conversation/index.js';\nimport { MAX_SYNC_ATTACHMENT_BYTES, MAX_SYNC_ATTACHMENT_CHUNK_BYTES } from '../device-network/libp2pSyncProtocol.js';\nimport type { ConversationEventPage as StoredConversationEventPage, MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from '../storage/ports.js';\nimport { type ConversationEventSyncPage, type VersionRange, versionVectorKey } from './protocol.js';\n\nimport type { IAgentStorage } from '../types.js';\nimport { assertAgentUserMessageWithinLimits, assertConversationMessageWithinPagingLimits } from '../userMessageAdmission.js';\n\nconst EVENT_PUSH_PAGE_MAX_BYTES = 12 * 1024 * 1024;\nconst EVENT_PAGE_MAX_ITEMS = 128;\nconst FRONTIER_PAGE_MAX_ITEMS = 128;\nconst MAX_SYNC_ID_LENGTH = 512;\nconst MAX_SYNC_CONVERSATION_SCOPE = 256;\nconst MAX_SYNC_WORK_PAGES_PER_PEER_PASS = 64;\n/**\n * Frontier discovery is cheap, bounded metadata work rather than body\n * transfer. Keeping a separate ceiling lets a restarted engine rebuild its\n * position from durable frontiers without weakening the 64 transfer-page\n * limit. 2,048 pages cover 262,144 distinct origin frontiers per pass.\n */\nconst MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS = 2_048;\nconst MAX_SYNC_EVENTS_PER_PEER_PASS = 4_096;\nconst MAX_SYNC_BYTES_PER_PEER_PASS = 80 * 1024 * 1024;\nconst MAX_SYNC_PEERS_PER_PASS = 64;\nconst utf8Encoder = new TextEncoder();\n\ninterface PeerSyncContinuation {\n localAfter?: MessageVersionFrontierCursor;\n remoteAfter?: MessageVersionFrontierCursor;\n localDone: boolean;\n remoteDone: boolean;\n}\n\ninterface PeerSyncWorkBudget {\n frontierPages: number;\n pages: number;\n events: number;\n bytes: number;\n exhausted: boolean;\n global: SyncPassWorkBudget;\n}\n\ninterface SyncPassWorkBudget {\n frontierPages: number;\n pages: number;\n events: number;\n bytes: number;\n exhausted: boolean;\n limits: ChatSyncPassLimits;\n}\n\nexport interface SyncIoOptions {\n signal?: AbortSignal;\n}\n\nexport interface ChatSyncPassProgress {\n peers: number;\n /** Frontier metadata pages inspected while discovering transfer work. */\n frontierPages: number;\n /** Event/attachment transfer pages; hard-limited independently of discovery. */\n pages: number;\n events: number;\n bytes: number;\n}\n\nexport interface ChatSyncPassResult {\n complete: boolean;\n progress: ChatSyncPassProgress;\n /** Present only when another bounded pass can make forward progress. */\n continuation?: {\n reason: 'work-budget';\n pendingPeerIds: string[];\n };\n}\n\nexport interface ChatSyncPassLimits {\n maxPeers: number;\n maxFrontierPages: number;\n maxPages: number;\n maxEvents: number;\n maxBytes: number;\n}\n\nexport interface ChatSyncPeer {\n nodeId: string;\n exchangeVersionFrontierPage(\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<{\n remotePage: MessageVersionFrontierPage;\n missingForRemote: VersionRange[];\n }>;\n pullMissingEvents?(\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage>;\n pullAttachmentChunk?(\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<\n {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n } | null\n >;\n pushEvents?(events: ConversationEvent[], options?: SyncIoOptions): Promise<void>;\n pushAttachmentChunk?(\n conversationId: string,\n contentHash: string,\n chunk: {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n },\n options?: SyncIoOptions,\n ): Promise<void>;\n}\n\nexport interface ChatSyncEngineOptions {\n nodeId: string;\n storage: IAgentStorage;\n peers: () => ChatSyncPeer[];\n /** Surface body-transfer failures to an interactive caller instead of relying on the next pass. */\n failOnMessageSyncError?: boolean;\n signal?: AbortSignal;\n /** Restrict this pass to these conversations; undefined means the full store. */\n conversationIds?: readonly string[];\n /** Optional lower ceilings for one foreground pass; hard protocol ceilings cannot be raised. */\n passLimits?: Partial<ChatSyncPassLimits>;\n}\n\n/** Bidirectional, raw-event anti-entropy for conversation state. */\nexport class ChatSyncEngine {\n private readonly nodeId: string;\n private readonly storage: IAgentStorage;\n private readonly getPeers: () => ChatSyncPeer[];\n private readonly failOnMessageSyncError: boolean;\n private readonly defaultSignal?: AbortSignal;\n private activeSignal?: AbortSignal;\n private readonly conversationIds?: string[];\n private readonly passLimits: ChatSyncPassLimits;\n private readonly continuations = new Map<string, PeerSyncContinuation>();\n private readonly pendingAttachmentPushes = new Map<string, Set<string>>();\n private nextPeerAfter?: string;\n private inFlightSync?: Promise<ChatSyncPassResult>;\n\n constructor(options: ChatSyncEngineOptions) {\n if (!isValidSyncIdentifier(options.nodeId)) throw new Error('invalid_sync_node_id');\n this.nodeId = options.nodeId;\n this.storage = options.storage;\n this.getPeers = options.peers;\n this.failOnMessageSyncError = options.failOnMessageSyncError ?? false;\n this.defaultSignal = options.signal;\n this.passLimits = resolvePassLimits(options.passLimits);\n this.conversationIds = options.conversationIds === undefined\n ? undefined\n : [...new Set(options.conversationIds)].sort(compareCodeUnits);\n if (\n this.conversationIds !== undefined &&\n (this.conversationIds.length > MAX_SYNC_CONVERSATION_SCOPE ||\n this.conversationIds.some(conversationId => !isValidSyncIdentifier(conversationId)))\n ) {\n throw new Error('invalid_sync_conversation_scope');\n }\n }\n\n public syncOnce(options: SyncIoOptions = {}): Promise<ChatSyncPassResult> {\n if (this.inFlightSync) return this.inFlightSync;\n this.activeSignal = options.signal ?? this.defaultSignal;\n const running = this.runSyncOnce();\n this.inFlightSync = running;\n const release = (): void => {\n if (this.inFlightSync === running) {\n this.inFlightSync = undefined;\n this.activeSignal = undefined;\n }\n };\n void running.then(release, release);\n return running;\n }\n\n private async runSyncOnce(): Promise<ChatSyncPassResult> {\n this.throwIfAborted();\n const peers = this.collectPeers();\n const activePeerIds = new Set(peers.map(peer => peer.nodeId));\n this.garbageCollectPeerState(activePeerIds);\n if (this.conversationIds?.length === 0) {\n return {\n complete: true,\n progress: { peers: 0, frontierPages: 0, pages: 0, events: 0, bytes: 0 },\n };\n }\n if (!this.storage.getEventVersionFrontierPage || !this.storage.getEventVersionFrontiersForKeys) {\n throw new Error('sync_event_frontier_store_not_configured');\n }\n const orderedPeers = rotatePeers(peers, this.nextPeerAfter);\n const globalBudget = createSyncPassWorkBudget(this.passLimits);\n const progress: ChatSyncPassProgress = {\n peers: 0,\n frontierPages: 0,\n pages: 0,\n events: 0,\n bytes: 0,\n };\n const pendingPeerIds: string[] = [];\n let complete = true;\n let processedPeers = 0;\n const scheduledPeers = orderedPeers.slice(0, this.passLimits.maxPeers);\n for (const peer of scheduledPeers) {\n if (globalBudget.frontierPages >= globalBudget.limits.maxFrontierPages) {\n globalBudget.exhausted = true;\n complete = false;\n break;\n }\n const budget = createPeerSyncWorkBudget(globalBudget);\n try {\n const peerComplete = await this.syncPeerFrontierPages(peer, scheduledPeers, budget);\n if (!peerComplete) {\n complete = false;\n if (budget.exhausted) {\n pendingPeerIds.push(peer.nodeId);\n } else if (this.failOnMessageSyncError) {\n throw new Error(`event_sync_incomplete:${peer.nodeId}`);\n }\n }\n } catch (error) {\n this.throwIfAborted();\n if (this.failOnMessageSyncError) throw error;\n complete = false;\n } finally {\n processedPeers += 1;\n this.nextPeerAfter = peer.nodeId;\n progress.peers += 1;\n progress.frontierPages += budget.frontierPages;\n progress.pages += budget.pages;\n progress.events += budget.events;\n progress.bytes += budget.bytes;\n }\n if (globalBudget.exhausted) break;\n }\n const skippedPeers = orderedPeers.slice(processedPeers);\n if (skippedPeers.length > 0) {\n complete = false;\n for (const peer of skippedPeers.slice(0, this.passLimits.maxPeers)) {\n pendingPeerIds.push(peer.nodeId);\n }\n } else if (complete) {\n this.nextPeerAfter = undefined;\n }\n const boundedPendingPeerIds = [...new Set(pendingPeerIds)].slice(0, this.passLimits.maxPeers);\n return {\n complete,\n progress,\n ...(boundedPendingPeerIds.length > 0\n ? { continuation: { reason: 'work-budget' as const, pendingPeerIds: boundedPendingPeerIds } }\n : {}),\n };\n }\n\n public antiEntropyOnce(options: SyncIoOptions = {}): Promise<ChatSyncPassResult> {\n return this.syncOnce(options);\n }\n\n private async syncPeerFrontierPages(\n peer: ChatSyncPeer,\n attachmentPeers: ChatSyncPeer[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n const continuation = this.continuations.get(peer.nodeId);\n let localAfter = continuation?.localAfter;\n let remoteAfter = continuation?.remoteAfter;\n let localDone = continuation?.localDone ?? false;\n let remoteDone = continuation?.remoteDone ?? false;\n do {\n this.throwIfAborted();\n if (!consumeFrontierScanPage(budget)) {\n this.saveContinuation(peer.nodeId, { localAfter, remoteAfter, localDone, remoteDone });\n return false;\n }\n const localPage: MessageVersionFrontierPage = localDone\n ? { items: [] }\n : await this.storage.getEventVersionFrontierPage({\n limit: FRONTIER_PAGE_MAX_ITEMS,\n ...(localAfter ? { after: localAfter } : {}),\n ...(this.conversationIds ? { conversationIds: this.conversationIds } : {}),\n signal: this.activeSignal,\n });\n this.assertValidFrontierPage(localPage, localAfter, 'storage');\n const exchange = await peer.exchangeVersionFrontierPage(\n localPage.items,\n remoteAfter,\n !remoteDone,\n this.conversationIds,\n { signal: this.activeSignal },\n );\n this.assertValidFrontierPage(exchange.remotePage, remoteAfter, peer.nodeId, remoteDone);\n if (\n !isValidVersionRanges(exchange.missingForRemote) ||\n !rangesMatchOfferedFrontiers(exchange.missingForRemote, localPage.items)\n ) {\n throw new Error(`inconsistent_sync_exchange:${peer.nodeId}`);\n }\n this.assertScopedRanges(exchange.missingForRemote, peer.nodeId);\n const pushComplete = await this.pushEventsToPeer(peer, exchange.missingForRemote, budget);\n if (!pushComplete) {\n this.saveContinuation(peer.nodeId, { localAfter, remoteAfter, localDone, remoteDone });\n return false;\n }\n\n const localForRemote = await this.storage.getEventVersionFrontiersForKeys(\n exchange.remotePage.items.map(frontier => ({\n conversationId: frontier.conversationId,\n originNodeId: frontier.originNodeId,\n })),\n { signal: this.activeSignal },\n );\n const localByKey = new Map(localForRemote.map(frontier => [\n versionVectorKey(frontier.conversationId, frontier.originNodeId),\n frontier.maxContiguousOriginSequence,\n ]));\n const missingForLocal = exchange.remotePage.items.flatMap(frontier => {\n const current = localByKey.get(versionVectorKey(\n frontier.conversationId,\n frontier.originNodeId,\n )) ?? 0;\n return frontier.maxContiguousOriginSequence > current\n ? [{\n conversationId: frontier.conversationId,\n originNodeId: frontier.originNodeId,\n fromExclusive: current,\n toInclusive: frontier.maxContiguousOriginSequence,\n }]\n : [];\n });\n this.assertScopedRanges(missingForLocal, peer.nodeId);\n const pullComplete = await this.pullEventsFromPeer(\n peer,\n missingForLocal,\n attachmentPeers,\n budget,\n );\n if (!pullComplete) {\n this.saveContinuation(peer.nodeId, { localAfter, remoteAfter, localDone, remoteDone });\n return false;\n }\n\n localAfter = localPage.nextCursor;\n remoteAfter = exchange.remotePage.nextCursor;\n localDone = localDone || localAfter === undefined;\n remoteDone = remoteDone || remoteAfter === undefined;\n } while (!localDone || !remoteDone);\n this.continuations.delete(peer.nodeId);\n this.pendingAttachmentPushes.delete(peer.nodeId);\n return true;\n }\n\n private async pushEventsToPeer(\n peer: ChatSyncPeer,\n ranges: VersionRange[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n if (ranges.length === 0) return true;\n if (!peer.pushEvents || !this.storage.getConversationEventPage) return false;\n try {\n const rangesByConversation = groupRangesByConversation(ranges);\n const coverage = createCoverageProgress(ranges);\n const pushedHashes = new Set<string>();\n const pendingPushes = this.pendingAttachmentPushes.get(peer.nodeId) ?? new Set<string>();\n this.pendingAttachmentPushes.set(peer.nodeId, pendingPushes);\n let batch: ConversationEvent[] = [];\n const flush = async (): Promise<void> => {\n if (batch.length === 0) return;\n const flushed = batch;\n await peer.pushEvents!(flushed, { signal: this.activeSignal });\n for (const event of flushed) {\n for (const attachment of conversationEventAttachmentReferences(event)) {\n pendingPushes.delete(`${event.conversationId}\\u0000${attachment.contentHash}`);\n }\n }\n batch = [];\n };\n\n for (const [conversationId, conversationRanges] of rangesByConversation) {\n let cursor: ConversationEventCursor | undefined;\n do {\n this.throwIfAborted();\n if (!consumeWorkPages(budget, 1)) {\n await flush();\n return false;\n }\n const page = await this.storage.getConversationEventPage(conversationId, {\n limit: EVENT_PAGE_MAX_ITEMS,\n after: cursor,\n direction: 'forward',\n signal: this.activeSignal,\n ranges: conversationRanges.map(range => ({\n originNodeId: range.originNodeId,\n fromExclusive: range.fromExclusive,\n toInclusive: range.toInclusive,\n })),\n });\n this.assertValidStoredEventPage(page, conversationId, cursor);\n for (const event of page.items) {\n if (!consumeWorkEvent(budget, event)) {\n await flush();\n return false;\n }\n const range = conversationRanges.find(candidate => eventInRange(event, candidate));\n if (!range) continue;\n recordObservedSequence(coverage, event);\n for (const attachment of conversationEventAttachmentReferences(event)) {\n const attachmentKey = `${conversationId}\\u0000${attachment.contentHash}`;\n if (pushedHashes.has(attachmentKey) || pendingPushes.has(attachmentKey)) continue;\n if (!await this.pushAttachmentToPeer(peer, conversationId, attachment, budget)) {\n await flush();\n return false;\n }\n pushedHashes.add(attachmentKey);\n pendingPushes.add(attachmentKey);\n }\n\n const candidate = [...batch, event];\n if (candidate.length > EVENT_PAGE_MAX_ITEMS || jsonByteLength(candidate) > EVENT_PUSH_PAGE_MAX_BYTES) {\n if (batch.length === 0) throw new Error('sync_event_too_large');\n await flush();\n batch = [event];\n if (jsonByteLength(batch) > EVENT_PUSH_PAGE_MAX_BYTES) {\n throw new Error('sync_event_too_large');\n }\n } else {\n batch = candidate;\n }\n }\n cursor = page.hasMoreAfter ? page.endCursor : undefined;\n } while (cursor !== undefined);\n }\n await flush();\n return rangesHaveExactCoverage(coverage);\n } catch (error) {\n this.throwIfAborted();\n if (this.failOnMessageSyncError) throw error;\n return false;\n }\n }\n\n private async pullEventsFromPeer(\n peer: ChatSyncPeer,\n ranges: VersionRange[],\n attachmentPeers: ChatSyncPeer[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n if (ranges.length === 0) return true;\n if (!peer.pullMissingEvents || !this.storage.insertEventsIfAbsent) return false;\n try {\n const rangesByConversation = groupRangesByConversation(ranges);\n let coverage = createCoverageProgress(ranges);\n for (const [conversationId, conversationRanges] of rangesByConversation) {\n let cursor: ConversationEventCursor | undefined;\n do {\n this.throwIfAborted();\n if (!consumeWorkPages(budget, 1)) return false;\n const page = await peer.pullMissingEvents(\n conversationId,\n conversationRanges,\n cursor,\n { signal: this.activeSignal },\n );\n this.assertValidEventPage(page, conversationId, conversationRanges, cursor, peer.nodeId);\n assertCanonicalConversationEvents(page.items);\n const candidateCoverage = cloneCoverageProgress(coverage);\n const acceptedEvents: ConversationEvent[] = [];\n for (const event of page.items) {\n if (!consumeWorkEvent(budget, event)) break;\n recordObservedSequence(candidateCoverage, event);\n acceptedEvents.push(event);\n }\n // BLOBs land before their referencing event. A failed or corrupt BLOB\n // therefore cannot leak into the durable frontier on a later retry.\n if (!await this.ensureAttachmentsFromEvents(acceptedEvents, attachmentPeers, budget)) {\n return false;\n }\n if (acceptedEvents.length > 0) {\n await this.storage.insertEventsIfAbsent(acceptedEvents);\n }\n coverage = candidateCoverage;\n if (acceptedEvents.length !== page.items.length) return false;\n cursor = page.nextCursor;\n } while (cursor !== undefined);\n }\n return rangesHaveExactCoverage(coverage);\n } catch (error) {\n this.throwIfAborted();\n if (this.failOnMessageSyncError) throw error;\n return false;\n }\n }\n\n private async ensureAttachmentsFromEvents(\n events: ConversationEvent[],\n peers: ChatSyncPeer[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n const references = new Map<string, { conversationId: string; reference: AttachmentReference }>();\n for (const event of events) {\n for (const reference of conversationEventAttachmentReferences(event)) {\n references.set(`${event.conversationId}\\u0000${reference.contentHash}`, {\n conversationId: event.conversationId,\n reference,\n });\n }\n }\n for (const { conversationId, reference } of references.values()) {\n if (await this.hasLocalAttachment(reference)) continue;\n if (\n !this.storage.stageAttachmentChunk || !this.storage.commitStagedAttachment ||\n reference.size > MAX_SYNC_ATTACHMENT_BYTES\n ) return false;\n const capablePeers = peers.filter(peer => peer.pullAttachmentChunk !== undefined);\n if (capablePeers.length === 0) return false;\n if (!reserveAttachmentWork(budget, reference.size)) return false;\n let fetched = false;\n for (const peer of capablePeers) {\n const pull = peer.pullAttachmentChunk?.bind(peer);\n if (!pull) continue;\n try {\n let offset = 0;\n while (offset <= reference.size) {\n this.throwIfAborted();\n const chunk = await pull(\n conversationId,\n reference.contentHash,\n offset,\n MAX_SYNC_ATTACHMENT_CHUNK_BYTES,\n { signal: this.activeSignal },\n );\n if (\n !chunk || chunk.offset !== offset || chunk.totalSize !== reference.size ||\n chunk.filename !== reference.filename || chunk.mimeType !== reference.mimeType ||\n chunk.data.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n chunk.done !== (offset + chunk.data.byteLength === reference.size) ||\n (!chunk.done && chunk.data.byteLength === 0)\n ) {\n throw new Error('invalid_sync_attachment_chunk');\n }\n const nextOffset = await this.storage.stageAttachmentChunk(\n reference,\n offset,\n chunk.data,\n { signal: this.activeSignal },\n );\n this.throwIfAborted();\n if (\n !Number.isSafeInteger(nextOffset) || nextOffset !== offset + chunk.data.byteLength ||\n nextOffset > reference.size\n ) {\n throw new Error('sync_attachment_cursor_mismatch');\n }\n offset = nextOffset;\n if (offset === reference.size) {\n await this.storage.commitStagedAttachment(\n reference.contentHash,\n { signal: this.activeSignal },\n );\n this.throwIfAborted();\n fetched = await this.hasLocalAttachment(reference);\n break;\n }\n }\n } catch {\n this.throwIfAborted();\n // Another authorized peer may still have the content-addressed body.\n }\n if (fetched) break;\n }\n if (!fetched) return false;\n }\n return true;\n }\n\n private async hasLocalAttachment(reference: AttachmentReference): Promise<boolean> {\n const stored = await this.storage.getAttachment(reference.contentHash);\n return stored !== null && stored.size === reference.size && stored.filename === reference.filename &&\n stored.mimeType === reference.mimeType && this.storage.verifyAttachment !== undefined &&\n await this.storage.verifyAttachment(reference.contentHash, { signal: this.activeSignal });\n }\n\n private async pushAttachmentToPeer(\n peer: ChatSyncPeer,\n conversationId: string,\n reference: AttachmentReference,\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n if (\n !peer.pushAttachmentChunk || !this.storage.readAttachmentRange ||\n reference.size > MAX_SYNC_ATTACHMENT_BYTES || !await this.hasLocalAttachment(reference)\n ) {\n return false;\n }\n if (!reserveAttachmentWork(budget, reference.size)) return false;\n let offset = 0;\n while (offset <= reference.size) {\n this.throwIfAborted();\n const data = await this.storage.readAttachmentRange(\n reference.contentHash,\n offset,\n MAX_SYNC_ATTACHMENT_CHUNK_BYTES,\n { signal: this.activeSignal },\n );\n this.throwIfAborted();\n if (\n !data || data.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n offset + data.byteLength > reference.size ||\n (data.byteLength === 0 && offset !== reference.size)\n ) return false;\n const done = offset + data.byteLength === reference.size;\n await peer.pushAttachmentChunk(\n conversationId,\n reference.contentHash,\n {\n data,\n offset,\n totalSize: reference.size,\n done,\n filename: reference.filename,\n mimeType: reference.mimeType,\n },\n { signal: this.activeSignal },\n );\n offset += data.byteLength;\n if (done) return true;\n }\n return false;\n }\n\n private assertValidEventPage(\n page: ConversationEventSyncPage,\n conversationId: string,\n ranges: VersionRange[],\n previousCursor: ConversationEventCursor | undefined,\n peerId: string,\n ): void {\n if (\n !isPlainRecord(page) || !hasOnlyKeys(page, ['items', 'nextCursor']) ||\n !Array.isArray(page.items) || page.items.length > EVENT_PAGE_MAX_ITEMS\n ) {\n throw new Error(`invalid_event_sync_page:${peerId}`);\n }\n assertBoundedCanonicalEventBytes(page.items, `invalid_event_sync_page:${peerId}`);\n let lastCursor = previousCursor;\n for (const event of page.items) {\n try {\n assertCanonicalConversationEvent(event);\n assertAdmittedConversationMessageEvent(event);\n } catch {\n throw new Error(`invalid_event_sync_item:${peerId}`);\n }\n if (\n event.conversationId !== conversationId ||\n !ranges.some(range => eventInRange(event, range))\n ) {\n throw new Error(`invalid_event_sync_item:${peerId}`);\n }\n const currentCursor = eventCursor(event);\n if (lastCursor && compareEventCursor(currentCursor, lastCursor) <= 0) {\n throw new Error(`invalid_event_sync_order:${peerId}`);\n }\n lastCursor = currentCursor;\n }\n if (page.nextCursor === undefined) return;\n if (!isConversationEventCursor(page.nextCursor)) throw new Error(`invalid_event_sync_cursor:${peerId}`);\n if (previousCursor && compareEventCursor(page.nextCursor, previousCursor) <= 0) {\n throw new Error(`event_sync_cursor_did_not_advance:${peerId}`);\n }\n const lastItem = page.items.at(-1);\n if (!lastItem || compareEventCursor(page.nextCursor, eventCursor(lastItem)) !== 0) {\n throw new Error(`event_sync_cursor_not_last_item:${peerId}`);\n }\n }\n\n private assertValidStoredEventPage(\n page: StoredConversationEventPage,\n conversationId: string,\n previousCursor: ConversationEventCursor | undefined,\n ): void {\n if (\n !isPlainRecord(page) || !hasOnlyKeys(page, [\n 'items',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startCursor',\n 'endCursor',\n ]) || !Array.isArray(page.items) || page.items.length > EVENT_PAGE_MAX_ITEMS ||\n typeof page.hasMoreBefore !== 'boolean' || typeof page.hasMoreAfter !== 'boolean' ||\n page.items.some(event => {\n try {\n assertCanonicalConversationEvent(event);\n assertAdmittedConversationMessageEvent(event);\n return event.conversationId !== conversationId;\n } catch {\n return true;\n }\n })\n ) {\n throw new Error('invalid_storage_event_page');\n }\n assertBoundedCanonicalEventBytes(page.items, 'invalid_storage_event_page');\n let lastCursor = previousCursor;\n for (const event of page.items) {\n const currentCursor = eventCursor(event);\n if (lastCursor && compareEventCursor(currentCursor, lastCursor) <= 0) {\n throw new Error('invalid_storage_event_order');\n }\n lastCursor = currentCursor;\n }\n if (!page.hasMoreAfter) return;\n if (\n page.items.length === 0 || !page.endCursor || !isConversationEventCursor(page.endCursor) ||\n previousCursor && compareEventCursor(page.endCursor, previousCursor) <= 0 ||\n lastCursor && compareEventCursor(page.endCursor, lastCursor) !== 0\n ) {\n throw new Error('storage_event_cursor_did_not_advance');\n }\n }\n\n public getStorage(): IAgentStorage {\n return this.storage;\n }\n\n private assertScopedRanges(ranges: VersionRange[], peerId: string): void {\n if (this.conversationIds === undefined) return;\n const allowed = new Set(this.conversationIds);\n if (ranges.some(range => !allowed.has(range.conversationId))) {\n throw new Error(`sync_peer_scope_escalation:${peerId}`);\n }\n }\n\n private assertValidFrontierPage(\n page: MessageVersionFrontierPage,\n previous: MessageVersionFrontierCursor | undefined,\n source: string,\n expectedEmpty = false,\n ): void {\n if (\n !isPlainRecord(page) || !hasOnlyKeys(page, ['items', 'nextCursor']) ||\n !Array.isArray(page.items) || page.items.length > FRONTIER_PAGE_MAX_ITEMS ||\n expectedEmpty && (page.items.length > 0 || page.nextCursor !== undefined)\n ) {\n throw new Error(`invalid_sync_frontier_page:${source}`);\n }\n let last = previous;\n for (const frontier of page.items) {\n if (!isValidFrontier(frontier)) throw new Error(`invalid_sync_frontier:${source}`);\n const cursor = { conversationId: frontier.conversationId, originNodeId: frontier.originNodeId };\n if (last && compareFrontierCursor(cursor, last) <= 0) {\n throw new Error(`invalid_sync_frontier_order:${source}`);\n }\n last = cursor;\n }\n if (page.nextCursor === undefined) return;\n if (\n !last || !isValidFrontierCursor(page.nextCursor) ||\n compareFrontierCursor(page.nextCursor, last) !== 0 ||\n previous && compareFrontierCursor(page.nextCursor, previous) <= 0\n ) {\n throw new Error(`sync_frontier_cursor_did_not_advance:${source}`);\n }\n }\n\n private saveContinuation(peerId: string, continuation: PeerSyncContinuation): void {\n this.continuations.set(peerId, {\n localDone: continuation.localDone,\n remoteDone: continuation.remoteDone,\n ...(continuation.localAfter ? { localAfter: { ...continuation.localAfter } } : {}),\n ...(continuation.remoteAfter ? { remoteAfter: { ...continuation.remoteAfter } } : {}),\n });\n }\n\n private collectPeers(): ChatSyncPeer[] {\n const unique = new Map<string, ChatSyncPeer>();\n for (const peer of this.getPeers()) {\n if (!isValidSyncIdentifier(peer.nodeId)) throw new Error('invalid_sync_peer_id');\n if (peer.nodeId === this.nodeId || unique.has(peer.nodeId)) continue;\n unique.set(peer.nodeId, peer);\n }\n return [...unique.values()].sort((left, right) => compareCodeUnits(left.nodeId, right.nodeId));\n }\n\n private garbageCollectPeerState(activePeerIds: ReadonlySet<string>): void {\n for (const peerId of this.continuations.keys()) {\n if (!activePeerIds.has(peerId)) this.continuations.delete(peerId);\n }\n for (const peerId of this.pendingAttachmentPushes.keys()) {\n if (!activePeerIds.has(peerId)) this.pendingAttachmentPushes.delete(peerId);\n }\n if (this.nextPeerAfter !== undefined && !activePeerIds.has(this.nextPeerAfter)) {\n this.nextPeerAfter = undefined;\n }\n }\n\n private throwIfAborted(): void {\n if (!this.activeSignal?.aborted) return;\n throw this.activeSignal.reason instanceof Error\n ? this.activeSignal.reason\n : new Error('chat_sync_aborted');\n }\n}\n\nfunction assertAdmittedConversationMessageEvent(event: ConversationEvent): void {\n if (event.kind !== 'message') return;\n const message = {\n ...event.message,\n conversationId: event.conversationId,\n originNodeId: event.originNodeId,\n originSequence: event.originSequence,\n lamportClock: event.lamportClock,\n timestamp: event.timestamp,\n };\n if (event.message.role === 'user') assertAgentUserMessageWithinLimits(message);\n else assertConversationMessageWithinPagingLimits(message);\n}\n\nfunction isValidFrontier(value: unknown): value is MessageVersionFrontier {\n if (\n !isPlainRecord(value) || !hasOnlyKeys(value, [\n 'conversationId',\n 'originNodeId',\n 'maxContiguousOriginSequence',\n ])\n ) return false;\n const frontier = value as Partial<MessageVersionFrontier>;\n return isValidSyncIdentifier(frontier.conversationId) &&\n isValidSyncIdentifier(frontier.originNodeId) &&\n typeof frontier.maxContiguousOriginSequence === 'number' &&\n Number.isSafeInteger(frontier.maxContiguousOriginSequence) &&\n frontier.maxContiguousOriginSequence > 0;\n}\n\nfunction isValidVersionRanges(value: unknown): value is VersionRange[] {\n if (!Array.isArray(value) || value.length > FRONTIER_PAGE_MAX_ITEMS) return false;\n const identities = new Set<string>();\n for (const item of value) {\n if (\n !isPlainRecord(item) || !hasOnlyKeys(item, [\n 'conversationId',\n 'originNodeId',\n 'fromExclusive',\n 'toInclusive',\n ])\n ) return false;\n const range = item as Partial<VersionRange>;\n if (\n !isValidSyncIdentifier(range.conversationId) ||\n !isValidSyncIdentifier(range.originNodeId) ||\n typeof range.fromExclusive !== 'number' || !Number.isSafeInteger(range.fromExclusive) ||\n range.fromExclusive < 0 || typeof range.toInclusive !== 'number' ||\n !Number.isSafeInteger(range.toInclusive) || range.toInclusive <= range.fromExclusive\n ) return false;\n const key = versionVectorKey(range.conversationId, range.originNodeId);\n if (identities.has(key)) return false;\n identities.add(key);\n }\n return true;\n}\n\nfunction rangesMatchOfferedFrontiers(\n ranges: VersionRange[],\n frontiers: MessageVersionFrontier[],\n): boolean {\n const offered = new Map(frontiers.map(frontier => [\n versionVectorKey(frontier.conversationId, frontier.originNodeId),\n frontier.maxContiguousOriginSequence,\n ]));\n return ranges.every(range => offered.get(versionVectorKey(range.conversationId, range.originNodeId)) === range.toInclusive);\n}\n\nfunction isValidFrontierCursor(value: unknown): value is MessageVersionFrontierCursor {\n if (!isPlainRecord(value) || !hasOnlyKeys(value, ['conversationId', 'originNodeId'])) return false;\n const cursor = value as Partial<MessageVersionFrontierCursor>;\n return isValidSyncIdentifier(cursor.conversationId) &&\n isValidSyncIdentifier(cursor.originNodeId);\n}\n\nfunction compareFrontierCursor(\n left: MessageVersionFrontierCursor,\n right: MessageVersionFrontierCursor,\n): number {\n return compareUtf8Bytes(left.conversationId, right.conversationId) ||\n compareUtf8Bytes(left.originNodeId, right.originNodeId);\n}\n\nfunction resolvePassLimits(input: Partial<ChatSyncPassLimits> | undefined): ChatSyncPassLimits {\n const limits: ChatSyncPassLimits = {\n maxPeers: input?.maxPeers ?? MAX_SYNC_PEERS_PER_PASS,\n maxFrontierPages: input?.maxFrontierPages ?? MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS,\n maxPages: input?.maxPages ?? MAX_SYNC_WORK_PAGES_PER_PEER_PASS,\n maxEvents: input?.maxEvents ?? MAX_SYNC_EVENTS_PER_PEER_PASS,\n maxBytes: input?.maxBytes ?? MAX_SYNC_BYTES_PER_PEER_PASS,\n };\n const hardLimits: ChatSyncPassLimits = {\n maxPeers: MAX_SYNC_PEERS_PER_PASS,\n maxFrontierPages: MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS,\n maxPages: MAX_SYNC_WORK_PAGES_PER_PEER_PASS,\n maxEvents: MAX_SYNC_EVENTS_PER_PEER_PASS,\n maxBytes: MAX_SYNC_BYTES_PER_PEER_PASS,\n };\n for (const key of Object.keys(limits) as Array<keyof ChatSyncPassLimits>) {\n if (!Number.isSafeInteger(limits[key]) || limits[key] <= 0 || limits[key] > hardLimits[key]) {\n throw new Error(`invalid_sync_pass_limit:${key}`);\n }\n }\n return limits;\n}\n\nfunction createSyncPassWorkBudget(limits: ChatSyncPassLimits): SyncPassWorkBudget {\n return { frontierPages: 0, pages: 0, events: 0, bytes: 0, exhausted: false, limits };\n}\n\nfunction createPeerSyncWorkBudget(global: SyncPassWorkBudget): PeerSyncWorkBudget {\n return { frontierPages: 0, pages: 0, events: 0, bytes: 0, exhausted: false, global };\n}\n\nfunction consumeFrontierScanPage(budget: PeerSyncWorkBudget): boolean {\n if (\n budget.frontierPages + 1 > MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS ||\n budget.global.frontierPages + 1 > budget.global.limits.maxFrontierPages\n ) {\n budget.exhausted = true;\n if (budget.global.frontierPages + 1 > budget.global.limits.maxFrontierPages) {\n budget.global.exhausted = true;\n }\n return false;\n }\n budget.frontierPages += 1;\n budget.global.frontierPages += 1;\n return true;\n}\n\nfunction consumeWorkPages(budget: PeerSyncWorkBudget, count: number): boolean {\n if (\n budget.pages + count > MAX_SYNC_WORK_PAGES_PER_PEER_PASS ||\n budget.global.pages + count > budget.global.limits.maxPages\n ) {\n budget.exhausted = true;\n if (budget.global.pages + count > budget.global.limits.maxPages) budget.global.exhausted = true;\n return false;\n }\n budget.pages += count;\n budget.global.pages += count;\n return true;\n}\n\nfunction consumeWorkEvent(budget: PeerSyncWorkBudget, event: ConversationEvent): boolean {\n const bytes = canonicalConversationEventBytes(event).byteLength;\n if (\n budget.events + 1 > MAX_SYNC_EVENTS_PER_PEER_PASS ||\n budget.bytes + bytes > MAX_SYNC_BYTES_PER_PEER_PASS ||\n budget.global.events + 1 > budget.global.limits.maxEvents ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) {\n budget.exhausted = true;\n if (\n budget.global.events + 1 > budget.global.limits.maxEvents ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) budget.global.exhausted = true;\n return false;\n }\n budget.events += 1;\n budget.bytes += bytes;\n budget.global.events += 1;\n budget.global.bytes += bytes;\n return true;\n}\n\nfunction reserveAttachmentWork(budget: PeerSyncWorkBudget, bytes: number): boolean {\n const chunks = Math.max(1, Math.ceil(bytes / MAX_SYNC_ATTACHMENT_CHUNK_BYTES));\n if (\n budget.pages + chunks > MAX_SYNC_WORK_PAGES_PER_PEER_PASS ||\n budget.bytes + bytes > MAX_SYNC_BYTES_PER_PEER_PASS ||\n budget.global.pages + chunks > budget.global.limits.maxPages ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) {\n budget.exhausted = true;\n if (\n budget.global.pages + chunks > budget.global.limits.maxPages ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) budget.global.exhausted = true;\n return false;\n }\n budget.pages += chunks;\n budget.bytes += bytes;\n budget.global.pages += chunks;\n budget.global.bytes += bytes;\n return true;\n}\n\nfunction rotatePeers(peers: ChatSyncPeer[], after: string | undefined): ChatSyncPeer[] {\n if (peers.length === 0 || after === undefined) return peers;\n const start = peers.findIndex(peer => compareCodeUnits(peer.nodeId, after) > 0);\n if (start < 0) return peers;\n return [...peers.slice(start), ...peers.slice(0, start)];\n}\n\nfunction groupRangesByConversation(ranges: VersionRange[]): Map<string, VersionRange[]> {\n const grouped = new Map<string, VersionRange[]>();\n for (const range of ranges) {\n const values = grouped.get(range.conversationId) ?? [];\n values.push(range);\n grouped.set(range.conversationId, values);\n }\n return grouped;\n}\n\nfunction eventInRange(event: ConversationEvent, range: VersionRange): boolean {\n return event.conversationId === range.conversationId &&\n event.originNodeId === range.originNodeId &&\n event.originSequence > range.fromExclusive &&\n event.originSequence <= range.toInclusive;\n}\n\ninterface CoverageProgress {\n nextExpected: number;\n toInclusive: number;\n}\n\nfunction createCoverageProgress(ranges: VersionRange[]): Map<string, CoverageProgress> {\n const coverage = new Map<string, CoverageProgress>();\n for (const range of ranges) {\n const key = versionVectorKey(range.conversationId, range.originNodeId);\n if (coverage.has(key)) throw new Error('sync_duplicate_version_range');\n coverage.set(key, {\n nextExpected: range.fromExclusive + 1,\n toInclusive: range.toInclusive,\n });\n }\n return coverage;\n}\n\nfunction cloneCoverageProgress(\n coverage: Map<string, CoverageProgress>,\n): Map<string, CoverageProgress> {\n return new Map([...coverage].map(([key, value]) => [key, { ...value }]));\n}\n\nfunction recordObservedSequence(\n coverage: Map<string, CoverageProgress>,\n event: ConversationEvent,\n): void {\n const key = versionVectorKey(event.conversationId, event.originNodeId);\n const progress = coverage.get(key);\n if (!progress || event.originSequence !== progress.nextExpected) {\n throw new Error('sync_non_contiguous_origin_sequence');\n }\n progress.nextExpected += 1;\n}\n\nfunction rangesHaveExactCoverage(\n coverage: Map<string, CoverageProgress>,\n): boolean {\n return [...coverage.values()].every(progress => progress.nextExpected === progress.toInclusive + 1);\n}\n\nfunction isConversationEventCursor(value: unknown): value is ConversationEventCursor {\n if (\n !isPlainRecord(value) || !hasOnlyKeys(value, [\n 'originNodeId',\n 'originSequence',\n 'eventId',\n ])\n ) return false;\n const cursor = value as Partial<ConversationEventCursor>;\n return isValidSyncIdentifier(cursor.originNodeId) &&\n typeof cursor.originSequence === 'number' && Number.isSafeInteger(cursor.originSequence) &&\n cursor.originSequence > 0 && isValidSyncIdentifier(cursor.eventId);\n}\n\nfunction eventCursor(event: ConversationEvent): ConversationEventCursor {\n return {\n originNodeId: event.originNodeId,\n originSequence: event.originSequence,\n eventId: event.eventId,\n };\n}\n\nfunction compareEventCursor(left: ConversationEventCursor, right: ConversationEventCursor): number {\n return compareUtf8Bytes(left.originNodeId, right.originNodeId) ||\n left.originSequence - right.originSequence ||\n compareUtf8Bytes(left.eventId, right.eventId);\n}\n\n/** Matches SQLite's default BINARY ordering used by the production event index. */\nfunction compareUtf8Bytes(left: string, right: string): number {\n if (left === right) return 0;\n const leftBytes = utf8Encoder.encode(left);\n const rightBytes = utf8Encoder.encode(right);\n const length = Math.min(leftBytes.length, rightBytes.length);\n for (let index = 0; index < length; index += 1) {\n const difference = leftBytes[index] - rightBytes[index];\n if (difference !== 0) return difference;\n }\n return leftBytes.length - rightBytes.length;\n}\n\nfunction compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction jsonByteLength(events: readonly ConversationEvent[]): number {\n return canonicalEventArrayBytes(events);\n}\n\nfunction canonicalEventArrayBytes(events: readonly ConversationEvent[]): number {\n let bytes = 2 + Math.max(0, events.length - 1);\n for (const event of events) bytes += canonicalConversationEventBytes(event).byteLength;\n return bytes;\n}\n\nfunction assertBoundedCanonicalEventBytes(\n events: readonly ConversationEvent[],\n errorCode: string,\n): void {\n if (canonicalEventArrayBytes(events) > EVENT_PUSH_PAGE_MAX_BYTES) throw new Error(errorCode);\n}\n\nfunction isValidSyncIdentifier(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 &&\n utf8Encoder.encode(value).byteLength <= MAX_SYNC_ID_LENGTH &&\n !Array.from(value).some(character => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 31 || codePoint === 127;\n });\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n try {\n const prototype = Object.getPrototypeOf(value) as object | null;\n return prototype === Object.prototype || prototype === null;\n } catch {\n return false;\n }\n}\n\nfunction hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {\n const keys = new Set(allowed);\n return Object.keys(value).every(key => keys.has(key));\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport type { AttachmentChunk } from '../device-network/types.js';\nimport type { MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from '../storage/ports.js';\nimport type { ConversationEventSyncPage, VersionRange } from './protocol.js';\n\nimport type { ChatSyncPeer, SyncIoOptions } from './chatSyncEngine.js';\n\nexport interface PeerNodeTransport {\n nodeId: string;\n exchangeVersionFrontierPage(\n targetNodeId: string,\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<{\n remotePage: MessageVersionFrontierPage;\n missingForRemote: VersionRange[];\n }>;\n pullMissingEvents?(\n targetNodeId: string,\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage>;\n\n /** 从指定节点拉取附件 BLOB(如 `memeloop.storage.getAttachmentBlob`)。 */\n pullAttachmentChunk?(\n targetNodeId: string,\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<AttachmentChunk | null>;\n pushEvents?(\n targetNodeId: string,\n events: ConversationEvent[],\n options?: SyncIoOptions,\n ): Promise<void>;\n pushAttachmentChunk?(\n targetNodeId: string,\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void>;\n}\n\nexport class PeerNodeSyncAdapter implements ChatSyncPeer {\n public readonly nodeId: string;\n private readonly transport: PeerNodeTransport;\n\n constructor(nodeId: string, transport: PeerNodeTransport) {\n this.nodeId = nodeId;\n this.transport = transport;\n }\n\n exchangeVersionFrontierPage(\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ) {\n return this.transport.exchangeVersionFrontierPage(\n this.nodeId,\n localFrontiers,\n remoteAfter,\n includeRemotePage,\n conversationIds,\n options,\n );\n }\n\n pullMissingEvents(\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage> {\n const function_ = this.transport.pullMissingEvents?.bind(this.transport);\n if (!function_) {\n return Promise.reject(new Error('Peer transport does not support event synchronization'));\n }\n return function_(this.nodeId, conversationId, ranges, cursor, options);\n }\n\n pullAttachmentChunk(\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ) {\n const function_ = this.transport.pullAttachmentChunk?.bind(this.transport);\n if (!function_) {\n return Promise.resolve(null);\n }\n return function_(this.nodeId, conversationId, contentHash, offset, maxBytes, options);\n }\n\n pushEvents(events: ConversationEvent[], options?: SyncIoOptions): Promise<void> {\n const function_ = this.transport.pushEvents?.bind(this.transport);\n if (!function_) return Promise.reject(new Error('Peer transport does not support event push'));\n return function_(this.nodeId, events, options);\n }\n\n pushAttachmentChunk(\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void> {\n const function_ = this.transport.pushAttachmentChunk?.bind(this.transport);\n if (!function_) return Promise.reject(new Error('Peer transport does not support attachment push'));\n return function_(this.nodeId, conversationId, contentHash, chunk, options);\n }\n}\n"],"mappings":"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","names":["assertExactKeys","asRecord","assertIdentifier","fail","asRecord","assertOnlyKeys","assertIdentifier","fail","value","assertArray","optionalBoolean","assertAttachmentReference","hasOnlyKeys","text","isRecord","assertExactKeys","copied","throwIfAborted","hasOnlyKeys","hasOnlyKeys","containsAsciiControlOrSpace","peerId","throwIfAborted","utf8Encoder","compareCodeUnits","candidate","jsonByteLength","hasOnlyKeys"]}
|
|
1
|
+
{"version":3,"sources":["../src/device-network-portable.ts","../src/encoding/canonicalJson.ts","../src/storage/conversationPaging.ts","../src/conversation/compactionBoundary.ts","../src/conversation/events.ts","../src/runState.ts","../src/userMessageAdmission.ts","../src/device-network/attachmentUpload.ts","../src/device-network/scheduledTaskRpc.ts","../src/device-network/agentDeviceRpc.ts","../src/device-network/agentDeviceRpcClient.ts","../src/device-network/deviceGrantMessages.ts","../src/device-network/cloudDeviceFetchClient.ts","../src/device-network/deviceCloudConnectionCoordinator.ts","../src/device-network/deviceHeartbeat.ts","../src/orchestration/errors.ts","../src/device-network/jsonFrame.ts","../src/device-network/deviceOrchestrationTransport.ts","../src/device-network/libp2pSyncProtocol.ts","../src/device-network/libp2pDeviceSyncTransport.ts","../src/device-network/libp2pRpcProtocol.ts","../src/device-network/localTrustDeviceAuthorizer.ts","../src/device-network/mutableDeviceAuthorizer.ts","../src/device-network/pairingInvite.ts","../src/device-network/reconcileCloudDeviceDirectory.ts","../src/device-network/standardDeviceCloudConnectionAdapter.ts","../src/device-network/types.ts","../src/sync/attachmentRpcCodec.ts","../src/sync/protocol.ts","../src/sync/chatSyncEngine.ts","../src/sync/peerNodeAdapter.ts"],"sourcesContent":["/**\n * Browser and React Native-safe device networking surface.\n *\n * Host adapters, orchestration controllers, and deployable script loading are\n * deliberately excluded from this graph.\n */\nexport { assertCanonicalConversationEvents, canonicalConversationEventBytes, conversationEventAttachmentReferences, isConversationEvent } from './conversation/events.js';\nexport type { ConversationEvent, ConversationEventCursor } from './conversation/events.js';\nexport * from './device-network/agentDeviceRpc.js';\nexport * from './device-network/agentDeviceRpcClient.js';\nexport * from './device-network/attachmentUpload.js';\nexport * from './device-network/cloudDeviceFetchClient.js';\nexport * from './device-network/deviceCloudConnectionCoordinator.js';\nexport * from './device-network/deviceGrantMessages.js';\nexport * from './device-network/deviceHeartbeat.js';\nexport * from './device-network/deviceOrchestrationTransport.js';\nexport * from './device-network/jsonFrame.js';\nexport * from './device-network/libp2pDeviceSyncTransport.js';\nexport * from './device-network/libp2pRpcProtocol.js';\nexport * from './device-network/libp2pSyncProtocol.js';\nexport * from './device-network/localTrustDeviceAuthorizer.js';\nexport * from './device-network/mutableDeviceAuthorizer.js';\nexport * from './device-network/pairingInvite.js';\nexport * from './device-network/reconcileCloudDeviceDirectory.js';\nexport * from './device-network/scheduledTaskRpc.js';\nexport * from './device-network/standardDeviceCloudConnectionAdapter.js';\nexport * from './device-network/types.js';\nexport type { ConversationEventPage, MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from './storage/ports.js';\nexport { decodeAttachmentBlobRpc } from './sync/attachmentRpcCodec.js';\nexport * from './sync/chatSyncEngine.js';\nexport * from './sync/peerNodeAdapter.js';\nexport * from './sync/protocol.js';\nexport type { IAgentStorage } from './types.js';\n","/** Resource bounds enforced while traversing and encoding canonical JSON. */\nexport interface CanonicalJsonLimits {\n /** Root is depth zero; every nested array/object member increments depth. */\n maxDepth: number;\n /** Counts every JSON value and every object key. */\n maxNodes: number;\n /** Per string/key bound checked before JSON escaping allocates an encoded copy. */\n maxStringCodeUnits: number;\n /** Per string/key UTF-8 bound. */\n maxStringBytes: number;\n /** Maximum UTF-8 bytes in the final canonical representation. */\n maxBytes: number;\n}\n\nexport const DEFAULT_CANONICAL_JSON_LIMITS: Readonly<CanonicalJsonLimits> = Object.freeze({\n maxDepth: 64,\n maxNodes: 100_000,\n maxStringCodeUnits: 1_048_576,\n maxStringBytes: 1_048_576,\n maxBytes: 1_048_576,\n});\n\nexport type CanonicalJsonErrorCode =\n | 'accessor_property'\n | 'array_property'\n | 'cycle'\n | 'dangerous_key'\n | 'invalid_unicode'\n | 'invalid_limit'\n | 'invalid_number'\n | 'max_bytes'\n | 'max_depth'\n | 'max_nodes'\n | 'max_string_bytes'\n | 'max_string_code_units'\n | 'non_enumerable_property'\n | 'non_plain_object'\n | 'sparse_array'\n | 'symbol_property'\n | 'unsupported_type';\n\n/** Stable fail-closed error surfaced by every canonical JSON entry point. */\nexport class CanonicalJsonError extends Error {\n public constructor(public readonly code: CanonicalJsonErrorCode, cause?: unknown) {\n super(`canonical_json_${code}`, cause === undefined ? undefined : { cause });\n this.name = 'CanonicalJsonError';\n }\n}\n\nconst DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\nconst ARRAY_INDEX = /^(?:0|[1-9]\\d*)$/u;\nconst LIMIT_KEYS = [\n 'maxDepth',\n 'maxNodes',\n 'maxStringCodeUnits',\n 'maxStringBytes',\n 'maxBytes',\n] as const satisfies ReadonlyArray<keyof CanonicalJsonLimits>;\nconst LIMIT_KEY_SET: ReadonlySet<string> = new Set(LIMIT_KEYS);\n\n/** Encode strict JSON with object keys sorted by UTF-16 code-unit order. */\nexport function canonicalJsonString(\n value: unknown,\n limits?: Partial<CanonicalJsonLimits>,\n): string {\n return new CanonicalJsonEncoder(resolveLimits(limits)).encode(value);\n}\n\n/** UTF-8 bytes of {@link canonicalJsonString}. */\nexport function canonicalJsonBytes(\n value: unknown,\n limits?: Partial<CanonicalJsonLimits>,\n): Uint8Array {\n return new TextEncoder().encode(canonicalJsonString(value, limits));\n}\n\n/**\n * Encode an unambiguous domain-separated envelope. Both the domain and payload\n * are JSON values inside `{\"domain\":...,\"payload\":...}`; no delimiter can be\n * injected to make two `(domain, payload)` pairs share bytes.\n */\nexport function domainSeparatedCanonicalJsonBytes(\n domain: string,\n payload: unknown,\n limits?: Partial<CanonicalJsonLimits>,\n): Uint8Array {\n if (typeof domain !== 'string' || domain.length === 0) {\n throw new CanonicalJsonError('unsupported_type');\n }\n return canonicalJsonBytes({ domain, payload }, limits);\n}\n\nclass CanonicalJsonEncoder {\n private readonly chunks: string[] = [];\n private readonly activeObjects = new Set<object>();\n private bytes = 0;\n private nodes = 0;\n\n public constructor(private readonly limits: CanonicalJsonLimits) {}\n\n public encode(value: unknown): string {\n this.writeValue(value, 0);\n return this.chunks.join('');\n }\n\n private writeValue(value: unknown, depth: number): void {\n if (depth > this.limits.maxDepth) this.fail('max_depth');\n this.consumeNode();\n if (value === null) {\n this.append('null');\n return;\n }\n switch (typeof value) {\n case 'string':\n this.writeString(value);\n return;\n case 'boolean':\n this.append(value ? 'true' : 'false');\n return;\n case 'number':\n this.writeNumber(value);\n return;\n case 'object':\n this.writeStructuredValue(value, depth);\n return;\n default:\n this.fail('unsupported_type');\n }\n }\n\n private writeNumber(value: number): void {\n if (!Number.isFinite(value) || (Number.isInteger(value) && !Number.isSafeInteger(value))) {\n this.fail('invalid_number');\n }\n this.append(JSON.stringify(value));\n }\n\n private writeString(value: string): void {\n const rawBytes = this.assertStringBounds(value);\n // JSON string encoding never uses fewer bytes than the raw valid UTF-8\n // plus its two quotes. Reject before JSON.stringify allocates an escaped\n // copy when even that lower bound cannot fit.\n if (rawBytes + 2 > this.limits.maxBytes - this.bytes) this.fail('max_bytes');\n this.append(JSON.stringify(value));\n }\n\n private writeStructuredValue(value: object, depth: number): void {\n this.withActiveObject(value, () => {\n let isArray: boolean;\n try {\n isArray = Array.isArray(value);\n } catch (error) {\n throw new CanonicalJsonError('non_plain_object', error);\n }\n if (isArray) this.writeArray(value as unknown[], depth);\n else this.writeObject(value, depth);\n });\n }\n\n private writeArray(value: unknown[], depth: number): void {\n if (this.readPrototype(value) !== Array.prototype) this.fail('non_plain_object');\n const properties = this.readProperties(value);\n const lengthProperty = properties.find(([key]) => key === 'length')?.[1];\n if (\n !lengthProperty || 'get' in lengthProperty || 'set' in lengthProperty ||\n !('value' in lengthProperty) || lengthProperty.enumerable ||\n typeof lengthProperty.value !== 'number' || !Number.isSafeInteger(lengthProperty.value) ||\n lengthProperty.value < 0\n ) this.fail('array_property');\n const length = lengthProperty.value;\n if (length > this.limits.maxNodes) this.fail('max_nodes');\n this.assertMinimumArrayBytes(length);\n const values = new Map<number, unknown>();\n for (const [key, descriptor] of properties) {\n if (key === 'length') continue;\n this.assertStringBounds(key);\n if (!ARRAY_INDEX.test(key)) this.fail('array_property');\n const index = Number(key);\n if (!Number.isSafeInteger(index) || index < 0 || index >= length) {\n this.fail('array_property');\n }\n this.assertDataProperty(descriptor);\n values.set(index, descriptor.value);\n }\n if (values.size !== length) this.fail('sparse_array');\n\n this.append('[');\n for (let index = 0; index < length; index += 1) {\n if (index > 0) this.append(',');\n this.writeValue(values.get(index), depth + 1);\n }\n this.append(']');\n }\n\n private writeObject(value: object, depth: number): void {\n const prototype = this.readPrototype(value);\n if (prototype !== Object.prototype && prototype !== null) this.fail('non_plain_object');\n const properties = this.readProperties(value);\n const entries: Array<[key: string, value: unknown, encodedKey: string]> = [];\n let minimumBytes = 2;\n for (const [key, descriptor] of properties) {\n if (DANGEROUS_KEYS.has(key)) this.fail('dangerous_key');\n this.consumeNode();\n const rawKeyBytes = this.assertStringBounds(key);\n this.assertDataProperty(descriptor);\n const entrySyntaxBytes = entries.length === 0 ? 2 : 3;\n minimumBytes = this.addMinimumBytes(\n minimumBytes,\n rawKeyBytes + 2 + entrySyntaxBytes,\n );\n const encodedKey = JSON.stringify(key);\n // One comma after the first entry, one colon, and at least one byte for\n // the value. This prevents sorting a huge key set that cannot possibly\n // fit in the configured output bound.\n const escapedExtraBytes = utf8ByteLength(encodedKey) - (rawKeyBytes + 2);\n minimumBytes = this.addMinimumBytes(minimumBytes, escapedExtraBytes);\n entries.push([key, descriptor.value, encodedKey]);\n }\n entries.sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0);\n\n this.append('{');\n entries.forEach(([, item, encodedKey], index) => {\n if (index > 0) this.append(',');\n this.append(encodedKey);\n this.append(':');\n this.writeValue(item, depth + 1);\n });\n this.append('}');\n }\n\n private readPrototype(value: object): object | null {\n try {\n return Object.getPrototypeOf(value) as object | null;\n } catch (error) {\n throw new CanonicalJsonError('non_plain_object', error);\n }\n }\n\n private readProperties(value: object): Array<[string, PropertyDescriptor]> {\n let keys: Array<string | symbol>;\n try {\n keys = Reflect.ownKeys(value);\n } catch (error) {\n throw new CanonicalJsonError('non_plain_object', error);\n }\n if (keys.length > this.limits.maxNodes + 1) this.fail('max_nodes');\n if (keys.some(key => typeof key === 'symbol')) this.fail('symbol_property');\n return keys.map((key) => {\n let descriptor: PropertyDescriptor | undefined;\n try {\n descriptor = Object.getOwnPropertyDescriptor(value, key);\n } catch (error) {\n throw new CanonicalJsonError('non_plain_object', error);\n }\n if (!descriptor) this.fail('non_plain_object');\n return [key as string, descriptor];\n });\n }\n\n private assertDataProperty(descriptor: PropertyDescriptor): asserts descriptor is PropertyDescriptor & {\n value: unknown;\n } {\n if ('get' in descriptor || 'set' in descriptor) this.fail('accessor_property');\n if (!descriptor.enumerable) this.fail('non_enumerable_property');\n if (!('value' in descriptor)) this.fail('accessor_property');\n }\n\n private withActiveObject(value: object, operation: () => void): void {\n if (this.activeObjects.has(value)) this.fail('cycle');\n this.activeObjects.add(value);\n try {\n operation();\n } finally {\n this.activeObjects.delete(value);\n }\n }\n\n private assertStringBounds(value: string): number {\n if (value.length > this.limits.maxStringCodeUnits) {\n this.fail('max_string_code_units');\n }\n const bytes = strictUtf8ByteLength(value, () => this.fail('invalid_unicode'));\n if (bytes > this.limits.maxStringBytes) {\n this.fail('max_string_bytes');\n }\n return bytes;\n }\n\n private assertMinimumArrayBytes(length: number): void {\n const remaining = this.limits.maxBytes - this.bytes;\n if (length === 0) {\n if (remaining < 2) this.fail('max_bytes');\n return;\n }\n // `[0]` is the shortest non-empty array and every additional value costs\n // at least one comma plus one value byte: 2 * length + 1.\n if (remaining < 1 || length > Math.floor((remaining - 1) / 2)) {\n this.fail('max_bytes');\n }\n }\n\n private addMinimumBytes(current: number, additional: number): number {\n const remaining = this.limits.maxBytes - this.bytes;\n if (current > remaining || additional > remaining - current) this.fail('max_bytes');\n return current + additional;\n }\n\n private consumeNode(): void {\n this.nodes += 1;\n if (this.nodes > this.limits.maxNodes) this.fail('max_nodes');\n }\n\n private append(value: string): void {\n const valueBytes = utf8ByteLength(value);\n if (valueBytes > this.limits.maxBytes - this.bytes) this.fail('max_bytes');\n this.bytes += valueBytes;\n this.chunks.push(value);\n }\n\n private fail(code: CanonicalJsonErrorCode): never {\n throw new CanonicalJsonError(code);\n }\n}\n\nfunction resolveLimits(overrides?: Partial<CanonicalJsonLimits>): CanonicalJsonLimits {\n const limits: CanonicalJsonLimits = { ...DEFAULT_CANONICAL_JSON_LIMITS };\n if (overrides === undefined) return limits;\n if (overrides === null || typeof overrides !== 'object') {\n throw new CanonicalJsonError('invalid_limit');\n }\n let prototype: object | null;\n let keys: Array<string | symbol>;\n try {\n prototype = Object.getPrototypeOf(overrides) as object | null;\n keys = Reflect.ownKeys(overrides);\n } catch (error) {\n throw new CanonicalJsonError('invalid_limit', error);\n }\n if (prototype !== Object.prototype && prototype !== null) {\n throw new CanonicalJsonError('invalid_limit');\n }\n for (const key of keys) {\n if (typeof key !== 'string' || !LIMIT_KEY_SET.has(key)) {\n throw new CanonicalJsonError('invalid_limit');\n }\n let descriptor: PropertyDescriptor | undefined;\n try {\n descriptor = Object.getOwnPropertyDescriptor(overrides, key);\n } catch (error) {\n throw new CanonicalJsonError('invalid_limit', error);\n }\n if (\n !descriptor || 'get' in descriptor || 'set' in descriptor ||\n !descriptor.enumerable || !('value' in descriptor) ||\n !Number.isSafeInteger(descriptor.value) || descriptor.value < 0\n ) {\n throw new CanonicalJsonError('invalid_limit');\n }\n limits[key as keyof CanonicalJsonLimits] = descriptor.value as number;\n }\n return limits;\n}\n\nfunction utf8ByteLength(value: string): number {\n let bytes = 0;\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 0x7f) {\n bytes += 1;\n } else if (code <= 0x7ff) {\n bytes += 2;\n } else if (code >= 0xd800 && code <= 0xdbff) {\n const next = value.charCodeAt(index + 1);\n if (next >= 0xdc00 && next <= 0xdfff) {\n bytes += 4;\n index += 1;\n } else {\n bytes += 3;\n }\n } else {\n bytes += 3;\n }\n }\n return bytes;\n}\n\nfunction strictUtf8ByteLength(value: string, invalidUnicode: () => never): number {\n let bytes = 0;\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 0x7f) {\n bytes += 1;\n } else if (code <= 0x7ff) {\n bytes += 2;\n } else if (code >= 0xd800 && code <= 0xdbff) {\n if (index + 1 >= value.length) invalidUnicode();\n const next = value.charCodeAt(index + 1);\n if (next < 0xdc00 || next > 0xdfff) invalidUnicode();\n bytes += 4;\n index += 1;\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n invalidUnicode();\n } else {\n bytes += 3;\n }\n }\n return bytes;\n}\n","import {\n assertCanonicalChatMessageProjection,\n assertCanonicalConversationEvent,\n type ConversationEvent,\n conversationEventToMessage,\n type ConversationMessageEvent,\n} from '../conversation/events.js';\nimport type { ChatMessage } from '../conversation/types.js';\nimport { canonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type {\n ConversationEventStore,\n ConversationMessageCursor,\n ConversationMessagePage,\n ConversationMessagePageSuccess,\n ConversationMessageWindowResult,\n ConversationMessageWindowSuccess,\n ConversationReadCallOptions,\n ConversationTimelineCompactionEntry,\n ConversationTimelineEntry,\n ConversationTimelinePage,\n ConversationTimelinePageCallOptions,\n ConversationTimelinePageSuccess,\n ConversationTimelineParticipantPreview,\n ConversationTimelineTurnEntry,\n GetConversationMessageWindowAroundOptions,\n GetConversationTimelinePageOptions,\n GetMessagePageOptions,\n} from './ports.js';\n\n/** One shared interactive row ceiling across local, RPC, browser, and native hosts. */\nexport const DEFAULT_MESSAGE_PAGE_SIZE = 50;\nexport const MAX_MESSAGE_PAGE_SIZE = 50;\nexport const MAX_CONVERSATION_TIMELINE_PAGE_SIZE = 50;\n/** Opening or navigating a conversation never transfers a multi-megabyte page. */\nexport const MAX_CONVERSATION_TIMELINE_PAGE_BYTES = 256 * 1_024;\nexport const MAX_CONVERSATION_TIMELINE_PREVIEW_LENGTH = 240;\nexport const MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS = 4;\nexport const MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH = 160;\nexport const MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS_BYTES = 1_024;\nexport const MAX_CONVERSATION_TIMELINE_TURN_ENTRY_BYTES = 1_024;\nexport const MAX_CONVERSATION_MESSAGE_WINDOW_SIZE = 50;\nexport const MAX_CONVERSATION_MESSAGE_WINDOW_BYTES = 256 * 1_024;\n\nexport type ConversationMessageListProjection =\n & Omit<\n ChatMessage,\n 'parts' | 'toolCalls' | 'attachments' | 'reasoning_content'\n >\n & {\n parts?: never;\n toolCalls?: never;\n attachments?: never;\n reasoning_content?: never;\n };\n\nexport interface ConversationMessageDisplayTruncation {\n truncated: true;\n originalCharacterCount: number;\n originalEstimatedBytes: number;\n originalEstimatedRenderRows: number;\n contentTruncated: boolean;\n omittedFields: Array<'parts' | 'toolCalls' | 'attachments' | 'reasoning_content'>;\n capability: 'detail' | 'export';\n}\n\n/**\n * The single portable on-demand/list projector used by storage and RPC hosts.\n * It never retains heavy structured fields, preserves detailRef/agentRunError,\n * and fits the complete canonical projection within the caller's byte budget.\n */\nexport function projectConversationMessageForList(\n message: ChatMessage,\n maximumBytes: number,\n): ConversationMessageListProjection {\n if (!Number.isSafeInteger(maximumBytes) || maximumBytes < 1) {\n throw new Error('invalid_conversation_message_projection_byte_budget');\n }\n const {\n attachments,\n parts,\n reasoning_content: reasoningContent,\n toolCalls,\n ...lightweight\n } = message;\n const omittedFields: ConversationMessageDisplayTruncation['omittedFields'] = [\n ...(parts === undefined ? [] : ['parts' as const]),\n ...(toolCalls === undefined ? [] : ['toolCalls' as const]),\n ...(attachments === undefined ? [] : ['attachments' as const]),\n ...(reasoningContent === undefined ? [] : ['reasoning_content' as const]),\n ];\n const originalBytes = new TextEncoder().encode(message.content).byteLength;\n let originalCharacters = 0;\n for (const _character of message.content) originalCharacters += 1;\n let originalRows = 1;\n for (let index = 0; index < message.content.length; index += 1) {\n if (message.content.charCodeAt(index) === 10) originalRows += 1;\n }\n const marker = (contentTruncated: boolean): ConversationMessageDisplayTruncation => ({\n truncated: true,\n originalCharacterCount: originalCharacters,\n originalEstimatedBytes: originalBytes,\n originalEstimatedRenderRows: originalRows,\n contentTruncated,\n omittedFields,\n capability: 'detail',\n });\n const metadata = omittedFields.length === 0\n ? message.metadata\n : { ...message.metadata, displayTruncation: marker(false) };\n const initial: ConversationMessageListProjection = {\n ...lightweight,\n ...(metadata === undefined ? {} : { metadata }),\n };\n if (conversationMessageProjectionFits(initial, maximumBytes)) return initial;\n\n const agentRunError = message.metadata?.agentRunError;\n const fallbackMetadata = {\n ...(agentRunError === undefined ? {} : { agentRunError }),\n displayTruncation: marker(true),\n };\n const base: ConversationMessageListProjection = {\n ...lightweight,\n content: '',\n metadata: fallbackMetadata,\n };\n if (!conversationMessageProjectionFits(base, maximumBytes)) {\n throw new Error('conversation_message_projection_item_exceeds_byte_budget');\n }\n const encoded = new TextEncoder().encode(message.content);\n let lower = 0;\n let upper = encoded.byteLength;\n let best = '';\n while (lower <= upper) {\n const middle = Math.floor((lower + upper) / 2);\n const content = utf8ProjectionPrefix(encoded, middle);\n const candidate = { ...base, content };\n if (conversationMessageProjectionFits(candidate, maximumBytes)) {\n best = content;\n lower = middle + 1;\n } else {\n upper = middle - 1;\n }\n }\n return { ...base, content: best };\n}\n\nfunction conversationMessageProjectionFits(value: unknown, maximumBytes: number): boolean {\n try {\n canonicalJsonBytes(value, {\n maxBytes: maximumBytes,\n maxDepth: 32,\n maxNodes: 10_000,\n maxStringBytes: maximumBytes,\n maxStringCodeUnits: maximumBytes,\n });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction utf8ProjectionPrefix(encoded: Uint8Array, maximumBytes: number): string {\n const decoder = new TextDecoder('utf-8', { fatal: true });\n for (let end = Math.min(maximumBytes, encoded.byteLength); end >= Math.max(0, maximumBytes - 3); end -= 1) {\n try {\n return decoder.decode(encoded.subarray(0, end));\n } catch {\n // Only a partial trailing code point can fail; UTF-8 code points are at most four bytes.\n }\n }\n return '';\n}\n\nexport function messageCursor(message: ChatMessage): ConversationMessageCursor {\n return {\n timestamp: message.timestamp,\n lamportClock: message.lamportClock,\n originNodeId: message.originNodeId,\n messageId: message.messageId,\n };\n}\n\nexport function compareMessageCursor(\n left: ConversationMessageCursor,\n right: ConversationMessageCursor,\n): number {\n return left.timestamp - right.timestamp ||\n left.lamportClock - right.lamportClock ||\n compareUtf8Text(left.originNodeId, right.originNodeId) ||\n compareUtf8Text(left.messageId, right.messageId);\n}\n\n/**\n * SQLite's default BINARY collation compares UTF-8 bytes. Comparing Unicode\n * code points gives the same order for valid strings and, unlike\n * `localeCompare`, is independent of the host locale.\n */\nfunction compareUtf8Text(left: string, right: string): number {\n const leftIterator = left[Symbol.iterator]();\n const rightIterator = right[Symbol.iterator]();\n for (;;) {\n const leftItem = leftIterator.next();\n const rightItem = rightIterator.next();\n if (leftItem.done || rightItem.done) {\n if (leftItem.done && rightItem.done) return 0;\n return leftItem.done ? -1 : 1;\n }\n const difference = leftItem.value.codePointAt(0)! - rightItem.value.codePointAt(0)!;\n if (difference !== 0) return difference;\n }\n}\n\nexport function normalizeMessagePageLimit(limit: number): number {\n if (!Number.isSafeInteger(limit) || limit <= 0) return DEFAULT_MESSAGE_PAGE_SIZE;\n return Math.min(limit, MAX_MESSAGE_PAGE_SIZE);\n}\n\n/** Read a bounded page from a storage host without any full-history fallback. */\nexport async function readConversationMessagePage(\n storage: ConversationEventStore,\n conversationId: string,\n options: GetMessagePageOptions,\n callOptions: ConversationReadCallOptions = {},\n): Promise<ConversationMessagePage> {\n const normalized = { ...options, limit: normalizeMessagePageLimit(options.limit) };\n assertMessagePageOptions(normalized);\n callOptions.signal?.throwIfAborted();\n const result = await storage.getMessagePage(conversationId, normalized, callOptions);\n callOptions.signal?.throwIfAborted();\n assertConversationMessagePage(result, conversationId, normalized);\n return result;\n}\n\n/** O(n) memory-host helper; persistent hosts select the same window transactionally. */\nexport function buildConversationMessagePage(\n sourceMessages: readonly ChatMessage[],\n conversationId: string,\n options: GetMessagePageOptions,\n currentRevision: string,\n): ConversationMessagePage {\n assertMessagePageOptions(options);\n assertOpaqueTimelineValue(currentRevision, 'revision');\n if (options.expectedRevision !== undefined && options.expectedRevision !== currentRevision) {\n return { reset: true, conversationId, revision: currentRevision };\n }\n const messages = sourceMessages\n .filter(message => message.conversationId === conversationId)\n .sort((left, right) => compareMessageCursor(messageCursor(left), messageCursor(right)));\n let start = 0;\n let end = messages.length;\n if (options.before) {\n const index = messages.findIndex(message => compareMessageCursor(messageCursor(message), options.before!) === 0);\n if (index < 0) return { reset: true, conversationId, revision: currentRevision };\n end = index;\n start = Math.max(0, end - options.limit);\n } else if (options.after) {\n const index = messages.findIndex(message => compareMessageCursor(messageCursor(message), options.after!) === 0);\n if (index < 0) return { reset: true, conversationId, revision: currentRevision };\n start = index + 1;\n end = Math.min(messages.length, start + options.limit);\n } else {\n start = Math.max(0, messages.length - options.limit);\n }\n const projectOnDemand = options.mode === 'on-demand' || options.mode === 'metadata-only';\n let items = messages.slice(start, end).map(message =>\n projectOnDemand\n ? projectConversationMessageForList(message, Math.max(1, options.maxBytes - 4_096))\n : message\n );\n let result = messagePageSuccess(conversationId, currentRevision, messages.length, start, items);\n while (!messageWindowFits(result, options.maxBytes)) {\n if (items.length <= 1) throw new Error('conversation_message_page_exceeds_byte_budget');\n if (options.after) items = items.slice(0, -1);\n else {\n items = items.slice(1);\n start += 1;\n }\n result = messagePageSuccess(conversationId, currentRevision, messages.length, start, items);\n }\n assertConversationMessagePage(result, conversationId, options);\n return result;\n}\n\nfunction messagePageSuccess(\n conversationId: string,\n revision: string,\n total: number,\n start: number,\n items: ChatMessage[],\n): ConversationMessagePageSuccess {\n const first = items[0];\n const last = items.at(-1);\n return {\n reset: false,\n conversationId,\n revision,\n items,\n hasMoreBefore: start > 0,\n hasMoreAfter: start + items.length < total,\n ...(first ? { startCursor: messageCursor(first) } : {}),\n ...(last ? { endCursor: messageCursor(last) } : {}),\n };\n}\n\nfunction assertMessagePageOptions(options: GetMessagePageOptions): void {\n if (\n !options ||\n !Number.isSafeInteger(options.limit) ||\n options.limit < 1 ||\n options.limit > MAX_MESSAGE_PAGE_SIZE ||\n !Number.isSafeInteger(options.maxBytes) ||\n options.maxBytes < 1 ||\n options.maxBytes > MAX_CONVERSATION_MESSAGE_WINDOW_BYTES ||\n (options.before !== undefined && options.after !== undefined)\n ) throw new Error('invalid_conversation_message_page_options');\n if ((options.before || options.after) && options.expectedRevision === undefined) {\n throw new Error('conversation_message_cursor_requires_revision');\n }\n if (options.expectedRevision !== undefined) {\n assertOpaqueTimelineValue(options.expectedRevision, 'expected_revision');\n }\n}\n\nexport function assertConversationMessagePage(\n value: unknown,\n conversationId: string,\n options: GetMessagePageOptions,\n): asserts value is ConversationMessagePage {\n assertMessagePageOptions(options);\n if (!messageWindowFits(value, options.maxBytes) || value === null || typeof value !== 'object') {\n throw new Error('invalid_conversation_message_page');\n }\n const result = value as ConversationMessagePage;\n if (result.conversationId !== conversationId || !isNonEmptyText(result.revision)) {\n throw new Error('invalid_conversation_message_page_scope');\n }\n if (result.reset) {\n assertWindowExactKeys(result, ['reset', 'conversationId', 'revision']);\n if (options.expectedRevision === undefined) {\n throw new Error('invalid_conversation_message_page_reset');\n }\n return;\n }\n assertWindowExactKeys(result, [\n 'reset',\n 'conversationId',\n 'revision',\n 'items',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startCursor',\n 'endCursor',\n ]);\n if (\n result.reset ||\n (options.expectedRevision !== undefined && result.revision !== options.expectedRevision) ||\n !Array.isArray(result.items) ||\n result.items.length > options.limit ||\n typeof result.hasMoreBefore !== 'boolean' ||\n typeof result.hasMoreAfter !== 'boolean'\n ) throw new Error('invalid_conversation_message_page');\n for (let index = 0; index < result.items.length; index += 1) {\n assertWindowMessage(result.items[index], conversationId);\n if (\n index > 0 &&\n compareMessageCursor(messageCursor(result.items[index - 1]), messageCursor(result.items[index])) >= 0\n ) throw new Error('invalid_conversation_message_page_order');\n }\n const first = result.items[0];\n const last = result.items.at(-1);\n if (\n (first && (!result.startCursor || compareMessageCursor(result.startCursor, messageCursor(first)) !== 0)) ||\n (last && (!result.endCursor || compareMessageCursor(result.endCursor, messageCursor(last)) !== 0)) ||\n (!first && (result.startCursor !== undefined || result.endCursor !== undefined ||\n result.hasMoreBefore || result.hasMoreAfter))\n ) throw new Error('invalid_conversation_message_page_cursor');\n}\n\n/** Strict bounded list/live projection; structured heavy fields are detail-only. */\nexport function assertConversationMessageProjection(\n value: unknown,\n conversationId?: string,\n): asserts value is ChatMessage {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('invalid_conversation_message_projection');\n }\n const message = value as ChatMessage;\n assertWindowExactKeys(message, [\n 'messageId',\n 'turnId',\n 'conversationId',\n 'originNodeId',\n 'originSequence',\n 'timestamp',\n 'lamportClock',\n 'role',\n 'content',\n 'detailRef',\n 'contentType',\n 'hidden',\n 'duration',\n 'metadata',\n ]);\n try {\n assertCanonicalChatMessageProjection(message, conversationId);\n } catch (error) {\n throw new Error('invalid_conversation_message_projection', { cause: error });\n }\n}\n\nfunction preview(content: string, maxLength: number): string {\n let lineStart = 0;\n while (lineStart <= content.length) {\n const newline = content.indexOf('\\n', lineStart);\n const lineEnd = newline < 0 ? content.length : newline;\n let start = lineStart;\n while (start < lineEnd && isPreviewWhitespace(content[start])) start += 1;\n let end = lineEnd;\n while (end > start && isPreviewWhitespace(content[end - 1])) end -= 1;\n if (end > start) {\n const length = end - start;\n if (length <= maxLength) return content.slice(start, end);\n if (maxLength === 1) return '…';\n let prefixEnd = start + maxLength - 1;\n const previous = content.charCodeAt(prefixEnd - 1);\n const next = content.charCodeAt(prefixEnd);\n if (\n previous >= 0xD800 && previous <= 0xDBFF &&\n next >= 0xDC00 && next <= 0xDFFF\n ) prefixEnd -= 1;\n return `${content.slice(start, prefixEnd)}…`;\n }\n if (newline < 0) break;\n lineStart = newline + 1;\n }\n return '';\n}\n\nfunction timelineParticipantPreview(\n message: ConversationMessageEvent['message'],\n originNodeId: string,\n requestedPreviewLength: number,\n): ConversationTimelineParticipantPreview {\n if (message.role !== 'assistant' && message.role !== 'agent') {\n throw new Error('invalid_conversation_timeline_participant_role');\n }\n const metadata = message.metadata;\n const actorId = boundedParticipantIdentity(\n metadataText(metadata, 'actorId') ?? metadataText(metadata, 'agentId') ?? originNodeId,\n );\n const actorLabel = boundedParticipantIdentity(\n metadataText(metadata, 'actorLabel') ?? metadataText(metadata, 'agentName') ?? actorId,\n );\n return {\n actorId,\n actorLabel,\n role: message.role,\n preview: preview(\n message.content,\n Math.min(requestedPreviewLength, MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH),\n ),\n };\n}\n\nfunction metadataText(\n metadata: Readonly<Record<string, unknown>> | undefined,\n key: string,\n): string | undefined {\n const value = metadata?.[key];\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction boundedParticipantIdentity(value: string): string {\n return preview(value, 64) || 'unknown';\n}\n\nfunction boundedParticipantPreviewSample(\n responses: readonly ConversationTimelineParticipantPreview[],\n): ConversationTimelineParticipantPreview[] {\n const sample = responses.length <= MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS\n ? [...responses]\n : [...responses.slice(0, 2), ...responses.slice(-2)];\n return sample;\n}\n\nfunction participantPreviewsFit(value: unknown): boolean {\n try {\n canonicalJsonBytes(value, {\n maxBytes: MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS_BYTES,\n maxDepth: 4,\n maxNodes: 64,\n maxStringBytes: MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS_BYTES,\n maxStringCodeUnits: MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS_BYTES,\n });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function boundConversationTimelineTurnEntry(\n source: ConversationTimelineTurnEntry,\n): ConversationTimelineTurnEntry {\n const entry: ConversationTimelineTurnEntry = {\n ...source,\n participantPreviews: source.participantPreviews.map(item => ({\n actorId: preview(item.actorId, MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH),\n actorLabel: preview(item.actorLabel, MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH),\n role: item.role,\n preview: preview(item.preview, MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH),\n })),\n };\n while (\n !timelineTurnEntryFits(entry) &&\n entry.participantPreviews.some(item => item.preview.length > 1)\n ) {\n entry.participantPreviews = entry.participantPreviews.map(item => ({\n ...item,\n preview: preview(item.preview, Math.max(1, Math.floor(item.preview.length / 2))),\n }));\n }\n while (\n !timelineTurnEntryFits(entry) &&\n entry.participantPreviews.some(item => item.actorId.length > 16 || item.actorLabel.length > 16)\n ) {\n entry.participantPreviews = entry.participantPreviews.map(item => ({\n ...item,\n actorId: preview(item.actorId, Math.max(16, Math.floor(item.actorId.length / 2))),\n actorLabel: preview(item.actorLabel, Math.max(16, Math.floor(item.actorLabel.length / 2))),\n }));\n }\n while (!timelineTurnEntryFits(entry) && entry.userPreview.length > 1) {\n entry.userPreview = preview(entry.userPreview, Math.max(1, Math.floor(entry.userPreview.length / 2)));\n }\n if (!timelineTurnEntryFits(entry)) {\n throw new Error('conversation_timeline_turn_entry_exceeds_byte_budget');\n }\n return entry;\n}\n\nfunction timelineTurnEntryFits(value: unknown): boolean {\n try {\n canonicalJsonBytes(value, {\n maxBytes: MAX_CONVERSATION_TIMELINE_TURN_ENTRY_BYTES,\n maxDepth: 6,\n maxNodes: 128,\n maxStringBytes: MAX_CONVERSATION_TIMELINE_TURN_ENTRY_BYTES,\n maxStringCodeUnits: MAX_CONVERSATION_TIMELINE_TURN_ENTRY_BYTES,\n });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction assertTimelineParticipantPreview(value: unknown): asserts value is ConversationTimelineParticipantPreview {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('invalid_conversation_timeline_participant_preview');\n }\n const participant = value as ConversationTimelineParticipantPreview;\n assertExactKeys(participant, ['actorId', 'actorLabel', 'role', 'preview'], 'participant_preview');\n if (\n !isNonEmptyText(participant.actorId) ||\n participant.actorId.length > MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH ||\n !isNonEmptyText(participant.actorLabel) ||\n participant.actorLabel.length > MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH ||\n (participant.role !== 'assistant' && participant.role !== 'agent') ||\n typeof participant.preview !== 'string' ||\n participant.preview.length > MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEW_LENGTH\n ) throw new Error('invalid_conversation_timeline_participant_preview');\n}\n\nfunction isPreviewWhitespace(value: string): boolean {\n return value.trim().length === 0;\n}\n\nfunction normalizeTimelinePreviewLength(requested: number | undefined): number {\n return Math.max(\n 1,\n Math.min(\n Number.isSafeInteger(requested) ? requested! : 96,\n MAX_CONVERSATION_TIMELINE_PREVIEW_LENGTH,\n ),\n );\n}\n\n/** Read the required revisioned projection with no getMessages fallback. */\nexport async function readConversationTimelinePage(\n storage: ConversationEventStore,\n conversationId: string,\n options: GetConversationTimelinePageOptions,\n callOptions: ConversationTimelinePageCallOptions = {},\n): Promise<ConversationTimelinePage> {\n assertTimelinePageOptions(options);\n callOptions.signal?.throwIfAborted();\n if (typeof storage.getConversationTimelinePage !== 'function') {\n throw new Error('conversation timeline page reader unavailable');\n }\n const page = await storage.getConversationTimelinePage(conversationId, options, callOptions);\n callOptions.signal?.throwIfAborted();\n assertConversationTimelinePage(page, conversationId, options);\n return page;\n}\n\n/** Explicit full-array builder for memory-only hosts; currentRevision is host-owned. */\nexport function buildConversationTimelinePage(\n sourceEvents: readonly ConversationEvent[],\n conversationId: string,\n options: GetConversationTimelinePageOptions,\n currentRevision: string,\n): ConversationTimelinePage {\n assertTimelinePageOptions(options);\n assertOpaqueTimelineValue(currentRevision, 'revision');\n if (\n options.expectedRevision !== undefined &&\n options.expectedRevision !== currentRevision\n ) return boundedTimelineReset(currentRevision, options.maxBytes);\n\n const materialized = materializeTimeline(\n sourceEvents,\n conversationId,\n normalizeTimelinePreviewLength(options.previewLength),\n );\n const { entries, messageEvents, totalTurns: turnIndex } = materialized;\n const range = timelinePageRange(entries, options);\n if (range === null) return boundedTimelineReset(currentRevision, options.maxBytes);\n let items = entries.slice(range.start, range.end);\n let page = timelineSuccessPage(items, messageEvents.length, turnIndex, entries.length, currentRevision, range);\n while (!timelinePageFits(page, options.maxBytes)) {\n if (items.length === 0) throw new Error('conversation_timeline_page_exceeds_byte_budget');\n items = trimTimelineItems(items, options);\n if (items.length === 0) throw new Error('conversation_timeline_entry_exceeds_byte_budget');\n page = timelineSuccessPage(items, messageEvents.length, turnIndex, entries.length, currentRevision, range);\n }\n assertConversationTimelinePage(page, conversationId, options);\n return page;\n}\n\ninterface MaterializedTimeline {\n events: ConversationEvent[];\n messageEvents: ConversationMessageEvent[];\n entries: ConversationTimelineEntry[];\n totalTurns: number;\n}\n\nfunction materializeTimeline(\n sourceEvents: readonly ConversationEvent[],\n conversationId: string,\n previewLength: number,\n): MaterializedTimeline {\n for (const event of sourceEvents) assertCanonicalConversationEvent(event);\n const events = [...sourceEvents]\n .filter(event => event.conversationId === conversationId)\n .sort(compareTimelineEvents);\n const tombstonedTurnIds = new Set(\n events.filter(event => event.kind === 'tombstone').map(event => event.targetTurnId),\n );\n const messageEvents = events.filter((event): event is ConversationMessageEvent =>\n event.kind === 'message' &&\n event.message.hidden !== true &&\n !tombstonedTurnIds.has(event.message.turnId)\n );\n const visibleMessageEventIds = new Set(messageEvents.map(event => event.eventId));\n const entries: ConversationTimelineEntry[] = [];\n const turnsById = new Map<string, ConversationTimelineTurnEntry>();\n const compactionEventIds = new Set<string>();\n let turnIndex = 0;\n for (const event of events) {\n if (\n event.kind === 'compaction' &&\n event.mode === 'summary' &&\n !tombstonedTurnIds.has(event.summary.turnId) &&\n preview(event.summary.content, previewLength).length > 0\n ) {\n const entry: ConversationTimelineCompactionEntry = {\n kind: 'compaction',\n entryId: event.eventId,\n conversationId,\n timestamp: event.timestamp,\n lamportClock: event.lamportClock,\n originNodeId: event.originNodeId,\n cursor: memoryTimelineCursor(event),\n entryIndex: entries.length,\n turnIndex,\n summaryPreview: preview(event.summary.content, previewLength),\n compactedMessageCount: event.boundary.droppedMessageCount,\n compactedTurnCount: event.boundary.droppedTurnCount,\n };\n entries.push(entry);\n compactionEventIds.add(event.eventId);\n continue;\n }\n if (event.kind !== 'message' || !visibleMessageEventIds.has(event.eventId)) continue;\n const message = event.message;\n if (\n message.role !== 'user' ||\n message.messageId !== message.turnId ||\n turnsById.has(message.turnId)\n ) continue;\n const entry: ConversationTimelineTurnEntry = {\n kind: 'turn',\n entryId: message.messageId,\n messageId: message.messageId,\n conversationId,\n timestamp: event.timestamp,\n lamportClock: event.lamportClock,\n originNodeId: event.originNodeId,\n cursor: memoryTimelineCursor(event),\n entryIndex: entries.length,\n turnIndex,\n turnId: message.turnId,\n userPreview: preview(message.content, previewLength),\n participantPreviews: [],\n responseCount: 0,\n };\n entries.push(entry);\n turnsById.set(message.turnId, entry);\n turnIndex += 1;\n }\n for (const event of messageEvents) {\n const message = event.message;\n if (\n compactionEventIds.has(event.eventId) ||\n (message.role !== 'assistant' && message.role !== 'agent')\n ) continue;\n const entry = turnsById.get(message.turnId);\n if (!entry) continue;\n entry.responseCount += 1;\n entry.participantPreviews.push(timelineParticipantPreview(\n message,\n event.originNodeId,\n previewLength,\n ));\n }\n for (const entry of turnsById.values()) {\n entry.participantPreviews = boundedParticipantPreviewSample(entry.participantPreviews);\n Object.assign(entry, boundConversationTimelineTurnEntry(entry));\n }\n\n return { events, messageEvents, entries, totalTurns: turnIndex };\n}\n\n/** Required single-read wrapper; never composes timeline and message pages client-side. */\nexport async function readConversationMessageWindowAround(\n storage: ConversationEventStore,\n conversationId: string,\n options: GetConversationMessageWindowAroundOptions,\n callOptions: ConversationTimelinePageCallOptions = {},\n): Promise<ConversationMessageWindowResult> {\n assertMessageWindowOptions(options);\n callOptions.signal?.throwIfAborted();\n const result = await storage.getMessageWindowAround(conversationId, options, callOptions);\n callOptions.signal?.throwIfAborted();\n assertConversationMessageWindowResult(result, conversationId, options);\n return result;\n}\n\n/** Explicit O(n) memory-host builder. Persistent hosts use indexed transactional reads. */\nexport function buildConversationMessageWindowAround(\n sourceEvents: readonly ConversationEvent[],\n conversationId: string,\n options: GetConversationMessageWindowAroundOptions,\n currentRevision: string,\n): ConversationMessageWindowResult {\n assertMessageWindowOptions(options);\n assertOpaqueTimelineValue(currentRevision, 'revision');\n if (options.expectedRevision !== currentRevision) {\n const reset = boundedMessageWindowReset(conversationId, currentRevision, options.maxBytes);\n assertConversationMessageWindowResult(reset, conversationId, options);\n return reset;\n }\n const materialized = materializeTimeline(sourceEvents, conversationId, 96);\n const requestedFocus = options.focus;\n const requestedEntry = requestedFocus.kind === 'timeline-entry'\n ? materialized.entries.find(entry => entry.entryId === requestedFocus.entryId && entry.cursor === requestedFocus.cursor)\n : materialized.entries.find(entry =>\n entry.kind === 'turn' &&\n entry.turnId === requestedFocus.turnId &&\n (requestedFocus.cursor === undefined || entry.cursor === requestedFocus.cursor)\n );\n if (!requestedEntry) {\n const reset = boundedMessageWindowReset(conversationId, currentRevision, options.maxBytes);\n assertConversationMessageWindowResult(reset, conversationId, options);\n return reset;\n }\n\n let focus: ConversationMessageWindowSuccess['focus'];\n let anchorTurnId: string | undefined;\n if (requestedEntry.kind === 'turn') {\n anchorTurnId = requestedEntry.turnId;\n focus = {\n kind: 'turn',\n turnId: requestedEntry.turnId,\n ...(options.focus.kind === 'timeline-entry'\n ? { entryId: requestedEntry.entryId, cursor: requestedEntry.cursor }\n : options.focus.cursor === undefined\n ? {}\n : { cursor: requestedEntry.cursor }),\n };\n } else {\n const nearest = nearestTimelineTurn(materialized.entries, requestedEntry.entryIndex);\n anchorTurnId = nearest?.entry.turnId;\n focus = {\n kind: 'compaction',\n entry: requestedEntry,\n ...(nearest\n ? { nearestPosition: nearest.position, nearestTurnId: nearest.entry.turnId }\n : { nearestPosition: 'none' }),\n };\n }\n\n const messages = materialized.messageEvents.map(event =>\n projectConversationMessageForList(\n conversationEventToMessage(event),\n Math.max(1, options.maxBytes - 4_096),\n )\n );\n const anchorIndex = anchorTurnId === undefined\n ? -1\n : messages.findIndex(message => message.turnId === anchorTurnId);\n let start = anchorIndex < 0\n ? 0\n : Math.max(\n 0,\n Math.min(\n anchorIndex - Math.floor(options.maxMessages / 2),\n Math.max(0, messages.length - options.maxMessages),\n ),\n );\n let end = anchorIndex < 0 ? 0 : Math.min(messages.length, start + options.maxMessages);\n let result = messageWindowSuccess(\n conversationId,\n currentRevision,\n focus,\n messages,\n start,\n end,\n );\n while (!messageWindowFits(result, options.maxBytes)) {\n if (end <= start + 1) throw new Error('conversation_message_window_focus_exceeds_byte_budget');\n const distanceBefore = anchorIndex - start;\n const distanceAfter = end - 1 - anchorIndex;\n if (distanceAfter > distanceBefore) end -= 1;\n else start += 1;\n result = messageWindowSuccess(\n conversationId,\n currentRevision,\n focus,\n messages,\n start,\n end,\n );\n }\n assertConversationMessageWindowResult(result, conversationId, options);\n return result;\n}\n\nfunction nearestTimelineTurn(\n entries: readonly ConversationTimelineEntry[],\n focusEntryIndex: number,\n): { entry: ConversationTimelineTurnEntry; position: 'before' | 'after' } | undefined {\n let before: ConversationTimelineTurnEntry | undefined;\n let after: ConversationTimelineTurnEntry | undefined;\n for (let index = focusEntryIndex - 1; index >= 0; index -= 1) {\n const entry = entries[index];\n if (entry?.kind === 'turn') {\n before = entry;\n break;\n }\n }\n for (let index = focusEntryIndex + 1; index < entries.length; index += 1) {\n const entry = entries[index];\n if (entry?.kind === 'turn') {\n after = entry;\n break;\n }\n }\n if (!before) return after ? { entry: after, position: 'after' } : undefined;\n if (!after) return { entry: before, position: 'before' };\n return after.entryIndex - focusEntryIndex <= focusEntryIndex - before.entryIndex\n ? { entry: after, position: 'after' }\n : { entry: before, position: 'before' };\n}\n\nfunction messageWindowSuccess(\n conversationId: string,\n revision: string,\n focus: ConversationMessageWindowSuccess['focus'],\n allMessages: readonly ChatMessage[],\n start: number,\n end: number,\n): ConversationMessageWindowSuccess {\n const items = allMessages.slice(start, end);\n const first = items[0];\n const last = items.at(-1);\n return {\n reset: false,\n conversationId,\n revision,\n focus,\n items,\n hasMoreBefore: start > 0,\n hasMoreAfter: end < allMessages.length,\n ...(first ? { startCursor: messageCursor(first) } : {}),\n ...(last ? { endCursor: messageCursor(last) } : {}),\n };\n}\n\nfunction boundedMessageWindowReset(\n conversationId: string,\n revision: string,\n maxBytes: number,\n): ConversationMessageWindowResult {\n const reset = { reset: true as const, conversationId, revision };\n if (!messageWindowFits(reset, maxBytes)) {\n throw new Error('conversation_message_window_exceeds_byte_budget');\n }\n return reset;\n}\n\nfunction assertMessageWindowOptions(options: GetConversationMessageWindowAroundOptions): void {\n if (\n !options ||\n !Number.isSafeInteger(options.maxMessages) ||\n options.maxMessages < 1 ||\n options.maxMessages > MAX_CONVERSATION_MESSAGE_WINDOW_SIZE\n ) throw new Error('invalid_conversation_message_window_limit');\n if (\n !Number.isSafeInteger(options.maxBytes) ||\n options.maxBytes < 1 ||\n options.maxBytes > MAX_CONVERSATION_MESSAGE_WINDOW_BYTES\n ) throw new Error('invalid_conversation_message_window_byte_budget');\n assertOpaqueTimelineValue(options.expectedRevision, 'expected_revision');\n if (!options.focus || !isNonEmptyText(options.focus.kind)) {\n throw new Error('invalid_conversation_message_window_focus');\n }\n if (options.focus.kind === 'turn') {\n if (!isNonEmptyText(options.focus.turnId)) {\n throw new Error('invalid_conversation_message_window_focus');\n }\n if (options.focus.cursor !== undefined) {\n assertOpaqueTimelineValue(options.focus.cursor, 'focus.cursor');\n }\n return;\n }\n if (\n options.focus.kind !== 'timeline-entry' ||\n !isNonEmptyText(options.focus.entryId)\n ) throw new Error('invalid_conversation_message_window_focus');\n assertOpaqueTimelineValue(options.focus.cursor, 'focus.cursor');\n}\n\nfunction messageWindowFits(value: unknown, maxBytes: number): boolean {\n try {\n canonicalJsonBytes(value, {\n maxBytes,\n maxDepth: 32,\n maxNodes: 100_000,\n maxStringBytes: maxBytes,\n maxStringCodeUnits: maxBytes,\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Strict storage/wire assertion shared by hosts and the device RPC boundary. */\nexport function assertConversationMessageWindowResult(\n value: unknown,\n conversationId: string,\n options: GetConversationMessageWindowAroundOptions,\n): asserts value is ConversationMessageWindowResult {\n assertMessageWindowOptions(options);\n if (!messageWindowFits(value, options.maxBytes)) {\n throw new Error('conversation_message_window_exceeds_byte_budget');\n }\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('invalid_conversation_message_window');\n }\n const result = value as ConversationMessageWindowResult;\n if (result.conversationId !== conversationId) {\n throw new Error('invalid_conversation_message_window_scope');\n }\n assertOpaqueTimelineValue(result.revision, 'message_window_revision');\n if (result.reset) {\n assertWindowExactKeys(result, ['reset', 'conversationId', 'revision']);\n return;\n }\n assertWindowExactKeys(result, [\n 'reset',\n 'conversationId',\n 'revision',\n 'focus',\n 'items',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startCursor',\n 'endCursor',\n ]);\n if (\n result.reset ||\n result.revision !== options.expectedRevision ||\n !Array.isArray(result.items) ||\n result.items.length > options.maxMessages ||\n typeof result.hasMoreBefore !== 'boolean' ||\n typeof result.hasMoreAfter !== 'boolean'\n ) throw new Error('invalid_conversation_message_window');\n const ids = new Set<string>();\n for (let index = 0; index < result.items.length; index += 1) {\n const message = result.items[index];\n assertWindowMessage(message, conversationId);\n if (ids.has(message.messageId)) throw new Error('invalid_conversation_message_window_items');\n ids.add(message.messageId);\n if (\n index > 0 &&\n compareMessageCursor(messageCursor(result.items[index - 1]), messageCursor(message)) >= 0\n ) throw new Error('invalid_conversation_message_window_order');\n }\n const first = result.items[0];\n const last = result.items.at(-1);\n if (\n (first && (!result.startCursor || compareMessageCursor(result.startCursor, messageCursor(first)) !== 0)) ||\n (last && (!result.endCursor || compareMessageCursor(result.endCursor, messageCursor(last)) !== 0)) ||\n (!first && (result.startCursor !== undefined || result.endCursor !== undefined ||\n result.hasMoreBefore || result.hasMoreAfter))\n ) throw new Error('invalid_conversation_message_window_cursor');\n assertResolvedWindowFocus(result, options);\n}\n\nfunction assertResolvedWindowFocus(\n result: ConversationMessageWindowSuccess,\n options: GetConversationMessageWindowAroundOptions,\n): void {\n const focus = result.focus;\n if (focus.kind === 'turn') {\n assertWindowExactKeys(focus, ['kind', 'turnId', 'entryId', 'cursor']);\n if (\n !isNonEmptyText(focus.turnId) ||\n !result.items.some(message => message.turnId === focus.turnId) ||\n (options.focus.kind === 'turn' && (\n focus.turnId !== options.focus.turnId ||\n focus.entryId !== undefined ||\n focus.cursor !== options.focus.cursor\n )) ||\n (options.focus.kind === 'timeline-entry' && (\n focus.entryId !== options.focus.entryId || focus.cursor !== options.focus.cursor\n ))\n ) throw new Error('invalid_conversation_message_window_focus');\n return;\n }\n assertWindowExactKeys(focus, ['kind', 'entry', 'nearestPosition', 'nearestTurnId']);\n if (options.focus.kind !== 'timeline-entry' || focus.kind !== 'compaction') {\n throw new Error('invalid_conversation_message_window_focus');\n }\n const entry = focus.entry;\n assertConversationTimelineCompactionEntry(entry, {\n conversationId: result.conversationId,\n });\n if (\n entry.entryId !== options.focus.entryId ||\n entry.cursor !== options.focus.cursor\n ) throw new Error('invalid_conversation_message_window_compaction');\n if (focus.nearestPosition === 'none') {\n if (focus.nearestTurnId !== undefined || result.items.length !== 0) {\n throw new Error('invalid_conversation_message_window_compaction');\n }\n return;\n }\n if (\n (focus.nearestPosition !== 'before' && focus.nearestPosition !== 'after') ||\n !isNonEmptyText(focus.nearestTurnId) ||\n !result.items.some(message => message.turnId === focus.nearestTurnId)\n ) throw new Error('invalid_conversation_message_window_compaction');\n}\n\n/** Exact standalone compaction-entry validator reused by storage and RPC focus envelopes. */\nexport function assertConversationTimelineCompactionEntry(\n value: unknown,\n options: { conversationId?: string; maximumPreview?: number } = {},\n): asserts value is ConversationTimelineCompactionEntry {\n const page: ConversationTimelinePageSuccess = {\n reset: false,\n items: [],\n revision: 'validation',\n totalMessages: Number.MAX_SAFE_INTEGER,\n totalTurns: Number.MAX_SAFE_INTEGER,\n totalEntries: Number.MAX_SAFE_INTEGER,\n hasMoreBefore: false,\n hasMoreAfter: false,\n };\n assertTimelineEntryShape(\n value,\n page,\n options.maximumPreview ?? MAX_CONVERSATION_TIMELINE_PREVIEW_LENGTH,\n );\n if (\n value.kind !== 'compaction' ||\n (options.conversationId !== undefined && value.conversationId !== options.conversationId)\n ) throw new Error('invalid_conversation_timeline_compaction');\n}\n\nfunction assertWindowMessage(message: ChatMessage, conversationId: string): void {\n try {\n assertCanonicalChatMessageProjection(message, conversationId);\n } catch (error) {\n throw new Error('invalid_conversation_message_window_message', { cause: error });\n }\n}\n\nfunction assertWindowExactKeys(value: object, allowed: readonly string[]): void {\n const keys = Reflect.ownKeys(value);\n if (keys.some(key => typeof key !== 'string' || !allowed.includes(key))) {\n throw new Error('invalid_conversation_message_window');\n }\n}\n\nfunction assertTimelinePageOptions(options: GetConversationTimelinePageOptions): void {\n if (\n !options ||\n !Number.isSafeInteger(options.limit) ||\n options.limit < 1 ||\n options.limit > MAX_CONVERSATION_TIMELINE_PAGE_SIZE\n ) throw new Error('invalid_conversation_timeline_page_limit');\n if (\n !Number.isSafeInteger(options.maxBytes) ||\n options.maxBytes < 1 ||\n options.maxBytes > MAX_CONVERSATION_TIMELINE_PAGE_BYTES\n ) {\n throw new Error('invalid_conversation_timeline_page_byte_budget');\n }\n if (\n options.previewLength !== undefined &&\n (!Number.isSafeInteger(options.previewLength) || options.previewLength < 1)\n ) throw new Error('invalid_conversation_timeline_preview_length');\n const cursors = [options.beforeCursor, options.afterCursor, options.aroundEntryIndex]\n .filter(value => value !== undefined);\n if (cursors.length > 1) throw new Error('conversation_timeline_page_cursor_conflict');\n if (options.beforeCursor !== undefined) assertOpaqueTimelineValue(options.beforeCursor, 'before_cursor');\n if (options.afterCursor !== undefined) assertOpaqueTimelineValue(options.afterCursor, 'after_cursor');\n if (\n (options.beforeCursor !== undefined || options.afterCursor !== undefined) &&\n options.expectedRevision === undefined\n ) throw new Error('conversation_timeline_cursor_requires_revision');\n if (\n options.aroundEntryIndex !== undefined &&\n (!Number.isSafeInteger(options.aroundEntryIndex) || options.aroundEntryIndex < 0)\n ) throw new Error('invalid_conversation_timeline_page_cursor');\n if (options.expectedRevision !== undefined) {\n assertOpaqueTimelineValue(options.expectedRevision, 'expected_revision');\n }\n}\n\nfunction timelinePageRange(\n entries: readonly ConversationTimelineEntry[],\n options: GetConversationTimelinePageOptions,\n): { start: number; end: number } | null {\n if (options.beforeCursor !== undefined) {\n const cursorIndex = entries.findIndex(entry => entry.cursor === options.beforeCursor);\n if (cursorIndex < 0) return null;\n return { start: Math.max(0, cursorIndex - options.limit), end: cursorIndex };\n }\n if (options.afterCursor !== undefined) {\n const cursorIndex = entries.findIndex(entry => entry.cursor === options.afterCursor);\n if (cursorIndex < 0) return null;\n const start = cursorIndex + 1;\n return { start, end: Math.min(entries.length, start + options.limit) };\n }\n if (options.aroundEntryIndex !== undefined) {\n const maximumStart = Math.max(0, entries.length - options.limit);\n const start = Math.max(\n 0,\n Math.min(options.aroundEntryIndex - Math.floor(options.limit / 2), maximumStart),\n );\n return { start, end: Math.min(entries.length, start + options.limit) };\n }\n return {\n start: Math.max(0, entries.length - options.limit),\n end: entries.length,\n };\n}\n\nfunction timelineSuccessPage(\n items: ConversationTimelineEntry[],\n totalMessages: number,\n totalTurns: number,\n totalEntries: number,\n revision: string,\n requestedRange: { start: number; end: number },\n): ConversationTimelinePageSuccess {\n const first = items[0];\n const last = items.at(-1);\n const conceptualStart = first?.entryIndex ?? requestedRange.start;\n const conceptualEnd = last ? last.entryIndex + 1 : requestedRange.end;\n return {\n reset: false,\n items,\n revision,\n totalMessages,\n totalTurns,\n totalEntries,\n hasMoreBefore: conceptualStart > 0,\n hasMoreAfter: conceptualEnd < totalEntries,\n ...(first\n ? { startEntryIndex: first.entryIndex, startCursor: first.cursor }\n : {}),\n ...(last\n ? { endEntryIndex: last.entryIndex, endCursor: last.cursor }\n : {}),\n };\n}\n\nfunction trimTimelineItems(\n items: readonly ConversationTimelineEntry[],\n options: GetConversationTimelinePageOptions,\n): ConversationTimelineEntry[] {\n if (options.afterCursor !== undefined) return items.slice(0, -1);\n if (options.aroundEntryIndex !== undefined && items.length > 1) {\n const firstDistance = Math.abs(items[0].entryIndex - options.aroundEntryIndex);\n const lastDistance = Math.abs(items.at(-1)!.entryIndex - options.aroundEntryIndex);\n return firstDistance > lastDistance ? items.slice(1) : items.slice(0, -1);\n }\n return items.slice(1);\n}\n\nfunction boundedTimelineReset(revision: string, maxBytes: number): ConversationTimelinePage {\n const reset = { reset: true as const, revision };\n if (!timelinePageFits(reset, maxBytes)) {\n throw new Error('conversation_timeline_page_exceeds_byte_budget');\n }\n return reset;\n}\n\nfunction timelinePageFits(page: ConversationTimelinePage, maxBytes: number): boolean {\n try {\n canonicalJsonBytes(page, {\n maxBytes,\n maxDepth: 12,\n maxNodes: 10_000,\n maxStringBytes: maxBytes,\n maxStringCodeUnits: maxBytes,\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Strict storage/wire envelope assertion shared by RPC and persistent hosts. */\nexport function assertConversationTimelinePageEnvelope(\n value: unknown,\n options: Pick<GetConversationTimelinePageOptions, 'limit' | 'maxBytes' | 'previewLength'>,\n): asserts value is ConversationTimelinePage {\n assertTimelinePageOptions({ ...options });\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('invalid_conversation_timeline_page');\n }\n const page = value as ConversationTimelinePage;\n if (!timelinePageFits(page, options.maxBytes)) {\n throw new Error('conversation_timeline_page_exceeds_byte_budget');\n }\n if (page.reset) {\n assertExactKeys(page, ['reset', 'revision'], 'reset');\n assertOpaqueTimelineValue(page.revision, 'revision');\n return;\n }\n assertExactKeys(page, [\n 'reset',\n 'items',\n 'revision',\n 'totalMessages',\n 'totalTurns',\n 'totalEntries',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startEntryIndex',\n 'endEntryIndex',\n 'startCursor',\n 'endCursor',\n ], 'page');\n if (\n page.reset ||\n !Array.isArray(page.items) ||\n page.items.length > options.limit ||\n !Number.isSafeInteger(page.totalMessages) ||\n page.totalMessages < 0 ||\n !Number.isSafeInteger(page.totalTurns) ||\n page.totalTurns < 0 ||\n !Number.isSafeInteger(page.totalEntries) ||\n page.totalEntries < 0 ||\n page.totalTurns > page.totalMessages ||\n typeof page.hasMoreBefore !== 'boolean' ||\n typeof page.hasMoreAfter !== 'boolean'\n ) throw new Error('invalid_conversation_timeline_page');\n assertOpaqueTimelineValue(page.revision, 'revision');\n const maximumPreview = normalizeTimelinePreviewLength(options.previewLength);\n const cursors = new Set<string>();\n let previousEntryIndex = -1;\n let expectedTurnIndex: number | undefined;\n for (const entry of page.items) {\n assertTimelineEntryShape(entry, page, maximumPreview);\n expectedTurnIndex ??= entry.turnIndex;\n if (\n entry.entryIndex <= previousEntryIndex ||\n (previousEntryIndex >= 0 && entry.entryIndex !== previousEntryIndex + 1) ||\n entry.turnIndex !== expectedTurnIndex ||\n cursors.has(entry.cursor)\n ) throw new Error('invalid_conversation_timeline_entry_order');\n previousEntryIndex = entry.entryIndex;\n cursors.add(entry.cursor);\n if (entry.kind === 'turn') expectedTurnIndex += 1;\n }\n assertTimelineBounds(page);\n}\n\n/** Full request-correlated assertion used after a persistent/RPC page read. */\nexport function assertConversationTimelinePage(\n page: unknown,\n conversationId: string,\n options: GetConversationTimelinePageOptions,\n): asserts page is ConversationTimelinePage {\n assertConversationTimelinePageEnvelope(page, options);\n if (page.reset) {\n return;\n }\n if (\n options.expectedRevision !== undefined &&\n page.revision !== options.expectedRevision\n ) throw new Error('conversation_timeline_revision_mismatch');\n for (const entry of page.items) {\n if (entry.conversationId !== conversationId) {\n throw new Error('invalid_conversation_timeline_entry');\n }\n }\n assertTimelineEmptyBoundsForRequest(page, options);\n}\n\nfunction assertTimelineBounds(\n page: ConversationTimelinePageSuccess,\n): void {\n const first = page.items[0];\n const last = page.items.at(-1);\n if (\n page.startEntryIndex !== first?.entryIndex ||\n page.endEntryIndex !== last?.entryIndex ||\n page.startCursor !== first?.cursor ||\n page.endCursor !== last?.cursor ||\n (first && page.hasMoreBefore !== (first.entryIndex > 0)) ||\n (last && page.hasMoreAfter !== (last.entryIndex + 1 < page.totalEntries)) ||\n (!first && (\n page.startEntryIndex !== undefined ||\n page.endEntryIndex !== undefined ||\n page.startCursor !== undefined ||\n page.endCursor !== undefined\n ))\n ) throw new Error('invalid_conversation_timeline_page_bounds');\n}\n\nfunction assertTimelineEmptyBoundsForRequest(\n page: ConversationTimelinePageSuccess,\n options: Pick<GetConversationTimelinePageOptions, 'beforeCursor' | 'afterCursor'>,\n): void {\n if (page.items.length > 0) return;\n const valid = options.beforeCursor !== undefined\n ? !page.hasMoreBefore && page.hasMoreAfter === (page.totalEntries > 0)\n : options.afterCursor !== undefined\n ? page.hasMoreBefore === (page.totalEntries > 0) && !page.hasMoreAfter\n : page.totalEntries === 0 && !page.hasMoreBefore && !page.hasMoreAfter;\n if (!valid) throw new Error('invalid_conversation_timeline_page_bounds');\n}\n\nfunction assertTimelineEntryShape(\n value: unknown,\n page: ConversationTimelinePageSuccess,\n maximumPreview: number,\n): asserts value is ConversationTimelineEntry {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('invalid_conversation_timeline_entry');\n }\n const entry = value as ConversationTimelineEntry;\n const common = [\n 'kind',\n 'entryId',\n 'conversationId',\n 'timestamp',\n 'lamportClock',\n 'originNodeId',\n 'cursor',\n 'entryIndex',\n 'turnIndex',\n ] as const;\n if (entry.kind === 'turn') {\n assertExactKeys(entry, [\n ...common,\n 'messageId',\n 'turnId',\n 'userPreview',\n 'participantPreviews',\n 'responseCount',\n ], 'turn');\n } else if (entry.kind === 'compaction') {\n assertExactKeys(entry, [\n ...common,\n 'summaryPreview',\n 'compactedMessageCount',\n 'compactedTurnCount',\n ], 'compaction');\n } else {\n throw new Error('invalid_conversation_timeline_entry');\n }\n if (\n !isNonEmptyText(entry.conversationId) ||\n !isNonEmptyText(entry.entryId) ||\n !isNonEmptyText(entry.originNodeId) ||\n !Number.isSafeInteger(entry.timestamp) ||\n entry.timestamp < 0 ||\n !Number.isSafeInteger(entry.lamportClock) ||\n entry.lamportClock < 0 ||\n !Number.isSafeInteger(entry.entryIndex) ||\n entry.entryIndex < 0 ||\n entry.entryIndex >= page.totalEntries ||\n !Number.isSafeInteger(entry.turnIndex) ||\n entry.turnIndex < 0 ||\n entry.turnIndex > page.totalTurns\n ) throw new Error('invalid_conversation_timeline_entry');\n assertOpaqueTimelineValue(entry.cursor, 'cursor');\n if (entry.kind === 'turn') {\n if (\n !isNonEmptyText(entry.messageId) ||\n !isNonEmptyText(entry.turnId) ||\n entry.entryId !== entry.messageId ||\n entry.messageId !== entry.turnId ||\n typeof entry.userPreview !== 'string' ||\n entry.userPreview.length > maximumPreview ||\n !Array.isArray(entry.participantPreviews) ||\n entry.participantPreviews.length > MAX_CONVERSATION_TIMELINE_PARTICIPANT_PREVIEWS ||\n !Number.isSafeInteger(entry.responseCount) ||\n entry.responseCount < entry.participantPreviews.length ||\n !participantPreviewsFit(entry.participantPreviews) ||\n !timelineTurnEntryFits(entry)\n ) throw new Error('invalid_conversation_timeline_turn');\n for (const participant of entry.participantPreviews) {\n assertTimelineParticipantPreview(participant);\n }\n return;\n }\n if (\n entry.kind !== 'compaction' ||\n entry.entryId.length === 0 ||\n typeof entry.summaryPreview !== 'string' ||\n entry.summaryPreview.length === 0 ||\n entry.summaryPreview.length > maximumPreview ||\n !Number.isSafeInteger(entry.compactedMessageCount) ||\n entry.compactedMessageCount < 0 ||\n !Number.isSafeInteger(entry.compactedTurnCount) ||\n entry.compactedTurnCount < 0\n ) throw new Error('invalid_conversation_timeline_compaction');\n}\n\nfunction assertExactKeys(\n value: object,\n allowed: readonly string[],\n kind: string,\n): void {\n const keys = Reflect.ownKeys(value);\n if (\n keys.some(key => typeof key !== 'string' || !allowed.includes(key)) ||\n allowed.some(key => {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n return descriptor !== undefined && (!descriptor.enumerable || !('value' in descriptor));\n })\n ) throw new Error(`invalid_conversation_timeline_${kind}`);\n}\n\nfunction memoryTimelineCursor(event: ConversationEvent): string {\n return `timeline-v2:${encodeURIComponent(event.originNodeId)}:${event.originSequence}:${encodeURIComponent(event.eventId)}`;\n}\n\nfunction compareTimelineEvents(left: ConversationEvent, right: ConversationEvent): number {\n return left.timestamp - right.timestamp ||\n left.lamportClock - right.lamportClock ||\n compareUtf8Text(left.originNodeId, right.originNodeId) ||\n compareUtf8Text(left.eventId, right.eventId);\n}\n\nfunction assertOpaqueTimelineValue(value: unknown, field: string): asserts value is string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.length > 2_048 ||\n value !== value.trim() ||\n hasAsciiControlToken(value)\n ) throw new Error(`invalid_conversation_timeline_${field}`);\n}\n\nfunction hasAsciiControlToken(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) return true;\n }\n return false;\n}\n\nfunction isNonEmptyText(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n","import { compareMessageCursor, messageCursor } from '../storage/conversationPaging.js';\nimport type { ChatMessage } from './types.js';\n\nexport const CONTEXT_COMPACTION_METADATA_KEY = 'contextCompaction';\n\n/** Durable, gap-safe semantic coverage for an append-only distributed log. */\nexport interface ContextCompactionBoundaryV2 {\n version: 2;\n /** Highest contiguous originSequence summarized for each origin. */\n coveredVersion: Record<string, number>;\n /** Exact visible message membership below each per-origin frontier. */\n coveredMessageCountByOrigin: Record<string, number>;\n /** Exact user-rooted turn membership below each per-origin frontier. */\n coveredUserTurnCountByOrigin: Record<string, number>;\n droppedMessageCount: number;\n droppedTurnCount: number;\n previousSummaryMessageIds?: string[];\n}\n\nexport interface ContextCompactionCoverage {\n coveredVersion: Record<string, number>;\n coveredMessageCountByOrigin: Record<string, number>;\n coveredUserTurnCountByOrigin: Record<string, number>;\n}\n\n/**\n * Content-free progress for one bounded compaction slice. Hosts may persist or\n * display this value and use it to schedule a later background slice without\n * receiving any conversation content.\n */\nexport interface ContextCompactionProgress {\n readonly checkpointRevision?: string;\n readonly processedMessages: number;\n readonly remainingEstimate?: number;\n readonly providerCalls: number;\n readonly workPages: number;\n}\n\nconst MAX_PREVIOUS_SUMMARY_IDS = 32;\n\nfunction isCoveredVersion(value: unknown): value is Record<string, number> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n return Object.values(value).every(sequence => typeof sequence === 'number' && Number.isSafeInteger(sequence) && sequence > 0);\n}\n\nfunction isCountMap(value: unknown): value is Record<string, number> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n return Object.values(value).every(count => typeof count === 'number' && Number.isSafeInteger(count) && count >= 0);\n}\n\nfunction sumCounts(counts: Readonly<Record<string, number>>): number {\n return Object.values(counts).reduce((total, count) => total + count, 0);\n}\n\nexport function isContextCompactionBoundaryV2(\n value: unknown,\n): value is ContextCompactionBoundaryV2 {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const boundary = value as Partial<ContextCompactionBoundaryV2> & Record<string, unknown>;\n const allowedKeys = new Set([\n 'version',\n 'coveredVersion',\n 'coveredMessageCountByOrigin',\n 'coveredUserTurnCountByOrigin',\n 'droppedMessageCount',\n 'droppedTurnCount',\n 'previousSummaryMessageIds',\n ]);\n if (Object.keys(boundary).some(key => !allowedKeys.has(key))) return false;\n if (\n boundary.version !== 2 ||\n !isCoveredVersion(boundary.coveredVersion) ||\n Object.keys(boundary.coveredVersion).length === 0 ||\n !isCountMap(boundary.coveredMessageCountByOrigin) ||\n !isCountMap(boundary.coveredUserTurnCountByOrigin)\n ) return false;\n const origins = new Set(Object.keys(boundary.coveredVersion));\n if (\n Object.keys(boundary.coveredMessageCountByOrigin).some(origin => !origins.has(origin)) ||\n Object.keys(boundary.coveredUserTurnCountByOrigin).some(origin => !origins.has(origin)) ||\n Object.entries(boundary.coveredUserTurnCountByOrigin).some(([origin, count]) => count > (boundary.coveredMessageCountByOrigin?.[origin] ?? 0))\n ) return false;\n const messageCount = sumCounts(boundary.coveredMessageCountByOrigin);\n const turnCount = sumCounts(boundary.coveredUserTurnCountByOrigin);\n if (\n messageCount < 0 ||\n boundary.droppedMessageCount !== messageCount ||\n boundary.droppedTurnCount !== turnCount\n ) return false;\n const previous = boundary.previousSummaryMessageIds;\n return previous === undefined ||\n Array.isArray(previous) &&\n previous.length > 0 &&\n previous.length <= MAX_PREVIOUS_SUMMARY_IDS &&\n new Set(previous).size === previous.length &&\n previous.every(id => typeof id === 'string' && id.length > 0 && id.length <= 256);\n}\n\nexport function getContextCompactionBoundary(\n message: ChatMessage,\n): ContextCompactionBoundaryV2 | undefined {\n const value = message.metadata?.[CONTEXT_COMPACTION_METADATA_KEY];\n return isContextCompactionBoundaryV2(value) ? value : undefined;\n}\n\nexport function isContextCompactionSummary(message: ChatMessage): boolean {\n return getContextCompactionBoundary(message) !== undefined;\n}\n\nfunction coverageDominates(left: Record<string, number>, right: Record<string, number>): boolean {\n return Object.entries(right).every(([originNodeId, sequence]) => (left[originNodeId] ?? 0) >= sequence);\n}\n\nfunction mergeCoverage(boundaries: readonly ContextCompactionBoundaryV2[]): Record<string, number> {\n const merged: Record<string, number> = {};\n for (const boundary of boundaries) {\n for (const [originNodeId, sequence] of Object.entries(boundary.coveredVersion)) {\n merged[originNodeId] = Math.max(merged[originNodeId] ?? 0, sequence);\n }\n }\n return merged;\n}\n\nfunction mergeExactCoverage(\n boundaries: readonly ContextCompactionBoundaryV2[],\n): ContextCompactionCoverage {\n const result: ContextCompactionCoverage = {\n coveredVersion: {},\n coveredMessageCountByOrigin: {},\n coveredUserTurnCountByOrigin: {},\n };\n for (const boundary of boundaries) {\n for (const [origin, sequence] of Object.entries(boundary.coveredVersion)) {\n const previousSequence = result.coveredVersion[origin] ?? 0;\n const nextMessageCount = boundary.coveredMessageCountByOrigin[origin] ?? 0;\n const nextTurnCount = boundary.coveredUserTurnCountByOrigin[origin] ?? 0;\n if (sequence < previousSequence) continue;\n if (sequence === previousSequence && sequence > 0) {\n if (\n nextMessageCount !== (result.coveredMessageCountByOrigin[origin] ?? 0) ||\n nextTurnCount !== (result.coveredUserTurnCountByOrigin[origin] ?? 0)\n ) throw new Error(`conflicting compaction counts for ${origin}@${sequence}`);\n continue;\n }\n result.coveredVersion[origin] = sequence;\n result.coveredMessageCountByOrigin[origin] = nextMessageCount;\n result.coveredUserTurnCountByOrigin[origin] = nextTurnCount;\n }\n }\n return result;\n}\n\nexport function contextCompactionCoverageFromSummaries(\n summaries: readonly ChatMessage[],\n): ContextCompactionCoverage {\n const boundaries = summaries.map(summary => {\n const boundary = getContextCompactionBoundary(summary);\n if (!boundary) throw new Error(`message ${summary.messageId} is not a v2 compaction summary`);\n return boundary;\n });\n return mergeExactCoverage(boundaries);\n}\n\nexport function createContextCompactionBoundaryFromCoverage(\n coverage: ContextCompactionCoverage,\n previousSummaryMessageIds: readonly string[] = [],\n): ContextCompactionBoundaryV2 {\n // Provenance is diagnostic, while coverage is the semantic truth. Concurrent\n // devices can legitimately produce more summaries than fit in one event, so\n // keep a deterministic bounded sample instead of making compaction wedge.\n const uniquePrevious = [...new Set(previousSummaryMessageIds)].sort().slice(0, MAX_PREVIOUS_SUMMARY_IDS);\n const boundary: ContextCompactionBoundaryV2 = {\n version: 2,\n coveredVersion: { ...coverage.coveredVersion },\n coveredMessageCountByOrigin: { ...coverage.coveredMessageCountByOrigin },\n coveredUserTurnCountByOrigin: { ...coverage.coveredUserTurnCountByOrigin },\n droppedMessageCount: sumCounts(coverage.coveredMessageCountByOrigin),\n droppedTurnCount: sumCounts(coverage.coveredUserTurnCountByOrigin),\n ...(uniquePrevious.length > 0 ? { previousSummaryMessageIds: uniquePrevious } : {}),\n };\n if (!isContextCompactionBoundaryV2(boundary)) {\n throw new Error('invalid exact compaction coverage');\n }\n return boundary;\n}\n\n/**\n * Project the audit log into model context. A dominating summary replaces the\n * summaries it semantically includes. Concurrent incomparable summaries are\n * both retained until a later compaction explicitly merges their contents.\n */\nexport function effectiveConversationHistory(messages: readonly ChatMessage[]): ChatMessage[] {\n const summaries = messages.filter(isContextCompactionSummary);\n if (summaries.length === 0) return [...messages];\n const retainedSummaries = summaries.filter(candidate => {\n const candidateBoundary = getContextCompactionBoundary(candidate)!;\n return !summaries.some(other => {\n if (other.messageId === candidate.messageId) return false;\n const otherBoundary = getContextCompactionBoundary(other)!;\n if (!coverageDominates(otherBoundary.coveredVersion, candidateBoundary.coveredVersion)) {\n return false;\n }\n const equivalent = coverageDominates(\n candidateBoundary.coveredVersion,\n otherBoundary.coveredVersion,\n );\n return !equivalent || compareMessageCursor(messageCursor(candidate), messageCursor(other)) < 0;\n });\n }).sort((left, right) => compareMessageCursor(messageCursor(left), messageCursor(right)));\n const coveredVersion = mergeCoverage(\n retainedSummaries.map(summary => getContextCompactionBoundary(summary)!),\n );\n const tail = messages.filter(message => {\n if (isContextCompactionSummary(message)) return false;\n const sequence = message.originSequence;\n if (typeof sequence !== 'number' || !Number.isSafeInteger(sequence) || sequence <= 0) {\n return true;\n }\n return sequence > (coveredVersion[message.originNodeId] ?? 0);\n });\n return [...retainedSummaries, ...tail];\n}\n\nexport function createContextCompactionBoundary(\n dropped: readonly ChatMessage[],\n): ContextCompactionBoundaryV2 | undefined {\n if (dropped.length === 0) return undefined;\n const previousSummaries = dropped.filter(isContextCompactionSummary);\n const previousBoundaries = previousSummaries.map(summary => getContextCompactionBoundary(summary)!);\n const coverage = mergeExactCoverage(previousBoundaries);\n const coveredVersion = coverage.coveredVersion;\n const previousVersion = { ...coveredVersion };\n const candidates = new Map<string, Set<number>>();\n for (const message of dropped) {\n if (isContextCompactionSummary(message)) continue;\n const sequence = message.originSequence;\n if (typeof sequence !== 'number' || !Number.isSafeInteger(sequence) || sequence <= 0) continue;\n const sequences = candidates.get(message.originNodeId) ?? new Set<number>();\n sequences.add(sequence);\n candidates.set(message.originNodeId, sequences);\n }\n for (const [originNodeId, sequences] of candidates) {\n let frontier = coveredVersion[originNodeId] ?? 0;\n while (sequences.has(frontier + 1)) frontier += 1;\n if (frontier > 0) coveredVersion[originNodeId] = frontier;\n }\n if (Object.keys(coveredVersion).length === 0) return undefined;\n\n const newlyCovered = dropped.filter(message => {\n if (isContextCompactionSummary(message)) return false;\n const sequence = message.originSequence;\n return typeof sequence === 'number' &&\n sequence > (previousVersion[message.originNodeId] ?? 0) &&\n sequence <= (coveredVersion[message.originNodeId] ?? 0);\n });\n for (const message of newlyCovered) {\n coverage.coveredMessageCountByOrigin[message.originNodeId] = (coverage.coveredMessageCountByOrigin[message.originNodeId] ?? 0) + 1;\n if (message.role === 'user') {\n coverage.coveredUserTurnCountByOrigin[message.originNodeId] = (coverage.coveredUserTurnCountByOrigin[message.originNodeId] ?? 0) + 1;\n }\n }\n return createContextCompactionBoundaryFromCoverage(\n coverage,\n previousSummaries.map(summary => summary.messageId),\n );\n}\n","import { canonicalJsonBytes, CanonicalJsonError } from '../encoding/canonicalJson.js';\nimport { type ContextCompactionBoundaryV2, isContextCompactionBoundaryV2 } from './compactionBoundary.js';\nimport type { AttachmentReference, ChatMessage, ChatMessagePart, ChatRole, DetailReference, ToolCall } from './types.js';\n\n/** 15 MiB leaves one MiB for sync/RPC framing under the 16 MiB frame ceiling. */\nexport const MAX_CONVERSATION_EVENT_BYTES = 15 * 1024 * 1024;\nconst MAX_CONVERSATION_EVENT_NODES = 200_000;\n\n/** Frozen wire/storage limits shared by every canonical event ingress. */\nexport const CONVERSATION_EVENT_LIMITS = Object.freeze(\n {\n identifierBytes: 512,\n referenceBytes: 2_048,\n sourceStringBytes: 512,\n titleBytes: 64 * 1_024,\n textBytes: 8 * 1_024 * 1_024,\n metadataStringBytes: 1 * 1_024 * 1_024,\n metadataKeyBytes: 512,\n metadataDepth: 16,\n metadataKeysPerObject: 256,\n metadataArrayItems: 4_096,\n messageParts: 2_048,\n toolCalls: 256,\n attachments: 256,\n compactionOrigins: 4_096,\n filenameBytes: 1_024,\n mimeTypeBytes: 256,\n attachmentBytes: 64 * 1_024 * 1_024,\n } as const,\n);\n\nconst ATTACHMENT_CONTENT_HASH_PATTERN = /^sha256:[\\da-f]{64}$/;\nconst MIME_TYPE_PATTERN = /^[!#$%&'*+.^_`|~\\dA-Za-z-]+\\/[!#$%&'*+.^_`|~\\dA-Za-z-]+$/;\nconst utf8Encoder = new TextEncoder();\n\nexport interface ConversationEventBase {\n eventId: string;\n conversationId: string;\n originNodeId: string;\n /** Contiguous, atomically allocated in the conversation+origin domain. */\n originSequence: number;\n lamportClock: number;\n timestamp: number;\n}\n\nexport interface ConversationMessagePayload {\n messageId: string;\n turnId: string;\n role: ChatRole;\n content: string;\n parts?: ChatMessagePart[];\n toolCalls?: ToolCall[];\n attachments?: ChatMessage['attachments'];\n detailRef?: DetailReference;\n reasoning_content?: string;\n contentType?: string;\n hidden?: boolean;\n duration?: number | null;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ConversationMessageEvent extends ConversationEventBase {\n kind: 'message';\n message: ConversationMessagePayload;\n}\n\nexport interface ConversationTombstoneEvent extends ConversationEventBase {\n kind: 'tombstone';\n targetTurnId: string;\n reason?: 'user-delete' | 'retention' | 'redaction';\n digest?: string;\n}\n\nexport interface ConversationCompactionSummaryEvent extends ConversationEventBase {\n kind: 'compaction';\n mode: 'summary';\n boundary: ContextCompactionBoundaryV2;\n summary: {\n turnId: string;\n content: string;\n parts?: Array<Exclude<ChatMessagePart, { type: 'attachment' }>>;\n };\n}\n\n/** Causal coverage checkpoint with no semantic text or ChatMessage projection. */\nexport interface ConversationCompactionCoverageEvent extends ConversationEventBase {\n kind: 'compaction';\n mode: 'coverage-only';\n boundary: ContextCompactionBoundaryV2;\n summary: null;\n}\n\nexport type ConversationCompactionEvent =\n | ConversationCompactionSummaryEvent\n | ConversationCompactionCoverageEvent;\n\nexport interface ConversationMetadataPatchFields {\n title?: string;\n definitionId?: string;\n instanceDelta?: Record<string, unknown>;\n isUserInitiated?: boolean;\n sourceChannel?: {\n channelId: string;\n platform: string;\n imUserId: string;\n } | null;\n}\n\nexport interface ConversationMetadataPatchEvent extends ConversationEventBase {\n kind: 'metadataPatch';\n patch: ConversationMetadataPatchFields;\n}\n\nexport type ConversationEvent =\n | ConversationMessageEvent\n | ConversationTombstoneEvent\n | ConversationCompactionEvent\n | ConversationMetadataPatchEvent;\n\ntype WithoutAssignedIdentity<Event extends ConversationEvent> = Omit<\n Event,\n 'originSequence' | 'lamportClock'\n>;\n\nexport type ConversationEventDraft = ConversationEvent extends infer Event ? Event extends ConversationEvent ? WithoutAssignedIdentity<Event>\n : never\n : never;\n\nexport interface ConversationEventCursor {\n originNodeId: string;\n originSequence: number;\n eventId: string;\n}\n\nexport function conversationEventToMessage(event: ConversationMessageEvent): ChatMessage {\n return {\n ...event.message,\n conversationId: event.conversationId,\n originNodeId: event.originNodeId,\n originSequence: event.originSequence,\n lamportClock: event.lamportClock,\n timestamp: event.timestamp,\n };\n}\n\nexport function messageToConversationEvent(message: ChatMessage): ConversationMessageEvent {\n const {\n messageId,\n turnId,\n conversationId,\n originNodeId,\n originSequence,\n lamportClock,\n timestamp,\n ...payload\n } = message;\n return {\n eventId: messageId,\n conversationId,\n originNodeId,\n originSequence,\n lamportClock,\n timestamp,\n kind: 'message',\n message: { messageId, turnId, ...payload },\n };\n}\n\n/** Strict shared validator for message projections returned by storage/RPC hosts. */\nexport function assertCanonicalChatMessageProjection(\n value: unknown,\n conversationId?: string,\n): asserts value is ChatMessage {\n try {\n canonicalJsonBytes(value, {\n maxDepth: 64,\n maxNodes: MAX_CONVERSATION_EVENT_NODES,\n maxStringCodeUnits: MAX_CONVERSATION_EVENT_BYTES,\n maxStringBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxBytes: MAX_CONVERSATION_EVENT_BYTES,\n });\n const event = normalizeCanonicalConversationEvent(messageToConversationEvent(value as ChatMessage));\n if (\n event.kind !== 'message' ||\n (conversationId !== undefined && event.conversationId !== conversationId)\n ) {\n throw new Error('invalid canonical chat message projection scope');\n }\n } catch (error) {\n throw new Error('invalid canonical chat message projection', { cause: error });\n }\n}\n\n/** Binary bodies are referenced only by message events, never control events. */\nexport function conversationEventAttachmentReferences(\n event: ConversationEvent,\n): AttachmentReference[] {\n if (event.kind !== 'message') return [];\n const references = new Map<string, AttachmentReference>();\n for (const reference of event.message.attachments ?? []) {\n references.set(reference.contentHash, reference);\n }\n for (const part of event.message.parts ?? []) {\n if (part.type === 'attachment') {\n references.set(part.attachment.contentHash, part.attachment);\n }\n }\n return [...references.values()];\n}\n\nexport function isConversationEvent(value: unknown): value is ConversationEvent {\n if (!isEventBase(value)) return false;\n const event = value as ConversationEvent & Record<string, unknown>;\n switch (event.kind) {\n case 'message':\n return hasOnlyKeys(event, [...eventBaseKeys, 'kind', 'message']) &&\n isMessagePayload(event.message) && event.eventId === event.message.messageId;\n case 'tombstone':\n return hasOnlyKeys(event, [...eventBaseKeys, 'kind', 'targetTurnId', 'reason', 'digest']) &&\n isIdentifier(event.targetTurnId) &&\n (event.reason === undefined ||\n event.reason === 'user-delete' || event.reason === 'retention' || event.reason === 'redaction') &&\n (event.digest === undefined || isBoundedSourceString(event.digest, true));\n case 'compaction':\n return hasOnlyKeys(event, [...eventBaseKeys, 'kind', 'mode', 'boundary', 'summary']) &&\n isContextCompactionBoundaryV2(event.boundary) &&\n isCompactionBoundaryWithinEventLimits(event.boundary) &&\n (event.mode === 'coverage-only' && event.summary === null ||\n event.mode === 'summary' && isCompactionSummary(event.summary));\n case 'metadataPatch':\n return hasOnlyKeys(event, [...eventBaseKeys, 'kind', 'patch']) &&\n isMetadataPatch(event.patch);\n default:\n return false;\n }\n}\n\n/**\n * Validate the exact event schema and its deep JSON graph before a storage or\n * sync boundary. Known optional schema fields explicitly set to `undefined`\n * are normalized as absent; arbitrary metadata/tool arguments remain strict.\n */\nexport function assertCanonicalConversationEvent(\n value: unknown,\n): asserts value is ConversationEvent {\n normalizeCanonicalConversationEvent(value);\n}\n\n/**\n * Return the exact schema-normalized event that must cross a storage boundary.\n * Callers must persist/project/return this value rather than the pre-validation\n * input so known optional `undefined` fields cannot diverge across hosts.\n */\nexport function normalizeCanonicalConversationEvent(value: unknown): ConversationEvent {\n let normalized: unknown;\n try {\n normalized = normalizeKnownOptionalEventFields(value);\n canonicalJsonBytes(normalized, {\n maxDepth: 64,\n maxNodes: MAX_CONVERSATION_EVENT_NODES,\n maxStringCodeUnits: MAX_CONVERSATION_EVENT_BYTES,\n maxStringBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxBytes: MAX_CONVERSATION_EVENT_BYTES,\n });\n } catch (error) {\n throw new Error('invalid canonical conversation event', { cause: error });\n }\n if (!isConversationEvent(normalized)) {\n throw new Error('invalid canonical conversation event schema');\n }\n return normalized;\n}\n\n/** Validate an entire remote/local batch before the caller starts a transaction. */\nexport function assertCanonicalConversationEvents(\n values: readonly unknown[],\n): asserts values is readonly ConversationEvent[] {\n for (const value of values) assertCanonicalConversationEvent(value);\n}\n\n/** Normalize a complete batch before any member is projected or persisted. */\nexport function normalizeCanonicalConversationEvents(\n values: readonly unknown[],\n): ConversationEvent[] {\n return values.map(value => normalizeCanonicalConversationEvent(value));\n}\n\n/**\n * Validate a local draft before opening a write transaction or allocating a\n * causal sequence. Worst-case safe-integer coordinates reserve enough bytes\n * for every value the allocator may assign later.\n */\nexport function assertCanonicalConversationEventDraft(\n value: unknown,\n): asserts value is ConversationEventDraft {\n const normalized = normalizeKnownOptionalEventFields(value);\n if (\n !isPlainObject(normalized) ||\n Object.hasOwn(normalized, 'originSequence') ||\n Object.hasOwn(normalized, 'lamportClock')\n ) {\n throw new Error('invalid canonical conversation event draft schema');\n }\n const candidate = Object.assign(Object.create(null) as Record<string, unknown>, normalized, {\n originSequence: Number.MAX_SAFE_INTEGER,\n lamportClock: Number.MAX_SAFE_INTEGER,\n });\n assertCanonicalConversationEvent(candidate);\n}\n\nexport function assertCanonicalConversationEventDrafts(\n values: readonly unknown[],\n): asserts values is readonly ConversationEventDraft[] {\n for (const value of values) assertCanonicalConversationEventDraft(value);\n}\n\n/** Canonical conflict/digest bytes using the same normalization as the boundary validator. */\nexport function canonicalConversationEventBytes(value: unknown): Uint8Array {\n const normalized = normalizeCanonicalConversationEvent(value);\n return canonicalJsonBytes(normalized, {\n maxDepth: 64,\n maxNodes: MAX_CONVERSATION_EVENT_NODES,\n maxStringCodeUnits: MAX_CONVERSATION_EVENT_BYTES,\n maxStringBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxBytes: MAX_CONVERSATION_EVENT_BYTES,\n });\n}\n\nfunction isEventBase(value: unknown): value is ConversationEventBase & { kind: unknown } {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const event = value as Partial<ConversationEventBase> & { kind?: unknown };\n return isIdentifier(event.eventId) &&\n isIdentifier(event.conversationId) &&\n isIdentifier(event.originNodeId) &&\n typeof event.originSequence === 'number' && Number.isSafeInteger(event.originSequence) &&\n event.originSequence > 0 && typeof event.lamportClock === 'number' &&\n Number.isSafeInteger(event.lamportClock) && event.lamportClock > 0 &&\n typeof event.timestamp === 'number' &&\n Number.isSafeInteger(event.timestamp) && event.timestamp >= 0 && typeof event.kind === 'string';\n}\n\nfunction normalizeKnownOptionalEventFields(value: unknown): unknown {\n const event = copyOptionalRecord(value, eventOptionalFields(value));\n if (!isPlainObject(event)) return event;\n if (event.kind === 'message') {\n event.message = normalizeMessagePayload(event.message);\n } else if (event.kind === 'compaction') {\n if (event.mode === 'summary') event.summary = normalizeCompactionSummary(event.summary);\n } else if (event.kind === 'metadataPatch') {\n event.patch = normalizeMetadataPatch(event.patch);\n }\n return event;\n}\n\nfunction eventOptionalFields(value: unknown): ReadonlySet<string> {\n const kind = safeDataProperty(value, 'kind');\n return kind === 'tombstone' ? new Set(['reason', 'digest']) : new Set();\n}\n\nfunction normalizeMessagePayload(value: unknown): unknown {\n const message = copyOptionalRecord(\n value,\n new Set([\n 'parts',\n 'toolCalls',\n 'attachments',\n 'detailRef',\n 'reasoning_content',\n 'contentType',\n 'hidden',\n 'duration',\n 'metadata',\n ]),\n );\n if (!isPlainObject(message)) return message;\n if (message.parts !== undefined) {\n message.parts = normalizeArray(message.parts, normalizeMessagePartOptionals);\n }\n if (message.detailRef !== undefined) {\n message.detailRef = normalizeDetailReference(message.detailRef);\n }\n return message;\n}\n\nfunction normalizeMessagePartOptionals(value: unknown): unknown {\n const type = safeDataProperty(value, 'type');\n if (type !== 'tool-result') return copyOptionalRecord(value, new Set());\n const part = copyOptionalRecord(\n value,\n new Set([\n 'toolCallId',\n 'parameters',\n 'isError',\n 'payload',\n 'detailRef',\n ]),\n );\n if (isPlainObject(part) && part.detailRef !== undefined) {\n part.detailRef = normalizeDetailReference(part.detailRef);\n }\n return part;\n}\n\nfunction normalizeDetailReference(value: unknown): unknown {\n return copyOptionalRecord(\n value,\n new Set([\n 'runId',\n 'conversationId',\n 'sessionId',\n 'nodeId',\n 'fileUri',\n 'exitCode',\n 'resourceVersion',\n ]),\n );\n}\n\nfunction normalizeCompactionSummary(value: unknown): unknown {\n const summary = copyOptionalRecord(value, new Set(['parts']));\n if (isPlainObject(summary) && summary.parts !== undefined) {\n summary.parts = normalizeArray(summary.parts, normalizeMessagePartOptionals);\n }\n return summary;\n}\n\nfunction normalizeMetadataPatch(value: unknown): unknown {\n return copyOptionalRecord(\n value,\n new Set([\n 'title',\n 'definitionId',\n 'instanceDelta',\n 'isUserInitiated',\n 'sourceChannel',\n ]),\n );\n}\n\nfunction copyOptionalRecord(value: unknown, optional: ReadonlySet<string>): unknown {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return value;\n let prototype: object | null;\n let keys: Array<string | symbol>;\n try {\n prototype = Object.getPrototypeOf(value) as object | null;\n keys = Reflect.ownKeys(value);\n } catch (error) {\n throw new CanonicalJsonError('non_plain_object', error);\n }\n if (prototype !== Object.prototype && prototype !== null) return value;\n if (keys.length > MAX_CONVERSATION_EVENT_NODES) {\n throw new CanonicalJsonError('max_nodes');\n }\n const copy = Object.create(null) as Record<string, unknown>;\n for (const key of keys) {\n if (typeof key === 'symbol') throw new CanonicalJsonError('symbol_property');\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (!descriptor) throw new CanonicalJsonError('non_plain_object');\n if ('get' in descriptor || 'set' in descriptor) {\n throw new CanonicalJsonError('accessor_property');\n }\n if (!descriptor.enumerable) throw new CanonicalJsonError('non_enumerable_property');\n if (optional.has(key) && descriptor.value === undefined) continue;\n copy[key] = descriptor.value;\n }\n return copy;\n}\n\nfunction normalizeArray(\n value: unknown,\n normalizeItem: (item: unknown) => unknown,\n): unknown {\n if (!Array.isArray(value)) return value;\n if (Object.getPrototypeOf(value) !== Array.prototype || value.length > MAX_CONVERSATION_EVENT_NODES) {\n return value;\n }\n const normalized: unknown[] = [];\n for (let index = 0; index < value.length; index += 1) {\n const descriptor = Object.getOwnPropertyDescriptor(value, String(index));\n if (!descriptor || 'get' in descriptor || 'set' in descriptor) {\n throw new CanonicalJsonError(descriptor ? 'accessor_property' : 'sparse_array');\n }\n normalized.push(normalizeItem(descriptor.value));\n }\n return normalized;\n}\n\nfunction safeDataProperty(value: unknown, key: string): unknown {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return undefined;\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (!descriptor || 'get' in descriptor || 'set' in descriptor) return undefined;\n return descriptor.value;\n}\n\nfunction isMessagePayload(value: unknown): value is ConversationMessagePayload {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const message = value as Partial<ConversationMessagePayload> & Record<string, unknown>;\n if (!hasOnlyKeys(message, messagePayloadKeys)) return false;\n return isIdentifier(message.messageId) &&\n isIdentifier(message.turnId) &&\n (message.role !== 'user' || message.messageId === message.turnId) &&\n (message.role === 'user' || message.role === 'assistant' || message.role === 'tool' ||\n message.role === 'agent' || message.role === 'error') &&\n isBoundedText(message.content, CONVERSATION_EVENT_LIMITS.textBytes, true) &&\n (message.parts === undefined || Array.isArray(message.parts) &&\n message.parts.length <= CONVERSATION_EVENT_LIMITS.messageParts &&\n message.parts.every(isMessagePart)) &&\n (message.toolCalls === undefined || Array.isArray(message.toolCalls) &&\n message.toolCalls.length <= CONVERSATION_EVENT_LIMITS.toolCalls &&\n message.toolCalls.every(isToolCall)) &&\n (message.attachments === undefined || Array.isArray(message.attachments) &&\n message.attachments.length <= CONVERSATION_EVENT_LIMITS.attachments &&\n message.attachments.every(isAttachmentReference)) &&\n (message.detailRef === undefined || isDetailReference(message.detailRef)) &&\n (message.reasoning_content === undefined ||\n isBoundedText(message.reasoning_content, CONVERSATION_EVENT_LIMITS.textBytes, true)) &&\n (message.contentType === undefined || isBoundedSourceString(message.contentType, false)) &&\n (message.hidden === undefined || typeof message.hidden === 'boolean') &&\n (message.duration === undefined || message.duration === null ||\n typeof message.duration === 'number' && Number.isSafeInteger(message.duration) &&\n message.duration >= 0) &&\n (message.metadata === undefined || isBoundedJsonRecord(message.metadata));\n}\n\nfunction isCompactionSummary(value: unknown): boolean {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const summary = value as Record<string, unknown>;\n return hasOnlyKeys(summary, ['turnId', 'content', 'parts']) &&\n isIdentifier(summary.turnId) &&\n isBoundedText(summary.content, CONVERSATION_EVENT_LIMITS.textBytes, true) &&\n (summary.parts === undefined || Array.isArray(summary.parts) &&\n summary.parts.length <= CONVERSATION_EVENT_LIMITS.messageParts &&\n summary.parts.every(part => isMessagePart(part) && part.type !== 'attachment'));\n}\n\nfunction isMetadataPatch(value: unknown): value is ConversationMetadataPatchFields {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const patch = value as Record<string, unknown>;\n const allowed = new Set(['title', 'definitionId', 'instanceDelta', 'isUserInitiated', 'sourceChannel']);\n if (Object.keys(patch).length === 0 || Object.keys(patch).some(key => !allowed.has(key))) return false;\n if (\n patch.title !== undefined &&\n !isBoundedText(patch.title, CONVERSATION_EVENT_LIMITS.titleBytes, true)\n ) return false;\n if (patch.definitionId !== undefined && !isIdentifier(patch.definitionId)) return false;\n if (patch.instanceDelta !== undefined && !isBoundedJsonRecord(patch.instanceDelta)) return false;\n if (patch.isUserInitiated !== undefined && typeof patch.isUserInitiated !== 'boolean') return false;\n if (patch.sourceChannel !== undefined && patch.sourceChannel !== null) {\n if (!isPlainObject(patch.sourceChannel)) return false;\n const source = patch.sourceChannel;\n if (\n !hasOnlyKeys(source, ['channelId', 'platform', 'imUserId']) ||\n !isBoundedSourceString(source.channelId, false) ||\n !isBoundedSourceString(source.platform, false) ||\n !isBoundedSourceString(source.imUserId, false)\n ) return false;\n }\n return true;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const prototype = Object.getPrototypeOf(value) as object | null;\n return prototype === Object.prototype || prototype === null;\n}\n\nconst eventBaseKeys = [\n 'eventId',\n 'conversationId',\n 'originNodeId',\n 'originSequence',\n 'lamportClock',\n 'timestamp',\n] as const;\n\nconst messagePayloadKeys = [\n 'messageId',\n 'turnId',\n 'role',\n 'content',\n 'parts',\n 'toolCalls',\n 'attachments',\n 'detailRef',\n 'reasoning_content',\n 'contentType',\n 'hidden',\n 'duration',\n 'metadata',\n] as const;\n\nfunction hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {\n const keys = new Set(allowed);\n return Object.keys(value).every(key => keys.has(key));\n}\n\nfunction isAttachmentReference(value: unknown): boolean {\n if (!isPlainObject(value) || !hasOnlyKeys(value, ['contentHash', 'filename', 'mimeType', 'size'])) {\n return false;\n }\n return typeof value.contentHash === 'string' &&\n ATTACHMENT_CONTENT_HASH_PATTERN.test(value.contentHash) &&\n isSafeFilename(value.filename) && isSafeMimeType(value.mimeType) &&\n typeof value.size === 'number' && Number.isSafeInteger(value.size) && value.size >= 0 &&\n value.size <= CONVERSATION_EVENT_LIMITS.attachmentBytes;\n}\n\nfunction isToolCall(value: unknown): boolean {\n return isPlainObject(value) && hasOnlyKeys(value, ['id', 'toolName', 'arguments']) &&\n isIdentifier(value.id) && isToolName(value.toolName) &&\n Object.hasOwn(value, 'arguments') && isBoundedJsonFragment(value.arguments);\n}\n\nfunction isDetailReference(value: unknown): boolean {\n if (\n !isPlainObject(value) || !hasOnlyKeys(value, [\n 'type',\n 'runId',\n 'conversationId',\n 'sessionId',\n 'nodeId',\n 'fileUri',\n 'exitCode',\n 'resourceVersion',\n ])\n ) return false;\n if (value.type !== 'agent-run' && value.type !== 'terminal-session' && value.type !== 'file') {\n return false;\n }\n if (\n !['runId', 'conversationId', 'sessionId', 'nodeId', 'resourceVersion']\n .every(key => value[key] === undefined || isIdentifier(value[key])) ||\n value.fileUri !== undefined &&\n !isBoundedText(value.fileUri, CONVERSATION_EVENT_LIMITS.referenceBytes, false)\n ) return false;\n if (\n value.exitCode !== undefined &&\n (typeof value.exitCode !== 'number' || !Number.isSafeInteger(value.exitCode))\n ) return false;\n if (value.type === 'agent-run') {\n return value.runId !== undefined || value.conversationId !== undefined;\n }\n if (value.type === 'terminal-session') return value.sessionId !== undefined;\n return value.fileUri !== undefined;\n}\n\nfunction isMessagePart(value: unknown): value is ChatMessagePart {\n if (!isPlainObject(value) || typeof value.type !== 'string') return false;\n switch (value.type) {\n case 'text':\n case 'reasoning':\n return hasOnlyKeys(value, ['type', 'text']) &&\n isBoundedText(value.text, CONVERSATION_EVENT_LIMITS.textBytes, true);\n case 'tool-call':\n return hasOnlyKeys(value, ['type', 'toolCallId', 'toolName', 'arguments']) &&\n isIdentifier(value.toolCallId) && isToolName(value.toolName) &&\n Object.hasOwn(value, 'arguments') && isBoundedJsonFragment(value.arguments);\n case 'attachment':\n return hasOnlyKeys(value, ['type', 'attachment']) && isAttachmentReference(value.attachment);\n case 'tool-result':\n return hasOnlyKeys(value, [\n 'type',\n 'toolCallId',\n 'toolName',\n 'parameters',\n 'result',\n 'isError',\n 'payload',\n 'detailRef',\n ]) && (value.toolCallId === undefined || isIdentifier(value.toolCallId)) &&\n isToolName(value.toolName) &&\n isBoundedText(value.result, CONVERSATION_EVENT_LIMITS.textBytes, true) &&\n (value.parameters === undefined || isBoundedJsonFragment(value.parameters)) &&\n (value.isError === undefined || typeof value.isError === 'boolean') &&\n (value.payload === undefined || isBoundedJsonFragment(value.payload)) &&\n (value.detailRef === undefined || isDetailReference(value.detailRef));\n default:\n return false;\n }\n}\n\nfunction isCompactionBoundaryWithinEventLimits(boundary: ContextCompactionBoundaryV2): boolean {\n const maps = [\n boundary.coveredVersion,\n boundary.coveredMessageCountByOrigin,\n boundary.coveredUserTurnCountByOrigin,\n ];\n if (maps.some(map => Object.keys(map).length > CONVERSATION_EVENT_LIMITS.compactionOrigins)) {\n return false;\n }\n if (maps.some(map => Object.keys(map).some(key => !isIdentifier(key)))) return false;\n return boundary.previousSummaryMessageIds?.every(isIdentifier) ?? true;\n}\n\nfunction isIdentifier(value: unknown): value is string {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.identifierBytes, false) &&\n !hasAsciiControl(value);\n}\n\nfunction isToolName(value: unknown): value is string {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.sourceStringBytes, false) &&\n !hasAsciiControl(value);\n}\n\nfunction isBoundedSourceString(value: unknown, allowEmpty: boolean): value is string {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.sourceStringBytes, allowEmpty) &&\n !hasAsciiControl(value);\n}\n\nfunction isBoundedText(value: unknown, maxBytes: number, allowEmpty: boolean): value is string {\n return typeof value === 'string' && (allowEmpty || value.length > 0) &&\n utf8Encoder.encode(value).byteLength <= maxBytes;\n}\n\nfunction isSafeFilename(value: unknown): value is string {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.filenameBytes, false) &&\n value !== '.' && value !== '..' && !hasAsciiControl(value) &&\n !value.includes('/') && !value.includes('\\\\');\n}\n\nfunction isSafeMimeType(value: unknown): value is string {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.mimeTypeBytes, false) &&\n MIME_TYPE_PATTERN.test(value);\n}\n\nfunction hasAsciiControl(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const codeUnit = value.charCodeAt(index);\n if (codeUnit < 0x20 || codeUnit === 0x7f) return true;\n }\n return false;\n}\n\ninterface JsonFragmentValidationState {\n active: WeakSet<object>;\n nodes: number;\n}\n\nfunction isBoundedJsonRecord(value: unknown): value is Record<string, unknown> {\n return isPlainObject(value) && isBoundedJsonFragment(value);\n}\n\nfunction isBoundedJsonFragment(\n value: unknown,\n depth = 0,\n state: JsonFragmentValidationState = { active: new WeakSet(), nodes: 0 },\n): boolean {\n state.nodes += 1;\n if (state.nodes > MAX_CONVERSATION_EVENT_NODES || depth > CONVERSATION_EVENT_LIMITS.metadataDepth) {\n return false;\n }\n if (value === null || typeof value === 'boolean') return true;\n if (typeof value === 'string') {\n return isBoundedText(value, CONVERSATION_EVENT_LIMITS.metadataStringBytes, true);\n }\n if (typeof value === 'number') {\n return Number.isFinite(value) && (!Number.isInteger(value) || Number.isSafeInteger(value));\n }\n if (typeof value !== 'object') return false;\n if (state.active.has(value)) return false;\n state.active.add(value);\n let valid = false;\n if (Array.isArray(value)) {\n valid = Object.getPrototypeOf(value) === Array.prototype &&\n value.length <= CONVERSATION_EVENT_LIMITS.metadataArrayItems &&\n value.every(item => isBoundedJsonFragment(item, depth + 1, state));\n } else if (isPlainObject(value)) {\n const keys = Reflect.ownKeys(value);\n valid = keys.length <= CONVERSATION_EVENT_LIMITS.metadataKeysPerObject && keys.every(key => {\n if (\n typeof key !== 'string' ||\n !isBoundedText(key, CONVERSATION_EVENT_LIMITS.metadataKeyBytes, false)\n ) return false;\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n return descriptor !== undefined && descriptor.enumerable &&\n !('get' in descriptor) && !('set' in descriptor) &&\n isBoundedJsonFragment(descriptor.value, depth + 1, state);\n });\n }\n state.active.delete(value);\n return valid;\n}\n","export type AgentRunState =\n | 'accepted'\n | 'queued'\n | 'running'\n | 'completed'\n | 'failed'\n | 'cancelled';\n\nexport const AGENT_RUN_ERROR_CODES = Object.freeze(\n [\n 'CANCELLED',\n 'INTERRUPTED',\n 'INVALID_REQUEST',\n 'USER_MESSAGE_TOO_LARGE',\n 'MODEL_NOT_FOUND',\n 'PROVIDER_AUTH_MISSING',\n 'PROVIDER_CONFIGURATION_MISSING',\n 'PROVIDER_UNAVAILABLE',\n 'RATE_LIMITED',\n 'RUNNER_UNAVAILABLE',\n 'STORAGE_UNAVAILABLE',\n 'DEVICE_AUTH_REQUIRED',\n 'DEVICE_PERMISSION_DENIED',\n 'NETWORK_UNAVAILABLE',\n 'CONTEXT_COMPACTION_PENDING',\n 'CONTEXT_COMPACTION_FAILED',\n 'CONTEXT_BUDGET_EXCEEDED',\n 'INTERNAL',\n ] as const,\n);\n\nexport type AgentRunErrorCode = typeof AGENT_RUN_ERROR_CODES[number];\n\nexport const AGENT_RUN_ERROR_MESSAGE_KEYS = Object.freeze(\n {\n CANCELLED: 'agent.run.error.cancelled',\n INTERRUPTED: 'agent.run.error.interrupted',\n INVALID_REQUEST: 'agent.run.error.invalidRequest',\n USER_MESSAGE_TOO_LARGE: 'agent.run.error.userMessageTooLarge',\n MODEL_NOT_FOUND: 'agent.run.error.modelNotFound',\n PROVIDER_AUTH_MISSING: 'agent.run.error.providerAuthMissing',\n PROVIDER_CONFIGURATION_MISSING: 'agent.run.error.providerConfigurationMissing',\n PROVIDER_UNAVAILABLE: 'agent.run.error.providerUnavailable',\n RATE_LIMITED: 'agent.run.error.rateLimited',\n RUNNER_UNAVAILABLE: 'agent.run.error.runnerUnavailable',\n STORAGE_UNAVAILABLE: 'agent.run.error.storageUnavailable',\n DEVICE_AUTH_REQUIRED: 'agent.run.error.deviceAuthRequired',\n DEVICE_PERMISSION_DENIED: 'agent.run.error.devicePermissionDenied',\n NETWORK_UNAVAILABLE: 'agent.run.error.networkUnavailable',\n CONTEXT_COMPACTION_PENDING: 'agent.run.error.contextCompactionPending',\n CONTEXT_COMPACTION_FAILED: 'agent.run.error.contextCompactionFailed',\n CONTEXT_BUDGET_EXCEEDED: 'agent.run.error.contextBudgetExceeded',\n INTERNAL: 'agent.run.error.internal',\n } satisfies Readonly<Record<AgentRunErrorCode, string>>,\n);\n\nexport type AgentRunErrorMessageKey = typeof AGENT_RUN_ERROR_MESSAGE_KEYS[AgentRunErrorCode];\n\nexport const AGENT_RUN_PROVIDER_SETTING_FIELDS = Object.freeze(\n [\n 'apiKey',\n 'baseUrl',\n 'model',\n 'apiMode',\n ] as const,\n);\n\nexport type AgentRunProviderSettingField = typeof AGENT_RUN_PROVIDER_SETTING_FIELDS[number];\n\nexport interface AgentRunErrorLocalizationParameters {\n providerId?: string;\n modelId?: string;\n settingField?: AgentRunProviderSettingField;\n retryAfterMs?: number;\n requested?: number;\n limit?: number;\n /** Content-free durable compaction checkpoint identity. */\n checkpointRevision?: string;\n /** Total messages causally covered by the durable checkpoint. */\n processedMessages?: number;\n /** Optional storage-supplied estimate; absence means unknown, never zero. */\n remainingEstimate?: number;\n}\n\nexport type AgentRunErrorSettingTarget =\n | {\n kind: 'provider';\n providerId: string;\n field: AgentRunProviderSettingField;\n }\n | { kind: 'model'; providerId: string; modelId: string }\n | { kind: 'runtime'; section: 'agent' | 'network' | 'storage' };\n\n/**\n * Public, restart-safe error metadata. This type intentionally has no message,\n * cause, provider body, credential, or arbitrary metadata escape hatch.\n */\nexport interface AgentRunError {\n code: AgentRunErrorCode;\n messageKey: AgentRunErrorMessageKey;\n retryable: boolean;\n /** Opaque support correlation identifier; never a provider request body or credential. */\n diagnosticId: string;\n providerId?: string;\n modelId?: string;\n localizedParams?: AgentRunErrorLocalizationParameters;\n settingTarget?: AgentRunErrorSettingTarget;\n}\n\nexport const AGENT_RUN_ERROR_LIMITS = Object.freeze(\n {\n maxTotalBytes: 4_096,\n maxDepth: 3,\n maxNodes: 3,\n maxProperties: 24,\n maxIdentifierBytes: 256,\n maxDiagnosticIdBytes: 128,\n } as const,\n);\n\nexport class AgentRunErrorValidationError extends Error {\n constructor() {\n super('invalid agent run error');\n this.name = 'AgentRunErrorValidationError';\n }\n}\n\n/** Durable identity and lifecycle state for one accepted agent run. */\nexport interface AgentRunRecord {\n runId: string;\n conversationId: string;\n definitionId: string;\n /** User-rooted turn identity shared by all message events produced by this run. */\n turnId: string;\n requestPeerId: string;\n requestId: string;\n /** SHA-256 of the canonical execution payload for idempotency drift detection. */\n payloadDigest: string;\n /** Present only for a durable retry; binds the replacement run to its original user-root turn. */\n retrySourceTurnId?: string;\n state: AgentRunState;\n acceptedAt: number;\n updatedAt: number;\n startedAt?: number;\n finishedAt?: number;\n cancelRequestedAt?: number;\n error?: AgentRunError;\n}\n\nconst AGENT_RUN_ERROR_CODE_SET = new Set<AgentRunErrorCode>(AGENT_RUN_ERROR_CODES);\nconst AGENT_RUN_PROVIDER_SETTING_FIELD_SET = new Set<AgentRunProviderSettingField>(\n AGENT_RUN_PROVIDER_SETTING_FIELDS,\n);\nconst ROOT_ERROR_KEYS = new Set([\n 'code',\n 'messageKey',\n 'retryable',\n 'diagnosticId',\n 'providerId',\n 'modelId',\n 'localizedParams',\n 'settingTarget',\n]);\nconst LOCALIZATION_PARAM_KEYS = new Set([\n 'providerId',\n 'modelId',\n 'settingField',\n 'retryAfterMs',\n 'requested',\n 'limit',\n 'checkpointRevision',\n 'processedMessages',\n 'remainingEstimate',\n]);\nconst SECRET_SHAPE =\n /(?:\\b(?:bearer|basic)\\s+[a-z0-9._~+/=-]+|\\b(?:sk|gsk|xai)-[a-z0-9_-]{12,}|\\bAIza[\\w-]{20,}|\\bAKIA[A-Z0-9]{12,}|eyJ[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\.|-----BEGIN [A-Z ]*PRIVATE KEY-----)/u;\nconst LONE_SURROGATE = /[\\ud800-\\udbff](?![\\udc00-\\udfff])|(?<![\\ud800-\\udbff])[\\udc00-\\udfff]/u;\nconst DIAGNOSTIC_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u;\nconst textEncoder = new TextEncoder();\nlet diagnosticSequence = 0;\n\ninterface DescriptorReadState {\n readonly seen: Set<object>;\n nodes: number;\n properties: number;\n}\n\nfunction invalidAgentRunError(): never {\n throw new AgentRunErrorValidationError();\n}\n\nfunction readDescriptorRecord(\n value: unknown,\n state: DescriptorReadState,\n depth: number,\n): Record<string, unknown> {\n if (\n value === null ||\n typeof value !== 'object' ||\n Array.isArray(value) ||\n depth > AGENT_RUN_ERROR_LIMITS.maxDepth\n ) invalidAgentRunError();\n const prototype = Object.getPrototypeOf(value) as unknown;\n if (prototype !== Object.prototype && prototype !== null) invalidAgentRunError();\n if (state.seen.has(value)) invalidAgentRunError();\n state.nodes += 1;\n if (state.nodes > AGENT_RUN_ERROR_LIMITS.maxNodes) invalidAgentRunError();\n state.seen.add(value);\n const keys = Reflect.ownKeys(value);\n state.properties += keys.length;\n if (state.properties > AGENT_RUN_ERROR_LIMITS.maxProperties) invalidAgentRunError();\n const record: Record<string, unknown> = {};\n for (const key of keys) {\n if (typeof key !== 'string') invalidAgentRunError();\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (!descriptor?.enumerable || !('value' in descriptor)) invalidAgentRunError();\n record[key] = descriptor.value as unknown;\n }\n return record;\n}\n\nfunction exactKeys(record: Record<string, unknown>, allowed: ReadonlySet<string>): void {\n if (Object.keys(record).some(key => !allowed.has(key))) invalidAgentRunError();\n}\n\nfunction boundedSafeText(\n value: unknown,\n maximumBytes: number,\n options: { diagnostic?: boolean } = {},\n): value is string {\n return typeof value === 'string' &&\n value.length > 0 &&\n value.trim() === value &&\n textEncoder.encode(value).byteLength <= maximumBytes &&\n !hasControlCharacter(value) &&\n !LONE_SURROGATE.test(value) &&\n !SECRET_SHAPE.test(value) &&\n (!options.diagnostic || DIAGNOSTIC_ID.test(value));\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 0x1F || code === 0x7F) return true;\n }\n return false;\n}\n\nfunction safeFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' &&\n Number.isFinite(value) &&\n Math.abs(value) <= Number.MAX_SAFE_INTEGER;\n}\n\nfunction isAgentRunProviderSettingField(\n value: unknown,\n): value is AgentRunProviderSettingField {\n return AGENT_RUN_PROVIDER_SETTING_FIELD_SET.has(value as AgentRunProviderSettingField);\n}\n\nfunction normalizeAgentRunErrorLocalizationParameters(\n value: unknown,\n state: DescriptorReadState,\n): Readonly<AgentRunErrorLocalizationParameters> | undefined {\n if (value === undefined) return undefined;\n const input = readDescriptorRecord(value, state, 2);\n exactKeys(input, LOCALIZATION_PARAM_KEYS);\n if (\n input.providerId !== undefined &&\n !boundedSafeText(input.providerId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) ||\n input.modelId !== undefined &&\n !boundedSafeText(input.modelId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) ||\n input.settingField !== undefined && !isAgentRunProviderSettingField(input.settingField) ||\n input.retryAfterMs !== undefined &&\n (!safeFiniteNumber(input.retryAfterMs) || input.retryAfterMs < 0) ||\n input.requested !== undefined &&\n (!safeFiniteNumber(input.requested) || input.requested < 0) ||\n input.limit !== undefined && (!safeFiniteNumber(input.limit) || input.limit < 0) ||\n input.checkpointRevision !== undefined &&\n !boundedSafeText(input.checkpointRevision, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) ||\n input.processedMessages !== undefined &&\n (!safeFiniteNumber(input.processedMessages) ||\n !Number.isSafeInteger(input.processedMessages) || input.processedMessages < 0) ||\n input.remainingEstimate !== undefined &&\n (!safeFiniteNumber(input.remainingEstimate) ||\n !Number.isSafeInteger(input.remainingEstimate) || input.remainingEstimate < 1)\n ) invalidAgentRunError();\n const normalized: AgentRunErrorLocalizationParameters = {};\n if (typeof input.providerId === 'string') normalized.providerId = input.providerId;\n if (typeof input.modelId === 'string') normalized.modelId = input.modelId;\n if (isAgentRunProviderSettingField(input.settingField)) {\n normalized.settingField = input.settingField;\n }\n if (typeof input.retryAfterMs === 'number') normalized.retryAfterMs = input.retryAfterMs;\n if (typeof input.requested === 'number') normalized.requested = input.requested;\n if (typeof input.limit === 'number') normalized.limit = input.limit;\n if (typeof input.checkpointRevision === 'string') {\n normalized.checkpointRevision = input.checkpointRevision;\n }\n if (typeof input.processedMessages === 'number') {\n normalized.processedMessages = input.processedMessages;\n }\n if (typeof input.remainingEstimate === 'number') {\n normalized.remainingEstimate = input.remainingEstimate;\n }\n return Object.freeze(normalized);\n}\n\n/** Strictly validate and clone safe public error metadata. */\nexport function normalizeAgentRunError(value: unknown): AgentRunError {\n const state: DescriptorReadState = { seen: new Set(), nodes: 0, properties: 0 };\n const input = readDescriptorRecord(value, state, 1);\n exactKeys(input, ROOT_ERROR_KEYS);\n if (\n !AGENT_RUN_ERROR_CODE_SET.has(input.code as AgentRunErrorCode) ||\n input.messageKey !== AGENT_RUN_ERROR_MESSAGE_KEYS[input.code as AgentRunErrorCode] ||\n typeof input.retryable !== 'boolean' ||\n !boundedSafeText(\n input.diagnosticId,\n AGENT_RUN_ERROR_LIMITS.maxDiagnosticIdBytes,\n { diagnostic: true },\n ) ||\n input.providerId !== undefined &&\n !boundedSafeText(input.providerId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) ||\n input.modelId !== undefined &&\n !boundedSafeText(input.modelId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes)\n ) invalidAgentRunError();\n const localizedParameters = normalizeAgentRunErrorLocalizationParameters(\n input.localizedParams,\n state,\n );\n const settingTarget = normalizeAgentRunErrorSettingTarget(input.settingTarget, state);\n if (\n localizedParameters?.providerId !== undefined &&\n localizedParameters.providerId !== input.providerId ||\n localizedParameters?.modelId !== undefined && localizedParameters.modelId !== input.modelId ||\n settingTarget?.kind !== undefined &&\n settingTarget.kind !== 'runtime' && settingTarget.providerId !== input.providerId ||\n settingTarget?.kind === 'model' && settingTarget.modelId !== input.modelId ||\n settingTarget?.kind === 'provider' &&\n localizedParameters?.settingField !== undefined &&\n localizedParameters.settingField !== settingTarget.field\n ) invalidAgentRunError();\n const normalized: AgentRunError = {\n code: input.code as AgentRunErrorCode,\n messageKey: input.messageKey,\n retryable: input.retryable,\n diagnosticId: input.diagnosticId,\n };\n if (typeof input.providerId === 'string') normalized.providerId = input.providerId;\n if (typeof input.modelId === 'string') normalized.modelId = input.modelId;\n if (localizedParameters) normalized.localizedParams = localizedParameters;\n if (settingTarget) normalized.settingTarget = settingTarget;\n if (textEncoder.encode(JSON.stringify(normalized)).byteLength > AGENT_RUN_ERROR_LIMITS.maxTotalBytes) {\n invalidAgentRunError();\n }\n return Object.freeze(normalized);\n}\n\nfunction normalizeAgentRunErrorSettingTarget(\n value: unknown,\n state: DescriptorReadState,\n): AgentRunErrorSettingTarget | undefined {\n if (value === undefined) return undefined;\n const target = readDescriptorRecord(value, state, 2);\n if (\n target.kind === 'provider' &&\n boundedSafeText(target.providerId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) &&\n isAgentRunProviderSettingField(target.field) &&\n Object.keys(target).every(\n key => key === 'kind' || key === 'providerId' || key === 'field',\n )\n ) {\n return Object.freeze({\n kind: 'provider' as const,\n providerId: target.providerId,\n field: target.field,\n });\n }\n if (\n target.kind === 'model' &&\n boundedSafeText(target.providerId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) &&\n boundedSafeText(target.modelId, AGENT_RUN_ERROR_LIMITS.maxIdentifierBytes) &&\n Object.keys(target).every(key => key === 'kind' || key === 'providerId' || key === 'modelId')\n ) {\n return Object.freeze({\n kind: 'model' as const,\n providerId: target.providerId,\n modelId: target.modelId,\n });\n }\n if (\n target.kind === 'runtime' &&\n (target.section === 'agent' || target.section === 'network' || target.section === 'storage') &&\n Object.keys(target).every(key => key === 'kind' || key === 'section')\n ) return Object.freeze({ kind: 'runtime' as const, section: target.section });\n return invalidAgentRunError();\n}\n\nexport function assertAgentRunError(value: unknown): asserts value is AgentRunError {\n normalizeAgentRunError(value);\n}\n\nexport function isAgentRunError(value: unknown): value is AgentRunError {\n try {\n normalizeAgentRunError(value);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Throwable carrier whose Error message is always the stable public code. */\nexport class AgentRunFailure extends Error {\n readonly agentRunError: AgentRunError;\n\n constructor(agentRunError: AgentRunError) {\n const normalized = normalizeAgentRunError(agentRunError);\n super(normalized.code);\n this.name = 'AgentRunFailure';\n this.agentRunError = normalized;\n }\n}\n\nexport function isAgentRunFailure(value: unknown): value is AgentRunFailure {\n return value instanceof AgentRunFailure;\n}\n\n/** Extracts only a strict public contract; accessors and malformed wrappers are ignored. */\nexport function extractAgentRunError(value: unknown): AgentRunError | undefined {\n try {\n return normalizeAgentRunError(value);\n } catch {\n // Try an own descriptor-backed typed failure wrapper.\n }\n if (value === null || typeof value !== 'object') return undefined;\n const descriptor = Object.getOwnPropertyDescriptor(value, 'agentRunError');\n if (!descriptor || !('value' in descriptor)) return undefined;\n try {\n return normalizeAgentRunError(descriptor.value);\n } catch {\n return undefined;\n }\n}\n\nexport function createAgentRunDiagnosticId(): string {\n try {\n if (typeof globalThis.crypto?.randomUUID === 'function') {\n return `agent-${globalThis.crypto.randomUUID()}`;\n }\n } catch {\n // Fall through to the portable monotonic fallback.\n }\n diagnosticSequence = (diagnosticSequence + 1) % Number.MAX_SAFE_INTEGER;\n return `agent-${Date.now().toString(36)}-${diagnosticSequence.toString(36)}`;\n}\n\nexport type CreateAgentRunErrorInput = Omit<AgentRunError, 'diagnosticId'> & {\n diagnosticId?: string;\n};\n\nexport function createAgentRunError(input: CreateAgentRunErrorInput): AgentRunError {\n const state: DescriptorReadState = { seen: new Set(), nodes: 0, properties: 0 };\n const descriptorInput = readDescriptorRecord(input, state, 1);\n exactKeys(descriptorInput, ROOT_ERROR_KEYS);\n return normalizeAgentRunError({\n ...descriptorInput,\n diagnosticId: descriptorInput.diagnosticId ?? createAgentRunDiagnosticId(),\n });\n}\n\nexport interface CreateMissingProviderSettingAgentRunErrorInput {\n providerId: string;\n field: AgentRunProviderSettingField;\n modelId?: string;\n diagnosticId?: string;\n}\n\n/** Creates safe settings-navigation metadata without accepting a setting value. */\nexport function createMissingProviderSettingAgentRunError(\n input: CreateMissingProviderSettingAgentRunErrorInput,\n): AgentRunError {\n const state: DescriptorReadState = { seen: new Set(), nodes: 0, properties: 0 };\n const descriptorInput = readDescriptorRecord(input, state, 1);\n exactKeys(descriptorInput, new Set(['providerId', 'field', 'modelId', 'diagnosticId']));\n const code: AgentRunErrorCode = descriptorInput.field === 'apiKey'\n ? 'PROVIDER_AUTH_MISSING'\n : 'PROVIDER_CONFIGURATION_MISSING';\n return createAgentRunError({\n code,\n messageKey: AGENT_RUN_ERROR_MESSAGE_KEYS[code],\n retryable: false,\n providerId: descriptorInput.providerId as string,\n ...(descriptorInput.modelId === undefined\n ? {}\n : { modelId: descriptorInput.modelId as string }),\n localizedParams: {\n providerId: descriptorInput.providerId as string,\n ...(descriptorInput.modelId === undefined\n ? {}\n : { modelId: descriptorInput.modelId as string }),\n settingField: descriptorInput.field as AgentRunProviderSettingField,\n },\n settingTarget: {\n kind: 'provider',\n providerId: descriptorInput.providerId as string,\n field: descriptorInput.field as AgentRunProviderSettingField,\n },\n ...(descriptorInput.diagnosticId === undefined\n ? {}\n : { diagnosticId: descriptorInput.diagnosticId as string }),\n });\n}\n\nexport type CreateMissingApiKeyAgentRunErrorInput = Omit<\n CreateMissingProviderSettingAgentRunErrorInput,\n 'field'\n>;\n\nexport function createMissingApiKeyAgentRunError(\n input: CreateMissingApiKeyAgentRunErrorInput,\n): AgentRunError {\n const state: DescriptorReadState = { seen: new Set(), nodes: 0, properties: 0 };\n const descriptorInput = readDescriptorRecord(input, state, 1);\n exactKeys(descriptorInput, new Set(['providerId', 'modelId', 'diagnosticId']));\n return createMissingProviderSettingAgentRunError({\n providerId: descriptorInput.providerId as string,\n ...(descriptorInput.modelId === undefined\n ? {}\n : { modelId: descriptorInput.modelId as string }),\n ...(descriptorInput.diagnosticId === undefined\n ? {}\n : { diagnosticId: descriptorInput.diagnosticId as string }),\n field: 'apiKey',\n });\n}\n\n/** Fail-closed conversion that never persists raw exception messages/bodies. */\nexport function agentRunErrorFromUnknown(error: unknown): AgentRunError {\n const extracted = extractAgentRunError(error);\n if (extracted) return extracted;\n if (error instanceof Error) {\n const descriptor = Object.getOwnPropertyDescriptor(error, 'message');\n const message = descriptor && 'value' in descriptor\n ? descriptor.value as unknown\n : undefined;\n if (typeof message === 'string' && message.startsWith('RUNNER_UNAVAILABLE:')) {\n return createAgentRunError({\n code: 'RUNNER_UNAVAILABLE',\n messageKey: AGENT_RUN_ERROR_MESSAGE_KEYS.RUNNER_UNAVAILABLE,\n retryable: false,\n });\n }\n }\n return createAgentRunError({\n code: 'INTERNAL',\n messageKey: AGENT_RUN_ERROR_MESSAGE_KEYS.INTERNAL,\n retryable: false,\n });\n}\n\nexport interface AgentRunPruneOptions {\n finishedBefore: number;\n maxRecords: number;\n}\n\n/**\n * Durable lifecycle/idempotency port. `createOrGet` atomically owns the\n * unique `(requestPeerId, requestId)` key, returns an existing record only\n * when its payload digest matches, and rejects payload drift.\n */\nexport interface AgentRunStateStore {\n createOrGet(record: AgentRunRecord): Promise<AgentRunRecord>;\n get(runId: string): Promise<AgentRunRecord | undefined>;\n /** Indexed replay lookup for the durable idempotency key. */\n getByRequest(requestPeerId: string, requestId: string): Promise<AgentRunRecord | undefined>;\n getByTurn(\n conversationId: string,\n turnId: string,\n requestPeerId: string,\n ): Promise<AgentRunRecord | undefined>;\n /** Atomic lifecycle CAS. Terminal records must never transition again. */\n transition(\n runId: string,\n expectedStates: readonly AgentRunState[],\n next: AgentRunRecord,\n ): Promise<boolean>;\n listActive(): Promise<AgentRunRecord[]>;\n prune(options: AgentRunPruneOptions): Promise<void>;\n}\n\nexport class AgentRunRequestConflictError extends Error {\n constructor(requestPeerId: string, requestId: string) {\n super(`Run request payload drift for ${requestPeerId}/${requestId}`);\n this.name = 'AgentRunRequestConflictError';\n }\n}\n\n/** Test/embedder fallback. Production hosts should inject a durable store. */\nexport class MemoryAgentRunStateStore implements AgentRunStateStore {\n private readonly records = new Map<string, AgentRunRecord>();\n private readonly requestIndex = new Map<string, string>();\n\n private requestKey(requestPeerId: string, requestId: string): string {\n return JSON.stringify([requestPeerId, requestId]);\n }\n\n async createOrGet(record: AgentRunRecord): Promise<AgentRunRecord> {\n const normalized = cloneAgentRunRecord(record);\n const key = this.requestKey(normalized.requestPeerId, normalized.requestId);\n const existingId = this.requestIndex.get(key);\n if (existingId) {\n const existing = this.records.get(existingId);\n if (!existing) throw new Error(`Run request index is corrupt: ${existingId}`);\n if (existing.payloadDigest !== normalized.payloadDigest) {\n throw new AgentRunRequestConflictError(normalized.requestPeerId, normalized.requestId);\n }\n return cloneAgentRunRecord(existing);\n }\n this.records.set(normalized.runId, normalized);\n this.requestIndex.set(key, normalized.runId);\n return cloneAgentRunRecord(normalized);\n }\n\n async get(runId: string): Promise<AgentRunRecord | undefined> {\n const record = this.records.get(runId);\n return record ? cloneAgentRunRecord(record) : undefined;\n }\n\n async getByRequest(\n requestPeerId: string,\n requestId: string,\n ): Promise<AgentRunRecord | undefined> {\n const runId = this.requestIndex.get(this.requestKey(requestPeerId, requestId));\n if (!runId) return undefined;\n const record = this.records.get(runId);\n if (!record) throw new Error(`Run request index is corrupt: ${runId}`);\n return cloneAgentRunRecord(record);\n }\n\n async getByTurn(\n conversationId: string,\n turnId: string,\n requestPeerId: string,\n ): Promise<AgentRunRecord | undefined> {\n const record = [...this.records.values()].find(candidate =>\n candidate.conversationId === conversationId &&\n candidate.turnId === turnId &&\n candidate.requestPeerId === requestPeerId\n );\n return record ? cloneAgentRunRecord(record) : undefined;\n }\n\n async transition(\n runId: string,\n expectedStates: readonly AgentRunState[],\n record: AgentRunRecord,\n ): Promise<boolean> {\n const normalized = cloneAgentRunRecord(record);\n const existing = this.records.get(record.runId);\n if (!existing || runId !== record.runId || !expectedStates.includes(existing.state)) return false;\n const legalNext: Record<'accepted' | 'queued' | 'running', readonly AgentRunState[]> = {\n accepted: ['queued', 'failed', 'cancelled'],\n queued: ['running', 'failed', 'cancelled'],\n running: ['completed', 'failed', 'cancelled'],\n };\n if (\n (existing.state === 'completed' || existing.state === 'failed' || existing.state === 'cancelled') ||\n !legalNext[existing.state].includes(record.state)\n ) return false;\n if (\n existing.requestPeerId !== record.requestPeerId ||\n existing.requestId !== record.requestId ||\n existing.payloadDigest !== record.payloadDigest ||\n existing.retrySourceTurnId !== record.retrySourceTurnId ||\n existing.conversationId !== record.conversationId ||\n existing.definitionId !== record.definitionId ||\n existing.turnId !== record.turnId\n ) {\n throw new Error(`Cannot change immutable run identity: ${record.runId}`);\n }\n this.records.set(record.runId, normalized);\n this.requestIndex.set(this.requestKey(record.requestPeerId, record.requestId), record.runId);\n return true;\n }\n\n async listActive(): Promise<AgentRunRecord[]> {\n return [...this.records.values()]\n .filter(record => record.state === 'accepted' || record.state === 'queued' || record.state === 'running')\n .map(record => cloneAgentRunRecord(record));\n }\n\n async prune(options: AgentRunPruneOptions): Promise<void> {\n for (const [runId, record] of this.records) {\n if (record.finishedAt !== undefined && record.finishedAt < options.finishedBefore) {\n this.deleteRecord(runId, record);\n }\n }\n const terminal = [...this.records.values()]\n .filter(record => record.finishedAt !== undefined)\n .sort((left, right) => left.updatedAt - right.updatedAt);\n while (this.records.size > options.maxRecords && terminal.length > 0) {\n const record = terminal.shift();\n if (record) this.deleteRecord(record.runId, record);\n }\n }\n\n private deleteRecord(runId: string, record: AgentRunRecord): void {\n this.records.delete(runId);\n this.requestIndex.delete(this.requestKey(record.requestPeerId, record.requestId));\n }\n}\n\nfunction cloneAgentRunRecord(record: AgentRunRecord): AgentRunRecord {\n return {\n ...record,\n ...(record.error ? { error: normalizeAgentRunError(record.error) } : {}),\n };\n}\n","import {\n assertCanonicalChatMessageProjection,\n canonicalConversationEventBytes,\n type ChatMessage,\n conversationEventToMessage,\n type ConversationMessagePayload,\n MAX_CONVERSATION_EVENT_BYTES,\n messageToConversationEvent,\n normalizeCanonicalConversationEvent,\n} from './conversation/index.js';\nimport { canonicalJsonBytes } from './encoding/canonicalJson.js';\nimport { AGENT_RUN_ERROR_MESSAGE_KEYS, AgentRunFailure, createAgentRunError } from './runState.js';\n\n/**\n * One user root must fit an ordinary 256 KiB message page including its page\n * envelope. Larger bodies belong in attachment/detail storage and are linked\n * from the bounded root event.\n */\nexport const CONVERSATION_MESSAGE_ADMISSION_LIMITS = Object.freeze(\n {\n canonicalMessageBytes: 248 * 1024,\n canonicalEventBytes: 252 * 1024,\n pagingEnvelopeBytes: 256 * 1024,\n } as const,\n);\n\nexport const AGENT_USER_MESSAGE_LIMITS = Object.freeze(\n {\n contentBytes: 240 * 1024,\n ...CONVERSATION_MESSAGE_ADMISSION_LIMITS,\n } as const,\n);\n\nexport type AgentUserMessageLimitKind = 'content' | 'canonical-message' | 'canonical-event';\n\nexport class AgentUserMessageLimitError extends AgentRunFailure {\n public readonly kind: AgentUserMessageLimitKind;\n public readonly requestedBytes: number;\n public readonly limitBytes: number;\n\n public constructor(kind: AgentUserMessageLimitKind, requestedBytes: number, limitBytes: number) {\n super(createAgentRunError({\n code: 'USER_MESSAGE_TOO_LARGE',\n messageKey: AGENT_RUN_ERROR_MESSAGE_KEYS.USER_MESSAGE_TOO_LARGE,\n retryable: false,\n localizedParams: { requested: requestedBytes, limit: limitBytes },\n }));\n this.name = 'AgentUserMessageLimitError';\n this.kind = kind;\n this.requestedBytes = requestedBytes;\n this.limitBytes = limitBytes;\n }\n}\n\nexport function assertAgentUserMessageContentWithinLimits(content: unknown): asserts content is string {\n if (typeof content !== 'string') throw new Error('invalid agent user message content');\n const contentBytes = new TextEncoder().encode(content).byteLength;\n if (contentBytes > AGENT_USER_MESSAGE_LIMITS.contentBytes) {\n throw new AgentUserMessageLimitError(\n 'content',\n contentBytes,\n AGENT_USER_MESSAGE_LIMITS.contentBytes,\n );\n }\n}\n\nexport function assertPendingAgentUserMessageWithinLimits(input: {\n readonly conversationId: string;\n readonly originNodeId: string;\n readonly timestamp: number;\n readonly message: ConversationMessagePayload;\n}): void {\n normalizeAgentUserMessageForAdmission({\n ...input.message,\n conversationId: input.conversationId,\n originNodeId: input.originNodeId,\n // Allocate against the largest legal coordinate representation. The\n // eventual durable event can only be equal or smaller.\n originSequence: Number.MAX_SAFE_INTEGER,\n lamportClock: Number.MAX_SAFE_INTEGER,\n timestamp: input.timestamp,\n });\n}\n\nexport function assertPendingConversationMessageWithinLimits(input: {\n readonly conversationId: string;\n readonly originNodeId: string;\n readonly timestamp: number;\n readonly message: ConversationMessagePayload;\n}): void {\n const candidate = {\n ...input.message,\n conversationId: input.conversationId,\n originNodeId: input.originNodeId,\n originSequence: Number.MAX_SAFE_INTEGER,\n lamportClock: Number.MAX_SAFE_INTEGER,\n timestamp: input.timestamp,\n };\n if (input.message.role === 'user') normalizeAgentUserMessageForAdmission(candidate);\n else normalizeConversationMessageForPagingAdmission(candidate);\n}\n\n/**\n * Normalize a locally generated assistant/tool payload before persistence.\n * Exact legacy/parts duplicates are removed first. If genuinely oversized,\n * a bounded Unicode-safe durable projection is stored with an explicit loss\n * marker; untrusted synced messages never use this projector.\n */\nexport function normalizeGeneratedConversationMessageForAdmission(input: {\n readonly conversationId: string;\n readonly originNodeId: string;\n readonly timestamp: number;\n readonly message: ConversationMessagePayload;\n}): ConversationMessagePayload {\n if (input.message.role === 'user') {\n assertPendingAgentUserMessageWithinLimits(input);\n return input.message;\n }\n const deduplicated = compactRedundantMessagePartsForPersistence(input.message);\n try {\n assertPendingConversationMessageWithinLimits({ ...input, message: deduplicated });\n return deduplicated;\n } catch (error) {\n if (!(error instanceof AgentUserMessageLimitError)) throw error;\n }\n\n const originalContentBytes = new TextEncoder().encode(deduplicated.content).byteLength;\n const structuredParts = (deduplicated.parts ?? []).filter(\n part => part.type !== 'text' && part.type !== 'reasoning',\n );\n const metadataVariants = projectedMetadataVariants(deduplicated.metadata);\n const maximumItemVariants = structuredParts.length > 0 || (deduplicated.toolCalls?.length ?? 0) > 0\n ? [2, 1]\n : [0];\n for (const maximumStructuredItems of maximumItemVariants) {\n const projectedParts = sampleEdges(structuredParts, maximumStructuredItems).map(part => {\n if (part.type !== 'tool-result') return part;\n return {\n type: 'tool-result' as const,\n ...(part.toolCallId === undefined ? {} : { toolCallId: part.toolCallId }),\n toolName: part.toolName,\n result: truncateUtf8(part.result, 24 * 1024),\n isError: part.isError,\n ...(part.detailRef === undefined ? {} : { detailRef: part.detailRef }),\n };\n });\n const projectedToolCalls = sampleEdges(\n deduplicated.toolCalls ?? [],\n maximumStructuredItems,\n );\n for (const metadataVariant of metadataVariants) {\n const projected: ConversationMessagePayload = {\n messageId: deduplicated.messageId,\n turnId: deduplicated.turnId,\n role: deduplicated.role,\n content: truncateUtf8(deduplicated.content, 48 * 1024),\n ...(projectedParts.length === 0 ? {} : { parts: projectedParts }),\n ...(projectedToolCalls.length === 0 ? {} : { toolCalls: projectedToolCalls }),\n ...(deduplicated.reasoning_content === undefined\n ? {}\n : { reasoning_content: truncateUtf8(deduplicated.reasoning_content, 12 * 1024) }),\n ...(deduplicated.attachments === undefined\n ? {}\n : { attachments: deduplicated.attachments.slice(0, 32) }),\n ...(deduplicated.detailRef === undefined ? {} : { detailRef: deduplicated.detailRef }),\n ...(deduplicated.contentType === undefined ? {} : { contentType: deduplicated.contentType }),\n metadata: {\n ...metadataVariant.value,\n durableProjection: {\n version: 1,\n originalContentBytes,\n contentTruncated: originalContentBytes > 48 * 1024,\n omittedStructuredParts: Math.max(0, structuredParts.length - projectedParts.length),\n omittedToolCalls: Math.max(\n 0,\n (deduplicated.toolCalls?.length ?? 0) - projectedToolCalls.length,\n ),\n ...(metadataVariant.omitted ? { omittedMetadata: true } : {}),\n capability: 'not-retained',\n },\n },\n };\n try {\n assertPendingConversationMessageWithinLimits({ ...input, message: projected });\n return projected;\n } catch (error) {\n if (!(error instanceof AgentUserMessageLimitError)) throw error;\n }\n }\n }\n throw new AgentUserMessageLimitError(\n 'canonical-message',\n CONVERSATION_MESSAGE_ADMISSION_LIMITS.canonicalMessageBytes + 1,\n CONVERSATION_MESSAGE_ADMISSION_LIMITS.canonicalMessageBytes,\n );\n}\n\nexport function compactRedundantMessagePartsForPersistence(\n message: ConversationMessagePayload,\n): ConversationMessagePayload {\n if (message.parts === undefined) return message;\n const matchingToolCalls = new Map(\n (message.toolCalls ?? []).map(call => [call.id, call]),\n );\n const matchingAttachments = new Map(\n (message.attachments ?? []).map(attachment => [attachment.contentHash, attachment]),\n );\n const parts = message.parts.filter(part =>\n !(part.type === 'text' && part.text === message.content) &&\n !(part.type === 'reasoning' && part.text === message.reasoning_content) &&\n !(part.type === 'tool-call' && (() => {\n const legacy = matchingToolCalls.get(part.toolCallId);\n return legacy !== undefined && legacy.toolName === part.toolName &&\n canonicalValuesEqual(legacy.arguments, part.arguments);\n })()) &&\n !(part.type === 'attachment' && (() => {\n const legacy = matchingAttachments.get(part.attachment.contentHash);\n return legacy !== undefined && canonicalValuesEqual(legacy, part.attachment);\n })())\n );\n const { parts: _parts, ...withoutParts } = message;\n return parts.length === 0 ? withoutParts : { ...withoutParts, parts };\n}\n\nfunction canonicalValuesEqual(left: unknown, right: unknown): boolean {\n try {\n const leftBytes = canonicalJsonBytes(left, {\n maxBytes: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n maxDepth: 32,\n maxNodes: 4_096,\n maxStringBytes: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n maxStringCodeUnits: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n });\n const rightBytes = canonicalJsonBytes(right, {\n maxBytes: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n maxDepth: 32,\n maxNodes: 4_096,\n maxStringBytes: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n maxStringCodeUnits: CONVERSATION_MESSAGE_ADMISSION_LIMITS.pagingEnvelopeBytes,\n });\n if (leftBytes.byteLength !== rightBytes.byteLength) return false;\n return leftBytes.every((byte, index) => byte === rightBytes[index]);\n } catch {\n return false;\n }\n}\n\nfunction sampleEdges<Value>(values: readonly Value[], maximum: number): Value[] {\n if (maximum <= 0) return [];\n if (values.length <= maximum) return [...values];\n if (maximum === 1) return values.slice(0, 1);\n const head = Math.ceil(maximum / 2);\n return [...values.slice(0, head), ...values.slice(values.length - (maximum - head))];\n}\n\nfunction projectedMetadataVariants(\n metadata: Record<string, unknown> | undefined,\n): Array<{ value: Record<string, unknown>; omitted: boolean }> {\n if (metadata === undefined) return [{ value: {}, omitted: false }];\n const full = descriptorSafeMetadataSubset(metadata, Reflect.ownKeys(metadata));\n const stable = descriptorSafeMetadataSubset(metadata, [\n 'modelUsage',\n 'containsToolCall',\n 'provenance',\n 'actorId',\n 'actorLabel',\n 'agentId',\n 'agentName',\n 'participantId',\n 'participantLabel',\n ]);\n return [\n { value: full, omitted: false },\n { value: stable, omitted: Object.keys(stable).length !== Object.keys(full).length },\n { value: {}, omitted: Object.keys(full).length > 0 },\n ];\n}\n\nfunction descriptorSafeMetadataSubset(\n metadata: Record<string, unknown>,\n keys: readonly PropertyKey[],\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key of keys) {\n if (typeof key !== 'string') continue;\n const descriptor = Object.getOwnPropertyDescriptor(metadata, key);\n if (!descriptor?.enumerable || !('value' in descriptor)) continue;\n result[key] = descriptor.value;\n }\n return result;\n}\n\nfunction truncateUtf8(value: string, maximumBytes: number): string {\n const encoded = new TextEncoder().encode(value);\n if (encoded.byteLength <= maximumBytes) return value;\n const decoder = new TextDecoder('utf-8', { fatal: true });\n for (let end = maximumBytes; end >= Math.max(0, maximumBytes - 3); end -= 1) {\n try {\n return decoder.decode(encoded.subarray(0, end));\n } catch {\n // Only a trailing partial code point can fail; UTF-8 code points use at most four bytes.\n }\n }\n return '';\n}\n\n/**\n * Strictly normalize and admit one user-root event. This validates content,\n * structured parts and metadata together so no alternate field can bypass the\n * paging/compaction ceiling.\n */\nexport function normalizeAgentUserMessageForAdmission(value: unknown): ChatMessage {\n const normalizedMessage = normalizeConversationMessageForPagingAdmission(value);\n if (normalizedMessage.role !== 'user' || normalizedMessage.messageId !== normalizedMessage.turnId) {\n throw new Error('invalid canonical user-root message');\n }\n assertAgentUserMessageContentWithinLimits(normalizedMessage.content);\n return normalizedMessage;\n}\n\n/** Admit every role before it can enter a 256 KiB full-content page. */\nexport function normalizeConversationMessageForPagingAdmission(value: unknown): ChatMessage {\n // Reject accessors, cycles and an unbounded object graph before schema code\n // observes any property.\n canonicalJsonBytes(value, {\n maxBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxDepth: 64,\n maxNodes: 200_000,\n maxStringBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxStringCodeUnits: MAX_CONVERSATION_EVENT_BYTES,\n });\n assertCanonicalChatMessageProjection(value);\n const normalizedEvent = normalizeCanonicalConversationEvent(messageToConversationEvent(value));\n if (normalizedEvent.kind !== 'message') throw new Error('invalid canonical conversation message event');\n const normalizedMessage = conversationEventToMessage(normalizedEvent);\n const messageBytes = canonicalJsonBytes(normalizedMessage, {\n maxBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxDepth: 64,\n maxNodes: 200_000,\n maxStringBytes: MAX_CONVERSATION_EVENT_BYTES,\n maxStringCodeUnits: MAX_CONVERSATION_EVENT_BYTES,\n }).byteLength;\n if (messageBytes > AGENT_USER_MESSAGE_LIMITS.canonicalMessageBytes) {\n throw new AgentUserMessageLimitError(\n 'canonical-message',\n messageBytes,\n AGENT_USER_MESSAGE_LIMITS.canonicalMessageBytes,\n );\n }\n const eventBytes = canonicalConversationEventBytes(normalizedEvent).byteLength;\n if (eventBytes > AGENT_USER_MESSAGE_LIMITS.canonicalEventBytes) {\n throw new AgentUserMessageLimitError(\n 'canonical-event',\n eventBytes,\n AGENT_USER_MESSAGE_LIMITS.canonicalEventBytes,\n );\n }\n return normalizedMessage;\n}\n\nexport function assertAgentUserMessageWithinLimits(value: unknown): asserts value is ChatMessage {\n normalizeAgentUserMessageForAdmission(value);\n}\n\nexport function assertConversationMessageWithinPagingLimits(value: unknown): asserts value is ChatMessage {\n normalizeConversationMessageForPagingAdmission(value);\n}\n","import type { AttachmentReference } from '../conversation/types.js';\n\nexport const ATTACHMENT_UPLOAD_RPC_METHODS = Object.freeze(\n {\n begin: 'memeloop.chat.beginAttachmentUpload',\n chunk: 'memeloop.chat.uploadAttachmentChunk',\n commit: 'memeloop.chat.commitAttachmentUpload',\n } as const,\n);\n\nexport const ATTACHMENT_UPLOAD_LIMITS = Object.freeze(\n {\n totalBytes: 64 * 1_024 * 1_024,\n chunkBytes: 3 * 1_024 * 1_024,\n chunkBase64Characters: 4 * 1_024 * 1_024,\n identifierCharacters: 512,\n filenameCharacters: 1_024,\n mimeTypeCharacters: 256,\n } as const,\n);\n\nexport const ATTACHMENT_UPLOAD_SHA256_PATTERN = /^sha256:[\\da-f]{64}$/u;\n\nexport type AttachmentUploadRpcMethod = typeof ATTACHMENT_UPLOAD_RPC_METHODS[keyof typeof ATTACHMENT_UPLOAD_RPC_METHODS];\n\nexport type AttachmentUploadStage = 'begin' | 'chunk' | 'commit';\n\ninterface AttachmentUploadOperationIdentity {\n /** Caller-generated durable idempotency key. Reuse it for transport retries. */\n requestId: string;\n /** Mandatory authorization and storage scope for every upload operation. */\n conversationId: string;\n}\n\nexport interface BeginAttachmentUploadRequest extends AttachmentUploadOperationIdentity {\n filename: string;\n mimeType: string;\n totalBytes: number;\n}\n\nexport interface BeginAttachmentUploadResponse extends AttachmentUploadOperationIdentity {\n ok: true;\n /** Durable opaque handle; callers must not parse or synthesize it. */\n uploadId: string;\n totalBytes: number;\n maxChunkBytes: number;\n}\n\nexport interface UploadAttachmentChunkRequest extends AttachmentUploadOperationIdentity {\n uploadId: string;\n offset: number;\n /** Must equal the strictly decoded byte count, not the base64 character count. */\n byteLength: number;\n encoding: 'base64';\n data: string;\n /** Optional integrity check over this decoded chunk. */\n sha256?: string;\n}\n\nexport interface UploadAttachmentChunkResponse extends AttachmentUploadOperationIdentity {\n ok: true;\n uploadId: string;\n offset: number;\n byteLength: number;\n}\n\nexport interface CommitAttachmentUploadRequest extends AttachmentUploadOperationIdentity {\n uploadId: string;\n /** Exact final byte count, checked against begin and persisted chunks. */\n size: number;\n /** Exact final digest and resulting content-addressed attachment hash. */\n sha256: string;\n}\n\nexport interface CommitAttachmentUploadResponse extends AttachmentUploadOperationIdentity {\n ok: true;\n uploadId: string;\n attachment: AttachmentReference;\n}\n\nexport interface AttachmentUploadRpcContract {\n [ATTACHMENT_UPLOAD_RPC_METHODS.begin]: {\n request: BeginAttachmentUploadRequest;\n response: BeginAttachmentUploadResponse;\n };\n [ATTACHMENT_UPLOAD_RPC_METHODS.chunk]: {\n request: UploadAttachmentChunkRequest;\n response: UploadAttachmentChunkResponse;\n };\n [ATTACHMENT_UPLOAD_RPC_METHODS.commit]: {\n request: CommitAttachmentUploadRequest;\n response: CommitAttachmentUploadResponse;\n };\n}\n\nexport type AttachmentUploadRpcRequest<M extends AttachmentUploadRpcMethod> = AttachmentUploadRpcContract[M]['request'];\n\nexport type AttachmentUploadRpcResponse<M extends AttachmentUploadRpcMethod> = AttachmentUploadRpcContract[M]['response'];\n\nexport class AttachmentUploadProtocolError extends Error {\n readonly code = 'invalid_attachment_upload' as const;\n\n constructor(readonly field: string) {\n super(`Invalid attachment upload ${field}`);\n this.name = 'AttachmentUploadProtocolError';\n }\n}\n\n/** Raised by a durable store when an idempotency key or chunk offset drifts. */\nexport class AttachmentUploadConflictError extends Error {\n readonly code = 'attachment_upload_conflict' as const;\n\n constructor(\n readonly stage: AttachmentUploadStage,\n readonly requestId: string,\n ) {\n super(`Attachment upload ${stage} request conflicts with an existing operation`);\n this.name = 'AttachmentUploadConflictError';\n }\n}\n\nexport interface AttachmentUploadStoreContext {\n /** Authenticated transport principal; never sourced from caller parameters. */\n ownerPeerId: string;\n signal?: AbortSignal;\n}\n\nexport interface AttachmentUploadIdempotencyRecord {\n stage: AttachmentUploadStage;\n ownerPeerId: string;\n conversationId: string;\n requestId: string;\n fingerprint: string;\n}\n\nexport interface PersistAttachmentUploadChunkInput extends Omit<UploadAttachmentChunkRequest, 'encoding' | 'data'> {\n /** Strictly decoded and, when requested, SHA-256 verified bytes. */\n data: Uint8Array;\n}\n\n/**\n * Durable streaming upload port. Implementations must not buffer a complete\n * upload in process memory. They must scope uploadId to conversationId and\n * the authenticated `ownerPeerId`, account quota/expiry to that owner, and\n * atomically enforce these idempotency rules:\n *\n * - the same `(stage, conversationId, requestId)` and operation fingerprint\n * returns the stored result;\n * - reusing that key with another fingerprint throws\n * `AttachmentUploadConflictError`;\n * - the same chunk operation at `(conversationId, uploadId, offset)` returns\n * the same result, while a different request, bytes, or length conflicts;\n * - a repeated identical commit returns its original attachment, while size\n * or digest drift conflicts.\n */\nexport interface AttachmentUploadStore {\n beginAttachmentUpload(\n request: BeginAttachmentUploadRequest,\n context: AttachmentUploadStoreContext,\n ): Promise<BeginAttachmentUploadResponse>;\n writeAttachmentUploadChunk(\n request: PersistAttachmentUploadChunkInput,\n context: AttachmentUploadStoreContext,\n ): Promise<UploadAttachmentChunkResponse>;\n commitAttachmentUpload(\n request: CommitAttachmentUploadRequest,\n context: AttachmentUploadStoreContext,\n ): Promise<CommitAttachmentUploadResponse>;\n}\n\nexport interface AttachmentUploadRpcCallOptions {\n signal?: AbortSignal;\n}\n\nexport type AttachmentUploadRpcCall = <M extends AttachmentUploadRpcMethod>(\n method: M,\n request: AttachmentUploadRpcRequest<M>,\n options?: AttachmentUploadRpcCallOptions,\n) => Promise<unknown>;\n\nexport interface AttachmentUploadRpcClientOptions {\n call: AttachmentUploadRpcCall;\n}\n\n/**\n * Typed browser/mobile client over an injected RPC call. This only streams\n * bounded chunks; it intentionally provides no full-file buffering fallback.\n */\nexport function createAttachmentUploadRpcClient(\n options: AttachmentUploadRpcClientOptions,\n) {\n async function request<M extends AttachmentUploadRpcMethod>(\n method: M,\n parameters: AttachmentUploadRpcRequest<M>,\n callOptions: AttachmentUploadRpcCallOptions = {},\n ): Promise<AttachmentUploadRpcResponse<M>> {\n callOptions.signal?.throwIfAborted();\n assertAttachmentUploadRpcRequest(method, parameters);\n if (method === ATTACHMENT_UPLOAD_RPC_METHODS.chunk) {\n await decodeAttachmentUploadChunk(parameters as UploadAttachmentChunkRequest);\n }\n callOptions.signal?.throwIfAborted();\n const raw = await options.call(method, parameters, callOptions);\n const response = parseAttachmentUploadRpcResponse(method, raw);\n assertAttachmentUploadRpcResponseCorrelation(method, parameters, response);\n return response;\n }\n\n return {\n begin: (\n parameters: BeginAttachmentUploadRequest,\n callOptions: AttachmentUploadRpcCallOptions = {},\n ) => request(ATTACHMENT_UPLOAD_RPC_METHODS.begin, parameters, callOptions),\n chunk: (\n parameters: UploadAttachmentChunkRequest,\n callOptions: AttachmentUploadRpcCallOptions = {},\n ) => request(ATTACHMENT_UPLOAD_RPC_METHODS.chunk, parameters, callOptions),\n commit: (\n parameters: CommitAttachmentUploadRequest,\n callOptions: AttachmentUploadRpcCallOptions = {},\n ) => request(ATTACHMENT_UPLOAD_RPC_METHODS.commit, parameters, callOptions),\n };\n}\n\nexport type AttachmentUploadRpcClient = ReturnType<typeof createAttachmentUploadRpcClient>;\n\n/** Validate an untrusted request, including actual base64 decoding for chunks. */\nexport function assertAttachmentUploadRpcRequest<M extends AttachmentUploadRpcMethod>(\n method: M,\n value: unknown,\n): asserts value is AttachmentUploadRpcRequest<M> {\n const record = asRecord(value, 'request');\n assertOperationIdentity(record, 'request');\n switch (method) {\n case ATTACHMENT_UPLOAD_RPC_METHODS.begin:\n assertExactKeys(record, [\n 'requestId',\n 'conversationId',\n 'filename',\n 'mimeType',\n 'totalBytes',\n ], 'request');\n assertText(record.filename, 'request.filename', ATTACHMENT_UPLOAD_LIMITS.filenameCharacters);\n assertText(record.mimeType, 'request.mimeType', ATTACHMENT_UPLOAD_LIMITS.mimeTypeCharacters);\n assertInteger(record.totalBytes, 'request.totalBytes', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n return;\n case ATTACHMENT_UPLOAD_RPC_METHODS.chunk: {\n assertExactKeys(record, [\n 'requestId',\n 'conversationId',\n 'uploadId',\n 'offset',\n 'byteLength',\n 'encoding',\n 'data',\n 'sha256',\n ], 'request');\n assertIdentifier(record.uploadId, 'request.uploadId');\n assertInteger(record.offset, 'request.offset', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n assertInteger(record.byteLength, 'request.byteLength', 1, ATTACHMENT_UPLOAD_LIMITS.chunkBytes);\n if (\n record.offset + record.byteLength >\n ATTACHMENT_UPLOAD_LIMITS.totalBytes\n ) fail('request.offset');\n if (record.encoding !== 'base64') fail('request.encoding');\n if (typeof record.data !== 'string') fail('request.data');\n const bytes = attachmentUploadBase64ToBytes(record.data);\n if (bytes.byteLength !== record.byteLength) fail('request.byteLength');\n if (record.sha256 !== undefined) assertSha256(record.sha256, 'request.sha256');\n return;\n }\n case ATTACHMENT_UPLOAD_RPC_METHODS.commit:\n assertExactKeys(record, [\n 'requestId',\n 'conversationId',\n 'uploadId',\n 'size',\n 'sha256',\n ], 'request');\n assertIdentifier(record.uploadId, 'request.uploadId');\n assertInteger(record.size, 'request.size', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n assertSha256(record.sha256, 'request.sha256');\n return;\n }\n}\n\n/** Parse and bound an untrusted successful response. */\nexport function parseAttachmentUploadRpcResponse<M extends AttachmentUploadRpcMethod>(\n method: M,\n value: unknown,\n): AttachmentUploadRpcResponse<M> {\n const record = asRecord(value, 'response');\n if (record.ok !== true) fail('response.ok');\n assertOperationIdentity(record, 'response');\n switch (method) {\n case ATTACHMENT_UPLOAD_RPC_METHODS.begin:\n assertExactKeys(record, [\n 'ok',\n 'requestId',\n 'conversationId',\n 'uploadId',\n 'totalBytes',\n 'maxChunkBytes',\n ], 'response');\n assertIdentifier(record.uploadId, 'response.uploadId');\n assertInteger(record.totalBytes, 'response.totalBytes', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n assertInteger(record.maxChunkBytes, 'response.maxChunkBytes', 1, ATTACHMENT_UPLOAD_LIMITS.chunkBytes);\n break;\n case ATTACHMENT_UPLOAD_RPC_METHODS.chunk:\n assertExactKeys(record, [\n 'ok',\n 'requestId',\n 'conversationId',\n 'uploadId',\n 'offset',\n 'byteLength',\n ], 'response');\n assertIdentifier(record.uploadId, 'response.uploadId');\n assertInteger(record.offset, 'response.offset', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n assertInteger(record.byteLength, 'response.byteLength', 1, ATTACHMENT_UPLOAD_LIMITS.chunkBytes);\n break;\n case ATTACHMENT_UPLOAD_RPC_METHODS.commit:\n assertExactKeys(record, [\n 'ok',\n 'requestId',\n 'conversationId',\n 'uploadId',\n 'attachment',\n ], 'response');\n assertIdentifier(record.uploadId, 'response.uploadId');\n assertAttachmentReference(record.attachment, 'response.attachment');\n break;\n }\n return value as AttachmentUploadRpcResponse<M>;\n}\n\n/** Reject a valid-shaped response from another upload operation or scope. */\nexport function assertAttachmentUploadRpcResponseCorrelation<M extends AttachmentUploadRpcMethod>(\n method: M,\n request: AttachmentUploadRpcRequest<M>,\n response: AttachmentUploadRpcResponse<M>,\n): void {\n if (\n response.requestId !== request.requestId ||\n response.conversationId !== request.conversationId\n ) fail('response');\n switch (method) {\n case ATTACHMENT_UPLOAD_RPC_METHODS.begin: {\n const beginRequest = request as BeginAttachmentUploadRequest;\n const beginResponse = response as BeginAttachmentUploadResponse;\n if (beginResponse.totalBytes !== beginRequest.totalBytes) fail('response.totalBytes');\n return;\n }\n case ATTACHMENT_UPLOAD_RPC_METHODS.chunk: {\n const chunkRequest = request as UploadAttachmentChunkRequest;\n const chunkResponse = response as UploadAttachmentChunkResponse;\n if (\n chunkResponse.uploadId !== chunkRequest.uploadId ||\n chunkResponse.offset !== chunkRequest.offset ||\n chunkResponse.byteLength !== chunkRequest.byteLength\n ) fail('response');\n return;\n }\n case ATTACHMENT_UPLOAD_RPC_METHODS.commit: {\n const commitRequest = request as CommitAttachmentUploadRequest;\n const commitResponse = response as CommitAttachmentUploadResponse;\n if (\n commitResponse.uploadId !== commitRequest.uploadId ||\n commitResponse.attachment.contentHash !== commitRequest.sha256 ||\n commitResponse.attachment.size !== commitRequest.size\n ) fail('response.attachment');\n return;\n }\n }\n}\n\n/**\n * Strictly decode a chunk and verify its optional SHA-256 before storage. The\n * returned bytes are independently owned and safe to pass to an async store.\n */\nexport async function decodeAttachmentUploadChunk(\n request: UploadAttachmentChunkRequest,\n): Promise<Uint8Array> {\n assertAttachmentUploadRpcRequest(ATTACHMENT_UPLOAD_RPC_METHODS.chunk, request);\n const bytes = attachmentUploadBase64ToBytes(request.data);\n if (request.sha256 !== undefined && await sha256AttachmentUploadBytes(bytes) !== request.sha256) {\n fail('request.sha256');\n }\n return bytes;\n}\n\nexport interface BuildAttachmentUploadChunkRequestInput extends Omit<UploadAttachmentChunkRequest, 'encoding' | 'data' | 'byteLength' | 'sha256'> {\n data: Uint8Array;\n /** Include a portable WebCrypto SHA-256 integrity check for this chunk. */\n includeSha256?: boolean;\n}\n\n/** Encode already-bounded bytes into the canonical chunk wire request. */\nexport async function buildAttachmentUploadChunkRequest(\n input: BuildAttachmentUploadChunkRequestInput,\n): Promise<UploadAttachmentChunkRequest> {\n const normalized = normalizeBuildAttachmentUploadChunkRequestInput(input);\n const data = normalizePortableUint8Array(\n normalized.data,\n 'request.data',\n 1,\n ATTACHMENT_UPLOAD_LIMITS.chunkBytes,\n 'request.byteLength',\n );\n const request: UploadAttachmentChunkRequest = {\n requestId: normalized.requestId,\n conversationId: normalized.conversationId,\n uploadId: normalized.uploadId,\n offset: normalized.offset,\n byteLength: data.byteLength,\n encoding: 'base64',\n data: encodeAttachmentUploadOwnedBytes(data),\n ...(normalized.includeSha256\n ? { sha256: await sha256OwnedAttachmentUploadBytes(data) }\n : {}),\n };\n assertAttachmentUploadRpcRequest(ATTACHMENT_UPLOAD_RPC_METHODS.chunk, request);\n return request;\n}\n\n/** Canonical operation digest suitable for a durable idempotency record. */\nexport async function fingerprintAttachmentUploadOperation<M extends AttachmentUploadRpcMethod>(\n method: M,\n request: AttachmentUploadRpcRequest<M>,\n): Promise<string> {\n assertAttachmentUploadRpcRequest(method, request);\n const canonical = method === ATTACHMENT_UPLOAD_RPC_METHODS.begin\n ? canonicalBegin(request as BeginAttachmentUploadRequest)\n : method === ATTACHMENT_UPLOAD_RPC_METHODS.chunk\n ? canonicalChunk(request as UploadAttachmentChunkRequest)\n : canonicalCommit(request as CommitAttachmentUploadRequest);\n return sha256AttachmentUploadBytes(new TextEncoder().encode(canonical));\n}\n\n/** Build the small durable record used to compare a retry with its first operation. */\nexport async function buildAttachmentUploadIdempotencyRecord<M extends AttachmentUploadRpcMethod>(\n method: M,\n request: AttachmentUploadRpcRequest<M>,\n ownerPeerId: string,\n): Promise<AttachmentUploadIdempotencyRecord> {\n assertIdentifier(ownerPeerId, 'ownerPeerId');\n return {\n stage: attachmentUploadStage(method),\n ownerPeerId,\n conversationId: request.conversationId,\n requestId: request.requestId,\n fingerprint: await fingerprintAttachmentUploadOperation(method, request),\n };\n}\n\n/** Accept an identical retry or throw the standard conflict for any drift. */\nexport async function assertAttachmentUploadIdempotentReplay<M extends AttachmentUploadRpcMethod>(\n existing: AttachmentUploadIdempotencyRecord,\n method: M,\n request: AttachmentUploadRpcRequest<M>,\n ownerPeerId: string,\n): Promise<void> {\n const next = await buildAttachmentUploadIdempotencyRecord(method, request, ownerPeerId);\n if (\n existing.stage !== next.stage ||\n existing.ownerPeerId !== next.ownerPeerId ||\n existing.conversationId !== next.conversationId ||\n existing.requestId !== next.requestId ||\n existing.fingerprint !== next.fingerprint\n ) {\n throw new AttachmentUploadConflictError(next.stage, next.requestId);\n }\n}\n\nexport async function sha256AttachmentUploadBytes(bytes: Uint8Array): Promise<string> {\n const owned = normalizePortableUint8Array(\n bytes,\n 'sha256.input',\n 0,\n ATTACHMENT_UPLOAD_LIMITS.totalBytes,\n 'sha256.input',\n );\n return sha256OwnedAttachmentUploadBytes(owned);\n}\n\nasync function sha256OwnedAttachmentUploadBytes(owned: Uint8Array<ArrayBuffer>): Promise<string> {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) fail('sha256.unavailable');\n const digest = new Uint8Array(await subtle.digest('SHA-256', owned));\n return `sha256:${[...digest].map(byte => byte.toString(16).padStart(2, '0')).join('')}`;\n}\n\n/** Strict canonical RFC 4648 base64 decoder with no Node Buffer dependency. */\nexport function attachmentUploadBase64ToBytes(value: string): Uint8Array {\n if (\n value.length === 0 ||\n value.length > ATTACHMENT_UPLOAD_LIMITS.chunkBase64Characters ||\n value.length % 4 !== 0 ||\n !/^(?:[A-Za-z\\d+/]{4})*(?:[A-Za-z\\d+/]{2}==|[A-Za-z\\d+/]{3}=)?$/u.test(value)\n ) fail('request.data');\n const padding = value.endsWith('==') ? 2 : value.endsWith('=') ? 1 : 0;\n const byteLength = (value.length / 4) * 3 - padding;\n if (byteLength <= 0 || byteLength > ATTACHMENT_UPLOAD_LIMITS.chunkBytes) {\n fail('request.data');\n }\n const result = new Uint8Array(byteLength);\n let writeOffset = 0;\n for (let offset = 0; offset < value.length; offset += 4) {\n const bits = (base64Value(value.charCodeAt(offset)) << 18) |\n (base64Value(value.charCodeAt(offset + 1)) << 12) |\n (value[offset + 2] === '=' ? 0 : base64Value(value.charCodeAt(offset + 2)) << 6) |\n (value[offset + 3] === '=' ? 0 : base64Value(value.charCodeAt(offset + 3)));\n if (writeOffset < byteLength) result[writeOffset++] = (bits >>> 16) & 0xFF;\n if (writeOffset < byteLength) result[writeOffset++] = (bits >>> 8) & 0xFF;\n if (writeOffset < byteLength) result[writeOffset++] = bits & 0xFF;\n }\n if (encodeAttachmentUploadOwnedBytes(result) !== value) fail('request.data');\n return result;\n}\n\n/** Canonical RFC 4648 base64 encoder with no Node Buffer/btoa dependency. */\nexport function attachmentUploadBytesToBase64(bytes: Uint8Array): string {\n const owned = normalizePortableUint8Array(\n bytes,\n 'request.data',\n 0,\n ATTACHMENT_UPLOAD_LIMITS.chunkBytes,\n 'request.byteLength',\n );\n return encodeAttachmentUploadOwnedBytes(owned);\n}\n\nfunction encodeAttachmentUploadOwnedBytes(bytes: Uint8Array): string {\n const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n let encoded = '';\n for (let offset = 0; offset < bytes.length; offset += 3) {\n const remaining = bytes.length - offset;\n const bits = (bytes[offset] << 16) |\n ((remaining > 1 ? bytes[offset + 1] : 0) << 8) |\n (remaining > 2 ? bytes[offset + 2] : 0);\n encoded += alphabet[(bits >>> 18) & 63];\n encoded += alphabet[(bits >>> 12) & 63];\n encoded += remaining > 1 ? alphabet[(bits >>> 6) & 63] : '=';\n encoded += remaining > 2 ? alphabet[bits & 63] : '=';\n }\n return encoded;\n}\n\nfunction canonicalBegin(request: BeginAttachmentUploadRequest): string {\n return JSON.stringify({\n method: ATTACHMENT_UPLOAD_RPC_METHODS.begin,\n requestId: request.requestId,\n conversationId: request.conversationId,\n filename: request.filename,\n mimeType: request.mimeType,\n totalBytes: request.totalBytes,\n });\n}\n\nfunction canonicalChunk(request: UploadAttachmentChunkRequest): string {\n return JSON.stringify({\n method: ATTACHMENT_UPLOAD_RPC_METHODS.chunk,\n requestId: request.requestId,\n conversationId: request.conversationId,\n uploadId: request.uploadId,\n offset: request.offset,\n byteLength: request.byteLength,\n encoding: request.encoding,\n data: request.data,\n ...(request.sha256 === undefined ? {} : { sha256: request.sha256 }),\n });\n}\n\nfunction canonicalCommit(request: CommitAttachmentUploadRequest): string {\n return JSON.stringify({\n method: ATTACHMENT_UPLOAD_RPC_METHODS.commit,\n requestId: request.requestId,\n conversationId: request.conversationId,\n uploadId: request.uploadId,\n size: request.size,\n sha256: request.sha256,\n });\n}\n\nfunction attachmentUploadStage(method: AttachmentUploadRpcMethod): AttachmentUploadStage {\n if (method === ATTACHMENT_UPLOAD_RPC_METHODS.begin) return 'begin';\n if (method === ATTACHMENT_UPLOAD_RPC_METHODS.chunk) return 'chunk';\n return 'commit';\n}\n\ninterface NormalizedBuildAttachmentUploadChunkRequestInput {\n requestId: string;\n conversationId: string;\n uploadId: string;\n offset: number;\n data: unknown;\n includeSha256: boolean;\n}\n\nfunction normalizeBuildAttachmentUploadChunkRequestInput(\n value: unknown,\n): NormalizedBuildAttachmentUploadChunkRequestInput {\n const descriptors = readPlainDataDescriptors(\n value,\n ['requestId', 'conversationId', 'uploadId', 'offset', 'data'],\n ['includeSha256'],\n 'request',\n );\n const requestId = readDescriptorValue(descriptors, 'requestId', 'request.requestId');\n const conversationId = readDescriptorValue(descriptors, 'conversationId', 'request.conversationId');\n const uploadId = readDescriptorValue(descriptors, 'uploadId', 'request.uploadId');\n const offset = readDescriptorValue(descriptors, 'offset', 'request.offset');\n const data = readDescriptorValue(descriptors, 'data', 'request.data');\n const includeSha256 = Object.prototype.hasOwnProperty.call(descriptors, 'includeSha256')\n ? readDescriptorValue(descriptors, 'includeSha256', 'request.includeSha256')\n : false;\n assertIdentifier(requestId, 'request.requestId');\n assertIdentifier(conversationId, 'request.conversationId');\n assertIdentifier(uploadId, 'request.uploadId');\n assertInteger(offset, 'request.offset', 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n if (typeof includeSha256 !== 'boolean') fail('request.includeSha256');\n return { requestId, conversationId, uploadId, offset, data, includeSha256 };\n}\n\ntype OwnDescriptorRecord = Readonly<Record<PropertyKey, PropertyDescriptor>>;\n\nfunction readPlainDataDescriptors(\n value: unknown,\n required: readonly string[],\n optional: readonly string[],\n field: string,\n): OwnDescriptorRecord {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) fail(field);\n let descriptors: PropertyDescriptorMap;\n try {\n const prototype = Object.getPrototypeOf(value) as object | null;\n if (!isPlainObjectPrototype(prototype)) fail(field);\n descriptors = Object.getOwnPropertyDescriptors(value);\n } catch (error) {\n if (error instanceof AttachmentUploadProtocolError) throw error;\n fail(field);\n }\n const allowed = new Set([...required, ...optional]);\n const keys = Reflect.ownKeys(descriptors);\n if (\n keys.some(key => typeof key !== 'string' || !allowed.has(key)) ||\n required.some(key => !Object.prototype.hasOwnProperty.call(descriptors, key))\n ) fail(field);\n for (const key of keys) {\n const descriptor = descriptors[key];\n if (!descriptor?.enumerable || !('value' in descriptor)) fail(field);\n }\n return descriptors;\n}\n\nfunction readDescriptorValue(\n descriptors: OwnDescriptorRecord,\n key: string,\n field: string,\n): unknown {\n const descriptor = descriptors[key];\n if (!descriptor || !('value' in descriptor)) fail(field);\n return descriptor.value;\n}\n\nfunction isPlainObjectPrototype(prototype: object | null): boolean {\n if (prototype === null || prototype === Object.prototype) return true;\n try {\n if (Object.getPrototypeOf(prototype) !== null) return false;\n const constructor = Object.getOwnPropertyDescriptor(prototype, 'constructor');\n const constructorValue: unknown = constructor && 'value' in constructor\n ? constructor.value as unknown\n : undefined;\n return typeof constructorValue === 'function' && constructorValue.name === 'Object';\n } catch {\n return false;\n }\n}\n\n/**\n * Brand-check a cross-realm Uint8Array using the unforgeable typed-array\n * intrinsic tag getter, then copy through its ordinary ArrayBuffer slots.\n * Object#toString, constructors, species, and caller properties are ignored.\n */\nfunction normalizePortableUint8Array(\n value: unknown,\n field: string,\n minimumBytes: number,\n maximumBytes: number,\n sizeField: string,\n): Uint8Array<ArrayBuffer> {\n if (!ArrayBuffer.isView(value)) fail(field);\n try {\n if (readTypedArrayIntrinsic(value, Symbol.toStringTag) !== 'Uint8Array') fail(field);\n const buffer = readTypedArrayIntrinsic(value, 'buffer');\n const byteOffset = readTypedArrayIntrinsic(value, 'byteOffset');\n const byteLength = readTypedArrayIntrinsic(value, 'byteLength');\n if (\n buffer === null ||\n typeof buffer !== 'object' ||\n typeof byteOffset !== 'number' ||\n !Number.isSafeInteger(byteOffset) ||\n byteOffset < 0 ||\n typeof byteLength !== 'number' ||\n !Number.isSafeInteger(byteLength) ||\n byteLength < minimumBytes ||\n byteLength > maximumBytes\n ) fail(sizeField);\n assertOrdinaryArrayBuffer(buffer);\n // A current-realm view avoids caller iterator/species/property access; the\n // second construction owns a detached-independent byte copy.\n return new Uint8Array(new Uint8Array(buffer as ArrayBuffer, byteOffset, byteLength));\n } catch (error) {\n if (error instanceof AttachmentUploadProtocolError) throw error;\n fail(field);\n }\n}\n\nfunction readTypedArrayIntrinsic(value: object, key: PropertyKey): unknown {\n const typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype) as object | null;\n if (!typedArrayPrototype) fail('request.data');\n const descriptor = Object.getOwnPropertyDescriptor(typedArrayPrototype, key);\n const getter: unknown = descriptor === undefined ? undefined : Reflect.get(descriptor, 'get');\n if (typeof getter !== 'function') fail('request.data');\n return Reflect.apply(getter, value, []);\n}\n\nfunction assertOrdinaryArrayBuffer(value: object): void {\n const descriptor = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, 'byteLength');\n const getter: unknown = descriptor === undefined ? undefined : Reflect.get(descriptor, 'get');\n if (typeof getter !== 'function') fail('request.data');\n // The ArrayBuffer intrinsic rejects SharedArrayBuffer and forged objects.\n Reflect.apply(getter, value, []);\n}\n\nfunction asRecord(value: unknown, field: string): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) fail(field);\n return value as Record<string, unknown>;\n}\n\nfunction assertExactKeys(\n record: Record<string, unknown>,\n keys: readonly string[],\n field: string,\n): void {\n const actual = Object.keys(record);\n if (actual.some(key => !keys.includes(key))) fail(field);\n}\n\nfunction assertOperationIdentity(record: Record<string, unknown>, field: string): void {\n assertIdentifier(record.requestId, `${field}.requestId`);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n}\n\nfunction assertIdentifier(value: unknown, field: string): asserts value is string {\n assertText(value, field, ATTACHMENT_UPLOAD_LIMITS.identifierCharacters);\n}\n\nfunction assertText(\n value: unknown,\n field: string,\n maximumCharacters: number,\n): asserts value is string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.length > maximumCharacters ||\n value !== value.trim()\n ) fail(field);\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) fail(field);\n }\n}\n\nfunction assertInteger(\n value: unknown,\n field: string,\n minimum: number,\n maximum: number,\n): asserts value is number {\n if (!Number.isSafeInteger(value) || (value as number) < minimum || (value as number) > maximum) {\n fail(field);\n }\n}\n\nfunction assertSha256(value: unknown, field: string): asserts value is string {\n if (typeof value !== 'string' || !ATTACHMENT_UPLOAD_SHA256_PATTERN.test(value)) fail(field);\n}\n\nfunction assertAttachmentReference(\n value: unknown,\n field: string,\n): asserts value is AttachmentReference {\n const record = asRecord(value, field);\n assertExactKeys(record, ['contentHash', 'filename', 'mimeType', 'size'], field);\n assertSha256(record.contentHash, `${field}.contentHash`);\n assertText(record.filename, `${field}.filename`, ATTACHMENT_UPLOAD_LIMITS.filenameCharacters);\n assertText(record.mimeType, `${field}.mimeType`, ATTACHMENT_UPLOAD_LIMITS.mimeTypeCharacters);\n assertInteger(record.size, `${field}.size`, 0, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n}\n\nfunction base64Value(code: number): number {\n if (code >= 65 && code <= 90) return code - 65;\n if (code >= 97 && code <= 122) return code - 71;\n if (code >= 48 && code <= 57) return code + 4;\n if (code === 43) return 62;\n if (code === 47) return 63;\n fail('request.data');\n}\n\nfunction fail(field: string): never {\n throw new AttachmentUploadProtocolError(field);\n}\n","import type { CreateScheduledTaskInput, ListScheduledTasksOptions, ScheduledTask, ScheduledTaskClient, ScheduledTaskState } from '../agent-management/types.js';\nimport { canonicalJsonBytes } from '../encoding/canonicalJson.js';\n\nexport const SCHEDULED_TASK_RPC_METHODS = Object.freeze(\n {\n list: 'memeloop.schedule.list',\n get: 'memeloop.schedule.get',\n create: 'memeloop.schedule.create',\n update: 'memeloop.schedule.update',\n delete: 'memeloop.schedule.delete',\n cronPreview: 'memeloop.schedule.cronPreview',\n } as const,\n);\n\nexport type ScheduledTaskRpcMethod = typeof SCHEDULED_TASK_RPC_METHODS[keyof typeof SCHEDULED_TASK_RPC_METHODS];\n\nexport const SCHEDULED_TASK_RPC_LIMITS = Object.freeze(\n {\n identifierCharacters: 512,\n nameCharacters: 256,\n labelCharacters: 256,\n creatorCharacters: 256,\n cronExpressionCharacters: 256,\n timezoneCharacters: 128,\n messageCharacters: 32 * 1024,\n cursorCharacters: 2_048,\n listPage: 100,\n listPageDefaultBytes: 256 * 1024,\n listPageMaxBytes: 256 * 1024,\n executionNodeFilters: 64,\n cronPreviewDates: 10,\n } as const,\n);\n\nexport type ScheduledTaskRpcSchedule = CreateScheduledTaskInput['schedule'];\n\nexport interface ScheduledTaskRpcCreateInput {\n agentInstanceId: string;\n agentDefinitionId: string;\n name: string;\n schedule: ScheduledTaskRpcSchedule;\n payload?: { message: string };\n activeHoursStart?: string;\n activeHoursEnd?: string;\n createdBy?: string;\n enabled?: boolean;\n /** Must equal the authenticated node receiving this RPC. */\n executionNodeId: string;\n executionNodeLabel?: string;\n}\n\nexport interface ScheduledTaskRpcUpdatePatch {\n name?: string;\n schedule?: ScheduledTaskRpcSchedule;\n payload?: { message: string } | null;\n activeHoursStart?: string | null;\n activeHoursEnd?: string | null;\n enabled?: boolean;\n /** Repeated deliberately so a transfer cannot be hidden in an update. */\n executionNodeId?: string;\n executionNodeLabel?: string | null;\n}\n\nexport interface ScheduledTaskRpcListRequest {\n /** Agent instances are conversation-scoped resources. */\n agentInstanceId: string;\n /** Per-device RPCs may enumerate only the authenticated execution node. */\n executionNodeId: string;\n states?: ScheduledTaskState[];\n cursor?: string;\n limit?: number;\n /** Required storage and transport scan budget for the complete response. */\n maxBytes: number;\n}\n\nexport interface ScheduledTaskRpcListResponse {\n items: ScheduledTask[];\n nextCursor?: string;\n hasMoreAfter: boolean;\n}\n\nexport interface ScheduledTaskRpcScopedTaskRequest {\n taskId: string;\n agentInstanceId: string;\n agentDefinitionId: string;\n executionNodeId: string;\n}\n\nexport type ScheduledTaskRpcGetRequest = ScheduledTaskRpcScopedTaskRequest;\n\nexport interface ScheduledTaskRpcGetResponse {\n task: ScheduledTask | null;\n}\n\nexport interface ScheduledTaskRpcCreateRequest {\n input: ScheduledTaskRpcCreateInput;\n}\n\nexport interface ScheduledTaskRpcCreateResponse {\n task: ScheduledTask;\n}\n\nexport interface ScheduledTaskRpcUpdateRequest extends ScheduledTaskRpcScopedTaskRequest {\n patch: ScheduledTaskRpcUpdatePatch;\n}\n\nexport interface ScheduledTaskRpcUpdateResponse {\n task: ScheduledTask;\n}\n\nexport type ScheduledTaskRpcDeleteRequest = ScheduledTaskRpcScopedTaskRequest;\n\nexport interface ScheduledTaskRpcDeleteResponse {\n deleted: true;\n taskId: string;\n}\n\nexport interface ScheduledTaskRpcCronPreviewRequest {\n expression: string;\n timezone?: string;\n count?: number;\n}\n\nexport interface ScheduledTaskRpcCronPreviewResponse {\n dates: string[];\n}\n\nexport interface ScheduledTaskRpcContract {\n [SCHEDULED_TASK_RPC_METHODS.list]: {\n request: ScheduledTaskRpcListRequest;\n response: ScheduledTaskRpcListResponse;\n };\n [SCHEDULED_TASK_RPC_METHODS.get]: {\n request: ScheduledTaskRpcGetRequest;\n response: ScheduledTaskRpcGetResponse;\n };\n [SCHEDULED_TASK_RPC_METHODS.create]: {\n request: ScheduledTaskRpcCreateRequest;\n response: ScheduledTaskRpcCreateResponse;\n };\n [SCHEDULED_TASK_RPC_METHODS.update]: {\n request: ScheduledTaskRpcUpdateRequest;\n response: ScheduledTaskRpcUpdateResponse;\n };\n [SCHEDULED_TASK_RPC_METHODS.delete]: {\n request: ScheduledTaskRpcDeleteRequest;\n response: ScheduledTaskRpcDeleteResponse;\n };\n [SCHEDULED_TASK_RPC_METHODS.cronPreview]: {\n request: ScheduledTaskRpcCronPreviewRequest;\n response: ScheduledTaskRpcCronPreviewResponse;\n };\n}\n\nexport type ScheduledTaskRpcRequest<M extends ScheduledTaskRpcMethod> = ScheduledTaskRpcContract[M]['request'];\nexport type ScheduledTaskRpcResponse<M extends ScheduledTaskRpcMethod> = ScheduledTaskRpcContract[M]['response'];\n\nconst SCHEDULED_TASK_RPC_METHOD_SET = new Set<string>(\n Object.values(SCHEDULED_TASK_RPC_METHODS),\n);\n\nexport function isScheduledTaskRpcMethod(value: unknown): value is ScheduledTaskRpcMethod {\n return typeof value === 'string' && SCHEDULED_TASK_RPC_METHOD_SET.has(value);\n}\n\nexport class ScheduledTaskRpcProtocolError extends Error {\n readonly code = 'invalid_scheduled_task_rpc' as const;\n\n constructor(readonly field: string) {\n super(`Invalid scheduled task RPC ${field}`);\n this.name = 'ScheduledTaskRpcProtocolError';\n }\n}\n\n/** Validate every caller-controlled request before authorization or dispatch. */\nexport function assertScheduledTaskRpcRequest<M extends ScheduledTaskRpcMethod>(\n method: M,\n value: unknown,\n): asserts value is ScheduledTaskRpcRequest<M> {\n const request = asRecord(value, 'request');\n switch (method) {\n case SCHEDULED_TASK_RPC_METHODS.list:\n assertOnlyKeys(request, [\n 'agentInstanceId',\n 'executionNodeId',\n 'states',\n 'cursor',\n 'limit',\n 'maxBytes',\n ], 'request');\n assertIdentifier(request.agentInstanceId, 'request.agentInstanceId');\n assertIdentifier(request.executionNodeId, 'request.executionNodeId');\n optionalStateList(request.states, 'request.states');\n optionalBoundedString(\n request.cursor,\n 'request.cursor',\n SCHEDULED_TASK_RPC_LIMITS.cursorCharacters,\n );\n optionalInteger(\n request.limit,\n 'request.limit',\n 1,\n SCHEDULED_TASK_RPC_LIMITS.listPage,\n );\n if (request.maxBytes === undefined) fail('request.maxBytes');\n optionalInteger(\n request.maxBytes,\n 'request.maxBytes',\n 64,\n SCHEDULED_TASK_RPC_LIMITS.listPageMaxBytes,\n );\n return;\n case SCHEDULED_TASK_RPC_METHODS.get:\n case SCHEDULED_TASK_RPC_METHODS.delete:\n assertScopedTaskRequest(request, 'request');\n return;\n case SCHEDULED_TASK_RPC_METHODS.create:\n assertOnlyKeys(request, ['input'], 'request');\n assertCreateInput(request.input, 'request.input');\n return;\n case SCHEDULED_TASK_RPC_METHODS.update:\n assertOnlyKeys(request, [\n 'taskId',\n 'agentInstanceId',\n 'agentDefinitionId',\n 'executionNodeId',\n 'patch',\n ], 'request');\n assertIdentifier(request.taskId, 'request.taskId');\n assertIdentifier(request.agentInstanceId, 'request.agentInstanceId');\n assertIdentifier(request.agentDefinitionId, 'request.agentDefinitionId');\n assertIdentifier(request.executionNodeId, 'request.executionNodeId');\n assertUpdatePatch(request.patch, 'request.patch');\n return;\n case SCHEDULED_TASK_RPC_METHODS.cronPreview:\n assertOnlyKeys(request, ['expression', 'timezone', 'count'], 'request');\n assertBoundedString(\n request.expression,\n 'request.expression',\n SCHEDULED_TASK_RPC_LIMITS.cronExpressionCharacters,\n );\n optionalBoundedString(\n request.timezone,\n 'request.timezone',\n SCHEDULED_TASK_RPC_LIMITS.timezoneCharacters,\n );\n optionalInteger(\n request.count,\n 'request.count',\n 1,\n SCHEDULED_TASK_RPC_LIMITS.cronPreviewDates,\n );\n return;\n }\n}\n\n/** Parse and bound every untrusted server/store response. */\nexport function parseScheduledTaskRpcResponse<M extends ScheduledTaskRpcMethod>(\n method: M,\n value: unknown,\n): ScheduledTaskRpcResponse<M> {\n const response = asRecord(value, 'response');\n switch (method) {\n case SCHEDULED_TASK_RPC_METHODS.list:\n assertOnlyKeys(response, ['items', 'nextCursor', 'hasMoreAfter'], 'response');\n assertArray(response.items, 'response.items');\n if (response.items.length > SCHEDULED_TASK_RPC_LIMITS.listPage) {\n fail('response.items');\n }\n for (const task of response.items) assertScheduledTask(task, 'response.items[]');\n optionalBoundedString(\n response.nextCursor,\n 'response.nextCursor',\n SCHEDULED_TASK_RPC_LIMITS.cursorCharacters,\n );\n if (\n typeof response.hasMoreAfter !== 'boolean' ||\n response.hasMoreAfter !== (response.nextCursor !== undefined)\n ) fail('response.hasMoreAfter');\n break;\n case SCHEDULED_TASK_RPC_METHODS.get:\n assertOnlyKeys(response, ['task'], 'response');\n if (response.task !== null) assertScheduledTask(response.task, 'response.task');\n break;\n case SCHEDULED_TASK_RPC_METHODS.create:\n case SCHEDULED_TASK_RPC_METHODS.update:\n assertOnlyKeys(response, ['task'], 'response');\n assertScheduledTask(response.task, 'response.task');\n break;\n case SCHEDULED_TASK_RPC_METHODS.delete:\n assertOnlyKeys(response, ['deleted', 'taskId'], 'response');\n if (response.deleted !== true) fail('response.deleted');\n assertIdentifier(response.taskId, 'response.taskId');\n break;\n case SCHEDULED_TASK_RPC_METHODS.cronPreview:\n assertOnlyKeys(response, ['dates'], 'response');\n assertArray(response.dates, 'response.dates');\n if (response.dates.length > SCHEDULED_TASK_RPC_LIMITS.cronPreviewDates) {\n fail('response.dates');\n }\n assertCanonicalDates(response.dates, 'response.dates');\n break;\n }\n return response as unknown as ScheduledTaskRpcResponse<M>;\n}\n\nexport interface ScheduledTaskRpcGrantResources {\n conversationId?: string;\n definitionId?: string;\n /** This is a transport target check, never a Cloud-grant authority claim. */\n executionNodeId?: string;\n}\n\n/** Validate and extract the resource tuple consumed by the shared grant check. */\nexport function parseScheduledTaskRpcGrantResources(\n method: string,\n parameters: unknown,\n): ScheduledTaskRpcGrantResources {\n if (!isScheduledTaskRpcMethod(method)) fail('method');\n assertScheduledTaskRpcRequest(method, parameters);\n const request = parameters as unknown as Record<string, unknown>;\n switch (method) {\n case SCHEDULED_TASK_RPC_METHODS.list:\n return {\n conversationId: request.agentInstanceId as string,\n executionNodeId: request.executionNodeId as string,\n };\n case SCHEDULED_TASK_RPC_METHODS.get:\n case SCHEDULED_TASK_RPC_METHODS.delete:\n return scopedTaskResources(request);\n case SCHEDULED_TASK_RPC_METHODS.create: {\n const input = request.input as ScheduledTaskRpcCreateInput;\n return {\n conversationId: input.agentInstanceId,\n definitionId: input.agentDefinitionId,\n executionNodeId: input.executionNodeId,\n };\n }\n case SCHEDULED_TASK_RPC_METHODS.update:\n return scopedTaskResources(request);\n case SCHEDULED_TASK_RPC_METHODS.cronPreview:\n return {};\n }\n}\n\nexport interface ScheduledTaskRpcStoreContext {\n /** Authenticated libp2p caller; stores must use this as origin on create. */\n remotePeerId: string;\n /** Authenticated node handling and executing this task. */\n localPeerId: string;\n /**\n * End-to-end RPC cancellation. Durable adapters must observe this before\n * committing a write and must stop bounded reads as soon as it aborts.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Narrow durable port. Update/delete implementations MUST atomically match the\n * complete taskId+agentInstanceId+agentDefinitionId+executionNodeId tuple.\n */\nexport interface ScheduledAgentTaskStore {\n /** Keyset read that must stop scanning before `request.maxBytes` is exceeded. */\n list(\n request: ScheduledTaskRpcListRequest,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<ScheduledTaskRpcListResponse>;\n get(\n request: ScheduledTaskRpcGetRequest,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<ScheduledTask | undefined>;\n create(\n input: ScheduledTaskRpcCreateInput,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<ScheduledTask>;\n update(\n request: ScheduledTaskRpcUpdateRequest,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<ScheduledTask>;\n delete(\n request: ScheduledTaskRpcDeleteRequest,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<void>;\n}\n\nexport interface ScheduledTaskCronPreviewer {\n preview(\n request: ScheduledTaskRpcCronPreviewRequest,\n context: ScheduledTaskRpcStoreContext,\n ): Promise<readonly string[]>;\n}\n\nexport interface ScheduledTaskRpcHandlerOptions {\n localPeerId: string;\n store?: ScheduledAgentTaskStore;\n cronPreviewer?: ScheduledTaskCronPreviewer;\n}\n\nexport interface ScheduledTaskRpcHandlerInput {\n remotePeerId: string;\n method: ScheduledTaskRpcMethod;\n parameters: unknown;\n signal?: AbortSignal;\n}\n\n/** Optional adapter used by the main RPC handler after its shared grant check. */\nexport function createScheduledTaskRpcHandler(options: ScheduledTaskRpcHandlerOptions) {\n assertIdentifier(options.localPeerId, 'options.localPeerId');\n return async (input: ScheduledTaskRpcHandlerInput): Promise<unknown> => {\n input.signal?.throwIfAborted();\n assertIdentifier(input.remotePeerId, 'input.remotePeerId');\n assertScheduledTaskRpcRequest(input.method, input.parameters);\n const resources = parseScheduledTaskRpcGrantResources(input.method, input.parameters);\n if (\n resources.executionNodeId !== undefined &&\n resources.executionNodeId !== options.localPeerId\n ) {\n throw new Error('scheduled_task_execution_target_mismatch');\n }\n const context: ScheduledTaskRpcStoreContext = {\n remotePeerId: input.remotePeerId,\n localPeerId: options.localPeerId,\n ...(input.signal === undefined ? {} : { signal: input.signal }),\n };\n let response: unknown;\n switch (input.method) {\n case SCHEDULED_TASK_RPC_METHODS.list:\n response = await requireStore(options).list(\n input.parameters as ScheduledTaskRpcListRequest,\n context,\n );\n break;\n case SCHEDULED_TASK_RPC_METHODS.get: {\n const task = await requireStore(options).get(\n input.parameters as ScheduledTaskRpcGetRequest,\n context,\n );\n response = { task: task ?? null };\n break;\n }\n case SCHEDULED_TASK_RPC_METHODS.create: {\n const request = input.parameters as ScheduledTaskRpcCreateRequest;\n response = { task: await requireStore(options).create(request.input, context) };\n break;\n }\n case SCHEDULED_TASK_RPC_METHODS.update:\n response = {\n task: await requireStore(options).update(\n input.parameters as ScheduledTaskRpcUpdateRequest,\n context,\n ),\n };\n break;\n case SCHEDULED_TASK_RPC_METHODS.delete: {\n const request = input.parameters as ScheduledTaskRpcDeleteRequest;\n await requireStore(options).delete(request, context);\n response = { deleted: true, taskId: request.taskId };\n break;\n }\n case SCHEDULED_TASK_RPC_METHODS.cronPreview: {\n if (!options.cronPreviewer) {\n throw new Error('scheduled_task_cron_previewer_unavailable');\n }\n const dates = await options.cronPreviewer.preview(\n input.parameters as ScheduledTaskRpcCronPreviewRequest,\n context,\n );\n response = { dates: [...dates] };\n break;\n }\n }\n input.signal?.throwIfAborted();\n const parsed = parseScheduledTaskRpcResponse(input.method, response);\n assertScheduledTaskRpcResponseCorrelation(input.method, input.parameters, parsed);\n if (\n input.method === SCHEDULED_TASK_RPC_METHODS.create &&\n (parsed as ScheduledTaskRpcCreateResponse).task.originNodeId !== input.remotePeerId\n ) {\n throw new Error('scheduled_task_origin_peer_mismatch');\n }\n return parsed;\n };\n}\n\nexport interface ScheduledTaskRpcCallOptions {\n signal?: AbortSignal;\n}\n\nexport type ScheduledTaskRpcCall = <M extends ScheduledTaskRpcMethod>(\n method: M,\n parameters: ScheduledTaskRpcRequest<M>,\n options?: ScheduledTaskRpcCallOptions,\n) => Promise<unknown>;\n\nexport function createScheduledTaskRpcClient(options: { call: ScheduledTaskRpcCall }) {\n async function request<M extends ScheduledTaskRpcMethod>(\n method: M,\n parameters: ScheduledTaskRpcRequest<M>,\n callOptions: ScheduledTaskRpcCallOptions = {},\n ): Promise<ScheduledTaskRpcResponse<M>> {\n callOptions.signal?.throwIfAborted();\n assertScheduledTaskRpcRequest(method, parameters);\n const untrustedResponse = await options.call(method, parameters, callOptions);\n callOptions.signal?.throwIfAborted();\n const response = parseScheduledTaskRpcResponse(method, untrustedResponse);\n assertScheduledTaskRpcResponseCorrelation(method, parameters, response);\n return response;\n }\n\n return {\n request,\n list: (\n parameters: ScheduledTaskRpcListRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => request(SCHEDULED_TASK_RPC_METHODS.list, parameters, callOptions),\n get: async (\n parameters: ScheduledTaskRpcGetRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => (await request(SCHEDULED_TASK_RPC_METHODS.get, parameters, callOptions)).task,\n create: async (\n parameters: ScheduledTaskRpcCreateRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => (await request(SCHEDULED_TASK_RPC_METHODS.create, parameters, callOptions)).task,\n update: async (\n parameters: ScheduledTaskRpcUpdateRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => (await request(SCHEDULED_TASK_RPC_METHODS.update, parameters, callOptions)).task,\n delete: async (\n parameters: ScheduledTaskRpcDeleteRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => request(SCHEDULED_TASK_RPC_METHODS.delete, parameters, callOptions),\n cronPreview: async (\n parameters: ScheduledTaskRpcCronPreviewRequest,\n callOptions?: ScheduledTaskRpcCallOptions,\n ) => (await request(SCHEDULED_TASK_RPC_METHODS.cronPreview, parameters, callOptions)).dates,\n };\n}\n\nexport type ScheduledTaskRpcClient = ReturnType<typeof createScheduledTaskRpcClient>;\n\n/**\n * Adapt the typed RPC client to the existing editor contract. Task-scoped\n * writes require a task previously returned by list/create/update, so a bare\n * attacker-controlled task id can never become an authorization hint.\n */\nexport function createScheduledTaskClientFromRpc(options: {\n rpc: ScheduledTaskRpcClient;\n executionNodeId: string;\n originNodeId: string;\n}): ScheduledTaskClient {\n assertIdentifier(options.executionNodeId, 'options.executionNodeId');\n assertIdentifier(options.originNodeId, 'options.originNodeId');\n const knownTasks = new Map<string, ScheduledTask>();\n\n const remember = (task: ScheduledTask): ScheduledTask => {\n knownTasks.set(task.id, task);\n return task;\n };\n\n return {\n async listScheduledTasksForAgent(\n agentInstanceId: string,\n listOptions: ListScheduledTasksOptions = {},\n ) {\n listOptions.signal?.throwIfAborted();\n if (listOptions.executionNodeIds !== undefined) {\n if (\n listOptions.executionNodeIds.length > 64 ||\n new Set(listOptions.executionNodeIds).size !== listOptions.executionNodeIds.length\n ) throw new ScheduledTaskRpcProtocolError('options.executionNodeIds');\n for (const executionNodeId of listOptions.executionNodeIds) {\n assertIdentifier(executionNodeId, 'options.executionNodeIds[]');\n }\n }\n if (\n listOptions.executionNodeIds !== undefined &&\n !listOptions.executionNodeIds.includes(options.executionNodeId)\n ) {\n return {\n items: [],\n hasMoreAfter: false,\n partial: false,\n sources: [],\n };\n }\n if (\n listOptions.executionNodeIds?.some(nodeId => nodeId !== options.executionNodeId)\n ) {\n throw new ScheduledTaskRpcProtocolError('options.executionNodeIds');\n }\n const request: ScheduledTaskRpcListRequest = {\n agentInstanceId,\n executionNodeId: options.executionNodeId,\n states: listOptions.states ?? ['active', 'paused'],\n ...(listOptions.cursor === undefined ? {} : { cursor: listOptions.cursor }),\n limit: listOptions.limit ?? SCHEDULED_TASK_RPC_LIMITS.listPage,\n maxBytes: listOptions.maxBytes ?? SCHEDULED_TASK_RPC_LIMITS.listPageDefaultBytes,\n };\n const response = listOptions.signal === undefined\n ? await options.rpc.list(request)\n : await options.rpc.list(request, { signal: listOptions.signal });\n listOptions.signal?.throwIfAborted();\n for (const task of response.items) remember(task);\n return {\n ...response,\n partial: false,\n sources: [{ executionNodeId: options.executionNodeId, state: 'online', fromCache: false }],\n };\n },\n\n async createScheduledTask(input: CreateScheduledTaskInput, callOptions = {}): Promise<ScheduledTask> {\n callOptions.signal?.throwIfAborted();\n assertEditorInputIdentity(input, options);\n const request = { input: createInputFromEditor(input) };\n const task = callOptions.signal === undefined\n ? await options.rpc.create(request)\n : await options.rpc.create(request, callOptions);\n callOptions.signal?.throwIfAborted();\n return remember(task);\n },\n\n async updateScheduledTask(\n taskId: string,\n input: Partial<CreateScheduledTaskInput>,\n callOptions = {},\n ): Promise<ScheduledTask> {\n callOptions.signal?.throwIfAborted();\n const task = requireKnownTask(knownTasks, taskId);\n assertEditorPatchIdentity(input, task, options);\n const patch = updatePatchFromEditor(input);\n const request = {\n taskId,\n agentInstanceId: task.agentInstanceId,\n agentDefinitionId: task.agentDefinitionId,\n executionNodeId: task.executionNodeId,\n patch,\n };\n return remember(\n callOptions.signal === undefined\n ? await options.rpc.update(request)\n : await options.rpc.update(request, callOptions),\n );\n },\n\n async deleteScheduledTask(taskId: string, callOptions = {}): Promise<void> {\n callOptions.signal?.throwIfAborted();\n const task = requireKnownTask(knownTasks, taskId);\n const request = {\n taskId,\n agentInstanceId: task.agentInstanceId,\n agentDefinitionId: task.agentDefinitionId,\n executionNodeId: task.executionNodeId,\n };\n if (callOptions.signal === undefined) await options.rpc.delete(request);\n else await options.rpc.delete(request, callOptions);\n callOptions.signal?.throwIfAborted();\n knownTasks.delete(taskId);\n },\n\n getCronPreviewDates: (expression, timezone, count, callOptions) => options.rpc.cronPreview({ expression, timezone, count }, callOptions),\n };\n}\n\nexport function assertScheduledTaskRpcResponseCorrelation(\n method: ScheduledTaskRpcMethod,\n requestValue: unknown,\n responseValue: unknown,\n): void {\n assertScheduledTaskRpcRequest(method, requestValue);\n const response = parseScheduledTaskRpcResponse(method, responseValue);\n const request = requestValue as unknown as Record<string, unknown>;\n switch (method) {\n case SCHEDULED_TASK_RPC_METHODS.list: {\n const listRequest = requestValue as ScheduledTaskRpcListRequest;\n const listResponse = response as ScheduledTaskRpcListResponse;\n const limit = listRequest.limit ?? SCHEDULED_TASK_RPC_LIMITS.listPage;\n if (listResponse.items.length > limit) fail('response.items');\n try {\n canonicalJsonBytes(listResponse, {\n maxDepth: 16,\n maxNodes: 20_000,\n maxStringCodeUnits: SCHEDULED_TASK_RPC_LIMITS.messageCharacters,\n maxStringBytes: SCHEDULED_TASK_RPC_LIMITS.messageCharacters * 4,\n maxBytes: listRequest.maxBytes,\n });\n } catch {\n fail('response.maxBytes');\n }\n const seen = new Set<string>();\n for (const task of listResponse.items) {\n if (\n task.agentInstanceId !== listRequest.agentInstanceId ||\n task.executionNodeId !== listRequest.executionNodeId ||\n (listRequest.states !== undefined && !listRequest.states.includes(task.state)) ||\n seen.has(task.id)\n ) fail('response.items');\n seen.add(task.id);\n }\n return;\n }\n case SCHEDULED_TASK_RPC_METHODS.get: {\n const task = (response as ScheduledTaskRpcGetResponse).task;\n if (task) assertTaskMatchesScopedRequest(task, request, 'response.task');\n return;\n }\n case SCHEDULED_TASK_RPC_METHODS.create: {\n const input = request.input as ScheduledTaskRpcCreateInput;\n const task = (response as ScheduledTaskRpcCreateResponse).task;\n if (\n task.agentInstanceId !== input.agentInstanceId ||\n task.agentDefinitionId !== input.agentDefinitionId ||\n task.executionNodeId !== input.executionNodeId\n ) fail('response.task');\n return;\n }\n case SCHEDULED_TASK_RPC_METHODS.update:\n assertTaskMatchesScopedRequest(\n (response as ScheduledTaskRpcUpdateResponse).task,\n request,\n 'response.task',\n );\n return;\n case SCHEDULED_TASK_RPC_METHODS.delete:\n if ((response as ScheduledTaskRpcDeleteResponse).taskId !== request.taskId) {\n fail('response.taskId');\n }\n return;\n case SCHEDULED_TASK_RPC_METHODS.cronPreview: {\n const previewRequest = requestValue as ScheduledTaskRpcCronPreviewRequest;\n if (\n (response as ScheduledTaskRpcCronPreviewResponse).dates.length >\n (previewRequest.count ?? 3)\n ) fail('response.dates');\n return;\n }\n }\n}\n\nfunction requireStore(options: ScheduledTaskRpcHandlerOptions): ScheduledAgentTaskStore {\n if (!options.store) throw new Error('scheduled_task_store_unavailable');\n return options.store;\n}\n\nfunction scopedTaskResources(request: Record<string, unknown>): ScheduledTaskRpcGrantResources {\n return {\n conversationId: request.agentInstanceId as string,\n definitionId: request.agentDefinitionId as string,\n executionNodeId: request.executionNodeId as string,\n };\n}\n\nfunction assertScopedTaskRequest(value: Record<string, unknown>, field: string): void {\n assertOnlyKeys(value, [\n 'taskId',\n 'agentInstanceId',\n 'agentDefinitionId',\n 'executionNodeId',\n ], field);\n assertIdentifier(value.taskId, `${field}.taskId`);\n assertIdentifier(value.agentInstanceId, `${field}.agentInstanceId`);\n assertIdentifier(value.agentDefinitionId, `${field}.agentDefinitionId`);\n assertIdentifier(value.executionNodeId, `${field}.executionNodeId`);\n}\n\nfunction assertCreateInput(value: unknown, field: string): asserts value is ScheduledTaskRpcCreateInput {\n const input = asRecord(value, field);\n assertOnlyKeys(input, [\n 'agentInstanceId',\n 'agentDefinitionId',\n 'name',\n 'schedule',\n 'payload',\n 'activeHoursStart',\n 'activeHoursEnd',\n 'createdBy',\n 'enabled',\n 'executionNodeId',\n 'executionNodeLabel',\n ], field);\n assertIdentifier(input.agentInstanceId, `${field}.agentInstanceId`);\n assertIdentifier(input.agentDefinitionId, `${field}.agentDefinitionId`);\n assertBoundedString(input.name, `${field}.name`, SCHEDULED_TASK_RPC_LIMITS.nameCharacters);\n assertSchedule(input.schedule, `${field}.schedule`);\n optionalPayload(input.payload, `${field}.payload`, false);\n optionalActiveHour(input.activeHoursStart, `${field}.activeHoursStart`, false);\n optionalActiveHour(input.activeHoursEnd, `${field}.activeHoursEnd`, false);\n optionalBoundedString(\n input.createdBy,\n `${field}.createdBy`,\n SCHEDULED_TASK_RPC_LIMITS.creatorCharacters,\n );\n optionalBoolean(input.enabled, `${field}.enabled`);\n assertIdentifier(input.executionNodeId, `${field}.executionNodeId`);\n optionalBoundedString(\n input.executionNodeLabel,\n `${field}.executionNodeLabel`,\n SCHEDULED_TASK_RPC_LIMITS.labelCharacters,\n );\n}\n\nfunction assertUpdatePatch(value: unknown, field: string): asserts value is ScheduledTaskRpcUpdatePatch {\n const patch = asRecord(value, field);\n assertOnlyKeys(patch, [\n 'name',\n 'schedule',\n 'payload',\n 'activeHoursStart',\n 'activeHoursEnd',\n 'enabled',\n 'executionNodeId',\n 'executionNodeLabel',\n ], field);\n if (Object.keys(patch).length === 0) fail(field);\n optionalBoundedString(\n patch.name,\n `${field}.name`,\n SCHEDULED_TASK_RPC_LIMITS.nameCharacters,\n );\n if (patch.schedule !== undefined) assertSchedule(patch.schedule, `${field}.schedule`);\n optionalPayload(patch.payload, `${field}.payload`, true);\n optionalActiveHour(patch.activeHoursStart, `${field}.activeHoursStart`, true);\n optionalActiveHour(patch.activeHoursEnd, `${field}.activeHoursEnd`, true);\n optionalBoolean(patch.enabled, `${field}.enabled`);\n if (patch.executionNodeId !== undefined) {\n assertIdentifier(patch.executionNodeId, `${field}.executionNodeId`);\n }\n optionalNullableBoundedString(\n patch.executionNodeLabel,\n `${field}.executionNodeLabel`,\n SCHEDULED_TASK_RPC_LIMITS.labelCharacters,\n );\n}\n\nfunction assertScheduledTask(value: unknown, field: string): asserts value is ScheduledTask {\n const task = asRecord(value, field);\n assertOnlyKeys(task, [\n 'id',\n 'agentInstanceId',\n 'agentDefinitionId',\n 'name',\n 'schedule',\n 'payload',\n 'activeHoursStart',\n 'activeHoursEnd',\n 'enabled',\n 'createdBy',\n 'state',\n 'executionNodeId',\n 'executionNodeLabel',\n 'originNodeId',\n 'updatedAt',\n 'nextRunAt',\n 'lastRunAt',\n 'lastRunStatus',\n 'lastError',\n 'lastFailureAt',\n 'consecutiveFailures',\n 'nextRetryAt',\n 'runCount',\n 'maxRuns',\n 'deleteAfterRun',\n 'executionRevision',\n 'occurrenceId',\n 'occurrenceScheduledFor',\n 'occurrenceAttempt',\n ], field);\n assertIdentifier(task.id, `${field}.id`);\n assertIdentifier(task.agentInstanceId, `${field}.agentInstanceId`);\n assertIdentifier(task.agentDefinitionId, `${field}.agentDefinitionId`);\n assertBoundedString(task.name, `${field}.name`, SCHEDULED_TASK_RPC_LIMITS.nameCharacters);\n assertSchedule(task.schedule, `${field}.schedule`);\n optionalPayload(task.payload, `${field}.payload`, false, true);\n optionalActiveHour(task.activeHoursStart, `${field}.activeHoursStart`, false);\n optionalActiveHour(task.activeHoursEnd, `${field}.activeHoursEnd`, false);\n if (typeof task.enabled !== 'boolean') fail(`${field}.enabled`);\n optionalBoundedString(\n task.createdBy,\n `${field}.createdBy`,\n SCHEDULED_TASK_RPC_LIMITS.creatorCharacters,\n );\n assertState(task.state, `${field}.state`);\n assertIdentifier(task.executionNodeId, `${field}.executionNodeId`);\n optionalBoundedString(\n task.executionNodeLabel,\n `${field}.executionNodeLabel`,\n SCHEDULED_TASK_RPC_LIMITS.labelCharacters,\n );\n assertIdentifier(task.originNodeId, `${field}.originNodeId`);\n if (task.updatedAt !== undefined) assertCanonicalDate(task.updatedAt, `${field}.updatedAt`);\n if (task.nextRunAt !== undefined) assertCanonicalDate(task.nextRunAt, `${field}.nextRunAt`);\n if (task.lastRunAt !== undefined) assertCanonicalDate(task.lastRunAt, `${field}.lastRunAt`);\n if (task.lastFailureAt !== undefined) assertCanonicalDate(task.lastFailureAt, `${field}.lastFailureAt`);\n if (task.nextRetryAt !== undefined) assertCanonicalDate(task.nextRetryAt, `${field}.nextRetryAt`);\n if (\n task.lastRunStatus !== undefined &&\n task.lastRunStatus !== 'succeeded' &&\n task.lastRunStatus !== 'failed'\n ) fail(`${field}.lastRunStatus`);\n optionalBoundedString(task.lastError, `${field}.lastError`, 1_024);\n optionalInteger(task.consecutiveFailures, `${field}.consecutiveFailures`, 0, 1_000_000);\n optionalInteger(task.runCount, `${field}.runCount`, 0, Number.MAX_SAFE_INTEGER);\n optionalInteger(task.maxRuns, `${field}.maxRuns`, 1, Number.MAX_SAFE_INTEGER);\n optionalBoolean(task.deleteAfterRun, `${field}.deleteAfterRun`);\n optionalInteger(task.executionRevision, `${field}.executionRevision`, 0, Number.MAX_SAFE_INTEGER);\n optionalBoundedString(task.occurrenceId, `${field}.occurrenceId`, 128);\n if (task.occurrenceScheduledFor !== undefined) {\n assertCanonicalDate(task.occurrenceScheduledFor, `${field}.occurrenceScheduledFor`);\n }\n optionalInteger(task.occurrenceAttempt, `${field}.occurrenceAttempt`, 0, 1_000_000);\n}\n\nfunction assertSchedule(value: unknown, field: string): asserts value is ScheduledTaskRpcSchedule {\n const schedule = asRecord(value, field);\n if (schedule.kind === 'cron') {\n assertOnlyKeys(schedule, ['kind', 'expression', 'timezone'], field);\n assertBoundedString(\n schedule.expression,\n `${field}.expression`,\n SCHEDULED_TASK_RPC_LIMITS.cronExpressionCharacters,\n );\n optionalBoundedString(\n schedule.timezone,\n `${field}.timezone`,\n SCHEDULED_TASK_RPC_LIMITS.timezoneCharacters,\n );\n return;\n }\n if (schedule.kind === 'at') {\n assertOnlyKeys(schedule, ['kind', 'wakeAtISO'], field);\n assertCanonicalDate(schedule.wakeAtISO, `${field}.wakeAtISO`);\n return;\n }\n fail(`${field}.kind`);\n}\n\nfunction optionalPayload(\n value: unknown,\n field: string,\n nullable: boolean,\n optionalMessage = false,\n): void {\n if (value === undefined || nullable && value === null) return;\n const payload = asRecord(value, field);\n assertOnlyKeys(payload, ['message'], field);\n if (optionalMessage && payload.message === undefined) return;\n assertBoundedString(\n payload.message,\n `${field}.message`,\n SCHEDULED_TASK_RPC_LIMITS.messageCharacters,\n true,\n );\n}\n\nfunction optionalActiveHour(value: unknown, field: string, nullable: boolean): void {\n if (value === undefined || nullable && value === null) return;\n if (typeof value !== 'string' || !/^(?:[01]\\d|2[0-3]):[0-5]\\d$/u.test(value)) fail(field);\n}\n\nfunction optionalStateList(value: unknown, field: string): void {\n if (value === undefined) return;\n assertArray(value, field);\n if (value.length === 0 || value.length > 5) fail(field);\n const seen = new Set<string>();\n for (const item of value) {\n assertState(item, `${field}[]`);\n if (seen.has(item)) fail(field);\n seen.add(item);\n }\n}\n\nfunction assertState(value: unknown, field: string): asserts value is ScheduledTaskState {\n if (\n value !== 'active' &&\n value !== 'paused' &&\n value !== 'completed' &&\n value !== 'cancelled' &&\n value !== 'archived'\n ) fail(field);\n}\n\nfunction assertCanonicalDates(values: unknown[], field: string): void {\n let previous: string | undefined;\n for (const value of values) {\n assertCanonicalDate(value, `${field}[]`);\n if (previous !== undefined && previous >= value) fail(field);\n previous = value;\n }\n}\n\nfunction assertCanonicalDate(value: unknown, field: string): asserts value is string {\n if (typeof value !== 'string' || value.length > 64) fail(field);\n let canonical: string;\n try {\n canonical = new Date(value).toISOString();\n } catch {\n fail(field);\n }\n if (canonical !== value) fail(field);\n}\n\nfunction assertTaskMatchesScopedRequest(\n task: ScheduledTask,\n request: Record<string, unknown>,\n field: string,\n): void {\n if (\n task.id !== request.taskId ||\n task.agentInstanceId !== request.agentInstanceId ||\n task.agentDefinitionId !== request.agentDefinitionId ||\n task.executionNodeId !== request.executionNodeId\n ) fail(field);\n}\n\nfunction assertEditorInputIdentity(\n input: CreateScheduledTaskInput,\n options: { executionNodeId: string; originNodeId: string },\n): void {\n if (input.executionNodeId !== options.executionNodeId) {\n throw new ScheduledTaskRpcProtocolError('input.executionNodeId');\n }\n if (input.originNodeId !== options.originNodeId) {\n throw new ScheduledTaskRpcProtocolError('input.originNodeId');\n }\n if (input.scheduleKind !== input.schedule.kind) {\n throw new ScheduledTaskRpcProtocolError('input.scheduleKind');\n }\n}\n\nfunction assertEditorPatchIdentity(\n input: Partial<CreateScheduledTaskInput>,\n task: ScheduledTask,\n options: { executionNodeId: string; originNodeId: string },\n): void {\n if (input.agentInstanceId !== undefined && input.agentInstanceId !== task.agentInstanceId) {\n throw new ScheduledTaskRpcProtocolError('input.agentInstanceId');\n }\n if (input.agentDefinitionId !== undefined && input.agentDefinitionId !== task.agentDefinitionId) {\n throw new ScheduledTaskRpcProtocolError('input.agentDefinitionId');\n }\n if (input.executionNodeId !== undefined && input.executionNodeId !== options.executionNodeId) {\n throw new ScheduledTaskRpcProtocolError('input.executionNodeId');\n }\n if (input.originNodeId !== undefined && input.originNodeId !== options.originNodeId) {\n throw new ScheduledTaskRpcProtocolError('input.originNodeId');\n }\n if (\n input.scheduleKind !== undefined &&\n input.schedule !== undefined &&\n input.scheduleKind !== input.schedule.kind\n ) {\n throw new ScheduledTaskRpcProtocolError('input.scheduleKind');\n }\n}\n\nfunction createInputFromEditor(input: CreateScheduledTaskInput): ScheduledTaskRpcCreateInput {\n return {\n agentInstanceId: input.agentInstanceId,\n agentDefinitionId: input.agentDefinitionId,\n name: input.name,\n schedule: input.schedule,\n payload: input.payload,\n activeHoursStart: input.activeHoursStart,\n activeHoursEnd: input.activeHoursEnd,\n createdBy: input.createdBy,\n enabled: input.enabled,\n executionNodeId: input.executionNodeId,\n executionNodeLabel: input.executionNodeLabel,\n };\n}\n\nfunction updatePatchFromEditor(\n input: Partial<CreateScheduledTaskInput>,\n): ScheduledTaskRpcUpdatePatch {\n const patch: ScheduledTaskRpcUpdatePatch = {};\n if (hasOwn(input, 'name')) patch.name = input.name;\n if (hasOwn(input, 'schedule')) patch.schedule = input.schedule;\n if (hasOwn(input, 'payload')) patch.payload = input.payload ?? null;\n if (hasOwn(input, 'activeHoursStart')) {\n patch.activeHoursStart = input.activeHoursStart ?? null;\n }\n if (hasOwn(input, 'activeHoursEnd')) patch.activeHoursEnd = input.activeHoursEnd ?? null;\n if (hasOwn(input, 'enabled')) patch.enabled = input.enabled;\n if (hasOwn(input, 'executionNodeId')) patch.executionNodeId = input.executionNodeId;\n if (hasOwn(input, 'executionNodeLabel')) {\n patch.executionNodeLabel = input.executionNodeLabel ?? null;\n }\n assertUpdatePatch(patch, 'request.patch');\n return patch;\n}\n\nfunction requireKnownTask(tasks: Map<string, ScheduledTask>, taskId: string): ScheduledTask {\n assertIdentifier(taskId, 'taskId');\n const task = tasks.get(taskId);\n if (!task) throw new Error('scheduled_task_scope_unavailable');\n return task;\n}\n\nfunction hasOwn(value: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(value, key);\n}\n\nfunction asRecord(value: unknown, field: string): Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) fail(field);\n return value as Record<string, unknown>;\n}\n\nfunction assertOnlyKeys(\n value: Record<string, unknown>,\n allowed: readonly string[],\n field: string,\n): void {\n const allowedSet = new Set(allowed);\n if (Object.keys(value).some(key => !allowedSet.has(key))) fail(field);\n}\n\nfunction assertArray(value: unknown, field: string): asserts value is unknown[] {\n if (!Array.isArray(value)) fail(field);\n}\n\nfunction assertIdentifier(value: unknown, field: string): asserts value is string {\n assertBoundedString(\n value,\n field,\n SCHEDULED_TASK_RPC_LIMITS.identifierCharacters,\n );\n}\n\nfunction assertBoundedString(\n value: unknown,\n field: string,\n maximum: number,\n allowEmpty = false,\n): asserts value is string {\n if (\n typeof value !== 'string' ||\n (!allowEmpty && value.length === 0) ||\n value.length > maximum ||\n value.includes('\\0')\n ) fail(field);\n}\n\nfunction optionalBoundedString(\n value: unknown,\n field: string,\n maximum: number,\n): void {\n if (value !== undefined) assertBoundedString(value, field, maximum);\n}\n\nfunction optionalNullableBoundedString(\n value: unknown,\n field: string,\n maximum: number,\n): void {\n if (value !== undefined && value !== null) assertBoundedString(value, field, maximum);\n}\n\nfunction optionalBoolean(value: unknown, field: string): void {\n if (value !== undefined && typeof value !== 'boolean') fail(field);\n}\n\nfunction optionalInteger(\n value: unknown,\n field: string,\n minimum: number,\n maximum: number,\n): void {\n if (\n value !== undefined &&\n (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum || value > maximum)\n ) fail(field);\n}\n\nfunction fail(field: string): never {\n throw new ScheduledTaskRpcProtocolError(field);\n}\n","import type { AgentDefinition } from '../agent/types.js';\nimport {\n assertCanonicalChatMessageProjection,\n conversationEventToMessage,\n type ConversationMessageEvent,\n type ConversationTombstoneEvent,\n isConversationEvent,\n MAX_CONVERSATION_EVENT_BYTES,\n} from '../conversation/events.js';\nimport type { AttachmentReference, ChatMessage } from '../conversation/types.js';\nimport { canonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type { PendingLocalChatMessage } from '../loopAPI/types.js';\nimport { normalizeAgentRunError } from '../runState.js';\nimport type { MemeLoopRunState, MemeLoopRunStatus } from '../runtime.js';\nimport {\n assertConversationMessageProjection,\n assertConversationTimelineCompactionEntry,\n assertConversationTimelinePage,\n assertConversationTimelinePageEnvelope,\n MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n MAX_CONVERSATION_MESSAGE_WINDOW_SIZE,\n MAX_CONVERSATION_TIMELINE_PAGE_BYTES,\n MAX_CONVERSATION_TIMELINE_PAGE_SIZE,\n MAX_MESSAGE_PAGE_SIZE,\n} from '../storage/conversationPaging.js';\nimport type {\n ConversationMessageWindowFocus,\n ConversationMessageWindowResolvedFocus,\n ConversationQueryMode,\n ConversationTimelineEntry,\n ConversationTimelinePage,\n ConversationTimelineParticipantPreview,\n} from '../storage/ports.js';\nimport type { ConversationMeta } from '../sync/protocol.js';\nimport { AGENT_USER_MESSAGE_LIMITS, assertAgentUserMessageWithinLimits } from '../userMessageAdmission.js';\nimport {\n assertAttachmentUploadRpcRequest,\n assertAttachmentUploadRpcResponseCorrelation,\n ATTACHMENT_UPLOAD_LIMITS,\n ATTACHMENT_UPLOAD_RPC_METHODS,\n ATTACHMENT_UPLOAD_SHA256_PATTERN,\n type AttachmentUploadRpcMethod,\n type AttachmentUploadRpcRequest,\n type AttachmentUploadRpcResponse,\n type BeginAttachmentUploadRequest,\n type BeginAttachmentUploadResponse,\n type CommitAttachmentUploadRequest,\n type CommitAttachmentUploadResponse,\n parseAttachmentUploadRpcResponse,\n type UploadAttachmentChunkRequest,\n type UploadAttachmentChunkResponse,\n} from './attachmentUpload.js';\nimport {\n assertScheduledTaskRpcRequest,\n assertScheduledTaskRpcResponseCorrelation,\n isScheduledTaskRpcMethod,\n parseScheduledTaskRpcGrantResources,\n parseScheduledTaskRpcResponse,\n SCHEDULED_TASK_RPC_METHODS,\n type ScheduledTaskRpcContract,\n type ScheduledTaskRpcMethod,\n type ScheduledTaskRpcRequest,\n type ScheduledTaskRpcResponse,\n} from './scheduledTaskRpc.js';\n\nexport * from './attachmentUpload.js';\nexport * from './scheduledTaskRpc.js';\n\n/** Portable limits shared by RPC handlers and every browser/mobile client. */\nexport const AGENT_DEVICE_RPC_LIMITS = Object.freeze(\n {\n conversationListPage: 100,\n conversationListBytes: 1024 * 1024,\n turnListPage: MAX_CONVERSATION_MESSAGE_WINDOW_SIZE,\n turnDetailPage: 50,\n turnDetailDefaultBytes: 256 * 1024,\n projectionPageDefaultBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n projectionPageMaxBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n projectionPageMinBytes: 64 * 1024,\n turnProjectionBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n turnRenderLines: 20_000,\n definitions: 256,\n definitionsBytes: 2 * 1024 * 1024,\n messagePage: MAX_MESSAGE_PAGE_SIZE,\n timelinePage: MAX_CONVERSATION_TIMELINE_PAGE_SIZE,\n /** Timeline has a storage-aligned budget independent of chat detail pages. */\n timelinePageDefaultBytes: MAX_CONVERSATION_TIMELINE_PAGE_BYTES,\n timelinePageMaxBytes: MAX_CONVERSATION_TIMELINE_PAGE_BYTES,\n timelinePreviewCharacters: 240,\n loadAroundMessages: MAX_CONVERSATION_MESSAGE_WINDOW_SIZE,\n loadAroundDefaultBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n loadAroundMaxBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n messageProjectionBytes: 128 * 1024,\n messagePageBytes: MAX_CONVERSATION_MESSAGE_WINDOW_BYTES,\n detailChunkBytes: 3 * 1024 * 1024,\n messageDetailBytes: 64 * 1024 * 1024,\n attachmentChunkBytes: 3 * 1024 * 1024,\n runLogPage: 50,\n runLogContentCharacters: 32 * 1024,\n runLogPageBytes: 256 * 1024,\n identifierCharacters: 512,\n cursorCharacters: 2_048,\n userMessageAttachments: 32,\n userMessageBytes: AGENT_USER_MESSAGE_LIMITS.canonicalMessageBytes,\n } as const,\n);\n\nexport const AGENT_DEVICE_RPC_METHODS = Object.freeze(\n {\n getDefinitions: 'memeloop.agent.getDefinitions',\n create: 'memeloop.agent.create',\n send: 'memeloop.agent.send',\n runTurn: 'memeloop.agent.runTurn',\n getRunStatus: 'memeloop.agent.getRunStatus',\n cancel: 'memeloop.agent.cancel',\n deleteTurn: 'memeloop.chat.deleteTurn',\n retryTurn: 'memeloop.chat.retryTurn',\n listConversations: 'memeloop.chat.listConversations',\n getConversationMeta: 'memeloop.chat.getConversationMeta',\n listTurns: 'memeloop.chat.listTurns',\n getTurnDetail: 'memeloop.chat.getTurnDetail',\n getMessagePage: 'memeloop.chat.getMessagePage',\n getConversationTimelinePage: 'memeloop.chat.getConversationTimelinePage',\n loadAround: 'memeloop.chat.loadAround',\n getMessageDetail: 'memeloop.chat.getMessageDetail',\n getAttachmentChunk: 'memeloop.chat.getAttachmentChunk',\n beginAttachmentUpload: ATTACHMENT_UPLOAD_RPC_METHODS.begin,\n uploadAttachmentChunk: ATTACHMENT_UPLOAD_RPC_METHODS.chunk,\n commitAttachmentUpload: ATTACHMENT_UPLOAD_RPC_METHODS.commit,\n pullAgentRunLog: 'memeloop.chat.pullAgentRunLog',\n scheduleList: SCHEDULED_TASK_RPC_METHODS.list,\n scheduleGet: SCHEDULED_TASK_RPC_METHODS.get,\n scheduleCreate: SCHEDULED_TASK_RPC_METHODS.create,\n scheduleUpdate: SCHEDULED_TASK_RPC_METHODS.update,\n scheduleDelete: SCHEDULED_TASK_RPC_METHODS.delete,\n scheduleCronPreview: SCHEDULED_TASK_RPC_METHODS.cronPreview,\n } as const,\n);\n\nexport type AgentDeviceRpcMethod = typeof AGENT_DEVICE_RPC_METHODS[keyof typeof AGENT_DEVICE_RPC_METHODS];\n\nconst AGENT_DEVICE_RPC_METHOD_SET = new Set<string>(Object.values(AGENT_DEVICE_RPC_METHODS));\n\nexport function isAgentDeviceRpcMethod(value: unknown): value is AgentDeviceRpcMethod {\n return typeof value === 'string' && AGENT_DEVICE_RPC_METHOD_SET.has(value);\n}\n\nexport interface AgentDeviceRpcGrantResources {\n conversationId?: string;\n definitionId?: string;\n /** Resolve this durable run before authorizing; parameters alone are insufficient. */\n runId?: string;\n}\n\n/**\n * Validate parameters and extract only caller-asserted scope hints. `runId`\n * methods must still replace these hints with the durable run record before\n * calling the shared grant authorizer.\n */\nexport function parseAgentDeviceRpcGrantResources(\n method: string,\n parameters: unknown,\n): AgentDeviceRpcGrantResources {\n if (!isAgentDeviceRpcMethod(method)) throw new AgentDeviceRpcProtocolError('method');\n assertAgentDeviceRpcRequest(method, parameters);\n const record = parameters as Record<string, unknown>;\n switch (method) {\n case AGENT_DEVICE_RPC_METHODS.getDefinitions:\n case AGENT_DEVICE_RPC_METHODS.listConversations:\n return {};\n case AGENT_DEVICE_RPC_METHODS.create:\n return {\n definitionId: record.definitionId as string,\n ...(record.conversationId === undefined ? {} : { conversationId: record.conversationId as string }),\n };\n case AGENT_DEVICE_RPC_METHODS.send:\n return {\n conversationId: record.conversationId as string,\n ...(record.definitionId === undefined ? {} : { definitionId: record.definitionId as string }),\n };\n case AGENT_DEVICE_RPC_METHODS.runTurn:\n return {\n conversationId: record.conversationId as string,\n definitionId: record.definitionId as string,\n };\n case AGENT_DEVICE_RPC_METHODS.getRunStatus:\n case AGENT_DEVICE_RPC_METHODS.cancel:\n return { runId: record.runId as string };\n case AGENT_DEVICE_RPC_METHODS.pullAgentRunLog:\n return {\n conversationId: record.conversationId as string,\n runId: record.runId as string,\n };\n case AGENT_DEVICE_RPC_METHODS.retryTurn:\n return {\n conversationId: record.conversationId as string,\n ...(record.definitionId === undefined ? {} : { definitionId: record.definitionId as string }),\n };\n case AGENT_DEVICE_RPC_METHODS.beginAttachmentUpload:\n case AGENT_DEVICE_RPC_METHODS.uploadAttachmentChunk:\n case AGENT_DEVICE_RPC_METHODS.commitAttachmentUpload:\n return { conversationId: record.conversationId as string };\n case AGENT_DEVICE_RPC_METHODS.deleteTurn:\n case AGENT_DEVICE_RPC_METHODS.getConversationMeta:\n case AGENT_DEVICE_RPC_METHODS.listTurns:\n case AGENT_DEVICE_RPC_METHODS.getTurnDetail:\n case AGENT_DEVICE_RPC_METHODS.getMessagePage:\n case AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage:\n case AGENT_DEVICE_RPC_METHODS.loadAround:\n case AGENT_DEVICE_RPC_METHODS.getMessageDetail:\n case AGENT_DEVICE_RPC_METHODS.getAttachmentChunk:\n return { conversationId: record.conversationId as string };\n case AGENT_DEVICE_RPC_METHODS.scheduleList:\n case AGENT_DEVICE_RPC_METHODS.scheduleGet:\n case AGENT_DEVICE_RPC_METHODS.scheduleCreate:\n case AGENT_DEVICE_RPC_METHODS.scheduleUpdate:\n case AGENT_DEVICE_RPC_METHODS.scheduleDelete:\n case AGENT_DEVICE_RPC_METHODS.scheduleCronPreview: {\n const resources = parseScheduledTaskRpcGrantResources(method, parameters);\n return {\n ...(resources.conversationId === undefined ? {} : { conversationId: resources.conversationId }),\n ...(resources.definitionId === undefined ? {} : { definitionId: resources.definitionId }),\n };\n }\n }\n}\n\nexport type AgentDeviceRpcGetDefinitionsRequest = Record<string, never>;\n\nexport interface AgentDeviceRpcGetDefinitionsResponse {\n definitions: AgentDefinition[];\n}\n\nexport interface AgentDeviceRpcCreateRequest {\n definitionId: string;\n initialMessage?: string;\n conversationId?: string;\n}\n\nexport interface AgentDeviceRpcCreateResponse {\n conversationId: string;\n}\n\nexport interface AgentDeviceRpcSendRequest {\n /** Caller-generated durable idempotency key. Reuse it for transport retries. */\n requestId: string;\n /** Stable logical turn identity, independent of its individual messages. */\n turnId: string;\n conversationId: string;\n message: string;\n definitionId?: string;\n /** Local-event payload only; the server allocates origin sequence and Lamport identity. */\n userMessage?: AgentDeviceRpcPendingUserMessage;\n}\n\nexport type AgentDeviceRpcPendingUserMessage = Omit<\n PendingLocalChatMessage,\n 'messageId' | 'turnId' | 'originNodeId' | 'timestamp'\n>;\n\nexport interface AgentDeviceRpcRunTurnRequest extends AgentDeviceRpcSendRequest {\n definitionId: string;\n conversation?: ConversationMeta;\n}\n\nexport interface AgentDeviceRpcTurnAcceptedResponse {\n ok: true;\n runId: string;\n requestId: string;\n turnId: string;\n conversationId: string;\n state: 'accepted';\n}\n\nexport interface AgentDeviceRpcGetRunStatusRequest {\n runId: string;\n}\n\nexport interface AgentDeviceRpcGetRunStatusResponse {\n status: AgentDeviceRpcRunStatus | null;\n}\n\nexport interface AgentDeviceRpcCancelRequest {\n runId: string;\n}\n\nexport interface AgentDeviceRpcCancelResponse {\n ok: boolean;\n status: AgentDeviceRpcRunStatus | null;\n}\n\nexport interface AgentDeviceRpcRunStatus extends MemeLoopRunStatus {\n requestId: string;\n turnId: string;\n}\n\nexport interface AgentDeviceRpcDeleteTurnRequest {\n conversationId: string;\n turnId: string;\n requestId: string;\n reason?: ConversationTombstoneEvent['reason'];\n}\n\n/** Deletion is an auditable append; implementations must never remove rows. */\nexport interface AgentDeviceRpcDeleteTurnResponse {\n ok: true;\n conversationId: string;\n turnId: string;\n requestId: string;\n tombstone: ConversationTombstoneEvent;\n}\n\nexport interface AgentDeviceRpcRetryTurnRequest {\n conversationId: string;\n /** Existing turn hidden by the atomically appended tombstone. */\n turnId: string;\n requestId: string;\n /** New stable turn identity; must differ from turnId. */\n newTurnId: string;\n definitionId?: string;\n}\n\n/** Atomic retry result: tombstone(old), user event(new), then one durable run. */\nexport interface AgentDeviceRpcRetryTurnResponse extends AgentDeviceRpcTurnAcceptedResponse {\n tombstone: ConversationTombstoneEvent;\n userEvent: ConversationMessageEvent;\n}\n\nexport interface AgentDeviceRpcListConversationsRequest {\n limit?: number;\n /** Opaque stable keyset cursor. Callers must never parse or synthesize it. */\n cursor?: string;\n /** Ask the server whether a previously rendered cursor is still retained. */\n seenCursor?: string;\n direction?: 'backward' | 'forward';\n}\n\nexport interface AgentDeviceRpcListConversationsResponse {\n items: ConversationMeta[];\n nextCursor?: string;\n previousCursor?: string;\n hasMoreBefore: boolean;\n hasMoreAfter: boolean;\n seenCursorFound?: boolean;\n}\n\nexport interface AgentDeviceRpcGetConversationMetaRequest {\n conversationId: string;\n}\n\nexport interface AgentDeviceRpcGetConversationMetaResponse {\n meta: ConversationMeta | null;\n}\n\nexport type AgentDeviceRpcTurnDetailState = 'summary' | 'full' | 'notLoaded';\n\nexport interface AgentDeviceRpcTurnSummary {\n turnId: string;\n conversationId: string;\n /** Opaque navigation cursor supplied back to list/load APIs unchanged. */\n cursor: string;\n startedAt: number;\n updatedAt: number;\n userPreview: string;\n participantPreviews: ConversationTimelineParticipantPreview[];\n responseCount: number;\n runState?: MemeLoopRunState;\n isCompaction: boolean;\n compactedMessageCount?: number;\n isTombstone: boolean;\n detailState: AgentDeviceRpcTurnDetailState;\n /** Present only when the bounded list projection could include the whole turn. */\n messages?: ChatMessage[];\n}\n\nexport interface AgentDeviceRpcListTurnsRequest {\n conversationId: string;\n cursor?: string;\n seenCursor?: string;\n direction?: 'backward' | 'forward';\n limit?: number;\n byteBudget?: number;\n renderLineBudget?: number;\n}\n\nexport interface AgentDeviceRpcListTurnsResponse {\n items: AgentDeviceRpcTurnSummary[];\n nextCursor?: string;\n previousCursor?: string;\n hasMoreBefore: boolean;\n hasMoreAfter: boolean;\n seenCursorFound?: boolean;\n budget: {\n bytes: number;\n renderLines: number;\n truncated: boolean;\n };\n}\n\nexport interface AgentDeviceRpcGetTurnDetailRequest {\n conversationId: string;\n turnId: string;\n cursor?: string;\n seenCursor?: string;\n direction?: 'backward' | 'forward';\n limit?: number;\n maxBytes?: number;\n}\n\nexport interface AgentDeviceRpcGetTurnDetailResponse {\n turnId: string;\n items: ChatMessage[];\n nextCursor?: string;\n previousCursor?: string;\n hasMoreBefore: boolean;\n hasMoreAfter: boolean;\n seenCursorFound?: boolean;\n}\n\nexport interface AgentDeviceRpcGetMessagePageRequest {\n conversationId: string;\n limit?: number;\n /** Opaque item cursor; the server owns its storage/keyset encoding. */\n cursor?: string;\n /** Required when replaying a revision-scoped cursor returned by loadAround. */\n expectedRevision?: string;\n seenCursor?: string;\n direction?: 'backward' | 'forward';\n mode?: ConversationQueryMode;\n /** UTF-8 JSON response budget. Defaults to and cannot exceed 256 KiB. */\n maxBytes?: number;\n}\n\nexport type AgentDeviceRpcGetMessagePageResponse =\n | { reset: true; conversationId: string; revision: string }\n | {\n reset: false;\n conversationId: string;\n revision: string;\n items: ChatMessage[];\n hasMoreBefore: boolean;\n hasMoreAfter: boolean;\n nextCursor?: string;\n previousCursor?: string;\n seenCursorFound?: boolean;\n };\n\nexport interface AgentDeviceRpcGetConversationTimelinePageRequest {\n conversationId: string;\n limit?: number;\n maxBytes?: number;\n expectedRevision?: string;\n /** At most one navigation selector; none reads the latest page. */\n beforeCursor?: string;\n afterCursor?: string;\n aroundEntryIndex?: number;\n}\n\nexport type AgentDeviceRpcTimelineEntry = ConversationTimelineEntry;\nexport type AgentDeviceRpcGetConversationTimelinePageResponse = ConversationTimelinePage;\n\nexport interface AgentDeviceRpcLoadAroundRequest {\n conversationId: string;\n focus: ConversationMessageWindowFocus;\n expectedRevision: string;\n maxMessages?: number;\n maxBytes?: number;\n}\n\nexport type AgentDeviceRpcLoadAroundResponse =\n | {\n reset: true;\n conversationId: string;\n revision: string;\n }\n | {\n reset: false;\n conversationId: string;\n revision: string;\n focus: ConversationMessageWindowResolvedFocus;\n items: ChatMessage[];\n hasMoreBefore: boolean;\n hasMoreAfter: boolean;\n /** Opaque cursor for a backward getMessagePage read. */\n previousCursor?: string;\n /** Opaque cursor for a forward getMessagePage read. */\n nextCursor?: string;\n };\n\nexport interface AgentDeviceRpcGetMessageDetailRequest {\n conversationId: string;\n messageId: string;\n offset?: number;\n}\n\nexport type AgentDeviceRpcGetMessageDetailResponse =\n | { found: false }\n | AgentDeviceRpcJsonChunk;\n\nexport interface AgentDeviceRpcJsonChunk {\n found: true;\n encoding: 'base64-json';\n data: string;\n offset: number;\n totalBytes: number;\n nextOffset?: number;\n}\n\nexport interface AgentDeviceRpcGetAttachmentChunkRequest {\n /** Required for resource-scope authorization; a hash alone is enumerable. */\n conversationId: string;\n contentHash: string;\n offset?: number;\n}\n\nexport type AgentDeviceRpcGetAttachmentChunkResponse =\n | { found: false }\n | AgentDeviceRpcAttachmentChunk;\n\nexport interface AgentDeviceRpcAttachmentChunk {\n found: true;\n reference: AttachmentReference;\n encoding: 'base64';\n data: string;\n offset: number;\n totalBytes: number;\n nextOffset?: number;\n}\n\nexport interface AgentDeviceRpcPullAgentRunLogRequest {\n conversationId: string;\n runId: string;\n cursor?: string;\n limit?: number;\n maxBytes?: number;\n}\n\nexport interface AgentDeviceRpcRunLogMessage {\n messageId: string;\n role: ChatMessage['role'];\n content: string;\n}\n\nexport interface AgentDeviceRpcPullAgentRunLogResponse {\n messages: AgentDeviceRpcRunLogMessage[];\n nextCursor?: string;\n hasMoreAfter: boolean;\n runStatus: AgentDeviceRpcRunStatus | null;\n}\n\nexport interface AgentDeviceRpcContract {\n [AGENT_DEVICE_RPC_METHODS.getDefinitions]: {\n request: AgentDeviceRpcGetDefinitionsRequest;\n response: AgentDeviceRpcGetDefinitionsResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.create]: {\n request: AgentDeviceRpcCreateRequest;\n response: AgentDeviceRpcCreateResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.send]: {\n request: AgentDeviceRpcSendRequest;\n response: AgentDeviceRpcTurnAcceptedResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.runTurn]: {\n request: AgentDeviceRpcRunTurnRequest;\n response: AgentDeviceRpcTurnAcceptedResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getRunStatus]: {\n request: AgentDeviceRpcGetRunStatusRequest;\n response: AgentDeviceRpcGetRunStatusResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.cancel]: {\n request: AgentDeviceRpcCancelRequest;\n response: AgentDeviceRpcCancelResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.deleteTurn]: {\n request: AgentDeviceRpcDeleteTurnRequest;\n response: AgentDeviceRpcDeleteTurnResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.retryTurn]: {\n request: AgentDeviceRpcRetryTurnRequest;\n response: AgentDeviceRpcRetryTurnResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.listConversations]: {\n request: AgentDeviceRpcListConversationsRequest;\n response: AgentDeviceRpcListConversationsResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getConversationMeta]: {\n request: AgentDeviceRpcGetConversationMetaRequest;\n response: AgentDeviceRpcGetConversationMetaResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.listTurns]: {\n request: AgentDeviceRpcListTurnsRequest;\n response: AgentDeviceRpcListTurnsResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getTurnDetail]: {\n request: AgentDeviceRpcGetTurnDetailRequest;\n response: AgentDeviceRpcGetTurnDetailResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getMessagePage]: {\n request: AgentDeviceRpcGetMessagePageRequest;\n response: AgentDeviceRpcGetMessagePageResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage]: {\n request: AgentDeviceRpcGetConversationTimelinePageRequest;\n response: AgentDeviceRpcGetConversationTimelinePageResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.loadAround]: {\n request: AgentDeviceRpcLoadAroundRequest;\n response: AgentDeviceRpcLoadAroundResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getMessageDetail]: {\n request: AgentDeviceRpcGetMessageDetailRequest;\n response: AgentDeviceRpcGetMessageDetailResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.getAttachmentChunk]: {\n request: AgentDeviceRpcGetAttachmentChunkRequest;\n response: AgentDeviceRpcGetAttachmentChunkResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.pullAgentRunLog]: {\n request: AgentDeviceRpcPullAgentRunLogRequest;\n response: AgentDeviceRpcPullAgentRunLogResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.beginAttachmentUpload]: {\n request: BeginAttachmentUploadRequest;\n response: BeginAttachmentUploadResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.uploadAttachmentChunk]: {\n request: UploadAttachmentChunkRequest;\n response: UploadAttachmentChunkResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.commitAttachmentUpload]: {\n request: CommitAttachmentUploadRequest;\n response: CommitAttachmentUploadResponse;\n };\n [AGENT_DEVICE_RPC_METHODS.scheduleList]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.list];\n [AGENT_DEVICE_RPC_METHODS.scheduleGet]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.get];\n [AGENT_DEVICE_RPC_METHODS.scheduleCreate]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.create];\n [AGENT_DEVICE_RPC_METHODS.scheduleUpdate]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.update];\n [AGENT_DEVICE_RPC_METHODS.scheduleDelete]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.delete];\n [AGENT_DEVICE_RPC_METHODS.scheduleCronPreview]: ScheduledTaskRpcContract[typeof SCHEDULED_TASK_RPC_METHODS.cronPreview];\n}\n\nexport type AgentDeviceRpcRequest<M extends AgentDeviceRpcMethod> = AgentDeviceRpcContract[M]['request'];\nexport type AgentDeviceRpcResponse<M extends AgentDeviceRpcMethod> = AgentDeviceRpcContract[M]['response'];\n\nexport class AgentDeviceRpcProtocolError extends Error {\n readonly code = 'invalid_agent_device_rpc' as const;\n\n constructor(readonly field: string) {\n super(`Invalid Agent device RPC ${field}`);\n this.name = 'AgentDeviceRpcProtocolError';\n }\n}\n\n/** Validate untrusted inbound parameters before dispatching to the local runtime. */\nexport function assertAgentDeviceRpcRequest<M extends AgentDeviceRpcMethod>(\n method: M,\n value: unknown,\n): asserts value is AgentDeviceRpcRequest<M> {\n assertJsonBytes(value, 8 * 1024 * 1024, 'request');\n const record = asRecord(value, 'request');\n switch (method) {\n case AGENT_DEVICE_RPC_METHODS.getDefinitions:\n assertOnlyKeys(record, [], 'request');\n return;\n case AGENT_DEVICE_RPC_METHODS.create:\n assertOnlyKeys(record, ['definitionId', 'initialMessage', 'conversationId'], 'request');\n assertIdentifier(record.definitionId, 'request.definitionId');\n optionalString(record.initialMessage, 'request.initialMessage');\n optionalIdentifier(record.conversationId, 'request.conversationId');\n return;\n case AGENT_DEVICE_RPC_METHODS.send:\n assertOnlyKeys(record, ['requestId', 'turnId', 'conversationId', 'message', 'definitionId', 'userMessage'], 'request');\n assertSendRequest(record, false);\n return;\n case AGENT_DEVICE_RPC_METHODS.runTurn:\n assertOnlyKeys(record, [\n 'requestId',\n 'turnId',\n 'conversationId',\n 'message',\n 'definitionId',\n 'userMessage',\n 'conversation',\n ], 'request');\n assertSendRequest(record, true);\n optionalConversationMeta(record.conversation, 'request.conversation');\n return;\n case AGENT_DEVICE_RPC_METHODS.getRunStatus:\n case AGENT_DEVICE_RPC_METHODS.cancel:\n assertOnlyKeys(record, ['runId'], 'request');\n assertIdentifier(record.runId, 'request.runId');\n return;\n case AGENT_DEVICE_RPC_METHODS.deleteTurn:\n assertOnlyKeys(record, ['conversationId', 'turnId', 'requestId', 'reason'], 'request');\n assertTurnControlIdentity(record);\n if (\n record.reason !== undefined &&\n record.reason !== 'user-delete' &&\n record.reason !== 'retention' &&\n record.reason !== 'redaction'\n ) fail('request.reason');\n return;\n case AGENT_DEVICE_RPC_METHODS.retryTurn:\n assertOnlyKeys(record, [\n 'conversationId',\n 'turnId',\n 'requestId',\n 'newTurnId',\n 'definitionId',\n ], 'request');\n assertTurnControlIdentity(record);\n assertIdentifier(record.newTurnId, 'request.newTurnId');\n if (record.newTurnId === record.turnId) fail('request.newTurnId');\n optionalIdentifier(record.definitionId, 'request.definitionId');\n return;\n case AGENT_DEVICE_RPC_METHODS.listConversations:\n assertOnlyKeys(record, ['limit', 'cursor', 'seenCursor', 'direction'], 'request');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.conversationListPage);\n optionalCursorString(record.cursor, 'request.cursor');\n optionalCursorString(record.seenCursor, 'request.seenCursor');\n optionalDirection(record.direction, 'request.direction');\n return;\n case AGENT_DEVICE_RPC_METHODS.getConversationMeta:\n assertOnlyKeys(record, ['conversationId'], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n return;\n case AGENT_DEVICE_RPC_METHODS.listTurns:\n assertOnlyKeys(record, [\n 'conversationId',\n 'cursor',\n 'seenCursor',\n 'direction',\n 'limit',\n 'byteBudget',\n 'renderLineBudget',\n ], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n optionalCursorString(record.cursor, 'request.cursor');\n optionalCursorString(record.seenCursor, 'request.seenCursor');\n optionalDirection(record.direction, 'request.direction');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.turnListPage);\n optionalBoundedInteger(record.byteBudget, 'request.byteBudget', 1, AGENT_DEVICE_RPC_LIMITS.turnProjectionBytes);\n optionalBoundedInteger(record.renderLineBudget, 'request.renderLineBudget', 1, AGENT_DEVICE_RPC_LIMITS.turnRenderLines);\n return;\n case AGENT_DEVICE_RPC_METHODS.getTurnDetail:\n assertOnlyKeys(record, [\n 'conversationId',\n 'turnId',\n 'cursor',\n 'seenCursor',\n 'direction',\n 'limit',\n 'maxBytes',\n ], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertIdentifier(record.turnId, 'request.turnId');\n optionalCursorString(record.cursor, 'request.cursor');\n optionalCursorString(record.seenCursor, 'request.seenCursor');\n optionalDirection(record.direction, 'request.direction');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.turnDetailPage);\n optionalBoundedInteger(\n record.maxBytes,\n 'request.maxBytes',\n AGENT_DEVICE_RPC_LIMITS.projectionPageMinBytes,\n AGENT_DEVICE_RPC_LIMITS.runLogPageBytes,\n );\n return;\n case AGENT_DEVICE_RPC_METHODS.getMessagePage:\n assertOnlyKeys(record, [\n 'conversationId',\n 'limit',\n 'cursor',\n 'expectedRevision',\n 'seenCursor',\n 'direction',\n 'mode',\n 'maxBytes',\n ], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.messagePage);\n optionalCursorString(record.cursor, 'request.cursor');\n optionalCursorString(record.expectedRevision, 'request.expectedRevision');\n optionalCursorString(record.seenCursor, 'request.seenCursor');\n optionalDirection(record.direction, 'request.direction');\n optionalQueryMode(record.mode, 'request.mode');\n optionalProjectionPageBytes(record.maxBytes, 'request.maxBytes');\n if (record.cursor !== undefined && record.expectedRevision === undefined) {\n fail('request.expectedRevision');\n }\n return;\n case AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage: {\n assertOnlyKeys(record, [\n 'conversationId',\n 'limit',\n 'maxBytes',\n 'expectedRevision',\n 'beforeCursor',\n 'afterCursor',\n 'aroundEntryIndex',\n ], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.timelinePage);\n optionalTimelinePageBytes(record.maxBytes, 'request.maxBytes');\n optionalCursorString(record.expectedRevision, 'request.expectedRevision');\n optionalCursorString(record.beforeCursor, 'request.beforeCursor');\n optionalCursorString(record.afterCursor, 'request.afterCursor');\n optionalBoundedInteger(record.aroundEntryIndex, 'request.aroundEntryIndex', 0, Number.MAX_SAFE_INTEGER);\n if (\n [record.beforeCursor, record.afterCursor, record.aroundEntryIndex]\n .filter(value => value !== undefined).length > 1\n ) fail('request.navigation');\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.loadAround:\n assertOnlyKeys(record, ['conversationId', 'focus', 'expectedRevision', 'maxMessages', 'maxBytes'], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertMessageWindowFocus(record.focus, 'request.focus');\n optionalCursorString(record.expectedRevision, 'request.expectedRevision');\n if (record.expectedRevision === undefined) fail('request.expectedRevision');\n optionalBoundedInteger(record.maxMessages, 'request.maxMessages', 1, AGENT_DEVICE_RPC_LIMITS.loadAroundMessages);\n optionalLoadAroundBytes(record.maxBytes, 'request.maxBytes');\n return;\n case AGENT_DEVICE_RPC_METHODS.getMessageDetail:\n assertOnlyKeys(record, ['conversationId', 'messageId', 'offset'], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertIdentifier(record.messageId, 'request.messageId');\n optionalBoundedInteger(record.offset, 'request.offset', 0, Number.MAX_SAFE_INTEGER);\n return;\n case AGENT_DEVICE_RPC_METHODS.getAttachmentChunk:\n assertOnlyKeys(record, ['conversationId', 'contentHash', 'offset'], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertIdentifier(record.contentHash, 'request.contentHash');\n optionalBoundedInteger(record.offset, 'request.offset', 0, Number.MAX_SAFE_INTEGER);\n return;\n case AGENT_DEVICE_RPC_METHODS.pullAgentRunLog:\n assertOnlyKeys(record, ['conversationId', 'runId', 'cursor', 'limit', 'maxBytes'], 'request');\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertIdentifier(record.runId, 'request.runId');\n optionalCursorString(record.cursor, 'request.cursor');\n optionalBoundedInteger(record.limit, 'request.limit', 1, AGENT_DEVICE_RPC_LIMITS.runLogPage);\n optionalProjectionPageBytes(record.maxBytes, 'request.maxBytes');\n return;\n case AGENT_DEVICE_RPC_METHODS.beginAttachmentUpload:\n case AGENT_DEVICE_RPC_METHODS.uploadAttachmentChunk:\n case AGENT_DEVICE_RPC_METHODS.commitAttachmentUpload:\n assertAttachmentUploadRpcRequest(method, value);\n return;\n case AGENT_DEVICE_RPC_METHODS.scheduleList:\n case AGENT_DEVICE_RPC_METHODS.scheduleGet:\n case AGENT_DEVICE_RPC_METHODS.scheduleCreate:\n case AGENT_DEVICE_RPC_METHODS.scheduleUpdate:\n case AGENT_DEVICE_RPC_METHODS.scheduleDelete:\n case AGENT_DEVICE_RPC_METHODS.scheduleCronPreview:\n assertScheduledTaskRpcRequest(method, value);\n return;\n }\n}\n\n/** Validate an untrusted response and return its method-specific type. */\nexport function parseAgentDeviceRpcResponse<M extends AgentDeviceRpcMethod>(\n method: M,\n value: unknown,\n): AgentDeviceRpcResponse<M> {\n // Traverse descriptors before reading a field: accessors, toJSON hooks,\n // exotic prototypes and non-canonical values must never execute here.\n assertJsonBytes(value, 16 * 1024 * 1024, 'response');\n const record = asRecord(value, 'response');\n switch (method) {\n case AGENT_DEVICE_RPC_METHODS.getDefinitions:\n assertOnlyKeys(record, ['definitions'], 'response');\n assertArray(record.definitions, 'response.definitions');\n if (record.definitions.length > AGENT_DEVICE_RPC_LIMITS.definitions) fail('response.definitions');\n for (const definition of record.definitions) assertAgentDefinition(definition, 'response.definitions[]');\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.definitionsBytes, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.create:\n assertOnlyKeys(record, ['conversationId'], 'response');\n assertIdentifier(record.conversationId, 'response.conversationId');\n break;\n case AGENT_DEVICE_RPC_METHODS.send:\n case AGENT_DEVICE_RPC_METHODS.runTurn:\n assertOnlyKeys(record, ['ok', 'runId', 'requestId', 'turnId', 'conversationId', 'state'], 'response');\n assertTurnAcceptedResponse(record);\n break;\n case AGENT_DEVICE_RPC_METHODS.getRunStatus:\n assertOnlyKeys(record, ['status'], 'response');\n nullableRunStatus(record.status, 'response.status');\n break;\n case AGENT_DEVICE_RPC_METHODS.cancel:\n assertOnlyKeys(record, ['ok', 'status'], 'response');\n if (typeof record.ok !== 'boolean') fail('response.ok');\n nullableRunStatus(record.status, 'response.status');\n break;\n case AGENT_DEVICE_RPC_METHODS.deleteTurn:\n assertOnlyKeys(record, ['ok', 'conversationId', 'turnId', 'requestId', 'tombstone'], 'response');\n assertTurnControlResponse(record, false);\n break;\n case AGENT_DEVICE_RPC_METHODS.retryTurn:\n assertOnlyKeys(record, [\n 'ok',\n 'runId',\n 'requestId',\n 'turnId',\n 'conversationId',\n 'state',\n 'tombstone',\n 'userEvent',\n ], 'response');\n assertTurnAcceptedResponse(record);\n assertTurnControlResponse(record, true);\n assertConversationMessageEvent(record.userEvent, 'response.userEvent');\n break;\n case AGENT_DEVICE_RPC_METHODS.listConversations:\n assertOnlyKeys(record, [\n 'items',\n 'nextCursor',\n 'previousCursor',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'seenCursorFound',\n ], 'response');\n assertArray(record.items, 'response.items');\n if (record.items.length > AGENT_DEVICE_RPC_LIMITS.conversationListPage) fail('response.items');\n for (const meta of record.items) assertConversationMeta(meta, 'response.items[]');\n optionalCursorString(record.nextCursor, 'response.nextCursor');\n optionalCursorString(record.previousCursor, 'response.previousCursor');\n if (typeof record.hasMoreBefore !== 'boolean') fail('response.hasMoreBefore');\n if (typeof record.hasMoreAfter !== 'boolean') fail('response.hasMoreAfter');\n optionalBoolean(record.seenCursorFound, 'response.seenCursorFound');\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.conversationListBytes, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getConversationMeta:\n assertOnlyKeys(record, ['meta'], 'response');\n if (!('meta' in record)) fail('response.meta');\n optionalConversationMeta(record.meta, 'response.meta', true);\n break;\n case AGENT_DEVICE_RPC_METHODS.listTurns:\n assertOnlyKeys(record, [\n 'items',\n 'nextCursor',\n 'previousCursor',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'seenCursorFound',\n 'budget',\n ], 'response');\n assertTurnList(record, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getTurnDetail:\n assertOnlyKeys(record, [\n 'turnId',\n 'items',\n 'nextCursor',\n 'previousCursor',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'seenCursorFound',\n ], 'response');\n assertTurnDetail(record, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getMessagePage:\n if (record.reset === true) {\n assertOnlyKeys(record, ['reset', 'conversationId', 'revision'], 'response');\n assertIdentifier(record.conversationId, 'response.conversationId');\n optionalCursorString(record.revision, 'response.revision');\n if (record.revision === undefined) fail('response.revision');\n } else {\n assertOnlyKeys(record, [\n 'reset',\n 'conversationId',\n 'revision',\n 'items',\n 'nextCursor',\n 'previousCursor',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'seenCursorFound',\n ], 'response');\n if (record.reset !== false) fail('response.reset');\n assertIdentifier(record.conversationId, 'response.conversationId');\n optionalCursorString(record.revision, 'response.revision');\n if (record.revision === undefined) fail('response.revision');\n assertMessagePage(record, AGENT_DEVICE_RPC_LIMITS.messagePage, 'response');\n }\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.messagePageBytes, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage:\n if (record.reset === true) {\n assertOnlyKeys(record, ['reset', 'revision'], 'response');\n optionalCursorString(record.revision, 'response.revision');\n if (record.revision === undefined) fail('response.revision');\n } else {\n assertOnlyKeys(record, [\n 'reset',\n 'items',\n 'totalEntries',\n 'totalMessages',\n 'totalTurns',\n 'revision',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startEntryIndex',\n 'endEntryIndex',\n 'startCursor',\n 'endCursor',\n ], 'response');\n assertTimeline(record, 'response');\n }\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.timelinePageMaxBytes, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.loadAround:\n assertMessageWindowResponse(record, 'response');\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.loadAroundMaxBytes, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getMessageDetail:\n assertOnlyKeys(\n record,\n record.found === false\n ? ['found']\n : ['found', 'encoding', 'data', 'offset', 'totalBytes', 'nextOffset'],\n 'response',\n );\n assertDetailChunk(record, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.getAttachmentChunk:\n assertOnlyKeys(\n record,\n record.found === false\n ? ['found']\n : ['found', 'reference', 'encoding', 'data', 'offset', 'totalBytes', 'nextOffset'],\n 'response',\n );\n assertAttachmentChunk(record, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.pullAgentRunLog:\n assertOnlyKeys(record, ['messages', 'nextCursor', 'hasMoreAfter', 'runStatus'], 'response');\n assertRunLog(record, 'response');\n break;\n case AGENT_DEVICE_RPC_METHODS.beginAttachmentUpload:\n case AGENT_DEVICE_RPC_METHODS.uploadAttachmentChunk:\n case AGENT_DEVICE_RPC_METHODS.commitAttachmentUpload:\n return parseAttachmentUploadRpcResponse(method, value) as AgentDeviceRpcResponse<M>;\n case AGENT_DEVICE_RPC_METHODS.scheduleList:\n case AGENT_DEVICE_RPC_METHODS.scheduleGet:\n case AGENT_DEVICE_RPC_METHODS.scheduleCreate:\n case AGENT_DEVICE_RPC_METHODS.scheduleUpdate:\n case AGENT_DEVICE_RPC_METHODS.scheduleDelete:\n case AGENT_DEVICE_RPC_METHODS.scheduleCronPreview:\n return parseScheduledTaskRpcResponse(method, value) as AgentDeviceRpcResponse<M>;\n }\n return value as AgentDeviceRpcResponse<M>;\n}\n\n/** Reject valid-shaped responses that do not belong to the originating request. */\nexport function assertAgentDeviceRpcResponseCorrelation<M extends AgentDeviceRpcMethod>(\n method: M,\n request: AgentDeviceRpcRequest<M>,\n response: AgentDeviceRpcResponse<M>,\n): void {\n const requestRecord = request as Record<string, unknown>;\n const responseRecord = response as Record<string, unknown>;\n if (\n requestRecord.seenCursor !== undefined &&\n typeof responseRecord.seenCursorFound !== 'boolean'\n ) fail('response.seenCursorFound');\n switch (method) {\n case AGENT_DEVICE_RPC_METHODS.create:\n if (\n requestRecord.conversationId !== undefined &&\n responseRecord.conversationId !== requestRecord.conversationId\n ) fail('response.conversationId');\n return;\n case AGENT_DEVICE_RPC_METHODS.send:\n case AGENT_DEVICE_RPC_METHODS.runTurn:\n for (const field of ['requestId', 'turnId', 'conversationId']) {\n if (responseRecord[field] !== requestRecord[field]) fail(`response.${field}`);\n }\n return;\n case AGENT_DEVICE_RPC_METHODS.getRunStatus:\n case AGENT_DEVICE_RPC_METHODS.cancel: {\n const status = responseRecord.status as AgentDeviceRpcRunStatus | null;\n if (status && status.runId !== requestRecord.runId) fail('response.status.runId');\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.deleteTurn: {\n assertTurnControlCorrelation(requestRecord, responseRecord);\n const tombstone = responseRecord.tombstone as ConversationTombstoneEvent;\n if (requestRecord.reason !== undefined && tombstone.reason !== requestRecord.reason) {\n fail('response.tombstone.reason');\n }\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.retryTurn: {\n if (\n responseRecord.requestId !== requestRecord.requestId ||\n responseRecord.turnId !== requestRecord.newTurnId ||\n responseRecord.conversationId !== requestRecord.conversationId\n ) fail('response');\n const tombstone = responseRecord.tombstone as ConversationTombstoneEvent;\n if (\n tombstone.conversationId !== requestRecord.conversationId ||\n tombstone.targetTurnId !== requestRecord.turnId\n ) fail('response.tombstone');\n const userEvent = responseRecord.userEvent as ConversationMessageEvent;\n if (\n userEvent.conversationId !== requestRecord.conversationId ||\n userEvent.message.messageId !== requestRecord.newTurnId ||\n userEvent.message.turnId !== requestRecord.newTurnId ||\n userEvent.message.role !== 'user'\n ) fail('response.userEvent');\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.getConversationMeta: {\n const meta = responseRecord.meta as ConversationMeta | null;\n if (meta && meta.conversationId !== requestRecord.conversationId) fail('response.meta.conversationId');\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.listConversations:\n assertRequestedPageLimit(requestRecord, responseRecord, AGENT_DEVICE_RPC_LIMITS.conversationListPage);\n return;\n case AGENT_DEVICE_RPC_METHODS.listTurns: {\n assertRequestedPageLimit(requestRecord, responseRecord, AGENT_DEVICE_RPC_LIMITS.turnListPage);\n const budget = responseRecord.budget as AgentDeviceRpcListTurnsResponse['budget'];\n if (budget.bytes > (requestRecord.byteBudget as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes)) {\n fail('response.budget.bytes');\n }\n if (\n jsonByteLength(responseRecord) >\n (requestRecord.byteBudget as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes)\n ) fail('response');\n if (\n budget.renderLines >\n (requestRecord.renderLineBudget as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.turnRenderLines)\n ) fail('response.budget.renderLines');\n if (\n turnRenderLines(responseRecord.items) >\n (requestRecord.renderLineBudget as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.turnRenderLines)\n ) fail('response.items');\n assertConversationItems(responseRecord, requestRecord.conversationId as string);\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.getMessagePage:\n if (responseRecord.conversationId !== requestRecord.conversationId) {\n fail('response.conversationId');\n }\n assertRequestedByteBudget(requestRecord, responseRecord);\n if (responseRecord.reset === true) return;\n if (\n requestRecord.expectedRevision !== undefined &&\n responseRecord.revision !== requestRecord.expectedRevision\n ) fail('response.revision');\n assertRequestedPageLimit(requestRecord, responseRecord, AGENT_DEVICE_RPC_LIMITS.messagePage);\n assertConversationItems(responseRecord, requestRecord.conversationId as string);\n return;\n case AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage:\n assertTimelinePageCorrelation(requestRecord, responseRecord);\n if (responseRecord.reset === true) {\n assertRequestedByteBudget(\n requestRecord,\n responseRecord,\n AGENT_DEVICE_RPC_LIMITS.timelinePageDefaultBytes,\n );\n return;\n }\n if (\n (responseRecord.items as unknown[]).length >\n (requestRecord.limit as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.timelinePage)\n ) fail('response.items');\n assertConversationItems(responseRecord, requestRecord.conversationId as string);\n assertRequestedByteBudget(\n requestRecord,\n responseRecord,\n AGENT_DEVICE_RPC_LIMITS.timelinePageDefaultBytes,\n );\n return;\n case AGENT_DEVICE_RPC_METHODS.getTurnDetail:\n assertRequestedPageLimit(requestRecord, responseRecord, AGENT_DEVICE_RPC_LIMITS.turnDetailPage);\n if (responseRecord.turnId !== requestRecord.turnId) fail('response.turnId');\n for (const item of responseRecord.items as ChatMessage[]) {\n if (item.conversationId !== requestRecord.conversationId || item.turnId !== requestRecord.turnId) {\n fail('response.items');\n }\n }\n assertRequestedByteBudget(requestRecord, responseRecord);\n return;\n case AGENT_DEVICE_RPC_METHODS.loadAround:\n assertMessageWindowCorrelation(\n requestRecord as unknown as AgentDeviceRpcLoadAroundRequest,\n responseRecord as unknown as AgentDeviceRpcLoadAroundResponse,\n );\n return;\n case AGENT_DEVICE_RPC_METHODS.getAttachmentChunk: {\n if (responseRecord.found === true) {\n const reference = responseRecord.reference as AttachmentReference;\n if (reference.contentHash !== requestRecord.contentHash) fail('response.reference.contentHash');\n }\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.pullAgentRunLog: {\n assertRequestedPageLimit(requestRecord, responseRecord, AGENT_DEVICE_RPC_LIMITS.runLogPage, 'messages');\n const status = responseRecord.runStatus as AgentDeviceRpcRunStatus | null;\n if (status && status.runId !== requestRecord.runId) fail('response.runStatus.runId');\n assertRequestedByteBudget(requestRecord, responseRecord);\n return;\n }\n case AGENT_DEVICE_RPC_METHODS.beginAttachmentUpload:\n case AGENT_DEVICE_RPC_METHODS.uploadAttachmentChunk:\n case AGENT_DEVICE_RPC_METHODS.commitAttachmentUpload:\n assertEmbeddedAttachmentUploadCorrelation(\n method as AttachmentUploadRpcMethod,\n request,\n response,\n );\n return;\n case AGENT_DEVICE_RPC_METHODS.scheduleList:\n case AGENT_DEVICE_RPC_METHODS.scheduleGet:\n case AGENT_DEVICE_RPC_METHODS.scheduleCreate:\n case AGENT_DEVICE_RPC_METHODS.scheduleUpdate:\n case AGENT_DEVICE_RPC_METHODS.scheduleDelete:\n case AGENT_DEVICE_RPC_METHODS.scheduleCronPreview:\n assertEmbeddedScheduledTaskCorrelation(method, request, response);\n return;\n case AGENT_DEVICE_RPC_METHODS.getDefinitions:\n case AGENT_DEVICE_RPC_METHODS.getMessageDetail:\n return;\n }\n}\n\nfunction assertEmbeddedScheduledTaskCorrelation(\n method: ScheduledTaskRpcMethod,\n request: unknown,\n response: unknown,\n): void {\n if (!isScheduledTaskRpcMethod(method)) fail('method');\n assertScheduledTaskRpcResponseCorrelation(\n method,\n request as ScheduledTaskRpcRequest<typeof method>,\n response as ScheduledTaskRpcResponse<typeof method>,\n );\n}\n\nfunction assertEmbeddedAttachmentUploadCorrelation(\n method: AttachmentUploadRpcMethod,\n request: unknown,\n response: unknown,\n): void {\n switch (method) {\n case ATTACHMENT_UPLOAD_RPC_METHODS.begin:\n assertAttachmentUploadRpcResponseCorrelation(\n method,\n request as AttachmentUploadRpcRequest<typeof method>,\n response as AttachmentUploadRpcResponse<typeof method>,\n );\n return;\n case ATTACHMENT_UPLOAD_RPC_METHODS.chunk:\n assertAttachmentUploadRpcResponseCorrelation(\n method,\n request as AttachmentUploadRpcRequest<typeof method>,\n response as AttachmentUploadRpcResponse<typeof method>,\n );\n return;\n case ATTACHMENT_UPLOAD_RPC_METHODS.commit:\n assertAttachmentUploadRpcResponseCorrelation(\n method,\n request as AttachmentUploadRpcRequest<typeof method>,\n response as AttachmentUploadRpcResponse<typeof method>,\n );\n }\n}\n\nfunction assertConversationItems(response: Record<string, unknown>, conversationId: string): void {\n for (const item of response.items as Array<{ conversationId: string }>) {\n if (item.conversationId !== conversationId) fail('response.items.conversationId');\n }\n}\n\nfunction assertTimelinePageCorrelation(\n request: Record<string, unknown>,\n response: Record<string, unknown>,\n): void {\n try {\n assertConversationTimelinePage(\n response,\n request.conversationId as string,\n {\n limit: request.limit as number | undefined ?? AGENT_DEVICE_RPC_LIMITS.timelinePage,\n maxBytes: request.maxBytes as number | undefined ??\n AGENT_DEVICE_RPC_LIMITS.timelinePageDefaultBytes,\n ...(request.expectedRevision === undefined\n ? {}\n : { expectedRevision: request.expectedRevision as string }),\n ...(request.beforeCursor === undefined\n ? {}\n : { beforeCursor: request.beforeCursor as string }),\n ...(request.afterCursor === undefined\n ? {}\n : { afterCursor: request.afterCursor as string }),\n ...(request.aroundEntryIndex === undefined\n ? {}\n : { aroundEntryIndex: request.aroundEntryIndex as number }),\n },\n );\n } catch {\n fail('response');\n }\n if (response.reset) return;\n const items = response.items;\n if (\n request.aroundEntryIndex !== undefined &&\n (request.aroundEntryIndex as number) < (response.totalEntries) &&\n !items.some(item => item.entryIndex === request.aroundEntryIndex)\n ) fail('response.items.entryIndex');\n}\n\nfunction assertRequestedPageLimit(\n request: Record<string, unknown>,\n response: Record<string, unknown>,\n defaultLimit: number,\n itemsField = 'items',\n): void {\n if ((response[itemsField] as unknown[]).length > (request.limit as number | undefined ?? defaultLimit)) {\n fail(`response.${itemsField}`);\n }\n}\n\nfunction assertRequestedByteBudget(\n request: Record<string, unknown>,\n response: Record<string, unknown>,\n defaultBytes = AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes,\n): void {\n const maximum = request.maxBytes as number | undefined ?? defaultBytes;\n if (jsonByteLength(response) > maximum) fail('response');\n}\n\nfunction assertSendRequest(record: Record<string, unknown>, requireDefinition: boolean): void {\n assertIdentifier(record.requestId, 'request.requestId');\n assertIdentifier(record.turnId, 'request.turnId');\n assertIdentifier(record.conversationId, 'request.conversationId');\n if (typeof record.message !== 'string') fail('request.message');\n if (requireDefinition) assertIdentifier(record.definitionId, 'request.definitionId');\n else optionalIdentifier(record.definitionId, 'request.definitionId');\n if (record.userMessage !== undefined) {\n assertPendingLocalUserMessage(record.userMessage, record.turnId);\n const userMessage = record.userMessage as AgentDeviceRpcPendingUserMessage;\n if (userMessage.content !== undefined && userMessage.content !== record.message) {\n fail('request.userMessage.content');\n }\n }\n}\n\nfunction assertPendingLocalUserMessage(value: unknown, turnId: string): void {\n const record = asRecord(value, 'request.userMessage');\n assertOnlyKeys(record, [\n 'content',\n 'parts',\n 'toolCalls',\n 'attachments',\n 'detailRef',\n 'reasoning_content',\n 'contentType',\n 'hidden',\n 'duration',\n 'metadata',\n ], 'request.userMessage');\n const event = {\n eventId: turnId,\n conversationId: 'rpc-validation',\n originNodeId: 'rpc-validation',\n originSequence: 1,\n lamportClock: 1,\n timestamp: 0,\n kind: 'message',\n message: {\n messageId: turnId,\n turnId,\n role: 'user',\n content: record.content ?? '',\n ...record,\n },\n };\n assertConversationMessageEvent(event, 'request.userMessage');\n try {\n assertAgentUserMessageWithinLimits(conversationEventToMessage(event));\n } catch {\n fail('request.userMessage');\n }\n const references: AttachmentReference[] = [\n ...((record.attachments as AttachmentReference[] | undefined) ?? []),\n ...((record.parts as Array<{ type: string; attachment?: AttachmentReference }> | undefined) ?? [])\n .filter(part => part.type === 'attachment' && part.attachment !== undefined)\n .map(part => part.attachment!),\n ];\n if (references.length > AGENT_DEVICE_RPC_LIMITS.userMessageAttachments) {\n fail('request.userMessage.attachments');\n }\n for (const reference of references) {\n if (\n !ATTACHMENT_UPLOAD_SHA256_PATTERN.test(reference.contentHash) ||\n reference.size > ATTACHMENT_UPLOAD_LIMITS.totalBytes ||\n reference.filename.length > ATTACHMENT_UPLOAD_LIMITS.filenameCharacters ||\n reference.mimeType.length > ATTACHMENT_UPLOAD_LIMITS.mimeTypeCharacters\n ) fail('request.userMessage.attachments');\n }\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.userMessageBytes, 'request.userMessage');\n}\n\nfunction assertTurnControlIdentity(record: Record<string, unknown>): void {\n assertIdentifier(record.conversationId, 'request.conversationId');\n assertIdentifier(record.turnId, 'request.turnId');\n assertIdentifier(record.requestId, 'request.requestId');\n}\n\nfunction assertTurnControlResponse(record: Record<string, unknown>, retry: boolean): void {\n if (record.ok !== true) fail('response.ok');\n assertIdentifier(record.conversationId, 'response.conversationId');\n assertIdentifier(record.turnId, 'response.turnId');\n assertIdentifier(record.requestId, 'response.requestId');\n assertConversationTombstoneEvent(record.tombstone, 'response.tombstone');\n if (!retry && record.tombstone.targetTurnId !== record.turnId) fail('response.tombstone.targetTurnId');\n}\n\nfunction assertTurnControlCorrelation(\n request: Record<string, unknown>,\n response: Record<string, unknown>,\n): void {\n if (\n response.requestId !== request.requestId ||\n response.turnId !== request.turnId ||\n response.conversationId !== request.conversationId\n ) fail('response');\n const tombstone = response.tombstone as ConversationTombstoneEvent;\n if (\n tombstone.conversationId !== request.conversationId ||\n tombstone.targetTurnId !== request.turnId\n ) fail('response.tombstone');\n}\n\nfunction assertConversationTombstoneEvent(\n value: unknown,\n field: string,\n): asserts value is ConversationTombstoneEvent {\n if (!isConversationEvent(value) || value.kind !== 'tombstone') fail(field);\n assertJsonBytes(value, MAX_CONVERSATION_EVENT_BYTES, field);\n}\n\nfunction assertConversationMessageEvent(\n value: unknown,\n field: string,\n): asserts value is ConversationMessageEvent {\n if (!isConversationEvent(value) || value.kind !== 'message') fail(field);\n assertJsonBytes(value, MAX_CONVERSATION_EVENT_BYTES, field);\n}\n\nfunction assertTurnAcceptedResponse(record: Record<string, unknown>): void {\n if (record.ok !== true || record.state !== 'accepted') fail('response.state');\n assertIdentifier(record.runId, 'response.runId');\n assertIdentifier(record.requestId, 'response.requestId');\n assertIdentifier(record.turnId, 'response.turnId');\n assertIdentifier(record.conversationId, 'response.conversationId');\n}\n\nfunction assertMessagePage(\n record: Record<string, unknown>,\n maximum: number,\n field: string,\n allowDuplicates = false,\n): void {\n assertArray(record.items, `${field}.items`);\n if (record.items.length > maximum) fail(`${field}.items`);\n const messageIds = new Set<string>();\n for (const message of record.items) {\n try {\n assertConversationMessageProjection(message);\n assertJsonBytes(message, AGENT_DEVICE_RPC_LIMITS.messageProjectionBytes, `${field}.items[]`);\n } catch {\n fail(`${field}.items[]`);\n }\n if (!allowDuplicates && messageIds.has(message.messageId)) fail(`${field}.items[].messageId`);\n messageIds.add(message.messageId);\n }\n if (typeof record.hasMoreBefore !== 'boolean') fail(`${field}.hasMoreBefore`);\n if (typeof record.hasMoreAfter !== 'boolean') fail(`${field}.hasMoreAfter`);\n optionalCursorString(record.nextCursor, `${field}.nextCursor`);\n optionalCursorString(record.previousCursor, `${field}.previousCursor`);\n optionalBoolean(record.seenCursorFound, `${field}.seenCursorFound`);\n}\n\nfunction assertTimeline(record: Record<string, unknown>, field: string): void {\n try {\n assertConversationTimelinePageEnvelope(record, {\n limit: AGENT_DEVICE_RPC_LIMITS.timelinePage,\n maxBytes: AGENT_DEVICE_RPC_LIMITS.timelinePageMaxBytes,\n previewLength: AGENT_DEVICE_RPC_LIMITS.timelinePreviewCharacters,\n });\n } catch {\n fail(field);\n }\n}\n\nfunction assertTurnList(record: Record<string, unknown>, field: string): void {\n assertArray(record.items, `${field}.items`);\n if (record.items.length > AGENT_DEVICE_RPC_LIMITS.turnListPage) fail(`${field}.items`);\n const turnIds = new Set<string>();\n for (const value of record.items) {\n assertTurnSummary(value, `${field}.items[]`);\n if (turnIds.has(value.turnId)) fail(`${field}.items[].turnId`);\n turnIds.add(value.turnId);\n }\n assertPageNavigation(record, field);\n const budget = asRecord(record.budget, `${field}.budget`);\n assertBoundedInteger(budget.bytes, `${field}.budget.bytes`, 0, AGENT_DEVICE_RPC_LIMITS.turnProjectionBytes);\n assertBoundedInteger(budget.renderLines, `${field}.budget.renderLines`, 0, AGENT_DEVICE_RPC_LIMITS.turnRenderLines);\n if (typeof budget.truncated !== 'boolean') fail(`${field}.budget.truncated`);\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.turnProjectionBytes, field);\n}\n\nfunction assertTurnDetail(record: Record<string, unknown>, field: string): void {\n assertIdentifier(record.turnId, `${field}.turnId`);\n assertArray(record.items, `${field}.items`);\n if (record.items.length > AGENT_DEVICE_RPC_LIMITS.turnDetailPage) fail(`${field}.items`);\n for (const message of record.items) {\n try {\n assertConversationMessageProjection(message);\n } catch {\n fail(`${field}.items[]`);\n }\n }\n assertPageNavigation(record, field);\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.messagePageBytes, field);\n}\n\nfunction assertMessageWindowFocus(\n value: unknown,\n field: string,\n): asserts value is ConversationMessageWindowFocus {\n const record = asRecord(value, field);\n if (record.kind === 'turn') {\n assertOnlyKeys(record, ['kind', 'turnId', 'cursor'], field);\n assertIdentifier(record.turnId, `${field}.turnId`);\n optionalCursorString(record.cursor, `${field}.cursor`);\n return;\n }\n if (record.kind === 'timeline-entry') {\n assertOnlyKeys(record, ['kind', 'entryId', 'cursor'], field);\n assertIdentifier(record.entryId, `${field}.entryId`);\n optionalCursorString(record.cursor, `${field}.cursor`);\n if (record.cursor === undefined) fail(`${field}.cursor`);\n return;\n }\n fail(`${field}.kind`);\n}\n\nfunction assertMessageWindowResponse(record: Record<string, unknown>, field: string): void {\n if (record.reset === true) {\n assertOnlyKeys(record, ['reset', 'conversationId', 'revision'], field);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n optionalCursorString(record.revision, `${field}.revision`);\n if (record.revision === undefined) fail(`${field}.revision`);\n return;\n }\n assertOnlyKeys(record, [\n 'reset',\n 'conversationId',\n 'revision',\n 'focus',\n 'items',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'previousCursor',\n 'nextCursor',\n ], field);\n if (record.reset !== false) fail(`${field}.reset`);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n optionalCursorString(record.revision, `${field}.revision`);\n if (record.revision === undefined) fail(`${field}.revision`);\n assertResolvedMessageWindowFocus(record.focus, `${field}.focus`);\n assertArray(record.items, `${field}.items`);\n if (record.items.length > AGENT_DEVICE_RPC_LIMITS.loadAroundMessages) fail(`${field}.items`);\n const messageIds = new Set<string>();\n for (const item of record.items) {\n try {\n assertConversationMessageProjection(item, record.conversationId);\n assertJsonBytes(item, AGENT_DEVICE_RPC_LIMITS.messageProjectionBytes, `${field}.items[]`);\n } catch {\n fail(`${field}.items[]`);\n }\n if (messageIds.has(item.messageId)) fail(`${field}.items[].messageId`);\n messageIds.add(item.messageId);\n }\n if (typeof record.hasMoreBefore !== 'boolean') fail(`${field}.hasMoreBefore`);\n if (typeof record.hasMoreAfter !== 'boolean') fail(`${field}.hasMoreAfter`);\n optionalCursorString(record.previousCursor, `${field}.previousCursor`);\n optionalCursorString(record.nextCursor, `${field}.nextCursor`);\n if (record.items.length === 0) {\n if (\n record.hasMoreBefore || record.hasMoreAfter ||\n record.previousCursor !== undefined || record.nextCursor !== undefined\n ) fail(`${field}.items`);\n return;\n }\n if (record.hasMoreBefore !== (record.previousCursor !== undefined)) fail(`${field}.previousCursor`);\n if (record.hasMoreAfter !== (record.nextCursor !== undefined)) fail(`${field}.nextCursor`);\n}\n\nfunction assertResolvedMessageWindowFocus(value: unknown, field: string): void {\n const record = asRecord(value, field);\n if (record.kind === 'turn') {\n assertOnlyKeys(record, ['kind', 'turnId', 'entryId', 'cursor'], field);\n assertIdentifier(record.turnId, `${field}.turnId`);\n optionalIdentifier(record.entryId, `${field}.entryId`);\n optionalCursorString(record.cursor, `${field}.cursor`);\n return;\n }\n if (record.kind !== 'compaction') fail(`${field}.kind`);\n assertOnlyKeys(record, ['kind', 'entry', 'nearestPosition', 'nearestTurnId'], field);\n try {\n assertConversationTimelineCompactionEntry(record.entry, {\n maximumPreview: AGENT_DEVICE_RPC_LIMITS.timelinePreviewCharacters,\n });\n } catch {\n fail(`${field}.entry`);\n }\n if (record.nearestPosition === 'none') {\n if (record.nearestTurnId !== undefined) fail(`${field}.nearestTurnId`);\n return;\n }\n if (record.nearestPosition !== 'before' && record.nearestPosition !== 'after') {\n fail(`${field}.nearestPosition`);\n }\n assertIdentifier(record.nearestTurnId, `${field}.nearestTurnId`);\n}\n\nfunction assertMessageWindowCorrelation(\n request: AgentDeviceRpcLoadAroundRequest,\n response: AgentDeviceRpcLoadAroundResponse,\n): void {\n if (response.conversationId !== request.conversationId) fail('response.conversationId');\n assertRequestedByteBudget(\n request as unknown as Record<string, unknown>,\n response as unknown as Record<string, unknown>,\n AGENT_DEVICE_RPC_LIMITS.loadAroundDefaultBytes,\n );\n if (response.reset) return;\n if (response.revision !== request.expectedRevision) fail('response.revision');\n if (response.items.length > (request.maxMessages ?? AGENT_DEVICE_RPC_LIMITS.loadAroundMessages)) {\n fail('response.items');\n }\n for (const item of response.items) {\n if (item.conversationId !== request.conversationId) fail('response.items');\n }\n if (request.focus.kind === 'turn') {\n if (\n response.focus.kind !== 'turn' ||\n response.focus.turnId !== request.focus.turnId ||\n response.focus.entryId !== undefined ||\n response.focus.cursor !== request.focus.cursor\n ) {\n fail('response.focus');\n }\n return;\n }\n if (response.focus.kind === 'turn') {\n if (\n response.focus.entryId !== request.focus.entryId ||\n response.focus.cursor !== request.focus.cursor\n ) fail('response.focus');\n return;\n }\n if (\n response.focus.entry.entryId !== request.focus.entryId ||\n response.focus.entry.cursor !== request.focus.cursor\n ) fail('response.focus');\n}\n\nfunction assertTurnSummary(value: unknown, field: string): asserts value is AgentDeviceRpcTurnSummary {\n const record = asRecord(value, field);\n assertIdentifier(record.turnId, `${field}.turnId`);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n optionalCursorString(record.cursor, `${field}.cursor`);\n if (record.cursor === undefined) fail(`${field}.cursor`);\n assertBoundedInteger(record.startedAt, `${field}.startedAt`, 0, Number.MAX_SAFE_INTEGER);\n assertBoundedInteger(record.updatedAt, `${field}.updatedAt`, 0, Number.MAX_SAFE_INTEGER);\n assertPreview(record.userPreview, `${field}.userPreview`);\n assertArray(record.participantPreviews, `${field}.participantPreviews`);\n if (record.participantPreviews.length > 4 || jsonByteLength(record.participantPreviews) > 1_024) {\n fail(`${field}.participantPreviews`);\n }\n for (const [index, participantValue] of record.participantPreviews.entries()) {\n const participant = asRecord(participantValue, `${field}.participantPreviews[${index}]`);\n if (\n Reflect.ownKeys(participant).some(key => typeof key !== 'string' || !['actorId', 'actorLabel', 'role', 'preview'].includes(key)) ||\n typeof participant.actorId !== 'string' || participant.actorId.length === 0 || participant.actorId.length > 160 ||\n typeof participant.actorLabel !== 'string' || participant.actorLabel.length === 0 || participant.actorLabel.length > 160 ||\n (participant.role !== 'assistant' && participant.role !== 'agent') ||\n typeof participant.preview !== 'string' || participant.preview.length > 160\n ) fail(`${field}.participantPreviews[${index}]`);\n }\n assertBoundedInteger(record.responseCount, `${field}.responseCount`, 0, Number.MAX_SAFE_INTEGER);\n if (record.responseCount < record.participantPreviews.length) fail(`${field}.responseCount`);\n if (\n record.runState !== undefined &&\n !['accepted', 'queued', 'running', 'completed', 'failed', 'cancelled'].includes(record.runState as string)\n ) fail(`${field}.runState`);\n if (typeof record.isCompaction !== 'boolean') fail(`${field}.isCompaction`);\n optionalBoundedInteger(record.compactedMessageCount, `${field}.compactedMessageCount`, 1, Number.MAX_SAFE_INTEGER);\n if (typeof record.isTombstone !== 'boolean') fail(`${field}.isTombstone`);\n if (record.detailState !== 'summary' && record.detailState !== 'full' && record.detailState !== 'notLoaded') {\n fail(`${field}.detailState`);\n }\n if (record.messages !== undefined) {\n if (record.detailState !== 'full') fail(`${field}.messages`);\n assertArray(record.messages, `${field}.messages`);\n if (record.messages.length > AGENT_DEVICE_RPC_LIMITS.turnDetailPage) fail(`${field}.messages`);\n for (const message of record.messages) assertChatMessage(message, `${field}.messages[]`);\n }\n}\n\nfunction assertPageNavigation(record: Record<string, unknown>, field: string, seen = true): void {\n if (typeof record.hasMoreBefore !== 'boolean') fail(`${field}.hasMoreBefore`);\n if (typeof record.hasMoreAfter !== 'boolean') fail(`${field}.hasMoreAfter`);\n optionalCursorString(record.nextCursor, `${field}.nextCursor`);\n optionalCursorString(record.previousCursor, `${field}.previousCursor`);\n if (seen) optionalBoolean(record.seenCursorFound, `${field}.seenCursorFound`);\n}\n\nfunction assertDetailChunk(record: Record<string, unknown>, field: string): void {\n if (record.found === false) return;\n if (record.found !== true || record.encoding !== 'base64-json') fail(`${field}.encoding`);\n assertChunk(record, AGENT_DEVICE_RPC_LIMITS.detailChunkBytes, field);\n}\n\nfunction assertAttachmentChunk(record: Record<string, unknown>, field: string): void {\n if (record.found === false) return;\n if (record.found !== true || record.encoding !== 'base64') fail(`${field}.encoding`);\n assertAttachmentReference(record.reference, `${field}.reference`);\n assertChunk(record, AGENT_DEVICE_RPC_LIMITS.attachmentChunkBytes, field);\n}\n\nfunction assertChunk(record: Record<string, unknown>, maximumBytes: number, field: string): void {\n if (typeof record.data !== 'string' || !isCanonicalBase64(record.data)) fail(`${field}.data`);\n const byteLength = decodedBase64ByteLength(record.data);\n if (byteLength > maximumBytes) fail(`${field}.data`);\n assertBoundedInteger(record.offset, `${field}.offset`, 0, Number.MAX_SAFE_INTEGER);\n assertBoundedInteger(record.totalBytes, `${field}.totalBytes`, 0, Number.MAX_SAFE_INTEGER);\n optionalBoundedInteger(record.nextOffset, `${field}.nextOffset`, 1, Number.MAX_SAFE_INTEGER);\n if (record.offset + byteLength > record.totalBytes) fail(`${field}.totalBytes`);\n const expectedNext = record.offset + byteLength;\n if (record.nextOffset !== undefined && record.nextOffset !== expectedNext) fail(`${field}.nextOffset`);\n if (record.nextOffset === undefined && expectedNext !== record.totalBytes) fail(`${field}.nextOffset`);\n}\n\nfunction assertRunLog(record: Record<string, unknown>, field: string): void {\n assertArray(record.messages, `${field}.messages`);\n if (record.messages.length > AGENT_DEVICE_RPC_LIMITS.runLogPage) fail(`${field}.messages`);\n for (const value of record.messages) {\n const message = asRecord(value, `${field}.messages[]`);\n assertIdentifier(message.messageId, `${field}.messages[].messageId`);\n assertChatRole(message.role, `${field}.messages[].role`);\n if (\n typeof message.content !== 'string' ||\n message.content.length > AGENT_DEVICE_RPC_LIMITS.runLogContentCharacters\n ) fail(`${field}.messages[].content`);\n }\n optionalCursorString(record.nextCursor, `${field}.nextCursor`);\n if (typeof record.hasMoreAfter !== 'boolean') fail(`${field}.hasMoreAfter`);\n nullableRunStatus(record.runStatus, `${field}.runStatus`);\n assertJsonBytes(record, AGENT_DEVICE_RPC_LIMITS.runLogPageBytes, field);\n}\n\nfunction assertAgentDefinition(value: unknown, field: string): void {\n const record = asRecord(value, field);\n assertIdentifier(record.id, `${field}.id`);\n if (typeof record.name !== 'string' || typeof record.description !== 'string' || typeof record.systemPrompt !== 'string') fail(field);\n assertArray(record.tools, `${field}.tools`);\n if (!record.tools.every(tool => typeof tool === 'string')) fail(`${field}.tools`);\n if (typeof record.version !== 'string') fail(`${field}.version`);\n}\n\nfunction assertConversationMeta(value: unknown, field: string): asserts value is ConversationMeta {\n const record = asRecord(value, field);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n if (\n typeof record.title !== 'string' || record.title.length > 512 ||\n typeof record.lastMessagePreview !== 'string' || record.lastMessagePreview.length > 2_000 ||\n typeof record.originNodeId !== 'string' ||\n typeof record.definitionId !== 'string' ||\n typeof record.isUserInitiated !== 'boolean'\n ) fail(field);\n assertBoundedInteger(record.lastMessageTimestamp, `${field}.lastMessageTimestamp`, 0, Number.MAX_SAFE_INTEGER);\n assertBoundedInteger(record.messageCount, `${field}.messageCount`, 0, Number.MAX_SAFE_INTEGER);\n assertBoundedInteger(record.originClock, `${field}.originClock`, 0, Number.MAX_SAFE_INTEGER);\n}\n\nfunction optionalConversationMeta(value: unknown, field: string, nullable = false): void {\n if (value === undefined || (nullable && value === null)) return;\n assertConversationMeta(value, field);\n}\n\nfunction assertChatMessage(\n value: unknown,\n field: string,\n maximumBytes = AGENT_DEVICE_RPC_LIMITS.messageProjectionBytes,\n): asserts value is ChatMessage {\n try {\n assertCanonicalChatMessageProjection(value);\n assertJsonBytes(value, maximumBytes, field);\n } catch {\n fail(field);\n }\n}\n\n/** Parse the complete JSON object reconstructed from getMessageDetail chunks. */\nexport function parseAgentDeviceRpcMessageDetail(value: unknown): ChatMessage {\n assertChatMessage(value, 'response.data', AGENT_DEVICE_RPC_LIMITS.messageDetailBytes);\n return value;\n}\n\nfunction assertChatRole(value: unknown, field: string): void {\n if (value !== 'user' && value !== 'assistant' && value !== 'tool' && value !== 'agent' && value !== 'error') fail(field);\n}\n\nfunction assertAttachmentReference(value: unknown, field: string): void {\n const record = asRecord(value, field);\n assertIdentifier(record.contentHash, `${field}.contentHash`);\n if (typeof record.filename !== 'string' || typeof record.mimeType !== 'string') fail(field);\n assertBoundedInteger(record.size, `${field}.size`, 0, Number.MAX_SAFE_INTEGER);\n}\n\nfunction nullableRunStatus(value: unknown, field: string): void {\n if (value === null) return;\n const record = asRecord(value, field);\n assertOnlyKeys(record, [\n 'runId',\n 'conversationId',\n 'definitionId',\n 'turnId',\n 'requestPeerId',\n 'requestId',\n 'payloadDigest',\n 'state',\n 'acceptedAt',\n 'updatedAt',\n 'startedAt',\n 'finishedAt',\n 'cancelRequestedAt',\n 'error',\n ], field);\n assertIdentifier(record.runId, `${field}.runId`);\n assertIdentifier(record.requestId, `${field}.requestId`);\n assertIdentifier(record.turnId, `${field}.turnId`);\n assertIdentifier(record.conversationId, `${field}.conversationId`);\n assertIdentifier(record.definitionId, `${field}.definitionId`);\n assertIdentifier(record.requestPeerId, `${field}.requestPeerId`);\n assertIdentifier(record.payloadDigest, `${field}.payloadDigest`);\n if (!['accepted', 'queued', 'running', 'completed', 'failed', 'cancelled'].includes(record.state as string)) fail(`${field}.state`);\n assertBoundedInteger(record.acceptedAt, `${field}.acceptedAt`, 0, Number.MAX_SAFE_INTEGER);\n assertBoundedInteger(record.updatedAt, `${field}.updatedAt`, 0, Number.MAX_SAFE_INTEGER);\n optionalBoundedInteger(record.startedAt, `${field}.startedAt`, 0, Number.MAX_SAFE_INTEGER);\n optionalBoundedInteger(record.finishedAt, `${field}.finishedAt`, 0, Number.MAX_SAFE_INTEGER);\n optionalBoundedInteger(record.cancelRequestedAt, `${field}.cancelRequestedAt`, 0, Number.MAX_SAFE_INTEGER);\n if (record.error !== undefined) {\n try {\n normalizeAgentRunError(record.error);\n } catch {\n fail(`${field}.error`);\n }\n }\n}\n\nfunction asRecord(value: unknown, field: string): Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) fail(field);\n return value as Record<string, unknown>;\n}\n\nfunction assertOnlyKeys(\n record: Record<string, unknown>,\n allowed: readonly string[],\n field: string,\n): void {\n if (Object.keys(record).some(key => !allowed.includes(key))) fail(field);\n}\n\nfunction assertArray(value: unknown, field: string): asserts value is unknown[] {\n if (!Array.isArray(value)) fail(field);\n}\n\nfunction assertIdentifier(value: unknown, field: string): asserts value is string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.length > AGENT_DEVICE_RPC_LIMITS.identifierCharacters ||\n value !== value.trim() ||\n hasAsciiControlText(value)\n ) fail(field);\n}\n\nfunction optionalIdentifier(value: unknown, field: string): void {\n if (value !== undefined) assertIdentifier(value, field);\n}\n\nfunction optionalString(value: unknown, field: string): void {\n if (value !== undefined && typeof value !== 'string') fail(field);\n}\n\nfunction optionalProjectionPageBytes(value: unknown, field: string): void {\n optionalBoundedInteger(\n value,\n field,\n AGENT_DEVICE_RPC_LIMITS.projectionPageMinBytes,\n AGENT_DEVICE_RPC_LIMITS.projectionPageMaxBytes,\n );\n}\n\nfunction optionalTimelinePageBytes(value: unknown, field: string): void {\n optionalBoundedInteger(\n value,\n field,\n 1,\n AGENT_DEVICE_RPC_LIMITS.timelinePageMaxBytes,\n );\n}\n\nfunction optionalLoadAroundBytes(value: unknown, field: string): void {\n optionalBoundedInteger(\n value,\n field,\n 1,\n AGENT_DEVICE_RPC_LIMITS.loadAroundMaxBytes,\n );\n}\n\nfunction optionalBoolean(value: unknown, field: string): void {\n if (value !== undefined && typeof value !== 'boolean') fail(field);\n}\n\nfunction optionalCursorString(value: unknown, field: string): void {\n if (\n value !== undefined &&\n (typeof value !== 'string' ||\n value.length === 0 ||\n value.length > AGENT_DEVICE_RPC_LIMITS.cursorCharacters ||\n value !== value.trim() ||\n hasAsciiControlText(value))\n ) fail(field);\n}\n\nfunction assertPreview(value: unknown, field: string): void {\n if (typeof value !== 'string' || value.length > AGENT_DEVICE_RPC_LIMITS.timelinePreviewCharacters + 1) fail(field);\n}\n\nfunction hasAsciiControlText(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) return true;\n }\n return false;\n}\n\nfunction assertBoundedInteger(value: unknown, field: string, minimum: number, maximum: number): asserts value is number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum || value > maximum) fail(field);\n}\n\nfunction optionalBoundedInteger(value: unknown, field: string, minimum: number, maximum: number): void {\n if (value !== undefined) assertBoundedInteger(value, field, minimum, maximum);\n}\n\nfunction optionalDirection(value: unknown, field: string): void {\n if (value !== undefined && value !== 'backward' && value !== 'forward') fail(field);\n}\n\nfunction optionalQueryMode(value: unknown, field: string): void {\n if (value !== undefined && value !== 'metadata-only' && value !== 'full-content' && value !== 'on-demand') fail(field);\n}\n\nfunction assertJsonBytes(value: unknown, maximum: number, field: string): void {\n if (jsonByteLength(value) > maximum) fail(field);\n}\n\nfunction jsonByteLength(value: unknown): number {\n try {\n return canonicalJsonBytes(value, {\n maxBytes: 16 * 1024 * 1024,\n maxStringBytes: 16 * 1024 * 1024,\n maxStringCodeUnits: 16 * 1024 * 1024,\n maxNodes: 200_000,\n }).byteLength;\n } catch {\n return Number.POSITIVE_INFINITY;\n }\n}\n\nfunction turnRenderLines(value: unknown): number {\n if (!Array.isArray(value)) return Number.POSITIVE_INFINITY;\n let lines = 0;\n for (const item of value) {\n const record = item as Record<string, unknown>;\n const userPreview = record.userPreview;\n if (typeof userPreview === 'string') lines += userPreview.split('\\n').length;\n if (Array.isArray(record.participantPreviews)) {\n for (const participant of record.participantPreviews) {\n const preview = (participant as Record<string, unknown>)?.preview;\n if (typeof preview === 'string') lines += preview.split('\\n').length;\n }\n }\n }\n return lines;\n}\n\nfunction isCanonicalBase64(value: string): boolean {\n return value.length % 4 === 0 && /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value);\n}\n\nfunction decodedBase64ByteLength(value: string): number {\n if (value.length === 0) return 0;\n const padding = value.endsWith('==') ? 2 : value.endsWith('=') ? 1 : 0;\n return value.length / 4 * 3 - padding;\n}\n\nfunction fail(field: string): never {\n throw new AgentDeviceRpcProtocolError(field);\n}\n","import type { ChatMessage } from '../conversation/types.js';\nimport {\n AGENT_DEVICE_RPC_LIMITS,\n AGENT_DEVICE_RPC_METHODS,\n type AgentDeviceRpcCancelRequest,\n type AgentDeviceRpcContract,\n type AgentDeviceRpcCreateRequest,\n type AgentDeviceRpcDeleteTurnRequest,\n type AgentDeviceRpcGetAttachmentChunkRequest,\n type AgentDeviceRpcGetConversationMetaRequest,\n type AgentDeviceRpcGetConversationTimelinePageRequest,\n type AgentDeviceRpcGetDefinitionsRequest,\n type AgentDeviceRpcGetMessageDetailRequest,\n type AgentDeviceRpcGetMessagePageRequest,\n type AgentDeviceRpcGetRunStatusRequest,\n type AgentDeviceRpcGetTurnDetailRequest,\n type AgentDeviceRpcListConversationsRequest,\n type AgentDeviceRpcListTurnsRequest,\n type AgentDeviceRpcLoadAroundRequest,\n type AgentDeviceRpcMethod,\n AgentDeviceRpcProtocolError,\n type AgentDeviceRpcPullAgentRunLogRequest,\n type AgentDeviceRpcRequest,\n type AgentDeviceRpcResponse,\n type AgentDeviceRpcRetryTurnRequest,\n type AgentDeviceRpcRunTurnRequest,\n type AgentDeviceRpcSendRequest,\n assertAgentDeviceRpcRequest,\n assertAgentDeviceRpcResponseCorrelation,\n parseAgentDeviceRpcMessageDetail,\n parseAgentDeviceRpcResponse,\n} from './agentDeviceRpc.js';\nimport { ATTACHMENT_UPLOAD_LIMITS, type AttachmentUploadRpcCall, createAttachmentUploadRpcClient } from './attachmentUpload.js';\nimport { createScheduledTaskRpcClient, type ScheduledTaskRpcCall } from './scheduledTaskRpc.js';\nimport type { DeviceConnectionGrant } from './types.js';\n\nexport type AgentDeviceRpcSend = (\n peerId: string,\n method: string,\n parameters: unknown,\n options?: AgentDeviceRpcTransportOptions,\n) => Promise<unknown>;\n\nexport interface AgentDeviceRpcTransportOptions {\n presentedGrant?: DeviceConnectionGrant;\n signal?: AbortSignal;\n}\n\nexport interface AgentDeviceRpcCallOptions {\n signal?: AbortSignal;\n}\n\nexport interface AgentDeviceRpcClientOptions {\n peerId: string;\n sendRpc: AgentDeviceRpcSend;\n presentedGrant?: DeviceConnectionGrant;\n /** Override only when the host's runtime needs a UUID polyfill. */\n createRequestId?: () => string;\n}\n\nexport type AgentDeviceRpcStartTurnRequest =\n | {\n kind: 'send';\n request: Omit<AgentDeviceRpcSendRequest, 'requestId' | 'turnId'> & { requestId?: string; turnId?: string };\n }\n | {\n kind: 'runTurn';\n request: Omit<AgentDeviceRpcRunTurnRequest, 'requestId' | 'turnId'> & { requestId?: string; turnId?: string };\n };\n\nexport type PreparedAgentDeviceRpcStartTurnRequest =\n | { kind: 'send'; request: AgentDeviceRpcSendRequest }\n | { kind: 'runTurn'; request: AgentDeviceRpcRunTurnRequest };\n\nexport interface AgentDeviceRpcReadAttachmentOptions extends AgentDeviceRpcCallOptions {\n /** A host policy bound; prevents a malicious peer from declaring unbounded data. */\n maxBytes: number;\n /** Whole multi-chunk operation deadline; defaults to 120 seconds. */\n deadlineMs?: number;\n}\n\nexport interface AgentDeviceRpcReadMessageDetailOptions extends AgentDeviceRpcCallOptions {\n /** Defaults to the portable 64 MiB safety ceiling and may only lower it. */\n maxBytes?: number;\n /** Whole multi-chunk operation deadline; defaults to 120 seconds. */\n deadlineMs?: number;\n}\n\n/**\n * Browser/mobile-safe typed facade. Host code supplies `sendRpc` once and no\n * longer embeds wire method strings or casts untrusted peer responses.\n */\nexport function createAgentDeviceRpcClient(options: AgentDeviceRpcClientOptions) {\n async function request<M extends AgentDeviceRpcMethod>(\n method: M,\n parameters: AgentDeviceRpcRequest<M>,\n callOptions: AgentDeviceRpcCallOptions = {},\n ): Promise<AgentDeviceRpcResponse<M>> {\n callOptions.signal?.throwIfAborted();\n assertAgentDeviceRpcRequest(method, parameters);\n const response = await options.sendRpc(\n options.peerId,\n method,\n parameters,\n { presentedGrant: options.presentedGrant, signal: callOptions.signal },\n );\n callOptions.signal?.throwIfAborted();\n const parsed = parseAgentDeviceRpcResponse(method, response);\n assertAgentDeviceRpcResponseCorrelation(method, parameters, parsed);\n return parsed;\n }\n\n async function getDefinitions(\n parameters: AgentDeviceRpcGetDefinitionsRequest = {},\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getDefinitions, parameters, callOptions);\n }\n\n async function createAgent(parameters: AgentDeviceRpcCreateRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.create, parameters, callOptions);\n }\n\n async function send(parameters: AgentDeviceRpcSendRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.send, parameters, callOptions);\n }\n\n async function runTurn(parameters: AgentDeviceRpcRunTurnRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.runTurn, parameters, callOptions);\n }\n\n function prepareStartTurn(parameters: AgentDeviceRpcStartTurnRequest): PreparedAgentDeviceRpcStartTurnRequest {\n const requestId = parameters.request.requestId ??\n (options.createRequestId ?? createAgentDeviceRpcRequestId)();\n const turnId = parameters.request.turnId ??\n (options.createRequestId ?? createAgentDeviceRpcRequestId)();\n return parameters.kind === 'send'\n ? { kind: 'send', request: { ...parameters.request, requestId, turnId } }\n : { kind: 'runTurn', request: { ...parameters.request, requestId, turnId } };\n }\n\n async function startTurn(\n parameters: PreparedAgentDeviceRpcStartTurnRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return parameters.kind === 'send'\n ? send(parameters.request, callOptions)\n : runTurn(parameters.request, callOptions);\n }\n\n async function getRunStatus(parameters: AgentDeviceRpcGetRunStatusRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.getRunStatus, parameters, callOptions);\n }\n\n async function cancel(parameters: AgentDeviceRpcCancelRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.cancel, parameters, callOptions);\n }\n\n async function deleteTurn(\n parameters: AgentDeviceRpcDeleteTurnRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.deleteTurn, parameters, callOptions);\n }\n\n async function retryTurn(\n parameters: AgentDeviceRpcRetryTurnRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.retryTurn, parameters, callOptions);\n }\n\n async function listConversations(\n parameters: AgentDeviceRpcListConversationsRequest = {},\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.listConversations, parameters, callOptions);\n }\n\n async function getConversationMeta(\n parameters: AgentDeviceRpcGetConversationMetaRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getConversationMeta, parameters, callOptions);\n }\n\n async function listTurns(parameters: AgentDeviceRpcListTurnsRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.listTurns, {\n ...parameters,\n byteBudget: parameters.byteBudget ?? AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes,\n }, callOptions);\n }\n\n async function getTurnDetail(\n parameters: AgentDeviceRpcGetTurnDetailRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getTurnDetail, {\n ...parameters,\n limit: parameters.limit ?? AGENT_DEVICE_RPC_LIMITS.turnDetailPage,\n maxBytes: parameters.maxBytes ?? AGENT_DEVICE_RPC_LIMITS.turnDetailDefaultBytes,\n }, callOptions);\n }\n\n async function getMessagePage(parameters: AgentDeviceRpcGetMessagePageRequest, callOptions: AgentDeviceRpcCallOptions = {}) {\n return request(AGENT_DEVICE_RPC_METHODS.getMessagePage, {\n ...parameters,\n mode: parameters.mode ?? 'on-demand',\n maxBytes: parameters.maxBytes ?? AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes,\n }, callOptions);\n }\n\n async function getConversationTimelinePage(\n parameters: AgentDeviceRpcGetConversationTimelinePageRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getConversationTimelinePage, {\n ...parameters,\n limit: parameters.limit ?? AGENT_DEVICE_RPC_LIMITS.timelinePage,\n maxBytes: parameters.maxBytes ?? AGENT_DEVICE_RPC_LIMITS.timelinePageDefaultBytes,\n }, callOptions);\n }\n\n async function loadAround(\n parameters: AgentDeviceRpcLoadAroundRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.loadAround, {\n ...parameters,\n maxMessages: parameters.maxMessages ?? AGENT_DEVICE_RPC_LIMITS.loadAroundMessages,\n maxBytes: parameters.maxBytes ?? AGENT_DEVICE_RPC_LIMITS.loadAroundDefaultBytes,\n }, callOptions);\n }\n\n async function getMessageDetail(\n parameters: AgentDeviceRpcGetMessageDetailRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getMessageDetail, parameters, callOptions);\n }\n\n async function readMessageDetail(\n parameters: Omit<AgentDeviceRpcGetMessageDetailRequest, 'offset'>,\n readOptions: AgentDeviceRpcReadMessageDetailOptions = {},\n ): Promise<ChatMessage | null> {\n const maxBytes = normalizeMaximumBytes(\n readOptions.maxBytes,\n AGENT_DEVICE_RPC_LIMITS.messageDetailBytes,\n );\n const bytes = await readChunks(\n async (offset, signal) => {\n const chunk = await getMessageDetail({ ...parameters, offset }, { signal });\n return chunk.found ? chunk : null;\n },\n maxBytes,\n readOptions,\n );\n if (bytes === null) return null;\n let value: unknown;\n try {\n value = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));\n } catch {\n throw new AgentDeviceRpcProtocolError('response.data');\n }\n return parseAgentDeviceRpcMessageDetail(value);\n }\n\n async function getAttachmentChunk(\n parameters: AgentDeviceRpcGetAttachmentChunkRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.getAttachmentChunk, parameters, callOptions);\n }\n\n async function readAttachment(\n parameters: Omit<AgentDeviceRpcGetAttachmentChunkRequest, 'offset'>,\n readOptions: AgentDeviceRpcReadAttachmentOptions,\n ): Promise<Uint8Array | null> {\n const maxBytes = normalizeMaximumBytes(readOptions.maxBytes, ATTACHMENT_UPLOAD_LIMITS.totalBytes);\n return readChunks(\n async (offset, signal) => {\n const chunk = await getAttachmentChunk({ ...parameters, offset }, { signal });\n if (!chunk.found) return null;\n if (chunk.totalBytes > maxBytes) {\n throw new AgentDeviceRpcProtocolError('response.totalBytes');\n }\n return chunk;\n },\n maxBytes,\n readOptions,\n );\n }\n\n async function pullAgentRunLog(\n parameters: AgentDeviceRpcPullAgentRunLogRequest,\n callOptions: AgentDeviceRpcCallOptions = {},\n ) {\n return request(AGENT_DEVICE_RPC_METHODS.pullAgentRunLog, {\n ...parameters,\n maxBytes: parameters.maxBytes ?? AGENT_DEVICE_RPC_LIMITS.projectionPageDefaultBytes,\n }, callOptions);\n }\n\n const attachmentUpload = createAttachmentUploadRpcClient({\n call: ((method, parameters, callOptions) => request(method, parameters, callOptions)) as AttachmentUploadRpcCall,\n });\n const scheduledTasks = createScheduledTaskRpcClient({\n call: ((method, parameters, callOptions) => request(method, parameters, callOptions)) as ScheduledTaskRpcCall,\n });\n\n return {\n request,\n getDefinitions,\n createAgent,\n send,\n runTurn,\n prepareStartTurn,\n startTurn,\n getRunStatus,\n cancel,\n deleteTurn,\n retryTurn,\n listConversations,\n getConversationMeta,\n listTurns,\n getTurnDetail,\n getMessagePage,\n getConversationTimelinePage,\n loadAround,\n getMessageDetail,\n readMessageDetail,\n getAttachmentChunk,\n readAttachment,\n pullAgentRunLog,\n beginAttachmentUpload: attachmentUpload.begin,\n uploadAttachmentChunk: attachmentUpload.chunk,\n commitAttachmentUpload: attachmentUpload.commit,\n scheduledTasks,\n listScheduledTasks: scheduledTasks.list,\n getScheduledTask: scheduledTasks.get,\n createScheduledTask: scheduledTasks.create,\n updateScheduledTask: scheduledTasks.update,\n deleteScheduledTask: scheduledTasks.delete,\n previewScheduledTaskCron: scheduledTasks.cronPreview,\n };\n}\n\nexport type AgentDeviceRpcClient = ReturnType<typeof createAgentDeviceRpcClient>;\n\n/** Create a UUID request id without importing Node crypto into browser/mobile. */\nexport function createAgentDeviceRpcRequestId(): string {\n const bytes = new Uint8Array(16);\n const getRandomValues = globalThis.crypto?.getRandomValues.bind(globalThis.crypto);\n if (!getRandomValues) throw new AgentDeviceRpcProtocolError('requestIdGenerator');\n getRandomValues(bytes);\n bytes[6] = (bytes[6] & 0x0F) | 0x40;\n bytes[8] = (bytes[8] & 0x3F) | 0x80;\n const hex = [...bytes].map(byte => byte.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\ninterface ReadableChunk {\n data: string;\n offset: number;\n totalBytes: number;\n nextOffset?: number;\n}\n\nasync function readChunks(\n read: (offset: number, signal: AbortSignal) => Promise<ReadableChunk | null>,\n maxBytes: number,\n options: { signal?: AbortSignal; deadlineMs?: number },\n): Promise<Uint8Array | null> {\n const operation = createDeadlineSignal(options.signal, options.deadlineMs);\n let offset = 0;\n let expectedTotal: number | undefined;\n let result: Uint8Array | undefined;\n let chunkCount = 0;\n try {\n for (;;) {\n operation.signal.throwIfAborted();\n chunkCount += 1;\n if (chunkCount > MAX_DETAIL_CHUNKS) throw new AgentDeviceRpcProtocolError('response.chunkCount');\n const chunk = await read(offset, operation.signal);\n operation.signal.throwIfAborted();\n if (chunk === null) {\n if (offset !== 0) throw new AgentDeviceRpcProtocolError('response.found');\n return null;\n }\n if (chunk.totalBytes > maxBytes) throw new AgentDeviceRpcProtocolError('response.totalBytes');\n if (chunk.offset !== offset) throw new AgentDeviceRpcProtocolError('response.offset');\n if (expectedTotal !== undefined && chunk.totalBytes !== expectedTotal) {\n throw new AgentDeviceRpcProtocolError('response.totalBytes');\n }\n expectedTotal = chunk.totalBytes;\n result ??= new Uint8Array(expectedTotal);\n const bytes = base64ToBytes(chunk.data);\n if (offset + bytes.byteLength > expectedTotal) throw new AgentDeviceRpcProtocolError('response.data');\n result.set(bytes, offset);\n const nextOffset = offset + bytes.byteLength;\n if (chunk.nextOffset === undefined) {\n if (nextOffset !== expectedTotal) throw new AgentDeviceRpcProtocolError('response.nextOffset');\n return result;\n }\n if (bytes.byteLength === 0 || chunk.nextOffset !== nextOffset) {\n throw new AgentDeviceRpcProtocolError('response.nextOffset');\n }\n offset = chunk.nextOffset;\n }\n } finally {\n operation.dispose();\n }\n}\n\nconst DEFAULT_DETAIL_DEADLINE_MS = 120_000;\nconst MAX_DETAIL_DEADLINE_MS = 600_000;\nconst MAX_DETAIL_CHUNKS = 256;\n\nfunction createDeadlineSignal(parent: AbortSignal | undefined, requested: number | undefined): {\n signal: AbortSignal;\n dispose(): void;\n} {\n const deadlineMs = requested ?? DEFAULT_DETAIL_DEADLINE_MS;\n if (!Number.isSafeInteger(deadlineMs) || deadlineMs < 1 || deadlineMs > MAX_DETAIL_DEADLINE_MS) {\n throw new AgentDeviceRpcProtocolError('options.deadlineMs');\n }\n const controller = new AbortController();\n const abortFromParent = () => {\n controller.abort(parent?.reason);\n };\n if (parent?.aborted) abortFromParent();\n else parent?.addEventListener('abort', abortFromParent, { once: true });\n const timeout = setTimeout(() => {\n controller.abort(new Error('agent_device_rpc_detail_deadline'));\n }, deadlineMs);\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timeout);\n parent?.removeEventListener('abort', abortFromParent);\n },\n };\n}\n\nfunction normalizeMaximumBytes(value: number | undefined, ceiling: number): number {\n const result = value ?? ceiling;\n if (!Number.isSafeInteger(result) || result < 0 || result > ceiling) {\n throw new AgentDeviceRpcProtocolError('options.maxBytes');\n }\n return result;\n}\n\nfunction base64ToBytes(value: string): Uint8Array {\n const binary = atob(value);\n const result = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index++) result[index] = binary.charCodeAt(index);\n return result;\n}\n\n// Ensure mapped DTOs remain visible in generated declarations without forcing\n// hosts to import the contract map directly.\nexport type { AgentDeviceRpcContract };\n","import { domainSeparatedCanonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type { DeviceConnectionGrant, DeviceConnectionGrantStringScope, DeviceRelayReservationToken, MemeLoopProtocol } from './types.js';\n\nexport const DEVICE_BINDING_SIGNATURE_DOMAIN = 'memeloop-device-binding-v2';\nexport const DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN = 'memeloop-device-connection-grant-v2';\nexport const DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN = 'memeloop-device-relay-admission-v2';\nexport const DEVICE_CONNECTION_GRANT_MAX_PEERS = 256;\nexport const DEVICE_CONNECTION_GRANT_MAX_RPC_METHODS = 128;\nexport const DEVICE_CONNECTION_GRANT_MAX_RESOURCE_IDS = 256;\nexport const DEVICE_CONNECTION_GRANT_MAX_SCOPE_VALUE_LENGTH = 512;\nexport const DEVICE_CONNECTION_GRANT_MAX_TTL_MS = 10 * 60_000;\nexport const DEVICE_RELAY_RESERVATION_TOKEN_MAX_TTL_MS = 40 * 60_000;\nexport const DEVICE_GRANT_MAX_CLOCK_SKEW_MS = 30_000;\nexport const DEVICE_RELAY_RESERVATION_MAX_ADDRESSES = 64;\nexport const DEVICE_RELAY_RESERVATION_MAX_ADDRESS_LENGTH = 2_048;\n\nconst DEVICE_SIGNATURE_LIMITS = Object.freeze({\n maxDepth: 8,\n maxNodes: 2_048,\n maxStringCodeUnits: 4_096,\n maxStringBytes: 16 * 1_024,\n maxBytes: 1_048_576,\n});\n\nconst DEVICE_PROTOCOLS: ReadonlySet<string> = new Set<MemeLoopProtocol>([\n '/memeloop/orchestration/2.0.0',\n '/memeloop/pairing/2.0.0',\n '/memeloop/relay-admission/2.0.0',\n '/memeloop/rpc/2.0.0',\n '/memeloop/sync/2.0.0',\n]);\n\nexport function buildDeviceBindingMessage(input: {\n accountId: string;\n peerId: string;\n publicKeyMultibase: string;\n nonce: string;\n}): Uint8Array {\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_BINDING_SIGNATURE_DOMAIN,\n input,\n DEVICE_SIGNATURE_LIMITS,\n );\n}\n\nexport function buildDeviceConnectionGrantMessage(\n grant: Omit<DeviceConnectionGrant, 'signature'>,\n): Uint8Array {\n if (!hasCanonicalDeviceConnectionGrantClaims({ ...grant, signature: 'validation-signature' })) {\n throw new Error('invalid device connection grant claims');\n }\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_CONNECTION_GRANT_SIGNATURE_DOMAIN,\n grant,\n DEVICE_SIGNATURE_LIMITS,\n );\n}\n\n/** True only for the one canonical, bounded encoding accepted by v2 verifiers. */\nexport function hasCanonicalDeviceConnectionGrantClaims(\n value: unknown,\n): value is DeviceConnectionGrant {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const grant = value as Record<string, unknown>;\n return (\n hasOnlyKeys(grant, [\n 'issuer',\n 'accountId',\n 'subjectPeerId',\n 'allowedPeerIds',\n 'protocols',\n 'rpcMethodScope',\n 'conversationScope',\n 'definitionScope',\n 'issuedAt',\n 'expiresAt',\n 'signature',\n ]) &&\n grant.issuer === 'memeloop-cloud' &&\n canonicalScopeValue(grant.accountId) &&\n canonicalScopeValue(grant.subjectPeerId) &&\n canonicalStringList(grant.allowedPeerIds, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_PEERS,\n }) &&\n canonicalStringList(grant.protocols, {\n maxEntries: DEVICE_PROTOCOLS.size,\n allowedValues: DEVICE_PROTOCOLS,\n }) &&\n canonicalScope(grant.rpcMethodScope, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_RPC_METHODS,\n }) &&\n canonicalScope(grant.conversationScope, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_RESOURCE_IDS,\n }) &&\n canonicalScope(grant.definitionScope, {\n maxEntries: DEVICE_CONNECTION_GRANT_MAX_RESOURCE_IDS,\n }) &&\n validLifetime(\n grant.issuedAt,\n grant.expiresAt,\n DEVICE_CONNECTION_GRANT_MAX_TTL_MS,\n ) &&\n canonicalScopeValue(grant.signature)\n );\n}\n\nfunction canonicalScopeValue(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 &&\n value.length <= DEVICE_CONNECTION_GRANT_MAX_SCOPE_VALUE_LENGTH &&\n hasPairedUtf16(value) && !value.includes(',') && !value.includes('\\n') &&\n !value.includes('\\r');\n}\n\nexport function deviceConnectionGrantAllowsProtocol(\n grant: DeviceConnectionGrant,\n protocol: MemeLoopProtocol,\n): boolean {\n return hasCanonicalDeviceConnectionGrantClaims(grant) && grant.protocols.includes(protocol);\n}\n\nexport function deviceConnectionGrantAllowsRpc(\n grant: DeviceConnectionGrant,\n input: { method: string; conversationId?: string; definitionId?: string },\n): boolean {\n if (!deviceConnectionGrantAllowsProtocol(grant, '/memeloop/rpc/2.0.0')) return false;\n if (!canonicalScopeValue(input.method)) return false;\n if (input.conversationId !== undefined && !canonicalScopeValue(input.conversationId)) return false;\n if (input.definitionId !== undefined && !canonicalScopeValue(input.definitionId)) return false;\n if (!scopeAllows(grant.rpcMethodScope, input.method)) return false;\n if (input.conversationId !== undefined && !scopeAllows(grant.conversationScope, input.conversationId)) {\n return false;\n }\n if (input.definitionId !== undefined && !scopeAllows(grant.definitionScope, input.definitionId)) {\n return false;\n }\n return true;\n}\n\nfunction scopeAllows(scope: DeviceConnectionGrantStringScope, value: string): boolean {\n return scope.mode === 'all' || (scope.mode === 'ids' && scope.ids.includes(value));\n}\n\nfunction canonicalScope(value: unknown, options: CanonicalStringListOptions): boolean {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const scope = value as Record<string, unknown>;\n if (scope.mode === 'none' || scope.mode === 'all') {\n return Object.keys(scope).length === 1;\n }\n return scope.mode === 'ids' && Object.keys(scope).length === 2 &&\n Object.hasOwn(scope, 'ids') && canonicalStringList(scope.ids, options) &&\n (scope.ids as unknown[]).length > 0;\n}\n\ninterface CanonicalStringListOptions {\n maxEntries: number;\n allowedValues?: ReadonlySet<string>;\n}\n\nfunction canonicalStringList(value: unknown, options: CanonicalStringListOptions): boolean {\n if (!Array.isArray(value) || value.length > options.maxEntries) return false;\n let previous: string | undefined;\n for (const entry of value) {\n if (\n !canonicalScopeValue(entry) ||\n (options.allowedValues && !options.allowedValues.has(entry)) ||\n (previous !== undefined && previous >= entry)\n ) return false;\n previous = entry;\n }\n return true;\n}\n\nexport function buildDeviceRelayReservationTokenMessage(\n token: Omit<DeviceRelayReservationToken, 'signature'>,\n): Uint8Array {\n if (\n !hasCanonicalDeviceRelayReservationTokenClaims({\n ...token,\n signature: 'validation-signature',\n })\n ) {\n throw new Error('invalid device relay reservation token claims');\n }\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_RELAY_ADMISSION_SIGNATURE_DOMAIN,\n token,\n DEVICE_SIGNATURE_LIMITS,\n );\n}\n\n/** Reject ambiguous/unbounded relay claims before signing or verification. */\nexport function hasCanonicalDeviceRelayReservationTokenClaims(\n value: unknown,\n): value is DeviceRelayReservationToken {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const token = value as Record<string, unknown>;\n return hasOnlyKeys(token, [\n 'issuer',\n 'accountId',\n 'peerId',\n 'relayMultiaddrs',\n 'bootstrapMultiaddrs',\n 'issuedAt',\n 'expiresAt',\n 'signature',\n ]) && token.issuer === 'memeloop-cloud' && canonicalScopeValue(token.accountId) &&\n canonicalScopeValue(token.peerId) && validLifetime(\n token.issuedAt,\n token.expiresAt,\n DEVICE_RELAY_RESERVATION_TOKEN_MAX_TTL_MS,\n ) &&\n canonicalAddressList(token.relayMultiaddrs, false) &&\n canonicalAddressList(token.bootstrapMultiaddrs, true) &&\n canonicalScopeValue(token.signature);\n}\n\nfunction canonicalAddressList(value: unknown, allowEmpty: boolean): boolean {\n if (!Array.isArray(value) || value.length > DEVICE_RELAY_RESERVATION_MAX_ADDRESSES) {\n return false;\n }\n if (!allowEmpty && value.length === 0) return false;\n let previous: string | undefined;\n for (const address of value) {\n if (\n typeof address !== 'string' || address.length === 0 ||\n address.length > DEVICE_RELAY_RESERVATION_MAX_ADDRESS_LENGTH ||\n address !== address.trim() || !hasPairedUtf16(address) || !address.startsWith('/') ||\n containsAsciiControlOrSpace(address) ||\n (previous !== undefined && previous >= address)\n ) return false;\n previous = address;\n }\n return true;\n}\n\nfunction validLifetime(issuedAt: unknown, expiresAt: unknown, maxTtlMs: number): boolean {\n return Number.isSafeInteger(issuedAt) && Number.isSafeInteger(expiresAt) &&\n (issuedAt as number) >= 0 && (expiresAt as number) > (issuedAt as number) &&\n (expiresAt as number) - (issuedAt as number) <= maxTtlMs;\n}\n\nfunction hasOnlyKeys(record: Record<string, unknown>, allowed: readonly string[]): boolean {\n const allowedKeys = new Set(allowed);\n return Object.keys(record).every(key => allowedKeys.has(key)) &&\n allowed.every(key => Object.hasOwn(record, key));\n}\n\nfunction hasPairedUtf16(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code >= 0xd800 && code <= 0xdbff) {\n const next = value.charCodeAt(index + 1);\n if (next < 0xdc00 || next > 0xdfff) return false;\n index += 1;\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n return false;\n }\n }\n return true;\n}\n\nfunction containsAsciiControlOrSpace(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 32 || code === 127) return true;\n }\n return false;\n}\n","import { hasCanonicalDeviceConnectionGrantClaims, hasCanonicalDeviceRelayReservationTokenClaims } from './deviceGrantMessages.js';\nimport type { CloudDeviceClient, CloudDeviceRecord, DeviceCloudCommitFence, DeviceConnectionGrant, DeviceRelayReservationToken } from './types.js';\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst DEFAULT_RESPONSE_MAX_BYTES = 2 * 1024 * 1024;\nconst DEFAULT_ERROR_MAX_CHARACTERS = 4_096;\nconst DEFAULT_TOKEN_SAFETY_MARGIN_MS = 2 * 60_000;\nconst CLOUD_URL_MAX_CHARACTERS = 2_048;\nconst CLOUD_ACCESS_TOKEN_MAX_CHARACTERS = 16_384;\n\ntype Awaitable<T> = T | Promise<T>;\ntype ConnectionGrantRequest = Parameters<CloudDeviceClient['createConnectionGrant']>[0];\n\nexport type CloudDeviceFetch = (\n input: RequestInfo | URL,\n init?: RequestInit,\n) => Promise<Response>;\n\nexport type CloudDeviceAccessTokenSupplier = (\n signal: AbortSignal,\n) => Awaitable<string | undefined>;\n\nexport interface DeviceCloudTokenStorage {\n loadConnectionGrant(input: ConnectionGrantRequest): Awaitable<unknown>;\n /** The final durable write must atomically reject a stale generation fence. */\n saveConnectionGrant(\n input: ConnectionGrantRequest,\n grant: DeviceConnectionGrant,\n fence?: DeviceCloudCommitFence,\n ): Awaitable<void>;\n loadRelayReservation(peerId: string): Awaitable<unknown>;\n /** The final durable write must atomically reject a stale generation fence. */\n saveRelayReservation(\n peerId: string,\n token: DeviceRelayReservationToken,\n fence?: DeviceCloudCommitFence,\n ): Awaitable<void>;\n clear(): Awaitable<void>;\n}\n\nexport class MemoryDeviceCloudTokenStorage implements DeviceCloudTokenStorage {\n private readonly grants = new Map<string, DeviceConnectionGrant>();\n private readonly relayReservations = new Map<string, DeviceRelayReservationToken>();\n\n public loadConnectionGrant(input: ConnectionGrantRequest): DeviceConnectionGrant | undefined {\n return this.grants.get(connectionGrantCacheKey(input));\n }\n\n public saveConnectionGrant(\n input: ConnectionGrantRequest,\n grant: DeviceConnectionGrant,\n fence?: DeviceCloudCommitFence,\n ): void {\n const write = (): void => {\n this.grants.set(connectionGrantCacheKey(input), grant);\n };\n if (!fence) {\n write();\n return;\n }\n if (!fence.commitSynchronous(write)) fence.throwIfStale();\n }\n\n public loadRelayReservation(peerId: string): DeviceRelayReservationToken | undefined {\n return this.relayReservations.get(peerId);\n }\n\n public saveRelayReservation(\n peerId: string,\n token: DeviceRelayReservationToken,\n fence?: DeviceCloudCommitFence,\n ): void {\n const write = (): void => {\n this.relayReservations.set(peerId, token);\n };\n if (!fence) {\n write();\n return;\n }\n if (!fence.commitSynchronous(write)) fence.throwIfStale();\n }\n\n public clear(): void {\n this.grants.clear();\n this.relayReservations.clear();\n }\n}\n\nexport type CloudDeviceFetchErrorCode =\n | 'cloud_request_failed'\n | 'cloud_http_error'\n | 'cloud_response_invalid_json'\n | 'cloud_response_invalid_shape'\n | 'cloud_response_too_large';\n\nexport class CloudDeviceFetchError extends Error {\n public readonly code: CloudDeviceFetchErrorCode;\n public readonly status?: number;\n public readonly responseBody?: string;\n\n constructor(\n code: CloudDeviceFetchErrorCode,\n options?: { cause?: unknown; status?: number; responseBody?: string },\n ) {\n const detail = options?.status === undefined\n ? code\n : `${code}: ${options.status} ${(options.responseBody ?? '').trim()}`.trim();\n super(detail, options?.cause === undefined ? undefined : { cause: options.cause });\n this.name = 'CloudDeviceFetchError';\n this.code = code;\n this.status = options?.status;\n this.responseBody = options?.responseBody;\n }\n}\n\nexport interface CloudDeviceFetchClientOptions {\n baseUrl: string;\n fetch?: CloudDeviceFetch;\n accessToken?: string;\n getAccessToken?: CloudDeviceAccessTokenSupplier;\n credentials?: RequestCredentials;\n requestTimeoutMs?: number;\n responseMaxBytes?: number;\n errorMaxCharacters?: number;\n tokenStorage?: DeviceCloudTokenStorage;\n tokenSafetyMarginMs?: number;\n now?: () => number;\n onTokenStorageError?: (operation: 'load' | 'save', error: unknown) => void;\n}\n\n/** Browser/React Native-safe transport for the audited MemeLoop Cloud device API. */\nexport class CloudDeviceFetchClient implements CloudDeviceClient {\n public readonly baseUrl: string;\n private readonly fetchImplementation: CloudDeviceFetch;\n private readonly getAccessToken?: CloudDeviceAccessTokenSupplier;\n private readonly credentials: RequestCredentials;\n private readonly requestTimeoutMs: number;\n private readonly responseMaxBytes: number;\n private readonly errorMaxCharacters: number;\n private readonly tokenStorage: DeviceCloudTokenStorage;\n private readonly tokenSafetyMarginMs: number;\n private readonly now: () => number;\n\n constructor(private readonly options: CloudDeviceFetchClientOptions) {\n this.baseUrl = normalizeCloudDeviceBaseUrl(options.baseUrl);\n if (options.fetch) {\n this.fetchImplementation = options.fetch;\n } else if (typeof globalThis.fetch === 'function') {\n this.fetchImplementation = globalThis.fetch.bind(globalThis);\n } else {\n throw new TypeError('cloud_fetch_required');\n }\n if (options.accessToken !== undefined && options.getAccessToken !== undefined) {\n throw new TypeError('cloud_access_token_supplier_ambiguous');\n }\n if (options.accessToken !== undefined) {\n const accessToken = normalizeAccessToken(options.accessToken);\n this.getAccessToken = () => accessToken;\n } else {\n this.getAccessToken = options.getAccessToken;\n }\n this.credentials = options.credentials ?? 'omit';\n this.requestTimeoutMs = positiveFinite(\n options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n 'requestTimeoutMs',\n );\n this.responseMaxBytes = positiveFinite(\n options.responseMaxBytes ?? DEFAULT_RESPONSE_MAX_BYTES,\n 'responseMaxBytes',\n );\n this.errorMaxCharacters = positiveFinite(\n options.errorMaxCharacters ?? DEFAULT_ERROR_MAX_CHARACTERS,\n 'errorMaxCharacters',\n );\n this.tokenSafetyMarginMs = nonNegativeFinite(\n options.tokenSafetyMarginMs ?? DEFAULT_TOKEN_SAFETY_MARGIN_MS,\n 'tokenSafetyMarginMs',\n );\n this.tokenStorage = options.tokenStorage ?? new MemoryDeviceCloudTokenStorage();\n this.now = options.now ?? Date.now;\n }\n\n public async createBindingNonce(signal?: AbortSignal): Promise<{\n nonce: string;\n accountId: string;\n expiresAt: string;\n }> {\n const value = await this.request('/api/devices/binding/nonce', { method: 'POST' }, signal);\n if (\n !isRecord(value) || !nonEmptyString(value.nonce) || !nonEmptyString(value.accountId) ||\n !nonEmptyString(value.expiresAt)\n ) {\n throw invalidShape();\n }\n return { nonce: value.nonce, accountId: value.accountId, expiresAt: value.expiresAt };\n }\n\n public async registerDevice(\n input: Parameters<CloudDeviceClient['registerDevice']>[0],\n signal?: AbortSignal,\n ): Promise<{ ok: boolean; peerId: string }> {\n const value = await this.request('/api/devices/register', {\n method: 'POST',\n body: JSON.stringify({\n peerId: input.identity.peerId,\n publicKeyMultibase: input.identity.publicKeyMultibase,\n deviceName: input.identity.deviceName,\n platform: input.identity.platform,\n cloudNonce: input.cloudNonce,\n signature: input.signature,\n capabilities: input.capabilities,\n multiaddrs: input.multiaddrs,\n relayReservations: input.relayReservations,\n }),\n }, signal);\n if (!isRecord(value) || typeof value.ok !== 'boolean' || !nonEmptyString(value.peerId)) {\n throw invalidShape();\n }\n return { ok: value.ok, peerId: value.peerId };\n }\n\n public async listDevices(signal?: AbortSignal): Promise<CloudDeviceRecord[]> {\n const value = await this.request('/api/devices', { method: 'GET' }, signal);\n if (\n !isRecord(value) || !Array.isArray(value.devices) ||\n !value.devices.every(isCloudDeviceRecord)\n ) {\n throw invalidShape();\n }\n return value.devices;\n }\n\n public async getConnectionGrantPublicKey(signal?: AbortSignal): Promise<{\n issuer: 'memeloop-cloud';\n publicKeyMultibase: string;\n }> {\n const value = await this.request(\n '/api/devices/connection-grant/public-key',\n { method: 'GET' },\n signal,\n );\n if (\n !isRecord(value) || value.issuer !== 'memeloop-cloud' ||\n !nonEmptyString(value.publicKeyMultibase)\n ) {\n throw invalidShape();\n }\n return { issuer: value.issuer, publicKeyMultibase: value.publicKeyMultibase };\n }\n\n public async createConnectionGrant(\n input: ConnectionGrantRequest,\n signal?: AbortSignal,\n fence?: DeviceCloudCommitFence,\n ): Promise<DeviceConnectionGrant> {\n assertFenceSignal(signal, fence);\n fence?.throwIfStale();\n if (!isCanonicalConnectionGrantRequest(input)) {\n throw new TypeError('invalid_connection_grant_scope');\n }\n const cacheInput = normalizedConnectionGrantRequest(input);\n const cached = await this.loadCachedGrant(cacheInput);\n throwIfAborted(signal);\n fence?.throwIfStale();\n if (isUsableConnectionGrant(cached, cacheInput, this.now() + this.tokenSafetyMarginMs)) {\n return cached;\n }\n const value = await this.request('/api/devices/connection-grant', {\n method: 'POST',\n body: JSON.stringify(input),\n }, signal);\n if (!isUsableConnectionGrant(value, cacheInput, this.now())) throw invalidShape();\n fence?.throwIfStale();\n await this.saveCachedGrant(cacheInput, value, fence);\n fence?.throwIfStale();\n return value;\n }\n\n public async createRelayReservation(\n input: { peerId: string },\n signal?: AbortSignal,\n fence?: DeviceCloudCommitFence,\n ): Promise<DeviceRelayReservationToken> {\n assertFenceSignal(signal, fence);\n fence?.throwIfStale();\n const cached = await this.loadCachedRelayReservation(input.peerId);\n throwIfAborted(signal);\n fence?.throwIfStale();\n if (isUsableRelayReservation(cached, input.peerId, this.now() + this.tokenSafetyMarginMs)) {\n return cached;\n }\n const value = await this.request('/api/devices/relay-reservation', {\n method: 'POST',\n body: JSON.stringify(input),\n }, signal);\n if (!isUsableRelayReservation(value, input.peerId, this.now())) throw invalidShape();\n fence?.throwIfStale();\n await this.saveCachedRelayReservation(input.peerId, value, fence);\n fence?.throwIfStale();\n return value;\n }\n\n public async heartbeat(\n input: Parameters<CloudDeviceClient['heartbeat']>[0],\n signal?: AbortSignal,\n ): Promise<{ ok: boolean }> {\n const value = await this.request('/api/devices/heartbeat', {\n method: 'POST',\n body: JSON.stringify(input),\n }, signal);\n if (!isRecord(value) || typeof value.ok !== 'boolean') throw invalidShape();\n return { ok: value.ok };\n }\n\n /** Clear every grant/relay token owned by this client configuration. */\n public async clearCachedTokens(signal?: AbortSignal): Promise<void> {\n throwIfAborted(signal);\n try {\n await this.tokenStorage.clear();\n } catch (error) {\n this.options.onTokenStorageError?.('save', error);\n throw error;\n }\n throwIfAborted(signal);\n }\n\n private async request(path: string, init: RequestInit, signal?: AbortSignal): Promise<unknown> {\n const request = createRequestSignal(signal, this.requestTimeoutMs);\n try {\n throwIfAborted(request.signal);\n const accessToken = await this.getAccessToken?.(request.signal);\n throwIfAborted(request.signal);\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n if (accessToken !== undefined) {\n headers.authorization = `Bearer ${normalizeAccessToken(accessToken)}`;\n }\n let response: Response;\n try {\n response = await this.fetchImplementation(`${this.baseUrl}${path}`, {\n ...init,\n credentials: this.credentials,\n headers,\n redirect: 'error',\n signal: request.signal,\n });\n } catch (error) {\n if (request.signal.aborted) throw abortReason(request.signal);\n throw new CloudDeviceFetchError('cloud_request_failed', { cause: error });\n }\n const responseText = await readBoundedCloudResponse(\n response,\n this.responseMaxBytes,\n request.signal,\n );\n if (!response.ok) {\n const responseBody = responseText.slice(0, this.errorMaxCharacters);\n throw new CloudDeviceFetchError('cloud_http_error', {\n status: response.status,\n responseBody,\n });\n }\n try {\n return JSON.parse(responseText) as unknown;\n } catch (error) {\n throw new CloudDeviceFetchError('cloud_response_invalid_json', { cause: error });\n }\n } finally {\n request.dispose();\n }\n }\n\n private async loadCachedGrant(input: ConnectionGrantRequest): Promise<unknown> {\n try {\n return await this.tokenStorage.loadConnectionGrant(input);\n } catch (error) {\n this.options.onTokenStorageError?.('load', error);\n return undefined;\n }\n }\n\n private async saveCachedGrant(\n input: ConnectionGrantRequest,\n grant: DeviceConnectionGrant,\n fence?: DeviceCloudCommitFence,\n ): Promise<void> {\n try {\n await this.tokenStorage.saveConnectionGrant(input, grant, fence);\n } catch (error) {\n if (fence && !fence.isCurrent()) fence.throwIfStale();\n this.options.onTokenStorageError?.('save', error);\n }\n }\n\n private async loadCachedRelayReservation(peerId: string): Promise<unknown> {\n try {\n return await this.tokenStorage.loadRelayReservation(peerId);\n } catch (error) {\n this.options.onTokenStorageError?.('load', error);\n return undefined;\n }\n }\n\n private async saveCachedRelayReservation(\n peerId: string,\n token: DeviceRelayReservationToken,\n fence?: DeviceCloudCommitFence,\n ): Promise<void> {\n try {\n await this.tokenStorage.saveRelayReservation(peerId, token, fence);\n } catch (error) {\n if (fence && !fence.isCurrent()) fence.throwIfStale();\n this.options.onTokenStorageError?.('save', error);\n }\n }\n}\n\nfunction assertFenceSignal(\n signal: AbortSignal | undefined,\n fence: DeviceCloudCommitFence | undefined,\n): void {\n if (fence && signal && fence.signal !== signal) {\n throw new TypeError('device_cloud_generation_signal_mismatch');\n }\n}\n\nexport function normalizeCloudDeviceBaseUrl(value: string): string {\n const baseUrl = value.trim();\n if (!baseUrl || baseUrl.length > CLOUD_URL_MAX_CHARACTERS) throw new Error('invalid_cloud_url');\n let parsed: URL;\n try {\n parsed = new URL(baseUrl);\n } catch {\n throw new Error('invalid_cloud_url');\n }\n const loopback = parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1' ||\n parsed.hostname === '[::1]';\n if (parsed.protocol !== 'https:' && !(parsed.protocol === 'http:' && loopback)) {\n throw new Error('cloud_url_requires_https');\n }\n if (\n parsed.username || parsed.password || parsed.search || parsed.hash ||\n (parsed.pathname !== '' && parsed.pathname !== '/')\n ) {\n throw new Error('invalid_cloud_url');\n }\n return parsed.origin;\n}\n\nfunction normalizeAccessToken(value: string): string {\n const accessToken = value.trim();\n if (!accessToken || accessToken.length > CLOUD_ACCESS_TOKEN_MAX_CHARACTERS) {\n throw new Error('invalid_cloud_access_token');\n }\n return accessToken;\n}\n\nfunction positiveFinite(value: number, name: string): number {\n if (!Number.isFinite(value) || value <= 0) throw new TypeError(`${name} must be positive and finite`);\n return value;\n}\n\nfunction nonNegativeFinite(value: number, name: string): number {\n if (!Number.isFinite(value) || value < 0) throw new TypeError(`${name} must be non-negative and finite`);\n return value;\n}\n\nfunction createRequestSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; dispose(): void } {\n const controller = new AbortController();\n const abortFromParent = (): void => {\n controller.abort(parent?.reason);\n };\n if (parent?.aborted) abortFromParent();\n else parent?.addEventListener('abort', abortFromParent, { once: true });\n const timeout = setTimeout(() => {\n controller.abort(new Error('cloud_request_timeout'));\n }, timeoutMs);\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timeout);\n parent?.removeEventListener('abort', abortFromParent);\n },\n };\n}\n\nasync function readBoundedCloudResponse(\n response: Response,\n maximumBytes: number,\n signal: AbortSignal,\n): Promise<string> {\n const declaredLength = Number(response.headers.get('content-length') ?? '0');\n if (Number.isFinite(declaredLength) && declaredLength > maximumBytes) {\n await response.body?.cancel('cloud_response_too_large');\n throw new CloudDeviceFetchError('cloud_response_too_large');\n }\n throwIfAborted(signal);\n if (!response.body || typeof response.body.getReader !== 'function') {\n const text = await awaitWithAbort(response.text(), signal);\n throwIfAborted(signal);\n if (new TextEncoder().encode(text).byteLength > maximumBytes) {\n throw new CloudDeviceFetchError('cloud_response_too_large');\n }\n return text;\n }\n const reader = response.body.getReader();\n const cancelReader = (): void => {\n void reader.cancel('cloud_request_aborted');\n };\n signal.addEventListener('abort', cancelReader, { once: true });\n const decoder = new TextDecoder('utf-8', { fatal: true });\n let totalBytes = 0;\n let text = '';\n try {\n for (;;) {\n throwIfAborted(signal);\n const { done, value } = await reader.read();\n if (done) break;\n totalBytes += value.byteLength;\n if (totalBytes > maximumBytes) {\n await reader.cancel('cloud_response_too_large');\n throw new CloudDeviceFetchError('cloud_response_too_large');\n }\n text += decoder.decode(value, { stream: true });\n }\n throwIfAborted(signal);\n return text + decoder.decode();\n } finally {\n signal.removeEventListener('abort', cancelReader);\n }\n}\n\nasync function awaitWithAbort<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n throwIfAborted(signal);\n let rejectAbort!: (reason: Error) => void;\n const aborted = new Promise<never>((_resolve, reject) => {\n rejectAbort = reject;\n });\n const onAbort = (): void => {\n rejectAbort(abortReason(signal));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n try {\n return await Promise.race([promise, aborted]);\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw abortReason(signal);\n}\n\nfunction abortReason(signal: AbortSignal): Error {\n return signal.reason instanceof Error ? signal.reason : new Error('cloud_request_aborted');\n}\n\nfunction invalidShape(): CloudDeviceFetchError {\n return new CloudDeviceFetchError('cloud_response_invalid_shape');\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction nonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n\nfunction stringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every(item => typeof item === 'string');\n}\n\nfunction isCloudDeviceRecord(value: unknown): value is CloudDeviceRecord {\n if (\n !isRecord(value) || !nonEmptyString(value.accountId) || !nonEmptyString(value.peerId) ||\n !nonEmptyString(value.publicKeyMultibase) || !nonEmptyString(value.deviceName) ||\n (value.platform !== 'desktop' && value.platform !== 'mobile' && value.platform !== 'cli' &&\n value.platform !== 'web') ||\n !isDeviceCapabilities(value.capabilities) ||\n !stringArray(value.multiaddrs) || !stringArray(value.relayReservations) ||\n typeof value.lastSeen !== 'number' || !Number.isFinite(value.lastSeen)\n ) {\n return false;\n }\n return value.revokedAt === undefined ||\n (typeof value.revokedAt === 'number' && Number.isFinite(value.revokedAt));\n}\n\nfunction isDeviceCapabilities(value: unknown): boolean {\n if (\n !isRecord(value) || !stringArray(value.tools) || !stringArray(value.mcpServers) ||\n typeof value.hasWiki !== 'boolean' || !stringArray(value.imChannels) ||\n !Array.isArray(value.wikis) ||\n (value.agentLoop !== undefined && typeof value.agentLoop !== 'boolean')\n ) {\n return false;\n }\n return value.wikis.every(wiki =>\n isRecord(wiki) && nonEmptyString(wiki.wikiId) &&\n (wiki.title === undefined || typeof wiki.title === 'string') &&\n (wiki.pathHint === undefined || typeof wiki.pathHint === 'string')\n );\n}\n\nfunction normalizedConnectionGrantRequest(input: ConnectionGrantRequest): ConnectionGrantRequest {\n return {\n subjectPeerId: input.subjectPeerId,\n allowedPeerIds: [...input.allowedPeerIds],\n protocols: [...input.protocols],\n rpcMethodScope: cloneScope(input.rpcMethodScope),\n conversationScope: cloneScope(input.conversationScope),\n definitionScope: cloneScope(input.definitionScope),\n };\n}\n\nfunction connectionGrantCacheKey(input: ConnectionGrantRequest): string {\n const normalized = normalizedConnectionGrantRequest(input);\n return JSON.stringify([\n normalized.subjectPeerId,\n normalized.allowedPeerIds,\n normalized.protocols,\n normalized.rpcMethodScope,\n normalized.conversationScope,\n normalized.definitionScope,\n ]);\n}\n\nfunction sameStringList(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\nfunction cloneScope<T extends ConnectionGrantRequest['rpcMethodScope']>(scope: T): T {\n return (scope.mode === 'ids' ? { mode: 'ids', ids: [...scope.ids] } : { mode: scope.mode }) as T;\n}\n\nfunction sameScope(\n left: ConnectionGrantRequest['rpcMethodScope'],\n right: ConnectionGrantRequest['rpcMethodScope'],\n): boolean {\n return left.mode === right.mode &&\n (left.mode !== 'ids' || (right.mode === 'ids' && sameStringList(left.ids, right.ids)));\n}\n\nfunction isCanonicalConnectionGrantRequest(input: ConnectionGrantRequest): boolean {\n return hasCanonicalDeviceConnectionGrantClaims({\n ...input,\n issuer: 'memeloop-cloud',\n accountId: 'validation-account',\n issuedAt: 0,\n expiresAt: 1,\n signature: 'validation-signature',\n });\n}\n\nfunction isUsableConnectionGrant(\n value: unknown,\n input: ConnectionGrantRequest,\n usableAfter: number,\n): value is DeviceConnectionGrant {\n if (!isRecord(value)) return false;\n const grant = value as unknown as DeviceConnectionGrant;\n if (!hasCanonicalDeviceConnectionGrantClaims(grant)) return false;\n return grant.issuer === 'memeloop-cloud' && grant.subjectPeerId === input.subjectPeerId &&\n nonEmptyString(grant.accountId) && sameStringList(grant.allowedPeerIds, input.allowedPeerIds) &&\n sameStringList(grant.protocols, input.protocols) &&\n sameScope(grant.rpcMethodScope, input.rpcMethodScope) &&\n sameScope(grant.conversationScope, input.conversationScope) &&\n sameScope(grant.definitionScope, input.definitionScope) &&\n typeof grant.issuedAt === 'number' && Number.isFinite(grant.issuedAt) &&\n typeof grant.expiresAt === 'number' && Number.isFinite(grant.expiresAt) &&\n grant.expiresAt > usableAfter && nonEmptyString(grant.signature);\n}\n\nfunction isUsableRelayReservation(\n value: unknown,\n peerId: string,\n usableAfter: number,\n): value is DeviceRelayReservationToken {\n if (!isRecord(value)) return false;\n const token = value as unknown as DeviceRelayReservationToken;\n return hasCanonicalDeviceRelayReservationTokenClaims(token) && token.peerId === peerId &&\n typeof value.issuedAt === 'number' && Number.isFinite(value.issuedAt) &&\n typeof value.expiresAt === 'number' && Number.isFinite(value.expiresAt) &&\n value.expiresAt > usableAfter && nonEmptyString(value.signature);\n}\n","import type { DeviceCloudCommitFence, SyncResult } from './types.js';\n\nexport type { DeviceCloudCommitFence } from './types.js';\n\nexport type DeviceCloudConnectionStatus =\n | 'not-configured'\n | 'connecting'\n | 'online'\n | 'degraded'\n | 'offline'\n | 'error';\n\nexport type DeviceCloudConnectionComponent =\n | 'authorizer'\n | 'registration'\n | 'relay'\n | 'heartbeat'\n | 'directory';\n\nexport type DeviceCloudComponentStatus = 'pending' | 'ready' | 'failed' | 'not-run';\n\nexport type DeviceCloudErrorClassification = 'offline' | 'error' | 'registration-invalid';\n\n/** A deliberately small, stable error safe to persist, render, and log. */\nexport interface DeviceCloudConnectionError {\n readonly code:\n | 'DEVICE_CLOUD_STEP_FAILED'\n | 'DEVICE_CLOUD_DISPOSE_FAILED'\n | 'DEVICE_CLOUD_OBSERVER_FAILED';\n readonly classification: DeviceCloudErrorClassification;\n readonly component?: DeviceCloudConnectionComponent;\n}\n\nexport interface DeviceCloudConnectionSnapshot {\n readonly status: DeviceCloudConnectionStatus;\n readonly generation: number;\n readonly components: Readonly<Record<DeviceCloudConnectionComponent, DeviceCloudComponentStatus>>;\n readonly lastError?: DeviceCloudConnectionError;\n readonly nextRetryAt?: number;\n}\n\nexport class DeviceCloudStaleGenerationError extends Error {\n public readonly code = 'DEVICE_CLOUD_STALE_GENERATION';\n\n constructor() {\n super('Device Cloud generation is stale');\n this.name = 'DeviceCloudStaleGenerationError';\n }\n}\n\nexport interface DeviceCloudStepResult {\n commit?: (fence: DeviceCloudCommitFence) => Promise<unknown>;\n}\n\nexport interface DeviceCloudConnectionAdapter<Configuration> {\n isConfigured(configuration: Configuration | undefined): configuration is Configuration;\n relayRequiredForOnline(configuration: Configuration): boolean;\n ensureAuthorizer(\n configuration: Configuration,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined>;\n registerDevice(\n configuration: Configuration,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined>;\n ensureRelay(\n configuration: Configuration,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined>;\n heartbeat(\n configuration: Configuration,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined>;\n syncDirectory(\n configuration: Configuration,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined>;\n /**\n * Optional background anti-entropy hooks. The coordinator keeps one run per\n * peer and generation, retries incomplete bounded results, and aborts every\n * old-generation run before activating replacement configuration.\n */\n listBackgroundSyncPeerIds?(\n configuration: Configuration,\n signal: AbortSignal,\n ): readonly string[] | Promise<readonly string[]>;\n syncDevice?(\n configuration: Configuration,\n peerId: string,\n signal: AbortSignal,\n ): Promise<SyncResult>;\n /** Clear every generation-scoped authorizer, relay, token, trust, and address effect. */\n dispose?(configuration: Configuration, signal: AbortSignal): Promise<void>;\n classifyError?(error: unknown): DeviceCloudErrorClassification;\n}\n\nexport interface DeviceCloudConnectionCoordinatorOptions<Configuration> {\n adapter: DeviceCloudConnectionAdapter<Configuration>;\n configuration?: Configuration;\n heartbeatIntervalMs?: number;\n initialBackoffMs?: number;\n maxBackoffMs?: number;\n jitterRatio?: number;\n backgroundSyncInitialBackoffMs?: number;\n backgroundSyncMaxBackoffMs?: number;\n now?: () => number;\n random?: () => number;\n /** Async status persistence must use the fence at its final write point. */\n onStatus?: (\n snapshot: DeviceCloudConnectionSnapshot,\n fence: DeviceCloudCommitFence,\n ) => void | Promise<void>;\n logWarning?: (message: string, error: DeviceCloudConnectionError) => void | Promise<void>;\n}\n\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 60_000;\nconst DEFAULT_INITIAL_BACKOFF_MS = 1_000;\nconst DEFAULT_MAX_BACKOFF_MS = 60_000;\nconst DEFAULT_JITTER_RATIO = 0.2;\nconst DEFAULT_BACKGROUND_SYNC_INITIAL_BACKOFF_MS = 1_000;\nconst DEFAULT_BACKGROUND_SYNC_MAX_BACKOFF_MS = 60_000;\nconst MAX_BACKGROUND_SYNC_PEERS = 1_024;\nconst MAX_BACKGROUND_SYNC_PEER_ID_CHARACTERS = 512;\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n\nfunction emptyComponents(): Readonly<Record<DeviceCloudConnectionComponent, DeviceCloudComponentStatus>> {\n return Object.freeze({\n authorizer: 'not-run',\n registration: 'not-run',\n relay: 'not-run',\n heartbeat: 'not-run',\n directory: 'not-run',\n });\n}\n\nfunction assertPositiveFiniteDelay(value: number, name: string): void {\n if (!Number.isSafeInteger(value) || value <= 0 || value > MAX_TIMER_DELAY_MS) {\n throw new TypeError(`${name} must be a finite integer between 1 and ${MAX_TIMER_DELAY_MS}`);\n }\n}\n\nfunction normalizeBackgroundSyncPeerIds(peerIds: unknown): string[] {\n if (!Array.isArray(peerIds) || peerIds.length > MAX_BACKGROUND_SYNC_PEERS) {\n throw new TypeError('invalid_background_sync_peer_ids');\n }\n const normalized: unknown[] = [...new Set<unknown>(peerIds)];\n if (\n normalized.some(peerId =>\n typeof peerId !== 'string' || peerId.length === 0 ||\n peerId.length > MAX_BACKGROUND_SYNC_PEER_ID_CHARACTERS || peerId !== peerId.trim()\n )\n ) {\n throw new TypeError('invalid_background_sync_peer_ids');\n }\n return normalized.map(peerId => String(peerId)).sort();\n}\n\nasync function abortableDelay(delayMs: number, signal: AbortSignal): Promise<void> {\n signal.throwIfAborted();\n await new Promise<void>((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n signal.removeEventListener('abort', onAbort);\n reject(signal.reason instanceof Error ? signal.reason : new Error('operation_aborted'));\n };\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, delayMs);\n signal.addEventListener('abort', onAbort, { once: true });\n if (signal.aborted) onAbort();\n });\n signal.throwIfAborted();\n}\n\nfunction safeError(\n code: DeviceCloudConnectionError['code'],\n classification: DeviceCloudErrorClassification,\n component?: DeviceCloudConnectionComponent,\n): DeviceCloudConnectionError {\n return Object.freeze(\n component === undefined\n ? { code, classification }\n : { code, classification, component },\n );\n}\n\nfunction freezeSnapshot(snapshot: DeviceCloudConnectionSnapshot): DeviceCloudConnectionSnapshot {\n return Object.freeze({\n ...snapshot,\n components: Object.freeze({ ...snapshot.components }),\n ...(snapshot.lastError === undefined ? {} : { lastError: Object.freeze({ ...snapshot.lastError }) }),\n });\n}\n\n/** Portable, generation-safe Cloud lifecycle shared by every MemeLoop host. */\nexport class DeviceCloudConnectionCoordinator<Configuration> {\n private configuration: Configuration | undefined;\n private desiredConfiguration: Configuration | undefined;\n private generation = 0;\n private requestedGeneration = 0;\n private transition?: Promise<void>;\n private controller = new AbortController();\n private timer?: ReturnType<typeof setTimeout>;\n private inFlight?: Promise<void>;\n private readonly backgroundSyncRuns = new Map<string, {\n generation: number;\n promise: Promise<void>;\n }>();\n private started = false;\n private generationActivated = false;\n private consecutiveFailures = 0;\n private snapshotValue: DeviceCloudConnectionSnapshot = freezeSnapshot({\n status: 'not-configured',\n generation: 0,\n components: emptyComponents(),\n });\n private readonly heartbeatIntervalMs: number;\n private readonly initialBackoffMs: number;\n private readonly maxBackoffMs: number;\n private readonly jitterRatio: number;\n private readonly backgroundSyncInitialBackoffMs: number;\n private readonly backgroundSyncMaxBackoffMs: number;\n private readonly now: () => number;\n private readonly random: () => number;\n\n constructor(private readonly options: DeviceCloudConnectionCoordinatorOptions<Configuration>) {\n this.configuration = options.configuration;\n this.desiredConfiguration = options.configuration;\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;\n this.initialBackoffMs = options.initialBackoffMs ?? DEFAULT_INITIAL_BACKOFF_MS;\n this.maxBackoffMs = options.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;\n this.jitterRatio = options.jitterRatio ?? DEFAULT_JITTER_RATIO;\n this.backgroundSyncInitialBackoffMs = options.backgroundSyncInitialBackoffMs ??\n DEFAULT_BACKGROUND_SYNC_INITIAL_BACKOFF_MS;\n this.backgroundSyncMaxBackoffMs = options.backgroundSyncMaxBackoffMs ??\n DEFAULT_BACKGROUND_SYNC_MAX_BACKOFF_MS;\n this.now = options.now ?? Date.now;\n this.random = options.random ?? Math.random;\n assertPositiveFiniteDelay(this.heartbeatIntervalMs, 'heartbeatIntervalMs');\n assertPositiveFiniteDelay(this.initialBackoffMs, 'initialBackoffMs');\n assertPositiveFiniteDelay(this.maxBackoffMs, 'maxBackoffMs');\n assertPositiveFiniteDelay(\n this.backgroundSyncInitialBackoffMs,\n 'backgroundSyncInitialBackoffMs',\n );\n assertPositiveFiniteDelay(\n this.backgroundSyncMaxBackoffMs,\n 'backgroundSyncMaxBackoffMs',\n );\n if (this.maxBackoffMs < this.initialBackoffMs) {\n throw new TypeError('maxBackoffMs must be greater than or equal to initialBackoffMs');\n }\n if (this.backgroundSyncMaxBackoffMs < this.backgroundSyncInitialBackoffMs) {\n throw new TypeError(\n 'backgroundSyncMaxBackoffMs must be greater than or equal to backgroundSyncInitialBackoffMs',\n );\n }\n if (!Number.isFinite(this.jitterRatio) || this.jitterRatio < 0 || this.jitterRatio > 1) {\n throw new TypeError('jitterRatio must be a finite number between 0 and 1');\n }\n this.resetSnapshot();\n }\n\n public get snapshot(): DeviceCloudConnectionSnapshot {\n return this.snapshotValue;\n }\n\n public async start(): Promise<void> {\n if (this.started) return this.runNow();\n this.started = true;\n const transition = this.transition;\n if (transition) {\n await transition;\n return;\n }\n await this.runCurrent();\n }\n\n public stop(): Promise<void> {\n if (\n !this.started && !this.inFlight && !this.transition && !this.generationActivated &&\n this.backgroundSyncRuns.size === 0\n ) {\n return Promise.resolve();\n }\n this.started = false;\n return this.requestTransition('device cloud coordinator stopped');\n }\n\n public setConfiguration(configuration: Configuration | undefined): Promise<void> {\n this.desiredConfiguration = configuration;\n return this.requestTransition('device cloud configuration changed');\n }\n\n public runNow(): Promise<void> {\n if (this.transition) {\n return this.started ? this.transition : this.transition.then(() => this.runCurrent());\n }\n return this.runCurrent();\n }\n\n private runCurrent(): Promise<void> {\n if (this.inFlight) return this.inFlight;\n if (!this.options.adapter.isConfigured(this.configuration)) {\n this.resetSnapshot();\n return Promise.resolve();\n }\n const generation = this.generation;\n const configuration = this.configuration;\n const signal = this.controller.signal;\n this.generationActivated = true;\n const run = this.maintain(configuration, generation, signal);\n const tracked = run.finally(() => {\n if (this.inFlight === tracked) this.inFlight = undefined;\n });\n this.inFlight = tracked;\n return tracked;\n }\n\n private requestTransition(reason: string): Promise<void> {\n this.requestedGeneration += 1;\n this.clearTimer();\n this.controller.abort(new Error(reason));\n if (!this.transition) {\n const transition = this.drainTransitions().finally(() => {\n if (this.transition === transition) this.transition = undefined;\n });\n this.transition = transition;\n }\n return this.transition;\n }\n\n private async drainTransitions(): Promise<void> {\n while (this.generation !== this.requestedGeneration) {\n const previousConfiguration = this.configuration;\n const previousRun = this.inFlight;\n await previousRun?.catch(() => undefined);\n await this.drainBackgroundSyncGeneration(this.generation);\n\n if (\n this.generationActivated &&\n this.options.adapter.isConfigured(previousConfiguration)\n ) {\n try {\n await this.options.adapter.dispose?.(previousConfiguration, new AbortController().signal);\n } catch {\n this.warn(\n 'Device Cloud generation cleanup failed',\n safeError('DEVICE_CLOUD_DISPOSE_FAILED', 'error'),\n );\n }\n }\n this.generationActivated = false;\n\n // Requests arriving while cleanup was in progress are deliberately\n // coalesced: only the newest desired configuration is ever activated.\n this.configuration = this.desiredConfiguration;\n this.generation = this.requestedGeneration;\n this.consecutiveFailures = 0;\n this.controller = new AbortController();\n if (this.inFlight === previousRun) this.inFlight = undefined;\n this.resetSnapshot();\n\n if (this.started && this.options.adapter.isConfigured(this.configuration)) {\n await this.runCurrent().catch((error: unknown) => {\n if (this.isCurrent(this.generation, this.controller.signal)) throw error;\n });\n }\n }\n }\n\n private async maintain(\n configuration: Configuration,\n generation: number,\n signal: AbortSignal,\n ): Promise<void> {\n if (!this.isCurrent(generation, signal)) return;\n await this.updateSnapshot(generation, {\n status: 'connecting',\n lastError: undefined,\n nextRetryAt: undefined,\n });\n\n let activeComponent: DeviceCloudConnectionComponent = 'authorizer';\n try {\n if (this.snapshotValue.components.authorizer !== 'ready') {\n activeComponent = 'authorizer';\n await this.runStep(activeComponent, generation, signal, fence => this.options.adapter.ensureAuthorizer(configuration, signal, fence));\n }\n if (this.snapshotValue.components.registration !== 'ready') {\n activeComponent = 'registration';\n await this.runStep(activeComponent, generation, signal, fence => this.options.adapter.registerDevice(configuration, signal, fence));\n }\n\n let relayFailure: DeviceCloudConnectionError | undefined;\n try {\n activeComponent = 'relay';\n await this.runStep(activeComponent, generation, signal, fence => this.options.adapter.ensureRelay(configuration, signal, fence));\n } catch (error) {\n const classification = this.classify(error);\n if (classification === 'registration-invalid') throw error;\n relayFailure = safeError('DEVICE_CLOUD_STEP_FAILED', classification, 'relay');\n this.warn('Device Cloud relay maintenance failed', relayFailure);\n }\n\n activeComponent = 'heartbeat';\n await this.runStep(activeComponent, generation, signal, fence => this.options.adapter.heartbeat(configuration, signal, fence));\n\n let directoryFailure: DeviceCloudConnectionError | undefined;\n try {\n activeComponent = 'directory';\n await this.runStep(activeComponent, generation, signal, fence => this.options.adapter.syncDirectory(configuration, signal, fence));\n } catch (error) {\n const classification = this.classify(error);\n if (classification === 'registration-invalid') throw error;\n directoryFailure = safeError('DEVICE_CLOUD_STEP_FAILED', classification, 'directory');\n this.warn('Device Cloud directory synchronization failed', directoryFailure);\n }\n\n if (!directoryFailure) this.startBackgroundSync(configuration, generation, signal);\n\n if (!this.isCurrent(generation, signal)) return;\n this.consecutiveFailures = 0;\n const relayRequired = this.options.adapter.relayRequiredForOnline(configuration);\n const nextRetryAt = this.retryAt(this.heartbeatIntervalMs);\n await this.updateSnapshot(generation, {\n status: directoryFailure || (relayRequired && relayFailure) ? 'degraded' : 'online',\n lastError: directoryFailure ?? relayFailure,\n nextRetryAt,\n });\n this.schedule(this.heartbeatIntervalMs, generation);\n } catch (error) {\n if (!this.isCurrent(generation, signal)) return;\n this.consecutiveFailures += 1;\n const classification = this.classify(error);\n if (classification === 'registration-invalid') {\n await this.setComponent('registration', 'not-run', generation);\n }\n const status = classification === 'error' ? 'error' : 'offline';\n const delay = this.backoffDelay();\n await this.updateSnapshot(generation, {\n status,\n lastError: safeError('DEVICE_CLOUD_STEP_FAILED', classification, activeComponent),\n nextRetryAt: this.retryAt(delay),\n });\n this.schedule(delay, generation);\n throw error;\n }\n }\n\n private async runStep(\n component: DeviceCloudConnectionComponent,\n generation: number,\n signal: AbortSignal,\n operation: (fence: DeviceCloudCommitFence) => Promise<DeviceCloudStepResult | undefined>,\n ): Promise<void> {\n if (!this.isCurrent(generation, signal)) return;\n await this.setComponent(component, 'pending', generation);\n try {\n const fence = this.createCommitFence(generation, signal);\n const result = await operation(fence);\n if (!this.isCurrent(generation, signal)) return;\n await result?.commit?.(fence);\n if (!this.isCurrent(generation, signal)) return;\n await this.setComponent(component, 'ready', generation);\n } catch (error) {\n if (this.isCurrent(generation, signal)) await this.setComponent(component, 'failed', generation);\n throw error;\n }\n }\n\n private createCommitFence(generation: number, signal: AbortSignal): DeviceCloudCommitFence {\n return Object.freeze({\n generation,\n signal,\n isCurrent: () => this.isCurrent(generation, signal),\n throwIfStale: () => {\n if (!this.isCurrent(generation, signal)) throw new DeviceCloudStaleGenerationError();\n },\n commitSynchronous: <Result>(\n operation: () => Result extends PromiseLike<unknown> ? never : Result,\n ) => {\n if (!this.isCurrent(generation, signal)) return false;\n operation();\n return true;\n },\n });\n }\n\n private classify(error: unknown): DeviceCloudErrorClassification {\n try {\n const classification = this.options.adapter.classifyError?.(error) ?? 'offline';\n return classification === 'offline' || classification === 'error' || classification === 'registration-invalid'\n ? classification\n : 'error';\n } catch {\n return 'error';\n }\n }\n\n private backoffDelay(): number {\n const exponential = Math.min(\n this.maxBackoffMs,\n this.initialBackoffMs * 2 ** Math.max(0, this.consecutiveFailures - 1),\n );\n const random = this.random();\n if (!Number.isFinite(random) || random < 0 || random > 1) {\n throw new TypeError('random() must return a finite number between 0 and 1');\n }\n const jitter = exponential * this.jitterRatio * (random * 2 - 1);\n return Math.max(1, Math.min(MAX_TIMER_DELAY_MS, Math.round(exponential + jitter)));\n }\n\n private startBackgroundSync(\n configuration: Configuration,\n generation: number,\n signal: AbortSignal,\n ): void {\n const listBackgroundSyncPeerIds = this.options.adapter.listBackgroundSyncPeerIds?.bind(\n this.options.adapter,\n );\n const syncDevice = this.options.adapter.syncDevice?.bind(this.options.adapter);\n if (!listBackgroundSyncPeerIds || !syncDevice || !this.isCurrent(generation, signal)) return;\n void Promise.resolve()\n .then(async () => {\n const rawPeerIds = await listBackgroundSyncPeerIds(configuration, signal);\n if (!this.isCurrent(generation, signal)) return;\n const peerIds = normalizeBackgroundSyncPeerIds(rawPeerIds);\n for (const peerId of peerIds) {\n if (!this.isCurrent(generation, signal)) return;\n const existing = this.backgroundSyncRuns.get(peerId);\n if (existing?.generation === generation) continue;\n const run = this.runBackgroundSyncDevice(\n configuration,\n peerId,\n generation,\n signal,\n syncDevice,\n );\n const record = { generation, promise: run };\n this.backgroundSyncRuns.set(peerId, record);\n const release = (): void => {\n if (this.backgroundSyncRuns.get(peerId) === record) {\n this.backgroundSyncRuns.delete(peerId);\n }\n };\n void run.then(release, release);\n }\n })\n .catch((error: unknown) => {\n if (!this.isCurrent(generation, signal)) return;\n this.warn(\n 'Device Cloud background sync discovery failed',\n safeError('DEVICE_CLOUD_STEP_FAILED', this.classify(error)),\n );\n });\n }\n\n private async runBackgroundSyncDevice(\n configuration: Configuration,\n peerId: string,\n generation: number,\n signal: AbortSignal,\n syncDevice: NonNullable<DeviceCloudConnectionAdapter<Configuration>['syncDevice']>,\n ): Promise<void> {\n let attempt = 0;\n while (this.isCurrent(generation, signal)) {\n try {\n const result = await syncDevice(configuration, peerId, signal);\n if (!this.isCurrent(generation, signal) || result.complete) return;\n attempt = 0;\n } catch (error) {\n if (!this.isCurrent(generation, signal)) return;\n attempt += 1;\n this.warn(\n 'Device Cloud background sync failed',\n safeError('DEVICE_CLOUD_STEP_FAILED', this.classify(error)),\n );\n }\n const delay = this.backgroundSyncBackoffDelay(attempt);\n try {\n await abortableDelay(delay, signal);\n } catch {\n return;\n }\n }\n }\n\n private backgroundSyncBackoffDelay(attempt: number): number {\n const exponential = Math.min(\n this.backgroundSyncMaxBackoffMs,\n this.backgroundSyncInitialBackoffMs * 2 ** Math.max(0, attempt - 1),\n );\n const random = this.random();\n if (!Number.isFinite(random) || random < 0 || random > 1) {\n return this.backgroundSyncInitialBackoffMs;\n }\n const jitter = exponential * this.jitterRatio * (random * 2 - 1);\n return Math.max(1, Math.min(MAX_TIMER_DELAY_MS, Math.round(exponential + jitter)));\n }\n\n private async drainBackgroundSyncGeneration(generation: number): Promise<void> {\n const runs = [...this.backgroundSyncRuns.values()]\n .filter(run => run.generation === generation)\n .map(run => run.promise.catch(() => undefined));\n await Promise.all(runs);\n }\n\n private readNow(): number {\n const value = this.now();\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new TypeError('now() must return a finite non-negative safe integer timestamp');\n }\n return value;\n }\n\n private retryAt(delayMs: number): number {\n const now = this.readNow();\n if (now > Number.MAX_SAFE_INTEGER - delayMs) {\n throw new TypeError('now() plus delay must remain a safe integer timestamp');\n }\n return now + delayMs;\n }\n\n private schedule(delayMs: number, generation: number): void {\n if (!this.started || !this.isCurrent(generation, this.controller.signal)) return;\n this.clearTimer();\n this.timer = setTimeout(() => {\n if (!this.isCurrent(generation, this.controller.signal)) return;\n void this.runNow().catch(() => {\n this.warn(\n 'Device Cloud scheduled maintenance failed',\n safeError('DEVICE_CLOUD_STEP_FAILED', 'offline'),\n );\n });\n }, delayMs);\n }\n\n private clearTimer(): void {\n if (this.timer) clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n private isCurrent(generation: number, signal: AbortSignal): boolean {\n return generation === this.generation && generation === this.requestedGeneration && !signal.aborted;\n }\n\n private async setComponent(\n component: DeviceCloudConnectionComponent,\n status: DeviceCloudComponentStatus,\n generation: number,\n ): Promise<void> {\n if (generation !== this.generation || generation !== this.requestedGeneration) return;\n this.snapshotValue = freezeSnapshot({\n ...this.snapshotValue,\n components: { ...this.snapshotValue.components, [component]: status },\n });\n this.emit();\n }\n\n private async updateSnapshot(\n generation: number,\n update: Partial<Omit<DeviceCloudConnectionSnapshot, 'generation' | 'components'>>,\n ): Promise<void> {\n if (generation !== this.generation || generation !== this.requestedGeneration) return;\n const next: DeviceCloudConnectionSnapshot = {\n ...this.snapshotValue,\n ...update,\n ...(update.lastError === undefined ? { lastError: undefined } : {}),\n };\n this.snapshotValue = freezeSnapshot(next);\n this.emit();\n }\n\n private resetSnapshot(): void {\n this.snapshotValue = freezeSnapshot({\n status: this.options.adapter.isConfigured(this.configuration)\n ? 'offline'\n : 'not-configured',\n generation: this.generation,\n components: emptyComponents(),\n });\n this.emit();\n }\n\n /** Status observers are telemetry only: never part of a network transition. */\n private emit(): void {\n const snapshot = this.snapshotValue;\n const signal = this.controller.signal;\n void Promise.resolve()\n .then(async () => {\n if (!this.isCurrent(snapshot.generation, signal)) return;\n await this.options.onStatus?.(\n snapshot,\n this.createCommitFence(snapshot.generation, signal),\n );\n })\n .catch(() => {\n this.warn(\n 'Device Cloud status observer failed',\n safeError('DEVICE_CLOUD_OBSERVER_FAILED', 'error'),\n );\n });\n }\n\n private warn(message: string, error: DeviceCloudConnectionError): void {\n const boundedMessage = message.slice(0, 160);\n void Promise.resolve()\n .then(() => this.options.logWarning?.(boundedMessage, error))\n .catch(() => undefined);\n }\n}\n","import { domainSeparatedCanonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type { DeviceCapabilities } from './types.js';\n\n/** Domain separator for device heartbeat proof-of-possession signatures. */\nexport const DEVICE_HEARTBEAT_SIGNATURE_DOMAIN = 'memeloop-device-heartbeat-v2';\n\n/** The default amount of clock skew accepted on either side of a heartbeat timestamp. */\nexport const DEVICE_HEARTBEAT_DEFAULT_MAX_CLOCK_SKEW_MS = 60_000;\n\nexport const DEVICE_HEARTBEAT_LIMITS = Object.freeze({\n peerIdCharacters: 256,\n nonceCharacters: 256,\n signatureCharacters: 4_096,\n publicKeyCharacters: 4_096,\n capabilityItems: 128,\n capabilityItemCharacters: 512,\n wikiItems: 128,\n wikiIdCharacters: 512,\n wikiTitleCharacters: 512,\n wikiPathHintCharacters: 2_048,\n multiaddrs: 64,\n multiaddrCharacters: 2_048,\n relayReservations: 64,\n relayReservationCharacters: 4_096,\n canonicalPayloadBytes: 64 * 1_024,\n});\n\nexport interface DeviceHeartbeatUnsignedMessage {\n peerId: string;\n timestamp: number;\n nonce: string;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n}\n\nexport interface DeviceHeartbeatMessage extends DeviceHeartbeatUnsignedMessage {\n signature: string;\n}\n\nexport type DeviceHeartbeatSigner = (\n payload: Uint8Array,\n) => string | Promise<string>;\n\nexport interface DeviceHeartbeatSignOptions {\n sign: DeviceHeartbeatSigner;\n}\n\n/**\n * A host-provided portable identity verifier. Implementations MUST both derive\n * (or otherwise validate) `peerId` from `publicKeyMultibase` and verify that\n * `signature` authenticates `payload` with that public key.\n */\nexport interface DeviceHeartbeatIdentityVerifierInput {\n peerId: string;\n publicKeyMultibase: string;\n payload: Uint8Array;\n signature: string;\n}\n\nexport type DeviceHeartbeatIdentityVerifier = (\n input: DeviceHeartbeatIdentityVerifierInput,\n) => boolean | Promise<boolean>;\n\nexport interface DeviceHeartbeatNonceConsumptionInput {\n peerId: string;\n publicKeyMultibase: string;\n timestamp: number;\n nonce: string;\n}\n\n/**\n * Atomically consumes a nonce. `true` means this call consumed it; `false`\n * means it was already used or otherwise cannot be accepted.\n */\nexport type DeviceHeartbeatNonceConsumer = (\n input: DeviceHeartbeatNonceConsumptionInput,\n) => boolean | Promise<boolean>;\n\nexport interface VerifyDeviceHeartbeatOptions {\n /** Public key pinned by the registration record, never supplied by the heartbeat. */\n publicKeyMultibase: string;\n now?: number;\n maxClockSkewMs?: number;\n /** Preferred verifier name, matching the pairing identity-verifier contract. */\n verifyIdentity?: DeviceHeartbeatIdentityVerifier;\n /** Concise alias for hosts whose crypto adapter exposes `verify`. */\n verify?: DeviceHeartbeatIdentityVerifier;\n /** Required for acceptance so verification is fail-closed against replay. */\n consumeNonce?: DeviceHeartbeatNonceConsumer;\n}\n\ntype NormalizedHeartbeat = DeviceHeartbeatUnsignedMessage;\n\nconst unsignedKeys = [\n 'peerId',\n 'timestamp',\n 'nonce',\n 'capabilities',\n 'multiaddrs',\n 'relayReservations',\n] as const;\n\nconst capabilityKeys = [\n 'tools',\n 'mcpServers',\n 'hasWiki',\n 'agentLoop',\n 'imChannels',\n 'wikis',\n] as const;\n\nfunction invalid(field: string): never {\n throw new Error(`invalid device heartbeat ${field}`);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const prototype: unknown = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction assertExactKeys(\n value: Record<string, unknown>,\n allowed: readonly string[],\n location: string,\n): void {\n if (Object.keys(value).some(key => !allowed.includes(key))) invalid(location);\n}\n\nfunction boundedText(value: unknown, field: string, maxCharacters: number): string {\n if (\n typeof value !== 'string' ||\n value.length === 0 ||\n value.length > maxCharacters ||\n value !== value.trim()\n ) invalid(field);\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 31 || code === 127) invalid(field);\n }\n return value;\n}\n\nfunction normalizedStringSet(\n value: unknown,\n field: string,\n maxItems: number,\n maxCharacters: number,\n): string[] {\n if (!Array.isArray(value) || value.length > maxItems) invalid(field);\n const items = Array.from(value, item => boundedText(item, field, maxCharacters));\n if (new Set(items).size !== items.length) invalid(field);\n return items.sort(compareText);\n}\n\nfunction compareText(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction normalizeCapabilities(value: unknown): DeviceCapabilities {\n if (!isRecord(value)) invalid('capabilities');\n assertExactKeys(value, capabilityKeys, 'capabilities');\n if (typeof value.hasWiki !== 'boolean') invalid('capabilities.hasWiki');\n if (value.agentLoop !== undefined && typeof value.agentLoop !== 'boolean') {\n invalid('capabilities.agentLoop');\n }\n if (!Array.isArray(value.wikis) || value.wikis.length > DEVICE_HEARTBEAT_LIMITS.wikiItems) {\n invalid('capabilities.wikis');\n }\n\n const wikis = Array.from(value.wikis, (item) => {\n if (!isRecord(item)) invalid('capabilities.wikis');\n assertExactKeys(item, ['wikiId', 'title', 'pathHint'], 'capabilities.wikis');\n const wiki = {\n wikiId: boundedText(\n item.wikiId,\n 'capabilities.wikis.wikiId',\n DEVICE_HEARTBEAT_LIMITS.wikiIdCharacters,\n ),\n ...(item.title === undefined\n ? {}\n : {\n title: boundedText(\n item.title,\n 'capabilities.wikis.title',\n DEVICE_HEARTBEAT_LIMITS.wikiTitleCharacters,\n ),\n }),\n ...(item.pathHint === undefined\n ? {}\n : {\n pathHint: boundedText(\n item.pathHint,\n 'capabilities.wikis.pathHint',\n DEVICE_HEARTBEAT_LIMITS.wikiPathHintCharacters,\n ),\n }),\n };\n return wiki;\n });\n const wikiIds = wikis.map(wiki => wiki.wikiId);\n if (new Set(wikiIds).size !== wikiIds.length) invalid('capabilities.wikis');\n wikis.sort((left, right) =>\n compareText(left.wikiId, right.wikiId) ||\n compareText(left.title ?? '', right.title ?? '') ||\n compareText(left.pathHint ?? '', right.pathHint ?? '')\n );\n\n return {\n tools: normalizedStringSet(\n value.tools,\n 'capabilities.tools',\n DEVICE_HEARTBEAT_LIMITS.capabilityItems,\n DEVICE_HEARTBEAT_LIMITS.capabilityItemCharacters,\n ),\n mcpServers: normalizedStringSet(\n value.mcpServers,\n 'capabilities.mcpServers',\n DEVICE_HEARTBEAT_LIMITS.capabilityItems,\n DEVICE_HEARTBEAT_LIMITS.capabilityItemCharacters,\n ),\n hasWiki: value.hasWiki,\n ...(value.agentLoop === undefined ? {} : { agentLoop: value.agentLoop }),\n imChannels: normalizedStringSet(\n value.imChannels,\n 'capabilities.imChannels',\n DEVICE_HEARTBEAT_LIMITS.capabilityItems,\n DEVICE_HEARTBEAT_LIMITS.capabilityItemCharacters,\n ),\n wikis,\n };\n}\n\nfunction normalizeUnsignedMessage(value: unknown): NormalizedHeartbeat {\n if (!isRecord(value)) invalid('message');\n assertExactKeys(value, unsignedKeys, 'message');\n if (!Number.isSafeInteger(value.timestamp) || (value.timestamp as number) < 0) {\n invalid('timestamp');\n }\n return {\n peerId: boundedText(\n value.peerId,\n 'peerId',\n DEVICE_HEARTBEAT_LIMITS.peerIdCharacters,\n ),\n timestamp: value.timestamp as number,\n nonce: boundedText(\n value.nonce,\n 'nonce',\n DEVICE_HEARTBEAT_LIMITS.nonceCharacters,\n ),\n capabilities: normalizeCapabilities(value.capabilities),\n multiaddrs: normalizedStringSet(\n value.multiaddrs,\n 'multiaddrs',\n DEVICE_HEARTBEAT_LIMITS.multiaddrs,\n DEVICE_HEARTBEAT_LIMITS.multiaddrCharacters,\n ),\n relayReservations: normalizedStringSet(\n value.relayReservations,\n 'relayReservations',\n DEVICE_HEARTBEAT_LIMITS.relayReservations,\n DEVICE_HEARTBEAT_LIMITS.relayReservationCharacters,\n ),\n };\n}\n\nfunction canonicalBytes(message: NormalizedHeartbeat): Uint8Array {\n try {\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_HEARTBEAT_SIGNATURE_DOMAIN,\n message,\n {\n maxDepth: 8,\n maxNodes: 2_048,\n maxStringCodeUnits: DEVICE_HEARTBEAT_LIMITS.relayReservationCharacters,\n maxStringBytes: DEVICE_HEARTBEAT_LIMITS.relayReservationCharacters * 4,\n maxBytes: DEVICE_HEARTBEAT_LIMITS.canonicalPayloadBytes,\n },\n );\n } catch {\n invalid('payload');\n }\n}\n\n/** Build the deterministic, domain-separated bytes authenticated by a heartbeat signature. */\nexport function buildDeviceHeartbeatMessage(\n message: DeviceHeartbeatUnsignedMessage,\n): Uint8Array {\n return canonicalBytes(normalizeUnsignedMessage(message));\n}\n\n/** Validate, canonicalize, and sign a heartbeat without requiring Node APIs. */\nexport async function signDeviceHeartbeatMessage(\n message: DeviceHeartbeatUnsignedMessage,\n options: DeviceHeartbeatSignOptions | DeviceHeartbeatSigner,\n): Promise<DeviceHeartbeatMessage> {\n const normalized = normalizeUnsignedMessage(message);\n const sign = typeof options === 'function' ? options : options.sign;\n if (typeof sign !== 'function') invalid('signer');\n const signature = boundedText(\n await sign(canonicalBytes(normalized)),\n 'signature',\n DEVICE_HEARTBEAT_LIMITS.signatureCharacters,\n );\n return { ...normalized, signature };\n}\n\n/**\n * Verify identity binding, signature, freshness, and atomic nonce consumption.\n * Any malformed input, adapter error, or missing replay store fails closed.\n */\nexport async function verifyDeviceHeartbeatMessage(\n message: DeviceHeartbeatMessage,\n options: VerifyDeviceHeartbeatOptions,\n): Promise<boolean> {\n try {\n if (!isRecord(message)) return false;\n assertExactKeys(message, [...unsignedKeys, 'signature'], 'message');\n const signature = boundedText(\n message.signature,\n 'signature',\n DEVICE_HEARTBEAT_LIMITS.signatureCharacters,\n );\n const unsigned = Object.fromEntries(\n unsignedKeys.map(key => [key, message[key]]),\n ) as unknown as DeviceHeartbeatUnsignedMessage;\n const normalized = normalizeUnsignedMessage(unsigned);\n const publicKeyMultibase = boundedText(\n options.publicKeyMultibase,\n 'publicKeyMultibase',\n DEVICE_HEARTBEAT_LIMITS.publicKeyCharacters,\n );\n const now = options.now ?? Date.now();\n const maxClockSkewMs = options.maxClockSkewMs ??\n DEVICE_HEARTBEAT_DEFAULT_MAX_CLOCK_SKEW_MS;\n if (\n !Number.isSafeInteger(now) ||\n !Number.isSafeInteger(maxClockSkewMs) ||\n maxClockSkewMs < 0 ||\n Math.abs(normalized.timestamp - now) > maxClockSkewMs\n ) return false;\n\n const verifyIdentity = options.verifyIdentity ?? options.verify;\n if (typeof verifyIdentity !== 'function' || typeof options.consumeNonce !== 'function') {\n return false;\n }\n const payload = canonicalBytes(normalized);\n if (\n !await verifyIdentity({\n peerId: normalized.peerId,\n publicKeyMultibase,\n payload,\n signature,\n })\n ) return false;\n\n return await options.consumeNonce({\n peerId: normalized.peerId,\n publicKeyMultibase,\n timestamp: normalized.timestamp,\n nonce: normalized.nonce,\n });\n } catch {\n return false;\n }\n}\n","import { safeErrorMessageFromUnknown } from '../safeError.js';\n\nexport const ORCHESTRATION_ERROR_CODES = [\n 'UNSUPPORTED',\n 'FORBIDDEN',\n 'CONFLICT',\n 'STALE_EPOCH',\n 'NOT_FOUND',\n 'INVALID',\n 'EXHAUSTED',\n 'UNAVAILABLE',\n 'TIMEOUT',\n 'CANCELLED',\n 'UNKNOWN_EFFECT',\n 'WATCH_COMPACTED',\n 'INTERNAL',\n] as const;\n\nexport type OrchestrationErrorCode = typeof ORCHESTRATION_ERROR_CODES[number];\n\nexport interface OrchestrationErrorData {\n code: OrchestrationErrorCode;\n message: string;\n retryable: boolean;\n retryAfterMs?: number;\n reason?: string;\n details?: Record<string, unknown>;\n}\n\nexport class OrchestrationError extends Error {\n readonly code: OrchestrationErrorCode;\n readonly retryable: boolean;\n readonly retryAfterMs?: number;\n readonly reason?: string;\n readonly details?: Record<string, unknown>;\n\n constructor(data: OrchestrationErrorData) {\n super(data.message);\n this.name = 'OrchestrationError';\n this.code = data.code;\n this.retryable = data.retryable;\n this.retryAfterMs = data.retryAfterMs;\n this.reason = data.reason;\n this.details = data.details;\n }\n\n toJSON(): OrchestrationErrorData {\n return {\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n retryAfterMs: this.retryAfterMs,\n reason: this.reason,\n details: this.details,\n };\n }\n}\n\nexport function isOrchestrationError(error: unknown): error is OrchestrationError {\n return error instanceof OrchestrationError;\n}\n\nexport function toOrchestrationErrorData(\n error: unknown,\n fallback: Pick<OrchestrationErrorData, 'code' | 'retryable'> = {\n code: 'INTERNAL',\n retryable: false,\n },\n): OrchestrationErrorData {\n if (isOrchestrationError(error)) return error.toJSON();\n return {\n ...fallback,\n message: safeErrorMessageFromUnknown(error, { fallback: 'Orchestration request failed' }),\n };\n}\n","export type JsonFrameErrorCode =\n | 'FRAME_TOO_LARGE'\n | 'TRUNCATED_FRAME'\n | 'INVALID_UTF8'\n | 'INVALID_JSON'\n | 'IDLE_TIMEOUT'\n | 'TOTAL_TIMEOUT'\n | 'ABORTED';\n\nexport class JsonFrameError extends Error {\n public readonly code: JsonFrameErrorCode;\n\n constructor(code: JsonFrameErrorCode, message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'JsonFrameError';\n this.code = code;\n }\n}\n\nexport interface JsonFrameReaderOptions {\n maxPayloadBytes: number;\n idleTimeoutMs: number;\n totalTimeoutMs: number;\n signal?: AbortSignal;\n abort?: (error: JsonFrameError) => void | Promise<void>;\n}\n\nconst HEADER_BYTES = 4;\nconst MAX_UINT32 = 0xffff_ffff;\n\nfunction assertPositiveInteger(value: number, name: string): void {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new TypeError(`${name} must be a positive safe integer`);\n }\n}\n\nfunction validateMaxPayloadBytes(maxPayloadBytes: number): void {\n assertPositiveInteger(maxPayloadBytes, 'maxPayloadBytes');\n if (maxPayloadBytes > MAX_UINT32) {\n throw new TypeError('maxPayloadBytes must fit in an unsigned 32-bit frame length');\n }\n}\n\nexport function encodeJsonFrame(value: unknown, maxPayloadBytes = MAX_UINT32): Uint8Array {\n validateMaxPayloadBytes(maxPayloadBytes);\n let serialized: string | undefined;\n try {\n serialized = JSON.stringify(value);\n } catch (error) {\n throw new JsonFrameError('INVALID_JSON', 'JSON frame value cannot be serialized', {\n cause: error,\n });\n }\n if (serialized === undefined) {\n throw new JsonFrameError('INVALID_JSON', 'JSON frame value cannot be serialized');\n }\n const payload = new TextEncoder().encode(serialized);\n if (payload.byteLength > maxPayloadBytes) {\n throw new JsonFrameError(\n 'FRAME_TOO_LARGE',\n `JSON frame payload exceeds ${maxPayloadBytes} bytes`,\n );\n }\n const frame = new Uint8Array(HEADER_BYTES + payload.byteLength);\n new DataView(frame.buffer, frame.byteOffset, HEADER_BYTES).setUint32(0, payload.byteLength, false);\n frame.set(payload, HEADER_BYTES);\n return frame;\n}\n\nexport async function* encodeJsonFrames(\n values: AsyncIterable<unknown> | Iterable<unknown>,\n maxPayloadBytes = MAX_UINT32,\n): AsyncIterable<Uint8Array> {\n for await (const value of values) {\n yield encodeJsonFrame(value, maxPayloadBytes);\n }\n}\n\nfunction abortedError(signal?: AbortSignal): JsonFrameError {\n return new JsonFrameError('ABORTED', 'JSON frame reading was aborted', {\n cause: signal?.reason,\n });\n}\n\ninterface JsonFrameDeadline {\n at: number;\n code: 'IDLE_TIMEOUT' | 'TOTAL_TIMEOUT';\n message: string;\n}\n\n/**\n * Select the deadline that governs one iterator pull. The selection remains\n * stable for the lifetime of that pull: a delayed timer must report the first\n * deadline that was crossed, rather than whichever deadlines happen to be\n * expired when its callback runs. Total timeout wins an exact tie so a frame\n * whose idle and total budgets end together is classified deterministically.\n */\nfunction selectReadDeadline(\n idleDeadline: number,\n totalDeadline: number | undefined,\n): JsonFrameDeadline {\n if (totalDeadline !== undefined && totalDeadline <= idleDeadline) {\n return {\n at: totalDeadline,\n code: 'TOTAL_TIMEOUT',\n message: 'JSON frame total timeout expired',\n };\n }\n return {\n at: idleDeadline,\n code: 'IDLE_TIMEOUT',\n message: 'JSON frame idle timeout expired',\n };\n}\n\nasync function readNextChunk(\n iterator: AsyncIterator<Uint8Array>,\n idleDeadline: number,\n totalDeadline: number | undefined,\n signal: AbortSignal | undefined,\n): Promise<IteratorResult<Uint8Array>> {\n if (signal?.aborted) throw abortedError(signal);\n const now = Date.now();\n const deadline = selectReadDeadline(idleDeadline, totalDeadline);\n if (deadline.at <= now) {\n throw new JsonFrameError(deadline.code, deadline.message);\n }\n\n return new Promise<IteratorResult<Uint8Array>>((resolve, reject) => {\n let settled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const finish = (callback: () => void) => {\n if (settled) return;\n settled = true;\n if (timer !== undefined) clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n callback();\n };\n const onAbort = () => {\n finish(() => {\n reject(abortedError(signal));\n });\n };\n\n const onTimeout = () => {\n if (settled) return;\n const remainingMs = deadline.at - Date.now();\n if (remainingMs > 0) {\n // Node and browser timers may fire slightly early (and fractional\n // delays are truncated). Never turn that scheduler detail into a\n // timeout classification bug: wait until the selected absolute\n // deadline has actually elapsed.\n timer = setTimeout(onTimeout, Math.max(1, remainingMs));\n return;\n }\n finish(() => {\n reject(new JsonFrameError(deadline.code, deadline.message));\n });\n };\n\n timer = setTimeout(onTimeout, Math.max(1, deadline.at - now));\n signal?.addEventListener('abort', onAbort, { once: true });\n // Cover an abort racing between the entry check and listener attachment.\n if (signal?.aborted) {\n onAbort();\n return;\n }\n void iterator.next().then(\n (result) => {\n finish(() => {\n resolve(result);\n });\n },\n (error: unknown) => {\n finish(() => {\n reject(\n error instanceof Error ? error : new Error('JSON frame source failed', {\n cause: error,\n }),\n );\n });\n },\n );\n });\n}\n\n/**\n * Decode uint32be-length-prefixed, strict UTF-8 JSON frames from an arbitrary\n * chunked byte stream. Buffered remainder is retained so one chunk may contain\n * any number of complete or partial frames.\n */\nexport function createJsonFrameReader(\n source: AsyncIterable<Uint8Array>,\n options: JsonFrameReaderOptions,\n): AsyncIterable<unknown> {\n validateMaxPayloadBytes(options.maxPayloadBytes);\n assertPositiveInteger(options.idleTimeoutMs, 'idleTimeoutMs');\n assertPositiveInteger(options.totalTimeoutMs, 'totalTimeoutMs');\n\n return (async function* readFrames(): AsyncIterable<unknown> {\n const iterator = source[Symbol.asyncIterator]();\n const header = new Uint8Array(HEADER_BYTES);\n let headerBytes = 0;\n let payload: Uint8Array | undefined;\n let payloadBytes = 0;\n let expectedPayloadBytes: number | undefined;\n let idleDeadline = Date.now() + options.idleTimeoutMs;\n let totalDeadline: number | undefined;\n let abortCalled = false;\n let completed = false;\n\n const abortOnce = (error: JsonFrameError): void => {\n if (abortCalled) return;\n abortCalled = true;\n try {\n // Aborting is a notification/cancellation boundary, not part of error\n // delivery. A defective host abort implementation must never prevent\n // the framing error from reaching the caller.\n void Promise.resolve(options.abort?.(error)).catch(() => undefined);\n } catch {\n // A synchronous host error is intentionally isolated for the same\n // reason as a rejected abort promise.\n }\n };\n\n const decodePayload = (bytes: Uint8Array): unknown => {\n let text: string;\n try {\n text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n } catch (error) {\n throw new JsonFrameError('INVALID_UTF8', 'JSON frame payload is not valid UTF-8', {\n cause: error,\n });\n }\n try {\n return JSON.parse(text) as unknown;\n } catch (error) {\n throw new JsonFrameError('INVALID_JSON', 'JSON frame payload is not valid JSON', {\n cause: error,\n });\n }\n };\n\n const onExternalAbort = (): void => {\n abortOnce(abortedError(options.signal));\n };\n options.signal?.addEventListener('abort', onExternalAbort, { once: true });\n if (options.signal?.aborted) onExternalAbort();\n\n try {\n for (;;) {\n const result = await readNextChunk(\n iterator,\n idleDeadline,\n totalDeadline,\n options.signal,\n );\n if (result.done) {\n if (headerBytes > 0 || expectedPayloadBytes !== undefined) {\n throw new JsonFrameError('TRUNCATED_FRAME', 'JSON frame stream ended mid-frame');\n }\n completed = true;\n return;\n }\n if (!(result.value instanceof Uint8Array)) {\n throw new TypeError('JSON frame source must yield Uint8Array chunks');\n }\n if (result.value.byteLength === 0) continue;\n const now = Date.now();\n idleDeadline = now + options.idleTimeoutMs;\n totalDeadline ??= now + options.totalTimeoutMs;\n\n // Retain at most the current source chunk and copy every frame byte\n // exactly once into the fixed header or exact-size payload allocation.\n // The source is not pulled again until this chunk is fully consumed,\n // so producers may safely reuse their buffer on the next pull while\n // byte-at-a-time input remains O(n).\n let chunkOffset = 0;\n while (chunkOffset < result.value.byteLength) {\n if (expectedPayloadBytes === undefined) {\n const headerRemaining = HEADER_BYTES - headerBytes;\n const copied = Math.min(headerRemaining, result.value.byteLength - chunkOffset);\n header.set(result.value.subarray(chunkOffset, chunkOffset + copied), headerBytes);\n headerBytes += copied;\n chunkOffset += copied;\n if (headerBytes < HEADER_BYTES) continue;\n\n expectedPayloadBytes = new DataView(\n header.buffer,\n header.byteOffset,\n HEADER_BYTES,\n ).getUint32(0, false);\n if (expectedPayloadBytes > options.maxPayloadBytes) {\n throw new JsonFrameError(\n 'FRAME_TOO_LARGE',\n `JSON frame payload exceeds ${options.maxPayloadBytes} bytes`,\n );\n }\n payload = new Uint8Array(expectedPayloadBytes);\n payloadBytes = 0;\n }\n\n const payloadRemaining = expectedPayloadBytes - payloadBytes;\n const copied = Math.min(payloadRemaining, result.value.byteLength - chunkOffset);\n if (copied > 0) {\n payload!.set(result.value.subarray(chunkOffset, chunkOffset + copied), payloadBytes);\n payloadBytes += copied;\n chunkOffset += copied;\n }\n if (payloadBytes < expectedPayloadBytes) continue;\n\n const value = decodePayload(payload!);\n headerBytes = 0;\n payload = undefined;\n payloadBytes = 0;\n expectedPayloadBytes = undefined;\n const hasRemainingChunkBytes = chunkOffset < result.value.byteLength;\n totalDeadline = undefined;\n yield value;\n if (options.signal?.aborted) throw abortedError(options.signal);\n // Consumer backpressure is neither source idleness nor time spent\n // receiving the next frame. Start both clocks only after the\n // consumer resumes and before processing coalesced remainder bytes.\n const resumedAt = Date.now();\n idleDeadline = resumedAt + options.idleTimeoutMs;\n if (hasRemainingChunkBytes) {\n totalDeadline = resumedAt + options.totalTimeoutMs;\n }\n }\n }\n } catch (error) {\n const frameError = error instanceof JsonFrameError\n ? error\n : new JsonFrameError('ABORTED', 'JSON frame source failed', { cause: error });\n abortOnce(frameError);\n throw frameError;\n } finally {\n options.signal?.removeEventListener('abort', onExternalAbort);\n if (!completed) abortOnce(abortedError(options.signal));\n // An async generator can be blocked in an uncooperative await. The\n // underlying stream abort above is the cancellation boundary; waiting\n // for iterator.return() here would let that source deadlock the caller.\n try {\n const returned = iterator.return?.();\n if (returned !== undefined) void Promise.resolve(returned).catch(() => undefined);\n } catch {\n // Iterator cleanup is best effort and must not replace a frame error.\n }\n }\n })();\n}\n","import { OrchestrationError } from '../orchestration/errors.js';\nimport type { RemoteOrchestrationRequest, RemoteOrchestrationResponse, RemoteOrchestrationTransport, RemoteOrchestrationTransportOptions } from '../orchestration/remoteClient.js';\nimport { createJsonFrameReader, encodeJsonFrames, JsonFrameError } from './jsonFrame.js';\nimport type { DeviceConnectionGrant, DeviceNetworkService, MemeLoopDuplexStream } from './types.js';\n\nexport const DEVICE_ORCHESTRATION_PROTOCOL = '/memeloop/orchestration/2.0.0' as const;\nexport const DEVICE_ORCHESTRATION_FRAME_LIMITS = Object.freeze({\n maxPayloadBytes: 1024 * 1024,\n requestIdleTimeoutMs: 10_000,\n requestTotalTimeoutMs: 30_000,\n watchIdleTimeoutMs: 90_000,\n watchBookmarkIntervalMs: 30_000,\n});\nconst DEFAULT_MAX_FRAME_BYTES = DEVICE_ORCHESTRATION_FRAME_LIMITS.maxPayloadBytes;\nconst REQUEST_IDLE_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.requestIdleTimeoutMs;\nconst REQUEST_TOTAL_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.requestTotalTimeoutMs;\nconst WATCH_IDLE_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.watchIdleTimeoutMs;\nconst WATCH_BOOKMARK_INTERVAL_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.watchBookmarkIntervalMs;\n\nexport interface DeviceOrchestrationTransportOptions {\n deviceNetwork: Pick<DeviceNetworkService, 'openStream'>;\n peerId: string;\n grantProvider?: (\n peerId: string,\n signal?: AbortSignal,\n ) => DeviceConnectionGrant | undefined | Promise<DeviceConnectionGrant | undefined>;\n maxFrameBytes?: number;\n}\n\nexport interface DeviceOrchestrationStreamHandlerInput {\n remotePeerId: string;\n stream: MemeLoopDuplexStream;\n authorize?: (presentedGrant: DeviceConnectionGrant | undefined) => boolean | Promise<boolean>;\n}\n\nexport type RemoteOrchestrationHandler = {\n request(\n request: RemoteOrchestrationRequest,\n options?: RemoteOrchestrationTransportOptions,\n ): Promise<RemoteOrchestrationResponse>;\n watch(\n request: RemoteOrchestrationRequest,\n options?: RemoteOrchestrationTransportOptions,\n ): AsyncIterable<RemoteOrchestrationResponse>;\n};\n\nexport interface DeviceOrchestrationStreamHandlerOptions {\n resolveHandler: (\n remotePeerId: string,\n ) => RemoteOrchestrationHandler | Promise<RemoteOrchestrationHandler>;\n maxFrameBytes?: number;\n}\n\nexport type DeviceOrchestrationStreamHandler = (\n input: DeviceOrchestrationStreamHandlerInput,\n) => Promise<void>;\n\ninterface DeviceOrchestrationRequestEnvelope {\n type: 'memeloop-device-orchestration-request-v2';\n request: RemoteOrchestrationRequest;\n deadline?: string;\n grant?: DeviceConnectionGrant;\n}\n\nfunction orchestrationTransportError(\n code: 'CANCELLED' | 'EXHAUSTED' | 'INVALID' | 'UNAVAILABLE',\n message: string,\n): OrchestrationError {\n return new OrchestrationError({\n code,\n message,\n retryable: code === 'UNAVAILABLE',\n });\n}\n\nfunction assertFrameLimit(limit: number): void {\n if (!Number.isSafeInteger(limit) || limit < 256) {\n throw new TypeError('maxFrameBytes must be a safe integer of at least 256');\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw orchestrationTransportError('CANCELLED', 'device orchestration request was cancelled');\n }\n}\n\nasync function openAuthenticatedStream(\n options: DeviceOrchestrationTransportOptions,\n signal?: AbortSignal,\n): Promise<{\n stream: MemeLoopDuplexStream;\n grant: DeviceConnectionGrant | undefined;\n}> {\n const grant = await options.grantProvider?.(options.peerId, signal);\n return {\n stream: await options.deviceNetwork.openStream(\n options.peerId,\n DEVICE_ORCHESTRATION_PROTOCOL,\n {\n presentedGrant: grant,\n signal,\n },\n ),\n grant,\n };\n}\n\nasync function writeRequest(\n stream: MemeLoopDuplexStream,\n request: RemoteOrchestrationRequest,\n grant: DeviceConnectionGrant | undefined,\n deadline: string | undefined,\n maxFrameBytes: number,\n): Promise<void> {\n const envelope: DeviceOrchestrationRequestEnvelope = {\n type: 'memeloop-device-orchestration-request-v2',\n request,\n ...(deadline ? { deadline } : {}),\n ...(grant ? { grant } : {}),\n };\n await stream.sink(encodeJsonFrames([envelope], maxFrameBytes));\n}\n\nfunction abortStreamOnce(stream: MemeLoopDuplexStream): (error: Error) => Promise<void> {\n let aborted = false;\n return async (error) => {\n if (aborted) return;\n aborted = true;\n await stream.abort(error);\n };\n}\n\nfunction frameReader(\n stream: MemeLoopDuplexStream,\n maxFrameBytes: number,\n idleTimeoutMs: number,\n signal: AbortSignal | undefined,\n abort: (error: Error) => Promise<void>,\n): AsyncIterable<unknown> {\n return createJsonFrameReader(stream.source, {\n maxPayloadBytes: maxFrameBytes,\n idleTimeoutMs,\n totalTimeoutMs: REQUEST_TOTAL_TIMEOUT_MS,\n signal,\n abort,\n });\n}\n\nfunction mapFrameError(error: unknown): never {\n if (!(error instanceof JsonFrameError)) throw error;\n if (error.code === 'ABORTED') {\n throw orchestrationTransportError('CANCELLED', error.message);\n }\n if (error.code === 'FRAME_TOO_LARGE') {\n throw orchestrationTransportError('EXHAUSTED', error.message);\n }\n if (error.code === 'IDLE_TIMEOUT' || error.code === 'TOTAL_TIMEOUT') {\n throw orchestrationTransportError('UNAVAILABLE', error.message);\n }\n throw orchestrationTransportError('INVALID', error.message);\n}\n\n/**\n * Carry the portable resource protocol over an already authenticated and\n * encrypted device-network stream. No bearer credential crosses the link:\n * authorization is bound to the paired peer identity opening the protocol.\n */\nexport function createDeviceOrchestrationTransport(\n options: DeviceOrchestrationTransportOptions,\n): RemoteOrchestrationTransport {\n const maxFrameBytes = options.maxFrameBytes ?? DEFAULT_MAX_FRAME_BYTES;\n assertFrameLimit(maxFrameBytes);\n\n return {\n async request(request, transportOptions = {}) {\n throwIfAborted(transportOptions.signal);\n const deadline = transportOptions.deadline;\n const { stream, grant } = await openAuthenticatedStream(options, transportOptions.signal);\n const abort = abortStreamOnce(stream);\n const closeOnAbort = () => {\n void abort(orchestrationTransportError('CANCELLED', 'device orchestration request was cancelled'));\n };\n transportOptions.signal?.addEventListener('abort', closeOnAbort, {\n once: true,\n });\n try {\n await writeRequest(stream, request, grant, deadline, maxFrameBytes);\n let response: RemoteOrchestrationResponse | undefined;\n for await (\n const value of frameReader(\n stream,\n maxFrameBytes,\n REQUEST_IDLE_TIMEOUT_MS,\n transportOptions.signal,\n abort,\n )\n ) {\n if (response) {\n throw orchestrationTransportError(\n 'INVALID',\n 'device orchestration request returned multiple responses',\n );\n }\n response = value as RemoteOrchestrationResponse;\n }\n throwIfAborted(transportOptions.signal);\n if (!response) {\n throw orchestrationTransportError(\n 'UNAVAILABLE',\n 'device orchestration request returned no response',\n );\n }\n return response;\n } catch (error) {\n if (error instanceof JsonFrameError) await abort(error);\n mapFrameError(error);\n } finally {\n transportOptions.signal?.removeEventListener('abort', closeOnAbort);\n await stream.close().catch(() => undefined);\n }\n },\n async *watch(request, transportOptions = {}) {\n throwIfAborted(transportOptions.signal);\n const { stream, grant } = await openAuthenticatedStream(options, transportOptions.signal);\n const abort = abortStreamOnce(stream);\n const closeOnAbort = () => {\n void abort(orchestrationTransportError('CANCELLED', 'device orchestration watch was cancelled'));\n };\n transportOptions.signal?.addEventListener('abort', closeOnAbort, {\n once: true,\n });\n try {\n await writeRequest(\n stream,\n request,\n grant,\n transportOptions.deadline,\n maxFrameBytes,\n );\n for await (\n const value of frameReader(\n stream,\n maxFrameBytes,\n WATCH_IDLE_TIMEOUT_MS,\n transportOptions.signal,\n abort,\n )\n ) {\n throwIfAborted(transportOptions.signal);\n yield value as RemoteOrchestrationResponse;\n }\n throwIfAborted(transportOptions.signal);\n } catch (error) {\n if (error instanceof JsonFrameError) await abort(error);\n mapFrameError(error);\n } finally {\n transportOptions.signal?.removeEventListener('abort', closeOnAbort);\n await stream.close().catch(() => undefined);\n }\n },\n };\n}\n\nasync function readSingleRequest(\n stream: MemeLoopDuplexStream,\n maxFrameBytes: number,\n): Promise<DeviceOrchestrationRequestEnvelope> {\n const abort = abortStreamOnce(stream);\n let envelope: DeviceOrchestrationRequestEnvelope | undefined;\n for await (\n const value of frameReader(\n stream,\n maxFrameBytes,\n REQUEST_IDLE_TIMEOUT_MS,\n undefined,\n abort,\n )\n ) {\n if (envelope) {\n throw orchestrationTransportError(\n 'INVALID',\n 'device orchestration stream accepts exactly one request',\n );\n }\n if (\n value === null ||\n typeof value !== 'object' ||\n Array.isArray(value) ||\n (value as Record<string, unknown>).type !== 'memeloop-device-orchestration-request-v2' ||\n (value as Record<string, unknown>).request === null ||\n typeof (value as Record<string, unknown>).request !== 'object'\n ) {\n throw orchestrationTransportError(\n 'INVALID',\n 'device orchestration request envelope is invalid',\n );\n }\n envelope = value as DeviceOrchestrationRequestEnvelope;\n }\n if (!envelope) {\n throw orchestrationTransportError('INVALID', 'device orchestration request is missing');\n }\n return envelope;\n}\n\nasync function* withWatchBookmarks(\n source: AsyncIterable<RemoteOrchestrationResponse>,\n request: RemoteOrchestrationRequest,\n signal: AbortSignal,\n): AsyncIterable<RemoteOrchestrationResponse> {\n const iterator = source[Symbol.asyncIterator]();\n type WatchActivity =\n | { kind: 'value'; value: IteratorResult<RemoteOrchestrationResponse> }\n | { kind: 'error'; error: unknown }\n | { kind: 'aborted' };\n\n let activity: WatchActivity | undefined;\n let activityWaiter: ((value: WatchActivity | { kind: 'bookmark' }) => void) | undefined;\n let bookmarkTimer: ReturnType<typeof setTimeout> | undefined;\n let readInFlight = false;\n let lastResourceVersion = watchResourceVersion(request.payload.options) ?? '0';\n\n const clearBookmarkTimer = () => {\n if (bookmarkTimer !== undefined) clearTimeout(bookmarkTimer);\n bookmarkTimer = undefined;\n };\n const publishActivity = (value: WatchActivity) => {\n if (activityWaiter) {\n const resolve = activityWaiter;\n activityWaiter = undefined;\n clearBookmarkTimer();\n resolve(value);\n return;\n }\n activity = value;\n };\n const readNext = () => {\n if (readInFlight) return;\n readInFlight = true;\n void iterator.next().then(\n (value) => {\n readInFlight = false;\n publishActivity({ kind: 'value', value });\n },\n (error: unknown) => {\n readInFlight = false;\n publishActivity({ kind: 'error', error });\n },\n );\n };\n const waitForActivity = (): Promise<WatchActivity | { kind: 'bookmark' }> => {\n if (activity) {\n const value = activity;\n activity = undefined;\n return Promise.resolve(value);\n }\n if (signal.aborted) return Promise.resolve({ kind: 'aborted' });\n return new Promise((resolve) => {\n activityWaiter = resolve;\n bookmarkTimer = setTimeout(() => {\n bookmarkTimer = undefined;\n activityWaiter = undefined;\n resolve({ kind: 'bookmark' });\n }, WATCH_BOOKMARK_INTERVAL_MS);\n });\n };\n const onAbort = () => {\n publishActivity({ kind: 'aborted' });\n };\n\n signal.addEventListener('abort', onAbort, { once: true });\n readNext();\n try {\n for (;;) {\n const result = await waitForActivity();\n if (result.kind === 'aborted') return;\n if (result.kind === 'bookmark') {\n yield {\n protocol: request.protocol,\n requestId: request.requestId,\n ok: true,\n result: { type: 'BOOKMARK', resourceVersion: lastResourceVersion },\n };\n continue;\n }\n if (result.kind === 'error') throw result.error;\n if (result.value.done) return;\n const response = result.value.value;\n lastResourceVersion = response.ok\n ? watchResourceVersion(response.result) ?? lastResourceVersion\n : lastResourceVersion;\n yield response;\n readNext();\n }\n } finally {\n clearBookmarkTimer();\n activityWaiter = undefined;\n signal.removeEventListener('abort', onAbort);\n void iterator.return?.();\n }\n}\n\nfunction watchResourceVersion(value: unknown): string | undefined {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return undefined;\n const resourceVersion = (value as Record<string, unknown>).resourceVersion;\n return typeof resourceVersion === 'string' && resourceVersion.length > 0\n ? resourceVersion\n : undefined;\n}\n\n/** Bind a trusted peer identity to a policy-scoped orchestration handler. */\nexport function createDeviceOrchestrationStreamHandler(\n options: DeviceOrchestrationStreamHandlerOptions,\n): DeviceOrchestrationStreamHandler {\n const maxFrameBytes = options.maxFrameBytes ?? DEFAULT_MAX_FRAME_BYTES;\n assertFrameLimit(maxFrameBytes);\n return async ({ remotePeerId, stream, authorize }) => {\n const abort = new AbortController();\n const abortFromStream = (): void => {\n if (!abort.signal.aborted) {\n abort.abort(stream.signal?.reason ?? new Error('device orchestration stream closed'));\n }\n };\n stream.signal?.addEventListener('abort', abortFromStream, { once: true });\n if (stream.signal?.aborted) abortFromStream();\n try {\n const envelope = await readSingleRequest(stream, maxFrameBytes);\n if (authorize && !(await authorize(envelope.grant))) {\n throw orchestrationTransportError('UNAVAILABLE', 'device_not_trusted');\n }\n const request = envelope.request;\n const handler = await options.resolveHandler(remotePeerId);\n if (request.operation === 'watch') {\n await stream.sink(\n encodeJsonFrames(\n withWatchBookmarks(handler.watch(request, { signal: abort.signal }), request, abort.signal),\n maxFrameBytes,\n ),\n );\n } else {\n const response = await handler.request(request, {\n signal: stream.signal,\n deadline: envelope.deadline ?? new Date(Date.now() + REQUEST_TOTAL_TIMEOUT_MS).toISOString(),\n });\n if (stream.signal?.aborted) return;\n await stream.sink(encodeJsonFrames([response], maxFrameBytes));\n }\n } finally {\n stream.signal?.removeEventListener('abort', abortFromStream);\n if (!abort.signal.aborted) abort.abort();\n await stream.close().catch(() => undefined);\n }\n };\n}\n","import type { DeviceConnectionGrant } from './types.js';\n\nexport const LIBP2P_SYNC_REQUEST_TYPE = 'memeloop-sync-request-v2';\nexport const LIBP2P_SYNC_RESPONSE_TYPE = 'memeloop-sync-response-v2';\n\nexport type Libp2pSyncMethod =\n | 'exchangeVersionFrontierPage'\n | 'pullMissingEvents'\n | 'pullAttachmentChunk'\n | 'pushEvents'\n | 'pushAttachmentChunk';\n\nexport interface Libp2pSyncRequest {\n type: typeof LIBP2P_SYNC_REQUEST_TYPE;\n id: string;\n method: Libp2pSyncMethod;\n params: unknown;\n grant?: DeviceConnectionGrant;\n}\n\nexport type Libp2pSyncResponse =\n | {\n type: typeof LIBP2P_SYNC_RESPONSE_TYPE;\n id: string;\n ok: true;\n result: unknown;\n }\n | {\n type: typeof LIBP2P_SYNC_RESPONSE_TYPE;\n id: string;\n ok: false;\n error: { code: string };\n };\n\nexport const MAX_SYNC_ATTACHMENT_CHUNK_BYTES = 3 * 1024 * 1024;\nexport const MAX_SYNC_ATTACHMENT_BYTES = 64 * 1024 * 1024;\n\nexport interface AttachmentChunkWire {\n dataBase64Url: string;\n byteLength: number;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n}\n\nconst syncMethods = new Set<Libp2pSyncMethod>([\n 'exchangeVersionFrontierPage',\n 'pullMissingEvents',\n 'pullAttachmentChunk',\n 'pushEvents',\n 'pushAttachmentChunk',\n]);\n\nexport function isLibp2pSyncRequest(value: unknown): value is Libp2pSyncRequest {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n hasOnlyKeys(record, ['type', 'id', 'method', 'params', 'grant']) &&\n record.type === LIBP2P_SYNC_REQUEST_TYPE &&\n typeof record.id === 'string' &&\n record.id.length > 0 && record.id.length <= 128 &&\n typeof record.method === 'string' &&\n syncMethods.has(record.method as Libp2pSyncMethod) &&\n 'params' in record\n );\n}\n\nexport function isLibp2pSyncResponse(value: unknown): value is Libp2pSyncResponse {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n if (\n record.type !== LIBP2P_SYNC_RESPONSE_TYPE || typeof record.id !== 'string' ||\n record.id.length === 0 || record.id.length > 128 || typeof record.ok !== 'boolean'\n ) return false;\n if (record.ok) return hasOnlyKeys(record, ['type', 'id', 'ok', 'result']);\n if (\n !hasOnlyKeys(record, ['type', 'id', 'ok', 'error']) ||\n record.error === null || typeof record.error !== 'object' || Array.isArray(record.error)\n ) {\n return false;\n }\n const error = record.error as Record<string, unknown>;\n return hasOnlyKeys(error, ['code']) && typeof error.code === 'string' &&\n /^[a-z][a-z\\d_]{0,63}$/u.test(error.code);\n}\n\nfunction isAttachmentChunkWire(value: unknown): value is AttachmentChunkWire {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n hasOnlyKeys(record, [\n 'dataBase64Url',\n 'byteLength',\n 'offset',\n 'totalSize',\n 'done',\n 'filename',\n 'mimeType',\n ]) &&\n typeof record.dataBase64Url === 'string' &&\n typeof record.byteLength === 'number' &&\n typeof record.offset === 'number' &&\n typeof record.totalSize === 'number' &&\n typeof record.done === 'boolean' &&\n typeof record.filename === 'string' &&\n typeof record.mimeType === 'string'\n );\n}\n\nfunction hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {\n const keys = new Set(allowed);\n return Object.keys(value).every(key => keys.has(key));\n}\n\nexport async function attachmentChunkFromWire(value: unknown): Promise<\n {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n } | null\n> {\n if (value === null) return null;\n if (\n !isAttachmentChunkWire(value) ||\n !Number.isSafeInteger(value.byteLength) || value.byteLength < 0 ||\n value.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n !Number.isSafeInteger(value.offset) || value.offset < 0 ||\n !Number.isSafeInteger(value.totalSize) || value.totalSize < 0 ||\n value.totalSize > MAX_SYNC_ATTACHMENT_BYTES ||\n value.offset + value.byteLength > value.totalSize ||\n value.done !== (value.offset + value.byteLength === value.totalSize) ||\n (!value.done && value.byteLength === 0) ||\n value.dataBase64Url.length > Math.ceil(MAX_SYNC_ATTACHMENT_CHUNK_BYTES / 3) * 4 + 4 ||\n value.filename.length > 512 || value.mimeType.length > 256\n ) {\n throw new Error('invalid_sync_attachment_chunk');\n }\n let data: Uint8Array;\n try {\n const base64 = value.dataBase64Url.replace(/-/g, '+').replace(/_/g, '/');\n const paddedBase64 = base64.padEnd(Math.ceil(base64.length / 4) * 4, '=');\n const binary = atob(paddedBase64);\n data = Uint8Array.from(binary, (character) => character.charCodeAt(0));\n } catch {\n throw new Error('invalid_sync_attachment_chunk');\n }\n if (data.byteLength !== value.byteLength) throw new Error('invalid_sync_attachment_chunk');\n return {\n data,\n offset: value.offset,\n totalSize: value.totalSize,\n done: value.done,\n filename: value.filename,\n mimeType: value.mimeType,\n };\n}\n\nexport function attachmentChunkToWire(value: {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n}): AttachmentChunkWire {\n if (\n value.data.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n !Number.isSafeInteger(value.offset) || value.offset < 0 ||\n !Number.isSafeInteger(value.totalSize) || value.totalSize < 0 ||\n value.totalSize > MAX_SYNC_ATTACHMENT_BYTES ||\n value.offset + value.data.byteLength > value.totalSize ||\n value.done !== (value.offset + value.data.byteLength === value.totalSize) ||\n (!value.done && value.data.byteLength === 0)\n ) {\n throw new Error('invalid_sync_attachment_chunk');\n }\n let binary = '';\n for (let offset = 0; offset < value.data.length; offset += 32_768) {\n binary += String.fromCharCode(...value.data.subarray(offset, offset + 32_768));\n }\n return {\n dataBase64Url: btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/g, ''),\n byteLength: value.data.byteLength,\n offset: value.offset,\n totalSize: value.totalSize,\n done: value.done,\n filename: value.filename,\n mimeType: value.mimeType,\n };\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport type { MessageVersionFrontier, MessageVersionFrontierCursor } from '../storage/ports.js';\nimport type { SyncIoOptions } from '../sync/chatSyncEngine.js';\nimport type { ConversationEventSyncPage, VersionRange } from '../sync/protocol.js';\nimport { createJsonFrameReader, encodeJsonFrames } from './jsonFrame.js';\nimport {\n attachmentChunkFromWire,\n attachmentChunkToWire,\n isLibp2pSyncResponse,\n LIBP2P_SYNC_REQUEST_TYPE,\n type Libp2pSyncMethod,\n type Libp2pSyncRequest,\n} from './libp2pSyncProtocol.js';\nimport type { AttachmentChunk, Device, DeviceConnectionGrant, DeviceNetworkService, DeviceSyncTransport, ExchangeVersionFrontierPageResult } from './types.js';\n\nexport interface Libp2pDeviceSyncTransportOptions {\n nodeId: string;\n deviceNetwork: Pick<DeviceNetworkService, 'listDevices' | 'openStream'>;\n grantProvider?: (peerId: string, signal?: AbortSignal) => Promise<DeviceConnectionGrant | undefined>;\n signal?: AbortSignal;\n}\n\nexport class Libp2pDeviceSyncTransport implements DeviceSyncTransport {\n public readonly nodeId: string;\n private readonly deviceNetwork: Pick<DeviceNetworkService, 'listDevices' | 'openStream'>;\n private readonly grantProvider?: (\n peerId: string,\n signal?: AbortSignal,\n ) => Promise<DeviceConnectionGrant | undefined>;\n private readonly signal?: AbortSignal;\n\n constructor(options: Libp2pDeviceSyncTransportOptions) {\n this.nodeId = options.nodeId;\n this.deviceNetwork = options.deviceNetwork;\n this.grantProvider = options.grantProvider;\n this.signal = options.signal;\n }\n\n public listPeers(): Promise<Device[]> {\n return this.deviceNetwork.listDevices();\n }\n\n public exchangeVersionFrontierPage(\n peerId: string,\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<ExchangeVersionFrontierPageResult> {\n return this.request(peerId, 'exchangeVersionFrontierPage', {\n localFrontiers,\n remoteAfter,\n includeRemotePage,\n conversationIds,\n }, options?.signal) as Promise<ExchangeVersionFrontierPageResult>;\n }\n\n public pullMissingEvents(\n peerId: string,\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage> {\n return this.request(peerId, 'pullMissingEvents', { conversationId, ranges, cursor }, options?.signal) as Promise<ConversationEventSyncPage>;\n }\n\n public async pullAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<AttachmentChunk | null> {\n const result = await this.request(\n peerId,\n 'pullAttachmentChunk',\n { conversationId, contentHash, offset, maxBytes },\n options?.signal,\n );\n return attachmentChunkFromWire(result);\n }\n\n public async pushEvents(\n peerId: string,\n events: ConversationEvent[],\n options?: SyncIoOptions,\n ): Promise<void> {\n await this.request(peerId, 'pushEvents', { events }, options?.signal);\n }\n\n public async pushAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void> {\n await this.request(peerId, 'pushAttachmentChunk', {\n conversationId,\n contentHash,\n chunk: attachmentChunkToWire(chunk),\n }, options?.signal);\n }\n\n private async request(\n peerId: string,\n method: Libp2pSyncMethod,\n parameters: unknown,\n operationSignal?: AbortSignal,\n ): Promise<unknown> {\n const signal = operationSignal ?? this.signal;\n const grant = await this.grantProvider?.(peerId, signal);\n const stream = await this.deviceNetwork.openStream(peerId, '/memeloop/sync/2.0.0', {\n presentedGrant: grant,\n signal,\n });\n let aborted = false;\n const abort = async (error: Error): Promise<void> => {\n if (aborted) return;\n aborted = true;\n await stream.abort(error);\n };\n const request: Libp2pSyncRequest = {\n type: LIBP2P_SYNC_REQUEST_TYPE,\n id: crypto.randomUUID(),\n method,\n params: parameters,\n grant,\n };\n try {\n await stream.sink(encodeJsonFrames([request], 16 * 1024 * 1024));\n let response: unknown;\n for await (\n const value of createJsonFrameReader(stream.source, {\n maxPayloadBytes: 16 * 1024 * 1024,\n idleTimeoutMs: 15_000,\n totalTimeoutMs: 120_000,\n signal,\n abort,\n })\n ) {\n if (response !== undefined) throw new Error('sync_response_multiple');\n response = value;\n }\n if (!isLibp2pSyncResponse(response)) throw new Error('invalid_sync_response');\n if (response.id !== request.id) throw new Error('sync_response_id_mismatch');\n if (!response.ok) throw new Error(response.error.code);\n return response.result;\n } catch (error) {\n await abort(error instanceof Error ? error : new Error('sync_transport_failed'));\n if (signal?.aborted) signal.throwIfAborted();\n throw error;\n } finally {\n await stream.close().catch(() => undefined);\n }\n }\n}\n","import { hasCanonicalDeviceConnectionGrantClaims } from './deviceGrantMessages.js';\nimport type { DeviceConnectionGrant } from './types.js';\n\nexport const LIBP2P_RPC_REQUEST_TYPE = 'memeloop-rpc-request-v2';\nexport const LIBP2P_RPC_RESPONSE_TYPE = 'memeloop-rpc-response-v2';\n\nexport interface Libp2pRpcRequest {\n type: typeof LIBP2P_RPC_REQUEST_TYPE;\n id: string;\n method: string;\n params: unknown;\n grant?: DeviceConnectionGrant;\n}\n\nexport type Libp2pRpcResponse =\n | {\n type: typeof LIBP2P_RPC_RESPONSE_TYPE;\n id: string;\n ok: true;\n result: unknown;\n }\n | {\n type: typeof LIBP2P_RPC_RESPONSE_TYPE;\n id: string;\n ok: false;\n error: { code: string };\n };\n\nconst MAX_RPC_ID_LENGTH = 128;\nconst MAX_RPC_METHOD_LENGTH = 256;\nconst RPC_ERROR_CODE_PATTERN = /^[a-z][a-z\\d_]{0,63}$/u;\n\nexport function isLibp2pRpcRequest(value: unknown): value is Libp2pRpcRequest {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n hasOnlyKeys(record, ['type', 'id', 'method', 'params', 'grant']) &&\n record.type === LIBP2P_RPC_REQUEST_TYPE &&\n typeof record.id === 'string' &&\n record.id.length > 0 && record.id.length <= MAX_RPC_ID_LENGTH &&\n typeof record.method === 'string' &&\n record.method.length > 0 && record.method.length <= MAX_RPC_METHOD_LENGTH &&\n 'params' in record &&\n (record.grant === undefined || hasCanonicalDeviceConnectionGrantClaims(record.grant))\n );\n}\n\nexport function isLibp2pRpcResponse(value: unknown): value is Libp2pRpcResponse {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n if (\n record.type !== LIBP2P_RPC_RESPONSE_TYPE || typeof record.id !== 'string' ||\n record.id.length === 0 || record.id.length > MAX_RPC_ID_LENGTH ||\n typeof record.ok !== 'boolean'\n ) return false;\n if (record.ok) return hasOnlyKeys(record, ['type', 'id', 'ok', 'result']);\n if (\n !hasOnlyKeys(record, ['type', 'id', 'ok', 'error']) ||\n record.error === null || typeof record.error !== 'object' || Array.isArray(record.error)\n ) return false;\n const error = record.error as Record<string, unknown>;\n return hasOnlyKeys(error, ['code']) && typeof error.code === 'string' &&\n RPC_ERROR_CODE_PATTERN.test(error.code);\n}\n\nfunction hasOnlyKeys(record: Record<string, unknown>, allowed: readonly string[]): boolean {\n const allowedKeys = new Set(allowed);\n return Object.keys(record).every(key => allowedKeys.has(key));\n}\n","import type { DeviceAuthorizer, MemeLoopProtocol, TrustedDeviceRecord } from './types.js';\n\nexport interface LocalTrustDeviceAuthorizerOptions {\n trustedDevices?: Iterable<TrustedDeviceRecord>;\n getTrustedDevice?: (peerId: string) => TrustedDeviceRecord | undefined;\n allowPairingProtocol?: boolean;\n}\n\nconst PAIRING_PROTOCOL: MemeLoopProtocol = '/memeloop/pairing/2.0.0';\n\nexport class LocalTrustDeviceAuthorizer implements DeviceAuthorizer {\n private readonly trustedDevices = new Map<string, TrustedDeviceRecord>();\n private readonly allowPairingProtocol: boolean;\n\n constructor(private readonly options: LocalTrustDeviceAuthorizerOptions = {}) {\n this.allowPairingProtocol = options.allowPairingProtocol ?? true;\n for (const record of options.trustedDevices ?? []) {\n this.trustedDevices.set(record.peerId, record);\n }\n }\n\n public setTrustedDevice(record: TrustedDeviceRecord): void {\n this.trustedDevices.set(record.peerId, record);\n }\n\n public removeTrustedDevice(peerId: string): void {\n this.trustedDevices.delete(peerId);\n }\n\n public async canOpenProtocol(input: {\n remotePeerId: string;\n protocol: MemeLoopProtocol;\n }): Promise<boolean> {\n const record = this.options.getTrustedDevice?.(input.remotePeerId) ?? this.trustedDevices.get(input.remotePeerId);\n if (record?.revokedAt !== undefined) return false;\n if (input.protocol === PAIRING_PROTOCOL) return this.allowPairingProtocol;\n // Cloud directory entries are discovery metadata, not local trust. Only\n // an explicit local pairing may authorize business protocols here;\n // cloud-account peers must be evaluated by CloudDeviceAuthorizer with a\n // current signed grant.\n return record?.trustMode === 'local-pairing';\n }\n}\n","import type { DeviceAuthorizer, DeviceCloudCommitFence } from './types.js';\n\n/**\n * Stable authorizer identity for long-lived network runtimes.\n *\n * Active-generation replacements are fenced. Reset is intentionally a\n * separate operation for the coordinator's serialized disposal phase, where\n * the old generation is already aborted and no active-generation fence can be\n * current.\n */\nexport class MutableDeviceAuthorizer implements DeviceAuthorizer {\n private delegate: DeviceAuthorizer;\n\n constructor(private readonly fallbackDelegate: DeviceAuthorizer) {\n this.delegate = fallbackDelegate;\n }\n\n /** Atomically install a delegate only while its Cloud generation is current. */\n public setDelegate(delegate: DeviceAuthorizer, fence: DeviceCloudCommitFence): boolean {\n return fence.commitSynchronous(() => {\n this.delegate = delegate;\n });\n }\n\n /** Restore the fail-closed/local-only delegate during serialized disposal. */\n public resetDelegate(signal: AbortSignal): void {\n signal.throwIfAborted();\n this.delegate = this.fallbackDelegate;\n signal.throwIfAborted();\n }\n\n public canOpenProtocol(input: Parameters<DeviceAuthorizer['canOpenProtocol']>[0]): Promise<boolean> {\n // Capture one delegate per authorization call. A generation switch cannot\n // split a single decision across two verification policies.\n const delegate = this.delegate;\n return delegate.canOpenProtocol(input);\n }\n}\n","import { canonicalJsonString, domainSeparatedCanonicalJsonBytes } from '../encoding/canonicalJson.js';\nimport type { Device } from './types.js';\n\nexport const DEVICE_PAIRING_INVITE_PROTOCOL = 'memeloop-device-pairing-v2';\nexport const DEVICE_PAIRING_INVITE_TTL_MS = 5 * 60_000;\nexport const DEVICE_PAIRING_INVITE_MAX_CLOCK_SKEW_MS = 30_000;\nconst MAX_INVITE_LENGTH = 16 * 1024;\nconst MAX_ADDRESSES = 8;\nconst PAIRING_CANONICAL_LIMITS = Object.freeze({\n maxDepth: 4,\n maxNodes: 64,\n maxStringCodeUnits: 4_096,\n maxStringBytes: 16 * 1_024,\n maxBytes: MAX_INVITE_LENGTH,\n});\n\nexport interface DevicePairingInvite {\n protocol: typeof DEVICE_PAIRING_INVITE_PROTOCOL;\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n multiaddrs: string[];\n createdAt: number;\n expiresAt: number;\n signature: string;\n}\n\nexport type DevicePairingInviteUnsignedPayload = Omit<DevicePairingInvite, 'signature'>;\n\nexport interface DevicePairingInviteIdentityVerifierInput {\n invite: DevicePairingInvite;\n payload: Uint8Array;\n}\n\nexport type DevicePairingInviteIdentityVerifier = (\n input: DevicePairingInviteIdentityVerifierInput,\n) => boolean | Promise<boolean>;\n\nexport interface CreateDevicePairingInviteOptions {\n now?: number;\n ttlMs?: number;\n sign(payload: Uint8Array): Promise<string>;\n}\n\nexport interface ParseDevicePairingInviteOptions {\n now?: number;\n /** Must bind publicKeyMultibase -> peerId and verify signature over payload. */\n verifyIdentity: DevicePairingInviteIdentityVerifier;\n}\n\nfunction requireText(value: string, name: string, maxLength: number): string {\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > maxLength) {\n throw new Error(`invalid device pairing invite ${name}`);\n }\n return trimmed;\n}\n\nfunction validatePeerBoundAddress(address: string, peerId: string): boolean {\n if (\n address.length === 0 || address.length > 2_048 || address !== address.trim() ||\n !address.startsWith('/') || address.endsWith('/') || address.includes('//') ||\n containsAsciiControlOrSpace(address)\n ) return false;\n const parts = address.split('/');\n const peerIndexes: number[] = [];\n const circuitIndexes: number[] = [];\n for (let index = 1; index < parts.length; index += 1) {\n if (!parts[index]) return false;\n if (parts[index] === 'p2p-circuit') circuitIndexes.push(index);\n if (parts[index] !== 'p2p') continue;\n const peerId = parts[index + 1];\n if (!peerId) return false;\n peerIndexes.push(index);\n index += 1;\n }\n const destinationIndex = peerIndexes.at(-1);\n if (destinationIndex !== parts.length - 2 || parts[destinationIndex + 1] !== peerId) {\n return false;\n }\n if (circuitIndexes.length === 0) return peerIndexes.length === 1;\n if (circuitIndexes.length !== 1 || peerIndexes.length !== 2) return false;\n return peerIndexes[0] < circuitIndexes[0] && circuitIndexes[0] < destinationIndex;\n}\n\nfunction containsAsciiControlOrSpace(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 32 || code === 127) return true;\n }\n return false;\n}\n\nfunction validateAddresses(addresses: readonly string[], peerId: string): string[] {\n const unique = [...new Set(addresses.map((address) => address.trim()))].filter(Boolean);\n if (\n unique.length === 0 ||\n unique.length > MAX_ADDRESSES ||\n unique.some(address => !validatePeerBoundAddress(address, peerId))\n ) {\n throw new Error('device pairing invite requires structurally valid PeerId-bound multiaddrs');\n }\n return unique;\n}\n\nfunction validateLifetime(createdAt: number, expiresAt: number, now: number): void {\n if (\n !Number.isSafeInteger(now) || now < 0 ||\n !Number.isSafeInteger(createdAt) ||\n !Number.isSafeInteger(expiresAt) ||\n createdAt < 0 ||\n expiresAt <= createdAt ||\n expiresAt - createdAt > DEVICE_PAIRING_INVITE_TTL_MS\n ) {\n throw new Error('invalid device pairing invite lifetime');\n }\n if (createdAt > now + DEVICE_PAIRING_INVITE_MAX_CLOCK_SKEW_MS) {\n throw new Error('device pairing invite is from the future');\n }\n if (expiresAt <= now) throw new Error('device pairing invite has expired');\n}\n\nfunction unsignedPayload(invite: DevicePairingInviteUnsignedPayload): DevicePairingInviteUnsignedPayload {\n const peerId = requireText(invite.peerId, 'peerId', 256);\n return {\n protocol: DEVICE_PAIRING_INVITE_PROTOCOL,\n peerId,\n publicKeyMultibase: requireText(invite.publicKeyMultibase, 'publicKeyMultibase', 4096),\n deviceName: requireText(invite.deviceName, 'deviceName', 256),\n multiaddrs: [...validateAddresses(invite.multiaddrs, peerId)].sort(),\n createdAt: invite.createdAt,\n expiresAt: invite.expiresAt,\n };\n}\n\nexport function canonicalDevicePairingInviteBytes(\n invite: DevicePairingInviteUnsignedPayload,\n): Uint8Array {\n const payload = unsignedPayload(invite);\n return domainSeparatedCanonicalJsonBytes(\n DEVICE_PAIRING_INVITE_PROTOCOL,\n payload,\n PAIRING_CANONICAL_LIMITS,\n );\n}\n\nexport async function createDevicePairingInvite(\n device: Pick<Device, 'peerId' | 'displayName' | 'multiaddrs'> & {\n publicKeyMultibase: string;\n },\n options: CreateDevicePairingInviteOptions,\n): Promise<DevicePairingInvite> {\n const createdAt = options.now ?? Date.now();\n const ttlMs = options.ttlMs ?? DEVICE_PAIRING_INVITE_TTL_MS;\n if (!Number.isSafeInteger(createdAt) || !Number.isSafeInteger(ttlMs) || ttlMs <= 0) {\n throw new Error('invalid device pairing invite lifetime');\n }\n const payload = unsignedPayload({\n protocol: DEVICE_PAIRING_INVITE_PROTOCOL,\n peerId: device.peerId,\n publicKeyMultibase: device.publicKeyMultibase,\n deviceName: device.displayName,\n multiaddrs: device.multiaddrs ?? [],\n createdAt,\n expiresAt: createdAt + ttlMs,\n });\n validateLifetime(payload.createdAt, payload.expiresAt, createdAt);\n const signature = requireText(\n await options.sign(canonicalDevicePairingInviteBytes(payload)),\n 'signature',\n 4096,\n );\n return { ...payload, signature };\n}\n\nexport function encodeDevicePairingInvite(invite: DevicePairingInvite): string {\n const payload = unsignedPayload(invite);\n const signature = requireText(invite.signature, 'signature', 4096);\n return canonicalJsonString({ ...payload, signature }, PAIRING_CANONICAL_LIMITS);\n}\n\nexport async function parseDevicePairingInvite(\n serialized: string,\n options: ParseDevicePairingInviteOptions,\n): Promise<DevicePairingInvite> {\n if (!serialized || serialized.length > MAX_INVITE_LENGTH) {\n throw new Error('invalid device pairing invite length');\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(serialized);\n } catch {\n throw new Error('device pairing invite is not valid JSON');\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('invalid device pairing invite');\n }\n const record = parsed as Record<string, unknown>;\n const expectedKeys = [\n 'protocol',\n 'peerId',\n 'publicKeyMultibase',\n 'deviceName',\n 'multiaddrs',\n 'createdAt',\n 'expiresAt',\n 'signature',\n ];\n if (\n Object.keys(record).length !== expectedKeys.length ||\n expectedKeys.some(key => !Object.hasOwn(record, key)) ||\n record.protocol !== DEVICE_PAIRING_INVITE_PROTOCOL ||\n typeof record.peerId !== 'string' ||\n typeof record.publicKeyMultibase !== 'string' ||\n typeof record.deviceName !== 'string' ||\n !Array.isArray(record.multiaddrs) ||\n record.multiaddrs.some((address) => typeof address !== 'string') ||\n typeof record.createdAt !== 'number' ||\n typeof record.expiresAt !== 'number' ||\n typeof record.signature !== 'string'\n ) {\n throw new Error('invalid device pairing invite');\n }\n validateLifetime(record.createdAt, record.expiresAt, options.now ?? Date.now());\n const payload = unsignedPayload({\n protocol: DEVICE_PAIRING_INVITE_PROTOCOL,\n peerId: record.peerId,\n publicKeyMultibase: record.publicKeyMultibase,\n deviceName: record.deviceName,\n multiaddrs: record.multiaddrs as string[],\n createdAt: record.createdAt,\n expiresAt: record.expiresAt,\n });\n const invite: DevicePairingInvite = {\n ...payload,\n signature: requireText(record.signature, 'signature', 4096),\n };\n if (\n !await options.verifyIdentity({\n invite,\n payload: canonicalDevicePairingInviteBytes(payload),\n })\n ) {\n throw new Error('device pairing invite identity verification failed');\n }\n return invite;\n}\n","import type { CloudDeviceRecord, Device, DeviceTrustStore, TrustedDeviceRecord } from './types.js';\n\nconst DEFAULT_CLOUD_DEVICE_FRESHNESS_MS = 3 * 60_000;\n\ntype Awaitable<T> = T | Promise<T>;\n\n/**\n * Host-owned live address/discovery overlay. Implementations can bridge this\n * to libp2p, a browser transport, or a mobile transport without Core importing\n * any one of those concrete network stacks.\n */\nexport interface DeviceCloudLiveDirectoryCapability {\n listCloudDeviceAddressPeerIds(): Awaitable<readonly string[]>;\n setCloudDeviceAddresses(peerId: string, multiaddrs: readonly string[]): Awaitable<void>;\n removeCloudDeviceAddresses(peerId: string): Awaitable<void>;\n upsertCloudDiscoveredDevice?(device: Device): Awaitable<void>;\n removeCloudDiscoveredDevice?(peerId: string): Awaitable<void>;\n upsertCloudTrustedDevice?(record: TrustedDeviceRecord): Awaitable<void>;\n removeCloudTrustedDevice?(peerId: string): Awaitable<void>;\n}\n\nexport interface CloudDeviceDirectoryReconcileLogger {\n warn(message: string, details?: Record<string, unknown>): void;\n}\n\nexport interface CloudDeviceDirectoryReconcileResult {\n cloudDevices: CloudDeviceRecord[];\n devices: Device[];\n removedPeerIds: string[];\n}\n\n/** Reconcile a fetched Cloud snapshot into durable trust and a live address overlay. */\nexport async function reconcileCloudDeviceDirectory(input: {\n cloudDevices: readonly CloudDeviceRecord[];\n excludePeerIds?: Iterable<string>;\n freshnessMs?: number;\n liveDirectory: DeviceCloudLiveDirectoryCapability;\n logger?: CloudDeviceDirectoryReconcileLogger;\n now?: () => number;\n trustStore: DeviceTrustStore;\n}): Promise<CloudDeviceDirectoryReconcileResult> {\n const now = input.now?.() ?? Date.now();\n const freshnessMs = input.freshnessMs ?? DEFAULT_CLOUD_DEVICE_FRESHNESS_MS;\n if (!Number.isFinite(freshnessMs) || freshnessMs < 0) {\n throw new TypeError('freshnessMs must be finite and non-negative');\n }\n const existingRecords = await input.trustStore.loadTrustedDevices();\n const liveAddressPeerIds = await input.liveDirectory.listCloudDeviceAddressPeerIds();\n const existingByPeerId = new Map(existingRecords.map(record => [record.peerId, record]));\n const excludedPeerIds = new Set(input.excludePeerIds ?? []);\n const recordsByPeerId = new Map<string, CloudDeviceRecord>();\n for (const record of input.cloudDevices) {\n if (recordsByPeerId.has(record.peerId)) throw new Error('cloud_directory_duplicate_peer');\n recordsByPeerId.set(record.peerId, record);\n }\n const activeCloudDevices = [...recordsByPeerId.values()].filter(\n record => record.revokedAt === undefined && !excludedPeerIds.has(record.peerId),\n );\n const activePeerIds = new Set(activeCloudDevices.map(record => record.peerId));\n const removedPeerIds: string[] = [];\n\n const previousCloudPeerIds = new Set([\n ...existingRecords\n .filter(record => record.trustMode === 'cloud-account')\n .map(record => record.peerId),\n ...liveAddressPeerIds,\n ]);\n for (const peerId of previousCloudPeerIds) {\n if (activePeerIds.has(peerId)) continue;\n const existing = existingByPeerId.get(peerId);\n if (existing?.trustMode === 'cloud-account') {\n await input.trustStore.removeTrustedDevice(peerId);\n await input.liveDirectory.removeCloudTrustedDevice?.(peerId);\n }\n await input.liveDirectory.removeCloudDeviceAddresses(peerId);\n await input.liveDirectory.removeCloudDiscoveredDevice?.(peerId);\n removedPeerIds.push(peerId);\n }\n\n const devices: Device[] = [];\n for (const cloudDevice of activeCloudDevices) {\n const existing = existingByPeerId.get(cloudDevice.peerId);\n const trustMode = existing?.trustMode === 'local-pairing'\n ? 'local-pairing' as const\n : 'cloud-account' as const;\n let trustedRecord = existing;\n if (trustMode === 'cloud-account') {\n trustedRecord = {\n peerId: cloudDevice.peerId,\n publicKeyMultibase: cloudDevice.publicKeyMultibase,\n deviceName: cloudDevice.deviceName,\n platform: cloudDevice.platform,\n trustMode,\n accountId: cloudDevice.accountId,\n createdAt: existing?.createdAt ?? now,\n lastSeen: cloudDevice.lastSeen,\n revokedAt: cloudDevice.revokedAt,\n };\n if (\n existing?.trustMode === 'cloud-account' &&\n existing.publicKeyMultibase !== cloudDevice.publicKeyMultibase\n ) {\n input.logger?.warn(\n '[device-network] Cloud directory rotated a cloud-account device public key',\n { peerId: existing.peerId, accountId: existing.accountId },\n );\n }\n if (!existing || !sameTrustedDevice(existing, trustedRecord)) {\n await input.trustStore.saveTrustedDevice(trustedRecord);\n }\n await input.liveDirectory.upsertCloudTrustedDevice?.(trustedRecord);\n }\n\n const device = cloudRecordToDevice(cloudDevice, trustMode, now, freshnessMs);\n await input.liveDirectory.setCloudDeviceAddresses(\n device.peerId,\n device.multiaddrs ?? [],\n );\n await input.liveDirectory.upsertCloudDiscoveredDevice?.(device);\n devices.push(device);\n }\n\n return { cloudDevices: activeCloudDevices, devices, removedPeerIds };\n}\n\nexport function cloudRecordToDevice(\n cloudDevice: CloudDeviceRecord,\n trustMode: Device['trustMode'],\n now = Date.now(),\n freshnessMs = DEFAULT_CLOUD_DEVICE_FRESHNESS_MS,\n): Device {\n const directMultiaddrs = normalizedAddresses(cloudDevice.multiaddrs)\n .filter(address => !address.includes('/p2p-circuit'));\n const relayMultiaddrs = normalizedAddresses([\n ...cloudDevice.multiaddrs.filter(address => address.includes('/p2p-circuit')),\n ...cloudDevice.relayReservations,\n ]);\n const paths: Device['reachability']['paths'] = [\n ...(directMultiaddrs.length > 0 ? ['direct' as const] : []),\n ...(relayMultiaddrs.length > 0 ? ['relay' as const] : []),\n ];\n const fresh = Number.isFinite(cloudDevice.lastSeen) &&\n cloudDevice.lastSeen >= now - freshnessMs;\n return {\n peerId: cloudDevice.peerId,\n displayName: cloudDevice.deviceName,\n platform: cloudDevice.platform,\n trustMode,\n trusted: true,\n reachability: {\n state: fresh && paths.length > 0 ? 'online' : 'offline',\n paths: fresh ? paths : [],\n },\n capabilities: cloudDevice.capabilities,\n multiaddrs: normalizedAddresses([...directMultiaddrs, ...relayMultiaddrs]),\n lastSeen: cloudDevice.lastSeen,\n };\n}\n\nfunction normalizedAddresses(addresses: readonly string[]): string[] {\n return [...new Set(addresses.map(address => address.trim()).filter(Boolean))];\n}\n\nfunction sameTrustedDevice(left: TrustedDeviceRecord, right: TrustedDeviceRecord): boolean {\n return left.peerId === right.peerId &&\n left.publicKeyMultibase === right.publicKeyMultibase &&\n left.deviceName === right.deviceName &&\n left.platform === right.platform &&\n left.trustMode === right.trustMode &&\n left.accountId === right.accountId &&\n left.createdAt === right.createdAt &&\n left.lastSeen === right.lastSeen &&\n left.revokedAt === right.revokedAt;\n}\n","import { CloudDeviceFetchError } from './cloudDeviceFetchClient.js';\nimport type { DeviceCloudCommitFence, DeviceCloudConnectionAdapter, DeviceCloudStepResult } from './deviceCloudConnectionCoordinator.js';\nimport { buildDeviceHeartbeatMessage, DEVICE_HEARTBEAT_LIMITS } from './deviceHeartbeat.js';\nimport { type CloudDeviceDirectoryReconcileLogger, type DeviceCloudLiveDirectoryCapability, reconcileCloudDeviceDirectory } from './reconcileCloudDeviceDirectory.js';\nimport type {\n CloudDeviceClient,\n CloudDeviceRecord,\n DeviceCapabilities,\n DeviceRelayReservationToken,\n DeviceTrustStore,\n LocalDeviceIdentity,\n PublicDeviceIdentity,\n SyncResult,\n} from './types.js';\n\nconst DEFAULT_RELAY_TOKEN_SAFETY_MARGIN_MS = 2 * 60_000;\nconst REGISTRATION_INVALID_ERROR_CODES = new Set([\n 'device_not_found',\n 'device_registration_invalid',\n 'device_registration_not_found',\n 'invalid_device_registration',\n 'registration_invalid',\n]);\n\ntype Awaitable<T> = T | Promise<T>;\n\nclass DeviceCloudRegistrationInvalidError extends Error {\n public readonly code = 'DEVICE_CLOUD_REGISTRATION_INVALID';\n\n constructor(cause?: unknown) {\n super(\n 'cloud device heartbeat rejected',\n cause === undefined ? undefined : { cause },\n );\n this.name = 'DeviceCloudRegistrationInvalidError';\n }\n}\n\nexport interface StandardDeviceCloudNetworkCapability {\n getMultiaddrs(): readonly string[];\n /** Final host write must reject a stale fence at its durable commit point. */\n configureRelayReservation(\n token: DeviceRelayReservationToken,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Awaitable<void>;\n clearRelayReservation(signal: AbortSignal): Awaitable<void>;\n}\n\nexport interface StandardDeviceCloudConnectionAdapterOptions {\n capabilities: () => Awaitable<DeviceCapabilities>;\n /** Final host write must reject a stale fence at its durable commit point. */\n configureConnectionGrantPublicKey: (\n value: { issuer: 'memeloop-cloud'; publicKeyMultibase: string },\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ) => Awaitable<void>;\n /**\n * Atomically publish a fetched Cloud directory snapshot only when the\n * supplied generation is still current. Implementations backed by async\n * persistence must perform an expected-generation CAS in the same durable\n * transaction as the snapshot write; a check followed by an awaited write\n * is not sufficient.\n */\n commitCloudDirectorySnapshot: (\n input: {\n cloudDevices: readonly CloudDeviceRecord[];\n excludePeerIds: readonly string[];\n freshnessMs?: number;\n now: number;\n },\n fence: DeviceCloudCommitFence,\n ) => Awaitable<void>;\n clearConnectionGrantPublicKey: (signal: AbortSignal) => Awaitable<void>;\n clearTokenCache: (client: CloudDeviceClient, signal: AbortSignal) => Awaitable<void>;\n directoryFreshnessMs?: number;\n directoryLogger?: CloudDeviceDirectoryReconcileLogger;\n identity: LocalDeviceIdentity;\n liveDirectory: DeviceCloudLiveDirectoryCapability;\n network: StandardDeviceCloudNetworkCapability;\n now?: () => number;\n relayRequiredForOnline?: (multiaddrs: readonly string[]) => boolean;\n relayTokenSafetyMarginMs?: number;\n signDeviceBinding: (input: {\n accountId: string;\n identity: LocalDeviceIdentity;\n nonce: string;\n signal: AbortSignal;\n }) => Awaitable<string>;\n signHeartbeat: (input: {\n peerId: string;\n timestamp: number;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n signal: AbortSignal;\n }) => Awaitable<{ nonce: string; signature: string }>;\n /** Host wrapper obtains the scoped Cloud grant before entering libp2p sync. */\n syncDevice?: (\n client: CloudDeviceClient,\n peerId: string,\n signal: AbortSignal,\n ) => Promise<SyncResult>;\n trustStore: DeviceTrustStore;\n}\n\n/** Shared host adapter for Cloud registration, relay, heartbeat, and directory maintenance. */\nexport class StandardDeviceCloudConnectionAdapter implements DeviceCloudConnectionAdapter<CloudDeviceClient> {\n private relayReservation?: DeviceRelayReservationToken;\n private relayReservationClient?: CloudDeviceClient;\n private backgroundSyncPeerIds: string[] = [];\n private readonly now: () => number;\n private readonly relayTokenSafetyMarginMs: number;\n\n constructor(private readonly options: StandardDeviceCloudConnectionAdapterOptions) {\n this.now = options.now ?? Date.now;\n this.relayTokenSafetyMarginMs = options.relayTokenSafetyMarginMs ??\n DEFAULT_RELAY_TOKEN_SAFETY_MARGIN_MS;\n if (!Number.isFinite(this.relayTokenSafetyMarginMs) || this.relayTokenSafetyMarginMs < 0) {\n throw new TypeError('relayTokenSafetyMarginMs must be finite and non-negative');\n }\n }\n\n public isConfigured(\n configuration: CloudDeviceClient | undefined,\n ): configuration is CloudDeviceClient {\n return configuration !== undefined;\n }\n\n public relayRequiredForOnline(_configuration: CloudDeviceClient): boolean {\n const addresses = this.options.network.getMultiaddrs();\n return this.options.relayRequiredForOnline?.(addresses) ??\n !hasValidDirectCloudDeviceAddress(addresses, this.options.identity.peerId);\n }\n\n public async ensureAuthorizer(\n client: CloudDeviceClient,\n signal: AbortSignal,\n _fence?: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult> {\n const publicKey = await client.getConnectionGrantPublicKey(signal);\n return {\n commit: async (fence) => {\n fence.throwIfStale();\n await this.options.configureConnectionGrantPublicKey(publicKey, signal, fence);\n fence.throwIfStale();\n },\n };\n }\n\n public async registerDevice(\n client: CloudDeviceClient,\n signal: AbortSignal,\n _fence?: DeviceCloudCommitFence,\n ): Promise<undefined> {\n const nonce = await client.createBindingNonce(signal);\n throwIfAborted(signal);\n const signature = await this.options.signDeviceBinding({\n accountId: nonce.accountId,\n identity: this.options.identity,\n nonce: nonce.nonce,\n signal,\n });\n throwIfAborted(signal);\n const capabilities = await this.options.capabilities();\n throwIfAborted(signal);\n const registration = await client.registerDevice({\n // Construct a fresh public projection at the capability boundary. A\n // custom CloudDeviceClient must never observe host-local key references\n // or serialized private-key material through structural typing.\n identity: toPublicDeviceIdentity(this.options.identity),\n cloudNonce: nonce.nonce,\n signature,\n capabilities,\n multiaddrs: [...this.options.network.getMultiaddrs()],\n relayReservations: this.currentRelayReservations(),\n }, signal);\n if (!registration.ok || registration.peerId !== this.options.identity.peerId) {\n throw new Error('cloud device registration rejected');\n }\n return undefined;\n }\n\n public async ensureRelay(\n client: CloudDeviceClient,\n signal: AbortSignal,\n fence?: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult | undefined> {\n if (\n this.relayReservationClient === client &&\n this.relayReservation &&\n this.relayReservation.expiresAt > this.now() + this.relayTokenSafetyMarginMs\n ) {\n return undefined;\n }\n const relayReservation = await client.createRelayReservation(\n { peerId: this.options.identity.peerId },\n signal,\n fence,\n );\n return {\n commit: async (fence) => {\n fence.throwIfStale();\n await this.options.network.configureRelayReservation(relayReservation, signal, fence);\n fence.throwIfStale();\n fence.commitSynchronous(() => {\n this.relayReservation = relayReservation;\n this.relayReservationClient = client;\n });\n },\n };\n }\n\n public async heartbeat(\n client: CloudDeviceClient,\n signal: AbortSignal,\n _fence?: DeviceCloudCommitFence,\n ): Promise<undefined> {\n throwIfAborted(signal);\n const capabilities = await this.options.capabilities();\n throwIfAborted(signal);\n const unsigned = {\n peerId: this.options.identity.peerId,\n timestamp: this.now(),\n capabilities,\n multiaddrs: [...this.options.network.getMultiaddrs()],\n relayReservations: this.currentRelayReservations(),\n };\n const proof = await this.options.signHeartbeat({ ...unsigned, signal });\n throwIfAborted(signal);\n const heartbeat = { ...unsigned, ...proof };\n void buildDeviceHeartbeatMessage({ ...unsigned, nonce: proof.nonce });\n if (!boundedProofSignature(heartbeat.signature)) {\n throw new Error('invalid device heartbeat signature');\n }\n let result: Awaited<ReturnType<CloudDeviceClient['heartbeat']>>;\n try {\n result = await client.heartbeat(heartbeat, signal);\n } catch (error) {\n if (isHeartbeatRegistrationInvalid(error)) {\n throw new DeviceCloudRegistrationInvalidError(error);\n }\n throw error;\n }\n if (!result.ok) throw new DeviceCloudRegistrationInvalidError();\n return undefined;\n }\n\n public async dispose(client: CloudDeviceClient, signal: AbortSignal): Promise<void> {\n this.relayReservation = undefined;\n this.relayReservationClient = undefined;\n this.backgroundSyncPeerIds = [];\n const errors: unknown[] = [];\n await bestEffortCleanup(\n () => this.options.clearConnectionGrantPublicKey(signal),\n errors,\n );\n await bestEffortCleanup(\n () => this.options.network.clearRelayReservation(signal),\n errors,\n );\n await bestEffortCleanup(\n async () => {\n await reconcileCloudDeviceDirectory({\n cloudDevices: [],\n liveDirectory: this.options.liveDirectory,\n logger: this.options.directoryLogger,\n now: this.now,\n trustStore: this.options.trustStore,\n });\n },\n errors,\n );\n await bestEffortCleanup(\n () => this.options.clearTokenCache(client, signal),\n errors,\n );\n if (errors.length > 0) {\n throw new AggregateError(errors, 'device cloud generation cleanup failed');\n }\n }\n\n public async syncDirectory(\n client: CloudDeviceClient,\n signal: AbortSignal,\n _fence?: DeviceCloudCommitFence,\n ): Promise<DeviceCloudStepResult> {\n const cloudDevices = await client.listDevices(signal);\n return {\n commit: async (fence) => {\n fence.throwIfStale();\n await this.options.commitCloudDirectorySnapshot({\n cloudDevices,\n excludePeerIds: [this.options.identity.peerId],\n freshnessMs: this.options.directoryFreshnessMs,\n now: this.now(),\n }, fence);\n fence.throwIfStale();\n fence.commitSynchronous(() => {\n this.backgroundSyncPeerIds = cloudDevices\n .filter(device => device.peerId !== this.options.identity.peerId && device.revokedAt === undefined)\n .map(device => device.peerId);\n });\n },\n };\n }\n\n public listBackgroundSyncPeerIds(\n _client: CloudDeviceClient,\n signal: AbortSignal,\n ): readonly string[] {\n signal.throwIfAborted();\n return this.options.syncDevice ? [...this.backgroundSyncPeerIds] : [];\n }\n\n public syncDevice(\n client: CloudDeviceClient,\n peerId: string,\n signal: AbortSignal,\n ): Promise<SyncResult> {\n signal.throwIfAborted();\n if (!this.options.syncDevice) throw new Error('background_device_sync_not_configured');\n return this.options.syncDevice(client, peerId, signal);\n }\n\n public classifyError(error: unknown): 'offline' | 'error' | 'registration-invalid' {\n if (error instanceof DeviceCloudRegistrationInvalidError) return 'registration-invalid';\n if (error instanceof CloudDeviceFetchError) {\n return error.code === 'cloud_request_failed' ? 'offline' : 'error';\n }\n return 'offline';\n }\n\n private currentRelayReservations(): string[] {\n const active = this.options.network.getMultiaddrs()\n .filter(address => address.includes('/p2p-circuit'));\n return active.length > 0 ? [...active] : [...(this.relayReservation?.relayMultiaddrs ?? [])];\n }\n}\n\nfunction isHeartbeatRegistrationInvalid(error: unknown): boolean {\n if (!(error instanceof CloudDeviceFetchError) || error.code !== 'cloud_http_error') {\n return false;\n }\n if (error.status === 404) return true;\n return error.status === 401 && hasExplicitRegistrationInvalidCode(error.responseBody);\n}\n\nfunction hasExplicitRegistrationInvalidCode(responseBody: string | undefined): boolean {\n const body = responseBody?.trim();\n if (!body) return false;\n let value: unknown;\n try {\n value = JSON.parse(body) as unknown;\n } catch {\n return REGISTRATION_INVALID_ERROR_CODES.has(normalizeErrorCode(body));\n }\n return registrationInvalidCodeFromValue(value);\n}\n\nfunction registrationInvalidCodeFromValue(value: unknown): boolean {\n if (typeof value === 'string') {\n return REGISTRATION_INVALID_ERROR_CODES.has(normalizeErrorCode(value));\n }\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return registrationInvalidCodeFromValue(record.code) ||\n registrationInvalidCodeFromValue(record.errorCode) ||\n registrationInvalidCodeFromValue(record.error);\n}\n\nfunction normalizeErrorCode(value: string): string {\n return value.trim().toLowerCase().replaceAll('-', '_');\n}\n\nfunction toPublicDeviceIdentity(identity: LocalDeviceIdentity): PublicDeviceIdentity {\n return {\n peerId: identity.peerId,\n publicKeyMultibase: identity.publicKeyMultibase,\n createdAt: identity.createdAt,\n deviceName: identity.deviceName,\n platform: identity.platform,\n };\n}\n\n/**\n * True only when another device can dial a complete direct transport address.\n *\n * Merely finding a public-looking host is insufficient: `/ip4/8.8.8.8`,\n * `tcp/0`, and an unknown transport are not usable paths and must not let a\n * host report `online` without a relay. The optional PeerId pins advertised\n * addresses to the local identity while retaining the standalone classifier\n * used by hosts that append `/p2p/<peerId>` later.\n */\nexport function hasValidDirectCloudDeviceAddress(\n addresses: readonly string[],\n expectedPeerId?: string,\n): boolean {\n return addresses.some(address => isDialableDirectMultiaddr(address, expectedPeerId));\n}\n\nfunction isDialableDirectMultiaddr(address: string, expectedPeerId?: string): boolean {\n if (\n address.length === 0 || address.length > 4_096 || address !== address.trim() ||\n !address.startsWith('/') || address.endsWith('/') || address.includes('//') ||\n address.includes('/p2p-circuit')\n ) return false;\n const parts = address.split('/').slice(1);\n if (parts.some(part => part.length === 0 || containsAsciiControlOrSpace(part))) return false;\n\n const hostProtocol = parts[0];\n const host = parts[1]?.toLowerCase();\n if (\n host === undefined ||\n (hostProtocol !== 'ip4' && hostProtocol !== 'ip6' && hostProtocol !== 'dns' &&\n hostProtocol !== 'dns4' && hostProtocol !== 'dns6')\n ) return false;\n const publicHost = hostProtocol === 'ip4'\n ? isPublicIpv4(host)\n : hostProtocol === 'ip6'\n ? isPublicIpv6(host)\n : isPlausiblePublicDnsHost(host);\n if (!publicHost) return false;\n\n const transport = parts[2];\n const port = parsePort(parts[3]);\n if (transport !== 'tcp' || port === undefined) return false;\n let index = 4;\n if (parts[index] === 'ws' || parts[index] === 'wss') index += 1;\n\n if (parts[index] === 'p2p') {\n const peerId = parts[index + 1];\n if (!peerId || containsAsciiControlOrSpace(peerId)) return false;\n if (expectedPeerId !== undefined && peerId !== expectedPeerId) return false;\n index += 2;\n }\n return index === parts.length;\n}\n\nfunction parsePort(value: string | undefined): number | undefined {\n if (value === undefined || !/^\\d{1,5}$/u.test(value)) return undefined;\n const port = Number(value);\n return port >= 1 && port <= 65_535 ? port : undefined;\n}\n\nfunction containsAsciiControlOrSpace(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 32 || code === 127) return true;\n }\n return false;\n}\n\nfunction isPublicIpv4(host: string): boolean {\n const octets = host.split('.').map(part => Number(part));\n if (octets.length !== 4 || octets.some(octet => !Number.isInteger(octet) || octet < 0 || octet > 255)) {\n return false;\n }\n const [first, second] = octets as [number, number, number, number];\n return first !== 0 && first !== 10 && first !== 127 && first < 224 &&\n !(first === 100 && second >= 64 && second <= 127) &&\n !(first === 169 && second === 254) &&\n !(first === 172 && second >= 16 && second <= 31) &&\n !(first === 192 && second === 0 && octets[2] === 0) &&\n !(first === 192 && second === 0 && octets[2] === 2) &&\n !(first === 192 && second === 88 && octets[2] === 99) &&\n !(first === 192 && second === 168) &&\n !(first === 198 && (second === 18 || second === 19)) &&\n !(first === 198 && second === 51 && octets[2] === 100) &&\n !(first === 203 && second === 0 && octets[2] === 113);\n}\n\nfunction isPublicIpv6(host: string): boolean {\n const groups = parseIpv6(host);\n if (!groups) return false;\n const [first, second] = groups;\n if ((first & 0xe000) !== 0x2000) return false;\n // Documentation-only addresses are valid syntax but never direct public paths.\n return !(first === 0x2001 && second === 0x0db8);\n}\n\nfunction parseIpv6(host: string): number[] | undefined {\n const normalized = host.toLowerCase();\n if (normalized.includes('%') || normalized.includes('.')) return undefined;\n const halves = normalized.split('::');\n if (halves.length > 2) return undefined;\n const parseHalf = (half: string): number[] | undefined => {\n if (half === '') return [];\n const parts = half.split(':');\n if (parts.some(part => !/^[0-9a-f]{1,4}$/u.test(part))) return undefined;\n return parts.map(part => Number.parseInt(part, 16));\n };\n const left = parseHalf(halves[0] ?? '');\n const right = parseHalf(halves[1] ?? '');\n if (!left || !right) return undefined;\n if (halves.length === 1) return left.length === 8 ? left : undefined;\n const missing = 8 - left.length - right.length;\n if (missing < 1) return undefined;\n return [...left, ...Array.from({ length: missing }, () => 0), ...right];\n}\n\nfunction isPlausiblePublicDnsHost(host: string): boolean {\n const normalized = host.endsWith('.') ? host.slice(0, -1) : host;\n if (isIpv4Syntax(normalized)) return isPublicIpv4(normalized);\n if (normalized.includes(':')) return isPublicIpv6(normalized);\n const specialUseSuffixes = [\n 'example',\n 'home.arpa',\n 'internal',\n 'invalid',\n 'local',\n 'localhost',\n 'onion',\n 'test',\n ];\n if (specialUseSuffixes.some(suffix => normalized === suffix || normalized.endsWith(`.${suffix}`))) return false;\n const labels = normalized.split('.');\n return labels.length > 1 && labels.every(label =>\n label.length > 0 && label.length <= 63 &&\n /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u.test(label)\n );\n}\n\nfunction isIpv4Syntax(host: string): boolean {\n return /^\\d{1,3}(?:\\.\\d{1,3}){3}$/u.test(host);\n}\n\nfunction boundedProofSignature(signature: unknown): signature is string {\n if (\n typeof signature !== 'string' || signature.length === 0 ||\n signature.length > DEVICE_HEARTBEAT_LIMITS.signatureCharacters ||\n signature !== signature.trim()\n ) {\n return false;\n }\n for (let index = 0; index < signature.length; index += 1) {\n const code = signature.charCodeAt(index);\n if (code <= 31 || code === 127) return false;\n }\n return true;\n}\n\nasync function bestEffortCleanup(\n operation: () => Awaitable<void>,\n errors: unknown[],\n): Promise<void> {\n try {\n await operation();\n } catch (error) {\n errors.push(error);\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal): void {\n if (!signal.aborted) return;\n throw signal.reason instanceof Error ? signal.reason : new Error('device_cloud_operation_aborted');\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport type { MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from '../storage/ports.js';\nimport type { SyncIoOptions } from '../sync/chatSyncEngine.js';\nimport type { ConversationEventSyncPage, VersionRange } from '../sync/protocol.js';\n\nexport type DevicePlatform = 'desktop' | 'mobile' | 'cli' | 'web';\nexport type DeviceTrustMode = 'local-pairing' | 'cloud-account';\nexport type DeviceReachabilityState = 'nearby' | 'online' | 'offline' | 'connecting';\nexport type DeviceNetworkPath = 'lan' | 'direct' | 'relay';\nexport type DeviceProtocolDirection = 'inbound' | 'outbound';\nexport type PairingSessionDirection = 'inbound' | 'outbound';\nexport type PairingSessionStatus = 'pending' | 'accepted' | 'rejected' | 'expired';\n\n/** Generation-scoped authority for a final synchronous host or persistence write. */\nexport interface DeviceCloudCommitFence {\n readonly generation: number;\n readonly signal: AbortSignal;\n isCurrent(): boolean;\n throwIfStale(): void;\n commitSynchronous<Result>(\n operation: () => Result extends PromiseLike<unknown> ? never : Result,\n ): boolean;\n}\n\nexport type MemeLoopProtocol =\n | '/memeloop/rpc/2.0.0'\n | '/memeloop/sync/2.0.0'\n | '/memeloop/pairing/2.0.0'\n | '/memeloop/orchestration/2.0.0'\n | '/memeloop/relay-admission/2.0.0';\n\nexport interface DeviceCapabilities {\n tools: string[];\n mcpServers: string[];\n hasWiki: boolean;\n agentLoop?: boolean;\n imChannels: string[];\n wikis: Array<{\n wikiId: string;\n title?: string;\n pathHint?: string;\n }>;\n}\n\n/** Device identity fields safe to disclose to Cloud and remote peers. */\nexport interface PublicDeviceIdentity {\n peerId: string;\n publicKeyMultibase: string;\n createdAt: number;\n deviceName: string;\n platform: DevicePlatform;\n}\n\n/** Host-local identity. Private-key material must never cross an adapter boundary. */\nexport interface LocalDeviceIdentity extends PublicDeviceIdentity {\n privateKeyRef: string;\n privateKeyPkcs8Base64Url?: string;\n privateKeyRawSeedBase64Url?: string;\n}\n\nexport interface DeviceNetworkListenOptions {\n addresses: string[];\n announce?: string[];\n}\n\nexport interface DeviceReachability {\n state: DeviceReachabilityState;\n paths: DeviceNetworkPath[];\n}\n\nexport interface Device {\n peerId: string;\n displayName: string;\n platform: DevicePlatform;\n trustMode: DeviceTrustMode;\n trusted?: boolean;\n reachability: DeviceReachability;\n capabilities: DeviceCapabilities;\n multiaddrs?: string[];\n lastSeen?: number;\n}\n\nexport interface TrustedDeviceRecord {\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n platform: DevicePlatform;\n trustMode: DeviceTrustMode;\n accountId?: string;\n createdAt: number;\n lastSeen?: number;\n revokedAt?: number;\n}\n\nexport interface DeviceTrustStore {\n loadTrustedDevices(): Promise<TrustedDeviceRecord[]>;\n saveTrustedDevice(record: TrustedDeviceRecord): Promise<void>;\n removeTrustedDevice(peerId: string): Promise<void>;\n}\n\nexport interface DeviceAccountBindingRequest {\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n platform: DevicePlatform;\n cloudNonce: string;\n signature: string;\n}\n\nexport interface CloudDeviceRecord {\n accountId: string;\n peerId: string;\n publicKeyMultibase: string;\n deviceName: string;\n platform: DevicePlatform;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n lastSeen: number;\n revokedAt?: number;\n}\n\nexport interface DeviceConnectionGrant {\n issuer: 'memeloop-cloud';\n accountId: string;\n subjectPeerId: string;\n allowedPeerIds: string[];\n protocols: MemeLoopProtocol[];\n rpcMethodScope: DeviceConnectionGrantStringScope;\n conversationScope: DeviceConnectionGrantStringScope;\n definitionScope: DeviceConnectionGrantStringScope;\n issuedAt: number;\n expiresAt: number;\n signature: string;\n}\n\nexport type DeviceConnectionGrantStringScope =\n | { mode: 'none' }\n | { mode: 'all' }\n | { mode: 'ids'; ids: string[] };\n\nexport interface DeviceConnectionGrantVerificationInput {\n grant: DeviceConnectionGrant;\n verificationPublicKeyMultibase: string;\n subjectPeerId?: string;\n allowedPeerId?: string;\n now?: number;\n}\n\nexport interface DeviceRelayReservationToken {\n issuer: 'memeloop-cloud';\n accountId: string;\n peerId: string;\n relayMultiaddrs: string[];\n bootstrapMultiaddrs: string[];\n issuedAt: number;\n expiresAt: number;\n signature: string;\n}\n\nexport interface DeviceRelayReservationTokenVerificationInput {\n token: DeviceRelayReservationToken;\n verificationPublicKeyMultibase: string;\n peerId?: string;\n now?: number;\n}\n\nexport interface PairingSession {\n sessionId: string;\n localPeerId: string;\n remotePeerId: string;\n remotePublicKeyMultibase: string;\n remoteDeviceName: string;\n remotePlatform: DevicePlatform;\n remoteCapabilities: DeviceCapabilities;\n remoteMultiaddrs: string[];\n direction: PairingSessionDirection;\n status: PairingSessionStatus;\n confirmCode: string;\n createdAt: number;\n expiresAt: number;\n}\n\nexport interface LocalPairingRequestOptions {\n multiaddrs?: string[];\n /** Cancels dialing and the in-flight pairing frame exchange. */\n signal?: AbortSignal;\n}\n\nexport interface SyncProgress {\n passes: number;\n peers: number;\n /** Bounded frontier metadata pages inspected while discovering transfer work. */\n frontierPages: number;\n /** Event/attachment transfer pages. */\n pages: number;\n events: number;\n bytes: number;\n elapsedMs: number;\n}\n\nexport interface SyncContinuation {\n reason: 'pass-limit' | 'time-limit';\n /**\n * Continuations never carry an authoritative cursor. A later call resumes\n * from the durable event frontier, so cancellation or process restart cannot\n * skip acknowledged work.\n */\n resumeFrom: 'durable-frontier';\n}\n\nexport interface SyncResult {\n /** The bounded operation itself succeeded, including an incomplete resumable result. */\n ok: true;\n peerId: string;\n syncedAt: number;\n complete: boolean;\n progress: SyncProgress;\n continuation?: SyncContinuation;\n}\n\nexport type DeviceNetworkUnavailableCode =\n | 'device_network_pairing_unavailable'\n | 'device_network_stream_unavailable'\n | 'device_network_sync_unavailable';\n\n/** Stable, non-secret error for an adapter that cannot perform a network operation. */\nexport class DeviceNetworkUnavailableError extends Error {\n public readonly code: DeviceNetworkUnavailableCode;\n\n constructor(code: DeviceNetworkUnavailableCode) {\n super(code);\n this.name = 'DeviceNetworkUnavailableError';\n this.code = code;\n }\n}\n\nexport interface MemeLoopDuplexStream {\n source: AsyncIterable<Uint8Array>;\n sink(source: AsyncIterable<Uint8Array>): Promise<void>;\n close(): Promise<void>;\n abort(error: Error): void | Promise<void>;\n /** Aborts when the underlying remote stream disconnects or is reset. */\n signal?: AbortSignal;\n}\n\nexport interface DeviceRpcHandlerInput {\n remotePeerId: string;\n method: string;\n parameters: unknown;\n presentedGrant?: DeviceConnectionGrant;\n /** Aborts when the authenticated transport request is cancelled or disconnected. */\n signal?: AbortSignal;\n}\n\nexport type DeviceRpcHandler = (input: DeviceRpcHandlerInput) => Promise<unknown>;\n\nexport interface DeviceStreamOptions {\n presentedGrant?: DeviceConnectionGrant;\n signal?: AbortSignal;\n}\n\nexport type AgentExecutionLocation = { kind: 'local' } | { kind: 'device'; peerId: string };\n\nexport type AgentExecutionState = 'idle' | 'running' | 'stopping';\n\nexport interface ConversationExecutionPlacement {\n conversationId: string;\n location: AgentExecutionLocation;\n state: AgentExecutionState;\n updatedAt: number;\n}\n\nexport interface DeviceAuthorizer {\n canOpenProtocol(input: {\n remotePeerId: string;\n protocol: MemeLoopProtocol;\n direction?: DeviceProtocolDirection;\n presentedGrant?: DeviceConnectionGrant;\n }): Promise<boolean>;\n}\n\nexport interface CloudDeviceClient {\n listDevices(signal?: AbortSignal): Promise<CloudDeviceRecord[]>;\n getConnectionGrantPublicKey(signal?: AbortSignal): Promise<{\n issuer: 'memeloop-cloud';\n publicKeyMultibase: string;\n }>;\n createConnectionGrant(\n input: {\n subjectPeerId: string;\n allowedPeerIds: string[];\n protocols: MemeLoopProtocol[];\n rpcMethodScope: DeviceConnectionGrantStringScope;\n conversationScope: DeviceConnectionGrantStringScope;\n definitionScope: DeviceConnectionGrantStringScope;\n },\n signal?: AbortSignal,\n fence?: DeviceCloudCommitFence,\n ): Promise<DeviceConnectionGrant>;\n createRelayReservation(\n input: { peerId: string },\n signal?: AbortSignal,\n fence?: DeviceCloudCommitFence,\n ): Promise<DeviceRelayReservationToken>;\n createBindingNonce(signal?: AbortSignal): Promise<{\n nonce: string;\n accountId: string;\n expiresAt: string;\n }>;\n registerDevice(\n input: Pick<DeviceAccountBindingRequest, 'cloudNonce' | 'signature'> & {\n identity: PublicDeviceIdentity;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n },\n signal?: AbortSignal,\n ): Promise<{ ok: boolean; peerId: string }>;\n heartbeat(input: {\n peerId: string;\n timestamp: number;\n nonce: string;\n capabilities: DeviceCapabilities;\n multiaddrs: string[];\n relayReservations: string[];\n signature: string;\n }, signal?: AbortSignal): Promise<{ ok: boolean }>;\n}\n\nexport interface DeviceNetworkService {\n start(): Promise<void>;\n stop(): Promise<void>;\n getLocalDevice(): Promise<Device>;\n listDevices(): Promise<Device[]>;\n observeDevices(listener: (devices: Device[]) => void): () => void;\n listPairingSessions(): Promise<PairingSession[]>;\n observePairingSessions(listener: (sessions: PairingSession[]) => void): () => void;\n requestLocalPairing(\n peerId: string,\n options?: LocalPairingRequestOptions,\n ): Promise<PairingSession>;\n acceptPairing(sessionId: string): Promise<void>;\n rejectPairing(sessionId: string): Promise<void>;\n removeTrustedDevice(peerId: string): Promise<void>;\n openStream(\n peerId: string,\n protocol: MemeLoopProtocol,\n options?: DeviceStreamOptions,\n ): Promise<MemeLoopDuplexStream>;\n sendRpc<T>(\n peerId: string,\n method: string,\n parameters: unknown,\n options?: DeviceStreamOptions,\n ): Promise<T>;\n syncWithDevice(peerId: string, options?: DeviceSyncOptions): Promise<SyncResult>;\n\n /** Configure Cloud connection. When set, syncCloudDevices() and CloudDeviceAuthorizer become available. */\n configureCloud?(config: { cloudUrl: string; accessToken: string }): void;\n /** Apply a Cloud-signed private relay admission token and connect to advertised relay/bootstrap peers. */\n configureRelayReservation?(\n token: DeviceRelayReservationToken,\n signal: AbortSignal,\n fence: DeviceCloudCommitFence,\n ): Promise<void>;\n /** Fetch devices from Cloud directory and persist into local trust store. Returns synced devices. */\n syncCloudDevices?(): Promise<CloudDeviceRecord[]>;\n}\n\nexport interface DeviceSyncOptions {\n presentedGrant?: DeviceConnectionGrant;\n /** Restrict synchronization to active conversations; undefined syncs all. */\n conversationIds?: string[];\n signal?: AbortSignal;\n}\n\nexport interface ExchangeVersionFrontierPageResult {\n remotePage: MessageVersionFrontierPage;\n missingForRemote: VersionRange[];\n}\n\nexport interface AttachmentChunk {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n}\n\nexport interface DeviceSyncTransport {\n listPeers(): Promise<Device[]>;\n exchangeVersionFrontierPage(\n peerId: string,\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<ExchangeVersionFrontierPageResult>;\n pullMissingEvents(\n peerId: string,\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage>;\n pullAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<AttachmentChunk | null>;\n pushEvents(peerId: string, events: ConversationEvent[], options?: SyncIoOptions): Promise<void>;\n pushAttachmentChunk(\n peerId: string,\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void>;\n}\n","/**\n * 将节点 RPC `memeloop.storage.getAttachmentBlob` 的返回值解码为同步引擎可用的 BLOB。\n */\n\nexport function decodeAttachmentBlobRpc(\n result: unknown,\n): { data: Uint8Array; filename: string; mimeType: string; size: number } | null {\n if (result == null || typeof result !== 'object') return null;\n const r = result as {\n found?: boolean;\n error?: string;\n dataBase64?: string;\n filename?: string;\n mimeType?: string;\n size?: number;\n };\n if (r.error || !r.found || typeof r.dataBase64 !== 'string') return null;\n let data: Uint8Array;\n try {\n const binary = atob(r.dataBase64);\n if (!binary.length) return null;\n data = Uint8Array.from(binary, (character) => character.charCodeAt(0));\n } catch {\n return null;\n }\n return {\n data,\n filename: typeof r.filename === 'string' ? r.filename : 'attachment',\n mimeType: typeof r.mimeType === 'string' ? r.mimeType : 'application/octet-stream',\n size: typeof r.size === 'number' && r.size > 0 ? r.size : data.byteLength,\n };\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\n\n/** Highest contiguous originSequence for each conversation+origin pair. */\nexport type VersionVector = Record<string, number>;\n\n/**\n * Version-vector entries are scoped to one conversation and one message\n * origin. Lamport clocks are allocated per conversation, so a node-wide key\n * would incorrectly hide a new short conversation after a long one was\n * acknowledged.\n */\nexport function versionVectorKey(conversationId: string, originNodeId: string): string {\n return JSON.stringify([conversationId, originNodeId]);\n}\n\nexport function parseVersionVectorKey(\n key: string,\n): { conversationId: string; originNodeId: string } | undefined {\n try {\n const value: unknown = JSON.parse(key);\n if (\n !Array.isArray(value) ||\n value.length !== 2 ||\n typeof value[0] !== 'string' ||\n value[0].length === 0 ||\n typeof value[1] !== 'string' ||\n value[1].length === 0\n ) return undefined;\n return { conversationId: value[0], originNodeId: value[1] };\n } catch {\n return undefined;\n }\n}\n\nexport interface ConversationMeta {\n conversationId: string;\n title: string;\n lastMessagePreview: string;\n lastMessageTimestamp: number;\n messageCount: number;\n originNodeId: string;\n /** Lamport clock of the origin metadata event; never substitute messageCount. */\n originClock: number;\n definitionId: string;\n instanceDelta?: Record<string, unknown>;\n isUserInitiated: boolean;\n sourceChannel?: {\n channelId: string;\n platform: string;\n imUserId: string;\n };\n}\n\nexport function isConversationMeta(value: unknown): value is ConversationMeta {\n if (value === null || typeof value !== 'object') return false;\n const o = value as Record<string, unknown>;\n return (\n typeof o.conversationId === 'string' &&\n typeof o.title === 'string' &&\n typeof o.originNodeId === 'string' &&\n typeof o.originClock === 'number' &&\n typeof o.definitionId === 'string' &&\n typeof o.messageCount === 'number' &&\n typeof o.lastMessageTimestamp === 'number' &&\n typeof o.isUserInitiated === 'boolean'\n );\n}\n\nexport interface VersionRange {\n conversationId: string;\n originNodeId: string;\n fromExclusive: number;\n toInclusive: number;\n}\n\nexport function computeMissingVersionRanges(\n currentVersion: VersionVector,\n availableVersion: VersionVector,\n): VersionRange[] {\n const ranges: VersionRange[] = [];\n for (const [key, availableClock] of Object.entries(availableVersion)) {\n const identity = parseVersionVectorKey(key);\n if (!identity) continue;\n const currentClock = currentVersion[key] ?? 0;\n if (availableClock > currentClock) {\n ranges.push({ ...identity, fromExclusive: currentClock, toInclusive: availableClock });\n }\n }\n return ranges.sort((left, right) =>\n compareCodeUnits(left.conversationId, right.conversationId) ||\n compareCodeUnits(left.originNodeId, right.originNodeId)\n );\n}\n\nexport function versionVectorCoversRange(\n vector: VersionVector,\n range: VersionRange,\n): boolean {\n const key = versionVectorKey(range.conversationId, range.originNodeId);\n return (vector[key] ?? 0) >= range.toInclusive;\n}\n\nfunction compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\n/** Bounded, forward-only raw event page used by peer anti-entropy. */\nexport interface ConversationEventSyncPage {\n items: ConversationEvent[];\n /** Cursor of the final returned matching event. */\n nextCursor?: ConversationEventCursor;\n}\n","import type { AttachmentReference, ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport {\n assertCanonicalConversationEvent,\n assertCanonicalConversationEvents,\n canonicalConversationEventBytes,\n conversationEventAttachmentReferences,\n} from '../conversation/index.js';\nimport { MAX_SYNC_ATTACHMENT_BYTES, MAX_SYNC_ATTACHMENT_CHUNK_BYTES } from '../device-network/libp2pSyncProtocol.js';\nimport type { ConversationEventPage as StoredConversationEventPage, MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from '../storage/ports.js';\nimport { type ConversationEventSyncPage, type VersionRange, versionVectorKey } from './protocol.js';\n\nimport type { IAgentStorage } from '../types.js';\nimport { assertAgentUserMessageWithinLimits, assertConversationMessageWithinPagingLimits } from '../userMessageAdmission.js';\n\nconst EVENT_PUSH_PAGE_MAX_BYTES = 12 * 1024 * 1024;\nconst EVENT_PAGE_MAX_ITEMS = 128;\nconst FRONTIER_PAGE_MAX_ITEMS = 128;\nconst MAX_SYNC_ID_LENGTH = 512;\nconst MAX_SYNC_CONVERSATION_SCOPE = 256;\nconst MAX_SYNC_WORK_PAGES_PER_PEER_PASS = 64;\n/**\n * Frontier discovery is cheap, bounded metadata work rather than body\n * transfer. Keeping a separate ceiling lets a restarted engine rebuild its\n * position from durable frontiers without weakening the 64 transfer-page\n * limit. 2,048 pages cover 262,144 distinct origin frontiers per pass.\n */\nconst MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS = 2_048;\nconst MAX_SYNC_EVENTS_PER_PEER_PASS = 4_096;\nconst MAX_SYNC_BYTES_PER_PEER_PASS = 80 * 1024 * 1024;\nconst MAX_SYNC_PEERS_PER_PASS = 64;\nconst utf8Encoder = new TextEncoder();\n\ninterface PeerSyncContinuation {\n localAfter?: MessageVersionFrontierCursor;\n remoteAfter?: MessageVersionFrontierCursor;\n localDone: boolean;\n remoteDone: boolean;\n}\n\ninterface PeerSyncWorkBudget {\n frontierPages: number;\n pages: number;\n events: number;\n bytes: number;\n exhausted: boolean;\n global: SyncPassWorkBudget;\n}\n\ninterface SyncPassWorkBudget {\n frontierPages: number;\n pages: number;\n events: number;\n bytes: number;\n exhausted: boolean;\n limits: ChatSyncPassLimits;\n}\n\nexport interface SyncIoOptions {\n signal?: AbortSignal;\n}\n\nexport interface ChatSyncPassProgress {\n peers: number;\n /** Frontier metadata pages inspected while discovering transfer work. */\n frontierPages: number;\n /** Event/attachment transfer pages; hard-limited independently of discovery. */\n pages: number;\n events: number;\n bytes: number;\n}\n\nexport interface ChatSyncPassResult {\n complete: boolean;\n progress: ChatSyncPassProgress;\n /** Present only when another bounded pass can make forward progress. */\n continuation?: {\n reason: 'work-budget';\n pendingPeerIds: string[];\n };\n}\n\nexport interface ChatSyncPassLimits {\n maxPeers: number;\n maxFrontierPages: number;\n maxPages: number;\n maxEvents: number;\n maxBytes: number;\n}\n\nexport interface ChatSyncPeer {\n nodeId: string;\n exchangeVersionFrontierPage(\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<{\n remotePage: MessageVersionFrontierPage;\n missingForRemote: VersionRange[];\n }>;\n pullMissingEvents?(\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage>;\n pullAttachmentChunk?(\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<\n {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n } | null\n >;\n pushEvents?(events: ConversationEvent[], options?: SyncIoOptions): Promise<void>;\n pushAttachmentChunk?(\n conversationId: string,\n contentHash: string,\n chunk: {\n data: Uint8Array;\n offset: number;\n totalSize: number;\n done: boolean;\n filename: string;\n mimeType: string;\n },\n options?: SyncIoOptions,\n ): Promise<void>;\n}\n\nexport interface ChatSyncEngineOptions {\n nodeId: string;\n storage: IAgentStorage;\n peers: () => ChatSyncPeer[];\n /** Surface body-transfer failures to an interactive caller instead of relying on the next pass. */\n failOnMessageSyncError?: boolean;\n signal?: AbortSignal;\n /** Restrict this pass to these conversations; undefined means the full store. */\n conversationIds?: readonly string[];\n /** Optional lower ceilings for one foreground pass; hard protocol ceilings cannot be raised. */\n passLimits?: Partial<ChatSyncPassLimits>;\n}\n\n/** Bidirectional, raw-event anti-entropy for conversation state. */\nexport class ChatSyncEngine {\n private readonly nodeId: string;\n private readonly storage: IAgentStorage;\n private readonly getPeers: () => ChatSyncPeer[];\n private readonly failOnMessageSyncError: boolean;\n private readonly defaultSignal?: AbortSignal;\n private activeSignal?: AbortSignal;\n private readonly conversationIds?: string[];\n private readonly passLimits: ChatSyncPassLimits;\n private readonly continuations = new Map<string, PeerSyncContinuation>();\n private readonly pendingAttachmentPushes = new Map<string, Set<string>>();\n private nextPeerAfter?: string;\n private inFlightSync?: Promise<ChatSyncPassResult>;\n\n constructor(options: ChatSyncEngineOptions) {\n if (!isValidSyncIdentifier(options.nodeId)) throw new Error('invalid_sync_node_id');\n this.nodeId = options.nodeId;\n this.storage = options.storage;\n this.getPeers = options.peers;\n this.failOnMessageSyncError = options.failOnMessageSyncError ?? false;\n this.defaultSignal = options.signal;\n this.passLimits = resolvePassLimits(options.passLimits);\n this.conversationIds = options.conversationIds === undefined\n ? undefined\n : [...new Set(options.conversationIds)].sort(compareCodeUnits);\n if (\n this.conversationIds !== undefined &&\n (this.conversationIds.length > MAX_SYNC_CONVERSATION_SCOPE ||\n this.conversationIds.some(conversationId => !isValidSyncIdentifier(conversationId)))\n ) {\n throw new Error('invalid_sync_conversation_scope');\n }\n }\n\n public syncOnce(options: SyncIoOptions = {}): Promise<ChatSyncPassResult> {\n if (this.inFlightSync) return this.inFlightSync;\n this.activeSignal = options.signal ?? this.defaultSignal;\n const running = this.runSyncOnce();\n this.inFlightSync = running;\n const release = (): void => {\n if (this.inFlightSync === running) {\n this.inFlightSync = undefined;\n this.activeSignal = undefined;\n }\n };\n void running.then(release, release);\n return running;\n }\n\n private async runSyncOnce(): Promise<ChatSyncPassResult> {\n this.throwIfAborted();\n const peers = this.collectPeers();\n const activePeerIds = new Set(peers.map(peer => peer.nodeId));\n this.garbageCollectPeerState(activePeerIds);\n if (this.conversationIds?.length === 0) {\n return {\n complete: true,\n progress: { peers: 0, frontierPages: 0, pages: 0, events: 0, bytes: 0 },\n };\n }\n if (!this.storage.getEventVersionFrontierPage || !this.storage.getEventVersionFrontiersForKeys) {\n throw new Error('sync_event_frontier_store_not_configured');\n }\n const orderedPeers = rotatePeers(peers, this.nextPeerAfter);\n const globalBudget = createSyncPassWorkBudget(this.passLimits);\n const progress: ChatSyncPassProgress = {\n peers: 0,\n frontierPages: 0,\n pages: 0,\n events: 0,\n bytes: 0,\n };\n const pendingPeerIds: string[] = [];\n let complete = true;\n let processedPeers = 0;\n const scheduledPeers = orderedPeers.slice(0, this.passLimits.maxPeers);\n for (const peer of scheduledPeers) {\n if (globalBudget.frontierPages >= globalBudget.limits.maxFrontierPages) {\n globalBudget.exhausted = true;\n complete = false;\n break;\n }\n const budget = createPeerSyncWorkBudget(globalBudget);\n try {\n const peerComplete = await this.syncPeerFrontierPages(peer, scheduledPeers, budget);\n if (!peerComplete) {\n complete = false;\n if (budget.exhausted) {\n pendingPeerIds.push(peer.nodeId);\n } else if (this.failOnMessageSyncError) {\n throw new Error(`event_sync_incomplete:${peer.nodeId}`);\n }\n }\n } catch (error) {\n this.throwIfAborted();\n if (this.failOnMessageSyncError) throw error;\n complete = false;\n } finally {\n processedPeers += 1;\n this.nextPeerAfter = peer.nodeId;\n progress.peers += 1;\n progress.frontierPages += budget.frontierPages;\n progress.pages += budget.pages;\n progress.events += budget.events;\n progress.bytes += budget.bytes;\n }\n if (globalBudget.exhausted) break;\n }\n const skippedPeers = orderedPeers.slice(processedPeers);\n if (skippedPeers.length > 0) {\n complete = false;\n for (const peer of skippedPeers.slice(0, this.passLimits.maxPeers)) {\n pendingPeerIds.push(peer.nodeId);\n }\n } else if (complete) {\n this.nextPeerAfter = undefined;\n }\n const boundedPendingPeerIds = [...new Set(pendingPeerIds)].slice(0, this.passLimits.maxPeers);\n return {\n complete,\n progress,\n ...(boundedPendingPeerIds.length > 0\n ? { continuation: { reason: 'work-budget' as const, pendingPeerIds: boundedPendingPeerIds } }\n : {}),\n };\n }\n\n public antiEntropyOnce(options: SyncIoOptions = {}): Promise<ChatSyncPassResult> {\n return this.syncOnce(options);\n }\n\n private async syncPeerFrontierPages(\n peer: ChatSyncPeer,\n attachmentPeers: ChatSyncPeer[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n const continuation = this.continuations.get(peer.nodeId);\n let localAfter = continuation?.localAfter;\n let remoteAfter = continuation?.remoteAfter;\n let localDone = continuation?.localDone ?? false;\n let remoteDone = continuation?.remoteDone ?? false;\n do {\n this.throwIfAborted();\n if (!consumeFrontierScanPage(budget)) {\n this.saveContinuation(peer.nodeId, { localAfter, remoteAfter, localDone, remoteDone });\n return false;\n }\n const localPage: MessageVersionFrontierPage = localDone\n ? { items: [] }\n : await this.storage.getEventVersionFrontierPage({\n limit: FRONTIER_PAGE_MAX_ITEMS,\n ...(localAfter ? { after: localAfter } : {}),\n ...(this.conversationIds ? { conversationIds: this.conversationIds } : {}),\n signal: this.activeSignal,\n });\n this.assertValidFrontierPage(localPage, localAfter, 'storage');\n const exchange = await peer.exchangeVersionFrontierPage(\n localPage.items,\n remoteAfter,\n !remoteDone,\n this.conversationIds,\n { signal: this.activeSignal },\n );\n this.assertValidFrontierPage(exchange.remotePage, remoteAfter, peer.nodeId, remoteDone);\n if (\n !isValidVersionRanges(exchange.missingForRemote) ||\n !rangesMatchOfferedFrontiers(exchange.missingForRemote, localPage.items)\n ) {\n throw new Error(`inconsistent_sync_exchange:${peer.nodeId}`);\n }\n this.assertScopedRanges(exchange.missingForRemote, peer.nodeId);\n const pushComplete = await this.pushEventsToPeer(peer, exchange.missingForRemote, budget);\n if (!pushComplete) {\n this.saveContinuation(peer.nodeId, { localAfter, remoteAfter, localDone, remoteDone });\n return false;\n }\n\n const localForRemote = await this.storage.getEventVersionFrontiersForKeys(\n exchange.remotePage.items.map(frontier => ({\n conversationId: frontier.conversationId,\n originNodeId: frontier.originNodeId,\n })),\n { signal: this.activeSignal },\n );\n const localByKey = new Map(localForRemote.map(frontier => [\n versionVectorKey(frontier.conversationId, frontier.originNodeId),\n frontier.maxContiguousOriginSequence,\n ]));\n const missingForLocal = exchange.remotePage.items.flatMap(frontier => {\n const current = localByKey.get(versionVectorKey(\n frontier.conversationId,\n frontier.originNodeId,\n )) ?? 0;\n return frontier.maxContiguousOriginSequence > current\n ? [{\n conversationId: frontier.conversationId,\n originNodeId: frontier.originNodeId,\n fromExclusive: current,\n toInclusive: frontier.maxContiguousOriginSequence,\n }]\n : [];\n });\n this.assertScopedRanges(missingForLocal, peer.nodeId);\n const pullComplete = await this.pullEventsFromPeer(\n peer,\n missingForLocal,\n attachmentPeers,\n budget,\n );\n if (!pullComplete) {\n this.saveContinuation(peer.nodeId, { localAfter, remoteAfter, localDone, remoteDone });\n return false;\n }\n\n localAfter = localPage.nextCursor;\n remoteAfter = exchange.remotePage.nextCursor;\n localDone = localDone || localAfter === undefined;\n remoteDone = remoteDone || remoteAfter === undefined;\n } while (!localDone || !remoteDone);\n this.continuations.delete(peer.nodeId);\n this.pendingAttachmentPushes.delete(peer.nodeId);\n return true;\n }\n\n private async pushEventsToPeer(\n peer: ChatSyncPeer,\n ranges: VersionRange[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n if (ranges.length === 0) return true;\n if (!peer.pushEvents || !this.storage.getConversationEventPage) return false;\n try {\n const rangesByConversation = groupRangesByConversation(ranges);\n const coverage = createCoverageProgress(ranges);\n const pushedHashes = new Set<string>();\n const pendingPushes = this.pendingAttachmentPushes.get(peer.nodeId) ?? new Set<string>();\n this.pendingAttachmentPushes.set(peer.nodeId, pendingPushes);\n let batch: ConversationEvent[] = [];\n const flush = async (): Promise<void> => {\n if (batch.length === 0) return;\n const flushed = batch;\n await peer.pushEvents!(flushed, { signal: this.activeSignal });\n for (const event of flushed) {\n for (const attachment of conversationEventAttachmentReferences(event)) {\n pendingPushes.delete(`${event.conversationId}\\u0000${attachment.contentHash}`);\n }\n }\n batch = [];\n };\n\n for (const [conversationId, conversationRanges] of rangesByConversation) {\n let cursor: ConversationEventCursor | undefined;\n do {\n this.throwIfAborted();\n if (!consumeWorkPages(budget, 1)) {\n await flush();\n return false;\n }\n const page = await this.storage.getConversationEventPage(conversationId, {\n limit: EVENT_PAGE_MAX_ITEMS,\n after: cursor,\n direction: 'forward',\n signal: this.activeSignal,\n ranges: conversationRanges.map(range => ({\n originNodeId: range.originNodeId,\n fromExclusive: range.fromExclusive,\n toInclusive: range.toInclusive,\n })),\n });\n this.assertValidStoredEventPage(page, conversationId, cursor);\n for (const event of page.items) {\n if (!consumeWorkEvent(budget, event)) {\n await flush();\n return false;\n }\n const range = conversationRanges.find(candidate => eventInRange(event, candidate));\n if (!range) continue;\n recordObservedSequence(coverage, event);\n for (const attachment of conversationEventAttachmentReferences(event)) {\n const attachmentKey = `${conversationId}\\u0000${attachment.contentHash}`;\n if (pushedHashes.has(attachmentKey) || pendingPushes.has(attachmentKey)) continue;\n if (!await this.pushAttachmentToPeer(peer, conversationId, attachment, budget)) {\n await flush();\n return false;\n }\n pushedHashes.add(attachmentKey);\n pendingPushes.add(attachmentKey);\n }\n\n const candidate = [...batch, event];\n if (candidate.length > EVENT_PAGE_MAX_ITEMS || jsonByteLength(candidate) > EVENT_PUSH_PAGE_MAX_BYTES) {\n if (batch.length === 0) throw new Error('sync_event_too_large');\n await flush();\n batch = [event];\n if (jsonByteLength(batch) > EVENT_PUSH_PAGE_MAX_BYTES) {\n throw new Error('sync_event_too_large');\n }\n } else {\n batch = candidate;\n }\n }\n cursor = page.hasMoreAfter ? page.endCursor : undefined;\n } while (cursor !== undefined);\n }\n await flush();\n return rangesHaveExactCoverage(coverage);\n } catch (error) {\n this.throwIfAborted();\n if (this.failOnMessageSyncError) throw error;\n return false;\n }\n }\n\n private async pullEventsFromPeer(\n peer: ChatSyncPeer,\n ranges: VersionRange[],\n attachmentPeers: ChatSyncPeer[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n if (ranges.length === 0) return true;\n if (!peer.pullMissingEvents || !this.storage.insertEventsIfAbsent) return false;\n try {\n const rangesByConversation = groupRangesByConversation(ranges);\n let coverage = createCoverageProgress(ranges);\n for (const [conversationId, conversationRanges] of rangesByConversation) {\n let cursor: ConversationEventCursor | undefined;\n do {\n this.throwIfAborted();\n if (!consumeWorkPages(budget, 1)) return false;\n const page = await peer.pullMissingEvents(\n conversationId,\n conversationRanges,\n cursor,\n { signal: this.activeSignal },\n );\n this.assertValidEventPage(page, conversationId, conversationRanges, cursor, peer.nodeId);\n assertCanonicalConversationEvents(page.items);\n const candidateCoverage = cloneCoverageProgress(coverage);\n const acceptedEvents: ConversationEvent[] = [];\n for (const event of page.items) {\n if (!consumeWorkEvent(budget, event)) break;\n recordObservedSequence(candidateCoverage, event);\n acceptedEvents.push(event);\n }\n // BLOBs land before their referencing event. A failed or corrupt BLOB\n // therefore cannot leak into the durable frontier on a later retry.\n if (!await this.ensureAttachmentsFromEvents(acceptedEvents, attachmentPeers, budget)) {\n return false;\n }\n if (acceptedEvents.length > 0) {\n await this.storage.insertEventsIfAbsent(acceptedEvents);\n }\n coverage = candidateCoverage;\n if (acceptedEvents.length !== page.items.length) return false;\n cursor = page.nextCursor;\n } while (cursor !== undefined);\n }\n return rangesHaveExactCoverage(coverage);\n } catch (error) {\n this.throwIfAborted();\n if (this.failOnMessageSyncError) throw error;\n return false;\n }\n }\n\n private async ensureAttachmentsFromEvents(\n events: ConversationEvent[],\n peers: ChatSyncPeer[],\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n const references = new Map<string, { conversationId: string; reference: AttachmentReference }>();\n for (const event of events) {\n for (const reference of conversationEventAttachmentReferences(event)) {\n references.set(`${event.conversationId}\\u0000${reference.contentHash}`, {\n conversationId: event.conversationId,\n reference,\n });\n }\n }\n for (const { conversationId, reference } of references.values()) {\n if (await this.hasLocalAttachment(reference)) continue;\n if (\n !this.storage.stageAttachmentChunk || !this.storage.commitStagedAttachment ||\n reference.size > MAX_SYNC_ATTACHMENT_BYTES\n ) return false;\n const capablePeers = peers.filter(peer => peer.pullAttachmentChunk !== undefined);\n if (capablePeers.length === 0) return false;\n if (!reserveAttachmentWork(budget, reference.size)) return false;\n let fetched = false;\n for (const peer of capablePeers) {\n const pull = peer.pullAttachmentChunk?.bind(peer);\n if (!pull) continue;\n try {\n let offset = 0;\n while (offset <= reference.size) {\n this.throwIfAborted();\n const chunk = await pull(\n conversationId,\n reference.contentHash,\n offset,\n MAX_SYNC_ATTACHMENT_CHUNK_BYTES,\n { signal: this.activeSignal },\n );\n if (\n !chunk || chunk.offset !== offset || chunk.totalSize !== reference.size ||\n chunk.filename !== reference.filename || chunk.mimeType !== reference.mimeType ||\n chunk.data.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n chunk.done !== (offset + chunk.data.byteLength === reference.size) ||\n (!chunk.done && chunk.data.byteLength === 0)\n ) {\n throw new Error('invalid_sync_attachment_chunk');\n }\n const nextOffset = await this.storage.stageAttachmentChunk(\n reference,\n offset,\n chunk.data,\n { signal: this.activeSignal },\n );\n this.throwIfAborted();\n if (\n !Number.isSafeInteger(nextOffset) || nextOffset !== offset + chunk.data.byteLength ||\n nextOffset > reference.size\n ) {\n throw new Error('sync_attachment_cursor_mismatch');\n }\n offset = nextOffset;\n if (offset === reference.size) {\n await this.storage.commitStagedAttachment(\n reference.contentHash,\n { signal: this.activeSignal },\n );\n this.throwIfAborted();\n fetched = await this.hasLocalAttachment(reference);\n break;\n }\n }\n } catch {\n this.throwIfAborted();\n // Another authorized peer may still have the content-addressed body.\n }\n if (fetched) break;\n }\n if (!fetched) return false;\n }\n return true;\n }\n\n private async hasLocalAttachment(reference: AttachmentReference): Promise<boolean> {\n const stored = await this.storage.getAttachment(reference.contentHash);\n return stored !== null && stored.size === reference.size && stored.filename === reference.filename &&\n stored.mimeType === reference.mimeType && this.storage.verifyAttachment !== undefined &&\n await this.storage.verifyAttachment(reference.contentHash, { signal: this.activeSignal });\n }\n\n private async pushAttachmentToPeer(\n peer: ChatSyncPeer,\n conversationId: string,\n reference: AttachmentReference,\n budget: PeerSyncWorkBudget,\n ): Promise<boolean> {\n if (\n !peer.pushAttachmentChunk || !this.storage.readAttachmentRange ||\n reference.size > MAX_SYNC_ATTACHMENT_BYTES || !await this.hasLocalAttachment(reference)\n ) {\n return false;\n }\n if (!reserveAttachmentWork(budget, reference.size)) return false;\n let offset = 0;\n while (offset <= reference.size) {\n this.throwIfAborted();\n const data = await this.storage.readAttachmentRange(\n reference.contentHash,\n offset,\n MAX_SYNC_ATTACHMENT_CHUNK_BYTES,\n { signal: this.activeSignal },\n );\n this.throwIfAborted();\n if (\n !data || data.byteLength > MAX_SYNC_ATTACHMENT_CHUNK_BYTES ||\n offset + data.byteLength > reference.size ||\n (data.byteLength === 0 && offset !== reference.size)\n ) return false;\n const done = offset + data.byteLength === reference.size;\n await peer.pushAttachmentChunk(\n conversationId,\n reference.contentHash,\n {\n data,\n offset,\n totalSize: reference.size,\n done,\n filename: reference.filename,\n mimeType: reference.mimeType,\n },\n { signal: this.activeSignal },\n );\n offset += data.byteLength;\n if (done) return true;\n }\n return false;\n }\n\n private assertValidEventPage(\n page: ConversationEventSyncPage,\n conversationId: string,\n ranges: VersionRange[],\n previousCursor: ConversationEventCursor | undefined,\n peerId: string,\n ): void {\n if (\n !isPlainRecord(page) || !hasOnlyKeys(page, ['items', 'nextCursor']) ||\n !Array.isArray(page.items) || page.items.length > EVENT_PAGE_MAX_ITEMS\n ) {\n throw new Error(`invalid_event_sync_page:${peerId}`);\n }\n assertBoundedCanonicalEventBytes(page.items, `invalid_event_sync_page:${peerId}`);\n let lastCursor = previousCursor;\n for (const event of page.items) {\n try {\n assertCanonicalConversationEvent(event);\n assertAdmittedConversationMessageEvent(event);\n } catch {\n throw new Error(`invalid_event_sync_item:${peerId}`);\n }\n if (\n event.conversationId !== conversationId ||\n !ranges.some(range => eventInRange(event, range))\n ) {\n throw new Error(`invalid_event_sync_item:${peerId}`);\n }\n const currentCursor = eventCursor(event);\n if (lastCursor && compareEventCursor(currentCursor, lastCursor) <= 0) {\n throw new Error(`invalid_event_sync_order:${peerId}`);\n }\n lastCursor = currentCursor;\n }\n if (page.nextCursor === undefined) return;\n if (!isConversationEventCursor(page.nextCursor)) throw new Error(`invalid_event_sync_cursor:${peerId}`);\n if (previousCursor && compareEventCursor(page.nextCursor, previousCursor) <= 0) {\n throw new Error(`event_sync_cursor_did_not_advance:${peerId}`);\n }\n const lastItem = page.items.at(-1);\n if (!lastItem || compareEventCursor(page.nextCursor, eventCursor(lastItem)) !== 0) {\n throw new Error(`event_sync_cursor_not_last_item:${peerId}`);\n }\n }\n\n private assertValidStoredEventPage(\n page: StoredConversationEventPage,\n conversationId: string,\n previousCursor: ConversationEventCursor | undefined,\n ): void {\n if (\n !isPlainRecord(page) || !hasOnlyKeys(page, [\n 'items',\n 'hasMoreBefore',\n 'hasMoreAfter',\n 'startCursor',\n 'endCursor',\n ]) || !Array.isArray(page.items) || page.items.length > EVENT_PAGE_MAX_ITEMS ||\n typeof page.hasMoreBefore !== 'boolean' || typeof page.hasMoreAfter !== 'boolean' ||\n page.items.some(event => {\n try {\n assertCanonicalConversationEvent(event);\n assertAdmittedConversationMessageEvent(event);\n return event.conversationId !== conversationId;\n } catch {\n return true;\n }\n })\n ) {\n throw new Error('invalid_storage_event_page');\n }\n assertBoundedCanonicalEventBytes(page.items, 'invalid_storage_event_page');\n let lastCursor = previousCursor;\n for (const event of page.items) {\n const currentCursor = eventCursor(event);\n if (lastCursor && compareEventCursor(currentCursor, lastCursor) <= 0) {\n throw new Error('invalid_storage_event_order');\n }\n lastCursor = currentCursor;\n }\n if (!page.hasMoreAfter) return;\n if (\n page.items.length === 0 || !page.endCursor || !isConversationEventCursor(page.endCursor) ||\n previousCursor && compareEventCursor(page.endCursor, previousCursor) <= 0 ||\n lastCursor && compareEventCursor(page.endCursor, lastCursor) !== 0\n ) {\n throw new Error('storage_event_cursor_did_not_advance');\n }\n }\n\n public getStorage(): IAgentStorage {\n return this.storage;\n }\n\n private assertScopedRanges(ranges: VersionRange[], peerId: string): void {\n if (this.conversationIds === undefined) return;\n const allowed = new Set(this.conversationIds);\n if (ranges.some(range => !allowed.has(range.conversationId))) {\n throw new Error(`sync_peer_scope_escalation:${peerId}`);\n }\n }\n\n private assertValidFrontierPage(\n page: MessageVersionFrontierPage,\n previous: MessageVersionFrontierCursor | undefined,\n source: string,\n expectedEmpty = false,\n ): void {\n if (\n !isPlainRecord(page) || !hasOnlyKeys(page, ['items', 'nextCursor']) ||\n !Array.isArray(page.items) || page.items.length > FRONTIER_PAGE_MAX_ITEMS ||\n expectedEmpty && (page.items.length > 0 || page.nextCursor !== undefined)\n ) {\n throw new Error(`invalid_sync_frontier_page:${source}`);\n }\n let last = previous;\n for (const frontier of page.items) {\n if (!isValidFrontier(frontier)) throw new Error(`invalid_sync_frontier:${source}`);\n const cursor = { conversationId: frontier.conversationId, originNodeId: frontier.originNodeId };\n if (last && compareFrontierCursor(cursor, last) <= 0) {\n throw new Error(`invalid_sync_frontier_order:${source}`);\n }\n last = cursor;\n }\n if (page.nextCursor === undefined) return;\n if (\n !last || !isValidFrontierCursor(page.nextCursor) ||\n compareFrontierCursor(page.nextCursor, last) !== 0 ||\n previous && compareFrontierCursor(page.nextCursor, previous) <= 0\n ) {\n throw new Error(`sync_frontier_cursor_did_not_advance:${source}`);\n }\n }\n\n private saveContinuation(peerId: string, continuation: PeerSyncContinuation): void {\n this.continuations.set(peerId, {\n localDone: continuation.localDone,\n remoteDone: continuation.remoteDone,\n ...(continuation.localAfter ? { localAfter: { ...continuation.localAfter } } : {}),\n ...(continuation.remoteAfter ? { remoteAfter: { ...continuation.remoteAfter } } : {}),\n });\n }\n\n private collectPeers(): ChatSyncPeer[] {\n const unique = new Map<string, ChatSyncPeer>();\n for (const peer of this.getPeers()) {\n if (!isValidSyncIdentifier(peer.nodeId)) throw new Error('invalid_sync_peer_id');\n if (peer.nodeId === this.nodeId || unique.has(peer.nodeId)) continue;\n unique.set(peer.nodeId, peer);\n }\n return [...unique.values()].sort((left, right) => compareCodeUnits(left.nodeId, right.nodeId));\n }\n\n private garbageCollectPeerState(activePeerIds: ReadonlySet<string>): void {\n for (const peerId of this.continuations.keys()) {\n if (!activePeerIds.has(peerId)) this.continuations.delete(peerId);\n }\n for (const peerId of this.pendingAttachmentPushes.keys()) {\n if (!activePeerIds.has(peerId)) this.pendingAttachmentPushes.delete(peerId);\n }\n if (this.nextPeerAfter !== undefined && !activePeerIds.has(this.nextPeerAfter)) {\n this.nextPeerAfter = undefined;\n }\n }\n\n private throwIfAborted(): void {\n if (!this.activeSignal?.aborted) return;\n throw this.activeSignal.reason instanceof Error\n ? this.activeSignal.reason\n : new Error('chat_sync_aborted');\n }\n}\n\nfunction assertAdmittedConversationMessageEvent(event: ConversationEvent): void {\n if (event.kind !== 'message') return;\n const message = {\n ...event.message,\n conversationId: event.conversationId,\n originNodeId: event.originNodeId,\n originSequence: event.originSequence,\n lamportClock: event.lamportClock,\n timestamp: event.timestamp,\n };\n if (event.message.role === 'user') assertAgentUserMessageWithinLimits(message);\n else assertConversationMessageWithinPagingLimits(message);\n}\n\nfunction isValidFrontier(value: unknown): value is MessageVersionFrontier {\n if (\n !isPlainRecord(value) || !hasOnlyKeys(value, [\n 'conversationId',\n 'originNodeId',\n 'maxContiguousOriginSequence',\n ])\n ) return false;\n const frontier = value as Partial<MessageVersionFrontier>;\n return isValidSyncIdentifier(frontier.conversationId) &&\n isValidSyncIdentifier(frontier.originNodeId) &&\n typeof frontier.maxContiguousOriginSequence === 'number' &&\n Number.isSafeInteger(frontier.maxContiguousOriginSequence) &&\n frontier.maxContiguousOriginSequence > 0;\n}\n\nfunction isValidVersionRanges(value: unknown): value is VersionRange[] {\n if (!Array.isArray(value) || value.length > FRONTIER_PAGE_MAX_ITEMS) return false;\n const identities = new Set<string>();\n for (const item of value) {\n if (\n !isPlainRecord(item) || !hasOnlyKeys(item, [\n 'conversationId',\n 'originNodeId',\n 'fromExclusive',\n 'toInclusive',\n ])\n ) return false;\n const range = item as Partial<VersionRange>;\n if (\n !isValidSyncIdentifier(range.conversationId) ||\n !isValidSyncIdentifier(range.originNodeId) ||\n typeof range.fromExclusive !== 'number' || !Number.isSafeInteger(range.fromExclusive) ||\n range.fromExclusive < 0 || typeof range.toInclusive !== 'number' ||\n !Number.isSafeInteger(range.toInclusive) || range.toInclusive <= range.fromExclusive\n ) return false;\n const key = versionVectorKey(range.conversationId, range.originNodeId);\n if (identities.has(key)) return false;\n identities.add(key);\n }\n return true;\n}\n\nfunction rangesMatchOfferedFrontiers(\n ranges: VersionRange[],\n frontiers: MessageVersionFrontier[],\n): boolean {\n const offered = new Map(frontiers.map(frontier => [\n versionVectorKey(frontier.conversationId, frontier.originNodeId),\n frontier.maxContiguousOriginSequence,\n ]));\n return ranges.every(range => offered.get(versionVectorKey(range.conversationId, range.originNodeId)) === range.toInclusive);\n}\n\nfunction isValidFrontierCursor(value: unknown): value is MessageVersionFrontierCursor {\n if (!isPlainRecord(value) || !hasOnlyKeys(value, ['conversationId', 'originNodeId'])) return false;\n const cursor = value as Partial<MessageVersionFrontierCursor>;\n return isValidSyncIdentifier(cursor.conversationId) &&\n isValidSyncIdentifier(cursor.originNodeId);\n}\n\nfunction compareFrontierCursor(\n left: MessageVersionFrontierCursor,\n right: MessageVersionFrontierCursor,\n): number {\n return compareUtf8Bytes(left.conversationId, right.conversationId) ||\n compareUtf8Bytes(left.originNodeId, right.originNodeId);\n}\n\nfunction resolvePassLimits(input: Partial<ChatSyncPassLimits> | undefined): ChatSyncPassLimits {\n const limits: ChatSyncPassLimits = {\n maxPeers: input?.maxPeers ?? MAX_SYNC_PEERS_PER_PASS,\n maxFrontierPages: input?.maxFrontierPages ?? MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS,\n maxPages: input?.maxPages ?? MAX_SYNC_WORK_PAGES_PER_PEER_PASS,\n maxEvents: input?.maxEvents ?? MAX_SYNC_EVENTS_PER_PEER_PASS,\n maxBytes: input?.maxBytes ?? MAX_SYNC_BYTES_PER_PEER_PASS,\n };\n const hardLimits: ChatSyncPassLimits = {\n maxPeers: MAX_SYNC_PEERS_PER_PASS,\n maxFrontierPages: MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS,\n maxPages: MAX_SYNC_WORK_PAGES_PER_PEER_PASS,\n maxEvents: MAX_SYNC_EVENTS_PER_PEER_PASS,\n maxBytes: MAX_SYNC_BYTES_PER_PEER_PASS,\n };\n for (const key of Object.keys(limits) as Array<keyof ChatSyncPassLimits>) {\n if (!Number.isSafeInteger(limits[key]) || limits[key] <= 0 || limits[key] > hardLimits[key]) {\n throw new Error(`invalid_sync_pass_limit:${key}`);\n }\n }\n return limits;\n}\n\nfunction createSyncPassWorkBudget(limits: ChatSyncPassLimits): SyncPassWorkBudget {\n return { frontierPages: 0, pages: 0, events: 0, bytes: 0, exhausted: false, limits };\n}\n\nfunction createPeerSyncWorkBudget(global: SyncPassWorkBudget): PeerSyncWorkBudget {\n return { frontierPages: 0, pages: 0, events: 0, bytes: 0, exhausted: false, global };\n}\n\nfunction consumeFrontierScanPage(budget: PeerSyncWorkBudget): boolean {\n if (\n budget.frontierPages + 1 > MAX_SYNC_FRONTIER_SCAN_PAGES_PER_PEER_PASS ||\n budget.global.frontierPages + 1 > budget.global.limits.maxFrontierPages\n ) {\n budget.exhausted = true;\n if (budget.global.frontierPages + 1 > budget.global.limits.maxFrontierPages) {\n budget.global.exhausted = true;\n }\n return false;\n }\n budget.frontierPages += 1;\n budget.global.frontierPages += 1;\n return true;\n}\n\nfunction consumeWorkPages(budget: PeerSyncWorkBudget, count: number): boolean {\n if (\n budget.pages + count > MAX_SYNC_WORK_PAGES_PER_PEER_PASS ||\n budget.global.pages + count > budget.global.limits.maxPages\n ) {\n budget.exhausted = true;\n if (budget.global.pages + count > budget.global.limits.maxPages) budget.global.exhausted = true;\n return false;\n }\n budget.pages += count;\n budget.global.pages += count;\n return true;\n}\n\nfunction consumeWorkEvent(budget: PeerSyncWorkBudget, event: ConversationEvent): boolean {\n const bytes = canonicalConversationEventBytes(event).byteLength;\n if (\n budget.events + 1 > MAX_SYNC_EVENTS_PER_PEER_PASS ||\n budget.bytes + bytes > MAX_SYNC_BYTES_PER_PEER_PASS ||\n budget.global.events + 1 > budget.global.limits.maxEvents ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) {\n budget.exhausted = true;\n if (\n budget.global.events + 1 > budget.global.limits.maxEvents ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) budget.global.exhausted = true;\n return false;\n }\n budget.events += 1;\n budget.bytes += bytes;\n budget.global.events += 1;\n budget.global.bytes += bytes;\n return true;\n}\n\nfunction reserveAttachmentWork(budget: PeerSyncWorkBudget, bytes: number): boolean {\n const chunks = Math.max(1, Math.ceil(bytes / MAX_SYNC_ATTACHMENT_CHUNK_BYTES));\n if (\n budget.pages + chunks > MAX_SYNC_WORK_PAGES_PER_PEER_PASS ||\n budget.bytes + bytes > MAX_SYNC_BYTES_PER_PEER_PASS ||\n budget.global.pages + chunks > budget.global.limits.maxPages ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) {\n budget.exhausted = true;\n if (\n budget.global.pages + chunks > budget.global.limits.maxPages ||\n budget.global.bytes + bytes > budget.global.limits.maxBytes\n ) budget.global.exhausted = true;\n return false;\n }\n budget.pages += chunks;\n budget.bytes += bytes;\n budget.global.pages += chunks;\n budget.global.bytes += bytes;\n return true;\n}\n\nfunction rotatePeers(peers: ChatSyncPeer[], after: string | undefined): ChatSyncPeer[] {\n if (peers.length === 0 || after === undefined) return peers;\n const start = peers.findIndex(peer => compareCodeUnits(peer.nodeId, after) > 0);\n if (start < 0) return peers;\n return [...peers.slice(start), ...peers.slice(0, start)];\n}\n\nfunction groupRangesByConversation(ranges: VersionRange[]): Map<string, VersionRange[]> {\n const grouped = new Map<string, VersionRange[]>();\n for (const range of ranges) {\n const values = grouped.get(range.conversationId) ?? [];\n values.push(range);\n grouped.set(range.conversationId, values);\n }\n return grouped;\n}\n\nfunction eventInRange(event: ConversationEvent, range: VersionRange): boolean {\n return event.conversationId === range.conversationId &&\n event.originNodeId === range.originNodeId &&\n event.originSequence > range.fromExclusive &&\n event.originSequence <= range.toInclusive;\n}\n\ninterface CoverageProgress {\n nextExpected: number;\n toInclusive: number;\n}\n\nfunction createCoverageProgress(ranges: VersionRange[]): Map<string, CoverageProgress> {\n const coverage = new Map<string, CoverageProgress>();\n for (const range of ranges) {\n const key = versionVectorKey(range.conversationId, range.originNodeId);\n if (coverage.has(key)) throw new Error('sync_duplicate_version_range');\n coverage.set(key, {\n nextExpected: range.fromExclusive + 1,\n toInclusive: range.toInclusive,\n });\n }\n return coverage;\n}\n\nfunction cloneCoverageProgress(\n coverage: Map<string, CoverageProgress>,\n): Map<string, CoverageProgress> {\n return new Map([...coverage].map(([key, value]) => [key, { ...value }]));\n}\n\nfunction recordObservedSequence(\n coverage: Map<string, CoverageProgress>,\n event: ConversationEvent,\n): void {\n const key = versionVectorKey(event.conversationId, event.originNodeId);\n const progress = coverage.get(key);\n if (!progress || event.originSequence !== progress.nextExpected) {\n throw new Error('sync_non_contiguous_origin_sequence');\n }\n progress.nextExpected += 1;\n}\n\nfunction rangesHaveExactCoverage(\n coverage: Map<string, CoverageProgress>,\n): boolean {\n return [...coverage.values()].every(progress => progress.nextExpected === progress.toInclusive + 1);\n}\n\nfunction isConversationEventCursor(value: unknown): value is ConversationEventCursor {\n if (\n !isPlainRecord(value) || !hasOnlyKeys(value, [\n 'originNodeId',\n 'originSequence',\n 'eventId',\n ])\n ) return false;\n const cursor = value as Partial<ConversationEventCursor>;\n return isValidSyncIdentifier(cursor.originNodeId) &&\n typeof cursor.originSequence === 'number' && Number.isSafeInteger(cursor.originSequence) &&\n cursor.originSequence > 0 && isValidSyncIdentifier(cursor.eventId);\n}\n\nfunction eventCursor(event: ConversationEvent): ConversationEventCursor {\n return {\n originNodeId: event.originNodeId,\n originSequence: event.originSequence,\n eventId: event.eventId,\n };\n}\n\nfunction compareEventCursor(left: ConversationEventCursor, right: ConversationEventCursor): number {\n return compareUtf8Bytes(left.originNodeId, right.originNodeId) ||\n left.originSequence - right.originSequence ||\n compareUtf8Bytes(left.eventId, right.eventId);\n}\n\n/** Matches SQLite's default BINARY ordering used by the production event index. */\nfunction compareUtf8Bytes(left: string, right: string): number {\n if (left === right) return 0;\n const leftBytes = utf8Encoder.encode(left);\n const rightBytes = utf8Encoder.encode(right);\n const length = Math.min(leftBytes.length, rightBytes.length);\n for (let index = 0; index < length; index += 1) {\n const difference = leftBytes[index] - rightBytes[index];\n if (difference !== 0) return difference;\n }\n return leftBytes.length - rightBytes.length;\n}\n\nfunction compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction jsonByteLength(events: readonly ConversationEvent[]): number {\n return canonicalEventArrayBytes(events);\n}\n\nfunction canonicalEventArrayBytes(events: readonly ConversationEvent[]): number {\n let bytes = 2 + Math.max(0, events.length - 1);\n for (const event of events) bytes += canonicalConversationEventBytes(event).byteLength;\n return bytes;\n}\n\nfunction assertBoundedCanonicalEventBytes(\n events: readonly ConversationEvent[],\n errorCode: string,\n): void {\n if (canonicalEventArrayBytes(events) > EVENT_PUSH_PAGE_MAX_BYTES) throw new Error(errorCode);\n}\n\nfunction isValidSyncIdentifier(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 &&\n utf8Encoder.encode(value).byteLength <= MAX_SYNC_ID_LENGTH &&\n !Array.from(value).some(character => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 31 || codePoint === 127;\n });\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n try {\n const prototype = Object.getPrototypeOf(value) as object | null;\n return prototype === Object.prototype || prototype === null;\n } catch {\n return false;\n }\n}\n\nfunction hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {\n const keys = new Set(allowed);\n return Object.keys(value).every(key => keys.has(key));\n}\n","import type { ConversationEvent, ConversationEventCursor } from '../conversation/index.js';\nimport type { AttachmentChunk } from '../device-network/types.js';\nimport type { MessageVersionFrontier, MessageVersionFrontierCursor, MessageVersionFrontierPage } from '../storage/ports.js';\nimport type { ConversationEventSyncPage, VersionRange } from './protocol.js';\n\nimport type { ChatSyncPeer, SyncIoOptions } from './chatSyncEngine.js';\n\nexport interface PeerNodeTransport {\n nodeId: string;\n exchangeVersionFrontierPage(\n targetNodeId: string,\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ): Promise<{\n remotePage: MessageVersionFrontierPage;\n missingForRemote: VersionRange[];\n }>;\n pullMissingEvents?(\n targetNodeId: string,\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage>;\n\n /** 从指定节点拉取附件 BLOB(如 `memeloop.storage.getAttachmentBlob`)。 */\n pullAttachmentChunk?(\n targetNodeId: string,\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ): Promise<AttachmentChunk | null>;\n pushEvents?(\n targetNodeId: string,\n events: ConversationEvent[],\n options?: SyncIoOptions,\n ): Promise<void>;\n pushAttachmentChunk?(\n targetNodeId: string,\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void>;\n}\n\nexport class PeerNodeSyncAdapter implements ChatSyncPeer {\n public readonly nodeId: string;\n private readonly transport: PeerNodeTransport;\n\n constructor(nodeId: string, transport: PeerNodeTransport) {\n this.nodeId = nodeId;\n this.transport = transport;\n }\n\n exchangeVersionFrontierPage(\n localFrontiers: MessageVersionFrontier[],\n remoteAfter: MessageVersionFrontierCursor | undefined,\n includeRemotePage: boolean,\n conversationIds?: string[],\n options?: SyncIoOptions,\n ) {\n return this.transport.exchangeVersionFrontierPage(\n this.nodeId,\n localFrontiers,\n remoteAfter,\n includeRemotePage,\n conversationIds,\n options,\n );\n }\n\n pullMissingEvents(\n conversationId: string,\n ranges: VersionRange[],\n cursor?: ConversationEventCursor,\n options?: SyncIoOptions,\n ): Promise<ConversationEventSyncPage> {\n const function_ = this.transport.pullMissingEvents?.bind(this.transport);\n if (!function_) {\n return Promise.reject(new Error('Peer transport does not support event synchronization'));\n }\n return function_(this.nodeId, conversationId, ranges, cursor, options);\n }\n\n pullAttachmentChunk(\n conversationId: string,\n contentHash: string,\n offset: number,\n maxBytes: number,\n options?: SyncIoOptions,\n ) {\n const function_ = this.transport.pullAttachmentChunk?.bind(this.transport);\n if (!function_) {\n return Promise.resolve(null);\n }\n return function_(this.nodeId, conversationId, contentHash, offset, maxBytes, options);\n }\n\n pushEvents(events: ConversationEvent[], options?: SyncIoOptions): Promise<void> {\n const function_ = this.transport.pushEvents?.bind(this.transport);\n if (!function_) return Promise.reject(new Error('Peer transport does not support event push'));\n return function_(this.nodeId, events, options);\n }\n\n pushAttachmentChunk(\n conversationId: string,\n contentHash: string,\n chunk: AttachmentChunk,\n options?: SyncIoOptions,\n ): Promise<void> {\n const function_ = this.transport.pushAttachmentChunk?.bind(this.transport);\n if (!function_) return Promise.reject(new Error('Peer transport does not support attachment push'));\n return function_(this.nodeId, conversationId, contentHash, chunk, options);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACcO,IAAM,gCAA+D,OAAO,OAAO;AAAA,EACxF,UAAU;AAAA,EACV,UAAU;AAAA,EACV,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,UAAU;AACZ,CAAC;AAsBM,IAAM,qBAAN,cAAiC,MAAM;AAAA,EACrC,YAA4B,MAA8B,OAAiB;AAChF,UAAM,kBAAkB,IAAI,IAAI,UAAU,SAAY,SAAY,EAAE,MAAM,CAAC;AAD1C;AAEjC,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,iBAAiB,oBAAI,IAAI,CAAC,aAAa,eAAe,WAAW,CAAC;AACxE,IAAM,cAAc;AACpB,IAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAM,gBAAqC,IAAI,IAAI,UAAU;AAGtD,SAAS,oBACd,OACA,QACQ;AACR,SAAO,IAAI,qBAAqB,cAAc,MAAM,CAAC,EAAE,OAAO,KAAK;AACrE;AAGO,SAAS,mBACd,OACA,QACY;AACZ,SAAO,IAAI,YAAY,EAAE,OAAO,oBAAoB,OAAO,MAAM,CAAC;AACpE;AAOO,SAAS,kCACd,QACA,SACA,QACY;AACZ,MAAI,OAAO,WAAW,YAAY,OAAO,WAAW,GAAG;AACrD,UAAM,IAAI,mBAAmB,kBAAkB;AAAA,EACjD;AACA,SAAO,mBAAmB,EAAE,QAAQ,QAAQ,GAAG,MAAM;AACvD;AAEA,IAAM,uBAAN,MAA2B;AAAA,EAMlB,YAA6B,QAA6B;AAA7B;AAAA,EAA8B;AAAA,EALjD,SAAmB,CAAC;AAAA,EACpB,gBAAgB,oBAAI,IAAY;AAAA,EACzC,QAAQ;AAAA,EACR,QAAQ;AAAA,EAIT,OAAO,OAAwB;AACpC,SAAK,WAAW,OAAO,CAAC;AACxB,WAAO,KAAK,OAAO,KAAK,EAAE;AAAA,EAC5B;AAAA,EAEQ,WAAW,OAAgB,OAAqB;AACtD,QAAI,QAAQ,KAAK,OAAO,SAAU,MAAK,KAAK,WAAW;AACvD,SAAK,YAAY;AACjB,QAAI,UAAU,MAAM;AAClB,WAAK,OAAO,MAAM;AAClB;AAAA,IACF;AACA,YAAQ,OAAO,OAAO;AAAA,MACpB,KAAK;AACH,aAAK,YAAY,KAAK;AACtB;AAAA,MACF,KAAK;AACH,aAAK,OAAO,QAAQ,SAAS,OAAO;AACpC;AAAA,MACF,KAAK;AACH,aAAK,YAAY,KAAK;AACtB;AAAA,MACF,KAAK;AACH,aAAK,qBAAqB,OAAO,KAAK;AACtC;AAAA,MACF;AACE,aAAK,KAAK,kBAAkB;AAAA,IAChC;AAAA,EACF;AAAA,EAEQ,YAAY,OAAqB;AACvC,QAAI,CAAC,OAAO,SAAS,KAAK,KAAM,OAAO,UAAU,KAAK,KAAK,CAAC,OAAO,cAAc,KAAK,GAAI;AACxF,WAAK,KAAK,gBAAgB;AAAA,IAC5B;AACA,SAAK,OAAO,KAAK,UAAU,KAAK,CAAC;AAAA,EACnC;AAAA,EAEQ,YAAY,OAAqB;AACvC,UAAM,WAAW,KAAK,mBAAmB,KAAK;AAI9C,QAAI,WAAW,IAAI,KAAK,OAAO,WAAW,KAAK,MAAO,MAAK,KAAK,WAAW;AAC3E,SAAK,OAAO,KAAK,UAAU,KAAK,CAAC;AAAA,EACnC;AAAA,EAEQ,qBAAqB,OAAe,OAAqB;AAC/D,SAAK,iBAAiB,OAAO,MAAM;AACjC,UAAI;AACJ,UAAI;AACF,kBAAU,MAAM,QAAQ,KAAK;AAAA,MAC/B,SAAS,OAAO;AACd,cAAM,IAAI,mBAAmB,oBAAoB,KAAK;AAAA,MACxD;AACA,UAAI,QAAS,MAAK,WAAW,OAAoB,KAAK;AAAA,UACjD,MAAK,YAAY,OAAO,KAAK;AAAA,IACpC,CAAC;AAAA,EACH;AAAA,EAEQ,WAAW,OAAkB,OAAqB;AACxD,QAAI,KAAK,cAAc,KAAK,MAAM,MAAM,UAAW,MAAK,KAAK,kBAAkB;AAC/E,UAAM,aAAa,KAAK,eAAe,KAAK;AAC5C,UAAM,iBAAiB,WAAW,KAAK,CAAC,CAAC,GAAG,MAAM,QAAQ,QAAQ,IAAI,CAAC;AACvE,QACE,CAAC,kBAAkB,SAAS,kBAAkB,SAAS,kBACvD,EAAE,WAAW,mBAAmB,eAAe,cAC/C,OAAO,eAAe,UAAU,YAAY,CAAC,OAAO,cAAc,eAAe,KAAK,KACtF,eAAe,QAAQ,EACvB,MAAK,KAAK,gBAAgB;AAC5B,UAAM,SAAS,eAAe;AAC9B,QAAI,SAAS,KAAK,OAAO,SAAU,MAAK,KAAK,WAAW;AACxD,SAAK,wBAAwB,MAAM;AACnC,UAAM,SAAS,oBAAI,IAAqB;AACxC,eAAW,CAAC,KAAK,UAAU,KAAK,YAAY;AAC1C,UAAI,QAAQ,SAAU;AACtB,WAAK,mBAAmB,GAAG;AAC3B,UAAI,CAAC,YAAY,KAAK,GAAG,EAAG,MAAK,KAAK,gBAAgB;AACtD,YAAM,QAAQ,OAAO,GAAG;AACxB,UAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,KAAK,SAAS,QAAQ;AAChE,aAAK,KAAK,gBAAgB;AAAA,MAC5B;AACA,WAAK,mBAAmB,UAAU;AAClC,aAAO,IAAI,OAAO,WAAW,KAAK;AAAA,IACpC;AACA,QAAI,OAAO,SAAS,OAAQ,MAAK,KAAK,cAAc;AAEpD,SAAK,OAAO,GAAG;AACf,aAAS,QAAQ,GAAG,QAAQ,QAAQ,SAAS,GAAG;AAC9C,UAAI,QAAQ,EAAG,MAAK,OAAO,GAAG;AAC9B,WAAK,WAAW,OAAO,IAAI,KAAK,GAAG,QAAQ,CAAC;AAAA,IAC9C;AACA,SAAK,OAAO,GAAG;AAAA,EACjB;AAAA,EAEQ,YAAY,OAAe,OAAqB;AACtD,UAAM,YAAY,KAAK,cAAc,KAAK;AAC1C,QAAI,cAAc,OAAO,aAAa,cAAc,KAAM,MAAK,KAAK,kBAAkB;AACtF,UAAM,aAAa,KAAK,eAAe,KAAK;AAC5C,UAAM,UAAoE,CAAC;AAC3E,QAAI,eAAe;AACnB,eAAW,CAAC,KAAK,UAAU,KAAK,YAAY;AAC1C,UAAI,eAAe,IAAI,GAAG,EAAG,MAAK,KAAK,eAAe;AACtD,WAAK,YAAY;AACjB,YAAM,cAAc,KAAK,mBAAmB,GAAG;AAC/C,WAAK,mBAAmB,UAAU;AAClC,YAAM,mBAAmB,QAAQ,WAAW,IAAI,IAAI;AACpD,qBAAe,KAAK;AAAA,QAClB;AAAA,QACA,cAAc,IAAI;AAAA,MACpB;AACA,YAAM,aAAa,KAAK,UAAU,GAAG;AAIrC,YAAM,oBAAoB,eAAe,UAAU,KAAK,cAAc;AACtE,qBAAe,KAAK,gBAAgB,cAAc,iBAAiB;AACnE,cAAQ,KAAK,CAAC,KAAK,WAAW,OAAO,UAAU,CAAC;AAAA,IAClD;AACA,YAAQ,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MAAM,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC;AAE1E,SAAK,OAAO,GAAG;AACf,YAAQ,QAAQ,CAAC,CAAC,EAAE,MAAM,UAAU,GAAG,UAAU;AAC/C,UAAI,QAAQ,EAAG,MAAK,OAAO,GAAG;AAC9B,WAAK,OAAO,UAAU;AACtB,WAAK,OAAO,GAAG;AACf,WAAK,WAAW,MAAM,QAAQ,CAAC;AAAA,IACjC,CAAC;AACD,SAAK,OAAO,GAAG;AAAA,EACjB;AAAA,EAEQ,cAAc,OAA8B;AAClD,QAAI;AACF,aAAO,OAAO,eAAe,KAAK;AAAA,IACpC,SAAS,OAAO;AACd,YAAM,IAAI,mBAAmB,oBAAoB,KAAK;AAAA,IACxD;AAAA,EACF;AAAA,EAEQ,eAAe,OAAoD;AACzE,QAAI;AACJ,QAAI;AACF,aAAO,QAAQ,QAAQ,KAAK;AAAA,IAC9B,SAAS,OAAO;AACd,YAAM,IAAI,mBAAmB,oBAAoB,KAAK;AAAA,IACxD;AACA,QAAI,KAAK,SAAS,KAAK,OAAO,WAAW,EAAG,MAAK,KAAK,WAAW;AACjE,QAAI,KAAK,KAAK,SAAO,OAAO,QAAQ,QAAQ,EAAG,MAAK,KAAK,iBAAiB;AAC1E,WAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,UAAI;AACJ,UAAI;AACF,qBAAa,OAAO,yBAAyB,OAAO,GAAG;AAAA,MACzD,SAAS,OAAO;AACd,cAAM,IAAI,mBAAmB,oBAAoB,KAAK;AAAA,MACxD;AACA,UAAI,CAAC,WAAY,MAAK,KAAK,kBAAkB;AAC7C,aAAO,CAAC,KAAe,UAAU;AAAA,IACnC,CAAC;AAAA,EACH;AAAA,EAEQ,mBAAmB,YAEzB;AACA,QAAI,SAAS,cAAc,SAAS,WAAY,MAAK,KAAK,mBAAmB;AAC7E,QAAI,CAAC,WAAW,WAAY,MAAK,KAAK,yBAAyB;AAC/D,QAAI,EAAE,WAAW,YAAa,MAAK,KAAK,mBAAmB;AAAA,EAC7D;AAAA,EAEQ,iBAAiB,OAAe,WAA6B;AACnE,QAAI,KAAK,cAAc,IAAI,KAAK,EAAG,MAAK,KAAK,OAAO;AACpD,SAAK,cAAc,IAAI,KAAK;AAC5B,QAAI;AACF,gBAAU;AAAA,IACZ,UAAE;AACA,WAAK,cAAc,OAAO,KAAK;AAAA,IACjC;AAAA,EACF;AAAA,EAEQ,mBAAmB,OAAuB;AAChD,QAAI,MAAM,SAAS,KAAK,OAAO,oBAAoB;AACjD,WAAK,KAAK,uBAAuB;AAAA,IACnC;AACA,UAAM,QAAQ,qBAAqB,OAAO,MAAM,KAAK,KAAK,iBAAiB,CAAC;AAC5E,QAAI,QAAQ,KAAK,OAAO,gBAAgB;AACtC,WAAK,KAAK,kBAAkB;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,wBAAwB,QAAsB;AACpD,UAAM,YAAY,KAAK,OAAO,WAAW,KAAK;AAC9C,QAAI,WAAW,GAAG;AAChB,UAAI,YAAY,EAAG,MAAK,KAAK,WAAW;AACxC;AAAA,IACF;AAGA,QAAI,YAAY,KAAK,SAAS,KAAK,OAAO,YAAY,KAAK,CAAC,GAAG;AAC7D,WAAK,KAAK,WAAW;AAAA,IACvB;AAAA,EACF;AAAA,EAEQ,gBAAgB,SAAiB,YAA4B;AACnE,UAAM,YAAY,KAAK,OAAO,WAAW,KAAK;AAC9C,QAAI,UAAU,aAAa,aAAa,YAAY,QAAS,MAAK,KAAK,WAAW;AAClF,WAAO,UAAU;AAAA,EACnB;AAAA,EAEQ,cAAoB;AAC1B,SAAK,SAAS;AACd,QAAI,KAAK,QAAQ,KAAK,OAAO,SAAU,MAAK,KAAK,WAAW;AAAA,EAC9D;AAAA,EAEQ,OAAO,OAAqB;AAClC,UAAM,aAAa,eAAe,KAAK;AACvC,QAAI,aAAa,KAAK,OAAO,WAAW,KAAK,MAAO,MAAK,KAAK,WAAW;AACzE,SAAK,SAAS;AACd,SAAK,OAAO,KAAK,KAAK;AAAA,EACxB;AAAA,EAEQ,KAAK,MAAqC;AAChD,UAAM,IAAI,mBAAmB,IAAI;AAAA,EACnC;AACF;AAEA,SAAS,cAAc,WAA+D;AACpF,QAAM,SAA8B,EAAE,GAAG,8BAA8B;AACvE,MAAI,cAAc,OAAW,QAAO;AACpC,MAAI,cAAc,QAAQ,OAAO,cAAc,UAAU;AACvD,UAAM,IAAI,mBAAmB,eAAe;AAAA,EAC9C;AACA,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,gBAAY,OAAO,eAAe,SAAS;AAC3C,WAAO,QAAQ,QAAQ,SAAS;AAAA,EAClC,SAAS,OAAO;AACd,UAAM,IAAI,mBAAmB,iBAAiB,KAAK;AAAA,EACrD;AACA,MAAI,cAAc,OAAO,aAAa,cAAc,MAAM;AACxD,UAAM,IAAI,mBAAmB,eAAe;AAAA,EAC9C;AACA,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,QAAQ,YAAY,CAAC,cAAc,IAAI,GAAG,GAAG;AACtD,YAAM,IAAI,mBAAmB,eAAe;AAAA,IAC9C;AACA,QAAI;AACJ,QAAI;AACF,mBAAa,OAAO,yBAAyB,WAAW,GAAG;AAAA,IAC7D,SAAS,OAAO;AACd,YAAM,IAAI,mBAAmB,iBAAiB,KAAK;AAAA,IACrD;AACA,QACE,CAAC,cAAc,SAAS,cAAc,SAAS,cAC/C,CAAC,WAAW,cAAc,EAAE,WAAW,eACvC,CAAC,OAAO,cAAc,WAAW,KAAK,KAAK,WAAW,QAAQ,GAC9D;AACA,YAAM,IAAI,mBAAmB,eAAe;AAAA,IAC9C;AACA,WAAO,GAAgC,IAAI,WAAW;AAAA,EACxD;AACA,SAAO;AACT;AAEA,SAAS,eAAe,OAAuB;AAC7C,MAAI,QAAQ;AACZ,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,KAAM;AAChB,eAAS;AAAA,IACX,WAAW,QAAQ,MAAO;AACxB,eAAS;AAAA,IACX,WAAW,QAAQ,SAAU,QAAQ,OAAQ;AAC3C,YAAM,OAAO,MAAM,WAAW,QAAQ,CAAC;AACvC,UAAI,QAAQ,SAAU,QAAQ,OAAQ;AACpC,iBAAS;AACT,iBAAS;AAAA,MACX,OAAO;AACL,iBAAS;AAAA,MACX;AAAA,IACF,OAAO;AACL,eAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,OAAe,gBAAqC;AAChF,MAAI,QAAQ;AACZ,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,KAAM;AAChB,eAAS;AAAA,IACX,WAAW,QAAQ,MAAO;AACxB,eAAS;AAAA,IACX,WAAW,QAAQ,SAAU,QAAQ,OAAQ;AAC3C,UAAI,QAAQ,KAAK,MAAM,OAAQ,gBAAe;AAC9C,YAAM,OAAO,MAAM,WAAW,QAAQ,CAAC;AACvC,UAAI,OAAO,SAAU,OAAO,MAAQ,gBAAe;AACnD,eAAS;AACT,eAAS;AAAA,IACX,WAAW,QAAQ,SAAU,QAAQ,OAAQ;AAC3C,qBAAe;AAAA,IACjB,OAAO;AACL,eAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO;AACT;;;ACxXO,IAAM,wBAAwB;AAC9B,IAAM,sCAAsC;AAE5C,IAAM,uCAAuC,MAAM;AACnD,IAAM,2CAA2C;AACjD,IAAM,iDAAiD;AACvD,IAAM,uDAAuD;AAC7D,IAAM,uDAAuD;AAC7D,IAAM,6CAA6C;AACnD,IAAM,uCAAuC;AAC7C,IAAM,wCAAwC,MAAM;AAkVpD,SAAS,oCACd,OACA,gBAC8B;AAC9B,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AACA,QAAM,UAAU;AAChB,wBAAsB,SAAS;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI;AACF,yCAAqC,SAAS,cAAc;AAAA,EAC9D,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,2CAA2C,EAAE,OAAO,MAAM,CAAC;AAAA,EAC7E;AACF;AA6EA,SAAS,uBAAuB,OAAyB;AACvD,MAAI;AACF,uBAAmB,OAAO;AAAA,MACxB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,IACtB,CAAC;AACD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AA0CA,SAAS,sBAAsB,OAAyB;AACtD,MAAI;AACF,uBAAmB,OAAO;AAAA,MACxB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,IACtB,CAAC;AACD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iCAAiC,OAAyE;AACjH,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AACA,QAAM,cAAc;AACpB,kBAAgB,aAAa,CAAC,WAAW,cAAc,QAAQ,SAAS,GAAG,qBAAqB;AAChG,MACE,CAAC,eAAe,YAAY,OAAO,KACnC,YAAY,QAAQ,SAAS,wDAC7B,CAAC,eAAe,YAAY,UAAU,KACtC,YAAY,WAAW,SAAS,wDAC/B,YAAY,SAAS,eAAe,YAAY,SAAS,WAC1D,OAAO,YAAY,YAAY,YAC/B,YAAY,QAAQ,SAAS,qDAC7B,OAAM,IAAI,MAAM,mDAAmD;AACvE;AAMA,SAAS,+BAA+B,WAAuC;AAC7E,SAAO,KAAK;AAAA,IACV;AAAA,IACA,KAAK;AAAA,MACH,OAAO,cAAc,SAAS,IAAI,YAAa;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AACF;AA6eO,SAAS,0CACd,OACA,UAAgE,CAAC,GACX;AACtD,QAAM,OAAwC;AAAA,IAC5C,OAAO;AAAA,IACP,OAAO,CAAC;AAAA,IACR,UAAU;AAAA,IACV,eAAe,OAAO;AAAA,IACtB,YAAY,OAAO;AAAA,IACnB,cAAc,OAAO;AAAA,IACrB,eAAe;AAAA,IACf,cAAc;AAAA,EAChB;AACA;AAAA,IACE;AAAA,IACA;AAAA,IACA,QAAQ,kBAAkB;AAAA,EAC5B;AACA,MACE,MAAM,SAAS,gBACd,QAAQ,mBAAmB,UAAa,MAAM,mBAAmB,QAAQ,eAC1E,OAAM,IAAI,MAAM,0CAA0C;AAC9D;AAUA,SAAS,sBAAsB,OAAe,SAAkC;AAC9E,QAAM,OAAO,QAAQ,QAAQ,KAAK;AAClC,MAAI,KAAK,KAAK,SAAO,OAAO,QAAQ,YAAY,CAAC,QAAQ,SAAS,GAAG,CAAC,GAAG;AACvE,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AACF;AAEA,SAAS,0BAA0B,SAAmD;AACpF,MACE,CAAC,WACD,CAAC,OAAO,cAAc,QAAQ,KAAK,KACnC,QAAQ,QAAQ,KAChB,QAAQ,QAAQ,oCAChB,OAAM,IAAI,MAAM,0CAA0C;AAC5D,MACE,CAAC,OAAO,cAAc,QAAQ,QAAQ,KACtC,QAAQ,WAAW,KACnB,QAAQ,WAAW,sCACnB;AACA,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACA,MACE,QAAQ,kBAAkB,WACzB,CAAC,OAAO,cAAc,QAAQ,aAAa,KAAK,QAAQ,gBAAgB,GACzE,OAAM,IAAI,MAAM,8CAA8C;AAChE,QAAM,UAAU,CAAC,QAAQ,cAAc,QAAQ,aAAa,QAAQ,gBAAgB,EACjF,OAAO,WAAS,UAAU,MAAS;AACtC,MAAI,QAAQ,SAAS,EAAG,OAAM,IAAI,MAAM,4CAA4C;AACpF,MAAI,QAAQ,iBAAiB,OAAW,2BAA0B,QAAQ,cAAc,eAAe;AACvG,MAAI,QAAQ,gBAAgB,OAAW,2BAA0B,QAAQ,aAAa,cAAc;AACpG,OACG,QAAQ,iBAAiB,UAAa,QAAQ,gBAAgB,WAC/D,QAAQ,qBAAqB,OAC7B,OAAM,IAAI,MAAM,gDAAgD;AAClE,MACE,QAAQ,qBAAqB,WAC5B,CAAC,OAAO,cAAc,QAAQ,gBAAgB,KAAK,QAAQ,mBAAmB,GAC/E,OAAM,IAAI,MAAM,2CAA2C;AAC7D,MAAI,QAAQ,qBAAqB,QAAW;AAC1C,8BAA0B,QAAQ,kBAAkB,mBAAmB;AAAA,EACzE;AACF;AAkFA,SAAS,iBAAiB,MAAgC,UAA2B;AACnF,MAAI;AACF,uBAAmB,MAAM;AAAA,MACvB;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,IACtB,CAAC;AACD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,uCACd,OACA,SAC2C;AAC3C,4BAA0B,EAAE,GAAG,QAAQ,CAAC;AACxC,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AACA,QAAM,OAAO;AACb,MAAI,CAAC,iBAAiB,MAAM,QAAQ,QAAQ,GAAG;AAC7C,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACA,MAAI,KAAK,OAAO;AACd,oBAAgB,MAAM,CAAC,SAAS,UAAU,GAAG,OAAO;AACpD,8BAA0B,KAAK,UAAU,UAAU;AACnD;AAAA,EACF;AACA,kBAAgB,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,MAAM;AACT,MACE,KAAK,SACL,CAAC,MAAM,QAAQ,KAAK,KAAK,KACzB,KAAK,MAAM,SAAS,QAAQ,SAC5B,CAAC,OAAO,cAAc,KAAK,aAAa,KACxC,KAAK,gBAAgB,KACrB,CAAC,OAAO,cAAc,KAAK,UAAU,KACrC,KAAK,aAAa,KAClB,CAAC,OAAO,cAAc,KAAK,YAAY,KACvC,KAAK,eAAe,KACpB,KAAK,aAAa,KAAK,iBACvB,OAAO,KAAK,kBAAkB,aAC9B,OAAO,KAAK,iBAAiB,UAC7B,OAAM,IAAI,MAAM,oCAAoC;AACtD,4BAA0B,KAAK,UAAU,UAAU;AACnD,QAAM,iBAAiB,+BAA+B,QAAQ,aAAa;AAC3E,QAAM,UAAU,oBAAI,IAAY;AAChC,MAAI,qBAAqB;AACzB,MAAI;AACJ,aAAW,SAAS,KAAK,OAAO;AAC9B,6BAAyB,OAAO,MAAM,cAAc;AACpD,0BAAsB,MAAM;AAC5B,QACE,MAAM,cAAc,sBACnB,sBAAsB,KAAK,MAAM,eAAe,qBAAqB,KACtE,MAAM,cAAc,qBACpB,QAAQ,IAAI,MAAM,MAAM,EACxB,OAAM,IAAI,MAAM,2CAA2C;AAC7D,yBAAqB,MAAM;AAC3B,YAAQ,IAAI,MAAM,MAAM;AACxB,QAAI,MAAM,SAAS,OAAQ,sBAAqB;AAAA,EAClD;AACA,uBAAqB,IAAI;AAC3B;AAGO,SAAS,+BACd,MACA,gBACA,SAC0C;AAC1C,yCAAuC,MAAM,OAAO;AACpD,MAAI,KAAK,OAAO;AACd;AAAA,EACF;AACA,MACE,QAAQ,qBAAqB,UAC7B,KAAK,aAAa,QAAQ,iBAC1B,OAAM,IAAI,MAAM,yCAAyC;AAC3D,aAAW,SAAS,KAAK,OAAO;AAC9B,QAAI,MAAM,mBAAmB,gBAAgB;AAC3C,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AAAA,EACF;AACA,sCAAoC,MAAM,OAAO;AACnD;AAEA,SAAS,qBACP,MACM;AACN,QAAM,QAAQ,KAAK,MAAM,CAAC;AAC1B,QAAM,OAAO,KAAK,MAAM,GAAG,EAAE;AAC7B,MACE,KAAK,oBAAoB,OAAO,cAChC,KAAK,kBAAkB,MAAM,cAC7B,KAAK,gBAAgB,OAAO,UAC5B,KAAK,cAAc,MAAM,UACxB,SAAS,KAAK,kBAAmB,MAAM,aAAa,KACpD,QAAQ,KAAK,iBAAkB,KAAK,aAAa,IAAI,KAAK,gBAC1D,CAAC,UACA,KAAK,oBAAoB,UACzB,KAAK,kBAAkB,UACvB,KAAK,gBAAgB,UACrB,KAAK,cAAc,QAErB,OAAM,IAAI,MAAM,2CAA2C;AAC/D;AAEA,SAAS,oCACP,MACA,SACM;AACN,MAAI,KAAK,MAAM,SAAS,EAAG;AAC3B,QAAM,QAAQ,QAAQ,iBAAiB,SACnC,CAAC,KAAK,iBAAiB,KAAK,iBAAkB,KAAK,eAAe,IAClE,QAAQ,gBAAgB,SACxB,KAAK,kBAAmB,KAAK,eAAe,KAAM,CAAC,KAAK,eACxD,KAAK,iBAAiB,KAAK,CAAC,KAAK,iBAAiB,CAAC,KAAK;AAC5D,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,2CAA2C;AACzE;AAEA,SAAS,yBACP,OACA,MACA,gBAC4C;AAC5C,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AACA,QAAM,QAAQ;AACd,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,MAAM,SAAS,QAAQ;AACzB,oBAAgB,OAAO;AAAA,MACrB,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,GAAG,MAAM;AAAA,EACX,WAAW,MAAM,SAAS,cAAc;AACtC,oBAAgB,OAAO;AAAA,MACrB,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACF,GAAG,YAAY;AAAA,EACjB,OAAO;AACL,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AACA,MACE,CAAC,eAAe,MAAM,cAAc,KACpC,CAAC,eAAe,MAAM,OAAO,KAC7B,CAAC,eAAe,MAAM,YAAY,KAClC,CAAC,OAAO,cAAc,MAAM,SAAS,KACrC,MAAM,YAAY,KAClB,CAAC,OAAO,cAAc,MAAM,YAAY,KACxC,MAAM,eAAe,KACrB,CAAC,OAAO,cAAc,MAAM,UAAU,KACtC,MAAM,aAAa,KACnB,MAAM,cAAc,KAAK,gBACzB,CAAC,OAAO,cAAc,MAAM,SAAS,KACrC,MAAM,YAAY,KAClB,MAAM,YAAY,KAAK,WACvB,OAAM,IAAI,MAAM,qCAAqC;AACvD,4BAA0B,MAAM,QAAQ,QAAQ;AAChD,MAAI,MAAM,SAAS,QAAQ;AACzB,QACE,CAAC,eAAe,MAAM,SAAS,KAC/B,CAAC,eAAe,MAAM,MAAM,KAC5B,MAAM,YAAY,MAAM,aACxB,MAAM,cAAc,MAAM,UAC1B,OAAO,MAAM,gBAAgB,YAC7B,MAAM,YAAY,SAAS,kBAC3B,CAAC,MAAM,QAAQ,MAAM,mBAAmB,KACxC,MAAM,oBAAoB,SAAS,kDACnC,CAAC,OAAO,cAAc,MAAM,aAAa,KACzC,MAAM,gBAAgB,MAAM,oBAAoB,UAChD,CAAC,uBAAuB,MAAM,mBAAmB,KACjD,CAAC,sBAAsB,KAAK,EAC5B,OAAM,IAAI,MAAM,oCAAoC;AACtD,eAAW,eAAe,MAAM,qBAAqB;AACnD,uCAAiC,WAAW;AAAA,IAC9C;AACA;AAAA,EACF;AACA,MACE,MAAM,SAAS,gBACf,MAAM,QAAQ,WAAW,KACzB,OAAO,MAAM,mBAAmB,YAChC,MAAM,eAAe,WAAW,KAChC,MAAM,eAAe,SAAS,kBAC9B,CAAC,OAAO,cAAc,MAAM,qBAAqB,KACjD,MAAM,wBAAwB,KAC9B,CAAC,OAAO,cAAc,MAAM,kBAAkB,KAC9C,MAAM,qBAAqB,EAC3B,OAAM,IAAI,MAAM,0CAA0C;AAC9D;AAEA,SAAS,gBACP,OACA,SACA,MACM;AACN,QAAM,OAAO,QAAQ,QAAQ,KAAK;AAClC,MACE,KAAK,KAAK,SAAO,OAAO,QAAQ,YAAY,CAAC,QAAQ,SAAS,GAAG,CAAC,KAClE,QAAQ,KAAK,SAAO;AAClB,UAAM,aAAa,OAAO,yBAAyB,OAAO,GAAG;AAC7D,WAAO,eAAe,WAAc,CAAC,WAAW,cAAc,EAAE,WAAW;AAAA,EAC7E,CAAC,EACD,OAAM,IAAI,MAAM,iCAAiC,IAAI,EAAE;AAC3D;AAaA,SAAS,0BAA0B,OAAgB,OAAwC;AACzF,MACE,OAAO,UAAU,YACjB,MAAM,WAAW,KACjB,MAAM,SAAS,QACf,UAAU,MAAM,KAAK,KACrB,qBAAqB,KAAK,EAC1B,OAAM,IAAI,MAAM,iCAAiC,KAAK,EAAE;AAC5D;AAEA,SAAS,qBAAqB,OAAwB;AACpD,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,MAAM,SAAS,IAAK,QAAO;AAAA,EACzC;AACA,SAAO;AACT;AAEA,SAAS,eAAe,OAAiC;AACvD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS;AACrD;;;AC37CA,IAAM,2BAA2B;AAEjC,SAAS,iBAAiB,OAAiD;AACzE,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,SAAO,OAAO,OAAO,KAAK,EAAE,MAAM,cAAY,OAAO,aAAa,YAAY,OAAO,cAAc,QAAQ,KAAK,WAAW,CAAC;AAC9H;AAEA,SAAS,WAAW,OAAiD;AACnE,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,SAAO,OAAO,OAAO,KAAK,EAAE,MAAM,WAAS,OAAO,UAAU,YAAY,OAAO,cAAc,KAAK,KAAK,SAAS,CAAC;AACnH;AAEA,SAAS,UAAU,QAAkD;AACnE,SAAO,OAAO,OAAO,MAAM,EAAE,OAAO,CAAC,OAAO,UAAU,QAAQ,OAAO,CAAC;AACxE;AAEO,SAAS,8BACd,OACsC;AACtC,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,WAAW;AACjB,QAAM,cAAc,oBAAI,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,OAAO,KAAK,QAAQ,EAAE,KAAK,SAAO,CAAC,YAAY,IAAI,GAAG,CAAC,EAAG,QAAO;AACrE,MACE,SAAS,YAAY,KACrB,CAAC,iBAAiB,SAAS,cAAc,KACzC,OAAO,KAAK,SAAS,cAAc,EAAE,WAAW,KAChD,CAAC,WAAW,SAAS,2BAA2B,KAChD,CAAC,WAAW,SAAS,4BAA4B,EACjD,QAAO;AACT,QAAM,UAAU,IAAI,IAAI,OAAO,KAAK,SAAS,cAAc,CAAC;AAC5D,MACE,OAAO,KAAK,SAAS,2BAA2B,EAAE,KAAK,YAAU,CAAC,QAAQ,IAAI,MAAM,CAAC,KACrF,OAAO,KAAK,SAAS,4BAA4B,EAAE,KAAK,YAAU,CAAC,QAAQ,IAAI,MAAM,CAAC,KACtF,OAAO,QAAQ,SAAS,4BAA4B,EAAE,KAAK,CAAC,CAAC,QAAQ,KAAK,MAAM,SAAS,SAAS,8BAA8B,MAAM,KAAK,EAAE,EAC7I,QAAO;AACT,QAAM,eAAe,UAAU,SAAS,2BAA2B;AACnE,QAAM,YAAY,UAAU,SAAS,4BAA4B;AACjE,MACE,eAAe,KACf,SAAS,wBAAwB,gBACjC,SAAS,qBAAqB,UAC9B,QAAO;AACT,QAAM,WAAW,SAAS;AAC1B,SAAO,aAAa,UAClB,MAAM,QAAQ,QAAQ,KACpB,SAAS,SAAS,KAClB,SAAS,UAAU,4BACnB,IAAI,IAAI,QAAQ,EAAE,SAAS,SAAS,UACpC,SAAS,MAAM,QAAM,OAAO,OAAO,YAAY,GAAG,SAAS,KAAK,GAAG,UAAU,GAAG;AACtF;;;AC3FO,IAAM,+BAA+B,KAAK,OAAO;AACxD,IAAM,+BAA+B;AAG9B,IAAM,4BAA4B,OAAO;AAAA,EAC9C;AAAA,IACE,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,YAAY,KAAK;AAAA,IACjB,WAAW,IAAI,OAAQ;AAAA,IACvB,qBAAqB,IAAI,OAAQ;AAAA,IACjC,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,uBAAuB;AAAA,IACvB,oBAAoB;AAAA,IACpB,cAAc;AAAA,IACd,WAAW;AAAA,IACX,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,eAAe;AAAA,IACf,iBAAiB,KAAK,OAAQ;AAAA,EAChC;AACF;AAEA,IAAM,kCAAkC;AACxC,IAAM,oBAAoB;AAC1B,IAAM,cAAc,IAAI,YAAY;AAqG7B,SAAS,2BAA2B,OAA8C;AACvF,SAAO;AAAA,IACL,GAAG,MAAM;AAAA,IACT,gBAAgB,MAAM;AAAA,IACtB,cAAc,MAAM;AAAA,IACpB,gBAAgB,MAAM;AAAA,IACtB,cAAc,MAAM;AAAA,IACpB,WAAW,MAAM;AAAA,EACnB;AACF;AAEO,SAAS,2BAA2B,SAAgD;AACzF,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AACJ,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,SAAS,EAAE,WAAW,QAAQ,GAAG,QAAQ;AAAA,EAC3C;AACF;AAGO,SAAS,qCACd,OACA,gBAC8B;AAC9B,MAAI;AACF,uBAAmB,OAAO;AAAA,MACxB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,oBAAoB;AAAA,MACpB,gBAAgB;AAAA,MAChB,UAAU;AAAA,IACZ,CAAC;AACD,UAAM,QAAQ,oCAAoC,2BAA2B,KAAoB,CAAC;AAClG,QACE,MAAM,SAAS,aACd,mBAAmB,UAAa,MAAM,mBAAmB,gBAC1D;AACA,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,6CAA6C,EAAE,OAAO,MAAM,CAAC;AAAA,EAC/E;AACF;AAGO,SAAS,sCACd,OACuB;AACvB,MAAI,MAAM,SAAS,UAAW,QAAO,CAAC;AACtC,QAAM,aAAa,oBAAI,IAAiC;AACxD,aAAW,aAAa,MAAM,QAAQ,eAAe,CAAC,GAAG;AACvD,eAAW,IAAI,UAAU,aAAa,SAAS;AAAA,EACjD;AACA,aAAW,QAAQ,MAAM,QAAQ,SAAS,CAAC,GAAG;AAC5C,QAAI,KAAK,SAAS,cAAc;AAC9B,iBAAW,IAAI,KAAK,WAAW,aAAa,KAAK,UAAU;AAAA,IAC7D;AAAA,EACF;AACA,SAAO,CAAC,GAAG,WAAW,OAAO,CAAC;AAChC;AAEO,SAAS,oBAAoB,OAA4C;AAC9E,MAAI,CAAC,YAAY,KAAK,EAAG,QAAO;AAChC,QAAM,QAAQ;AACd,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,GAAG,eAAe,QAAQ,SAAS,CAAC,KAC7D,iBAAiB,MAAM,OAAO,KAAK,MAAM,YAAY,MAAM,QAAQ;AAAA,IACvE,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,GAAG,eAAe,QAAQ,gBAAgB,UAAU,QAAQ,CAAC,KACtF,aAAa,MAAM,YAAY,MAC9B,MAAM,WAAW,UAChB,MAAM,WAAW,iBAAiB,MAAM,WAAW,eAAe,MAAM,WAAW,iBACpF,MAAM,WAAW,UAAa,sBAAsB,MAAM,QAAQ,IAAI;AAAA,IAC3E,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,GAAG,eAAe,QAAQ,QAAQ,YAAY,SAAS,CAAC,KACjF,8BAA8B,MAAM,QAAQ,KAC5C,sCAAsC,MAAM,QAAQ,MACnD,MAAM,SAAS,mBAAmB,MAAM,YAAY,QACnD,MAAM,SAAS,aAAa,oBAAoB,MAAM,OAAO;AAAA,IACnE,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,GAAG,eAAe,QAAQ,OAAO,CAAC,KAC3D,gBAAgB,MAAM,KAAK;AAAA,IAC/B;AACE,aAAO;AAAA,EACX;AACF;AAOO,SAAS,iCACd,OACoC;AACpC,sCAAoC,KAAK;AAC3C;AAOO,SAAS,oCAAoC,OAAmC;AACrF,MAAI;AACJ,MAAI;AACF,iBAAa,kCAAkC,KAAK;AACpD,uBAAmB,YAAY;AAAA,MAC7B,UAAU;AAAA,MACV,UAAU;AAAA,MACV,oBAAoB;AAAA,MACpB,gBAAgB;AAAA,MAChB,UAAU;AAAA,IACZ,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,wCAAwC,EAAE,OAAO,MAAM,CAAC;AAAA,EAC1E;AACA,MAAI,CAAC,oBAAoB,UAAU,GAAG;AACpC,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,SAAO;AACT;AAGO,SAAS,kCACd,QACgD;AAChD,aAAW,SAAS,OAAQ,kCAAiC,KAAK;AACpE;AAuCO,SAAS,gCAAgC,OAA4B;AAC1E,QAAM,aAAa,oCAAoC,KAAK;AAC5D,SAAO,mBAAmB,YAAY;AAAA,IACpC,UAAU;AAAA,IACV,UAAU;AAAA,IACV,oBAAoB;AAAA,IACpB,gBAAgB;AAAA,IAChB,UAAU;AAAA,EACZ,CAAC;AACH;AAEA,SAAS,YAAY,OAAoE;AACvF,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,QAAQ;AACd,SAAO,aAAa,MAAM,OAAO,KAC/B,aAAa,MAAM,cAAc,KACjC,aAAa,MAAM,YAAY,KAC/B,OAAO,MAAM,mBAAmB,YAAY,OAAO,cAAc,MAAM,cAAc,KACrF,MAAM,iBAAiB,KAAK,OAAO,MAAM,iBAAiB,YAC1D,OAAO,cAAc,MAAM,YAAY,KAAK,MAAM,eAAe,KACjE,OAAO,MAAM,cAAc,YAC3B,OAAO,cAAc,MAAM,SAAS,KAAK,MAAM,aAAa,KAAK,OAAO,MAAM,SAAS;AAC3F;AAEA,SAAS,kCAAkC,OAAyB;AAClE,QAAM,QAAQ,mBAAmB,OAAO,oBAAoB,KAAK,CAAC;AAClE,MAAI,CAAC,cAAc,KAAK,EAAG,QAAO;AAClC,MAAI,MAAM,SAAS,WAAW;AAC5B,UAAM,UAAU,wBAAwB,MAAM,OAAO;AAAA,EACvD,WAAW,MAAM,SAAS,cAAc;AACtC,QAAI,MAAM,SAAS,UAAW,OAAM,UAAU,2BAA2B,MAAM,OAAO;AAAA,EACxF,WAAW,MAAM,SAAS,iBAAiB;AACzC,UAAM,QAAQ,uBAAuB,MAAM,KAAK;AAAA,EAClD;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,OAAqC;AAChE,QAAM,OAAO,iBAAiB,OAAO,MAAM;AAC3C,SAAO,SAAS,cAAc,oBAAI,IAAI,CAAC,UAAU,QAAQ,CAAC,IAAI,oBAAI,IAAI;AACxE;AAEA,SAAS,wBAAwB,OAAyB;AACxD,QAAM,UAAU;AAAA,IACd;AAAA,IACA,oBAAI,IAAI;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACA,MAAI,CAAC,cAAc,OAAO,EAAG,QAAO;AACpC,MAAI,QAAQ,UAAU,QAAW;AAC/B,YAAQ,QAAQ,eAAe,QAAQ,OAAO,6BAA6B;AAAA,EAC7E;AACA,MAAI,QAAQ,cAAc,QAAW;AACnC,YAAQ,YAAY,yBAAyB,QAAQ,SAAS;AAAA,EAChE;AACA,SAAO;AACT;AAEA,SAAS,8BAA8B,OAAyB;AAC9D,QAAM,OAAO,iBAAiB,OAAO,MAAM;AAC3C,MAAI,SAAS,cAAe,QAAO,mBAAmB,OAAO,oBAAI,IAAI,CAAC;AACtE,QAAM,OAAO;AAAA,IACX;AAAA,IACA,oBAAI,IAAI;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACA,MAAI,cAAc,IAAI,KAAK,KAAK,cAAc,QAAW;AACvD,SAAK,YAAY,yBAAyB,KAAK,SAAS;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,SAAS,yBAAyB,OAAyB;AACzD,SAAO;AAAA,IACL;AAAA,IACA,oBAAI,IAAI;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,SAAS,2BAA2B,OAAyB;AAC3D,QAAM,UAAU,mBAAmB,OAAO,oBAAI,IAAI,CAAC,OAAO,CAAC,CAAC;AAC5D,MAAI,cAAc,OAAO,KAAK,QAAQ,UAAU,QAAW;AACzD,YAAQ,QAAQ,eAAe,QAAQ,OAAO,6BAA6B;AAAA,EAC7E;AACA,SAAO;AACT;AAEA,SAAS,uBAAuB,OAAyB;AACvD,SAAO;AAAA,IACL;AAAA,IACA,oBAAI,IAAI;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,SAAS,mBAAmB,OAAgB,UAAwC;AAClF,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,gBAAY,OAAO,eAAe,KAAK;AACvC,WAAO,QAAQ,QAAQ,KAAK;AAAA,EAC9B,SAAS,OAAO;AACd,UAAM,IAAI,mBAAmB,oBAAoB,KAAK;AAAA,EACxD;AACA,MAAI,cAAc,OAAO,aAAa,cAAc,KAAM,QAAO;AACjE,MAAI,KAAK,SAAS,8BAA8B;AAC9C,UAAM,IAAI,mBAAmB,WAAW;AAAA,EAC1C;AACA,QAAM,OAAO,uBAAO,OAAO,IAAI;AAC/B,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,QAAQ,SAAU,OAAM,IAAI,mBAAmB,iBAAiB;AAC3E,UAAM,aAAa,OAAO,yBAAyB,OAAO,GAAG;AAC7D,QAAI,CAAC,WAAY,OAAM,IAAI,mBAAmB,kBAAkB;AAChE,QAAI,SAAS,cAAc,SAAS,YAAY;AAC9C,YAAM,IAAI,mBAAmB,mBAAmB;AAAA,IAClD;AACA,QAAI,CAAC,WAAW,WAAY,OAAM,IAAI,mBAAmB,yBAAyB;AAClF,QAAI,SAAS,IAAI,GAAG,KAAK,WAAW,UAAU,OAAW;AACzD,SAAK,GAAG,IAAI,WAAW;AAAA,EACzB;AACA,SAAO;AACT;AAEA,SAAS,eACP,OACA,eACS;AACT,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,MAAI,OAAO,eAAe,KAAK,MAAM,MAAM,aAAa,MAAM,SAAS,8BAA8B;AACnG,WAAO;AAAA,EACT;AACA,QAAM,aAAwB,CAAC;AAC/B,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,aAAa,OAAO,yBAAyB,OAAO,OAAO,KAAK,CAAC;AACvE,QAAI,CAAC,cAAc,SAAS,cAAc,SAAS,YAAY;AAC7D,YAAM,IAAI,mBAAmB,aAAa,sBAAsB,cAAc;AAAA,IAChF;AACA,eAAW,KAAK,cAAc,WAAW,KAAK,CAAC;AAAA,EACjD;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAgB,KAAsB;AAC9D,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,aAAa,OAAO,yBAAyB,OAAO,GAAG;AAC7D,MAAI,CAAC,cAAc,SAAS,cAAc,SAAS,WAAY,QAAO;AACtE,SAAO,WAAW;AACpB;AAEA,SAAS,iBAAiB,OAAqD;AAC7E,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,UAAU;AAChB,MAAI,CAAC,YAAY,SAAS,kBAAkB,EAAG,QAAO;AACtD,SAAO,aAAa,QAAQ,SAAS,KACnC,aAAa,QAAQ,MAAM,MAC1B,QAAQ,SAAS,UAAU,QAAQ,cAAc,QAAQ,YACzD,QAAQ,SAAS,UAAU,QAAQ,SAAS,eAAe,QAAQ,SAAS,UAC3E,QAAQ,SAAS,WAAW,QAAQ,SAAS,YAC/C,cAAc,QAAQ,SAAS,0BAA0B,WAAW,IAAI,MACvE,QAAQ,UAAU,UAAa,MAAM,QAAQ,QAAQ,KAAK,KACvD,QAAQ,MAAM,UAAU,0BAA0B,gBAClD,QAAQ,MAAM,MAAM,aAAa,OACpC,QAAQ,cAAc,UAAa,MAAM,QAAQ,QAAQ,SAAS,KAC/D,QAAQ,UAAU,UAAU,0BAA0B,aACtD,QAAQ,UAAU,MAAM,UAAU,OACrC,QAAQ,gBAAgB,UAAa,MAAM,QAAQ,QAAQ,WAAW,KACnE,QAAQ,YAAY,UAAU,0BAA0B,eACxD,QAAQ,YAAY,MAAM,qBAAqB,OAClD,QAAQ,cAAc,UAAa,kBAAkB,QAAQ,SAAS,OACtE,QAAQ,sBAAsB,UAC7B,cAAc,QAAQ,mBAAmB,0BAA0B,WAAW,IAAI,OACnF,QAAQ,gBAAgB,UAAa,sBAAsB,QAAQ,aAAa,KAAK,OACrF,QAAQ,WAAW,UAAa,OAAO,QAAQ,WAAW,eAC1D,QAAQ,aAAa,UAAa,QAAQ,aAAa,QACtD,OAAO,QAAQ,aAAa,YAAY,OAAO,cAAc,QAAQ,QAAQ,KAC3E,QAAQ,YAAY,OACvB,QAAQ,aAAa,UAAa,oBAAoB,QAAQ,QAAQ;AAC3E;AAEA,SAAS,oBAAoB,OAAyB;AACpD,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,UAAU;AAChB,SAAO,YAAY,SAAS,CAAC,UAAU,WAAW,OAAO,CAAC,KACxD,aAAa,QAAQ,MAAM,KAC3B,cAAc,QAAQ,SAAS,0BAA0B,WAAW,IAAI,MACvE,QAAQ,UAAU,UAAa,MAAM,QAAQ,QAAQ,KAAK,KACvD,QAAQ,MAAM,UAAU,0BAA0B,gBAClD,QAAQ,MAAM,MAAM,UAAQ,cAAc,IAAI,KAAK,KAAK,SAAS,YAAY;AACrF;AAEA,SAAS,gBAAgB,OAA0D;AACjF,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,QAAQ;AACd,QAAM,UAAU,oBAAI,IAAI,CAAC,SAAS,gBAAgB,iBAAiB,mBAAmB,eAAe,CAAC;AACtG,MAAI,OAAO,KAAK,KAAK,EAAE,WAAW,KAAK,OAAO,KAAK,KAAK,EAAE,KAAK,SAAO,CAAC,QAAQ,IAAI,GAAG,CAAC,EAAG,QAAO;AACjG,MACE,MAAM,UAAU,UAChB,CAAC,cAAc,MAAM,OAAO,0BAA0B,YAAY,IAAI,EACtE,QAAO;AACT,MAAI,MAAM,iBAAiB,UAAa,CAAC,aAAa,MAAM,YAAY,EAAG,QAAO;AAClF,MAAI,MAAM,kBAAkB,UAAa,CAAC,oBAAoB,MAAM,aAAa,EAAG,QAAO;AAC3F,MAAI,MAAM,oBAAoB,UAAa,OAAO,MAAM,oBAAoB,UAAW,QAAO;AAC9F,MAAI,MAAM,kBAAkB,UAAa,MAAM,kBAAkB,MAAM;AACrE,QAAI,CAAC,cAAc,MAAM,aAAa,EAAG,QAAO;AAChD,UAAM,SAAS,MAAM;AACrB,QACE,CAAC,YAAY,QAAQ,CAAC,aAAa,YAAY,UAAU,CAAC,KAC1D,CAAC,sBAAsB,OAAO,WAAW,KAAK,KAC9C,CAAC,sBAAsB,OAAO,UAAU,KAAK,KAC7C,CAAC,sBAAsB,OAAO,UAAU,KAAK,EAC7C,QAAO;AAAA,EACX;AACA,SAAO;AACT;AAEA,SAAS,cAAc,OAAkD;AACvE,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,YAAY,OAAO,eAAe,KAAK;AAC7C,SAAO,cAAc,OAAO,aAAa,cAAc;AACzD;AAEA,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,YAAY,OAAgC,SAAqC;AACxF,QAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,SAAO,OAAO,KAAK,KAAK,EAAE,MAAM,SAAO,KAAK,IAAI,GAAG,CAAC;AACtD;AAEA,SAAS,sBAAsB,OAAyB;AACtD,MAAI,CAAC,cAAc,KAAK,KAAK,CAAC,YAAY,OAAO,CAAC,eAAe,YAAY,YAAY,MAAM,CAAC,GAAG;AACjG,WAAO;AAAA,EACT;AACA,SAAO,OAAO,MAAM,gBAAgB,YAClC,gCAAgC,KAAK,MAAM,WAAW,KACtD,eAAe,MAAM,QAAQ,KAAK,eAAe,MAAM,QAAQ,KAC/D,OAAO,MAAM,SAAS,YAAY,OAAO,cAAc,MAAM,IAAI,KAAK,MAAM,QAAQ,KACpF,MAAM,QAAQ,0BAA0B;AAC5C;AAEA,SAAS,WAAW,OAAyB;AAC3C,SAAO,cAAc,KAAK,KAAK,YAAY,OAAO,CAAC,MAAM,YAAY,WAAW,CAAC,KAC/E,aAAa,MAAM,EAAE,KAAK,WAAW,MAAM,QAAQ,KACnD,OAAO,OAAO,OAAO,WAAW,KAAK,sBAAsB,MAAM,SAAS;AAC9E;AAEA,SAAS,kBAAkB,OAAyB;AAClD,MACE,CAAC,cAAc,KAAK,KAAK,CAAC,YAAY,OAAO;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,EACD,QAAO;AACT,MAAI,MAAM,SAAS,eAAe,MAAM,SAAS,sBAAsB,MAAM,SAAS,QAAQ;AAC5F,WAAO;AAAA,EACT;AACA,MACE,CAAC,CAAC,SAAS,kBAAkB,aAAa,UAAU,iBAAiB,EAClE,MAAM,SAAO,MAAM,GAAG,MAAM,UAAa,aAAa,MAAM,GAAG,CAAC,CAAC,KACpE,MAAM,YAAY,UAChB,CAAC,cAAc,MAAM,SAAS,0BAA0B,gBAAgB,KAAK,EAC/E,QAAO;AACT,MACE,MAAM,aAAa,WAClB,OAAO,MAAM,aAAa,YAAY,CAAC,OAAO,cAAc,MAAM,QAAQ,GAC3E,QAAO;AACT,MAAI,MAAM,SAAS,aAAa;AAC9B,WAAO,MAAM,UAAU,UAAa,MAAM,mBAAmB;AAAA,EAC/D;AACA,MAAI,MAAM,SAAS,mBAAoB,QAAO,MAAM,cAAc;AAClE,SAAO,MAAM,YAAY;AAC3B;AAEA,SAAS,cAAc,OAA0C;AAC/D,MAAI,CAAC,cAAc,KAAK,KAAK,OAAO,MAAM,SAAS,SAAU,QAAO;AACpE,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,MAAM,CAAC,KACxC,cAAc,MAAM,MAAM,0BAA0B,WAAW,IAAI;AAAA,IACvE,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,cAAc,YAAY,WAAW,CAAC,KACvE,aAAa,MAAM,UAAU,KAAK,WAAW,MAAM,QAAQ,KAC3D,OAAO,OAAO,OAAO,WAAW,KAAK,sBAAsB,MAAM,SAAS;AAAA,IAC9E,KAAK;AACH,aAAO,YAAY,OAAO,CAAC,QAAQ,YAAY,CAAC,KAAK,sBAAsB,MAAM,UAAU;AAAA,IAC7F,KAAK;AACH,aAAO,YAAY,OAAO;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,MAAM,MAAM,eAAe,UAAa,aAAa,MAAM,UAAU,MACpE,WAAW,MAAM,QAAQ,KACzB,cAAc,MAAM,QAAQ,0BAA0B,WAAW,IAAI,MACpE,MAAM,eAAe,UAAa,sBAAsB,MAAM,UAAU,OACxE,MAAM,YAAY,UAAa,OAAO,MAAM,YAAY,eACxD,MAAM,YAAY,UAAa,sBAAsB,MAAM,OAAO,OAClE,MAAM,cAAc,UAAa,kBAAkB,MAAM,SAAS;AAAA,IACvE;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,sCAAsC,UAAgD;AAC7F,QAAM,OAAO;AAAA,IACX,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACA,MAAI,KAAK,KAAK,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,0BAA0B,iBAAiB,GAAG;AAC3F,WAAO;AAAA,EACT;AACA,MAAI,KAAK,KAAK,SAAO,OAAO,KAAK,GAAG,EAAE,KAAK,SAAO,CAAC,aAAa,GAAG,CAAC,CAAC,EAAG,QAAO;AAC/E,SAAO,SAAS,2BAA2B,MAAM,YAAY,KAAK;AACpE;AAEA,SAAS,aAAa,OAAiC;AACrD,SAAO,cAAc,OAAO,0BAA0B,iBAAiB,KAAK,KAC1E,CAAC,gBAAgB,KAAK;AAC1B;AAEA,SAAS,WAAW,OAAiC;AACnD,SAAO,cAAc,OAAO,0BAA0B,mBAAmB,KAAK,KAC5E,CAAC,gBAAgB,KAAK;AAC1B;AAEA,SAAS,sBAAsB,OAAgB,YAAsC;AACnF,SAAO,cAAc,OAAO,0BAA0B,mBAAmB,UAAU,KACjF,CAAC,gBAAgB,KAAK;AAC1B;AAEA,SAAS,cAAc,OAAgB,UAAkB,YAAsC;AAC7F,SAAO,OAAO,UAAU,aAAa,cAAc,MAAM,SAAS,MAChE,YAAY,OAAO,KAAK,EAAE,cAAc;AAC5C;AAEA,SAAS,eAAe,OAAiC;AACvD,SAAO,cAAc,OAAO,0BAA0B,eAAe,KAAK,KACxE,UAAU,OAAO,UAAU,QAAQ,CAAC,gBAAgB,KAAK,KACzD,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,SAAS,IAAI;AAChD;AAEA,SAAS,eAAe,OAAiC;AACvD,SAAO,cAAc,OAAO,0BAA0B,eAAe,KAAK,KACxE,kBAAkB,KAAK,KAAK;AAChC;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,WAAW,MAAM,WAAW,KAAK;AACvC,QAAI,WAAW,MAAQ,aAAa,IAAM,QAAO;AAAA,EACnD;AACA,SAAO;AACT;AAOA,SAAS,oBAAoB,OAAkD;AAC7E,SAAO,cAAc,KAAK,KAAK,sBAAsB,KAAK;AAC5D;AAEA,SAAS,sBACP,OACA,QAAQ,GACR,QAAqC,EAAE,QAAQ,oBAAI,QAAQ,GAAG,OAAO,EAAE,GAC9D;AACT,QAAM,SAAS;AACf,MAAI,MAAM,QAAQ,gCAAgC,QAAQ,0BAA0B,eAAe;AACjG,WAAO;AAAA,EACT;AACA,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAW,QAAO;AACzD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,cAAc,OAAO,0BAA0B,qBAAqB,IAAI;AAAA,EACjF;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,OAAO,SAAS,KAAK,MAAM,CAAC,OAAO,UAAU,KAAK,KAAK,OAAO,cAAc,KAAK;AAAA,EAC1F;AACA,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,MAAM,OAAO,IAAI,KAAK,EAAG,QAAO;AACpC,QAAM,OAAO,IAAI,KAAK;AACtB,MAAI,QAAQ;AACZ,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAQ,OAAO,eAAe,KAAK,MAAM,MAAM,aAC7C,MAAM,UAAU,0BAA0B,sBAC1C,MAAM,MAAM,UAAQ,sBAAsB,MAAM,QAAQ,GAAG,KAAK,CAAC;AAAA,EACrE,WAAW,cAAc,KAAK,GAAG;AAC/B,UAAM,OAAO,QAAQ,QAAQ,KAAK;AAClC,YAAQ,KAAK,UAAU,0BAA0B,yBAAyB,KAAK,MAAM,SAAO;AAC1F,UACE,OAAO,QAAQ,YACf,CAAC,cAAc,KAAK,0BAA0B,kBAAkB,KAAK,EACrE,QAAO;AACT,YAAM,aAAa,OAAO,yBAAyB,OAAO,GAAG;AAC7D,aAAO,eAAe,UAAa,WAAW,cAC5C,EAAE,SAAS,eAAe,EAAE,SAAS,eACrC,sBAAsB,WAAW,OAAO,QAAQ,GAAG,KAAK;AAAA,IAC5D,CAAC;AAAA,EACH;AACA,QAAM,OAAO,OAAO,KAAK;AACzB,SAAO;AACT;;;ACrwBO,IAAM,wBAAwB,OAAO;AAAA,EAC1C;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAIO,IAAM,+BAA+B,OAAO;AAAA,EACjD;AAAA,IACE,WAAW;AAAA,IACX,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,wBAAwB;AAAA,IACxB,iBAAiB;AAAA,IACjB,uBAAuB;AAAA,IACvB,gCAAgC;AAAA,IAChC,sBAAsB;AAAA,IACtB,cAAc;AAAA,IACd,oBAAoB;AAAA,IACpB,qBAAqB;AAAA,IACrB,sBAAsB;AAAA,IACtB,0BAA0B;AAAA,IAC1B,qBAAqB;AAAA,IACrB,4BAA4B;AAAA,IAC5B,2BAA2B;AAAA,IAC3B,yBAAyB;AAAA,IACzB,UAAU;AAAA,EACZ;AACF;AAIO,IAAM,oCAAoC,OAAO;AAAA,EACtD;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AA4CO,IAAM,yBAAyB,OAAO;AAAA,EAC3C;AAAA,IACE,eAAe;AAAA,IACf,UAAU;AAAA,IACV,UAAU;AAAA,IACV,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,sBAAsB;AAAA,EACxB;AACF;AAEO,IAAM,+BAAN,cAA2C,MAAM;AAAA,EACtD,cAAc;AACZ,UAAM,yBAAyB;AAC/B,SAAK,OAAO;AAAA,EACd;AACF;AAwBA,IAAM,2BAA2B,IAAI,IAAuB,qBAAqB;AACjF,IAAM,uCAAuC,IAAI;AAAA,EAC/C;AACF;AACA,IAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,0BAA0B,oBAAI,IAAI;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,eACJ;AACF,IAAM,iBAAiB;AACvB,IAAM,gBAAgB;AACtB,IAAM,cAAc,IAAI,YAAY;AACpC,IAAI,qBAAqB;AAQzB,SAAS,uBAA8B;AACrC,QAAM,IAAI,6BAA6B;AACzC;AAEA,SAAS,qBACP,OACA,OACA,OACyB;AACzB,MACE,UAAU,QACV,OAAO,UAAU,YACjB,MAAM,QAAQ,KAAK,KACnB,QAAQ,uBAAuB,SAC/B,sBAAqB;AACvB,QAAM,YAAY,OAAO,eAAe,KAAK;AAC7C,MAAI,cAAc,OAAO,aAAa,cAAc,KAAM,sBAAqB;AAC/E,MAAI,MAAM,KAAK,IAAI,KAAK,EAAG,sBAAqB;AAChD,QAAM,SAAS;AACf,MAAI,MAAM,QAAQ,uBAAuB,SAAU,sBAAqB;AACxE,QAAM,KAAK,IAAI,KAAK;AACpB,QAAM,OAAO,QAAQ,QAAQ,KAAK;AAClC,QAAM,cAAc,KAAK;AACzB,MAAI,MAAM,aAAa,uBAAuB,cAAe,sBAAqB;AAClF,QAAM,SAAkC,CAAC;AACzC,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,QAAQ,SAAU,sBAAqB;AAClD,UAAM,aAAa,OAAO,yBAAyB,OAAO,GAAG;AAC7D,QAAI,CAAC,YAAY,cAAc,EAAE,WAAW,YAAa,sBAAqB;AAC9E,WAAO,GAAG,IAAI,WAAW;AAAA,EAC3B;AACA,SAAO;AACT;AAEA,SAAS,UAAU,QAAiC,SAAoC;AACtF,MAAI,OAAO,KAAK,MAAM,EAAE,KAAK,SAAO,CAAC,QAAQ,IAAI,GAAG,CAAC,EAAG,sBAAqB;AAC/E;AAEA,SAAS,gBACP,OACA,cACA,UAAoC,CAAC,GACpB;AACjB,SAAO,OAAO,UAAU,YACtB,MAAM,SAAS,KACf,MAAM,KAAK,MAAM,SACjB,YAAY,OAAO,KAAK,EAAE,cAAc,gBACxC,CAAC,oBAAoB,KAAK,KAC1B,CAAC,eAAe,KAAK,KAAK,KAC1B,CAAC,aAAa,KAAK,KAAK,MACvB,CAAC,QAAQ,cAAc,cAAc,KAAK,KAAK;AACpD;AAEA,SAAS,oBAAoB,OAAwB;AACnD,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,MAAQ,SAAS,IAAM,QAAO;AAAA,EAC5C;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAiC;AACzD,SAAO,OAAO,UAAU,YACtB,OAAO,SAAS,KAAK,KACrB,KAAK,IAAI,KAAK,KAAK,OAAO;AAC9B;AAEA,SAAS,+BACP,OACuC;AACvC,SAAO,qCAAqC,IAAI,KAAqC;AACvF;AAEA,SAAS,6CACP,OACA,OAC2D;AAC3D,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,QAAQ,qBAAqB,OAAO,OAAO,CAAC;AAClD,YAAU,OAAO,uBAAuB;AACxC,MACE,MAAM,eAAe,UACnB,CAAC,gBAAgB,MAAM,YAAY,uBAAuB,kBAAkB,KAC9E,MAAM,YAAY,UAChB,CAAC,gBAAgB,MAAM,SAAS,uBAAuB,kBAAkB,KAC3E,MAAM,iBAAiB,UAAa,CAAC,+BAA+B,MAAM,YAAY,KACtF,MAAM,iBAAiB,WACpB,CAAC,iBAAiB,MAAM,YAAY,KAAK,MAAM,eAAe,MACjE,MAAM,cAAc,WACjB,CAAC,iBAAiB,MAAM,SAAS,KAAK,MAAM,YAAY,MAC3D,MAAM,UAAU,WAAc,CAAC,iBAAiB,MAAM,KAAK,KAAK,MAAM,QAAQ,MAC9E,MAAM,uBAAuB,UAC3B,CAAC,gBAAgB,MAAM,oBAAoB,uBAAuB,kBAAkB,KACtF,MAAM,sBAAsB,WACzB,CAAC,iBAAiB,MAAM,iBAAiB,KACxC,CAAC,OAAO,cAAc,MAAM,iBAAiB,KAAK,MAAM,oBAAoB,MAChF,MAAM,sBAAsB,WACzB,CAAC,iBAAiB,MAAM,iBAAiB,KACxC,CAAC,OAAO,cAAc,MAAM,iBAAiB,KAAK,MAAM,oBAAoB,GAChF,sBAAqB;AACvB,QAAM,aAAkD,CAAC;AACzD,MAAI,OAAO,MAAM,eAAe,SAAU,YAAW,aAAa,MAAM;AACxE,MAAI,OAAO,MAAM,YAAY,SAAU,YAAW,UAAU,MAAM;AAClE,MAAI,+BAA+B,MAAM,YAAY,GAAG;AACtD,eAAW,eAAe,MAAM;AAAA,EAClC;AACA,MAAI,OAAO,MAAM,iBAAiB,SAAU,YAAW,eAAe,MAAM;AAC5E,MAAI,OAAO,MAAM,cAAc,SAAU,YAAW,YAAY,MAAM;AACtE,MAAI,OAAO,MAAM,UAAU,SAAU,YAAW,QAAQ,MAAM;AAC9D,MAAI,OAAO,MAAM,uBAAuB,UAAU;AAChD,eAAW,qBAAqB,MAAM;AAAA,EACxC;AACA,MAAI,OAAO,MAAM,sBAAsB,UAAU;AAC/C,eAAW,oBAAoB,MAAM;AAAA,EACvC;AACA,MAAI,OAAO,MAAM,sBAAsB,UAAU;AAC/C,eAAW,oBAAoB,MAAM;AAAA,EACvC;AACA,SAAO,OAAO,OAAO,UAAU;AACjC;AAGO,SAAS,uBAAuB,OAA+B;AACpE,QAAM,QAA6B,EAAE,MAAM,oBAAI,IAAI,GAAG,OAAO,GAAG,YAAY,EAAE;AAC9E,QAAM,QAAQ,qBAAqB,OAAO,OAAO,CAAC;AAClD,YAAU,OAAO,eAAe;AAChC,MACE,CAAC,yBAAyB,IAAI,MAAM,IAAyB,KAC7D,MAAM,eAAe,6BAA6B,MAAM,IAAyB,KACjF,OAAO,MAAM,cAAc,aAC3B,CAAC;AAAA,IACC,MAAM;AAAA,IACN,uBAAuB;AAAA,IACvB,EAAE,YAAY,KAAK;AAAA,EACrB,KACA,MAAM,eAAe,UACnB,CAAC,gBAAgB,MAAM,YAAY,uBAAuB,kBAAkB,KAC9E,MAAM,YAAY,UAChB,CAAC,gBAAgB,MAAM,SAAS,uBAAuB,kBAAkB,EAC3E,sBAAqB;AACvB,QAAM,sBAAsB;AAAA,IAC1B,MAAM;AAAA,IACN;AAAA,EACF;AACA,QAAM,gBAAgB,oCAAoC,MAAM,eAAe,KAAK;AACpF,MACE,qBAAqB,eAAe,UAClC,oBAAoB,eAAe,MAAM,cAC3C,qBAAqB,YAAY,UAAa,oBAAoB,YAAY,MAAM,WACpF,eAAe,SAAS,UACtB,cAAc,SAAS,aAAa,cAAc,eAAe,MAAM,cACzE,eAAe,SAAS,WAAW,cAAc,YAAY,MAAM,WACnE,eAAe,SAAS,cACtB,qBAAqB,iBAAiB,UACtC,oBAAoB,iBAAiB,cAAc,MACrD,sBAAqB;AACvB,QAAM,aAA4B;AAAA,IAChC,MAAM,MAAM;AAAA,IACZ,YAAY,MAAM;AAAA,IAClB,WAAW,MAAM;AAAA,IACjB,cAAc,MAAM;AAAA,EACtB;AACA,MAAI,OAAO,MAAM,eAAe,SAAU,YAAW,aAAa,MAAM;AACxE,MAAI,OAAO,MAAM,YAAY,SAAU,YAAW,UAAU,MAAM;AAClE,MAAI,oBAAqB,YAAW,kBAAkB;AACtD,MAAI,cAAe,YAAW,gBAAgB;AAC9C,MAAI,YAAY,OAAO,KAAK,UAAU,UAAU,CAAC,EAAE,aAAa,uBAAuB,eAAe;AACpG,yBAAqB;AAAA,EACvB;AACA,SAAO,OAAO,OAAO,UAAU;AACjC;AAEA,SAAS,oCACP,OACA,OACwC;AACxC,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,SAAS,qBAAqB,OAAO,OAAO,CAAC;AACnD,MACE,OAAO,SAAS,cAChB,gBAAgB,OAAO,YAAY,uBAAuB,kBAAkB,KAC5E,+BAA+B,OAAO,KAAK,KAC3C,OAAO,KAAK,MAAM,EAAE;AAAA,IAClB,SAAO,QAAQ,UAAU,QAAQ,gBAAgB,QAAQ;AAAA,EAC3D,GACA;AACA,WAAO,OAAO,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,YAAY,OAAO;AAAA,MACnB,OAAO,OAAO;AAAA,IAChB,CAAC;AAAA,EACH;AACA,MACE,OAAO,SAAS,WAChB,gBAAgB,OAAO,YAAY,uBAAuB,kBAAkB,KAC5E,gBAAgB,OAAO,SAAS,uBAAuB,kBAAkB,KACzE,OAAO,KAAK,MAAM,EAAE,MAAM,SAAO,QAAQ,UAAU,QAAQ,gBAAgB,QAAQ,SAAS,GAC5F;AACA,WAAO,OAAO,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,YAAY,OAAO;AAAA,MACnB,SAAS,OAAO;AAAA,IAClB,CAAC;AAAA,EACH;AACA,MACE,OAAO,SAAS,cACf,OAAO,YAAY,WAAW,OAAO,YAAY,aAAa,OAAO,YAAY,cAClF,OAAO,KAAK,MAAM,EAAE,MAAM,SAAO,QAAQ,UAAU,QAAQ,SAAS,EACpE,QAAO,OAAO,OAAO,EAAE,MAAM,WAAoB,SAAS,OAAO,QAAQ,CAAC;AAC5E,SAAO,qBAAqB;AAC9B;AAgBO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAChC;AAAA,EAET,YAAY,eAA8B;AACxC,UAAM,aAAa,uBAAuB,aAAa;AACvD,UAAM,WAAW,IAAI;AACrB,SAAK,OAAO;AACZ,SAAK,gBAAgB;AAAA,EACvB;AACF;AAuBO,SAAS,6BAAqC;AACnD,MAAI;AACF,QAAI,OAAO,WAAW,QAAQ,eAAe,YAAY;AACvD,aAAO,SAAS,WAAW,OAAO,WAAW,CAAC;AAAA,IAChD;AAAA,EACF,QAAQ;AAAA,EAER;AACA,wBAAsB,qBAAqB,KAAK,OAAO;AACvD,SAAO,SAAS,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,mBAAmB,SAAS,EAAE,CAAC;AAC5E;AAMO,SAAS,oBAAoB,OAAgD;AAClF,QAAM,QAA6B,EAAE,MAAM,oBAAI,IAAI,GAAG,OAAO,GAAG,YAAY,EAAE;AAC9E,QAAM,kBAAkB,qBAAqB,OAAO,OAAO,CAAC;AAC5D,YAAU,iBAAiB,eAAe;AAC1C,SAAO,uBAAuB;AAAA,IAC5B,GAAG;AAAA,IACH,cAAc,gBAAgB,gBAAgB,2BAA2B;AAAA,EAC3E,CAAC;AACH;;;ACncO,IAAM,wCAAwC,OAAO;AAAA,EAC1D;AAAA,IACE,uBAAuB,MAAM;AAAA,IAC7B,qBAAqB,MAAM;AAAA,IAC3B,qBAAqB,MAAM;AAAA,EAC7B;AACF;AAEO,IAAM,4BAA4B,OAAO;AAAA,EAC9C;AAAA,IACE,cAAc,MAAM;AAAA,IACpB,GAAG;AAAA,EACL;AACF;AAIO,IAAM,6BAAN,cAAyC,gBAAgB;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,MAAiC,gBAAwB,YAAoB;AAC9F,UAAM,oBAAoB;AAAA,MACxB,MAAM;AAAA,MACN,YAAY,6BAA6B;AAAA,MACzC,WAAW;AAAA,MACX,iBAAiB,EAAE,WAAW,gBAAgB,OAAO,WAAW;AAAA,IAClE,CAAC,CAAC;AACF,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,iBAAiB;AACtB,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,SAAS,0CAA0C,SAA6C;AACrG,MAAI,OAAO,YAAY,SAAU,OAAM,IAAI,MAAM,oCAAoC;AACrF,QAAM,eAAe,IAAI,YAAY,EAAE,OAAO,OAAO,EAAE;AACvD,MAAI,eAAe,0BAA0B,cAAc;AACzD,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,0BAA0B;AAAA,IAC5B;AAAA,EACF;AACF;AAuPO,SAAS,sCAAsC,OAA6B;AACjF,QAAM,oBAAoB,+CAA+C,KAAK;AAC9E,MAAI,kBAAkB,SAAS,UAAU,kBAAkB,cAAc,kBAAkB,QAAQ;AACjG,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AACA,4CAA0C,kBAAkB,OAAO;AACnE,SAAO;AACT;AAGO,SAAS,+CAA+C,OAA6B;AAG1F,qBAAmB,OAAO;AAAA,IACxB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,EACtB,CAAC;AACD,uCAAqC,KAAK;AAC1C,QAAM,kBAAkB,oCAAoC,2BAA2B,KAAK,CAAC;AAC7F,MAAI,gBAAgB,SAAS,UAAW,OAAM,IAAI,MAAM,8CAA8C;AACtG,QAAM,oBAAoB,2BAA2B,eAAe;AACpE,QAAM,eAAe,mBAAmB,mBAAmB;AAAA,IACzD,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,EACtB,CAAC,EAAE;AACH,MAAI,eAAe,0BAA0B,uBAAuB;AAClE,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,0BAA0B;AAAA,IAC5B;AAAA,EACF;AACA,QAAM,aAAa,gCAAgC,eAAe,EAAE;AACpE,MAAI,aAAa,0BAA0B,qBAAqB;AAC9D,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA,0BAA0B;AAAA,IAC5B;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,mCAAmC,OAA8C;AAC/F,wCAAsC,KAAK;AAC7C;AAEO,SAAS,4CAA4C,OAA8C;AACxG,iDAA+C,KAAK;AACtD;;;AC5WO,IAAM,gCAAgC,OAAO;AAAA,EAClD;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AACF;AAEO,IAAM,2BAA2B,OAAO;AAAA,EAC7C;AAAA,IACE,YAAY,KAAK,OAAQ;AAAA,IACzB,YAAY,IAAI,OAAQ;AAAA,IACxB,uBAAuB,IAAI,OAAQ;AAAA,IACnC,sBAAsB;AAAA,IACtB,oBAAoB;AAAA,IACpB,oBAAoB;AAAA,EACtB;AACF;AAEO,IAAM,mCAAmC;AA8EzC,IAAM,gCAAN,cAA4C,MAAM;AAAA,EAGvD,YAAqB,OAAe;AAClC,UAAM,6BAA6B,KAAK,EAAE;AADvB;AAEnB,SAAK,OAAO;AAAA,EACd;AAAA,EALS,OAAO;AAMlB;AAGO,IAAM,gCAAN,cAA4C,MAAM;AAAA,EAGvD,YACW,OACA,WACT;AACA,UAAM,qBAAqB,KAAK,+CAA+C;AAHtE;AACA;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EARS,OAAO;AASlB;AAqEO,SAAS,gCACd,SACA;AACA,iBAAe,QACb,QACA,YACA,cAA8C,CAAC,GACN;AACzC,gBAAY,QAAQ,eAAe;AACnC,qCAAiC,QAAQ,UAAU;AACnD,QAAI,WAAW,8BAA8B,OAAO;AAClD,YAAM,4BAA4B,UAA0C;AAAA,IAC9E;AACA,gBAAY,QAAQ,eAAe;AACnC,UAAM,MAAM,MAAM,QAAQ,KAAK,QAAQ,YAAY,WAAW;AAC9D,UAAM,WAAW,iCAAiC,QAAQ,GAAG;AAC7D,iDAA6C,QAAQ,YAAY,QAAQ;AACzE,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,OAAO,CACL,YACA,cAA8C,CAAC,MAC5C,QAAQ,8BAA8B,OAAO,YAAY,WAAW;AAAA,IACzE,OAAO,CACL,YACA,cAA8C,CAAC,MAC5C,QAAQ,8BAA8B,OAAO,YAAY,WAAW;AAAA,IACzE,QAAQ,CACN,YACA,cAA8C,CAAC,MAC5C,QAAQ,8BAA8B,QAAQ,YAAY,WAAW;AAAA,EAC5E;AACF;AAKO,SAAS,iCACd,QACA,OACgD;AAChD,QAAM,SAAS,SAAS,OAAO,SAAS;AACxC,0BAAwB,QAAQ,SAAS;AACzC,UAAQ,QAAQ;AAAA,IACd,KAAK,8BAA8B;AACjC,MAAAA,iBAAgB,QAAQ;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,iBAAW,OAAO,UAAU,oBAAoB,yBAAyB,kBAAkB;AAC3F,iBAAW,OAAO,UAAU,oBAAoB,yBAAyB,kBAAkB;AAC3F,oBAAc,OAAO,YAAY,sBAAsB,GAAG,yBAAyB,UAAU;AAC7F;AAAA,IACF,KAAK,8BAA8B,OAAO;AACxC,MAAAA,iBAAgB,QAAQ;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,uBAAiB,OAAO,UAAU,kBAAkB;AACpD,oBAAc,OAAO,QAAQ,kBAAkB,GAAG,yBAAyB,UAAU;AACrF,oBAAc,OAAO,YAAY,sBAAsB,GAAG,yBAAyB,UAAU;AAC7F,UACE,OAAO,SAAS,OAAO,aACrB,yBAAyB,WAC3B,MAAK,gBAAgB;AACvB,UAAI,OAAO,aAAa,SAAU,MAAK,kBAAkB;AACzD,UAAI,OAAO,OAAO,SAAS,SAAU,MAAK,cAAc;AACxD,YAAM,QAAQ,8BAA8B,OAAO,IAAI;AACvD,UAAI,MAAM,eAAe,OAAO,WAAY,MAAK,oBAAoB;AACrE,UAAI,OAAO,WAAW,OAAW,cAAa,OAAO,QAAQ,gBAAgB;AAC7E;AAAA,IACF;AAAA,IACA,KAAK,8BAA8B;AACjC,MAAAA,iBAAgB,QAAQ;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,uBAAiB,OAAO,UAAU,kBAAkB;AACpD,oBAAc,OAAO,MAAM,gBAAgB,GAAG,yBAAyB,UAAU;AACjF,mBAAa,OAAO,QAAQ,gBAAgB;AAC5C;AAAA,EACJ;AACF;AAGO,SAAS,iCACd,QACA,OACgC;AAChC,QAAM,SAAS,SAAS,OAAO,UAAU;AACzC,MAAI,OAAO,OAAO,KAAM,MAAK,aAAa;AAC1C,0BAAwB,QAAQ,UAAU;AAC1C,UAAQ,QAAQ;AAAA,IACd,KAAK,8BAA8B;AACjC,MAAAA,iBAAgB,QAAQ;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,UAAU;AACb,uBAAiB,OAAO,UAAU,mBAAmB;AACrD,oBAAc,OAAO,YAAY,uBAAuB,GAAG,yBAAyB,UAAU;AAC9F,oBAAc,OAAO,eAAe,0BAA0B,GAAG,yBAAyB,UAAU;AACpG;AAAA,IACF,KAAK,8BAA8B;AACjC,MAAAA,iBAAgB,QAAQ;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,UAAU;AACb,uBAAiB,OAAO,UAAU,mBAAmB;AACrD,oBAAc,OAAO,QAAQ,mBAAmB,GAAG,yBAAyB,UAAU;AACtF,oBAAc,OAAO,YAAY,uBAAuB,GAAG,yBAAyB,UAAU;AAC9F;AAAA,IACF,KAAK,8BAA8B;AACjC,MAAAA,iBAAgB,QAAQ;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,UAAU;AACb,uBAAiB,OAAO,UAAU,mBAAmB;AACrD,gCAA0B,OAAO,YAAY,qBAAqB;AAClE;AAAA,EACJ;AACA,SAAO;AACT;AAGO,SAAS,6CACd,QACA,SACA,UACM;AACN,MACE,SAAS,cAAc,QAAQ,aAC/B,SAAS,mBAAmB,QAAQ,eACpC,MAAK,UAAU;AACjB,UAAQ,QAAQ;AAAA,IACd,KAAK,8BAA8B,OAAO;AACxC,YAAM,eAAe;AACrB,YAAM,gBAAgB;AACtB,UAAI,cAAc,eAAe,aAAa,WAAY,MAAK,qBAAqB;AACpF;AAAA,IACF;AAAA,IACA,KAAK,8BAA8B,OAAO;AACxC,YAAM,eAAe;AACrB,YAAM,gBAAgB;AACtB,UACE,cAAc,aAAa,aAAa,YACxC,cAAc,WAAW,aAAa,UACtC,cAAc,eAAe,aAAa,WAC1C,MAAK,UAAU;AACjB;AAAA,IACF;AAAA,IACA,KAAK,8BAA8B,QAAQ;AACzC,YAAM,gBAAgB;AACtB,YAAM,iBAAiB;AACvB,UACE,eAAe,aAAa,cAAc,YAC1C,eAAe,WAAW,gBAAgB,cAAc,UACxD,eAAe,WAAW,SAAS,cAAc,KACjD,MAAK,qBAAqB;AAC5B;AAAA,IACF;AAAA,EACF;AACF;AAMA,eAAsB,4BACpB,SACqB;AACrB,mCAAiC,8BAA8B,OAAO,OAAO;AAC7E,QAAM,QAAQ,8BAA8B,QAAQ,IAAI;AACxD,MAAI,QAAQ,WAAW,UAAa,MAAM,4BAA4B,KAAK,MAAM,QAAQ,QAAQ;AAC/F,SAAK,gBAAgB;AAAA,EACvB;AACA,SAAO;AACT;AASA,eAAsB,kCACpB,OACuC;AACvC,QAAM,aAAa,gDAAgD,KAAK;AACxE,QAAM,OAAO;AAAA,IACX,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,yBAAyB;AAAA,IACzB;AAAA,EACF;AACA,QAAM,UAAwC;AAAA,IAC5C,WAAW,WAAW;AAAA,IACtB,gBAAgB,WAAW;AAAA,IAC3B,UAAU,WAAW;AAAA,IACrB,QAAQ,WAAW;AAAA,IACnB,YAAY,KAAK;AAAA,IACjB,UAAU;AAAA,IACV,MAAM,iCAAiC,IAAI;AAAA,IAC3C,GAAI,WAAW,gBACX,EAAE,QAAQ,MAAM,iCAAiC,IAAI,EAAE,IACvD,CAAC;AAAA,EACP;AACA,mCAAiC,8BAA8B,OAAO,OAAO;AAC7E,SAAO;AACT;AAGA,eAAsB,qCACpB,QACA,SACiB;AACjB,mCAAiC,QAAQ,OAAO;AAChD,QAAM,YAAY,WAAW,8BAA8B,QACvD,eAAe,OAAuC,IACtD,WAAW,8BAA8B,QACzC,eAAe,OAAuC,IACtD,gBAAgB,OAAwC;AAC5D,SAAO,4BAA4B,IAAI,YAAY,EAAE,OAAO,SAAS,CAAC;AACxE;AAGA,eAAsB,uCACpB,QACA,SACA,aAC4C;AAC5C,mBAAiB,aAAa,aAAa;AAC3C,SAAO;AAAA,IACL,OAAO,sBAAsB,MAAM;AAAA,IACnC;AAAA,IACA,gBAAgB,QAAQ;AAAA,IACxB,WAAW,QAAQ;AAAA,IACnB,aAAa,MAAM,qCAAqC,QAAQ,OAAO;AAAA,EACzE;AACF;AAGA,eAAsB,uCACpB,UACA,QACA,SACA,aACe;AACf,QAAM,OAAO,MAAM,uCAAuC,QAAQ,SAAS,WAAW;AACtF,MACE,SAAS,UAAU,KAAK,SACxB,SAAS,gBAAgB,KAAK,eAC9B,SAAS,mBAAmB,KAAK,kBACjC,SAAS,cAAc,KAAK,aAC5B,SAAS,gBAAgB,KAAK,aAC9B;AACA,UAAM,IAAI,8BAA8B,KAAK,OAAO,KAAK,SAAS;AAAA,EACpE;AACF;AAEA,eAAsB,4BAA4B,OAAoC;AACpF,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA,yBAAyB;AAAA,IACzB;AAAA,EACF;AACA,SAAO,iCAAiC,KAAK;AAC/C;AAEA,eAAe,iCAAiC,OAAiD;AAC/F,QAAM,SAAS,WAAW,QAAQ;AAClC,MAAI,CAAC,OAAQ,MAAK,oBAAoB;AACtC,QAAM,SAAS,IAAI,WAAW,MAAM,OAAO,OAAO,WAAW,KAAK,CAAC;AACnE,SAAO,UAAU,CAAC,GAAG,MAAM,EAAE,IAAI,UAAQ,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AACvF;AAGO,SAAS,8BAA8B,OAA2B;AACvE,MACE,MAAM,WAAW,KACjB,MAAM,SAAS,yBAAyB,yBACxC,MAAM,SAAS,MAAM,KACrB,CAAC,iEAAiE,KAAK,KAAK,EAC5E,MAAK,cAAc;AACrB,QAAM,UAAU,MAAM,SAAS,IAAI,IAAI,IAAI,MAAM,SAAS,GAAG,IAAI,IAAI;AACrE,QAAM,aAAc,MAAM,SAAS,IAAK,IAAI;AAC5C,MAAI,cAAc,KAAK,aAAa,yBAAyB,YAAY;AACvE,SAAK,cAAc;AAAA,EACrB;AACA,QAAM,SAAS,IAAI,WAAW,UAAU;AACxC,MAAI,cAAc;AAClB,WAAS,SAAS,GAAG,SAAS,MAAM,QAAQ,UAAU,GAAG;AACvD,UAAM,OAAQ,YAAY,MAAM,WAAW,MAAM,CAAC,KAAK,KACpD,YAAY,MAAM,WAAW,SAAS,CAAC,CAAC,KAAK,MAC7C,MAAM,SAAS,CAAC,MAAM,MAAM,IAAI,YAAY,MAAM,WAAW,SAAS,CAAC,CAAC,KAAK,MAC7E,MAAM,SAAS,CAAC,MAAM,MAAM,IAAI,YAAY,MAAM,WAAW,SAAS,CAAC,CAAC;AAC3E,QAAI,cAAc,WAAY,QAAO,aAAa,IAAK,SAAS,KAAM;AACtE,QAAI,cAAc,WAAY,QAAO,aAAa,IAAK,SAAS,IAAK;AACrE,QAAI,cAAc,WAAY,QAAO,aAAa,IAAI,OAAO;AAAA,EAC/D;AACA,MAAI,iCAAiC,MAAM,MAAM,MAAO,MAAK,cAAc;AAC3E,SAAO;AACT;AAGO,SAAS,8BAA8B,OAA2B;AACvE,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA,yBAAyB;AAAA,IACzB;AAAA,EACF;AACA,SAAO,iCAAiC,KAAK;AAC/C;AAEA,SAAS,iCAAiC,OAA2B;AACnE,QAAM,WAAW;AACjB,MAAI,UAAU;AACd,WAAS,SAAS,GAAG,SAAS,MAAM,QAAQ,UAAU,GAAG;AACvD,UAAM,YAAY,MAAM,SAAS;AACjC,UAAM,OAAQ,MAAM,MAAM,KAAK,MAC3B,YAAY,IAAI,MAAM,SAAS,CAAC,IAAI,MAAM,KAC3C,YAAY,IAAI,MAAM,SAAS,CAAC,IAAI;AACvC,eAAW,SAAU,SAAS,KAAM,EAAE;AACtC,eAAW,SAAU,SAAS,KAAM,EAAE;AACtC,eAAW,YAAY,IAAI,SAAU,SAAS,IAAK,EAAE,IAAI;AACzD,eAAW,YAAY,IAAI,SAAS,OAAO,EAAE,IAAI;AAAA,EACnD;AACA,SAAO;AACT;AAEA,SAAS,eAAe,SAA+C;AACrE,SAAO,KAAK,UAAU;AAAA,IACpB,QAAQ,8BAA8B;AAAA,IACtC,WAAW,QAAQ;AAAA,IACnB,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ;AAAA,IAClB,UAAU,QAAQ;AAAA,IAClB,YAAY,QAAQ;AAAA,EACtB,CAAC;AACH;AAEA,SAAS,eAAe,SAA+C;AACrE,SAAO,KAAK,UAAU;AAAA,IACpB,QAAQ,8BAA8B;AAAA,IACtC,WAAW,QAAQ;AAAA,IACnB,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ;AAAA,IAClB,QAAQ,QAAQ;AAAA,IAChB,YAAY,QAAQ;AAAA,IACpB,UAAU,QAAQ;AAAA,IAClB,MAAM,QAAQ;AAAA,IACd,GAAI,QAAQ,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;AAAA,EACnE,CAAC;AACH;AAEA,SAAS,gBAAgB,SAAgD;AACvE,SAAO,KAAK,UAAU;AAAA,IACpB,QAAQ,8BAA8B;AAAA,IACtC,WAAW,QAAQ;AAAA,IACnB,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ;AAAA,IAClB,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ;AAAA,EAClB,CAAC;AACH;AAEA,SAAS,sBAAsB,QAA0D;AACvF,MAAI,WAAW,8BAA8B,MAAO,QAAO;AAC3D,MAAI,WAAW,8BAA8B,MAAO,QAAO;AAC3D,SAAO;AACT;AAWA,SAAS,gDACP,OACkD;AAClD,QAAM,cAAc;AAAA,IAClB;AAAA,IACA,CAAC,aAAa,kBAAkB,YAAY,UAAU,MAAM;AAAA,IAC5D,CAAC,eAAe;AAAA,IAChB;AAAA,EACF;AACA,QAAM,YAAY,oBAAoB,aAAa,aAAa,mBAAmB;AACnF,QAAM,iBAAiB,oBAAoB,aAAa,kBAAkB,wBAAwB;AAClG,QAAM,WAAW,oBAAoB,aAAa,YAAY,kBAAkB;AAChF,QAAM,SAAS,oBAAoB,aAAa,UAAU,gBAAgB;AAC1E,QAAM,OAAO,oBAAoB,aAAa,QAAQ,cAAc;AACpE,QAAM,gBAAgB,OAAO,UAAU,eAAe,KAAK,aAAa,eAAe,IACnF,oBAAoB,aAAa,iBAAiB,uBAAuB,IACzE;AACJ,mBAAiB,WAAW,mBAAmB;AAC/C,mBAAiB,gBAAgB,wBAAwB;AACzD,mBAAiB,UAAU,kBAAkB;AAC7C,gBAAc,QAAQ,kBAAkB,GAAG,yBAAyB,UAAU;AAC9E,MAAI,OAAO,kBAAkB,UAAW,MAAK,uBAAuB;AACpE,SAAO,EAAE,WAAW,gBAAgB,UAAU,QAAQ,MAAM,cAAc;AAC5E;AAIA,SAAS,yBACP,OACA,UACA,UACA,OACqB;AACrB,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,MAAK,KAAK;AACnF,MAAI;AACJ,MAAI;AACF,UAAM,YAAY,OAAO,eAAe,KAAK;AAC7C,QAAI,CAAC,uBAAuB,SAAS,EAAG,MAAK,KAAK;AAClD,kBAAc,OAAO,0BAA0B,KAAK;AAAA,EACtD,SAAS,OAAO;AACd,QAAI,iBAAiB,8BAA+B,OAAM;AAC1D,SAAK,KAAK;AAAA,EACZ;AACA,QAAM,UAAU,oBAAI,IAAI,CAAC,GAAG,UAAU,GAAG,QAAQ,CAAC;AAClD,QAAM,OAAO,QAAQ,QAAQ,WAAW;AACxC,MACE,KAAK,KAAK,SAAO,OAAO,QAAQ,YAAY,CAAC,QAAQ,IAAI,GAAG,CAAC,KAC7D,SAAS,KAAK,SAAO,CAAC,OAAO,UAAU,eAAe,KAAK,aAAa,GAAG,CAAC,EAC5E,MAAK,KAAK;AACZ,aAAW,OAAO,MAAM;AACtB,UAAM,aAAa,YAAY,GAAG;AAClC,QAAI,CAAC,YAAY,cAAc,EAAE,WAAW,YAAa,MAAK,KAAK;AAAA,EACrE;AACA,SAAO;AACT;AAEA,SAAS,oBACP,aACA,KACA,OACS;AACT,QAAM,aAAa,YAAY,GAAG;AAClC,MAAI,CAAC,cAAc,EAAE,WAAW,YAAa,MAAK,KAAK;AACvD,SAAO,WAAW;AACpB;AAEA,SAAS,uBAAuB,WAAmC;AACjE,MAAI,cAAc,QAAQ,cAAc,OAAO,UAAW,QAAO;AACjE,MAAI;AACF,QAAI,OAAO,eAAe,SAAS,MAAM,KAAM,QAAO;AACtD,UAAM,cAAc,OAAO,yBAAyB,WAAW,aAAa;AAC5E,UAAM,mBAA4B,eAAe,WAAW,cACxD,YAAY,QACZ;AACJ,WAAO,OAAO,qBAAqB,cAAc,iBAAiB,SAAS;AAAA,EAC7E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAOA,SAAS,4BACP,OACA,OACA,cACA,cACA,WACyB;AACzB,MAAI,CAAC,YAAY,OAAO,KAAK,EAAG,MAAK,KAAK;AAC1C,MAAI;AACF,QAAI,wBAAwB,OAAO,OAAO,WAAW,MAAM,aAAc,MAAK,KAAK;AACnF,UAAM,SAAS,wBAAwB,OAAO,QAAQ;AACtD,UAAM,aAAa,wBAAwB,OAAO,YAAY;AAC9D,UAAM,aAAa,wBAAwB,OAAO,YAAY;AAC9D,QACE,WAAW,QACX,OAAO,WAAW,YAClB,OAAO,eAAe,YACtB,CAAC,OAAO,cAAc,UAAU,KAChC,aAAa,KACb,OAAO,eAAe,YACtB,CAAC,OAAO,cAAc,UAAU,KAChC,aAAa,gBACb,aAAa,aACb,MAAK,SAAS;AAChB,8BAA0B,MAAM;AAGhC,WAAO,IAAI,WAAW,IAAI,WAAW,QAAuB,YAAY,UAAU,CAAC;AAAA,EACrF,SAAS,OAAO;AACd,QAAI,iBAAiB,8BAA+B,OAAM;AAC1D,SAAK,KAAK;AAAA,EACZ;AACF;AAEA,SAAS,wBAAwB,OAAe,KAA2B;AACzE,QAAM,sBAAsB,OAAO,eAAe,WAAW,SAAS;AACtE,MAAI,CAAC,oBAAqB,MAAK,cAAc;AAC7C,QAAM,aAAa,OAAO,yBAAyB,qBAAqB,GAAG;AAC3E,QAAM,SAAkB,eAAe,SAAY,SAAY,QAAQ,IAAI,YAAY,KAAK;AAC5F,MAAI,OAAO,WAAW,WAAY,MAAK,cAAc;AACrD,SAAO,QAAQ,MAAM,QAAQ,OAAO,CAAC,CAAC;AACxC;AAEA,SAAS,0BAA0B,OAAqB;AACtD,QAAM,aAAa,OAAO,yBAAyB,YAAY,WAAW,YAAY;AACtF,QAAM,SAAkB,eAAe,SAAY,SAAY,QAAQ,IAAI,YAAY,KAAK;AAC5F,MAAI,OAAO,WAAW,WAAY,MAAK,cAAc;AAErD,UAAQ,MAAM,QAAQ,OAAO,CAAC,CAAC;AACjC;AAEA,SAAS,SAAS,OAAgB,OAAwC;AACxE,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,MAAK,KAAK;AAC3E,SAAO;AACT;AAEA,SAASA,iBACP,QACA,MACA,OACM;AACN,QAAM,SAAS,OAAO,KAAK,MAAM;AACjC,MAAI,OAAO,KAAK,SAAO,CAAC,KAAK,SAAS,GAAG,CAAC,EAAG,MAAK,KAAK;AACzD;AAEA,SAAS,wBAAwB,QAAiC,OAAqB;AACrF,mBAAiB,OAAO,WAAW,GAAG,KAAK,YAAY;AACvD,mBAAiB,OAAO,gBAAgB,GAAG,KAAK,iBAAiB;AACnE;AAEA,SAAS,iBAAiB,OAAgB,OAAwC;AAChF,aAAW,OAAO,OAAO,yBAAyB,oBAAoB;AACxE;AAEA,SAAS,WACP,OACA,OACA,mBACyB;AACzB,MACE,OAAO,UAAU,YACjB,MAAM,WAAW,KACjB,MAAM,SAAS,qBACf,UAAU,MAAM,KAAK,EACrB,MAAK,KAAK;AACZ,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,MAAM,SAAS,IAAK,MAAK,KAAK;AAAA,EAC5C;AACF;AAEA,SAAS,cACP,OACA,OACA,SACA,SACyB;AACzB,MAAI,CAAC,OAAO,cAAc,KAAK,KAAM,QAAmB,WAAY,QAAmB,SAAS;AAC9F,SAAK,KAAK;AAAA,EACZ;AACF;AAEA,SAAS,aAAa,OAAgB,OAAwC;AAC5E,MAAI,OAAO,UAAU,YAAY,CAAC,iCAAiC,KAAK,KAAK,EAAG,MAAK,KAAK;AAC5F;AAEA,SAAS,0BACP,OACA,OACsC;AACtC,QAAM,SAAS,SAAS,OAAO,KAAK;AACpC,EAAAA,iBAAgB,QAAQ,CAAC,eAAe,YAAY,YAAY,MAAM,GAAG,KAAK;AAC9E,eAAa,OAAO,aAAa,GAAG,KAAK,cAAc;AACvD,aAAW,OAAO,UAAU,GAAG,KAAK,aAAa,yBAAyB,kBAAkB;AAC5F,aAAW,OAAO,UAAU,GAAG,KAAK,aAAa,yBAAyB,kBAAkB;AAC5F,gBAAc,OAAO,MAAM,GAAG,KAAK,SAAS,GAAG,yBAAyB,UAAU;AACpF;AAEA,SAAS,YAAY,MAAsB;AACzC,MAAI,QAAQ,MAAM,QAAQ,GAAI,QAAO,OAAO;AAC5C,MAAI,QAAQ,MAAM,QAAQ,IAAK,QAAO,OAAO;AAC7C,MAAI,QAAQ,MAAM,QAAQ,GAAI,QAAO,OAAO;AAC5C,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,OAAK,cAAc;AACrB;AAEA,SAAS,KAAK,OAAsB;AAClC,QAAM,IAAI,8BAA8B,KAAK;AAC/C;;;AC1yBO,IAAM,6BAA6B,OAAO;AAAA,EAC/C;AAAA,IACE,MAAM;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AACF;AAIO,IAAM,4BAA4B,OAAO;AAAA,EAC9C;AAAA,IACE,sBAAsB;AAAA,IACtB,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,IACnB,0BAA0B;AAAA,IAC1B,oBAAoB;AAAA,IACpB,mBAAmB,KAAK;AAAA,IACxB,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,sBAAsB,MAAM;AAAA,IAC5B,kBAAkB,MAAM;AAAA,IACxB,sBAAsB;AAAA,IACtB,kBAAkB;AAAA,EACpB;AACF;AA6HA,IAAM,gCAAgC,IAAI;AAAA,EACxC,OAAO,OAAO,0BAA0B;AAC1C;AAEO,SAAS,yBAAyB,OAAiD;AACxF,SAAO,OAAO,UAAU,YAAY,8BAA8B,IAAI,KAAK;AAC7E;AAEO,IAAM,gCAAN,cAA4C,MAAM;AAAA,EAGvD,YAAqB,OAAe;AAClC,UAAM,8BAA8B,KAAK,EAAE;AADxB;AAEnB,SAAK,OAAO;AAAA,EACd;AAAA,EALS,OAAO;AAMlB;AAGO,SAAS,8BACd,QACA,OAC6C;AAC7C,QAAM,UAAUC,UAAS,OAAO,SAAS;AACzC,UAAQ,QAAQ;AAAA,IACd,KAAK,2BAA2B;AAC9B,qBAAe,SAAS;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,MAAAC,kBAAiB,QAAQ,iBAAiB,yBAAyB;AACnE,MAAAA,kBAAiB,QAAQ,iBAAiB,yBAAyB;AACnE,wBAAkB,QAAQ,QAAQ,gBAAgB;AAClD;AAAA,QACE,QAAQ;AAAA,QACR;AAAA,QACA,0BAA0B;AAAA,MAC5B;AACA;AAAA,QACE,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,0BAA0B;AAAA,MAC5B;AACA,UAAI,QAAQ,aAAa,OAAW,CAAAC,MAAK,kBAAkB;AAC3D;AAAA,QACE,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,0BAA0B;AAAA,MAC5B;AACA;AAAA,IACF,KAAK,2BAA2B;AAAA,IAChC,KAAK,2BAA2B;AAC9B,8BAAwB,SAAS,SAAS;AAC1C;AAAA,IACF,KAAK,2BAA2B;AAC9B,qBAAe,SAAS,CAAC,OAAO,GAAG,SAAS;AAC5C,wBAAkB,QAAQ,OAAO,eAAe;AAChD;AAAA,IACF,KAAK,2BAA2B;AAC9B,qBAAe,SAAS;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,MAAAD,kBAAiB,QAAQ,QAAQ,gBAAgB;AACjD,MAAAA,kBAAiB,QAAQ,iBAAiB,yBAAyB;AACnE,MAAAA,kBAAiB,QAAQ,mBAAmB,2BAA2B;AACvE,MAAAA,kBAAiB,QAAQ,iBAAiB,yBAAyB;AACnE,wBAAkB,QAAQ,OAAO,eAAe;AAChD;AAAA,IACF,KAAK,2BAA2B;AAC9B,qBAAe,SAAS,CAAC,cAAc,YAAY,OAAO,GAAG,SAAS;AACtE;AAAA,QACE,QAAQ;AAAA,QACR;AAAA,QACA,0BAA0B;AAAA,MAC5B;AACA;AAAA,QACE,QAAQ;AAAA,QACR;AAAA,QACA,0BAA0B;AAAA,MAC5B;AACA;AAAA,QACE,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,0BAA0B;AAAA,MAC5B;AACA;AAAA,EACJ;AACF;AAGO,SAAS,8BACd,QACA,OAC6B;AAC7B,QAAM,WAAWD,UAAS,OAAO,UAAU;AAC3C,UAAQ,QAAQ;AAAA,IACd,KAAK,2BAA2B;AAC9B,qBAAe,UAAU,CAAC,SAAS,cAAc,cAAc,GAAG,UAAU;AAC5E,kBAAY,SAAS,OAAO,gBAAgB;AAC5C,UAAI,SAAS,MAAM,SAAS,0BAA0B,UAAU;AAC9D,QAAAE,MAAK,gBAAgB;AAAA,MACvB;AACA,iBAAW,QAAQ,SAAS,MAAO,qBAAoB,MAAM,kBAAkB;AAC/E;AAAA,QACE,SAAS;AAAA,QACT;AAAA,QACA,0BAA0B;AAAA,MAC5B;AACA,UACE,OAAO,SAAS,iBAAiB,aACjC,SAAS,kBAAkB,SAAS,eAAe,QACnD,CAAAA,MAAK,uBAAuB;AAC9B;AAAA,IACF,KAAK,2BAA2B;AAC9B,qBAAe,UAAU,CAAC,MAAM,GAAG,UAAU;AAC7C,UAAI,SAAS,SAAS,KAAM,qBAAoB,SAAS,MAAM,eAAe;AAC9E;AAAA,IACF,KAAK,2BAA2B;AAAA,IAChC,KAAK,2BAA2B;AAC9B,qBAAe,UAAU,CAAC,MAAM,GAAG,UAAU;AAC7C,0BAAoB,SAAS,MAAM,eAAe;AAClD;AAAA,IACF,KAAK,2BAA2B;AAC9B,qBAAe,UAAU,CAAC,WAAW,QAAQ,GAAG,UAAU;AAC1D,UAAI,SAAS,YAAY,KAAM,CAAAA,MAAK,kBAAkB;AACtD,MAAAD,kBAAiB,SAAS,QAAQ,iBAAiB;AACnD;AAAA,IACF,KAAK,2BAA2B;AAC9B,qBAAe,UAAU,CAAC,OAAO,GAAG,UAAU;AAC9C,kBAAY,SAAS,OAAO,gBAAgB;AAC5C,UAAI,SAAS,MAAM,SAAS,0BAA0B,kBAAkB;AACtE,QAAAC,MAAK,gBAAgB;AAAA,MACvB;AACA,2BAAqB,SAAS,OAAO,gBAAgB;AACrD;AAAA,EACJ;AACA,SAAO;AACT;AAUO,SAAS,oCACd,QACA,YACgC;AAChC,MAAI,CAAC,yBAAyB,MAAM,EAAG,CAAAA,MAAK,QAAQ;AACpD,gCAA8B,QAAQ,UAAU;AAChD,QAAM,UAAU;AAChB,UAAQ,QAAQ;AAAA,IACd,KAAK,2BAA2B;AAC9B,aAAO;AAAA,QACL,gBAAgB,QAAQ;AAAA,QACxB,iBAAiB,QAAQ;AAAA,MAC3B;AAAA,IACF,KAAK,2BAA2B;AAAA,IAChC,KAAK,2BAA2B;AAC9B,aAAO,oBAAoB,OAAO;AAAA,IACpC,KAAK,2BAA2B,QAAQ;AACtC,YAAM,QAAQ,QAAQ;AACtB,aAAO;AAAA,QACL,gBAAgB,MAAM;AAAA,QACtB,cAAc,MAAM;AAAA,QACpB,iBAAiB,MAAM;AAAA,MACzB;AAAA,IACF;AAAA,IACA,KAAK,2BAA2B;AAC9B,aAAO,oBAAoB,OAAO;AAAA,IACpC,KAAK,2BAA2B;AAC9B,aAAO,CAAC;AAAA,EACZ;AACF;AA+DO,SAAS,8BAA8B,SAAyC;AACrF,EAAAD,kBAAiB,QAAQ,aAAa,qBAAqB;AAC3D,SAAO,OAAO,UAA0D;AACtE,UAAM,QAAQ,eAAe;AAC7B,IAAAA,kBAAiB,MAAM,cAAc,oBAAoB;AACzD,kCAA8B,MAAM,QAAQ,MAAM,UAAU;AAC5D,UAAM,YAAY,oCAAoC,MAAM,QAAQ,MAAM,UAAU;AACpF,QACE,UAAU,oBAAoB,UAC9B,UAAU,oBAAoB,QAAQ,aACtC;AACA,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AACA,UAAM,UAAwC;AAAA,MAC5C,cAAc,MAAM;AAAA,MACpB,aAAa,QAAQ;AAAA,MACrB,GAAI,MAAM,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,OAAO;AAAA,IAC/D;AACA,QAAI;AACJ,YAAQ,MAAM,QAAQ;AAAA,MACpB,KAAK,2BAA2B;AAC9B,mBAAW,MAAM,aAAa,OAAO,EAAE;AAAA,UACrC,MAAM;AAAA,UACN;AAAA,QACF;AACA;AAAA,MACF,KAAK,2BAA2B,KAAK;AACnC,cAAM,OAAO,MAAM,aAAa,OAAO,EAAE;AAAA,UACvC,MAAM;AAAA,UACN;AAAA,QACF;AACA,mBAAW,EAAE,MAAM,QAAQ,KAAK;AAChC;AAAA,MACF;AAAA,MACA,KAAK,2BAA2B,QAAQ;AACtC,cAAM,UAAU,MAAM;AACtB,mBAAW,EAAE,MAAM,MAAM,aAAa,OAAO,EAAE,OAAO,QAAQ,OAAO,OAAO,EAAE;AAC9E;AAAA,MACF;AAAA,MACA,KAAK,2BAA2B;AAC9B,mBAAW;AAAA,UACT,MAAM,MAAM,aAAa,OAAO,EAAE;AAAA,YAChC,MAAM;AAAA,YACN;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF,KAAK,2BAA2B,QAAQ;AACtC,cAAM,UAAU,MAAM;AACtB,cAAM,aAAa,OAAO,EAAE,OAAO,SAAS,OAAO;AACnD,mBAAW,EAAE,SAAS,MAAM,QAAQ,QAAQ,OAAO;AACnD;AAAA,MACF;AAAA,MACA,KAAK,2BAA2B,aAAa;AAC3C,YAAI,CAAC,QAAQ,eAAe;AAC1B,gBAAM,IAAI,MAAM,2CAA2C;AAAA,QAC7D;AACA,cAAM,QAAQ,MAAM,QAAQ,cAAc;AAAA,UACxC,MAAM;AAAA,UACN;AAAA,QACF;AACA,mBAAW,EAAE,OAAO,CAAC,GAAG,KAAK,EAAE;AAC/B;AAAA,MACF;AAAA,IACF;AACA,UAAM,QAAQ,eAAe;AAC7B,UAAM,SAAS,8BAA8B,MAAM,QAAQ,QAAQ;AACnE,8CAA0C,MAAM,QAAQ,MAAM,YAAY,MAAM;AAChF,QACE,MAAM,WAAW,2BAA2B,UAC3C,OAA0C,KAAK,iBAAiB,MAAM,cACvE;AACA,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AACA,WAAO;AAAA,EACT;AACF;AAYO,SAAS,6BAA6B,SAAyC;AACpF,iBAAe,QACb,QACA,YACA,cAA2C,CAAC,GACN;AACtC,gBAAY,QAAQ,eAAe;AACnC,kCAA8B,QAAQ,UAAU;AAChD,UAAM,oBAAoB,MAAM,QAAQ,KAAK,QAAQ,YAAY,WAAW;AAC5E,gBAAY,QAAQ,eAAe;AACnC,UAAM,WAAW,8BAA8B,QAAQ,iBAAiB;AACxE,8CAA0C,QAAQ,YAAY,QAAQ;AACtE,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,CACJ,YACA,gBACG,QAAQ,2BAA2B,MAAM,YAAY,WAAW;AAAA,IACrE,KAAK,OACH,YACA,iBACI,MAAM,QAAQ,2BAA2B,KAAK,YAAY,WAAW,GAAG;AAAA,IAC9E,QAAQ,OACN,YACA,iBACI,MAAM,QAAQ,2BAA2B,QAAQ,YAAY,WAAW,GAAG;AAAA,IACjF,QAAQ,OACN,YACA,iBACI,MAAM,QAAQ,2BAA2B,QAAQ,YAAY,WAAW,GAAG;AAAA,IACjF,QAAQ,OACN,YACA,gBACG,QAAQ,2BAA2B,QAAQ,YAAY,WAAW;AAAA,IACvE,aAAa,OACX,YACA,iBACI,MAAM,QAAQ,2BAA2B,aAAa,YAAY,WAAW,GAAG;AAAA,EACxF;AACF;AASO,SAAS,iCAAiC,SAIzB;AACtB,EAAAA,kBAAiB,QAAQ,iBAAiB,yBAAyB;AACnE,EAAAA,kBAAiB,QAAQ,cAAc,sBAAsB;AAC7D,QAAM,aAAa,oBAAI,IAA2B;AAElD,QAAM,WAAW,CAAC,SAAuC;AACvD,eAAW,IAAI,KAAK,IAAI,IAAI;AAC5B,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM,2BACJ,iBACA,cAAyC,CAAC,GAC1C;AACA,kBAAY,QAAQ,eAAe;AACnC,UAAI,YAAY,qBAAqB,QAAW;AAC9C,YACE,YAAY,iBAAiB,SAAS,MACtC,IAAI,IAAI,YAAY,gBAAgB,EAAE,SAAS,YAAY,iBAAiB,OAC5E,OAAM,IAAI,8BAA8B,0BAA0B;AACpE,mBAAW,mBAAmB,YAAY,kBAAkB;AAC1D,UAAAA,kBAAiB,iBAAiB,4BAA4B;AAAA,QAChE;AAAA,MACF;AACA,UACE,YAAY,qBAAqB,UACjC,CAAC,YAAY,iBAAiB,SAAS,QAAQ,eAAe,GAC9D;AACA,eAAO;AAAA,UACL,OAAO,CAAC;AAAA,UACR,cAAc;AAAA,UACd,SAAS;AAAA,UACT,SAAS,CAAC;AAAA,QACZ;AAAA,MACF;AACA,UACE,YAAY,kBAAkB,KAAK,YAAU,WAAW,QAAQ,eAAe,GAC/E;AACA,cAAM,IAAI,8BAA8B,0BAA0B;AAAA,MACpE;AACA,YAAM,UAAuC;AAAA,QAC3C;AAAA,QACA,iBAAiB,QAAQ;AAAA,QACzB,QAAQ,YAAY,UAAU,CAAC,UAAU,QAAQ;AAAA,QACjD,GAAI,YAAY,WAAW,SAAY,CAAC,IAAI,EAAE,QAAQ,YAAY,OAAO;AAAA,QACzE,OAAO,YAAY,SAAS,0BAA0B;AAAA,QACtD,UAAU,YAAY,YAAY,0BAA0B;AAAA,MAC9D;AACA,YAAM,WAAW,YAAY,WAAW,SACpC,MAAM,QAAQ,IAAI,KAAK,OAAO,IAC9B,MAAM,QAAQ,IAAI,KAAK,SAAS,EAAE,QAAQ,YAAY,OAAO,CAAC;AAClE,kBAAY,QAAQ,eAAe;AACnC,iBAAW,QAAQ,SAAS,MAAO,UAAS,IAAI;AAChD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,SAAS;AAAA,QACT,SAAS,CAAC,EAAE,iBAAiB,QAAQ,iBAAiB,OAAO,UAAU,WAAW,MAAM,CAAC;AAAA,MAC3F;AAAA,IACF;AAAA,IAEA,MAAM,oBAAoB,OAAiC,cAAc,CAAC,GAA2B;AACnG,kBAAY,QAAQ,eAAe;AACnC,gCAA0B,OAAO,OAAO;AACxC,YAAM,UAAU,EAAE,OAAO,sBAAsB,KAAK,EAAE;AACtD,YAAM,OAAO,YAAY,WAAW,SAChC,MAAM,QAAQ,IAAI,OAAO,OAAO,IAChC,MAAM,QAAQ,IAAI,OAAO,SAAS,WAAW;AACjD,kBAAY,QAAQ,eAAe;AACnC,aAAO,SAAS,IAAI;AAAA,IACtB;AAAA,IAEA,MAAM,oBACJ,QACA,OACA,cAAc,CAAC,GACS;AACxB,kBAAY,QAAQ,eAAe;AACnC,YAAM,OAAO,iBAAiB,YAAY,MAAM;AAChD,gCAA0B,OAAO,MAAM,OAAO;AAC9C,YAAM,QAAQ,sBAAsB,KAAK;AACzC,YAAM,UAAU;AAAA,QACd;AAAA,QACA,iBAAiB,KAAK;AAAA,QACtB,mBAAmB,KAAK;AAAA,QACxB,iBAAiB,KAAK;AAAA,QACtB;AAAA,MACF;AACA,aAAO;AAAA,QACL,YAAY,WAAW,SACnB,MAAM,QAAQ,IAAI,OAAO,OAAO,IAChC,MAAM,QAAQ,IAAI,OAAO,SAAS,WAAW;AAAA,MACnD;AAAA,IACF;AAAA,IAEA,MAAM,oBAAoB,QAAgB,cAAc,CAAC,GAAkB;AACzE,kBAAY,QAAQ,eAAe;AACnC,YAAM,OAAO,iBAAiB,YAAY,MAAM;AAChD,YAAM,UAAU;AAAA,QACd;AAAA,QACA,iBAAiB,KAAK;AAAA,QACtB,mBAAmB,KAAK;AAAA,QACxB,iBAAiB,KAAK;AAAA,MACxB;AACA,UAAI,YAAY,WAAW,OAAW,OAAM,QAAQ,IAAI,OAAO,OAAO;AAAA,UACjE,OAAM,QAAQ,IAAI,OAAO,SAAS,WAAW;AAClD,kBAAY,QAAQ,eAAe;AACnC,iBAAW,OAAO,MAAM;AAAA,IAC1B;AAAA,IAEA,qBAAqB,CAAC,YAAY,UAAU,OAAO,gBAAgB,QAAQ,IAAI,YAAY,EAAE,YAAY,UAAU,MAAM,GAAG,WAAW;AAAA,EACzI;AACF;AAEO,SAAS,0CACd,QACA,cACA,eACM;AACN,gCAA8B,QAAQ,YAAY;AAClD,QAAM,WAAW,8BAA8B,QAAQ,aAAa;AACpE,QAAM,UAAU;AAChB,UAAQ,QAAQ;AAAA,IACd,KAAK,2BAA2B,MAAM;AACpC,YAAM,cAAc;AACpB,YAAM,eAAe;AACrB,YAAM,QAAQ,YAAY,SAAS,0BAA0B;AAC7D,UAAI,aAAa,MAAM,SAAS,MAAO,CAAAC,MAAK,gBAAgB;AAC5D,UAAI;AACF,2BAAmB,cAAc;AAAA,UAC/B,UAAU;AAAA,UACV,UAAU;AAAA,UACV,oBAAoB,0BAA0B;AAAA,UAC9C,gBAAgB,0BAA0B,oBAAoB;AAAA,UAC9D,UAAU,YAAY;AAAA,QACxB,CAAC;AAAA,MACH,QAAQ;AACN,QAAAA,MAAK,mBAAmB;AAAA,MAC1B;AACA,YAAM,OAAO,oBAAI,IAAY;AAC7B,iBAAW,QAAQ,aAAa,OAAO;AACrC,YACE,KAAK,oBAAoB,YAAY,mBACrC,KAAK,oBAAoB,YAAY,mBACpC,YAAY,WAAW,UAAa,CAAC,YAAY,OAAO,SAAS,KAAK,KAAK,KAC5E,KAAK,IAAI,KAAK,EAAE,EAChB,CAAAA,MAAK,gBAAgB;AACvB,aAAK,IAAI,KAAK,EAAE;AAAA,MAClB;AACA;AAAA,IACF;AAAA,IACA,KAAK,2BAA2B,KAAK;AACnC,YAAM,OAAQ,SAAyC;AACvD,UAAI,KAAM,gCAA+B,MAAM,SAAS,eAAe;AACvE;AAAA,IACF;AAAA,IACA,KAAK,2BAA2B,QAAQ;AACtC,YAAM,QAAQ,QAAQ;AACtB,YAAM,OAAQ,SAA4C;AAC1D,UACE,KAAK,oBAAoB,MAAM,mBAC/B,KAAK,sBAAsB,MAAM,qBACjC,KAAK,oBAAoB,MAAM,gBAC/B,CAAAA,MAAK,eAAe;AACtB;AAAA,IACF;AAAA,IACA,KAAK,2BAA2B;AAC9B;AAAA,QACG,SAA4C;AAAA,QAC7C;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF,KAAK,2BAA2B;AAC9B,UAAK,SAA4C,WAAW,QAAQ,QAAQ;AAC1E,QAAAA,MAAK,iBAAiB;AAAA,MACxB;AACA;AAAA,IACF,KAAK,2BAA2B,aAAa;AAC3C,YAAM,iBAAiB;AACvB,UACG,SAAiD,MAAM,UACrD,eAAe,SAAS,GAC3B,CAAAA,MAAK,gBAAgB;AACvB;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,aAAa,SAAkE;AACtF,MAAI,CAAC,QAAQ,MAAO,OAAM,IAAI,MAAM,kCAAkC;AACtE,SAAO,QAAQ;AACjB;AAEA,SAAS,oBAAoB,SAAkE;AAC7F,SAAO;AAAA,IACL,gBAAgB,QAAQ;AAAA,IACxB,cAAc,QAAQ;AAAA,IACtB,iBAAiB,QAAQ;AAAA,EAC3B;AACF;AAEA,SAAS,wBAAwB,OAAgC,OAAqB;AACpF,iBAAe,OAAO;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,KAAK;AACR,EAAAD,kBAAiB,MAAM,QAAQ,GAAG,KAAK,SAAS;AAChD,EAAAA,kBAAiB,MAAM,iBAAiB,GAAG,KAAK,kBAAkB;AAClE,EAAAA,kBAAiB,MAAM,mBAAmB,GAAG,KAAK,oBAAoB;AACtE,EAAAA,kBAAiB,MAAM,iBAAiB,GAAG,KAAK,kBAAkB;AACpE;AAEA,SAAS,kBAAkB,OAAgB,OAA6D;AACtG,QAAM,QAAQD,UAAS,OAAO,KAAK;AACnC,iBAAe,OAAO;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,KAAK;AACR,EAAAC,kBAAiB,MAAM,iBAAiB,GAAG,KAAK,kBAAkB;AAClE,EAAAA,kBAAiB,MAAM,mBAAmB,GAAG,KAAK,oBAAoB;AACtE,sBAAoB,MAAM,MAAM,GAAG,KAAK,SAAS,0BAA0B,cAAc;AACzF,iBAAe,MAAM,UAAU,GAAG,KAAK,WAAW;AAClD,kBAAgB,MAAM,SAAS,GAAG,KAAK,YAAY,KAAK;AACxD,qBAAmB,MAAM,kBAAkB,GAAG,KAAK,qBAAqB,KAAK;AAC7E,qBAAmB,MAAM,gBAAgB,GAAG,KAAK,mBAAmB,KAAK;AACzE;AAAA,IACE,MAAM;AAAA,IACN,GAAG,KAAK;AAAA,IACR,0BAA0B;AAAA,EAC5B;AACA,kBAAgB,MAAM,SAAS,GAAG,KAAK,UAAU;AACjD,EAAAA,kBAAiB,MAAM,iBAAiB,GAAG,KAAK,kBAAkB;AAClE;AAAA,IACE,MAAM;AAAA,IACN,GAAG,KAAK;AAAA,IACR,0BAA0B;AAAA,EAC5B;AACF;AAEA,SAAS,kBAAkB,OAAgB,OAA6D;AACtG,QAAM,QAAQD,UAAS,OAAO,KAAK;AACnC,iBAAe,OAAO;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,KAAK;AACR,MAAI,OAAO,KAAK,KAAK,EAAE,WAAW,EAAG,CAAAE,MAAK,KAAK;AAC/C;AAAA,IACE,MAAM;AAAA,IACN,GAAG,KAAK;AAAA,IACR,0BAA0B;AAAA,EAC5B;AACA,MAAI,MAAM,aAAa,OAAW,gBAAe,MAAM,UAAU,GAAG,KAAK,WAAW;AACpF,kBAAgB,MAAM,SAAS,GAAG,KAAK,YAAY,IAAI;AACvD,qBAAmB,MAAM,kBAAkB,GAAG,KAAK,qBAAqB,IAAI;AAC5E,qBAAmB,MAAM,gBAAgB,GAAG,KAAK,mBAAmB,IAAI;AACxE,kBAAgB,MAAM,SAAS,GAAG,KAAK,UAAU;AACjD,MAAI,MAAM,oBAAoB,QAAW;AACvC,IAAAD,kBAAiB,MAAM,iBAAiB,GAAG,KAAK,kBAAkB;AAAA,EACpE;AACA;AAAA,IACE,MAAM;AAAA,IACN,GAAG,KAAK;AAAA,IACR,0BAA0B;AAAA,EAC5B;AACF;AAEA,SAAS,oBAAoB,OAAgB,OAA+C;AAC1F,QAAM,OAAOD,UAAS,OAAO,KAAK;AAClC,iBAAe,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,KAAK;AACR,EAAAC,kBAAiB,KAAK,IAAI,GAAG,KAAK,KAAK;AACvC,EAAAA,kBAAiB,KAAK,iBAAiB,GAAG,KAAK,kBAAkB;AACjE,EAAAA,kBAAiB,KAAK,mBAAmB,GAAG,KAAK,oBAAoB;AACrE,sBAAoB,KAAK,MAAM,GAAG,KAAK,SAAS,0BAA0B,cAAc;AACxF,iBAAe,KAAK,UAAU,GAAG,KAAK,WAAW;AACjD,kBAAgB,KAAK,SAAS,GAAG,KAAK,YAAY,OAAO,IAAI;AAC7D,qBAAmB,KAAK,kBAAkB,GAAG,KAAK,qBAAqB,KAAK;AAC5E,qBAAmB,KAAK,gBAAgB,GAAG,KAAK,mBAAmB,KAAK;AACxE,MAAI,OAAO,KAAK,YAAY,UAAW,CAAAC,MAAK,GAAG,KAAK,UAAU;AAC9D;AAAA,IACE,KAAK;AAAA,IACL,GAAG,KAAK;AAAA,IACR,0BAA0B;AAAA,EAC5B;AACA,cAAY,KAAK,OAAO,GAAG,KAAK,QAAQ;AACxC,EAAAD,kBAAiB,KAAK,iBAAiB,GAAG,KAAK,kBAAkB;AACjE;AAAA,IACE,KAAK;AAAA,IACL,GAAG,KAAK;AAAA,IACR,0BAA0B;AAAA,EAC5B;AACA,EAAAA,kBAAiB,KAAK,cAAc,GAAG,KAAK,eAAe;AAC3D,MAAI,KAAK,cAAc,OAAW,qBAAoB,KAAK,WAAW,GAAG,KAAK,YAAY;AAC1F,MAAI,KAAK,cAAc,OAAW,qBAAoB,KAAK,WAAW,GAAG,KAAK,YAAY;AAC1F,MAAI,KAAK,cAAc,OAAW,qBAAoB,KAAK,WAAW,GAAG,KAAK,YAAY;AAC1F,MAAI,KAAK,kBAAkB,OAAW,qBAAoB,KAAK,eAAe,GAAG,KAAK,gBAAgB;AACtG,MAAI,KAAK,gBAAgB,OAAW,qBAAoB,KAAK,aAAa,GAAG,KAAK,cAAc;AAChG,MACE,KAAK,kBAAkB,UACvB,KAAK,kBAAkB,eACvB,KAAK,kBAAkB,SACvB,CAAAC,MAAK,GAAG,KAAK,gBAAgB;AAC/B,wBAAsB,KAAK,WAAW,GAAG,KAAK,cAAc,IAAK;AACjE,kBAAgB,KAAK,qBAAqB,GAAG,KAAK,wBAAwB,GAAG,GAAS;AACtF,kBAAgB,KAAK,UAAU,GAAG,KAAK,aAAa,GAAG,OAAO,gBAAgB;AAC9E,kBAAgB,KAAK,SAAS,GAAG,KAAK,YAAY,GAAG,OAAO,gBAAgB;AAC5E,kBAAgB,KAAK,gBAAgB,GAAG,KAAK,iBAAiB;AAC9D,kBAAgB,KAAK,mBAAmB,GAAG,KAAK,sBAAsB,GAAG,OAAO,gBAAgB;AAChG,wBAAsB,KAAK,cAAc,GAAG,KAAK,iBAAiB,GAAG;AACrE,MAAI,KAAK,2BAA2B,QAAW;AAC7C,wBAAoB,KAAK,wBAAwB,GAAG,KAAK,yBAAyB;AAAA,EACpF;AACA,kBAAgB,KAAK,mBAAmB,GAAG,KAAK,sBAAsB,GAAG,GAAS;AACpF;AAEA,SAAS,eAAe,OAAgB,OAA0D;AAChG,QAAM,WAAWF,UAAS,OAAO,KAAK;AACtC,MAAI,SAAS,SAAS,QAAQ;AAC5B,mBAAe,UAAU,CAAC,QAAQ,cAAc,UAAU,GAAG,KAAK;AAClE;AAAA,MACE,SAAS;AAAA,MACT,GAAG,KAAK;AAAA,MACR,0BAA0B;AAAA,IAC5B;AACA;AAAA,MACE,SAAS;AAAA,MACT,GAAG,KAAK;AAAA,MACR,0BAA0B;AAAA,IAC5B;AACA;AAAA,EACF;AACA,MAAI,SAAS,SAAS,MAAM;AAC1B,mBAAe,UAAU,CAAC,QAAQ,WAAW,GAAG,KAAK;AACrD,wBAAoB,SAAS,WAAW,GAAG,KAAK,YAAY;AAC5D;AAAA,EACF;AACA,EAAAE,MAAK,GAAG,KAAK,OAAO;AACtB;AAEA,SAAS,gBACP,OACA,OACA,UACA,kBAAkB,OACZ;AACN,MAAI,UAAU,UAAa,YAAY,UAAU,KAAM;AACvD,QAAM,UAAUF,UAAS,OAAO,KAAK;AACrC,iBAAe,SAAS,CAAC,SAAS,GAAG,KAAK;AAC1C,MAAI,mBAAmB,QAAQ,YAAY,OAAW;AACtD;AAAA,IACE,QAAQ;AAAA,IACR,GAAG,KAAK;AAAA,IACR,0BAA0B;AAAA,IAC1B;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,OAAgB,OAAe,UAAyB;AAClF,MAAI,UAAU,UAAa,YAAY,UAAU,KAAM;AACvD,MAAI,OAAO,UAAU,YAAY,CAAC,+BAA+B,KAAK,KAAK,EAAG,CAAAE,MAAK,KAAK;AAC1F;AAEA,SAAS,kBAAkB,OAAgB,OAAqB;AAC9D,MAAI,UAAU,OAAW;AACzB,cAAY,OAAO,KAAK;AACxB,MAAI,MAAM,WAAW,KAAK,MAAM,SAAS,EAAG,CAAAA,MAAK,KAAK;AACtD,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,QAAQ,OAAO;AACxB,gBAAY,MAAM,GAAG,KAAK,IAAI;AAC9B,QAAI,KAAK,IAAI,IAAI,EAAG,CAAAA,MAAK,KAAK;AAC9B,SAAK,IAAI,IAAI;AAAA,EACf;AACF;AAEA,SAAS,YAAY,OAAgB,OAAoD;AACvF,MACE,UAAU,YACV,UAAU,YACV,UAAU,eACV,UAAU,eACV,UAAU,WACV,CAAAA,MAAK,KAAK;AACd;AAEA,SAAS,qBAAqB,QAAmB,OAAqB;AACpE,MAAI;AACJ,aAAW,SAAS,QAAQ;AAC1B,wBAAoB,OAAO,GAAG,KAAK,IAAI;AACvC,QAAI,aAAa,UAAa,YAAY,MAAO,CAAAA,MAAK,KAAK;AAC3D,eAAW;AAAA,EACb;AACF;AAEA,SAAS,oBAAoB,OAAgB,OAAwC;AACnF,MAAI,OAAO,UAAU,YAAY,MAAM,SAAS,GAAI,CAAAA,MAAK,KAAK;AAC9D,MAAI;AACJ,MAAI;AACF,gBAAY,IAAI,KAAK,KAAK,EAAE,YAAY;AAAA,EAC1C,QAAQ;AACN,IAAAA,MAAK,KAAK;AAAA,EACZ;AACA,MAAI,cAAc,MAAO,CAAAA,MAAK,KAAK;AACrC;AAEA,SAAS,+BACP,MACA,SACA,OACM;AACN,MACE,KAAK,OAAO,QAAQ,UACpB,KAAK,oBAAoB,QAAQ,mBACjC,KAAK,sBAAsB,QAAQ,qBACnC,KAAK,oBAAoB,QAAQ,gBACjC,CAAAA,MAAK,KAAK;AACd;AAEA,SAAS,0BACP,OACA,SACM;AACN,MAAI,MAAM,oBAAoB,QAAQ,iBAAiB;AACrD,UAAM,IAAI,8BAA8B,uBAAuB;AAAA,EACjE;AACA,MAAI,MAAM,iBAAiB,QAAQ,cAAc;AAC/C,UAAM,IAAI,8BAA8B,oBAAoB;AAAA,EAC9D;AACA,MAAI,MAAM,iBAAiB,MAAM,SAAS,MAAM;AAC9C,UAAM,IAAI,8BAA8B,oBAAoB;AAAA,EAC9D;AACF;AAEA,SAAS,0BACP,OACA,MACA,SACM;AACN,MAAI,MAAM,oBAAoB,UAAa,MAAM,oBAAoB,KAAK,iBAAiB;AACzF,UAAM,IAAI,8BAA8B,uBAAuB;AAAA,EACjE;AACA,MAAI,MAAM,sBAAsB,UAAa,MAAM,sBAAsB,KAAK,mBAAmB;AAC/F,UAAM,IAAI,8BAA8B,yBAAyB;AAAA,EACnE;AACA,MAAI,MAAM,oBAAoB,UAAa,MAAM,oBAAoB,QAAQ,iBAAiB;AAC5F,UAAM,IAAI,8BAA8B,uBAAuB;AAAA,EACjE;AACA,MAAI,MAAM,iBAAiB,UAAa,MAAM,iBAAiB,QAAQ,cAAc;AACnF,UAAM,IAAI,8BAA8B,oBAAoB;AAAA,EAC9D;AACA,MACE,MAAM,iBAAiB,UACvB,MAAM,aAAa,UACnB,MAAM,iBAAiB,MAAM,SAAS,MACtC;AACA,UAAM,IAAI,8BAA8B,oBAAoB;AAAA,EAC9D;AACF;AAEA,SAAS,sBAAsB,OAA8D;AAC3F,SAAO;AAAA,IACL,iBAAiB,MAAM;AAAA,IACvB,mBAAmB,MAAM;AAAA,IACzB,MAAM,MAAM;AAAA,IACZ,UAAU,MAAM;AAAA,IAChB,SAAS,MAAM;AAAA,IACf,kBAAkB,MAAM;AAAA,IACxB,gBAAgB,MAAM;AAAA,IACtB,WAAW,MAAM;AAAA,IACjB,SAAS,MAAM;AAAA,IACf,iBAAiB,MAAM;AAAA,IACvB,oBAAoB,MAAM;AAAA,EAC5B;AACF;AAEA,SAAS,sBACP,OAC6B;AAC7B,QAAM,QAAqC,CAAC;AAC5C,MAAI,OAAO,OAAO,MAAM,EAAG,OAAM,OAAO,MAAM;AAC9C,MAAI,OAAO,OAAO,UAAU,EAAG,OAAM,WAAW,MAAM;AACtD,MAAI,OAAO,OAAO,SAAS,EAAG,OAAM,UAAU,MAAM,WAAW;AAC/D,MAAI,OAAO,OAAO,kBAAkB,GAAG;AACrC,UAAM,mBAAmB,MAAM,oBAAoB;AAAA,EACrD;AACA,MAAI,OAAO,OAAO,gBAAgB,EAAG,OAAM,iBAAiB,MAAM,kBAAkB;AACpF,MAAI,OAAO,OAAO,SAAS,EAAG,OAAM,UAAU,MAAM;AACpD,MAAI,OAAO,OAAO,iBAAiB,EAAG,OAAM,kBAAkB,MAAM;AACpE,MAAI,OAAO,OAAO,oBAAoB,GAAG;AACvC,UAAM,qBAAqB,MAAM,sBAAsB;AAAA,EACzD;AACA,oBAAkB,OAAO,eAAe;AACxC,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAmC,QAA+B;AAC1F,EAAAD,kBAAiB,QAAQ,QAAQ;AACjC,QAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,kCAAkC;AAC7D,SAAO;AACT;AAEA,SAAS,OAAO,OAAe,KAAsB;AACnD,SAAO,OAAO,UAAU,eAAe,KAAK,OAAO,GAAG;AACxD;AAEA,SAASD,UAAS,OAAgB,OAAwC;AACxE,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,CAAAE,MAAK,KAAK;AACnF,SAAO;AACT;AAEA,SAAS,eACP,OACA,SACA,OACM;AACN,QAAM,aAAa,IAAI,IAAI,OAAO;AAClC,MAAI,OAAO,KAAK,KAAK,EAAE,KAAK,SAAO,CAAC,WAAW,IAAI,GAAG,CAAC,EAAG,CAAAA,MAAK,KAAK;AACtE;AAEA,SAAS,YAAY,OAAgB,OAA2C;AAC9E,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,CAAAA,MAAK,KAAK;AACvC;AAEA,SAASD,kBAAiB,OAAgB,OAAwC;AAChF;AAAA,IACE;AAAA,IACA;AAAA,IACA,0BAA0B;AAAA,EAC5B;AACF;AAEA,SAAS,oBACP,OACA,OACA,SACA,aAAa,OACY;AACzB,MACE,OAAO,UAAU,YAChB,CAAC,cAAc,MAAM,WAAW,KACjC,MAAM,SAAS,WACf,MAAM,SAAS,IAAI,EACnB,CAAAC,MAAK,KAAK;AACd;AAEA,SAAS,sBACP,OACA,OACA,SACM;AACN,MAAI,UAAU,OAAW,qBAAoB,OAAO,OAAO,OAAO;AACpE;AAEA,SAAS,8BACP,OACA,OACA,SACM;AACN,MAAI,UAAU,UAAa,UAAU,KAAM,qBAAoB,OAAO,OAAO,OAAO;AACtF;AAEA,SAAS,gBAAgB,OAAgB,OAAqB;AAC5D,MAAI,UAAU,UAAa,OAAO,UAAU,UAAW,CAAAA,MAAK,KAAK;AACnE;AAEA,SAAS,gBACP,OACA,OACA,SACA,SACM;AACN,MACE,UAAU,WACT,OAAO,UAAU,YAAY,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,WAAW,QAAQ,SACzF,CAAAA,MAAK,KAAK;AACd;AAEA,SAASA,MAAK,OAAsB;AAClC,QAAM,IAAI,8BAA8B,KAAK;AAC/C;;;ACllCO,IAAM,0BAA0B,OAAO;AAAA,EAC5C;AAAA,IACE,sBAAsB;AAAA,IACtB,uBAAuB,OAAO;AAAA,IAC9B,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,wBAAwB,MAAM;AAAA,IAC9B,4BAA4B;AAAA,IAC5B,wBAAwB;AAAA,IACxB,wBAAwB,KAAK;AAAA,IAC7B,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,kBAAkB,IAAI,OAAO;AAAA,IAC7B,aAAa;AAAA,IACb,cAAc;AAAA;AAAA,IAEd,0BAA0B;AAAA,IAC1B,sBAAsB;AAAA,IACtB,2BAA2B;AAAA,IAC3B,oBAAoB;AAAA,IACpB,wBAAwB;AAAA,IACxB,oBAAoB;AAAA,IACpB,wBAAwB,MAAM;AAAA,IAC9B,kBAAkB;AAAA,IAClB,kBAAkB,IAAI,OAAO;AAAA,IAC7B,oBAAoB,KAAK,OAAO;AAAA,IAChC,sBAAsB,IAAI,OAAO;AAAA,IACjC,YAAY;AAAA,IACZ,yBAAyB,KAAK;AAAA,IAC9B,iBAAiB,MAAM;AAAA,IACvB,sBAAsB;AAAA,IACtB,kBAAkB;AAAA,IAClB,wBAAwB;AAAA,IACxB,kBAAkB,0BAA0B;AAAA,EAC9C;AACF;AAEO,IAAM,2BAA2B,OAAO;AAAA,EAC7C;AAAA,IACE,gBAAgB;AAAA,IAChB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,cAAc;AAAA,IACd,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,qBAAqB;AAAA,IACrB,WAAW;AAAA,IACX,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,6BAA6B;AAAA,IAC7B,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,uBAAuB,8BAA8B;AAAA,IACrD,uBAAuB,8BAA8B;AAAA,IACrD,wBAAwB,8BAA8B;AAAA,IACtD,iBAAiB;AAAA,IACjB,cAAc,2BAA2B;AAAA,IACzC,aAAa,2BAA2B;AAAA,IACxC,gBAAgB,2BAA2B;AAAA,IAC3C,gBAAgB,2BAA2B;AAAA,IAC3C,gBAAgB,2BAA2B;AAAA,IAC3C,qBAAqB,2BAA2B;AAAA,EAClD;AACF;AAIA,IAAM,8BAA8B,IAAI,IAAY,OAAO,OAAO,wBAAwB,CAAC;AAEpF,SAAS,uBAAuB,OAA+C;AACpF,SAAO,OAAO,UAAU,YAAY,4BAA4B,IAAI,KAAK;AAC3E;AAcO,SAAS,kCACd,QACA,YAC8B;AAC9B,MAAI,CAAC,uBAAuB,MAAM,EAAG,OAAM,IAAI,4BAA4B,QAAQ;AACnF,8BAA4B,QAAQ,UAAU;AAC9C,QAAM,SAAS;AACf,UAAQ,QAAQ;AAAA,IACd,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,aAAO,CAAC;AAAA,IACV,KAAK,yBAAyB;AAC5B,aAAO;AAAA,QACL,cAAc,OAAO;AAAA,QACrB,GAAI,OAAO,mBAAmB,SAAY,CAAC,IAAI,EAAE,gBAAgB,OAAO,eAAyB;AAAA,MACnG;AAAA,IACF,KAAK,yBAAyB;AAC5B,aAAO;AAAA,QACL,gBAAgB,OAAO;AAAA,QACvB,GAAI,OAAO,iBAAiB,SAAY,CAAC,IAAI,EAAE,cAAc,OAAO,aAAuB;AAAA,MAC7F;AAAA,IACF,KAAK,yBAAyB;AAC5B,aAAO;AAAA,QACL,gBAAgB,OAAO;AAAA,QACvB,cAAc,OAAO;AAAA,MACvB;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,aAAO,EAAE,OAAO,OAAO,MAAgB;AAAA,IACzC,KAAK,yBAAyB;AAC5B,aAAO;AAAA,QACL,gBAAgB,OAAO;AAAA,QACvB,OAAO,OAAO;AAAA,MAChB;AAAA,IACF,KAAK,yBAAyB;AAC5B,aAAO;AAAA,QACL,gBAAgB,OAAO;AAAA,QACvB,GAAI,OAAO,iBAAiB,SAAY,CAAC,IAAI,EAAE,cAAc,OAAO,aAAuB;AAAA,MAC7F;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,aAAO,EAAE,gBAAgB,OAAO,eAAyB;AAAA,IAC3D,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,aAAO,EAAE,gBAAgB,OAAO,eAAyB;AAAA,IAC3D,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB,qBAAqB;AACjD,YAAM,YAAY,oCAAoC,QAAQ,UAAU;AACxE,aAAO;AAAA,QACL,GAAI,UAAU,mBAAmB,SAAY,CAAC,IAAI,EAAE,gBAAgB,UAAU,eAAe;AAAA,QAC7F,GAAI,UAAU,iBAAiB,SAAY,CAAC,IAAI,EAAE,cAAc,UAAU,aAAa;AAAA,MACzF;AAAA,IACF;AAAA,EACF;AACF;AAqaO,IAAM,8BAAN,cAA0C,MAAM;AAAA,EAGrD,YAAqB,OAAe;AAClC,UAAM,4BAA4B,KAAK,EAAE;AADtB;AAEnB,SAAK,OAAO;AAAA,EACd;AAAA,EALS,OAAO;AAMlB;AAGO,SAAS,4BACd,QACA,OAC2C;AAC3C,kBAAgB,OAAO,IAAI,OAAO,MAAM,SAAS;AACjD,QAAM,SAASC,UAAS,OAAO,SAAS;AACxC,UAAQ,QAAQ;AAAA,IACd,KAAK,yBAAyB;AAC5B,MAAAC,gBAAe,QAAQ,CAAC,GAAG,SAAS;AACpC;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA,gBAAe,QAAQ,CAAC,gBAAgB,kBAAkB,gBAAgB,GAAG,SAAS;AACtF,MAAAC,kBAAiB,OAAO,cAAc,sBAAsB;AAC5D,qBAAe,OAAO,gBAAgB,wBAAwB;AAC9D,yBAAmB,OAAO,gBAAgB,wBAAwB;AAClE;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAD,gBAAe,QAAQ,CAAC,aAAa,UAAU,kBAAkB,WAAW,gBAAgB,aAAa,GAAG,SAAS;AACrH,wBAAkB,QAAQ,KAAK;AAC/B;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA,gBAAe,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,wBAAkB,QAAQ,IAAI;AAC9B,+BAAyB,OAAO,cAAc,sBAAsB;AACpE;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,MAAAA,gBAAe,QAAQ,CAAC,OAAO,GAAG,SAAS;AAC3C,MAAAC,kBAAiB,OAAO,OAAO,eAAe;AAC9C;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAD,gBAAe,QAAQ,CAAC,kBAAkB,UAAU,aAAa,QAAQ,GAAG,SAAS;AACrF,gCAA0B,MAAM;AAChC,UACE,OAAO,WAAW,UAClB,OAAO,WAAW,iBAClB,OAAO,WAAW,eAClB,OAAO,WAAW,YAClB,CAAAE,MAAK,gBAAgB;AACvB;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAF,gBAAe,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,gCAA0B,MAAM;AAChC,MAAAC,kBAAiB,OAAO,WAAW,mBAAmB;AACtD,UAAI,OAAO,cAAc,OAAO,OAAQ,CAAAC,MAAK,mBAAmB;AAChE,yBAAmB,OAAO,cAAc,sBAAsB;AAC9D;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAF,gBAAe,QAAQ,CAAC,SAAS,UAAU,cAAc,WAAW,GAAG,SAAS;AAChF,6BAAuB,OAAO,OAAO,iBAAiB,GAAG,wBAAwB,oBAAoB;AACrG,2BAAqB,OAAO,QAAQ,gBAAgB;AACpD,2BAAqB,OAAO,YAAY,oBAAoB;AAC5D,wBAAkB,OAAO,WAAW,mBAAmB;AACvD;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA,gBAAe,QAAQ,CAAC,gBAAgB,GAAG,SAAS;AACpD,MAAAC,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAD,gBAAe,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,MAAAC,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE,2BAAqB,OAAO,QAAQ,gBAAgB;AACpD,2BAAqB,OAAO,YAAY,oBAAoB;AAC5D,wBAAkB,OAAO,WAAW,mBAAmB;AACvD,6BAAuB,OAAO,OAAO,iBAAiB,GAAG,wBAAwB,YAAY;AAC7F,6BAAuB,OAAO,YAAY,sBAAsB,GAAG,wBAAwB,mBAAmB;AAC9G,6BAAuB,OAAO,kBAAkB,4BAA4B,GAAG,wBAAwB,eAAe;AACtH;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAD,gBAAe,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,MAAAC,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE,MAAAA,kBAAiB,OAAO,QAAQ,gBAAgB;AAChD,2BAAqB,OAAO,QAAQ,gBAAgB;AACpD,2BAAqB,OAAO,YAAY,oBAAoB;AAC5D,wBAAkB,OAAO,WAAW,mBAAmB;AACvD,6BAAuB,OAAO,OAAO,iBAAiB,GAAG,wBAAwB,cAAc;AAC/F;AAAA,QACE,OAAO;AAAA,QACP;AAAA,QACA,wBAAwB;AAAA,QACxB,wBAAwB;AAAA,MAC1B;AACA;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAD,gBAAe,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,MAAAC,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE,6BAAuB,OAAO,OAAO,iBAAiB,GAAG,wBAAwB,WAAW;AAC5F,2BAAqB,OAAO,QAAQ,gBAAgB;AACpD,2BAAqB,OAAO,kBAAkB,0BAA0B;AACxE,2BAAqB,OAAO,YAAY,oBAAoB;AAC5D,wBAAkB,OAAO,WAAW,mBAAmB;AACvD,wBAAkB,OAAO,MAAM,cAAc;AAC7C,kCAA4B,OAAO,UAAU,kBAAkB;AAC/D,UAAI,OAAO,WAAW,UAAa,OAAO,qBAAqB,QAAW;AACxE,QAAAC,MAAK,0BAA0B;AAAA,MACjC;AACA;AAAA,IACF,KAAK,yBAAyB,6BAA6B;AACzD,MAAAF,gBAAe,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,SAAS;AACZ,MAAAC,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE,6BAAuB,OAAO,OAAO,iBAAiB,GAAG,wBAAwB,YAAY;AAC7F,gCAA0B,OAAO,UAAU,kBAAkB;AAC7D,2BAAqB,OAAO,kBAAkB,0BAA0B;AACxE,2BAAqB,OAAO,cAAc,sBAAsB;AAChE,2BAAqB,OAAO,aAAa,qBAAqB;AAC9D,6BAAuB,OAAO,kBAAkB,4BAA4B,GAAG,OAAO,gBAAgB;AACtG,UACE,CAAC,OAAO,cAAc,OAAO,aAAa,OAAO,gBAAgB,EAC9D,OAAO,CAAAE,WAASA,WAAU,MAAS,EAAE,SAAS,EACjD,CAAAD,MAAK,oBAAoB;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,yBAAyB;AAC5B,MAAAF,gBAAe,QAAQ,CAAC,kBAAkB,SAAS,oBAAoB,eAAe,UAAU,GAAG,SAAS;AAC5G,MAAAC,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE,+BAAyB,OAAO,OAAO,eAAe;AACtD,2BAAqB,OAAO,kBAAkB,0BAA0B;AACxE,UAAI,OAAO,qBAAqB,OAAW,CAAAC,MAAK,0BAA0B;AAC1E,6BAAuB,OAAO,aAAa,uBAAuB,GAAG,wBAAwB,kBAAkB;AAC/G,8BAAwB,OAAO,UAAU,kBAAkB;AAC3D;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAF,gBAAe,QAAQ,CAAC,kBAAkB,aAAa,QAAQ,GAAG,SAAS;AAC3E,MAAAC,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE,MAAAA,kBAAiB,OAAO,WAAW,mBAAmB;AACtD,6BAAuB,OAAO,QAAQ,kBAAkB,GAAG,OAAO,gBAAgB;AAClF;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAD,gBAAe,QAAQ,CAAC,kBAAkB,eAAe,QAAQ,GAAG,SAAS;AAC7E,MAAAC,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE,MAAAA,kBAAiB,OAAO,aAAa,qBAAqB;AAC1D,6BAAuB,OAAO,QAAQ,kBAAkB,GAAG,OAAO,gBAAgB;AAClF;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAD,gBAAe,QAAQ,CAAC,kBAAkB,SAAS,UAAU,SAAS,UAAU,GAAG,SAAS;AAC5F,MAAAC,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE,MAAAA,kBAAiB,OAAO,OAAO,eAAe;AAC9C,2BAAqB,OAAO,QAAQ,gBAAgB;AACpD,6BAAuB,OAAO,OAAO,iBAAiB,GAAG,wBAAwB,UAAU;AAC3F,kCAA4B,OAAO,UAAU,kBAAkB;AAC/D;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,uCAAiC,QAAQ,KAAK;AAC9C;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,oCAA8B,QAAQ,KAAK;AAC3C;AAAA,EACJ;AACF;AAGO,SAAS,4BACd,QACA,OAC2B;AAG3B,kBAAgB,OAAO,KAAK,OAAO,MAAM,UAAU;AACnD,QAAM,SAASF,UAAS,OAAO,UAAU;AACzC,UAAQ,QAAQ;AAAA,IACd,KAAK,yBAAyB;AAC5B,MAAAC,gBAAe,QAAQ,CAAC,aAAa,GAAG,UAAU;AAClD,MAAAI,aAAY,OAAO,aAAa,sBAAsB;AACtD,UAAI,OAAO,YAAY,SAAS,wBAAwB,YAAa,CAAAF,MAAK,sBAAsB;AAChG,iBAAW,cAAc,OAAO,YAAa,uBAAsB,YAAY,wBAAwB;AACvG,sBAAgB,QAAQ,wBAAwB,kBAAkB,UAAU;AAC5E;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAF,gBAAe,QAAQ,CAAC,gBAAgB,GAAG,UAAU;AACrD,MAAAC,kBAAiB,OAAO,gBAAgB,yBAAyB;AACjE;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,MAAAD,gBAAe,QAAQ,CAAC,MAAM,SAAS,aAAa,UAAU,kBAAkB,OAAO,GAAG,UAAU;AACpG,iCAA2B,MAAM;AACjC;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA,gBAAe,QAAQ,CAAC,QAAQ,GAAG,UAAU;AAC7C,wBAAkB,OAAO,QAAQ,iBAAiB;AAClD;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA,gBAAe,QAAQ,CAAC,MAAM,QAAQ,GAAG,UAAU;AACnD,UAAI,OAAO,OAAO,OAAO,UAAW,CAAAE,MAAK,aAAa;AACtD,wBAAkB,OAAO,QAAQ,iBAAiB;AAClD;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAF,gBAAe,QAAQ,CAAC,MAAM,kBAAkB,UAAU,aAAa,WAAW,GAAG,UAAU;AAC/F,gCAA0B,QAAQ,KAAK;AACvC;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA,gBAAe,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,UAAU;AACb,iCAA2B,MAAM;AACjC,gCAA0B,QAAQ,IAAI;AACtC,qCAA+B,OAAO,WAAW,oBAAoB;AACrE;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA,gBAAe,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,UAAU;AACb,MAAAI,aAAY,OAAO,OAAO,gBAAgB;AAC1C,UAAI,OAAO,MAAM,SAAS,wBAAwB,qBAAsB,CAAAF,MAAK,gBAAgB;AAC7F,iBAAW,QAAQ,OAAO,MAAO,wBAAuB,MAAM,kBAAkB;AAChF,2BAAqB,OAAO,YAAY,qBAAqB;AAC7D,2BAAqB,OAAO,gBAAgB,yBAAyB;AACrE,UAAI,OAAO,OAAO,kBAAkB,UAAW,CAAAA,MAAK,wBAAwB;AAC5E,UAAI,OAAO,OAAO,iBAAiB,UAAW,CAAAA,MAAK,uBAAuB;AAC1E,MAAAG,iBAAgB,OAAO,iBAAiB,0BAA0B;AAClE,sBAAgB,QAAQ,wBAAwB,uBAAuB,UAAU;AACjF;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAL,gBAAe,QAAQ,CAAC,MAAM,GAAG,UAAU;AAC3C,UAAI,EAAE,UAAU,QAAS,CAAAE,MAAK,eAAe;AAC7C,+BAAyB,OAAO,MAAM,iBAAiB,IAAI;AAC3D;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAF,gBAAe,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,UAAU;AACb,qBAAe,QAAQ,UAAU;AACjC;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA,gBAAe,QAAQ;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAAG,UAAU;AACb,uBAAiB,QAAQ,UAAU;AACnC;AAAA,IACF,KAAK,yBAAyB;AAC5B,UAAI,OAAO,UAAU,MAAM;AACzB,QAAAA,gBAAe,QAAQ,CAAC,SAAS,kBAAkB,UAAU,GAAG,UAAU;AAC1E,QAAAC,kBAAiB,OAAO,gBAAgB,yBAAyB;AACjE,6BAAqB,OAAO,UAAU,mBAAmB;AACzD,YAAI,OAAO,aAAa,OAAW,CAAAC,MAAK,mBAAmB;AAAA,MAC7D,OAAO;AACL,QAAAF,gBAAe,QAAQ;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,GAAG,UAAU;AACb,YAAI,OAAO,UAAU,MAAO,CAAAE,MAAK,gBAAgB;AACjD,QAAAD,kBAAiB,OAAO,gBAAgB,yBAAyB;AACjE,6BAAqB,OAAO,UAAU,mBAAmB;AACzD,YAAI,OAAO,aAAa,OAAW,CAAAC,MAAK,mBAAmB;AAC3D,0BAAkB,QAAQ,wBAAwB,aAAa,UAAU;AAAA,MAC3E;AACA,sBAAgB,QAAQ,wBAAwB,kBAAkB,UAAU;AAC5E;AAAA,IACF,KAAK,yBAAyB;AAC5B,UAAI,OAAO,UAAU,MAAM;AACzB,QAAAF,gBAAe,QAAQ,CAAC,SAAS,UAAU,GAAG,UAAU;AACxD,6BAAqB,OAAO,UAAU,mBAAmB;AACzD,YAAI,OAAO,aAAa,OAAW,CAAAE,MAAK,mBAAmB;AAAA,MAC7D,OAAO;AACL,QAAAF,gBAAe,QAAQ;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,GAAG,UAAU;AACb,uBAAe,QAAQ,UAAU;AAAA,MACnC;AACA,sBAAgB,QAAQ,wBAAwB,sBAAsB,UAAU;AAChF;AAAA,IACF,KAAK,yBAAyB;AAC5B,kCAA4B,QAAQ,UAAU;AAC9C,sBAAgB,QAAQ,wBAAwB,oBAAoB,UAAU;AAC9E;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA;AAAA,QACE;AAAA,QACA,OAAO,UAAU,QACb,CAAC,OAAO,IACR,CAAC,SAAS,YAAY,QAAQ,UAAU,cAAc,YAAY;AAAA,QACtE;AAAA,MACF;AACA,wBAAkB,QAAQ,UAAU;AACpC;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA;AAAA,QACE;AAAA,QACA,OAAO,UAAU,QACb,CAAC,OAAO,IACR,CAAC,SAAS,aAAa,YAAY,QAAQ,UAAU,cAAc,YAAY;AAAA,QACnF;AAAA,MACF;AACA,4BAAsB,QAAQ,UAAU;AACxC;AAAA,IACF,KAAK,yBAAyB;AAC5B,MAAAA,gBAAe,QAAQ,CAAC,YAAY,cAAc,gBAAgB,WAAW,GAAG,UAAU;AAC1F,mBAAa,QAAQ,UAAU;AAC/B;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,aAAO,iCAAiC,QAAQ,KAAK;AAAA,IACvD,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,aAAO,8BAA8B,QAAQ,KAAK;AAAA,EACtD;AACA,SAAO;AACT;AAGO,SAAS,wCACd,QACA,SACA,UACM;AACN,QAAM,gBAAgB;AACtB,QAAM,iBAAiB;AACvB,MACE,cAAc,eAAe,UAC7B,OAAO,eAAe,oBAAoB,UAC1C,CAAAE,MAAK,0BAA0B;AACjC,UAAQ,QAAQ;AAAA,IACd,KAAK,yBAAyB;AAC5B,UACE,cAAc,mBAAmB,UACjC,eAAe,mBAAmB,cAAc,eAChD,CAAAA,MAAK,yBAAyB;AAChC;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,iBAAW,SAAS,CAAC,aAAa,UAAU,gBAAgB,GAAG;AAC7D,YAAI,eAAe,KAAK,MAAM,cAAc,KAAK,EAAG,CAAAA,MAAK,YAAY,KAAK,EAAE;AAAA,MAC9E;AACA;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB,QAAQ;AACpC,YAAM,SAAS,eAAe;AAC9B,UAAI,UAAU,OAAO,UAAU,cAAc,MAAO,CAAAA,MAAK,uBAAuB;AAChF;AAAA,IACF;AAAA,IACA,KAAK,yBAAyB,YAAY;AACxC,mCAA6B,eAAe,cAAc;AAC1D,YAAM,YAAY,eAAe;AACjC,UAAI,cAAc,WAAW,UAAa,UAAU,WAAW,cAAc,QAAQ;AACnF,QAAAA,MAAK,2BAA2B;AAAA,MAClC;AACA;AAAA,IACF;AAAA,IACA,KAAK,yBAAyB,WAAW;AACvC,UACE,eAAe,cAAc,cAAc,aAC3C,eAAe,WAAW,cAAc,aACxC,eAAe,mBAAmB,cAAc,eAChD,CAAAA,MAAK,UAAU;AACjB,YAAM,YAAY,eAAe;AACjC,UACE,UAAU,mBAAmB,cAAc,kBAC3C,UAAU,iBAAiB,cAAc,OACzC,CAAAA,MAAK,oBAAoB;AAC3B,YAAM,YAAY,eAAe;AACjC,UACE,UAAU,mBAAmB,cAAc,kBAC3C,UAAU,QAAQ,cAAc,cAAc,aAC9C,UAAU,QAAQ,WAAW,cAAc,aAC3C,UAAU,QAAQ,SAAS,OAC3B,CAAAA,MAAK,oBAAoB;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,yBAAyB,qBAAqB;AACjD,YAAM,OAAO,eAAe;AAC5B,UAAI,QAAQ,KAAK,mBAAmB,cAAc,eAAgB,CAAAA,MAAK,8BAA8B;AACrG;AAAA,IACF;AAAA,IACA,KAAK,yBAAyB;AAC5B,+BAAyB,eAAe,gBAAgB,wBAAwB,oBAAoB;AACpG;AAAA,IACF,KAAK,yBAAyB,WAAW;AACvC,+BAAyB,eAAe,gBAAgB,wBAAwB,YAAY;AAC5F,YAAM,SAAS,eAAe;AAC9B,UAAI,OAAO,SAAS,cAAc,cAAoC,wBAAwB,6BAA6B;AACzH,QAAAA,MAAK,uBAAuB;AAAA,MAC9B;AACA,UACE,eAAe,cAAc,KAC1B,cAAc,cAAoC,wBAAwB,4BAC7E,CAAAA,MAAK,UAAU;AACjB,UACE,OAAO,eACJ,cAAc,oBAA0C,wBAAwB,iBACnF,CAAAA,MAAK,6BAA6B;AACpC,UACE,gBAAgB,eAAe,KAAK,KACjC,cAAc,oBAA0C,wBAAwB,iBACnF,CAAAA,MAAK,gBAAgB;AACvB,8BAAwB,gBAAgB,cAAc,cAAwB;AAC9E;AAAA,IACF;AAAA,IACA,KAAK,yBAAyB;AAC5B,UAAI,eAAe,mBAAmB,cAAc,gBAAgB;AAClE,QAAAA,MAAK,yBAAyB;AAAA,MAChC;AACA,gCAA0B,eAAe,cAAc;AACvD,UAAI,eAAe,UAAU,KAAM;AACnC,UACE,cAAc,qBAAqB,UACnC,eAAe,aAAa,cAAc,iBAC1C,CAAAA,MAAK,mBAAmB;AAC1B,+BAAyB,eAAe,gBAAgB,wBAAwB,WAAW;AAC3F,8BAAwB,gBAAgB,cAAc,cAAwB;AAC9E;AAAA,IACF,KAAK,yBAAyB;AAC5B,oCAA8B,eAAe,cAAc;AAC3D,UAAI,eAAe,UAAU,MAAM;AACjC;AAAA,UACE;AAAA,UACA;AAAA,UACA,wBAAwB;AAAA,QAC1B;AACA;AAAA,MACF;AACA,UACG,eAAe,MAAoB,UACjC,cAAc,SAA+B,wBAAwB,cACxE,CAAAA,MAAK,gBAAgB;AACvB,8BAAwB,gBAAgB,cAAc,cAAwB;AAC9E;AAAA,QACE;AAAA,QACA;AAAA,QACA,wBAAwB;AAAA,MAC1B;AACA;AAAA,IACF,KAAK,yBAAyB;AAC5B,+BAAyB,eAAe,gBAAgB,wBAAwB,cAAc;AAC9F,UAAI,eAAe,WAAW,cAAc,OAAQ,CAAAA,MAAK,iBAAiB;AAC1E,iBAAW,QAAQ,eAAe,OAAwB;AACxD,YAAI,KAAK,mBAAmB,cAAc,kBAAkB,KAAK,WAAW,cAAc,QAAQ;AAChG,UAAAA,MAAK,gBAAgB;AAAA,QACvB;AAAA,MACF;AACA,gCAA0B,eAAe,cAAc;AACvD;AAAA,IACF,KAAK,yBAAyB;AAC5B;AAAA,QACE;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF,KAAK,yBAAyB,oBAAoB;AAChD,UAAI,eAAe,UAAU,MAAM;AACjC,cAAM,YAAY,eAAe;AACjC,YAAI,UAAU,gBAAgB,cAAc,YAAa,CAAAA,MAAK,gCAAgC;AAAA,MAChG;AACA;AAAA,IACF;AAAA,IACA,KAAK,yBAAyB,iBAAiB;AAC7C,+BAAyB,eAAe,gBAAgB,wBAAwB,YAAY,UAAU;AACtG,YAAM,SAAS,eAAe;AAC9B,UAAI,UAAU,OAAO,UAAU,cAAc,MAAO,CAAAA,MAAK,0BAA0B;AACnF,gCAA0B,eAAe,cAAc;AACvD;AAAA,IACF;AAAA,IACA,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B,6CAAuC,QAAQ,SAAS,QAAQ;AAChE;AAAA,IACF,KAAK,yBAAyB;AAAA,IAC9B,KAAK,yBAAyB;AAC5B;AAAA,EACJ;AACF;AAEA,SAAS,uCACP,QACA,SACA,UACM;AACN,MAAI,CAAC,yBAAyB,MAAM,EAAG,CAAAA,MAAK,QAAQ;AACpD;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,0CACP,QACA,SACA,UACM;AACN,UAAQ,QAAQ;AAAA,IACd,KAAK,8BAA8B;AACjC;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF,KAAK,8BAA8B;AACjC;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF,KAAK,8BAA8B;AACjC;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,EACJ;AACF;AAEA,SAAS,wBAAwB,UAAmC,gBAA8B;AAChG,aAAW,QAAQ,SAAS,OAA4C;AACtE,QAAI,KAAK,mBAAmB,eAAgB,CAAAA,MAAK,+BAA+B;AAAA,EAClF;AACF;AAEA,SAAS,8BACP,SACA,UACM;AACN,MAAI;AACF;AAAA,MACE;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,QACE,OAAO,QAAQ,SAA+B,wBAAwB;AAAA,QACtE,UAAU,QAAQ,YAChB,wBAAwB;AAAA,QAC1B,GAAI,QAAQ,qBAAqB,SAC7B,CAAC,IACD,EAAE,kBAAkB,QAAQ,iBAA2B;AAAA,QAC3D,GAAI,QAAQ,iBAAiB,SACzB,CAAC,IACD,EAAE,cAAc,QAAQ,aAAuB;AAAA,QACnD,GAAI,QAAQ,gBAAgB,SACxB,CAAC,IACD,EAAE,aAAa,QAAQ,YAAsB;AAAA,QACjD,GAAI,QAAQ,qBAAqB,SAC7B,CAAC,IACD,EAAE,kBAAkB,QAAQ,iBAA2B;AAAA,MAC7D;AAAA,IACF;AAAA,EACF,QAAQ;AACN,IAAAA,MAAK,UAAU;AAAA,EACjB;AACA,MAAI,SAAS,MAAO;AACpB,QAAM,QAAQ,SAAS;AACvB,MACE,QAAQ,qBAAqB,UAC5B,QAAQ,mBAA+B,SAAS,gBACjD,CAAC,MAAM,KAAK,UAAQ,KAAK,eAAe,QAAQ,gBAAgB,EAChE,CAAAA,MAAK,2BAA2B;AACpC;AAEA,SAAS,yBACP,SACA,UACA,cACA,aAAa,SACP;AACN,MAAK,SAAS,UAAU,EAAgB,UAAU,QAAQ,SAA+B,eAAe;AACtG,IAAAA,MAAK,YAAY,UAAU,EAAE;AAAA,EAC/B;AACF;AAEA,SAAS,0BACP,SACA,UACA,eAAe,wBAAwB,4BACjC;AACN,QAAM,UAAU,QAAQ,YAAkC;AAC1D,MAAI,eAAe,QAAQ,IAAI,QAAS,CAAAA,MAAK,UAAU;AACzD;AAEA,SAAS,kBAAkB,QAAiC,mBAAkC;AAC5F,EAAAD,kBAAiB,OAAO,WAAW,mBAAmB;AACtD,EAAAA,kBAAiB,OAAO,QAAQ,gBAAgB;AAChD,EAAAA,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE,MAAI,OAAO,OAAO,YAAY,SAAU,CAAAC,MAAK,iBAAiB;AAC9D,MAAI,kBAAmB,CAAAD,kBAAiB,OAAO,cAAc,sBAAsB;AAAA,MAC9E,oBAAmB,OAAO,cAAc,sBAAsB;AACnE,MAAI,OAAO,gBAAgB,QAAW;AACpC,kCAA8B,OAAO,aAAa,OAAO,MAAM;AAC/D,UAAM,cAAc,OAAO;AAC3B,QAAI,YAAY,YAAY,UAAa,YAAY,YAAY,OAAO,SAAS;AAC/E,MAAAC,MAAK,6BAA6B;AAAA,IACpC;AAAA,EACF;AACF;AAEA,SAAS,8BAA8B,OAAgB,QAAsB;AAC3E,QAAM,SAASH,UAAS,OAAO,qBAAqB;AACpD,EAAAC,gBAAe,QAAQ;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,qBAAqB;AACxB,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,MACP,WAAW;AAAA,MACX;AAAA,MACA,MAAM;AAAA,MACN,SAAS,OAAO,WAAW;AAAA,MAC3B,GAAG;AAAA,IACL;AAAA,EACF;AACA,iCAA+B,OAAO,qBAAqB;AAC3D,MAAI;AACF,uCAAmC,2BAA2B,KAAK,CAAC;AAAA,EACtE,QAAQ;AACN,IAAAE,MAAK,qBAAqB;AAAA,EAC5B;AACA,QAAM,aAAoC;AAAA,IACxC,GAAK,OAAO,eAAqD,CAAC;AAAA,IAClE,IAAK,OAAO,SAAmF,CAAC,GAC7F,OAAO,UAAQ,KAAK,SAAS,gBAAgB,KAAK,eAAe,MAAS,EAC1E,IAAI,UAAQ,KAAK,UAAW;AAAA,EACjC;AACA,MAAI,WAAW,SAAS,wBAAwB,wBAAwB;AACtE,IAAAA,MAAK,iCAAiC;AAAA,EACxC;AACA,aAAW,aAAa,YAAY;AAClC,QACE,CAAC,iCAAiC,KAAK,UAAU,WAAW,KAC5D,UAAU,OAAO,yBAAyB,cAC1C,UAAU,SAAS,SAAS,yBAAyB,sBACrD,UAAU,SAAS,SAAS,yBAAyB,mBACrD,CAAAA,MAAK,iCAAiC;AAAA,EAC1C;AACA,kBAAgB,QAAQ,wBAAwB,kBAAkB,qBAAqB;AACzF;AAEA,SAAS,0BAA0B,QAAuC;AACxE,EAAAD,kBAAiB,OAAO,gBAAgB,wBAAwB;AAChE,EAAAA,kBAAiB,OAAO,QAAQ,gBAAgB;AAChD,EAAAA,kBAAiB,OAAO,WAAW,mBAAmB;AACxD;AAEA,SAAS,0BAA0B,QAAiC,OAAsB;AACxF,MAAI,OAAO,OAAO,KAAM,CAAAC,MAAK,aAAa;AAC1C,EAAAD,kBAAiB,OAAO,gBAAgB,yBAAyB;AACjE,EAAAA,kBAAiB,OAAO,QAAQ,iBAAiB;AACjD,EAAAA,kBAAiB,OAAO,WAAW,oBAAoB;AACvD,mCAAiC,OAAO,WAAW,oBAAoB;AACvE,MAAI,CAAC,SAAS,OAAO,UAAU,iBAAiB,OAAO,OAAQ,CAAAC,MAAK,iCAAiC;AACvG;AAEA,SAAS,6BACP,SACA,UACM;AACN,MACE,SAAS,cAAc,QAAQ,aAC/B,SAAS,WAAW,QAAQ,UAC5B,SAAS,mBAAmB,QAAQ,eACpC,CAAAA,MAAK,UAAU;AACjB,QAAM,YAAY,SAAS;AAC3B,MACE,UAAU,mBAAmB,QAAQ,kBACrC,UAAU,iBAAiB,QAAQ,OACnC,CAAAA,MAAK,oBAAoB;AAC7B;AAEA,SAAS,iCACP,OACA,OAC6C;AAC7C,MAAI,CAAC,oBAAoB,KAAK,KAAK,MAAM,SAAS,YAAa,CAAAA,MAAK,KAAK;AACzE,kBAAgB,OAAO,8BAA8B,KAAK;AAC5D;AAEA,SAAS,+BACP,OACA,OAC2C;AAC3C,MAAI,CAAC,oBAAoB,KAAK,KAAK,MAAM,SAAS,UAAW,CAAAA,MAAK,KAAK;AACvE,kBAAgB,OAAO,8BAA8B,KAAK;AAC5D;AAEA,SAAS,2BAA2B,QAAuC;AACzE,MAAI,OAAO,OAAO,QAAQ,OAAO,UAAU,WAAY,CAAAA,MAAK,gBAAgB;AAC5E,EAAAD,kBAAiB,OAAO,OAAO,gBAAgB;AAC/C,EAAAA,kBAAiB,OAAO,WAAW,oBAAoB;AACvD,EAAAA,kBAAiB,OAAO,QAAQ,iBAAiB;AACjD,EAAAA,kBAAiB,OAAO,gBAAgB,yBAAyB;AACnE;AAEA,SAAS,kBACP,QACA,SACA,OACA,kBAAkB,OACZ;AACN,EAAAG,aAAY,OAAO,OAAO,GAAG,KAAK,QAAQ;AAC1C,MAAI,OAAO,MAAM,SAAS,QAAS,CAAAF,MAAK,GAAG,KAAK,QAAQ;AACxD,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,WAAW,OAAO,OAAO;AAClC,QAAI;AACF,0CAAoC,OAAO;AAC3C,sBAAgB,SAAS,wBAAwB,wBAAwB,GAAG,KAAK,UAAU;AAAA,IAC7F,QAAQ;AACN,MAAAA,MAAK,GAAG,KAAK,UAAU;AAAA,IACzB;AACA,QAAI,CAAC,mBAAmB,WAAW,IAAI,QAAQ,SAAS,EAAG,CAAAA,MAAK,GAAG,KAAK,oBAAoB;AAC5F,eAAW,IAAI,QAAQ,SAAS;AAAA,EAClC;AACA,MAAI,OAAO,OAAO,kBAAkB,UAAW,CAAAA,MAAK,GAAG,KAAK,gBAAgB;AAC5E,MAAI,OAAO,OAAO,iBAAiB,UAAW,CAAAA,MAAK,GAAG,KAAK,eAAe;AAC1E,uBAAqB,OAAO,YAAY,GAAG,KAAK,aAAa;AAC7D,uBAAqB,OAAO,gBAAgB,GAAG,KAAK,iBAAiB;AACrE,EAAAG,iBAAgB,OAAO,iBAAiB,GAAG,KAAK,kBAAkB;AACpE;AAEA,SAAS,eAAe,QAAiC,OAAqB;AAC5E,MAAI;AACF,2CAAuC,QAAQ;AAAA,MAC7C,OAAO,wBAAwB;AAAA,MAC/B,UAAU,wBAAwB;AAAA,MAClC,eAAe,wBAAwB;AAAA,IACzC,CAAC;AAAA,EACH,QAAQ;AACN,IAAAH,MAAK,KAAK;AAAA,EACZ;AACF;AAEA,SAAS,eAAe,QAAiC,OAAqB;AAC5E,EAAAE,aAAY,OAAO,OAAO,GAAG,KAAK,QAAQ;AAC1C,MAAI,OAAO,MAAM,SAAS,wBAAwB,aAAc,CAAAF,MAAK,GAAG,KAAK,QAAQ;AACrF,QAAM,UAAU,oBAAI,IAAY;AAChC,aAAW,SAAS,OAAO,OAAO;AAChC,sBAAkB,OAAO,GAAG,KAAK,UAAU;AAC3C,QAAI,QAAQ,IAAI,MAAM,MAAM,EAAG,CAAAA,MAAK,GAAG,KAAK,iBAAiB;AAC7D,YAAQ,IAAI,MAAM,MAAM;AAAA,EAC1B;AACA,uBAAqB,QAAQ,KAAK;AAClC,QAAM,SAASH,UAAS,OAAO,QAAQ,GAAG,KAAK,SAAS;AACxD,uBAAqB,OAAO,OAAO,GAAG,KAAK,iBAAiB,GAAG,wBAAwB,mBAAmB;AAC1G,uBAAqB,OAAO,aAAa,GAAG,KAAK,uBAAuB,GAAG,wBAAwB,eAAe;AAClH,MAAI,OAAO,OAAO,cAAc,UAAW,CAAAG,MAAK,GAAG,KAAK,mBAAmB;AAC3E,kBAAgB,QAAQ,wBAAwB,qBAAqB,KAAK;AAC5E;AAEA,SAAS,iBAAiB,QAAiC,OAAqB;AAC9E,EAAAD,kBAAiB,OAAO,QAAQ,GAAG,KAAK,SAAS;AACjD,EAAAG,aAAY,OAAO,OAAO,GAAG,KAAK,QAAQ;AAC1C,MAAI,OAAO,MAAM,SAAS,wBAAwB,eAAgB,CAAAF,MAAK,GAAG,KAAK,QAAQ;AACvF,aAAW,WAAW,OAAO,OAAO;AAClC,QAAI;AACF,0CAAoC,OAAO;AAAA,IAC7C,QAAQ;AACN,MAAAA,MAAK,GAAG,KAAK,UAAU;AAAA,IACzB;AAAA,EACF;AACA,uBAAqB,QAAQ,KAAK;AAClC,kBAAgB,QAAQ,wBAAwB,kBAAkB,KAAK;AACzE;AAEA,SAAS,yBACP,OACA,OACiD;AACjD,QAAM,SAASH,UAAS,OAAO,KAAK;AACpC,MAAI,OAAO,SAAS,QAAQ;AAC1B,IAAAC,gBAAe,QAAQ,CAAC,QAAQ,UAAU,QAAQ,GAAG,KAAK;AAC1D,IAAAC,kBAAiB,OAAO,QAAQ,GAAG,KAAK,SAAS;AACjD,yBAAqB,OAAO,QAAQ,GAAG,KAAK,SAAS;AACrD;AAAA,EACF;AACA,MAAI,OAAO,SAAS,kBAAkB;AACpC,IAAAD,gBAAe,QAAQ,CAAC,QAAQ,WAAW,QAAQ,GAAG,KAAK;AAC3D,IAAAC,kBAAiB,OAAO,SAAS,GAAG,KAAK,UAAU;AACnD,yBAAqB,OAAO,QAAQ,GAAG,KAAK,SAAS;AACrD,QAAI,OAAO,WAAW,OAAW,CAAAC,MAAK,GAAG,KAAK,SAAS;AACvD;AAAA,EACF;AACA,EAAAA,MAAK,GAAG,KAAK,OAAO;AACtB;AAEA,SAAS,4BAA4B,QAAiC,OAAqB;AACzF,MAAI,OAAO,UAAU,MAAM;AACzB,IAAAF,gBAAe,QAAQ,CAAC,SAAS,kBAAkB,UAAU,GAAG,KAAK;AACrE,IAAAC,kBAAiB,OAAO,gBAAgB,GAAG,KAAK,iBAAiB;AACjE,yBAAqB,OAAO,UAAU,GAAG,KAAK,WAAW;AACzD,QAAI,OAAO,aAAa,OAAW,CAAAC,MAAK,GAAG,KAAK,WAAW;AAC3D;AAAA,EACF;AACA,EAAAF,gBAAe,QAAQ;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,KAAK;AACR,MAAI,OAAO,UAAU,MAAO,CAAAE,MAAK,GAAG,KAAK,QAAQ;AACjD,EAAAD,kBAAiB,OAAO,gBAAgB,GAAG,KAAK,iBAAiB;AACjE,uBAAqB,OAAO,UAAU,GAAG,KAAK,WAAW;AACzD,MAAI,OAAO,aAAa,OAAW,CAAAC,MAAK,GAAG,KAAK,WAAW;AAC3D,mCAAiC,OAAO,OAAO,GAAG,KAAK,QAAQ;AAC/D,EAAAE,aAAY,OAAO,OAAO,GAAG,KAAK,QAAQ;AAC1C,MAAI,OAAO,MAAM,SAAS,wBAAwB,mBAAoB,CAAAF,MAAK,GAAG,KAAK,QAAQ;AAC3F,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,QAAQ,OAAO,OAAO;AAC/B,QAAI;AACF,0CAAoC,MAAM,OAAO,cAAc;AAC/D,sBAAgB,MAAM,wBAAwB,wBAAwB,GAAG,KAAK,UAAU;AAAA,IAC1F,QAAQ;AACN,MAAAA,MAAK,GAAG,KAAK,UAAU;AAAA,IACzB;AACA,QAAI,WAAW,IAAI,KAAK,SAAS,EAAG,CAAAA,MAAK,GAAG,KAAK,oBAAoB;AACrE,eAAW,IAAI,KAAK,SAAS;AAAA,EAC/B;AACA,MAAI,OAAO,OAAO,kBAAkB,UAAW,CAAAA,MAAK,GAAG,KAAK,gBAAgB;AAC5E,MAAI,OAAO,OAAO,iBAAiB,UAAW,CAAAA,MAAK,GAAG,KAAK,eAAe;AAC1E,uBAAqB,OAAO,gBAAgB,GAAG,KAAK,iBAAiB;AACrE,uBAAqB,OAAO,YAAY,GAAG,KAAK,aAAa;AAC7D,MAAI,OAAO,MAAM,WAAW,GAAG;AAC7B,QACE,OAAO,iBAAiB,OAAO,gBAC/B,OAAO,mBAAmB,UAAa,OAAO,eAAe,OAC7D,CAAAA,MAAK,GAAG,KAAK,QAAQ;AACvB;AAAA,EACF;AACA,MAAI,OAAO,mBAAmB,OAAO,mBAAmB,QAAY,CAAAA,MAAK,GAAG,KAAK,iBAAiB;AAClG,MAAI,OAAO,kBAAkB,OAAO,eAAe,QAAY,CAAAA,MAAK,GAAG,KAAK,aAAa;AAC3F;AAEA,SAAS,iCAAiC,OAAgB,OAAqB;AAC7E,QAAM,SAASH,UAAS,OAAO,KAAK;AACpC,MAAI,OAAO,SAAS,QAAQ;AAC1B,IAAAC,gBAAe,QAAQ,CAAC,QAAQ,UAAU,WAAW,QAAQ,GAAG,KAAK;AACrE,IAAAC,kBAAiB,OAAO,QAAQ,GAAG,KAAK,SAAS;AACjD,uBAAmB,OAAO,SAAS,GAAG,KAAK,UAAU;AACrD,yBAAqB,OAAO,QAAQ,GAAG,KAAK,SAAS;AACrD;AAAA,EACF;AACA,MAAI,OAAO,SAAS,aAAc,CAAAC,MAAK,GAAG,KAAK,OAAO;AACtD,EAAAF,gBAAe,QAAQ,CAAC,QAAQ,SAAS,mBAAmB,eAAe,GAAG,KAAK;AACnF,MAAI;AACF,8CAA0C,OAAO,OAAO;AAAA,MACtD,gBAAgB,wBAAwB;AAAA,IAC1C,CAAC;AAAA,EACH,QAAQ;AACN,IAAAE,MAAK,GAAG,KAAK,QAAQ;AAAA,EACvB;AACA,MAAI,OAAO,oBAAoB,QAAQ;AACrC,QAAI,OAAO,kBAAkB,OAAW,CAAAA,MAAK,GAAG,KAAK,gBAAgB;AACrE;AAAA,EACF;AACA,MAAI,OAAO,oBAAoB,YAAY,OAAO,oBAAoB,SAAS;AAC7E,IAAAA,MAAK,GAAG,KAAK,kBAAkB;AAAA,EACjC;AACA,EAAAD,kBAAiB,OAAO,eAAe,GAAG,KAAK,gBAAgB;AACjE;AAEA,SAAS,+BACP,SACA,UACM;AACN,MAAI,SAAS,mBAAmB,QAAQ,eAAgB,CAAAC,MAAK,yBAAyB;AACtF;AAAA,IACE;AAAA,IACA;AAAA,IACA,wBAAwB;AAAA,EAC1B;AACA,MAAI,SAAS,MAAO;AACpB,MAAI,SAAS,aAAa,QAAQ,iBAAkB,CAAAA,MAAK,mBAAmB;AAC5E,MAAI,SAAS,MAAM,UAAU,QAAQ,eAAe,wBAAwB,qBAAqB;AAC/F,IAAAA,MAAK,gBAAgB;AAAA,EACvB;AACA,aAAW,QAAQ,SAAS,OAAO;AACjC,QAAI,KAAK,mBAAmB,QAAQ,eAAgB,CAAAA,MAAK,gBAAgB;AAAA,EAC3E;AACA,MAAI,QAAQ,MAAM,SAAS,QAAQ;AACjC,QACE,SAAS,MAAM,SAAS,UACxB,SAAS,MAAM,WAAW,QAAQ,MAAM,UACxC,SAAS,MAAM,YAAY,UAC3B,SAAS,MAAM,WAAW,QAAQ,MAAM,QACxC;AACA,MAAAA,MAAK,gBAAgB;AAAA,IACvB;AACA;AAAA,EACF;AACA,MAAI,SAAS,MAAM,SAAS,QAAQ;AAClC,QACE,SAAS,MAAM,YAAY,QAAQ,MAAM,WACzC,SAAS,MAAM,WAAW,QAAQ,MAAM,OACxC,CAAAA,MAAK,gBAAgB;AACvB;AAAA,EACF;AACA,MACE,SAAS,MAAM,MAAM,YAAY,QAAQ,MAAM,WAC/C,SAAS,MAAM,MAAM,WAAW,QAAQ,MAAM,OAC9C,CAAAA,MAAK,gBAAgB;AACzB;AAEA,SAAS,kBAAkB,OAAgB,OAA2D;AACpG,QAAM,SAASH,UAAS,OAAO,KAAK;AACpC,EAAAE,kBAAiB,OAAO,QAAQ,GAAG,KAAK,SAAS;AACjD,EAAAA,kBAAiB,OAAO,gBAAgB,GAAG,KAAK,iBAAiB;AACjE,uBAAqB,OAAO,QAAQ,GAAG,KAAK,SAAS;AACrD,MAAI,OAAO,WAAW,OAAW,CAAAC,MAAK,GAAG,KAAK,SAAS;AACvD,uBAAqB,OAAO,WAAW,GAAG,KAAK,cAAc,GAAG,OAAO,gBAAgB;AACvF,uBAAqB,OAAO,WAAW,GAAG,KAAK,cAAc,GAAG,OAAO,gBAAgB;AACvF,gBAAc,OAAO,aAAa,GAAG,KAAK,cAAc;AACxD,EAAAE,aAAY,OAAO,qBAAqB,GAAG,KAAK,sBAAsB;AACtE,MAAI,OAAO,oBAAoB,SAAS,KAAK,eAAe,OAAO,mBAAmB,IAAI,MAAO;AAC/F,IAAAF,MAAK,GAAG,KAAK,sBAAsB;AAAA,EACrC;AACA,aAAW,CAAC,OAAO,gBAAgB,KAAK,OAAO,oBAAoB,QAAQ,GAAG;AAC5E,UAAM,cAAcH,UAAS,kBAAkB,GAAG,KAAK,wBAAwB,KAAK,GAAG;AACvF,QACE,QAAQ,QAAQ,WAAW,EAAE,KAAK,SAAO,OAAO,QAAQ,YAAY,CAAC,CAAC,WAAW,cAAc,QAAQ,SAAS,EAAE,SAAS,GAAG,CAAC,KAC/H,OAAO,YAAY,YAAY,YAAY,YAAY,QAAQ,WAAW,KAAK,YAAY,QAAQ,SAAS,OAC5G,OAAO,YAAY,eAAe,YAAY,YAAY,WAAW,WAAW,KAAK,YAAY,WAAW,SAAS,OACpH,YAAY,SAAS,eAAe,YAAY,SAAS,WAC1D,OAAO,YAAY,YAAY,YAAY,YAAY,QAAQ,SAAS,IACxE,CAAAG,MAAK,GAAG,KAAK,wBAAwB,KAAK,GAAG;AAAA,EACjD;AACA,uBAAqB,OAAO,eAAe,GAAG,KAAK,kBAAkB,GAAG,OAAO,gBAAgB;AAC/F,MAAI,OAAO,gBAAgB,OAAO,oBAAoB,OAAQ,CAAAA,MAAK,GAAG,KAAK,gBAAgB;AAC3F,MACE,OAAO,aAAa,UACpB,CAAC,CAAC,YAAY,UAAU,WAAW,aAAa,UAAU,WAAW,EAAE,SAAS,OAAO,QAAkB,EACzG,CAAAA,MAAK,GAAG,KAAK,WAAW;AAC1B,MAAI,OAAO,OAAO,iBAAiB,UAAW,CAAAA,MAAK,GAAG,KAAK,eAAe;AAC1E,yBAAuB,OAAO,uBAAuB,GAAG,KAAK,0BAA0B,GAAG,OAAO,gBAAgB;AACjH,MAAI,OAAO,OAAO,gBAAgB,UAAW,CAAAA,MAAK,GAAG,KAAK,cAAc;AACxE,MAAI,OAAO,gBAAgB,aAAa,OAAO,gBAAgB,UAAU,OAAO,gBAAgB,aAAa;AAC3G,IAAAA,MAAK,GAAG,KAAK,cAAc;AAAA,EAC7B;AACA,MAAI,OAAO,aAAa,QAAW;AACjC,QAAI,OAAO,gBAAgB,OAAQ,CAAAA,MAAK,GAAG,KAAK,WAAW;AAC3D,IAAAE,aAAY,OAAO,UAAU,GAAG,KAAK,WAAW;AAChD,QAAI,OAAO,SAAS,SAAS,wBAAwB,eAAgB,CAAAF,MAAK,GAAG,KAAK,WAAW;AAC7F,eAAW,WAAW,OAAO,SAAU,mBAAkB,SAAS,GAAG,KAAK,aAAa;AAAA,EACzF;AACF;AAEA,SAAS,qBAAqB,QAAiC,OAAe,OAAO,MAAY;AAC/F,MAAI,OAAO,OAAO,kBAAkB,UAAW,CAAAA,MAAK,GAAG,KAAK,gBAAgB;AAC5E,MAAI,OAAO,OAAO,iBAAiB,UAAW,CAAAA,MAAK,GAAG,KAAK,eAAe;AAC1E,uBAAqB,OAAO,YAAY,GAAG,KAAK,aAAa;AAC7D,uBAAqB,OAAO,gBAAgB,GAAG,KAAK,iBAAiB;AACrE,MAAI,KAAM,CAAAG,iBAAgB,OAAO,iBAAiB,GAAG,KAAK,kBAAkB;AAC9E;AAEA,SAAS,kBAAkB,QAAiC,OAAqB;AAC/E,MAAI,OAAO,UAAU,MAAO;AAC5B,MAAI,OAAO,UAAU,QAAQ,OAAO,aAAa,cAAe,CAAAH,MAAK,GAAG,KAAK,WAAW;AACxF,cAAY,QAAQ,wBAAwB,kBAAkB,KAAK;AACrE;AAEA,SAAS,sBAAsB,QAAiC,OAAqB;AACnF,MAAI,OAAO,UAAU,MAAO;AAC5B,MAAI,OAAO,UAAU,QAAQ,OAAO,aAAa,SAAU,CAAAA,MAAK,GAAG,KAAK,WAAW;AACnF,EAAAI,2BAA0B,OAAO,WAAW,GAAG,KAAK,YAAY;AAChE,cAAY,QAAQ,wBAAwB,sBAAsB,KAAK;AACzE;AAEA,SAAS,YAAY,QAAiC,cAAsB,OAAqB;AAC/F,MAAI,OAAO,OAAO,SAAS,YAAY,CAAC,kBAAkB,OAAO,IAAI,EAAG,CAAAJ,MAAK,GAAG,KAAK,OAAO;AAC5F,QAAM,aAAa,wBAAwB,OAAO,IAAI;AACtD,MAAI,aAAa,aAAc,CAAAA,MAAK,GAAG,KAAK,OAAO;AACnD,uBAAqB,OAAO,QAAQ,GAAG,KAAK,WAAW,GAAG,OAAO,gBAAgB;AACjF,uBAAqB,OAAO,YAAY,GAAG,KAAK,eAAe,GAAG,OAAO,gBAAgB;AACzF,yBAAuB,OAAO,YAAY,GAAG,KAAK,eAAe,GAAG,OAAO,gBAAgB;AAC3F,MAAI,OAAO,SAAS,aAAa,OAAO,WAAY,CAAAA,MAAK,GAAG,KAAK,aAAa;AAC9E,QAAM,eAAe,OAAO,SAAS;AACrC,MAAI,OAAO,eAAe,UAAa,OAAO,eAAe,aAAc,CAAAA,MAAK,GAAG,KAAK,aAAa;AACrG,MAAI,OAAO,eAAe,UAAa,iBAAiB,OAAO,WAAY,CAAAA,MAAK,GAAG,KAAK,aAAa;AACvG;AAEA,SAAS,aAAa,QAAiC,OAAqB;AAC1E,EAAAE,aAAY,OAAO,UAAU,GAAG,KAAK,WAAW;AAChD,MAAI,OAAO,SAAS,SAAS,wBAAwB,WAAY,CAAAF,MAAK,GAAG,KAAK,WAAW;AACzF,aAAW,SAAS,OAAO,UAAU;AACnC,UAAM,UAAUH,UAAS,OAAO,GAAG,KAAK,aAAa;AACrD,IAAAE,kBAAiB,QAAQ,WAAW,GAAG,KAAK,uBAAuB;AACnE,mBAAe,QAAQ,MAAM,GAAG,KAAK,kBAAkB;AACvD,QACE,OAAO,QAAQ,YAAY,YAC3B,QAAQ,QAAQ,SAAS,wBAAwB,wBACjD,CAAAC,MAAK,GAAG,KAAK,qBAAqB;AAAA,EACtC;AACA,uBAAqB,OAAO,YAAY,GAAG,KAAK,aAAa;AAC7D,MAAI,OAAO,OAAO,iBAAiB,UAAW,CAAAA,MAAK,GAAG,KAAK,eAAe;AAC1E,oBAAkB,OAAO,WAAW,GAAG,KAAK,YAAY;AACxD,kBAAgB,QAAQ,wBAAwB,iBAAiB,KAAK;AACxE;AAEA,SAAS,sBAAsB,OAAgB,OAAqB;AAClE,QAAM,SAASH,UAAS,OAAO,KAAK;AACpC,EAAAE,kBAAiB,OAAO,IAAI,GAAG,KAAK,KAAK;AACzC,MAAI,OAAO,OAAO,SAAS,YAAY,OAAO,OAAO,gBAAgB,YAAY,OAAO,OAAO,iBAAiB,SAAU,CAAAC,MAAK,KAAK;AACpI,EAAAE,aAAY,OAAO,OAAO,GAAG,KAAK,QAAQ;AAC1C,MAAI,CAAC,OAAO,MAAM,MAAM,UAAQ,OAAO,SAAS,QAAQ,EAAG,CAAAF,MAAK,GAAG,KAAK,QAAQ;AAChF,MAAI,OAAO,OAAO,YAAY,SAAU,CAAAA,MAAK,GAAG,KAAK,UAAU;AACjE;AAEA,SAAS,uBAAuB,OAAgB,OAAkD;AAChG,QAAM,SAASH,UAAS,OAAO,KAAK;AACpC,EAAAE,kBAAiB,OAAO,gBAAgB,GAAG,KAAK,iBAAiB;AACjE,MACE,OAAO,OAAO,UAAU,YAAY,OAAO,MAAM,SAAS,OAC1D,OAAO,OAAO,uBAAuB,YAAY,OAAO,mBAAmB,SAAS,OACpF,OAAO,OAAO,iBAAiB,YAC/B,OAAO,OAAO,iBAAiB,YAC/B,OAAO,OAAO,oBAAoB,UAClC,CAAAC,MAAK,KAAK;AACZ,uBAAqB,OAAO,sBAAsB,GAAG,KAAK,yBAAyB,GAAG,OAAO,gBAAgB;AAC7G,uBAAqB,OAAO,cAAc,GAAG,KAAK,iBAAiB,GAAG,OAAO,gBAAgB;AAC7F,uBAAqB,OAAO,aAAa,GAAG,KAAK,gBAAgB,GAAG,OAAO,gBAAgB;AAC7F;AAEA,SAAS,yBAAyB,OAAgB,OAAe,WAAW,OAAa;AACvF,MAAI,UAAU,UAAc,YAAY,UAAU,KAAO;AACzD,yBAAuB,OAAO,KAAK;AACrC;AAEA,SAAS,kBACP,OACA,OACA,eAAe,wBAAwB,wBACT;AAC9B,MAAI;AACF,yCAAqC,KAAK;AAC1C,oBAAgB,OAAO,cAAc,KAAK;AAAA,EAC5C,QAAQ;AACN,IAAAA,MAAK,KAAK;AAAA,EACZ;AACF;AAGO,SAAS,iCAAiC,OAA6B;AAC5E,oBAAkB,OAAO,iBAAiB,wBAAwB,kBAAkB;AACpF,SAAO;AACT;AAEA,SAAS,eAAe,OAAgB,OAAqB;AAC3D,MAAI,UAAU,UAAU,UAAU,eAAe,UAAU,UAAU,UAAU,WAAW,UAAU,QAAS,CAAAA,MAAK,KAAK;AACzH;AAEA,SAASI,2BAA0B,OAAgB,OAAqB;AACtE,QAAM,SAASP,UAAS,OAAO,KAAK;AACpC,EAAAE,kBAAiB,OAAO,aAAa,GAAG,KAAK,cAAc;AAC3D,MAAI,OAAO,OAAO,aAAa,YAAY,OAAO,OAAO,aAAa,SAAU,CAAAC,MAAK,KAAK;AAC1F,uBAAqB,OAAO,MAAM,GAAG,KAAK,SAAS,GAAG,OAAO,gBAAgB;AAC/E;AAEA,SAAS,kBAAkB,OAAgB,OAAqB;AAC9D,MAAI,UAAU,KAAM;AACpB,QAAM,SAASH,UAAS,OAAO,KAAK;AACpC,EAAAC,gBAAe,QAAQ;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,KAAK;AACR,EAAAC,kBAAiB,OAAO,OAAO,GAAG,KAAK,QAAQ;AAC/C,EAAAA,kBAAiB,OAAO,WAAW,GAAG,KAAK,YAAY;AACvD,EAAAA,kBAAiB,OAAO,QAAQ,GAAG,KAAK,SAAS;AACjD,EAAAA,kBAAiB,OAAO,gBAAgB,GAAG,KAAK,iBAAiB;AACjE,EAAAA,kBAAiB,OAAO,cAAc,GAAG,KAAK,eAAe;AAC7D,EAAAA,kBAAiB,OAAO,eAAe,GAAG,KAAK,gBAAgB;AAC/D,EAAAA,kBAAiB,OAAO,eAAe,GAAG,KAAK,gBAAgB;AAC/D,MAAI,CAAC,CAAC,YAAY,UAAU,WAAW,aAAa,UAAU,WAAW,EAAE,SAAS,OAAO,KAAe,EAAG,CAAAC,MAAK,GAAG,KAAK,QAAQ;AAClI,uBAAqB,OAAO,YAAY,GAAG,KAAK,eAAe,GAAG,OAAO,gBAAgB;AACzF,uBAAqB,OAAO,WAAW,GAAG,KAAK,cAAc,GAAG,OAAO,gBAAgB;AACvF,yBAAuB,OAAO,WAAW,GAAG,KAAK,cAAc,GAAG,OAAO,gBAAgB;AACzF,yBAAuB,OAAO,YAAY,GAAG,KAAK,eAAe,GAAG,OAAO,gBAAgB;AAC3F,yBAAuB,OAAO,mBAAmB,GAAG,KAAK,sBAAsB,GAAG,OAAO,gBAAgB;AACzG,MAAI,OAAO,UAAU,QAAW;AAC9B,QAAI;AACF,6BAAuB,OAAO,KAAK;AAAA,IACrC,QAAQ;AACN,MAAAA,MAAK,GAAG,KAAK,QAAQ;AAAA,IACvB;AAAA,EACF;AACF;AAEA,SAASH,UAAS,OAAgB,OAAwC;AACxE,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,CAAAG,MAAK,KAAK;AACnF,SAAO;AACT;AAEA,SAASF,gBACP,QACA,SACA,OACM;AACN,MAAI,OAAO,KAAK,MAAM,EAAE,KAAK,SAAO,CAAC,QAAQ,SAAS,GAAG,CAAC,EAAG,CAAAE,MAAK,KAAK;AACzE;AAEA,SAASE,aAAY,OAAgB,OAA2C;AAC9E,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,CAAAF,MAAK,KAAK;AACvC;AAEA,SAASD,kBAAiB,OAAgB,OAAwC;AAChF,MACE,OAAO,UAAU,YACjB,MAAM,WAAW,KACjB,MAAM,SAAS,wBAAwB,wBACvC,UAAU,MAAM,KAAK,KACrB,oBAAoB,KAAK,EACzB,CAAAC,MAAK,KAAK;AACd;AAEA,SAAS,mBAAmB,OAAgB,OAAqB;AAC/D,MAAI,UAAU,OAAW,CAAAD,kBAAiB,OAAO,KAAK;AACxD;AAEA,SAAS,eAAe,OAAgB,OAAqB;AAC3D,MAAI,UAAU,UAAa,OAAO,UAAU,SAAU,CAAAC,MAAK,KAAK;AAClE;AAEA,SAAS,4BAA4B,OAAgB,OAAqB;AACxE;AAAA,IACE;AAAA,IACA;AAAA,IACA,wBAAwB;AAAA,IACxB,wBAAwB;AAAA,EAC1B;AACF;AAEA,SAAS,0BAA0B,OAAgB,OAAqB;AACtE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA,wBAAwB;AAAA,EAC1B;AACF;AAEA,SAAS,wBAAwB,OAAgB,OAAqB;AACpE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA,wBAAwB;AAAA,EAC1B;AACF;AAEA,SAASG,iBAAgB,OAAgB,OAAqB;AAC5D,MAAI,UAAU,UAAa,OAAO,UAAU,UAAW,CAAAH,MAAK,KAAK;AACnE;AAEA,SAAS,qBAAqB,OAAgB,OAAqB;AACjE,MACE,UAAU,WACT,OAAO,UAAU,YAChB,MAAM,WAAW,KACjB,MAAM,SAAS,wBAAwB,oBACvC,UAAU,MAAM,KAAK,KACrB,oBAAoB,KAAK,GAC3B,CAAAA,MAAK,KAAK;AACd;AAEA,SAAS,cAAc,OAAgB,OAAqB;AAC1D,MAAI,OAAO,UAAU,YAAY,MAAM,SAAS,wBAAwB,4BAA4B,EAAG,CAAAA,MAAK,KAAK;AACnH;AAEA,SAAS,oBAAoB,OAAwB;AACnD,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,MAAM,SAAS,IAAK,QAAO;AAAA,EACzC;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,OAAgB,OAAe,SAAiB,SAA0C;AACtH,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,WAAW,QAAQ,QAAS,CAAAA,MAAK,KAAK;AACjH;AAEA,SAAS,uBAAuB,OAAgB,OAAe,SAAiB,SAAuB;AACrG,MAAI,UAAU,OAAW,sBAAqB,OAAO,OAAO,SAAS,OAAO;AAC9E;AAEA,SAAS,kBAAkB,OAAgB,OAAqB;AAC9D,MAAI,UAAU,UAAa,UAAU,cAAc,UAAU,UAAW,CAAAA,MAAK,KAAK;AACpF;AAEA,SAAS,kBAAkB,OAAgB,OAAqB;AAC9D,MAAI,UAAU,UAAa,UAAU,mBAAmB,UAAU,kBAAkB,UAAU,YAAa,CAAAA,MAAK,KAAK;AACvH;AAEA,SAAS,gBAAgB,OAAgB,SAAiB,OAAqB;AAC7E,MAAI,eAAe,KAAK,IAAI,QAAS,CAAAA,MAAK,KAAK;AACjD;AAEA,SAAS,eAAe,OAAwB;AAC9C,MAAI;AACF,WAAO,mBAAmB,OAAO;AAAA,MAC/B,UAAU,KAAK,OAAO;AAAA,MACtB,gBAAgB,KAAK,OAAO;AAAA,MAC5B,oBAAoB,KAAK,OAAO;AAAA,MAChC,UAAU;AAAA,IACZ,CAAC,EAAE;AAAA,EACL,QAAQ;AACN,WAAO,OAAO;AAAA,EAChB;AACF;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,OAAO;AACzC,MAAI,QAAQ;AACZ,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS;AACf,UAAM,cAAc,OAAO;AAC3B,QAAI,OAAO,gBAAgB,SAAU,UAAS,YAAY,MAAM,IAAI,EAAE;AACtE,QAAI,MAAM,QAAQ,OAAO,mBAAmB,GAAG;AAC7C,iBAAW,eAAe,OAAO,qBAAqB;AACpD,cAAM,UAAW,aAAyC;AAC1D,YAAI,OAAO,YAAY,SAAU,UAAS,QAAQ,MAAM,IAAI,EAAE;AAAA,MAChE;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,OAAwB;AACjD,SAAO,MAAM,SAAS,MAAM,KAAK,mEAAmE,KAAK,KAAK;AAChH;AAEA,SAAS,wBAAwB,OAAuB;AACtD,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,UAAU,MAAM,SAAS,IAAI,IAAI,IAAI,MAAM,SAAS,GAAG,IAAI,IAAI;AACrE,SAAO,MAAM,SAAS,IAAI,IAAI;AAChC;AAEA,SAASA,MAAK,OAAsB;AAClC,QAAM,IAAI,4BAA4B,KAAK;AAC7C;;;AC14DO,SAAS,2BAA2B,SAAsC;AAC/E,iBAAe,QACb,QACA,YACA,cAAyC,CAAC,GACN;AACpC,gBAAY,QAAQ,eAAe;AACnC,gCAA4B,QAAQ,UAAU;AAC9C,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,EAAE,gBAAgB,QAAQ,gBAAgB,QAAQ,YAAY,OAAO;AAAA,IACvE;AACA,gBAAY,QAAQ,eAAe;AACnC,UAAM,SAAS,4BAA4B,QAAQ,QAAQ;AAC3D,4CAAwC,QAAQ,YAAY,MAAM;AAClE,WAAO;AAAA,EACT;AAEA,iBAAe,eACb,aAAkD,CAAC,GACnD,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,gBAAgB,YAAY,WAAW;AAAA,EACjF;AAEA,iBAAe,YAAY,YAAyC,cAAyC,CAAC,GAAG;AAC/G,WAAO,QAAQ,yBAAyB,QAAQ,YAAY,WAAW;AAAA,EACzE;AAEA,iBAAe,KAAK,YAAuC,cAAyC,CAAC,GAAG;AACtG,WAAO,QAAQ,yBAAyB,MAAM,YAAY,WAAW;AAAA,EACvE;AAEA,iBAAe,QAAQ,YAA0C,cAAyC,CAAC,GAAG;AAC5G,WAAO,QAAQ,yBAAyB,SAAS,YAAY,WAAW;AAAA,EAC1E;AAEA,WAAS,iBAAiB,YAAoF;AAC5G,UAAM,YAAY,WAAW,QAAQ,cAClC,QAAQ,mBAAmB,+BAA+B;AAC7D,UAAM,SAAS,WAAW,QAAQ,WAC/B,QAAQ,mBAAmB,+BAA+B;AAC7D,WAAO,WAAW,SAAS,SACvB,EAAE,MAAM,QAAQ,SAAS,EAAE,GAAG,WAAW,SAAS,WAAW,OAAO,EAAE,IACtE,EAAE,MAAM,WAAW,SAAS,EAAE,GAAG,WAAW,SAAS,WAAW,OAAO,EAAE;AAAA,EAC/E;AAEA,iBAAe,UACb,YACA,cAAyC,CAAC,GAC1C;AACA,WAAO,WAAW,SAAS,SACvB,KAAK,WAAW,SAAS,WAAW,IACpC,QAAQ,WAAW,SAAS,WAAW;AAAA,EAC7C;AAEA,iBAAe,aAAa,YAA+C,cAAyC,CAAC,GAAG;AACtH,WAAO,QAAQ,yBAAyB,cAAc,YAAY,WAAW;AAAA,EAC/E;AAEA,iBAAe,OAAO,YAAyC,cAAyC,CAAC,GAAG;AAC1G,WAAO,QAAQ,yBAAyB,QAAQ,YAAY,WAAW;AAAA,EACzE;AAEA,iBAAe,WACb,YACA,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,YAAY,YAAY,WAAW;AAAA,EAC7E;AAEA,iBAAe,UACb,YACA,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,WAAW,YAAY,WAAW;AAAA,EAC5E;AAEA,iBAAe,kBACb,aAAqD,CAAC,GACtD,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,mBAAmB,YAAY,WAAW;AAAA,EACpF;AAEA,iBAAe,oBACb,YACA,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,qBAAqB,YAAY,WAAW;AAAA,EACtF;AAEA,iBAAe,UAAU,YAA4C,cAAyC,CAAC,GAAG;AAChH,WAAO,QAAQ,yBAAyB,WAAW;AAAA,MACjD,GAAG;AAAA,MACH,YAAY,WAAW,cAAc,wBAAwB;AAAA,IAC/D,GAAG,WAAW;AAAA,EAChB;AAEA,iBAAe,cACb,YACA,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,eAAe;AAAA,MACrD,GAAG;AAAA,MACH,OAAO,WAAW,SAAS,wBAAwB;AAAA,MACnD,UAAU,WAAW,YAAY,wBAAwB;AAAA,IAC3D,GAAG,WAAW;AAAA,EAChB;AAEA,iBAAe,eAAe,YAAiD,cAAyC,CAAC,GAAG;AAC1H,WAAO,QAAQ,yBAAyB,gBAAgB;AAAA,MACtD,GAAG;AAAA,MACH,MAAM,WAAW,QAAQ;AAAA,MACzB,UAAU,WAAW,YAAY,wBAAwB;AAAA,IAC3D,GAAG,WAAW;AAAA,EAChB;AAEA,iBAAe,4BACb,YACA,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,6BAA6B;AAAA,MACnE,GAAG;AAAA,MACH,OAAO,WAAW,SAAS,wBAAwB;AAAA,MACnD,UAAU,WAAW,YAAY,wBAAwB;AAAA,IAC3D,GAAG,WAAW;AAAA,EAChB;AAEA,iBAAe,WACb,YACA,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,YAAY;AAAA,MAClD,GAAG;AAAA,MACH,aAAa,WAAW,eAAe,wBAAwB;AAAA,MAC/D,UAAU,WAAW,YAAY,wBAAwB;AAAA,IAC3D,GAAG,WAAW;AAAA,EAChB;AAEA,iBAAe,iBACb,YACA,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,kBAAkB,YAAY,WAAW;AAAA,EACnF;AAEA,iBAAe,kBACb,YACA,cAAsD,CAAC,GAC1B;AAC7B,UAAM,WAAW;AAAA,MACf,YAAY;AAAA,MACZ,wBAAwB;AAAA,IAC1B;AACA,UAAM,QAAQ,MAAM;AAAA,MAClB,OAAO,QAAQ,WAAW;AACxB,cAAM,QAAQ,MAAM,iBAAiB,EAAE,GAAG,YAAY,OAAO,GAAG,EAAE,OAAO,CAAC;AAC1E,eAAO,MAAM,QAAQ,QAAQ;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,UAAU,KAAM,QAAO;AAC3B,QAAI;AACJ,QAAI;AACF,cAAQ,KAAK,MAAM,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;AAAA,IAC5E,QAAQ;AACN,YAAM,IAAI,4BAA4B,eAAe;AAAA,IACvD;AACA,WAAO,iCAAiC,KAAK;AAAA,EAC/C;AAEA,iBAAe,mBACb,YACA,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,oBAAoB,YAAY,WAAW;AAAA,EACrF;AAEA,iBAAe,eACb,YACA,aAC4B;AAC5B,UAAM,WAAW,sBAAsB,YAAY,UAAU,yBAAyB,UAAU;AAChG,WAAO;AAAA,MACL,OAAO,QAAQ,WAAW;AACxB,cAAM,QAAQ,MAAM,mBAAmB,EAAE,GAAG,YAAY,OAAO,GAAG,EAAE,OAAO,CAAC;AAC5E,YAAI,CAAC,MAAM,MAAO,QAAO;AACzB,YAAI,MAAM,aAAa,UAAU;AAC/B,gBAAM,IAAI,4BAA4B,qBAAqB;AAAA,QAC7D;AACA,eAAO;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,iBAAe,gBACb,YACA,cAAyC,CAAC,GAC1C;AACA,WAAO,QAAQ,yBAAyB,iBAAiB;AAAA,MACvD,GAAG;AAAA,MACH,UAAU,WAAW,YAAY,wBAAwB;AAAA,IAC3D,GAAG,WAAW;AAAA,EAChB;AAEA,QAAM,mBAAmB,gCAAgC;AAAA,IACvD,OAAO,CAAC,QAAQ,YAAY,gBAAgB,QAAQ,QAAQ,YAAY,WAAW;AAAA,EACrF,CAAC;AACD,QAAM,iBAAiB,6BAA6B;AAAA,IAClD,OAAO,CAAC,QAAQ,YAAY,gBAAgB,QAAQ,QAAQ,YAAY,WAAW;AAAA,EACrF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,uBAAuB,iBAAiB;AAAA,IACxC,uBAAuB,iBAAiB;AAAA,IACxC,wBAAwB,iBAAiB;AAAA,IACzC;AAAA,IACA,oBAAoB,eAAe;AAAA,IACnC,kBAAkB,eAAe;AAAA,IACjC,qBAAqB,eAAe;AAAA,IACpC,qBAAqB,eAAe;AAAA,IACpC,qBAAqB,eAAe;AAAA,IACpC,0BAA0B,eAAe;AAAA,EAC3C;AACF;AAKO,SAAS,gCAAwC;AACtD,QAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,QAAM,kBAAkB,WAAW,QAAQ,gBAAgB,KAAK,WAAW,MAAM;AACjF,MAAI,CAAC,gBAAiB,OAAM,IAAI,4BAA4B,oBAAoB;AAChF,kBAAgB,KAAK;AACrB,QAAM,CAAC,IAAK,MAAM,CAAC,IAAI,KAAQ;AAC/B,QAAM,CAAC,IAAK,MAAM,CAAC,IAAI,KAAQ;AAC/B,QAAM,MAAM,CAAC,GAAG,KAAK,EAAE,IAAI,UAAQ,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAC9E,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC;AAC1G;AASA,eAAe,WACb,MACA,UACA,SAC4B;AAC5B,QAAM,YAAY,qBAAqB,QAAQ,QAAQ,QAAQ,UAAU;AACzE,MAAI,SAAS;AACb,MAAI;AACJ,MAAI;AACJ,MAAI,aAAa;AACjB,MAAI;AACF,eAAS;AACP,gBAAU,OAAO,eAAe;AAChC,oBAAc;AACd,UAAI,aAAa,kBAAmB,OAAM,IAAI,4BAA4B,qBAAqB;AAC/F,YAAM,QAAQ,MAAM,KAAK,QAAQ,UAAU,MAAM;AACjD,gBAAU,OAAO,eAAe;AAChC,UAAI,UAAU,MAAM;AAClB,YAAI,WAAW,EAAG,OAAM,IAAI,4BAA4B,gBAAgB;AACxE,eAAO;AAAA,MACT;AACA,UAAI,MAAM,aAAa,SAAU,OAAM,IAAI,4BAA4B,qBAAqB;AAC5F,UAAI,MAAM,WAAW,OAAQ,OAAM,IAAI,4BAA4B,iBAAiB;AACpF,UAAI,kBAAkB,UAAa,MAAM,eAAe,eAAe;AACrE,cAAM,IAAI,4BAA4B,qBAAqB;AAAA,MAC7D;AACA,sBAAgB,MAAM;AACtB,iBAAW,IAAI,WAAW,aAAa;AACvC,YAAM,QAAQ,cAAc,MAAM,IAAI;AACtC,UAAI,SAAS,MAAM,aAAa,cAAe,OAAM,IAAI,4BAA4B,eAAe;AACpG,aAAO,IAAI,OAAO,MAAM;AACxB,YAAM,aAAa,SAAS,MAAM;AAClC,UAAI,MAAM,eAAe,QAAW;AAClC,YAAI,eAAe,cAAe,OAAM,IAAI,4BAA4B,qBAAqB;AAC7F,eAAO;AAAA,MACT;AACA,UAAI,MAAM,eAAe,KAAK,MAAM,eAAe,YAAY;AAC7D,cAAM,IAAI,4BAA4B,qBAAqB;AAAA,MAC7D;AACA,eAAS,MAAM;AAAA,IACjB;AAAA,EACF,UAAE;AACA,cAAU,QAAQ;AAAA,EACpB;AACF;AAEA,IAAM,6BAA6B;AACnC,IAAM,yBAAyB;AAC/B,IAAM,oBAAoB;AAE1B,SAAS,qBAAqB,QAAiC,WAG7D;AACA,QAAM,aAAa,aAAa;AAChC,MAAI,CAAC,OAAO,cAAc,UAAU,KAAK,aAAa,KAAK,aAAa,wBAAwB;AAC9F,UAAM,IAAI,4BAA4B,oBAAoB;AAAA,EAC5D;AACA,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,kBAAkB,MAAM;AAC5B,eAAW,MAAM,QAAQ,MAAM;AAAA,EACjC;AACA,MAAI,QAAQ,QAAS,iBAAgB;AAAA,MAChC,SAAQ,iBAAiB,SAAS,iBAAiB,EAAE,MAAM,KAAK,CAAC;AACtE,QAAM,UAAU,WAAW,MAAM;AAC/B,eAAW,MAAM,IAAI,MAAM,kCAAkC,CAAC;AAAA,EAChE,GAAG,UAAU;AACb,SAAO;AAAA,IACL,QAAQ,WAAW;AAAA,IACnB,SAAS,MAAM;AACb,mBAAa,OAAO;AACpB,cAAQ,oBAAoB,SAAS,eAAe;AAAA,IACtD;AAAA,EACF;AACF;AAEA,SAAS,sBAAsB,OAA2B,SAAyB;AACjF,QAAM,SAAS,SAAS;AACxB,MAAI,CAAC,OAAO,cAAc,MAAM,KAAK,SAAS,KAAK,SAAS,SAAS;AACnE,UAAM,IAAI,4BAA4B,kBAAkB;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,SAAS,cAAc,OAA2B;AAChD,QAAM,SAAS,KAAK,KAAK;AACzB,QAAM,SAAS,IAAI,WAAW,OAAO,MAAM;AAC3C,WAAS,QAAQ,GAAG,QAAQ,OAAO,QAAQ,QAAS,QAAO,KAAK,IAAI,OAAO,WAAW,KAAK;AAC3F,SAAO;AACT;;;ACtcO,IAAM,kCAAkC;AACxC,IAAM,2CAA2C;AACjD,IAAM,0CAA0C;AAChD,IAAM,oCAAoC;AAC1C,IAAM,0CAA0C;AAChD,IAAM,2CAA2C;AACjD,IAAM,iDAAiD;AACvD,IAAM,qCAAqC,KAAK;AAChD,IAAM,4CAA4C,KAAK;AACvD,IAAM,iCAAiC;AACvC,IAAM,yCAAyC;AAC/C,IAAM,8CAA8C;AAE3D,IAAM,0BAA0B,OAAO,OAAO;AAAA,EAC5C,UAAU;AAAA,EACV,UAAU;AAAA,EACV,oBAAoB;AAAA,EACpB,gBAAgB,KAAK;AAAA,EACrB,UAAU;AACZ,CAAC;AAED,IAAM,mBAAwC,oBAAI,IAAsB;AAAA,EACtE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,SAAS,0BAA0B,OAK3B;AACb,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,kCACd,OACY;AACZ,MAAI,CAAC,wCAAwC,EAAE,GAAG,OAAO,WAAW,uBAAuB,CAAC,GAAG;AAC7F,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGO,SAAS,wCACd,OACgC;AAChC,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,QAAQ;AACd,SACEK,aAAY,OAAO;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,KACD,MAAM,WAAW,oBACjB,oBAAoB,MAAM,SAAS,KACnC,oBAAoB,MAAM,aAAa,KACvC,oBAAoB,MAAM,gBAAgB;AAAA,IACxC,YAAY;AAAA,EACd,CAAC,KACD,oBAAoB,MAAM,WAAW;AAAA,IACnC,YAAY,iBAAiB;AAAA,IAC7B,eAAe;AAAA,EACjB,CAAC,KACD,eAAe,MAAM,gBAAgB;AAAA,IACnC,YAAY;AAAA,EACd,CAAC,KACD,eAAe,MAAM,mBAAmB;AAAA,IACtC,YAAY;AAAA,EACd,CAAC,KACD,eAAe,MAAM,iBAAiB;AAAA,IACpC,YAAY;AAAA,EACd,CAAC,KACD;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACF,KACA,oBAAoB,MAAM,SAAS;AAEvC;AAEA,SAAS,oBAAoB,OAAiC;AAC5D,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,KACjD,MAAM,UAAU,kDAChB,eAAe,KAAK,KAAK,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,SAAS,IAAI,KACrE,CAAC,MAAM,SAAS,IAAI;AACxB;AAEO,SAAS,oCACd,OACA,UACS;AACT,SAAO,wCAAwC,KAAK,KAAK,MAAM,UAAU,SAAS,QAAQ;AAC5F;AAEO,SAAS,+BACd,OACA,OACS;AACT,MAAI,CAAC,oCAAoC,OAAO,qBAAqB,EAAG,QAAO;AAC/E,MAAI,CAAC,oBAAoB,MAAM,MAAM,EAAG,QAAO;AAC/C,MAAI,MAAM,mBAAmB,UAAa,CAAC,oBAAoB,MAAM,cAAc,EAAG,QAAO;AAC7F,MAAI,MAAM,iBAAiB,UAAa,CAAC,oBAAoB,MAAM,YAAY,EAAG,QAAO;AACzF,MAAI,CAAC,YAAY,MAAM,gBAAgB,MAAM,MAAM,EAAG,QAAO;AAC7D,MAAI,MAAM,mBAAmB,UAAa,CAAC,YAAY,MAAM,mBAAmB,MAAM,cAAc,GAAG;AACrG,WAAO;AAAA,EACT;AACA,MAAI,MAAM,iBAAiB,UAAa,CAAC,YAAY,MAAM,iBAAiB,MAAM,YAAY,GAAG;AAC/F,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAAyC,OAAwB;AACpF,SAAO,MAAM,SAAS,SAAU,MAAM,SAAS,SAAS,MAAM,IAAI,SAAS,KAAK;AAClF;AAEA,SAAS,eAAe,OAAgB,SAA8C;AACpF,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,QAAQ;AACd,MAAI,MAAM,SAAS,UAAU,MAAM,SAAS,OAAO;AACjD,WAAO,OAAO,KAAK,KAAK,EAAE,WAAW;AAAA,EACvC;AACA,SAAO,MAAM,SAAS,SAAS,OAAO,KAAK,KAAK,EAAE,WAAW,KAC3D,OAAO,OAAO,OAAO,KAAK,KAAK,oBAAoB,MAAM,KAAK,OAAO,KACpE,MAAM,IAAkB,SAAS;AACtC;AAOA,SAAS,oBAAoB,OAAgB,SAA8C;AACzF,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,QAAQ,WAAY,QAAO;AACvE,MAAI;AACJ,aAAW,SAAS,OAAO;AACzB,QACE,CAAC,oBAAoB,KAAK,KACzB,QAAQ,iBAAiB,CAAC,QAAQ,cAAc,IAAI,KAAK,KACzD,aAAa,UAAa,YAAY,MACvC,QAAO;AACT,eAAW;AAAA,EACb;AACA,SAAO;AACT;AAEO,SAAS,wCACd,OACY;AACZ,MACE,CAAC,8CAA8C;AAAA,IAC7C,GAAG;AAAA,IACH,WAAW;AAAA,EACb,CAAC,GACD;AACA,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACjE;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGO,SAAS,8CACd,OACsC;AACtC,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,QAAQ;AACd,SAAOA,aAAY,OAAO;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,KAAK,MAAM,WAAW,oBAAoB,oBAAoB,MAAM,SAAS,KAC5E,oBAAoB,MAAM,MAAM,KAAK;AAAA,IACnC,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACF,KACA,qBAAqB,MAAM,iBAAiB,KAAK,KACjD,qBAAqB,MAAM,qBAAqB,IAAI,KACpD,oBAAoB,MAAM,SAAS;AACvC;AAEA,SAAS,qBAAqB,OAAgB,YAA8B;AAC1E,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,wCAAwC;AAClF,WAAO;AAAA,EACT;AACA,MAAI,CAAC,cAAc,MAAM,WAAW,EAAG,QAAO;AAC9C,MAAI;AACJ,aAAW,WAAW,OAAO;AAC3B,QACE,OAAO,YAAY,YAAY,QAAQ,WAAW,KAClD,QAAQ,SAAS,+CACjB,YAAY,QAAQ,KAAK,KAAK,CAAC,eAAe,OAAO,KAAK,CAAC,QAAQ,WAAW,GAAG,KACjF,4BAA4B,OAAO,KAClC,aAAa,UAAa,YAAY,QACvC,QAAO;AACT,eAAW;AAAA,EACb;AACA,SAAO;AACT;AAEA,SAAS,cAAc,UAAmB,WAAoB,UAA2B;AACvF,SAAO,OAAO,cAAc,QAAQ,KAAK,OAAO,cAAc,SAAS,KACpE,YAAuB,KAAM,YAAwB,YACrD,YAAwB,YAAuB;AACpD;AAEA,SAASA,aAAY,QAAiC,SAAqC;AACzF,QAAM,cAAc,IAAI,IAAI,OAAO;AACnC,SAAO,OAAO,KAAK,MAAM,EAAE,MAAM,SAAO,YAAY,IAAI,GAAG,CAAC,KAC1D,QAAQ,MAAM,SAAO,OAAO,OAAO,QAAQ,GAAG,CAAC;AACnD;AAEA,SAAS,eAAe,OAAwB;AAC9C,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,SAAU,QAAQ,OAAQ;AACpC,YAAM,OAAO,MAAM,WAAW,QAAQ,CAAC;AACvC,UAAI,OAAO,SAAU,OAAO,MAAQ,QAAO;AAC3C,eAAS;AAAA,IACX,WAAW,QAAQ,SAAU,QAAQ,OAAQ;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,4BAA4B,OAAwB;AAC3D,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,MAAM,SAAS,IAAK,QAAO;AAAA,EACzC;AACA,SAAO;AACT;;;ACxQA,IAAM,6BAA6B;AACnC,IAAM,6BAA6B,IAAI,OAAO;AAC9C,IAAM,+BAA+B;AACrC,IAAM,iCAAiC,IAAI;AAC3C,IAAM,2BAA2B;AACjC,IAAM,oCAAoC;AAgCnC,IAAM,gCAAN,MAAuE;AAAA,EAC3D,SAAS,oBAAI,IAAmC;AAAA,EAChD,oBAAoB,oBAAI,IAAyC;AAAA,EAE3E,oBAAoB,OAAkE;AAC3F,WAAO,KAAK,OAAO,IAAI,wBAAwB,KAAK,CAAC;AAAA,EACvD;AAAA,EAEO,oBACL,OACA,OACA,OACM;AACN,UAAM,QAAQ,MAAY;AACxB,WAAK,OAAO,IAAI,wBAAwB,KAAK,GAAG,KAAK;AAAA,IACvD;AACA,QAAI,CAAC,OAAO;AACV,YAAM;AACN;AAAA,IACF;AACA,QAAI,CAAC,MAAM,kBAAkB,KAAK,EAAG,OAAM,aAAa;AAAA,EAC1D;AAAA,EAEO,qBAAqB,QAAyD;AACnF,WAAO,KAAK,kBAAkB,IAAI,MAAM;AAAA,EAC1C;AAAA,EAEO,qBACL,QACA,OACA,OACM;AACN,UAAM,QAAQ,MAAY;AACxB,WAAK,kBAAkB,IAAI,QAAQ,KAAK;AAAA,IAC1C;AACA,QAAI,CAAC,OAAO;AACV,YAAM;AACN;AAAA,IACF;AACA,QAAI,CAAC,MAAM,kBAAkB,KAAK,EAAG,OAAM,aAAa;AAAA,EAC1D;AAAA,EAEO,QAAc;AACnB,SAAK,OAAO,MAAM;AAClB,SAAK,kBAAkB,MAAM;AAAA,EAC/B;AACF;AASO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YACE,MACA,SACA;AACA,UAAM,SAAS,SAAS,WAAW,SAC/B,OACA,GAAG,IAAI,KAAK,QAAQ,MAAM,KAAK,QAAQ,gBAAgB,IAAI,KAAK,CAAC,GAAG,KAAK;AAC7E,UAAM,QAAQ,SAAS,UAAU,SAAY,SAAY,EAAE,OAAO,QAAQ,MAAM,CAAC;AACjF,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,SAAS,SAAS;AACvB,SAAK,eAAe,SAAS;AAAA,EAC/B;AACF;AAkBO,IAAM,yBAAN,MAA0D;AAAA,EAY/D,YAA6B,SAAwC;AAAxC;AAC3B,SAAK,UAAU,4BAA4B,QAAQ,OAAO;AAC1D,QAAI,QAAQ,OAAO;AACjB,WAAK,sBAAsB,QAAQ;AAAA,IACrC,WAAW,OAAO,WAAW,UAAU,YAAY;AACjD,WAAK,sBAAsB,WAAW,MAAM,KAAK,UAAU;AAAA,IAC7D,OAAO;AACL,YAAM,IAAI,UAAU,sBAAsB;AAAA,IAC5C;AACA,QAAI,QAAQ,gBAAgB,UAAa,QAAQ,mBAAmB,QAAW;AAC7E,YAAM,IAAI,UAAU,uCAAuC;AAAA,IAC7D;AACA,QAAI,QAAQ,gBAAgB,QAAW;AACrC,YAAM,cAAc,qBAAqB,QAAQ,WAAW;AAC5D,WAAK,iBAAiB,MAAM;AAAA,IAC9B,OAAO;AACL,WAAK,iBAAiB,QAAQ;AAAA,IAChC;AACA,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,mBAAmB;AAAA,MACtB,QAAQ,oBAAoB;AAAA,MAC5B;AAAA,IACF;AACA,SAAK,mBAAmB;AAAA,MACtB,QAAQ,oBAAoB;AAAA,MAC5B;AAAA,IACF;AACA,SAAK,qBAAqB;AAAA,MACxB,QAAQ,sBAAsB;AAAA,MAC9B;AAAA,IACF;AACA,SAAK,sBAAsB;AAAA,MACzB,QAAQ,uBAAuB;AAAA,MAC/B;AAAA,IACF;AACA,SAAK,eAAe,QAAQ,gBAAgB,IAAI,8BAA8B;AAC9E,SAAK,MAAM,QAAQ,OAAO,KAAK;AAAA,EACjC;AAAA,EAhDgB;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAyCjB,MAAa,mBAAmB,QAI7B;AACD,UAAM,QAAQ,MAAM,KAAK,QAAQ,8BAA8B,EAAE,QAAQ,OAAO,GAAG,MAAM;AACzF,QACE,CAAC,SAAS,KAAK,KAAK,CAAC,eAAe,MAAM,KAAK,KAAK,CAAC,eAAe,MAAM,SAAS,KACnF,CAAC,eAAe,MAAM,SAAS,GAC/B;AACA,YAAM,aAAa;AAAA,IACrB;AACA,WAAO,EAAE,OAAO,MAAM,OAAO,WAAW,MAAM,WAAW,WAAW,MAAM,UAAU;AAAA,EACtF;AAAA,EAEA,MAAa,eACX,OACA,QAC0C;AAC1C,UAAM,QAAQ,MAAM,KAAK,QAAQ,yBAAyB;AAAA,MACxD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,QAAQ,MAAM,SAAS;AAAA,QACvB,oBAAoB,MAAM,SAAS;AAAA,QACnC,YAAY,MAAM,SAAS;AAAA,QAC3B,UAAU,MAAM,SAAS;AAAA,QACzB,YAAY,MAAM;AAAA,QAClB,WAAW,MAAM;AAAA,QACjB,cAAc,MAAM;AAAA,QACpB,YAAY,MAAM;AAAA,QAClB,mBAAmB,MAAM;AAAA,MAC3B,CAAC;AAAA,IACH,GAAG,MAAM;AACT,QAAI,CAAC,SAAS,KAAK,KAAK,OAAO,MAAM,OAAO,aAAa,CAAC,eAAe,MAAM,MAAM,GAAG;AACtF,YAAM,aAAa;AAAA,IACrB;AACA,WAAO,EAAE,IAAI,MAAM,IAAI,QAAQ,MAAM,OAAO;AAAA,EAC9C;AAAA,EAEA,MAAa,YAAY,QAAoD;AAC3E,UAAM,QAAQ,MAAM,KAAK,QAAQ,gBAAgB,EAAE,QAAQ,MAAM,GAAG,MAAM;AAC1E,QACE,CAAC,SAAS,KAAK,KAAK,CAAC,MAAM,QAAQ,MAAM,OAAO,KAChD,CAAC,MAAM,QAAQ,MAAM,mBAAmB,GACxC;AACA,YAAM,aAAa;AAAA,IACrB;AACA,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,MAAa,4BAA4B,QAGtC;AACD,UAAM,QAAQ,MAAM,KAAK;AAAA,MACvB;AAAA,MACA,EAAE,QAAQ,MAAM;AAAA,MAChB;AAAA,IACF;AACA,QACE,CAAC,SAAS,KAAK,KAAK,MAAM,WAAW,oBACrC,CAAC,eAAe,MAAM,kBAAkB,GACxC;AACA,YAAM,aAAa;AAAA,IACrB;AACA,WAAO,EAAE,QAAQ,MAAM,QAAQ,oBAAoB,MAAM,mBAAmB;AAAA,EAC9E;AAAA,EAEA,MAAa,sBACX,OACA,QACA,OACgC;AAChC,sBAAkB,QAAQ,KAAK;AAC/B,WAAO,aAAa;AACpB,QAAI,CAAC,kCAAkC,KAAK,GAAG;AAC7C,YAAM,IAAI,UAAU,gCAAgC;AAAA,IACtD;AACA,UAAM,aAAa,iCAAiC,KAAK;AACzD,UAAM,SAAS,MAAM,KAAK,gBAAgB,UAAU;AACpD,mBAAe,MAAM;AACrB,WAAO,aAAa;AACpB,QAAI,wBAAwB,QAAQ,YAAY,KAAK,IAAI,IAAI,KAAK,mBAAmB,GAAG;AACtF,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,MAAM,KAAK,QAAQ,iCAAiC;AAAA,MAChE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,KAAK;AAAA,IAC5B,GAAG,MAAM;AACT,QAAI,CAAC,wBAAwB,OAAO,YAAY,KAAK,IAAI,CAAC,EAAG,OAAM,aAAa;AAChF,WAAO,aAAa;AACpB,UAAM,KAAK,gBAAgB,YAAY,OAAO,KAAK;AACnD,WAAO,aAAa;AACpB,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,uBACX,OACA,QACA,OACsC;AACtC,sBAAkB,QAAQ,KAAK;AAC/B,WAAO,aAAa;AACpB,UAAM,SAAS,MAAM,KAAK,2BAA2B,MAAM,MAAM;AACjE,mBAAe,MAAM;AACrB,WAAO,aAAa;AACpB,QAAI,yBAAyB,QAAQ,MAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,mBAAmB,GAAG;AACzF,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,MAAM,KAAK,QAAQ,kCAAkC;AAAA,MACjE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,KAAK;AAAA,IAC5B,GAAG,MAAM;AACT,QAAI,CAAC,yBAAyB,OAAO,MAAM,QAAQ,KAAK,IAAI,CAAC,EAAG,OAAM,aAAa;AACnF,WAAO,aAAa;AACpB,UAAM,KAAK,2BAA2B,MAAM,QAAQ,OAAO,KAAK;AAChE,WAAO,aAAa;AACpB,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,UACX,OACA,QAC0B;AAC1B,UAAM,QAAQ,MAAM,KAAK,QAAQ,0BAA0B;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,KAAK;AAAA,IAC5B,GAAG,MAAM;AACT,QAAI,CAAC,SAAS,KAAK,KAAK,OAAO,MAAM,OAAO,UAAW,OAAM,aAAa;AAC1E,WAAO,EAAE,IAAI,MAAM,GAAG;AAAA,EACxB;AAAA;AAAA,EAGA,MAAa,kBAAkB,QAAqC;AAClE,mBAAe,MAAM;AACrB,QAAI;AACF,YAAM,KAAK,aAAa,MAAM;AAAA,IAChC,SAAS,OAAO;AACd,WAAK,QAAQ,sBAAsB,QAAQ,KAAK;AAChD,YAAM;AAAA,IACR;AACA,mBAAe,MAAM;AAAA,EACvB;AAAA,EAEA,MAAc,QAAQ,MAAc,MAAmB,QAAwC;AAC7F,UAAM,UAAU,oBAAoB,QAAQ,KAAK,gBAAgB;AACjE,QAAI;AACF,qBAAe,QAAQ,MAAM;AAC7B,YAAM,cAAc,MAAM,KAAK,iBAAiB,QAAQ,MAAM;AAC9D,qBAAe,QAAQ,MAAM;AAC7B,YAAM,UAAkC,EAAE,gBAAgB,mBAAmB;AAC7E,UAAI,gBAAgB,QAAW;AAC7B,gBAAQ,gBAAgB,UAAU,qBAAqB,WAAW,CAAC;AAAA,MACrE;AACA,UAAI;AACJ,UAAI;AACF,mBAAW,MAAM,KAAK,oBAAoB,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,UAClE,GAAG;AAAA,UACH,aAAa,KAAK;AAAA,UAClB;AAAA,UACA,UAAU;AAAA,UACV,QAAQ,QAAQ;AAAA,QAClB,CAAC;AAAA,MACH,SAAS,OAAO;AACd,YAAI,QAAQ,OAAO,QAAS,OAAM,YAAY,QAAQ,MAAM;AAC5D,cAAM,IAAI,sBAAsB,wBAAwB,EAAE,OAAO,MAAM,CAAC;AAAA,MAC1E;AACA,YAAM,eAAe,MAAM;AAAA,QACzB;AAAA,QACA,KAAK;AAAA,QACL,QAAQ;AAAA,MACV;AACA,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,eAAe,aAAa,MAAM,GAAG,KAAK,kBAAkB;AAClE,cAAM,IAAI,sBAAsB,oBAAoB;AAAA,UAClD,QAAQ,SAAS;AAAA,UACjB;AAAA,QACF,CAAC;AAAA,MACH;AACA,UAAI;AACF,eAAO,KAAK,MAAM,YAAY;AAAA,MAChC,SAAS,OAAO;AACd,cAAM,IAAI,sBAAsB,+BAA+B,EAAE,OAAO,MAAM,CAAC;AAAA,MACjF;AAAA,IACF,UAAE;AACA,cAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAc,gBAAgB,OAAiD;AAC7E,QAAI;AACF,aAAO,MAAM,KAAK,aAAa,oBAAoB,KAAK;AAAA,IAC1D,SAAS,OAAO;AACd,WAAK,QAAQ,sBAAsB,QAAQ,KAAK;AAChD,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,gBACZ,OACA,OACA,OACe;AACf,QAAI;AACF,YAAM,KAAK,aAAa,oBAAoB,OAAO,OAAO,KAAK;AAAA,IACjE,SAAS,OAAO;AACd,UAAI,SAAS,CAAC,MAAM,UAAU,EAAG,OAAM,aAAa;AACpD,WAAK,QAAQ,sBAAsB,QAAQ,KAAK;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,MAAc,2BAA2B,QAAkC;AACzE,QAAI;AACF,aAAO,MAAM,KAAK,aAAa,qBAAqB,MAAM;AAAA,IAC5D,SAAS,OAAO;AACd,WAAK,QAAQ,sBAAsB,QAAQ,KAAK;AAChD,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,2BACZ,QACA,OACA,OACe;AACf,QAAI;AACF,YAAM,KAAK,aAAa,qBAAqB,QAAQ,OAAO,KAAK;AAAA,IACnE,SAAS,OAAO;AACd,UAAI,SAAS,CAAC,MAAM,UAAU,EAAG,OAAM,aAAa;AACpD,WAAK,QAAQ,sBAAsB,QAAQ,KAAK;AAAA,IAClD;AAAA,EACF;AACF;AAEA,SAAS,kBACP,QACA,OACM;AACN,MAAI,SAAS,UAAU,MAAM,WAAW,QAAQ;AAC9C,UAAM,IAAI,UAAU,yCAAyC;AAAA,EAC/D;AACF;AAEO,SAAS,4BAA4B,OAAuB;AACjE,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,WAAW,QAAQ,SAAS,yBAA0B,OAAM,IAAI,MAAM,mBAAmB;AAC9F,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,OAAO;AAAA,EAC1B,QAAQ;AACN,UAAM,IAAI,MAAM,mBAAmB;AAAA,EACrC;AACA,QAAM,WAAW,OAAO,aAAa,eAAe,OAAO,aAAa,eACtE,OAAO,aAAa;AACtB,MAAI,OAAO,aAAa,YAAY,EAAE,OAAO,aAAa,WAAW,WAAW;AAC9E,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AACA,MACE,OAAO,YAAY,OAAO,YAAY,OAAO,UAAU,OAAO,QAC7D,OAAO,aAAa,MAAM,OAAO,aAAa,KAC/C;AACA,UAAM,IAAI,MAAM,mBAAmB;AAAA,EACrC;AACA,SAAO,OAAO;AAChB;AAEA,SAAS,qBAAqB,OAAuB;AACnD,QAAM,cAAc,MAAM,KAAK;AAC/B,MAAI,CAAC,eAAe,YAAY,SAAS,mCAAmC;AAC1E,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC9C;AACA,SAAO;AACT;AAEA,SAAS,eAAe,OAAe,MAAsB;AAC3D,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,EAAG,OAAM,IAAI,UAAU,GAAG,IAAI,8BAA8B;AACpG,SAAO;AACT;AAEA,SAAS,kBAAkB,OAAe,MAAsB;AAC9D,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,EAAG,OAAM,IAAI,UAAU,GAAG,IAAI,kCAAkC;AACvG,SAAO;AACT;AAEA,SAAS,oBACP,QACA,WAC0C;AAC1C,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,kBAAkB,MAAY;AAClC,eAAW,MAAM,QAAQ,MAAM;AAAA,EACjC;AACA,MAAI,QAAQ,QAAS,iBAAgB;AAAA,MAChC,SAAQ,iBAAiB,SAAS,iBAAiB,EAAE,MAAM,KAAK,CAAC;AACtE,QAAM,UAAU,WAAW,MAAM;AAC/B,eAAW,MAAM,IAAI,MAAM,uBAAuB,CAAC;AAAA,EACrD,GAAG,SAAS;AACZ,SAAO;AAAA,IACL,QAAQ,WAAW;AAAA,IACnB,SAAS,MAAM;AACb,mBAAa,OAAO;AACpB,cAAQ,oBAAoB,SAAS,eAAe;AAAA,IACtD;AAAA,EACF;AACF;AAEA,eAAe,yBACb,UACA,cACA,QACiB;AACjB,QAAM,iBAAiB,OAAO,SAAS,QAAQ,IAAI,gBAAgB,KAAK,GAAG;AAC3E,MAAI,OAAO,SAAS,cAAc,KAAK,iBAAiB,cAAc;AACpE,UAAM,SAAS,MAAM,OAAO,0BAA0B;AACtD,UAAM,IAAI,sBAAsB,0BAA0B;AAAA,EAC5D;AACA,iBAAe,MAAM;AACrB,MAAI,CAAC,SAAS,QAAQ,OAAO,SAAS,KAAK,cAAc,YAAY;AACnE,UAAMC,QAAO,MAAM,eAAe,SAAS,KAAK,GAAG,MAAM;AACzD,mBAAe,MAAM;AACrB,QAAI,IAAI,YAAY,EAAE,OAAOA,KAAI,EAAE,aAAa,cAAc;AAC5D,YAAM,IAAI,sBAAsB,0BAA0B;AAAA,IAC5D;AACA,WAAOA;AAAA,EACT;AACA,QAAM,SAAS,SAAS,KAAK,UAAU;AACvC,QAAM,eAAe,MAAY;AAC/B,SAAK,OAAO,OAAO,uBAAuB;AAAA,EAC5C;AACA,SAAO,iBAAiB,SAAS,cAAc,EAAE,MAAM,KAAK,CAAC;AAC7D,QAAM,UAAU,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC;AACxD,MAAI,aAAa;AACjB,MAAI,OAAO;AACX,MAAI;AACF,eAAS;AACP,qBAAe,MAAM;AACrB,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,oBAAc,MAAM;AACpB,UAAI,aAAa,cAAc;AAC7B,cAAM,OAAO,OAAO,0BAA0B;AAC9C,cAAM,IAAI,sBAAsB,0BAA0B;AAAA,MAC5D;AACA,cAAQ,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAAA,IAChD;AACA,mBAAe,MAAM;AACrB,WAAO,OAAO,QAAQ,OAAO;AAAA,EAC/B,UAAE;AACA,WAAO,oBAAoB,SAAS,YAAY;AAAA,EAClD;AACF;AAEA,eAAe,eAAkB,SAAqB,QAAiC;AACrF,iBAAe,MAAM;AACrB,MAAI;AACJ,QAAM,UAAU,IAAI,QAAe,CAAC,UAAU,WAAW;AACvD,kBAAc;AAAA,EAChB,CAAC;AACD,QAAM,UAAU,MAAY;AAC1B,gBAAY,YAAY,MAAM,CAAC;AAAA,EACjC;AACA,SAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACxD,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK,CAAC,SAAS,OAAO,CAAC;AAAA,EAC9C,UAAE;AACA,WAAO,oBAAoB,SAAS,OAAO;AAAA,EAC7C;AACF;AAEA,SAAS,eAAe,QAA4B;AAClD,MAAI,QAAQ,QAAS,OAAM,YAAY,MAAM;AAC/C;AAEA,SAAS,YAAY,QAA4B;AAC/C,SAAO,OAAO,kBAAkB,QAAQ,OAAO,SAAS,IAAI,MAAM,uBAAuB;AAC3F;AAEA,SAAS,eAAsC;AAC7C,SAAO,IAAI,sBAAsB,8BAA8B;AACjE;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,eAAe,OAAiC;AACvD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS;AACrD;AAEA,SAAS,YAAY,OAAmC;AACtD,SAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAM,UAAQ,OAAO,SAAS,QAAQ;AAC7E;AAEA,SAAS,oBAAoB,OAA4C;AACvE,MACE,CAAC,SAAS,KAAK,KAAK,CAAC,eAAe,MAAM,SAAS,KAAK,CAAC,eAAe,MAAM,MAAM,KACpF,CAAC,eAAe,MAAM,kBAAkB,KAAK,CAAC,eAAe,MAAM,UAAU,KAC5E,MAAM,aAAa,aAAa,MAAM,aAAa,YAAY,MAAM,aAAa,SACjF,MAAM,aAAa,SACrB,CAAC,qBAAqB,MAAM,YAAY,KACxC,CAAC,YAAY,MAAM,UAAU,KAAK,CAAC,YAAY,MAAM,iBAAiB,KACtE,OAAO,MAAM,aAAa,YAAY,CAAC,OAAO,SAAS,MAAM,QAAQ,GACrE;AACA,WAAO;AAAA,EACT;AACA,SAAO,MAAM,cAAc,UACxB,OAAO,MAAM,cAAc,YAAY,OAAO,SAAS,MAAM,SAAS;AAC3E;AAEA,SAAS,qBAAqB,OAAyB;AACrD,MACE,CAAC,SAAS,KAAK,KAAK,CAAC,YAAY,MAAM,KAAK,KAAK,CAAC,YAAY,MAAM,UAAU,KAC9E,OAAO,MAAM,YAAY,aAAa,CAAC,YAAY,MAAM,UAAU,KACnE,CAAC,MAAM,QAAQ,MAAM,KAAK,KACzB,MAAM,cAAc,UAAa,OAAO,MAAM,cAAc,WAC7D;AACA,WAAO;AAAA,EACT;AACA,SAAO,MAAM,MAAM;AAAA,IAAM,UACvB,SAAS,IAAI,KAAK,eAAe,KAAK,MAAM,MAC3C,KAAK,UAAU,UAAa,OAAO,KAAK,UAAU,cAClD,KAAK,aAAa,UAAa,OAAO,KAAK,aAAa;AAAA,EAC3D;AACF;AAEA,SAAS,iCAAiC,OAAuD;AAC/F,SAAO;AAAA,IACL,eAAe,MAAM;AAAA,IACrB,gBAAgB,CAAC,GAAG,MAAM,cAAc;AAAA,IACxC,WAAW,CAAC,GAAG,MAAM,SAAS;AAAA,IAC9B,gBAAgB,WAAW,MAAM,cAAc;AAAA,IAC/C,mBAAmB,WAAW,MAAM,iBAAiB;AAAA,IACrD,iBAAiB,WAAW,MAAM,eAAe;AAAA,EACnD;AACF;AAEA,SAAS,wBAAwB,OAAuC;AACtE,QAAM,aAAa,iCAAiC,KAAK;AACzD,SAAO,KAAK,UAAU;AAAA,IACpB,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AACH;AAEA,SAAS,eAAe,MAAyB,OAAmC;AAClF,SAAO,KAAK,WAAW,MAAM,UAAU,KAAK,MAAM,CAAC,MAAM,UAAU,SAAS,MAAM,KAAK,CAAC;AAC1F;AAEA,SAAS,WAA+D,OAAa;AACnF,SAAQ,MAAM,SAAS,QAAQ,EAAE,MAAM,OAAO,KAAK,CAAC,GAAG,MAAM,GAAG,EAAE,IAAI,EAAE,MAAM,MAAM,KAAK;AAC3F;AAEA,SAAS,UACP,MACA,OACS;AACT,SAAO,KAAK,SAAS,MAAM,SACxB,KAAK,SAAS,SAAU,MAAM,SAAS,SAAS,eAAe,KAAK,KAAK,MAAM,GAAG;AACvF;AAEA,SAAS,kCAAkC,OAAwC;AACjF,SAAO,wCAAwC;AAAA,IAC7C,GAAG;AAAA,IACH,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,UAAU;AAAA,IACV,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AACH;AAEA,SAAS,wBACP,OACA,OACA,aACgC;AAChC,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO;AAC7B,QAAM,QAAQ;AACd,MAAI,CAAC,wCAAwC,KAAK,EAAG,QAAO;AAC5D,SAAO,MAAM,WAAW,oBAAoB,MAAM,kBAAkB,MAAM,iBACxE,eAAe,MAAM,SAAS,KAAK,eAAe,MAAM,gBAAgB,MAAM,cAAc,KAC5F,eAAe,MAAM,WAAW,MAAM,SAAS,KAC/C,UAAU,MAAM,gBAAgB,MAAM,cAAc,KACpD,UAAU,MAAM,mBAAmB,MAAM,iBAAiB,KAC1D,UAAU,MAAM,iBAAiB,MAAM,eAAe,KACtD,OAAO,MAAM,aAAa,YAAY,OAAO,SAAS,MAAM,QAAQ,KACpE,OAAO,MAAM,cAAc,YAAY,OAAO,SAAS,MAAM,SAAS,KACtE,MAAM,YAAY,eAAe,eAAe,MAAM,SAAS;AACnE;AAEA,SAAS,yBACP,OACA,QACA,aACsC;AACtC,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO;AAC7B,QAAM,QAAQ;AACd,SAAO,8CAA8C,KAAK,KAAK,MAAM,WAAW,UAC9E,OAAO,MAAM,aAAa,YAAY,OAAO,SAAS,MAAM,QAAQ,KACpE,OAAO,MAAM,cAAc,YAAY,OAAO,SAAS,MAAM,SAAS,KACtE,MAAM,YAAY,eAAe,eAAe,MAAM,SAAS;AACnE;;;ACtoBO,IAAM,kCAAN,cAA8C,MAAM;AAAA,EACzC,OAAO;AAAA,EAEvB,cAAc;AACZ,UAAM,kCAAkC;AACxC,SAAK,OAAO;AAAA,EACd;AACF;AAwEA,IAAM,gCAAgC;AACtC,IAAM,6BAA6B;AACnC,IAAM,yBAAyB;AAC/B,IAAM,uBAAuB;AAC7B,IAAM,6CAA6C;AACnD,IAAM,yCAAyC;AAC/C,IAAM,4BAA4B;AAClC,IAAM,yCAAyC;AAC/C,IAAM,qBAAqB;AAE3B,SAAS,kBAAgG;AACvG,SAAO,OAAO,OAAO;AAAA,IACnB,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,OAAO;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AACH;AAEA,SAAS,0BAA0B,OAAe,MAAoB;AACpE,MAAI,CAAC,OAAO,cAAc,KAAK,KAAK,SAAS,KAAK,QAAQ,oBAAoB;AAC5E,UAAM,IAAI,UAAU,GAAG,IAAI,2CAA2C,kBAAkB,EAAE;AAAA,EAC5F;AACF;AAEA,SAAS,+BAA+B,SAA4B;AAClE,MAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,2BAA2B;AACzE,UAAM,IAAI,UAAU,kCAAkC;AAAA,EACxD;AACA,QAAM,aAAwB,CAAC,GAAG,IAAI,IAAa,OAAO,CAAC;AAC3D,MACE,WAAW;AAAA,IAAK,YACd,OAAO,WAAW,YAAY,OAAO,WAAW,KAChD,OAAO,SAAS,0CAA0C,WAAW,OAAO,KAAK;AAAA,EACnF,GACA;AACA,UAAM,IAAI,UAAU,kCAAkC;AAAA,EACxD;AACA,SAAO,WAAW,IAAI,YAAU,OAAO,MAAM,CAAC,EAAE,KAAK;AACvD;AAEA,eAAe,eAAe,SAAiB,QAAoC;AACjF,SAAO,eAAe;AACtB,QAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,UAAM,UAAU,MAAY;AAC1B,mBAAa,KAAK;AAClB,aAAO,oBAAoB,SAAS,OAAO;AAC3C,aAAO,OAAO,kBAAkB,QAAQ,OAAO,SAAS,IAAI,MAAM,mBAAmB,CAAC;AAAA,IACxF;AACA,UAAM,QAAQ,WAAW,MAAM;AAC7B,aAAO,oBAAoB,SAAS,OAAO;AAC3C,cAAQ;AAAA,IACV,GAAG,OAAO;AACV,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACxD,QAAI,OAAO,QAAS,SAAQ;AAAA,EAC9B,CAAC;AACD,SAAO,eAAe;AACxB;AAEA,SAAS,UACP,MACA,gBACA,WAC4B;AAC5B,SAAO,OAAO;AAAA,IACZ,cAAc,SACV,EAAE,MAAM,eAAe,IACvB,EAAE,MAAM,gBAAgB,UAAU;AAAA,EACxC;AACF;AAEA,SAAS,eAAe,UAAwE;AAC9F,SAAO,OAAO,OAAO;AAAA,IACnB,GAAG;AAAA,IACH,YAAY,OAAO,OAAO,EAAE,GAAG,SAAS,WAAW,CAAC;AAAA,IACpD,GAAI,SAAS,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,OAAO,OAAO,EAAE,GAAG,SAAS,UAAU,CAAC,EAAE;AAAA,EACpG,CAAC;AACH;AAGO,IAAM,mCAAN,MAAsD;AAAA,EA8B3D,YAA6B,SAAiE;AAAjE;AAC3B,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,uBAAuB,QAAQ;AACpC,SAAK,sBAAsB,QAAQ,uBAAuB;AAC1D,SAAK,mBAAmB,QAAQ,oBAAoB;AACpD,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,iCAAiC,QAAQ,kCAC5C;AACF,SAAK,6BAA6B,QAAQ,8BACxC;AACF,SAAK,MAAM,QAAQ,OAAO,KAAK;AAC/B,SAAK,SAAS,QAAQ,UAAU,KAAK;AACrC,8BAA0B,KAAK,qBAAqB,qBAAqB;AACzE,8BAA0B,KAAK,kBAAkB,kBAAkB;AACnE,8BAA0B,KAAK,cAAc,cAAc;AAC3D;AAAA,MACE,KAAK;AAAA,MACL;AAAA,IACF;AACA;AAAA,MACE,KAAK;AAAA,MACL;AAAA,IACF;AACA,QAAI,KAAK,eAAe,KAAK,kBAAkB;AAC7C,YAAM,IAAI,UAAU,gEAAgE;AAAA,IACtF;AACA,QAAI,KAAK,6BAA6B,KAAK,gCAAgC;AACzE,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,OAAO,SAAS,KAAK,WAAW,KAAK,KAAK,cAAc,KAAK,KAAK,cAAc,GAAG;AACtF,YAAM,IAAI,UAAU,qDAAqD;AAAA,IAC3E;AACA,SAAK,cAAc;AAAA,EACrB;AAAA,EAjEQ;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB;AAAA,EACA,aAAa,IAAI,gBAAgB;AAAA,EACjC;AAAA,EACA;AAAA,EACS,qBAAqB,oBAAI,IAGvC;AAAA,EACK,UAAU;AAAA,EACV,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,gBAA+C,eAAe;AAAA,IACpE,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY,gBAAgB;AAAA,EAC9B,CAAC;AAAA,EACgB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAwCjB,IAAW,WAA0C;AACnD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAa,QAAuB;AAClC,QAAI,KAAK,QAAS,QAAO,KAAK,OAAO;AACrC,SAAK,UAAU;AACf,UAAM,aAAa,KAAK;AACxB,QAAI,YAAY;AACd,YAAM;AACN;AAAA,IACF;AACA,UAAM,KAAK,WAAW;AAAA,EACxB;AAAA,EAEO,OAAsB;AAC3B,QACE,CAAC,KAAK,WAAW,CAAC,KAAK,YAAY,CAAC,KAAK,cAAc,CAAC,KAAK,uBAC7D,KAAK,mBAAmB,SAAS,GACjC;AACA,aAAO,QAAQ,QAAQ;AAAA,IACzB;AACA,SAAK,UAAU;AACf,WAAO,KAAK,kBAAkB,kCAAkC;AAAA,EAClE;AAAA,EAEO,iBAAiB,eAAyD;AAC/E,SAAK,uBAAuB;AAC5B,WAAO,KAAK,kBAAkB,oCAAoC;AAAA,EACpE;AAAA,EAEO,SAAwB;AAC7B,QAAI,KAAK,YAAY;AACnB,aAAO,KAAK,UAAU,KAAK,aAAa,KAAK,WAAW,KAAK,MAAM,KAAK,WAAW,CAAC;AAAA,IACtF;AACA,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EAEQ,aAA4B;AAClC,QAAI,KAAK,SAAU,QAAO,KAAK;AAC/B,QAAI,CAAC,KAAK,QAAQ,QAAQ,aAAa,KAAK,aAAa,GAAG;AAC1D,WAAK,cAAc;AACnB,aAAO,QAAQ,QAAQ;AAAA,IACzB;AACA,UAAM,aAAa,KAAK;AACxB,UAAM,gBAAgB,KAAK;AAC3B,UAAM,SAAS,KAAK,WAAW;AAC/B,SAAK,sBAAsB;AAC3B,UAAM,MAAM,KAAK,SAAS,eAAe,YAAY,MAAM;AAC3D,UAAM,UAAU,IAAI,QAAQ,MAAM;AAChC,UAAI,KAAK,aAAa,QAAS,MAAK,WAAW;AAAA,IACjD,CAAC;AACD,SAAK,WAAW;AAChB,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,QAA+B;AACvD,SAAK,uBAAuB;AAC5B,SAAK,WAAW;AAChB,SAAK,WAAW,MAAM,IAAI,MAAM,MAAM,CAAC;AACvC,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,aAAa,KAAK,iBAAiB,EAAE,QAAQ,MAAM;AACvD,YAAI,KAAK,eAAe,WAAY,MAAK,aAAa;AAAA,MACxD,CAAC;AACD,WAAK,aAAa;AAAA,IACpB;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,mBAAkC;AAC9C,WAAO,KAAK,eAAe,KAAK,qBAAqB;AACnD,YAAM,wBAAwB,KAAK;AACnC,YAAM,cAAc,KAAK;AACzB,YAAM,aAAa,MAAM,MAAM,MAAS;AACxC,YAAM,KAAK,8BAA8B,KAAK,UAAU;AAExD,UACE,KAAK,uBACL,KAAK,QAAQ,QAAQ,aAAa,qBAAqB,GACvD;AACA,YAAI;AACF,gBAAM,KAAK,QAAQ,QAAQ,UAAU,uBAAuB,IAAI,gBAAgB,EAAE,MAAM;AAAA,QAC1F,QAAQ;AACN,eAAK;AAAA,YACH;AAAA,YACA,UAAU,+BAA+B,OAAO;AAAA,UAClD;AAAA,QACF;AAAA,MACF;AACA,WAAK,sBAAsB;AAI3B,WAAK,gBAAgB,KAAK;AAC1B,WAAK,aAAa,KAAK;AACvB,WAAK,sBAAsB;AAC3B,WAAK,aAAa,IAAI,gBAAgB;AACtC,UAAI,KAAK,aAAa,YAAa,MAAK,WAAW;AACnD,WAAK,cAAc;AAEnB,UAAI,KAAK,WAAW,KAAK,QAAQ,QAAQ,aAAa,KAAK,aAAa,GAAG;AACzE,cAAM,KAAK,WAAW,EAAE,MAAM,CAAC,UAAmB;AAChD,cAAI,KAAK,UAAU,KAAK,YAAY,KAAK,WAAW,MAAM,EAAG,OAAM;AAAA,QACrE,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,SACZ,eACA,YACA,QACe;AACf,QAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACzC,UAAM,KAAK,eAAe,YAAY;AAAA,MACpC,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,aAAa;AAAA,IACf,CAAC;AAED,QAAI,kBAAkD;AACtD,QAAI;AACF,UAAI,KAAK,cAAc,WAAW,eAAe,SAAS;AACxD,0BAAkB;AAClB,cAAM,KAAK,QAAQ,iBAAiB,YAAY,QAAQ,WAAS,KAAK,QAAQ,QAAQ,iBAAiB,eAAe,QAAQ,KAAK,CAAC;AAAA,MACtI;AACA,UAAI,KAAK,cAAc,WAAW,iBAAiB,SAAS;AAC1D,0BAAkB;AAClB,cAAM,KAAK,QAAQ,iBAAiB,YAAY,QAAQ,WAAS,KAAK,QAAQ,QAAQ,eAAe,eAAe,QAAQ,KAAK,CAAC;AAAA,MACpI;AAEA,UAAI;AACJ,UAAI;AACF,0BAAkB;AAClB,cAAM,KAAK,QAAQ,iBAAiB,YAAY,QAAQ,WAAS,KAAK,QAAQ,QAAQ,YAAY,eAAe,QAAQ,KAAK,CAAC;AAAA,MACjI,SAAS,OAAO;AACd,cAAM,iBAAiB,KAAK,SAAS,KAAK;AAC1C,YAAI,mBAAmB,uBAAwB,OAAM;AACrD,uBAAe,UAAU,4BAA4B,gBAAgB,OAAO;AAC5E,aAAK,KAAK,yCAAyC,YAAY;AAAA,MACjE;AAEA,wBAAkB;AAClB,YAAM,KAAK,QAAQ,iBAAiB,YAAY,QAAQ,WAAS,KAAK,QAAQ,QAAQ,UAAU,eAAe,QAAQ,KAAK,CAAC;AAE7H,UAAI;AACJ,UAAI;AACF,0BAAkB;AAClB,cAAM,KAAK,QAAQ,iBAAiB,YAAY,QAAQ,WAAS,KAAK,QAAQ,QAAQ,cAAc,eAAe,QAAQ,KAAK,CAAC;AAAA,MACnI,SAAS,OAAO;AACd,cAAM,iBAAiB,KAAK,SAAS,KAAK;AAC1C,YAAI,mBAAmB,uBAAwB,OAAM;AACrD,2BAAmB,UAAU,4BAA4B,gBAAgB,WAAW;AACpF,aAAK,KAAK,iDAAiD,gBAAgB;AAAA,MAC7E;AAEA,UAAI,CAAC,iBAAkB,MAAK,oBAAoB,eAAe,YAAY,MAAM;AAEjF,UAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACzC,WAAK,sBAAsB;AAC3B,YAAM,gBAAgB,KAAK,QAAQ,QAAQ,uBAAuB,aAAa;AAC/E,YAAM,cAAc,KAAK,QAAQ,KAAK,mBAAmB;AACzD,YAAM,KAAK,eAAe,YAAY;AAAA,QACpC,QAAQ,oBAAqB,iBAAiB,eAAgB,aAAa;AAAA,QAC3E,WAAW,oBAAoB;AAAA,QAC/B;AAAA,MACF,CAAC;AACD,WAAK,SAAS,KAAK,qBAAqB,UAAU;AAAA,IACpD,SAAS,OAAO;AACd,UAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACzC,WAAK,uBAAuB;AAC5B,YAAM,iBAAiB,KAAK,SAAS,KAAK;AAC1C,UAAI,mBAAmB,wBAAwB;AAC7C,cAAM,KAAK,aAAa,gBAAgB,WAAW,UAAU;AAAA,MAC/D;AACA,YAAM,SAAS,mBAAmB,UAAU,UAAU;AACtD,YAAM,QAAQ,KAAK,aAAa;AAChC,YAAM,KAAK,eAAe,YAAY;AAAA,QACpC;AAAA,QACA,WAAW,UAAU,4BAA4B,gBAAgB,eAAe;AAAA,QAChF,aAAa,KAAK,QAAQ,KAAK;AAAA,MACjC,CAAC;AACD,WAAK,SAAS,OAAO,UAAU;AAC/B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,QACZ,WACA,YACA,QACA,WACe;AACf,QAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACzC,UAAM,KAAK,aAAa,WAAW,WAAW,UAAU;AACxD,QAAI;AACF,YAAM,QAAQ,KAAK,kBAAkB,YAAY,MAAM;AACvD,YAAM,SAAS,MAAM,UAAU,KAAK;AACpC,UAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACzC,YAAM,QAAQ,SAAS,KAAK;AAC5B,UAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACzC,YAAM,KAAK,aAAa,WAAW,SAAS,UAAU;AAAA,IACxD,SAAS,OAAO;AACd,UAAI,KAAK,UAAU,YAAY,MAAM,EAAG,OAAM,KAAK,aAAa,WAAW,UAAU,UAAU;AAC/F,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,kBAAkB,YAAoB,QAA6C;AACzF,WAAO,OAAO,OAAO;AAAA,MACnB;AAAA,MACA;AAAA,MACA,WAAW,MAAM,KAAK,UAAU,YAAY,MAAM;AAAA,MAClD,cAAc,MAAM;AAClB,YAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG,OAAM,IAAI,gCAAgC;AAAA,MACrF;AAAA,MACA,mBAAmB,CACjB,cACG;AACH,YAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG,QAAO;AAChD,kBAAU;AACV,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,SAAS,OAAgD;AAC/D,QAAI;AACF,YAAM,iBAAiB,KAAK,QAAQ,QAAQ,gBAAgB,KAAK,KAAK;AACtE,aAAO,mBAAmB,aAAa,mBAAmB,WAAW,mBAAmB,yBACpF,iBACA;AAAA,IACN,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,eAAuB;AAC7B,UAAM,cAAc,KAAK;AAAA,MACvB,KAAK;AAAA,MACL,KAAK,mBAAmB,KAAK,KAAK,IAAI,GAAG,KAAK,sBAAsB,CAAC;AAAA,IACvE;AACA,UAAM,SAAS,KAAK,OAAO;AAC3B,QAAI,CAAC,OAAO,SAAS,MAAM,KAAK,SAAS,KAAK,SAAS,GAAG;AACxD,YAAM,IAAI,UAAU,sDAAsD;AAAA,IAC5E;AACA,UAAM,SAAS,cAAc,KAAK,eAAe,SAAS,IAAI;AAC9D,WAAO,KAAK,IAAI,GAAG,KAAK,IAAI,oBAAoB,KAAK,MAAM,cAAc,MAAM,CAAC,CAAC;AAAA,EACnF;AAAA,EAEQ,oBACN,eACA,YACA,QACM;AACN,UAAM,4BAA4B,KAAK,QAAQ,QAAQ,2BAA2B;AAAA,MAChF,KAAK,QAAQ;AAAA,IACf;AACA,UAAM,aAAa,KAAK,QAAQ,QAAQ,YAAY,KAAK,KAAK,QAAQ,OAAO;AAC7E,QAAI,CAAC,6BAA6B,CAAC,cAAc,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACtF,SAAK,QAAQ,QAAQ,EAClB,KAAK,YAAY;AAChB,YAAM,aAAa,MAAM,0BAA0B,eAAe,MAAM;AACxE,UAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACzC,YAAM,UAAU,+BAA+B,UAAU;AACzD,iBAAW,UAAU,SAAS;AAC5B,YAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACzC,cAAM,WAAW,KAAK,mBAAmB,IAAI,MAAM;AACnD,YAAI,UAAU,eAAe,WAAY;AACzC,cAAM,MAAM,KAAK;AAAA,UACf;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,cAAM,SAAS,EAAE,YAAY,SAAS,IAAI;AAC1C,aAAK,mBAAmB,IAAI,QAAQ,MAAM;AAC1C,cAAM,UAAU,MAAY;AAC1B,cAAI,KAAK,mBAAmB,IAAI,MAAM,MAAM,QAAQ;AAClD,iBAAK,mBAAmB,OAAO,MAAM;AAAA,UACvC;AAAA,QACF;AACA,aAAK,IAAI,KAAK,SAAS,OAAO;AAAA,MAChC;AAAA,IACF,CAAC,EACA,MAAM,CAAC,UAAmB;AACzB,UAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACzC,WAAK;AAAA,QACH;AAAA,QACA,UAAU,4BAA4B,KAAK,SAAS,KAAK,CAAC;AAAA,MAC5D;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEA,MAAc,wBACZ,eACA,QACA,YACA,QACA,YACe;AACf,QAAI,UAAU;AACd,WAAO,KAAK,UAAU,YAAY,MAAM,GAAG;AACzC,UAAI;AACF,cAAM,SAAS,MAAM,WAAW,eAAe,QAAQ,MAAM;AAC7D,YAAI,CAAC,KAAK,UAAU,YAAY,MAAM,KAAK,OAAO,SAAU;AAC5D,kBAAU;AAAA,MACZ,SAAS,OAAO;AACd,YAAI,CAAC,KAAK,UAAU,YAAY,MAAM,EAAG;AACzC,mBAAW;AACX,aAAK;AAAA,UACH;AAAA,UACA,UAAU,4BAA4B,KAAK,SAAS,KAAK,CAAC;AAAA,QAC5D;AAAA,MACF;AACA,YAAM,QAAQ,KAAK,2BAA2B,OAAO;AACrD,UAAI;AACF,cAAM,eAAe,OAAO,MAAM;AAAA,MACpC,QAAQ;AACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,2BAA2B,SAAyB;AAC1D,UAAM,cAAc,KAAK;AAAA,MACvB,KAAK;AAAA,MACL,KAAK,iCAAiC,KAAK,KAAK,IAAI,GAAG,UAAU,CAAC;AAAA,IACpE;AACA,UAAM,SAAS,KAAK,OAAO;AAC3B,QAAI,CAAC,OAAO,SAAS,MAAM,KAAK,SAAS,KAAK,SAAS,GAAG;AACxD,aAAO,KAAK;AAAA,IACd;AACA,UAAM,SAAS,cAAc,KAAK,eAAe,SAAS,IAAI;AAC9D,WAAO,KAAK,IAAI,GAAG,KAAK,IAAI,oBAAoB,KAAK,MAAM,cAAc,MAAM,CAAC,CAAC;AAAA,EACnF;AAAA,EAEA,MAAc,8BAA8B,YAAmC;AAC7E,UAAM,OAAO,CAAC,GAAG,KAAK,mBAAmB,OAAO,CAAC,EAC9C,OAAO,SAAO,IAAI,eAAe,UAAU,EAC3C,IAAI,SAAO,IAAI,QAAQ,MAAM,MAAM,MAAS,CAAC;AAChD,UAAM,QAAQ,IAAI,IAAI;AAAA,EACxB;AAAA,EAEQ,UAAkB;AACxB,UAAM,QAAQ,KAAK,IAAI;AACvB,QAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,GAAG;AAC7C,YAAM,IAAI,UAAU,gEAAgE;AAAA,IACtF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,QAAQ,SAAyB;AACvC,UAAM,MAAM,KAAK,QAAQ;AACzB,QAAI,MAAM,OAAO,mBAAmB,SAAS;AAC3C,YAAM,IAAI,UAAU,uDAAuD;AAAA,IAC7E;AACA,WAAO,MAAM;AAAA,EACf;AAAA,EAEQ,SAAS,SAAiB,YAA0B;AAC1D,QAAI,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU,YAAY,KAAK,WAAW,MAAM,EAAG;AAC1E,SAAK,WAAW;AAChB,SAAK,QAAQ,WAAW,MAAM;AAC5B,UAAI,CAAC,KAAK,UAAU,YAAY,KAAK,WAAW,MAAM,EAAG;AACzD,WAAK,KAAK,OAAO,EAAE,MAAM,MAAM;AAC7B,aAAK;AAAA,UACH;AAAA,UACA,UAAU,4BAA4B,SAAS;AAAA,QACjD;AAAA,MACF,CAAC;AAAA,IACH,GAAG,OAAO;AAAA,EACZ;AAAA,EAEQ,aAAmB;AACzB,QAAI,KAAK,MAAO,cAAa,KAAK,KAAK;AACvC,SAAK,QAAQ;AAAA,EACf;AAAA,EAEQ,UAAU,YAAoB,QAA8B;AAClE,WAAO,eAAe,KAAK,cAAc,eAAe,KAAK,uBAAuB,CAAC,OAAO;AAAA,EAC9F;AAAA,EAEA,MAAc,aACZ,WACA,QACA,YACe;AACf,QAAI,eAAe,KAAK,cAAc,eAAe,KAAK,oBAAqB;AAC/E,SAAK,gBAAgB,eAAe;AAAA,MAClC,GAAG,KAAK;AAAA,MACR,YAAY,EAAE,GAAG,KAAK,cAAc,YAAY,CAAC,SAAS,GAAG,OAAO;AAAA,IACtE,CAAC;AACD,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,MAAc,eACZ,YACA,QACe;AACf,QAAI,eAAe,KAAK,cAAc,eAAe,KAAK,oBAAqB;AAC/E,UAAM,OAAsC;AAAA,MAC1C,GAAG,KAAK;AAAA,MACR,GAAG;AAAA,MACH,GAAI,OAAO,cAAc,SAAY,EAAE,WAAW,OAAU,IAAI,CAAC;AAAA,IACnE;AACA,SAAK,gBAAgB,eAAe,IAAI;AACxC,SAAK,KAAK;AAAA,EACZ;AAAA,EAEQ,gBAAsB;AAC5B,SAAK,gBAAgB,eAAe;AAAA,MAClC,QAAQ,KAAK,QAAQ,QAAQ,aAAa,KAAK,aAAa,IACxD,YACA;AAAA,MACJ,YAAY,KAAK;AAAA,MACjB,YAAY,gBAAgB;AAAA,IAC9B,CAAC;AACD,SAAK,KAAK;AAAA,EACZ;AAAA;AAAA,EAGQ,OAAa;AACnB,UAAM,WAAW,KAAK;AACtB,UAAM,SAAS,KAAK,WAAW;AAC/B,SAAK,QAAQ,QAAQ,EAClB,KAAK,YAAY;AAChB,UAAI,CAAC,KAAK,UAAU,SAAS,YAAY,MAAM,EAAG;AAClD,YAAM,KAAK,QAAQ;AAAA,QACjB;AAAA,QACA,KAAK,kBAAkB,SAAS,YAAY,MAAM;AAAA,MACpD;AAAA,IACF,CAAC,EACA,MAAM,MAAM;AACX,WAAK;AAAA,QACH;AAAA,QACA,UAAU,gCAAgC,OAAO;AAAA,MACnD;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EAEQ,KAAK,SAAiB,OAAyC;AACrE,UAAM,iBAAiB,QAAQ,MAAM,GAAG,GAAG;AAC3C,SAAK,QAAQ,QAAQ,EAClB,KAAK,MAAM,KAAK,QAAQ,aAAa,gBAAgB,KAAK,CAAC,EAC3D,MAAM,MAAM,MAAS;AAAA,EAC1B;AACF;;;ACzsBO,IAAM,oCAAoC;AAG1C,IAAM,6CAA6C;AAEnD,IAAM,0BAA0B,OAAO,OAAO;AAAA,EACnD,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,0BAA0B;AAAA,EAC1B,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,YAAY;AAAA,EACZ,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,4BAA4B;AAAA,EAC5B,uBAAuB,KAAK;AAC9B,CAAC;AAqED,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,QAAQ,OAAsB;AACrC,QAAM,IAAI,MAAM,4BAA4B,KAAK,EAAE;AACrD;AAEA,SAASC,UAAS,OAAkD;AAClE,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,YAAqB,OAAO,eAAe,KAAK;AACtD,SAAO,cAAc,OAAO,aAAa,cAAc;AACzD;AAEA,SAASC,iBACP,OACA,SACA,UACM;AACN,MAAI,OAAO,KAAK,KAAK,EAAE,KAAK,SAAO,CAAC,QAAQ,SAAS,GAAG,CAAC,EAAG,SAAQ,QAAQ;AAC9E;AAEA,SAAS,YAAY,OAAgB,OAAe,eAA+B;AACjF,MACE,OAAO,UAAU,YACjB,MAAM,WAAW,KACjB,MAAM,SAAS,iBACf,UAAU,MAAM,KAAK,EACrB,SAAQ,KAAK;AACf,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,MAAM,SAAS,IAAK,SAAQ,KAAK;AAAA,EAC/C;AACA,SAAO;AACT;AAEA,SAAS,oBACP,OACA,OACA,UACA,eACU;AACV,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,SAAU,SAAQ,KAAK;AACnE,QAAM,QAAQ,MAAM,KAAK,OAAO,UAAQ,YAAY,MAAM,OAAO,aAAa,CAAC;AAC/E,MAAI,IAAI,IAAI,KAAK,EAAE,SAAS,MAAM,OAAQ,SAAQ,KAAK;AACvD,SAAO,MAAM,KAAK,WAAW;AAC/B;AAEA,SAAS,YAAY,MAAc,OAAuB;AACxD,SAAO,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;AAChD;AAEA,SAAS,sBAAsB,OAAoC;AACjE,MAAI,CAACD,UAAS,KAAK,EAAG,SAAQ,cAAc;AAC5C,EAAAC,iBAAgB,OAAO,gBAAgB,cAAc;AACrD,MAAI,OAAO,MAAM,YAAY,UAAW,SAAQ,sBAAsB;AACtE,MAAI,MAAM,cAAc,UAAa,OAAO,MAAM,cAAc,WAAW;AACzE,YAAQ,wBAAwB;AAAA,EAClC;AACA,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,KAAK,MAAM,MAAM,SAAS,wBAAwB,WAAW;AACzF,YAAQ,oBAAoB;AAAA,EAC9B;AAEA,QAAM,QAAQ,MAAM,KAAK,MAAM,OAAO,CAAC,SAAS;AAC9C,QAAI,CAACD,UAAS,IAAI,EAAG,SAAQ,oBAAoB;AACjD,IAAAC,iBAAgB,MAAM,CAAC,UAAU,SAAS,UAAU,GAAG,oBAAoB;AAC3E,UAAM,OAAO;AAAA,MACX,QAAQ;AAAA,QACN,KAAK;AAAA,QACL;AAAA,QACA,wBAAwB;AAAA,MAC1B;AAAA,MACA,GAAI,KAAK,UAAU,SACf,CAAC,IACD;AAAA,QACA,OAAO;AAAA,UACL,KAAK;AAAA,UACL;AAAA,UACA,wBAAwB;AAAA,QAC1B;AAAA,MACF;AAAA,MACF,GAAI,KAAK,aAAa,SAClB,CAAC,IACD;AAAA,QACA,UAAU;AAAA,UACR,KAAK;AAAA,UACL;AAAA,UACA,wBAAwB;AAAA,QAC1B;AAAA,MACF;AAAA,IACJ;AACA,WAAO;AAAA,EACT,CAAC;AACD,QAAM,UAAU,MAAM,IAAI,UAAQ,KAAK,MAAM;AAC7C,MAAI,IAAI,IAAI,OAAO,EAAE,SAAS,QAAQ,OAAQ,SAAQ,oBAAoB;AAC1E,QAAM;AAAA,IAAK,CAAC,MAAM,UAChB,YAAY,KAAK,QAAQ,MAAM,MAAM,KACrC,YAAY,KAAK,SAAS,IAAI,MAAM,SAAS,EAAE,KAC/C,YAAY,KAAK,YAAY,IAAI,MAAM,YAAY,EAAE;AAAA,EACvD;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,IAC1B;AAAA,IACA,YAAY;AAAA,MACV,MAAM;AAAA,MACN;AAAA,MACA,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,IAC1B;AAAA,IACA,SAAS,MAAM;AAAA,IACf,GAAI,MAAM,cAAc,SAAY,CAAC,IAAI,EAAE,WAAW,MAAM,UAAU;AAAA,IACtE,YAAY;AAAA,MACV,MAAM;AAAA,MACN;AAAA,MACA,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,yBAAyB,OAAqC;AACrE,MAAI,CAACD,UAAS,KAAK,EAAG,SAAQ,SAAS;AACvC,EAAAC,iBAAgB,OAAO,cAAc,SAAS;AAC9C,MAAI,CAAC,OAAO,cAAc,MAAM,SAAS,KAAM,MAAM,YAAuB,GAAG;AAC7E,YAAQ,WAAW;AAAA,EACrB;AACA,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,wBAAwB;AAAA,IAC1B;AAAA,IACA,WAAW,MAAM;AAAA,IACjB,OAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,wBAAwB;AAAA,IAC1B;AAAA,IACA,cAAc,sBAAsB,MAAM,YAAY;AAAA,IACtD,YAAY;AAAA,MACV,MAAM;AAAA,MACN;AAAA,MACA,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,IAC1B;AAAA,IACA,mBAAmB;AAAA,MACjB,MAAM;AAAA,MACN;AAAA,MACA,wBAAwB;AAAA,MACxB,wBAAwB;AAAA,IAC1B;AAAA,EACF;AACF;AAEA,SAAS,eAAe,SAA0C;AAChE,MAAI;AACF,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,UAAU;AAAA,QACV,oBAAoB,wBAAwB;AAAA,QAC5C,gBAAgB,wBAAwB,6BAA6B;AAAA,QACrE,UAAU,wBAAwB;AAAA,MACpC;AAAA,IACF;AAAA,EACF,QAAQ;AACN,YAAQ,SAAS;AAAA,EACnB;AACF;AAGO,SAAS,4BACd,SACY;AACZ,SAAO,eAAe,yBAAyB,OAAO,CAAC;AACzD;AAGA,eAAsB,2BACpB,SACA,SACiC;AACjC,QAAM,aAAa,yBAAyB,OAAO;AACnD,QAAM,OAAO,OAAO,YAAY,aAAa,UAAU,QAAQ;AAC/D,MAAI,OAAO,SAAS,WAAY,SAAQ,QAAQ;AAChD,QAAM,YAAY;AAAA,IAChB,MAAM,KAAK,eAAe,UAAU,CAAC;AAAA,IACrC;AAAA,IACA,wBAAwB;AAAA,EAC1B;AACA,SAAO,EAAE,GAAG,YAAY,UAAU;AACpC;AAMA,eAAsB,6BACpB,SACA,SACkB;AAClB,MAAI;AACF,QAAI,CAACD,UAAS,OAAO,EAAG,QAAO;AAC/B,IAAAC,iBAAgB,SAAS,CAAC,GAAG,cAAc,WAAW,GAAG,SAAS;AAClE,UAAM,YAAY;AAAA,MAChB,QAAQ;AAAA,MACR;AAAA,MACA,wBAAwB;AAAA,IAC1B;AACA,UAAM,WAAW,OAAO;AAAA,MACtB,aAAa,IAAI,SAAO,CAAC,KAAK,QAAQ,GAAG,CAAC,CAAC;AAAA,IAC7C;AACA,UAAM,aAAa,yBAAyB,QAAQ;AACpD,UAAM,qBAAqB;AAAA,MACzB,QAAQ;AAAA,MACR;AAAA,MACA,wBAAwB;AAAA,IAC1B;AACA,UAAM,MAAM,QAAQ,OAAO,KAAK,IAAI;AACpC,UAAM,iBAAiB,QAAQ,kBAC7B;AACF,QACE,CAAC,OAAO,cAAc,GAAG,KACzB,CAAC,OAAO,cAAc,cAAc,KACpC,iBAAiB,KACjB,KAAK,IAAI,WAAW,YAAY,GAAG,IAAI,eACvC,QAAO;AAET,UAAM,iBAAiB,QAAQ,kBAAkB,QAAQ;AACzD,QAAI,OAAO,mBAAmB,cAAc,OAAO,QAAQ,iBAAiB,YAAY;AACtF,aAAO;AAAA,IACT;AACA,UAAM,UAAU,eAAe,UAAU;AACzC,QACE,CAAC,MAAM,eAAe;AAAA,MACpB,QAAQ,WAAW;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC,EACD,QAAO;AAET,WAAO,MAAM,QAAQ,aAAa;AAAA,MAChC,QAAQ,WAAW;AAAA,MACnB;AAAA,MACA,WAAW,WAAW;AAAA,MACtB,OAAO,WAAW;AAAA,IACpB,CAAC;AAAA,EACH,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AClVO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,MAA8B;AACxC,UAAM,KAAK,OAAO;AAClB,SAAK,OAAO;AACZ,SAAK,OAAO,KAAK;AACjB,SAAK,YAAY,KAAK;AACtB,SAAK,eAAe,KAAK;AACzB,SAAK,SAAS,KAAK;AACnB,SAAK,UAAU,KAAK;AAAA,EACtB;AAAA,EAEA,SAAiC;AAC/B,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,cAAc,KAAK;AAAA,MACnB,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AACF;;;AC/CO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxB;AAAA,EAEhB,YAAY,MAA0B,SAAiB,SAAwB;AAC7E,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;AAUA,IAAM,eAAe;AACrB,IAAM,aAAa;AAEnB,SAAS,sBAAsB,OAAe,MAAoB;AAChE,MAAI,CAAC,OAAO,cAAc,KAAK,KAAK,SAAS,GAAG;AAC9C,UAAM,IAAI,UAAU,GAAG,IAAI,kCAAkC;AAAA,EAC/D;AACF;AAEA,SAAS,wBAAwB,iBAA+B;AAC9D,wBAAsB,iBAAiB,iBAAiB;AACxD,MAAI,kBAAkB,YAAY;AAChC,UAAM,IAAI,UAAU,6DAA6D;AAAA,EACnF;AACF;AAEO,SAAS,gBAAgB,OAAgB,kBAAkB,YAAwB;AACxF,0BAAwB,eAAe;AACvC,MAAI;AACJ,MAAI;AACF,iBAAa,KAAK,UAAU,KAAK;AAAA,EACnC,SAAS,OAAO;AACd,UAAM,IAAI,eAAe,gBAAgB,yCAAyC;AAAA,MAChF,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AACA,MAAI,eAAe,QAAW;AAC5B,UAAM,IAAI,eAAe,gBAAgB,uCAAuC;AAAA,EAClF;AACA,QAAM,UAAU,IAAI,YAAY,EAAE,OAAO,UAAU;AACnD,MAAI,QAAQ,aAAa,iBAAiB;AACxC,UAAM,IAAI;AAAA,MACR;AAAA,MACA,8BAA8B,eAAe;AAAA,IAC/C;AAAA,EACF;AACA,QAAM,QAAQ,IAAI,WAAW,eAAe,QAAQ,UAAU;AAC9D,MAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,YAAY,EAAE,UAAU,GAAG,QAAQ,YAAY,KAAK;AACjG,QAAM,IAAI,SAAS,YAAY;AAC/B,SAAO;AACT;AAEA,gBAAuB,iBACrB,QACA,kBAAkB,YACS;AAC3B,mBAAiB,SAAS,QAAQ;AAChC,UAAM,gBAAgB,OAAO,eAAe;AAAA,EAC9C;AACF;AAEA,SAAS,aAAa,QAAsC;AAC1D,SAAO,IAAI,eAAe,WAAW,kCAAkC;AAAA,IACrE,OAAO,QAAQ;AAAA,EACjB,CAAC;AACH;AAeA,SAAS,mBACP,cACA,eACmB;AACnB,MAAI,kBAAkB,UAAa,iBAAiB,cAAc;AAChE,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AACF;AAEA,eAAe,cACb,UACA,cACA,eACA,QACqC;AACrC,MAAI,QAAQ,QAAS,OAAM,aAAa,MAAM;AAC9C,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,WAAW,mBAAmB,cAAc,aAAa;AAC/D,MAAI,SAAS,MAAM,KAAK;AACtB,UAAM,IAAI,eAAe,SAAS,MAAM,SAAS,OAAO;AAAA,EAC1D;AAEA,SAAO,IAAI,QAAoC,CAAC,SAAS,WAAW;AAClE,QAAI,UAAU;AACd,QAAI;AACJ,UAAM,SAAS,CAAC,aAAyB;AACvC,UAAI,QAAS;AACb,gBAAU;AACV,UAAI,UAAU,OAAW,cAAa,KAAK;AAC3C,cAAQ,oBAAoB,SAAS,OAAO;AAC5C,eAAS;AAAA,IACX;AACA,UAAM,UAAU,MAAM;AACpB,aAAO,MAAM;AACX,eAAO,aAAa,MAAM,CAAC;AAAA,MAC7B,CAAC;AAAA,IACH;AAEA,UAAM,YAAY,MAAM;AACtB,UAAI,QAAS;AACb,YAAM,cAAc,SAAS,KAAK,KAAK,IAAI;AAC3C,UAAI,cAAc,GAAG;AAKnB,gBAAQ,WAAW,WAAW,KAAK,IAAI,GAAG,WAAW,CAAC;AACtD;AAAA,MACF;AACA,aAAO,MAAM;AACX,eAAO,IAAI,eAAe,SAAS,MAAM,SAAS,OAAO,CAAC;AAAA,MAC5D,CAAC;AAAA,IACH;AAEA,YAAQ,WAAW,WAAW,KAAK,IAAI,GAAG,SAAS,KAAK,GAAG,CAAC;AAC5D,YAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAEzD,QAAI,QAAQ,SAAS;AACnB,cAAQ;AACR;AAAA,IACF;AACA,SAAK,SAAS,KAAK,EAAE;AAAA,MACnB,CAAC,WAAW;AACV,eAAO,MAAM;AACX,kBAAQ,MAAM;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,MACA,CAAC,UAAmB;AAClB,eAAO,MAAM;AACX;AAAA,YACE,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,4BAA4B;AAAA,cACrE,OAAO;AAAA,YACT,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAOO,SAAS,sBACd,QACA,SACwB;AACxB,0BAAwB,QAAQ,eAAe;AAC/C,wBAAsB,QAAQ,eAAe,eAAe;AAC5D,wBAAsB,QAAQ,gBAAgB,gBAAgB;AAE9D,UAAQ,gBAAgB,aAAqC;AAC3D,UAAM,WAAW,OAAO,OAAO,aAAa,EAAE;AAC9C,UAAM,SAAS,IAAI,WAAW,YAAY;AAC1C,QAAI,cAAc;AAClB,QAAI;AACJ,QAAI,eAAe;AACnB,QAAI;AACJ,QAAI,eAAe,KAAK,IAAI,IAAI,QAAQ;AACxC,QAAI;AACJ,QAAI,cAAc;AAClB,QAAI,YAAY;AAEhB,UAAM,YAAY,CAAC,UAAgC;AACjD,UAAI,YAAa;AACjB,oBAAc;AACd,UAAI;AAIF,aAAK,QAAQ,QAAQ,QAAQ,QAAQ,KAAK,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,MACpE,QAAQ;AAAA,MAGR;AAAA,IACF;AAEA,UAAM,gBAAgB,CAAC,UAA+B;AACpD,UAAI;AACJ,UAAI;AACF,eAAO,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,EAAE,OAAO,KAAK;AAAA,MAC/D,SAAS,OAAO;AACd,cAAM,IAAI,eAAe,gBAAgB,yCAAyC;AAAA,UAChF,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AACA,UAAI;AACF,eAAO,KAAK,MAAM,IAAI;AAAA,MACxB,SAAS,OAAO;AACd,cAAM,IAAI,eAAe,gBAAgB,wCAAwC;AAAA,UAC/E,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,kBAAkB,MAAY;AAClC,gBAAU,aAAa,QAAQ,MAAM,CAAC;AAAA,IACxC;AACA,YAAQ,QAAQ,iBAAiB,SAAS,iBAAiB,EAAE,MAAM,KAAK,CAAC;AACzE,QAAI,QAAQ,QAAQ,QAAS,iBAAgB;AAE7C,QAAI;AACF,iBAAS;AACP,cAAM,SAAS,MAAM;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,QACV;AACA,YAAI,OAAO,MAAM;AACf,cAAI,cAAc,KAAK,yBAAyB,QAAW;AACzD,kBAAM,IAAI,eAAe,mBAAmB,mCAAmC;AAAA,UACjF;AACA,sBAAY;AACZ;AAAA,QACF;AACA,YAAI,EAAE,OAAO,iBAAiB,aAAa;AACzC,gBAAM,IAAI,UAAU,gDAAgD;AAAA,QACtE;AACA,YAAI,OAAO,MAAM,eAAe,EAAG;AACnC,cAAM,MAAM,KAAK,IAAI;AACrB,uBAAe,MAAM,QAAQ;AAC7B,0BAAkB,MAAM,QAAQ;AAOhC,YAAI,cAAc;AAClB,eAAO,cAAc,OAAO,MAAM,YAAY;AAC5C,cAAI,yBAAyB,QAAW;AACtC,kBAAM,kBAAkB,eAAe;AACvC,kBAAMC,UAAS,KAAK,IAAI,iBAAiB,OAAO,MAAM,aAAa,WAAW;AAC9E,mBAAO,IAAI,OAAO,MAAM,SAAS,aAAa,cAAcA,OAAM,GAAG,WAAW;AAChF,2BAAeA;AACf,2BAAeA;AACf,gBAAI,cAAc,aAAc;AAEhC,mCAAuB,IAAI;AAAA,cACzB,OAAO;AAAA,cACP,OAAO;AAAA,cACP;AAAA,YACF,EAAE,UAAU,GAAG,KAAK;AACpB,gBAAI,uBAAuB,QAAQ,iBAAiB;AAClD,oBAAM,IAAI;AAAA,gBACR;AAAA,gBACA,8BAA8B,QAAQ,eAAe;AAAA,cACvD;AAAA,YACF;AACA,sBAAU,IAAI,WAAW,oBAAoB;AAC7C,2BAAe;AAAA,UACjB;AAEA,gBAAM,mBAAmB,uBAAuB;AAChD,gBAAM,SAAS,KAAK,IAAI,kBAAkB,OAAO,MAAM,aAAa,WAAW;AAC/E,cAAI,SAAS,GAAG;AACd,oBAAS,IAAI,OAAO,MAAM,SAAS,aAAa,cAAc,MAAM,GAAG,YAAY;AACnF,4BAAgB;AAChB,2BAAe;AAAA,UACjB;AACA,cAAI,eAAe,qBAAsB;AAEzC,gBAAM,QAAQ,cAAc,OAAQ;AACpC,wBAAc;AACd,oBAAU;AACV,yBAAe;AACf,iCAAuB;AACvB,gBAAM,yBAAyB,cAAc,OAAO,MAAM;AAC1D,0BAAgB;AAChB,gBAAM;AACN,cAAI,QAAQ,QAAQ,QAAS,OAAM,aAAa,QAAQ,MAAM;AAI9D,gBAAM,YAAY,KAAK,IAAI;AAC3B,yBAAe,YAAY,QAAQ;AACnC,cAAI,wBAAwB;AAC1B,4BAAgB,YAAY,QAAQ;AAAA,UACtC;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,aAAa,iBAAiB,iBAChC,QACA,IAAI,eAAe,WAAW,4BAA4B,EAAE,OAAO,MAAM,CAAC;AAC9E,gBAAU,UAAU;AACpB,YAAM;AAAA,IACR,UAAE;AACA,cAAQ,QAAQ,oBAAoB,SAAS,eAAe;AAC5D,UAAI,CAAC,UAAW,WAAU,aAAa,QAAQ,MAAM,CAAC;AAItD,UAAI;AACF,cAAM,WAAW,SAAS,SAAS;AACnC,YAAI,aAAa,OAAW,MAAK,QAAQ,QAAQ,QAAQ,EAAE,MAAM,MAAM,MAAS;AAAA,MAClF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,GAAG;AACL;;;ACzVO,IAAM,gCAAgC;AACtC,IAAM,oCAAoC,OAAO,OAAO;AAAA,EAC7D,iBAAiB,OAAO;AAAA,EACxB,sBAAsB;AAAA,EACtB,uBAAuB;AAAA,EACvB,oBAAoB;AAAA,EACpB,yBAAyB;AAC3B,CAAC;AACD,IAAM,0BAA0B,kCAAkC;AAClE,IAAM,0BAA0B,kCAAkC;AAClE,IAAM,2BAA2B,kCAAkC;AACnE,IAAM,wBAAwB,kCAAkC;AAChE,IAAM,6BAA6B,kCAAkC;AA+CrE,SAAS,4BACP,MACA,SACoB;AACpB,SAAO,IAAI,mBAAmB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA,WAAW,SAAS;AAAA,EACtB,CAAC;AACH;AAEA,SAAS,iBAAiB,OAAqB;AAC7C,MAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,KAAK;AAC/C,UAAM,IAAI,UAAU,sDAAsD;AAAA,EAC5E;AACF;AAEA,SAASC,gBAAe,QAAuC;AAC7D,MAAI,QAAQ,SAAS;AACnB,UAAM,4BAA4B,aAAa,4CAA4C;AAAA,EAC7F;AACF;AAEA,eAAe,wBACb,SACA,QAIC;AACD,QAAM,QAAQ,MAAM,QAAQ,gBAAgB,QAAQ,QAAQ,MAAM;AAClE,SAAO;AAAA,IACL,QAAQ,MAAM,QAAQ,cAAc;AAAA,MAClC,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,QACE,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,aACb,QACA,SACA,OACA,UACA,eACe;AACf,QAAM,WAA+C;AAAA,IACnD,MAAM;AAAA,IACN;AAAA,IACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,EAC3B;AACA,QAAM,OAAO,KAAK,iBAAiB,CAAC,QAAQ,GAAG,aAAa,CAAC;AAC/D;AAEA,SAAS,gBAAgB,QAA+D;AACtF,MAAI,UAAU;AACd,SAAO,OAAO,UAAU;AACtB,QAAI,QAAS;AACb,cAAU;AACV,UAAM,OAAO,MAAM,KAAK;AAAA,EAC1B;AACF;AAEA,SAAS,YACP,QACA,eACA,eACA,QACA,OACwB;AACxB,SAAO,sBAAsB,OAAO,QAAQ;AAAA,IAC1C,iBAAiB;AAAA,IACjB;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,SAAS,cAAc,OAAuB;AAC5C,MAAI,EAAE,iBAAiB,gBAAiB,OAAM;AAC9C,MAAI,MAAM,SAAS,WAAW;AAC5B,UAAM,4BAA4B,aAAa,MAAM,OAAO;AAAA,EAC9D;AACA,MAAI,MAAM,SAAS,mBAAmB;AACpC,UAAM,4BAA4B,aAAa,MAAM,OAAO;AAAA,EAC9D;AACA,MAAI,MAAM,SAAS,kBAAkB,MAAM,SAAS,iBAAiB;AACnE,UAAM,4BAA4B,eAAe,MAAM,OAAO;AAAA,EAChE;AACA,QAAM,4BAA4B,WAAW,MAAM,OAAO;AAC5D;AAOO,SAAS,mCACd,SAC8B;AAC9B,QAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,mBAAiB,aAAa;AAE9B,SAAO;AAAA,IACL,MAAM,QAAQ,SAAS,mBAAmB,CAAC,GAAG;AAC5C,MAAAA,gBAAe,iBAAiB,MAAM;AACtC,YAAM,WAAW,iBAAiB;AAClC,YAAM,EAAE,QAAQ,MAAM,IAAI,MAAM,wBAAwB,SAAS,iBAAiB,MAAM;AACxF,YAAM,QAAQ,gBAAgB,MAAM;AACpC,YAAM,eAAe,MAAM;AACzB,aAAK,MAAM,4BAA4B,aAAa,4CAA4C,CAAC;AAAA,MACnG;AACA,uBAAiB,QAAQ,iBAAiB,SAAS,cAAc;AAAA,QAC/D,MAAM;AAAA,MACR,CAAC;AACD,UAAI;AACF,cAAM,aAAa,QAAQ,SAAS,OAAO,UAAU,aAAa;AAClE,YAAI;AACJ,yBACQ,SAAS;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA,iBAAiB;AAAA,UACjB;AAAA,QACF,GACA;AACA,cAAI,UAAU;AACZ,kBAAM;AAAA,cACJ;AAAA,cACA;AAAA,YACF;AAAA,UACF;AACA,qBAAW;AAAA,QACb;AACA,QAAAA,gBAAe,iBAAiB,MAAM;AACtC,YAAI,CAAC,UAAU;AACb,gBAAM;AAAA,YACJ;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,eAAO;AAAA,MACT,SAAS,OAAO;AACd,YAAI,iBAAiB,eAAgB,OAAM,MAAM,KAAK;AACtD,sBAAc,KAAK;AAAA,MACrB,UAAE;AACA,yBAAiB,QAAQ,oBAAoB,SAAS,YAAY;AAClE,cAAM,OAAO,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,MAC5C;AAAA,IACF;AAAA,IACA,OAAO,MAAM,SAAS,mBAAmB,CAAC,GAAG;AAC3C,MAAAA,gBAAe,iBAAiB,MAAM;AACtC,YAAM,EAAE,QAAQ,MAAM,IAAI,MAAM,wBAAwB,SAAS,iBAAiB,MAAM;AACxF,YAAM,QAAQ,gBAAgB,MAAM;AACpC,YAAM,eAAe,MAAM;AACzB,aAAK,MAAM,4BAA4B,aAAa,0CAA0C,CAAC;AAAA,MACjG;AACA,uBAAiB,QAAQ,iBAAiB,SAAS,cAAc;AAAA,QAC/D,MAAM;AAAA,MACR,CAAC;AACD,UAAI;AACF,cAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA,iBAAiB;AAAA,UACjB;AAAA,QACF;AACA,yBACQ,SAAS;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA,iBAAiB;AAAA,UACjB;AAAA,QACF,GACA;AACA,UAAAA,gBAAe,iBAAiB,MAAM;AACtC,gBAAM;AAAA,QACR;AACA,QAAAA,gBAAe,iBAAiB,MAAM;AAAA,MACxC,SAAS,OAAO;AACd,YAAI,iBAAiB,eAAgB,OAAM,MAAM,KAAK;AACtD,sBAAc,KAAK;AAAA,MACrB,UAAE;AACA,yBAAiB,QAAQ,oBAAoB,SAAS,YAAY;AAClE,cAAM,OAAO,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,kBACb,QACA,eAC6C;AAC7C,QAAM,QAAQ,gBAAgB,MAAM;AACpC,MAAI;AACJ,mBACQ,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GACA;AACA,QAAI,UAAU;AACZ,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QACE,UAAU,QACV,OAAO,UAAU,YACjB,MAAM,QAAQ,KAAK,KAClB,MAAkC,SAAS,8CAC3C,MAAkC,YAAY,QAC/C,OAAQ,MAAkC,YAAY,UACtD;AACA,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,eAAW;AAAA,EACb;AACA,MAAI,CAAC,UAAU;AACb,UAAM,4BAA4B,WAAW,yCAAyC;AAAA,EACxF;AACA,SAAO;AACT;AAEA,gBAAgB,mBACd,QACA,SACA,QAC4C;AAC5C,QAAM,WAAW,OAAO,OAAO,aAAa,EAAE;AAM9C,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,eAAe;AACnB,MAAI,sBAAsB,qBAAqB,QAAQ,QAAQ,OAAO,KAAK;AAE3E,QAAM,qBAAqB,MAAM;AAC/B,QAAI,kBAAkB,OAAW,cAAa,aAAa;AAC3D,oBAAgB;AAAA,EAClB;AACA,QAAM,kBAAkB,CAAC,UAAyB;AAChD,QAAI,gBAAgB;AAClB,YAAM,UAAU;AAChB,uBAAiB;AACjB,yBAAmB;AACnB,cAAQ,KAAK;AACb;AAAA,IACF;AACA,eAAW;AAAA,EACb;AACA,QAAM,WAAW,MAAM;AACrB,QAAI,aAAc;AAClB,mBAAe;AACf,SAAK,SAAS,KAAK,EAAE;AAAA,MACnB,CAAC,UAAU;AACT,uBAAe;AACf,wBAAgB,EAAE,MAAM,SAAS,MAAM,CAAC;AAAA,MAC1C;AAAA,MACA,CAAC,UAAmB;AAClB,uBAAe;AACf,wBAAgB,EAAE,MAAM,SAAS,MAAM,CAAC;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AACA,QAAM,kBAAkB,MAAqD;AAC3E,QAAI,UAAU;AACZ,YAAM,QAAQ;AACd,iBAAW;AACX,aAAO,QAAQ,QAAQ,KAAK;AAAA,IAC9B;AACA,QAAI,OAAO,QAAS,QAAO,QAAQ,QAAQ,EAAE,MAAM,UAAU,CAAC;AAC9D,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,uBAAiB;AACjB,sBAAgB,WAAW,MAAM;AAC/B,wBAAgB;AAChB,yBAAiB;AACjB,gBAAQ,EAAE,MAAM,WAAW,CAAC;AAAA,MAC9B,GAAG,0BAA0B;AAAA,IAC/B,CAAC;AAAA,EACH;AACA,QAAM,UAAU,MAAM;AACpB,oBAAgB,EAAE,MAAM,UAAU,CAAC;AAAA,EACrC;AAEA,SAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACxD,WAAS;AACT,MAAI;AACF,eAAS;AACP,YAAM,SAAS,MAAM,gBAAgB;AACrC,UAAI,OAAO,SAAS,UAAW;AAC/B,UAAI,OAAO,SAAS,YAAY;AAC9B,cAAM;AAAA,UACJ,UAAU,QAAQ;AAAA,UAClB,WAAW,QAAQ;AAAA,UACnB,IAAI;AAAA,UACJ,QAAQ,EAAE,MAAM,YAAY,iBAAiB,oBAAoB;AAAA,QACnE;AACA;AAAA,MACF;AACA,UAAI,OAAO,SAAS,QAAS,OAAM,OAAO;AAC1C,UAAI,OAAO,MAAM,KAAM;AACvB,YAAM,WAAW,OAAO,MAAM;AAC9B,4BAAsB,SAAS,KAC3B,qBAAqB,SAAS,MAAM,KAAK,sBACzC;AACJ,YAAM;AACN,eAAS;AAAA,IACX;AAAA,EACF,UAAE;AACA,uBAAmB;AACnB,qBAAiB;AACjB,WAAO,oBAAoB,SAAS,OAAO;AAC3C,SAAK,SAAS,SAAS;AAAA,EACzB;AACF;AAEA,SAAS,qBAAqB,OAAoC;AAChE,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,kBAAmB,MAAkC;AAC3D,SAAO,OAAO,oBAAoB,YAAY,gBAAgB,SAAS,IACnE,kBACA;AACN;AAGO,SAAS,uCACd,SACkC;AAClC,QAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,mBAAiB,aAAa;AAC9B,SAAO,OAAO,EAAE,cAAc,QAAQ,UAAU,MAAM;AACpD,UAAM,QAAQ,IAAI,gBAAgB;AAClC,UAAM,kBAAkB,MAAY;AAClC,UAAI,CAAC,MAAM,OAAO,SAAS;AACzB,cAAM,MAAM,OAAO,QAAQ,UAAU,IAAI,MAAM,oCAAoC,CAAC;AAAA,MACtF;AAAA,IACF;AACA,WAAO,QAAQ,iBAAiB,SAAS,iBAAiB,EAAE,MAAM,KAAK,CAAC;AACxE,QAAI,OAAO,QAAQ,QAAS,iBAAgB;AAC5C,QAAI;AACF,YAAM,WAAW,MAAM,kBAAkB,QAAQ,aAAa;AAC9D,UAAI,aAAa,CAAE,MAAM,UAAU,SAAS,KAAK,GAAI;AACnD,cAAM,4BAA4B,eAAe,oBAAoB;AAAA,MACvE;AACA,YAAM,UAAU,SAAS;AACzB,YAAM,UAAU,MAAM,QAAQ,eAAe,YAAY;AACzD,UAAI,QAAQ,cAAc,SAAS;AACjC,cAAM,OAAO;AAAA,UACX;AAAA,YACE,mBAAmB,QAAQ,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,CAAC,GAAG,SAAS,MAAM,MAAM;AAAA,YAC1F;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AACL,cAAM,WAAW,MAAM,QAAQ,QAAQ,SAAS;AAAA,UAC9C,QAAQ,OAAO;AAAA,UACf,UAAU,SAAS,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,wBAAwB,EAAE,YAAY;AAAA,QAC7F,CAAC;AACD,YAAI,OAAO,QAAQ,QAAS;AAC5B,cAAM,OAAO,KAAK,iBAAiB,CAAC,QAAQ,GAAG,aAAa,CAAC;AAAA,MAC/D;AAAA,IACF,UAAE;AACA,aAAO,QAAQ,oBAAoB,SAAS,eAAe;AAC3D,UAAI,CAAC,MAAM,OAAO,QAAS,OAAM,MAAM;AACvC,YAAM,OAAO,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,IAC5C;AAAA,EACF;AACF;;;ACpcO,IAAM,2BAA2B;AACjC,IAAM,4BAA4B;AA+BlC,IAAM,kCAAkC,IAAI,OAAO;AACnD,IAAM,4BAA4B,KAAK,OAAO;AAYrD,IAAM,cAAc,oBAAI,IAAsB;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,SAAS,oBAAoB,OAA4C;AAC9E,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,SAAS;AACf,SACEC,aAAY,QAAQ,CAAC,QAAQ,MAAM,UAAU,UAAU,OAAO,CAAC,KAC/D,OAAO,SAAS,4BAChB,OAAO,OAAO,OAAO,YACrB,OAAO,GAAG,SAAS,KAAK,OAAO,GAAG,UAAU,OAC5C,OAAO,OAAO,WAAW,YACzB,YAAY,IAAI,OAAO,MAA0B,KACjD,YAAY;AAEhB;AAEO,SAAS,qBAAqB,OAA6C;AAChF,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,SAAS;AACf,MACE,OAAO,SAAS,6BAA6B,OAAO,OAAO,OAAO,YAClE,OAAO,GAAG,WAAW,KAAK,OAAO,GAAG,SAAS,OAAO,OAAO,OAAO,OAAO,UACzE,QAAO;AACT,MAAI,OAAO,GAAI,QAAOA,aAAY,QAAQ,CAAC,QAAQ,MAAM,MAAM,QAAQ,CAAC;AACxE,MACE,CAACA,aAAY,QAAQ,CAAC,QAAQ,MAAM,MAAM,OAAO,CAAC,KAClD,OAAO,UAAU,QAAQ,OAAO,OAAO,UAAU,YAAY,MAAM,QAAQ,OAAO,KAAK,GACvF;AACA,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,OAAO;AACrB,SAAOA,aAAY,OAAO,CAAC,MAAM,CAAC,KAAK,OAAO,MAAM,SAAS,YAC3D,yBAAyB,KAAK,MAAM,IAAI;AAC5C;AAEA,SAAS,sBAAsB,OAA8C;AAC3E,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,SAAS;AACf,SACEA,aAAY,QAAQ;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,KACD,OAAO,OAAO,kBAAkB,YAChC,OAAO,OAAO,eAAe,YAC7B,OAAO,OAAO,WAAW,YACzB,OAAO,OAAO,cAAc,YAC5B,OAAO,OAAO,SAAS,aACvB,OAAO,OAAO,aAAa,YAC3B,OAAO,OAAO,aAAa;AAE/B;AAEA,SAASA,aAAY,OAAgC,SAAqC;AACxF,QAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,SAAO,OAAO,KAAK,KAAK,EAAE,MAAM,SAAO,KAAK,IAAI,GAAG,CAAC;AACtD;AAEA,eAAsB,wBAAwB,OAS5C;AACA,MAAI,UAAU,KAAM,QAAO;AAC3B,MACE,CAAC,sBAAsB,KAAK,KAC5B,CAAC,OAAO,cAAc,MAAM,UAAU,KAAK,MAAM,aAAa,KAC9D,MAAM,aAAa,mCACnB,CAAC,OAAO,cAAc,MAAM,MAAM,KAAK,MAAM,SAAS,KACtD,CAAC,OAAO,cAAc,MAAM,SAAS,KAAK,MAAM,YAAY,KAC5D,MAAM,YAAY,6BAClB,MAAM,SAAS,MAAM,aAAa,MAAM,aACxC,MAAM,UAAU,MAAM,SAAS,MAAM,eAAe,MAAM,cACzD,CAAC,MAAM,QAAQ,MAAM,eAAe,KACrC,MAAM,cAAc,SAAS,KAAK,KAAK,kCAAkC,CAAC,IAAI,IAAI,KAClF,MAAM,SAAS,SAAS,OAAO,MAAM,SAAS,SAAS,KACvD;AACA,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AACA,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,MAAM,cAAc,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AACvE,UAAM,eAAe,OAAO,OAAO,KAAK,KAAK,OAAO,SAAS,CAAC,IAAI,GAAG,GAAG;AACxE,UAAM,SAAS,KAAK,YAAY;AAChC,WAAO,WAAW,KAAK,QAAQ,CAAC,cAAc,UAAU,WAAW,CAAC,CAAC;AAAA,EACvE,QAAQ;AACN,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AACA,MAAI,KAAK,eAAe,MAAM,WAAY,OAAM,IAAI,MAAM,+BAA+B;AACzF,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,MAAM;AAAA,IACd,WAAW,MAAM;AAAA,IACjB,MAAM,MAAM;AAAA,IACZ,UAAU,MAAM;AAAA,IAChB,UAAU,MAAM;AAAA,EAClB;AACF;AAEO,SAAS,sBAAsB,OAOd;AACtB,MACE,MAAM,KAAK,aAAa,mCACxB,CAAC,OAAO,cAAc,MAAM,MAAM,KAAK,MAAM,SAAS,KACtD,CAAC,OAAO,cAAc,MAAM,SAAS,KAAK,MAAM,YAAY,KAC5D,MAAM,YAAY,6BAClB,MAAM,SAAS,MAAM,KAAK,aAAa,MAAM,aAC7C,MAAM,UAAU,MAAM,SAAS,MAAM,KAAK,eAAe,MAAM,cAC9D,CAAC,MAAM,QAAQ,MAAM,KAAK,eAAe,GAC1C;AACA,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AACA,MAAI,SAAS;AACb,WAAS,SAAS,GAAG,SAAS,MAAM,KAAK,QAAQ,UAAU,OAAQ;AACjE,cAAU,OAAO,aAAa,GAAG,MAAM,KAAK,SAAS,QAAQ,SAAS,KAAM,CAAC;AAAA,EAC/E;AACA,SAAO;AAAA,IACL,eAAe,KAAK,MAAM,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAAA,IACtF,YAAY,MAAM,KAAK;AAAA,IACvB,QAAQ,MAAM;AAAA,IACd,WAAW,MAAM;AAAA,IACjB,MAAM,MAAM;AAAA,IACZ,UAAU,MAAM;AAAA,IAChB,UAAU,MAAM;AAAA,EAClB;AACF;;;AC5KO,IAAM,4BAAN,MAA+D;AAAA,EACpD;AAAA,EACC;AAAA,EACA;AAAA,EAIA;AAAA,EAEjB,YAAY,SAA2C;AACrD,SAAK,SAAS,QAAQ;AACtB,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,SAAS,QAAQ;AAAA,EACxB;AAAA,EAEO,YAA+B;AACpC,WAAO,KAAK,cAAc,YAAY;AAAA,EACxC;AAAA,EAEO,4BACL,QACA,gBACA,aACA,mBACA,iBACA,SAC4C;AAC5C,WAAO,KAAK,QAAQ,QAAQ,+BAA+B;AAAA,MACzD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,GAAG,SAAS,MAAM;AAAA,EACpB;AAAA,EAEO,kBACL,QACA,gBACA,QACA,QACA,SACoC;AACpC,WAAO,KAAK,QAAQ,QAAQ,qBAAqB,EAAE,gBAAgB,QAAQ,OAAO,GAAG,SAAS,MAAM;AAAA,EACtG;AAAA,EAEA,MAAa,oBACX,QACA,gBACA,aACA,QACA,UACA,SACiC;AACjC,UAAM,SAAS,MAAM,KAAK;AAAA,MACxB;AAAA,MACA;AAAA,MACA,EAAE,gBAAgB,aAAa,QAAQ,SAAS;AAAA,MAChD,SAAS;AAAA,IACX;AACA,WAAO,wBAAwB,MAAM;AAAA,EACvC;AAAA,EAEA,MAAa,WACX,QACA,QACA,SACe;AACf,UAAM,KAAK,QAAQ,QAAQ,cAAc,EAAE,OAAO,GAAG,SAAS,MAAM;AAAA,EACtE;AAAA,EAEA,MAAa,oBACX,QACA,gBACA,aACA,OACA,SACe;AACf,UAAM,KAAK,QAAQ,QAAQ,uBAAuB;AAAA,MAChD;AAAA,MACA;AAAA,MACA,OAAO,sBAAsB,KAAK;AAAA,IACpC,GAAG,SAAS,MAAM;AAAA,EACpB;AAAA,EAEA,MAAc,QACZ,QACA,QACA,YACA,iBACkB;AAClB,UAAM,SAAS,mBAAmB,KAAK;AACvC,UAAM,QAAQ,MAAM,KAAK,gBAAgB,QAAQ,MAAM;AACvD,UAAM,SAAS,MAAM,KAAK,cAAc,WAAW,QAAQ,wBAAwB;AAAA,MACjF,gBAAgB;AAAA,MAChB;AAAA,IACF,CAAC;AACD,QAAI,UAAU;AACd,UAAM,QAAQ,OAAO,UAAgC;AACnD,UAAI,QAAS;AACb,gBAAU;AACV,YAAM,OAAO,MAAM,KAAK;AAAA,IAC1B;AACA,UAAM,UAA6B;AAAA,MACjC,MAAM;AAAA,MACN,IAAI,OAAO,WAAW;AAAA,MACtB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF;AACA,QAAI;AACF,YAAM,OAAO,KAAK,iBAAiB,CAAC,OAAO,GAAG,KAAK,OAAO,IAAI,CAAC;AAC/D,UAAI;AACJ,uBACQ,SAAS,sBAAsB,OAAO,QAAQ;AAAA,QAClD,iBAAiB,KAAK,OAAO;AAAA,QAC7B,eAAe;AAAA,QACf,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,MACF,CAAC,GACD;AACA,YAAI,aAAa,OAAW,OAAM,IAAI,MAAM,wBAAwB;AACpE,mBAAW;AAAA,MACb;AACA,UAAI,CAAC,qBAAqB,QAAQ,EAAG,OAAM,IAAI,MAAM,uBAAuB;AAC5E,UAAI,SAAS,OAAO,QAAQ,GAAI,OAAM,IAAI,MAAM,2BAA2B;AAC3E,UAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,SAAS,MAAM,IAAI;AACrD,aAAO,SAAS;AAAA,IAClB,SAAS,OAAO;AACd,YAAM,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,uBAAuB,CAAC;AAC/E,UAAI,QAAQ,QAAS,QAAO,eAAe;AAC3C,YAAM;AAAA,IACR,UAAE;AACA,YAAM,OAAO,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,IAC5C;AAAA,EACF;AACF;;;AC5JO,IAAM,0BAA0B;AAChC,IAAM,2BAA2B;AAwBxC,IAAM,oBAAoB;AAC1B,IAAM,wBAAwB;AAC9B,IAAM,yBAAyB;AAExB,SAAS,mBAAmB,OAA2C;AAC5E,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,SAAS;AACf,SACEC,aAAY,QAAQ,CAAC,QAAQ,MAAM,UAAU,UAAU,OAAO,CAAC,KAC/D,OAAO,SAAS,2BAChB,OAAO,OAAO,OAAO,YACrB,OAAO,GAAG,SAAS,KAAK,OAAO,GAAG,UAAU,qBAC5C,OAAO,OAAO,WAAW,YACzB,OAAO,OAAO,SAAS,KAAK,OAAO,OAAO,UAAU,yBACpD,YAAY,WACX,OAAO,UAAU,UAAa,wCAAwC,OAAO,KAAK;AAEvF;AAEO,SAAS,oBAAoB,OAA4C;AAC9E,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,SAAS;AACf,MACE,OAAO,SAAS,4BAA4B,OAAO,OAAO,OAAO,YACjE,OAAO,GAAG,WAAW,KAAK,OAAO,GAAG,SAAS,qBAC7C,OAAO,OAAO,OAAO,UACrB,QAAO;AACT,MAAI,OAAO,GAAI,QAAOA,aAAY,QAAQ,CAAC,QAAQ,MAAM,MAAM,QAAQ,CAAC;AACxE,MACE,CAACA,aAAY,QAAQ,CAAC,QAAQ,MAAM,MAAM,OAAO,CAAC,KAClD,OAAO,UAAU,QAAQ,OAAO,OAAO,UAAU,YAAY,MAAM,QAAQ,OAAO,KAAK,EACvF,QAAO;AACT,QAAM,QAAQ,OAAO;AACrB,SAAOA,aAAY,OAAO,CAAC,MAAM,CAAC,KAAK,OAAO,MAAM,SAAS,YAC3D,uBAAuB,KAAK,MAAM,IAAI;AAC1C;AAEA,SAASA,aAAY,QAAiC,SAAqC;AACzF,QAAM,cAAc,IAAI,IAAI,OAAO;AACnC,SAAO,OAAO,KAAK,MAAM,EAAE,MAAM,SAAO,YAAY,IAAI,GAAG,CAAC;AAC9D;;;AC5DA,IAAM,mBAAqC;AAEpC,IAAM,6BAAN,MAA6D;AAAA,EAIlE,YAA6B,UAA6C,CAAC,GAAG;AAAjD;AAC3B,SAAK,uBAAuB,QAAQ,wBAAwB;AAC5D,eAAW,UAAU,QAAQ,kBAAkB,CAAC,GAAG;AACjD,WAAK,eAAe,IAAI,OAAO,QAAQ,MAAM;AAAA,IAC/C;AAAA,EACF;AAAA,EARiB,iBAAiB,oBAAI,IAAiC;AAAA,EACtD;AAAA,EASV,iBAAiB,QAAmC;AACzD,SAAK,eAAe,IAAI,OAAO,QAAQ,MAAM;AAAA,EAC/C;AAAA,EAEO,oBAAoB,QAAsB;AAC/C,SAAK,eAAe,OAAO,MAAM;AAAA,EACnC;AAAA,EAEA,MAAa,gBAAgB,OAGR;AACnB,UAAM,SAAS,KAAK,QAAQ,mBAAmB,MAAM,YAAY,KAAK,KAAK,eAAe,IAAI,MAAM,YAAY;AAChH,QAAI,QAAQ,cAAc,OAAW,QAAO;AAC5C,QAAI,MAAM,aAAa,iBAAkB,QAAO,KAAK;AAKrD,WAAO,QAAQ,cAAc;AAAA,EAC/B;AACF;;;AChCO,IAAM,0BAAN,MAA0D;AAAA,EAG/D,YAA6B,kBAAoC;AAApC;AAC3B,SAAK,WAAW;AAAA,EAClB;AAAA,EAJQ;AAAA;AAAA,EAOD,YAAY,UAA4B,OAAwC;AACrF,WAAO,MAAM,kBAAkB,MAAM;AACnC,WAAK,WAAW;AAAA,IAClB,CAAC;AAAA,EACH;AAAA;AAAA,EAGO,cAAc,QAA2B;AAC9C,WAAO,eAAe;AACtB,SAAK,WAAW,KAAK;AACrB,WAAO,eAAe;AAAA,EACxB;AAAA,EAEO,gBAAgB,OAA6E;AAGlG,UAAM,WAAW,KAAK;AACtB,WAAO,SAAS,gBAAgB,KAAK;AAAA,EACvC;AACF;;;AClCO,IAAM,iCAAiC;AACvC,IAAM,+BAA+B,IAAI;AACzC,IAAM,0CAA0C;AACvD,IAAM,oBAAoB,KAAK;AAC/B,IAAM,gBAAgB;AACtB,IAAM,2BAA2B,OAAO,OAAO;AAAA,EAC7C,UAAU;AAAA,EACV,UAAU;AAAA,EACV,oBAAoB;AAAA,EACpB,gBAAgB,KAAK;AAAA,EACrB,UAAU;AACZ,CAAC;AAoCD,SAAS,YAAY,OAAe,MAAc,WAA2B;AAC3E,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,WAAW,QAAQ,SAAS,WAAW;AAC1C,UAAM,IAAI,MAAM,iCAAiC,IAAI,EAAE;AAAA,EACzD;AACA,SAAO;AACT;AAEA,SAAS,yBAAyB,SAAiB,QAAyB;AAC1E,MACE,QAAQ,WAAW,KAAK,QAAQ,SAAS,QAAS,YAAY,QAAQ,KAAK,KAC3E,CAAC,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,IAAI,KAC1EC,6BAA4B,OAAO,EACnC,QAAO;AACT,QAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,QAAM,cAAwB,CAAC;AAC/B,QAAM,iBAA2B,CAAC;AAClC,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,QAAI,CAAC,MAAM,KAAK,EAAG,QAAO;AAC1B,QAAI,MAAM,KAAK,MAAM,cAAe,gBAAe,KAAK,KAAK;AAC7D,QAAI,MAAM,KAAK,MAAM,MAAO;AAC5B,UAAMC,UAAS,MAAM,QAAQ,CAAC;AAC9B,QAAI,CAACA,QAAQ,QAAO;AACpB,gBAAY,KAAK,KAAK;AACtB,aAAS;AAAA,EACX;AACA,QAAM,mBAAmB,YAAY,GAAG,EAAE;AAC1C,MAAI,qBAAqB,MAAM,SAAS,KAAK,MAAM,mBAAmB,CAAC,MAAM,QAAQ;AACnF,WAAO;AAAA,EACT;AACA,MAAI,eAAe,WAAW,EAAG,QAAO,YAAY,WAAW;AAC/D,MAAI,eAAe,WAAW,KAAK,YAAY,WAAW,EAAG,QAAO;AACpE,SAAO,YAAY,CAAC,IAAI,eAAe,CAAC,KAAK,eAAe,CAAC,IAAI;AACnE;AAEA,SAASD,6BAA4B,OAAwB;AAC3D,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,MAAM,SAAS,IAAK,QAAO;AAAA,EACzC;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,WAA8B,QAA0B;AACjF,QAAM,SAAS,CAAC,GAAG,IAAI,IAAI,UAAU,IAAI,CAAC,YAAY,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,OAAO;AACtF,MACE,OAAO,WAAW,KAClB,OAAO,SAAS,iBAChB,OAAO,KAAK,aAAW,CAAC,yBAAyB,SAAS,MAAM,CAAC,GACjE;AACA,UAAM,IAAI,MAAM,2EAA2E;AAAA,EAC7F;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,WAAmB,WAAmB,KAAmB;AACjF,MACE,CAAC,OAAO,cAAc,GAAG,KAAK,MAAM,KACpC,CAAC,OAAO,cAAc,SAAS,KAC/B,CAAC,OAAO,cAAc,SAAS,KAC/B,YAAY,KACZ,aAAa,aACb,YAAY,YAAY,8BACxB;AACA,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,MAAI,YAAY,MAAM,yCAAyC;AAC7D,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AACA,MAAI,aAAa,IAAK,OAAM,IAAI,MAAM,mCAAmC;AAC3E;AAEA,SAAS,gBAAgB,QAAgF;AACvG,QAAM,SAAS,YAAY,OAAO,QAAQ,UAAU,GAAG;AACvD,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA,oBAAoB,YAAY,OAAO,oBAAoB,sBAAsB,IAAI;AAAA,IACrF,YAAY,YAAY,OAAO,YAAY,cAAc,GAAG;AAAA,IAC5D,YAAY,CAAC,GAAG,kBAAkB,OAAO,YAAY,MAAM,CAAC,EAAE,KAAK;AAAA,IACnE,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,EACpB;AACF;AAEO,SAAS,kCACd,QACY;AACZ,QAAM,UAAU,gBAAgB,MAAM;AACtC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,0BACpB,QAGA,SAC8B;AAC9B,QAAM,YAAY,QAAQ,OAAO,KAAK,IAAI;AAC1C,QAAM,QAAQ,QAAQ,SAAS;AAC/B,MAAI,CAAC,OAAO,cAAc,SAAS,KAAK,CAAC,OAAO,cAAc,KAAK,KAAK,SAAS,GAAG;AAClF,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,QAAM,UAAU,gBAAgB;AAAA,IAC9B,UAAU;AAAA,IACV,QAAQ,OAAO;AAAA,IACf,oBAAoB,OAAO;AAAA,IAC3B,YAAY,OAAO;AAAA,IACnB,YAAY,OAAO,cAAc,CAAC;AAAA,IAClC;AAAA,IACA,WAAW,YAAY;AAAA,EACzB,CAAC;AACD,mBAAiB,QAAQ,WAAW,QAAQ,WAAW,SAAS;AAChE,QAAM,YAAY;AAAA,IAChB,MAAM,QAAQ,KAAK,kCAAkC,OAAO,CAAC;AAAA,IAC7D;AAAA,IACA;AAAA,EACF;AACA,SAAO,EAAE,GAAG,SAAS,UAAU;AACjC;AAEO,SAAS,0BAA0B,QAAqC;AAC7E,QAAM,UAAU,gBAAgB,MAAM;AACtC,QAAM,YAAY,YAAY,OAAO,WAAW,aAAa,IAAI;AACjE,SAAO,oBAAoB,EAAE,GAAG,SAAS,UAAU,GAAG,wBAAwB;AAChF;AAEA,eAAsB,yBACpB,YACA,SAC8B;AAC9B,MAAI,CAAC,cAAc,WAAW,SAAS,mBAAmB;AACxD,UAAM,IAAI,MAAM,sCAAsC;AAAA,EACxD;AACA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,UAAU;AAAA,EAChC,QAAQ;AACN,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AACA,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAClE,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AACA,QAAM,SAAS;AACf,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MACE,OAAO,KAAK,MAAM,EAAE,WAAW,aAAa,UAC5C,aAAa,KAAK,SAAO,CAAC,OAAO,OAAO,QAAQ,GAAG,CAAC,KACpD,OAAO,aAAa,kCACpB,OAAO,OAAO,WAAW,YACzB,OAAO,OAAO,uBAAuB,YACrC,OAAO,OAAO,eAAe,YAC7B,CAAC,MAAM,QAAQ,OAAO,UAAU,KAChC,OAAO,WAAW,KAAK,CAAC,YAAY,OAAO,YAAY,QAAQ,KAC/D,OAAO,OAAO,cAAc,YAC5B,OAAO,OAAO,cAAc,YAC5B,OAAO,OAAO,cAAc,UAC5B;AACA,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AACA,mBAAiB,OAAO,WAAW,OAAO,WAAW,QAAQ,OAAO,KAAK,IAAI,CAAC;AAC9E,QAAM,UAAU,gBAAgB;AAAA,IAC9B,UAAU;AAAA,IACV,QAAQ,OAAO;AAAA,IACf,oBAAoB,OAAO;AAAA,IAC3B,YAAY,OAAO;AAAA,IACnB,YAAY,OAAO;AAAA,IACnB,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,EACpB,CAAC;AACD,QAAM,SAA8B;AAAA,IAClC,GAAG;AAAA,IACH,WAAW,YAAY,OAAO,WAAW,aAAa,IAAI;AAAA,EAC5D;AACA,MACE,CAAC,MAAM,QAAQ,eAAe;AAAA,IAC5B;AAAA,IACA,SAAS,kCAAkC,OAAO;AAAA,EACpD,CAAC,GACD;AACA,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AACA,SAAO;AACT;;;ACpPA,IAAM,oCAAoC,IAAI;AA8B9C,eAAsB,8BAA8B,OAQH;AAC/C,QAAM,MAAM,MAAM,MAAM,KAAK,KAAK,IAAI;AACtC,QAAM,cAAc,MAAM,eAAe;AACzC,MAAI,CAAC,OAAO,SAAS,WAAW,KAAK,cAAc,GAAG;AACpD,UAAM,IAAI,UAAU,6CAA6C;AAAA,EACnE;AACA,QAAM,kBAAkB,MAAM,MAAM,WAAW,mBAAmB;AAClE,QAAM,qBAAqB,MAAM,MAAM,cAAc,8BAA8B;AACnF,QAAM,mBAAmB,IAAI,IAAI,gBAAgB,IAAI,YAAU,CAAC,OAAO,QAAQ,MAAM,CAAC,CAAC;AACvF,QAAM,kBAAkB,IAAI,IAAI,MAAM,kBAAkB,CAAC,CAAC;AAC1D,QAAM,kBAAkB,oBAAI,IAA+B;AAC3D,aAAW,UAAU,MAAM,cAAc;AACvC,QAAI,gBAAgB,IAAI,OAAO,MAAM,EAAG,OAAM,IAAI,MAAM,gCAAgC;AACxF,oBAAgB,IAAI,OAAO,QAAQ,MAAM;AAAA,EAC3C;AACA,QAAM,qBAAqB,CAAC,GAAG,gBAAgB,OAAO,CAAC,EAAE;AAAA,IACvD,YAAU,OAAO,cAAc,UAAa,CAAC,gBAAgB,IAAI,OAAO,MAAM;AAAA,EAChF;AACA,QAAM,gBAAgB,IAAI,IAAI,mBAAmB,IAAI,YAAU,OAAO,MAAM,CAAC;AAC7E,QAAM,iBAA2B,CAAC;AAElC,QAAM,uBAAuB,oBAAI,IAAI;AAAA,IACnC,GAAG,gBACA,OAAO,YAAU,OAAO,cAAc,eAAe,EACrD,IAAI,YAAU,OAAO,MAAM;AAAA,IAC9B,GAAG;AAAA,EACL,CAAC;AACD,aAAW,UAAU,sBAAsB;AACzC,QAAI,cAAc,IAAI,MAAM,EAAG;AAC/B,UAAM,WAAW,iBAAiB,IAAI,MAAM;AAC5C,QAAI,UAAU,cAAc,iBAAiB;AAC3C,YAAM,MAAM,WAAW,oBAAoB,MAAM;AACjD,YAAM,MAAM,cAAc,2BAA2B,MAAM;AAAA,IAC7D;AACA,UAAM,MAAM,cAAc,2BAA2B,MAAM;AAC3D,UAAM,MAAM,cAAc,8BAA8B,MAAM;AAC9D,mBAAe,KAAK,MAAM;AAAA,EAC5B;AAEA,QAAM,UAAoB,CAAC;AAC3B,aAAW,eAAe,oBAAoB;AAC5C,UAAM,WAAW,iBAAiB,IAAI,YAAY,MAAM;AACxD,UAAM,YAAY,UAAU,cAAc,kBACtC,kBACA;AACJ,QAAI,gBAAgB;AACpB,QAAI,cAAc,iBAAiB;AACjC,sBAAgB;AAAA,QACd,QAAQ,YAAY;AAAA,QACpB,oBAAoB,YAAY;AAAA,QAChC,YAAY,YAAY;AAAA,QACxB,UAAU,YAAY;AAAA,QACtB;AAAA,QACA,WAAW,YAAY;AAAA,QACvB,WAAW,UAAU,aAAa;AAAA,QAClC,UAAU,YAAY;AAAA,QACtB,WAAW,YAAY;AAAA,MACzB;AACA,UACE,UAAU,cAAc,mBACxB,SAAS,uBAAuB,YAAY,oBAC5C;AACA,cAAM,QAAQ;AAAA,UACZ;AAAA,UACA,EAAE,QAAQ,SAAS,QAAQ,WAAW,SAAS,UAAU;AAAA,QAC3D;AAAA,MACF;AACA,UAAI,CAAC,YAAY,CAAC,kBAAkB,UAAU,aAAa,GAAG;AAC5D,cAAM,MAAM,WAAW,kBAAkB,aAAa;AAAA,MACxD;AACA,YAAM,MAAM,cAAc,2BAA2B,aAAa;AAAA,IACpE;AAEA,UAAM,SAAS,oBAAoB,aAAa,WAAW,KAAK,WAAW;AAC3E,UAAM,MAAM,cAAc;AAAA,MACxB,OAAO;AAAA,MACP,OAAO,cAAc,CAAC;AAAA,IACxB;AACA,UAAM,MAAM,cAAc,8BAA8B,MAAM;AAC9D,YAAQ,KAAK,MAAM;AAAA,EACrB;AAEA,SAAO,EAAE,cAAc,oBAAoB,SAAS,eAAe;AACrE;AAEO,SAAS,oBACd,aACA,WACA,MAAM,KAAK,IAAI,GACf,cAAc,mCACN;AACR,QAAM,mBAAmB,oBAAoB,YAAY,UAAU,EAChE,OAAO,aAAW,CAAC,QAAQ,SAAS,cAAc,CAAC;AACtD,QAAM,kBAAkB,oBAAoB;AAAA,IAC1C,GAAG,YAAY,WAAW,OAAO,aAAW,QAAQ,SAAS,cAAc,CAAC;AAAA,IAC5E,GAAG,YAAY;AAAA,EACjB,CAAC;AACD,QAAM,QAAyC;AAAA,IAC7C,GAAI,iBAAiB,SAAS,IAAI,CAAC,QAAiB,IAAI,CAAC;AAAA,IACzD,GAAI,gBAAgB,SAAS,IAAI,CAAC,OAAgB,IAAI,CAAC;AAAA,EACzD;AACA,QAAM,QAAQ,OAAO,SAAS,YAAY,QAAQ,KAChD,YAAY,YAAY,MAAM;AAChC,SAAO;AAAA,IACL,QAAQ,YAAY;AAAA,IACpB,aAAa,YAAY;AAAA,IACzB,UAAU,YAAY;AAAA,IACtB;AAAA,IACA,SAAS;AAAA,IACT,cAAc;AAAA,MACZ,OAAO,SAAS,MAAM,SAAS,IAAI,WAAW;AAAA,MAC9C,OAAO,QAAQ,QAAQ,CAAC;AAAA,IAC1B;AAAA,IACA,cAAc,YAAY;AAAA,IAC1B,YAAY,oBAAoB,CAAC,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAAA,IACzE,UAAU,YAAY;AAAA,EACxB;AACF;AAEA,SAAS,oBAAoB,WAAwC;AACnE,SAAO,CAAC,GAAG,IAAI,IAAI,UAAU,IAAI,aAAW,QAAQ,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,CAAC;AAC9E;AAEA,SAAS,kBAAkB,MAA2B,OAAqC;AACzF,SAAO,KAAK,WAAW,MAAM,UAC3B,KAAK,uBAAuB,MAAM,sBAClC,KAAK,eAAe,MAAM,cAC1B,KAAK,aAAa,MAAM,YACxB,KAAK,cAAc,MAAM,aACzB,KAAK,cAAc,MAAM,aACzB,KAAK,cAAc,MAAM,aACzB,KAAK,aAAa,MAAM,YACxB,KAAK,cAAc,MAAM;AAC7B;;;AC9JA,IAAM,uCAAuC,IAAI;AACjD,IAAM,mCAAmC,oBAAI,IAAI;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAID,IAAM,sCAAN,cAAkD,MAAM;AAAA,EACtC,OAAO;AAAA,EAEvB,YAAY,OAAiB;AAC3B;AAAA,MACE;AAAA,MACA,UAAU,SAAY,SAAY,EAAE,MAAM;AAAA,IAC5C;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAuEO,IAAM,uCAAN,MAAsG;AAAA,EAO3G,YAA6B,SAAsD;AAAtD;AAC3B,SAAK,MAAM,QAAQ,OAAO,KAAK;AAC/B,SAAK,2BAA2B,QAAQ,4BACtC;AACF,QAAI,CAAC,OAAO,SAAS,KAAK,wBAAwB,KAAK,KAAK,2BAA2B,GAAG;AACxF,YAAM,IAAI,UAAU,0DAA0D;AAAA,IAChF;AAAA,EACF;AAAA,EAbQ;AAAA,EACA;AAAA,EACA,wBAAkC,CAAC;AAAA,EAC1B;AAAA,EACA;AAAA,EAWV,aACL,eACoC;AACpC,WAAO,kBAAkB;AAAA,EAC3B;AAAA,EAEO,uBAAuB,gBAA4C;AACxE,UAAM,YAAY,KAAK,QAAQ,QAAQ,cAAc;AACrD,WAAO,KAAK,QAAQ,yBAAyB,SAAS,KACpD,CAAC,iCAAiC,WAAW,KAAK,QAAQ,SAAS,MAAM;AAAA,EAC7E;AAAA,EAEA,MAAa,iBACX,QACA,QACA,QACgC;AAChC,UAAM,YAAY,MAAM,OAAO,4BAA4B,MAAM;AACjE,WAAO;AAAA,MACL,QAAQ,OAAO,UAAU;AACvB,cAAM,aAAa;AACnB,cAAM,KAAK,QAAQ,kCAAkC,WAAW,QAAQ,KAAK;AAC7E,cAAM,aAAa;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAa,eACX,QACA,QACA,QACoB;AACpB,UAAM,QAAQ,MAAM,OAAO,mBAAmB,MAAM;AACpD,IAAAE,gBAAe,MAAM;AACrB,UAAM,YAAY,MAAM,KAAK,QAAQ,kBAAkB;AAAA,MACrD,WAAW,MAAM;AAAA,MACjB,UAAU,KAAK,QAAQ;AAAA,MACvB,OAAO,MAAM;AAAA,MACb;AAAA,IACF,CAAC;AACD,IAAAA,gBAAe,MAAM;AACrB,UAAM,eAAe,MAAM,KAAK,QAAQ,aAAa;AACrD,IAAAA,gBAAe,MAAM;AACrB,UAAM,eAAe,MAAM,OAAO,eAAe;AAAA;AAAA;AAAA;AAAA,MAI/C,UAAU,uBAAuB,KAAK,QAAQ,QAAQ;AAAA,MACtD,YAAY,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,MACA,YAAY,CAAC,GAAG,KAAK,QAAQ,QAAQ,cAAc,CAAC;AAAA,MACpD,mBAAmB,KAAK,yBAAyB;AAAA,IACnD,GAAG,MAAM;AACT,QAAI,CAAC,aAAa,MAAM,aAAa,WAAW,KAAK,QAAQ,SAAS,QAAQ;AAC5E,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,YACX,QACA,QACA,OAC4C;AAC5C,QACE,KAAK,2BAA2B,UAChC,KAAK,oBACL,KAAK,iBAAiB,YAAY,KAAK,IAAI,IAAI,KAAK,0BACpD;AACA,aAAO;AAAA,IACT;AACA,UAAM,mBAAmB,MAAM,OAAO;AAAA,MACpC,EAAE,QAAQ,KAAK,QAAQ,SAAS,OAAO;AAAA,MACvC;AAAA,MACA;AAAA,IACF;AACA,WAAO;AAAA,MACL,QAAQ,OAAOC,WAAU;AACvB,QAAAA,OAAM,aAAa;AACnB,cAAM,KAAK,QAAQ,QAAQ,0BAA0B,kBAAkB,QAAQA,MAAK;AACpF,QAAAA,OAAM,aAAa;AACnB,QAAAA,OAAM,kBAAkB,MAAM;AAC5B,eAAK,mBAAmB;AACxB,eAAK,yBAAyB;AAAA,QAChC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAa,UACX,QACA,QACA,QACoB;AACpB,IAAAD,gBAAe,MAAM;AACrB,UAAM,eAAe,MAAM,KAAK,QAAQ,aAAa;AACrD,IAAAA,gBAAe,MAAM;AACrB,UAAM,WAAW;AAAA,MACf,QAAQ,KAAK,QAAQ,SAAS;AAAA,MAC9B,WAAW,KAAK,IAAI;AAAA,MACpB;AAAA,MACA,YAAY,CAAC,GAAG,KAAK,QAAQ,QAAQ,cAAc,CAAC;AAAA,MACpD,mBAAmB,KAAK,yBAAyB;AAAA,IACnD;AACA,UAAM,QAAQ,MAAM,KAAK,QAAQ,cAAc,EAAE,GAAG,UAAU,OAAO,CAAC;AACtE,IAAAA,gBAAe,MAAM;AACrB,UAAM,YAAY,EAAE,GAAG,UAAU,GAAG,MAAM;AAC1C,SAAK,4BAA4B,EAAE,GAAG,UAAU,OAAO,MAAM,MAAM,CAAC;AACpE,QAAI,CAAC,sBAAsB,UAAU,SAAS,GAAG;AAC/C,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AACA,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,OAAO,UAAU,WAAW,MAAM;AAAA,IACnD,SAAS,OAAO;AACd,UAAI,+BAA+B,KAAK,GAAG;AACzC,cAAM,IAAI,oCAAoC,KAAK;AAAA,MACrD;AACA,YAAM;AAAA,IACR;AACA,QAAI,CAAC,OAAO,GAAI,OAAM,IAAI,oCAAoC;AAC9D,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,QAAQ,QAA2B,QAAoC;AAClF,SAAK,mBAAmB;AACxB,SAAK,yBAAyB;AAC9B,SAAK,wBAAwB,CAAC;AAC9B,UAAM,SAAoB,CAAC;AAC3B,UAAM;AAAA,MACJ,MAAM,KAAK,QAAQ,8BAA8B,MAAM;AAAA,MACvD;AAAA,IACF;AACA,UAAM;AAAA,MACJ,MAAM,KAAK,QAAQ,QAAQ,sBAAsB,MAAM;AAAA,MACvD;AAAA,IACF;AACA,UAAM;AAAA,MACJ,YAAY;AACV,cAAM,8BAA8B;AAAA,UAClC,cAAc,CAAC;AAAA,UACf,eAAe,KAAK,QAAQ;AAAA,UAC5B,QAAQ,KAAK,QAAQ;AAAA,UACrB,KAAK,KAAK;AAAA,UACV,YAAY,KAAK,QAAQ;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,MACA;AAAA,IACF;AACA,UAAM;AAAA,MACJ,MAAM,KAAK,QAAQ,gBAAgB,QAAQ,MAAM;AAAA,MACjD;AAAA,IACF;AACA,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,IAAI,eAAe,QAAQ,wCAAwC;AAAA,IAC3E;AAAA,EACF;AAAA,EAEA,MAAa,cACX,QACA,QACA,QACgC;AAChC,UAAM,eAAe,MAAM,OAAO,YAAY,MAAM;AACpD,WAAO;AAAA,MACL,QAAQ,OAAO,UAAU;AACvB,cAAM,aAAa;AACnB,cAAM,KAAK,QAAQ,6BAA6B;AAAA,UAC9C;AAAA,UACA,gBAAgB,CAAC,KAAK,QAAQ,SAAS,MAAM;AAAA,UAC7C,aAAa,KAAK,QAAQ;AAAA,UAC1B,KAAK,KAAK,IAAI;AAAA,QAChB,GAAG,KAAK;AACR,cAAM,aAAa;AACnB,cAAM,kBAAkB,MAAM;AAC5B,eAAK,wBAAwB,aAC1B,OAAO,YAAU,OAAO,WAAW,KAAK,QAAQ,SAAS,UAAU,OAAO,cAAc,MAAS,EACjG,IAAI,YAAU,OAAO,MAAM;AAAA,QAChC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEO,0BACL,SACA,QACmB;AACnB,WAAO,eAAe;AACtB,WAAO,KAAK,QAAQ,aAAa,CAAC,GAAG,KAAK,qBAAqB,IAAI,CAAC;AAAA,EACtE;AAAA,EAEO,WACL,QACA,QACA,QACqB;AACrB,WAAO,eAAe;AACtB,QAAI,CAAC,KAAK,QAAQ,WAAY,OAAM,IAAI,MAAM,uCAAuC;AACrF,WAAO,KAAK,QAAQ,WAAW,QAAQ,QAAQ,MAAM;AAAA,EACvD;AAAA,EAEO,cAAc,OAA8D;AACjF,QAAI,iBAAiB,oCAAqC,QAAO;AACjE,QAAI,iBAAiB,uBAAuB;AAC1C,aAAO,MAAM,SAAS,yBAAyB,YAAY;AAAA,IAC7D;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,2BAAqC;AAC3C,UAAM,SAAS,KAAK,QAAQ,QAAQ,cAAc,EAC/C,OAAO,aAAW,QAAQ,SAAS,cAAc,CAAC;AACrD,WAAO,OAAO,SAAS,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,GAAI,KAAK,kBAAkB,mBAAmB,CAAC,CAAE;AAAA,EAC7F;AACF;AAEA,SAAS,+BAA+B,OAAyB;AAC/D,MAAI,EAAE,iBAAiB,0BAA0B,MAAM,SAAS,oBAAoB;AAClF,WAAO;AAAA,EACT;AACA,MAAI,MAAM,WAAW,IAAK,QAAO;AACjC,SAAO,MAAM,WAAW,OAAO,mCAAmC,MAAM,YAAY;AACtF;AAEA,SAAS,mCAAmC,cAA2C;AACrF,QAAM,OAAO,cAAc,KAAK;AAChC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACJ,MAAI;AACF,YAAQ,KAAK,MAAM,IAAI;AAAA,EACzB,QAAQ;AACN,WAAO,iCAAiC,IAAI,mBAAmB,IAAI,CAAC;AAAA,EACtE;AACA,SAAO,iCAAiC,KAAK;AAC/C;AAEA,SAAS,iCAAiC,OAAyB;AACjE,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,iCAAiC,IAAI,mBAAmB,KAAK,CAAC;AAAA,EACvE;AACA,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,SAAS;AACf,SAAO,iCAAiC,OAAO,IAAI,KACjD,iCAAiC,OAAO,SAAS,KACjD,iCAAiC,OAAO,KAAK;AACjD;AAEA,SAAS,mBAAmB,OAAuB;AACjD,SAAO,MAAM,KAAK,EAAE,YAAY,EAAE,WAAW,KAAK,GAAG;AACvD;AAEA,SAAS,uBAAuB,UAAqD;AACnF,SAAO;AAAA,IACL,QAAQ,SAAS;AAAA,IACjB,oBAAoB,SAAS;AAAA,IAC7B,WAAW,SAAS;AAAA,IACpB,YAAY,SAAS;AAAA,IACrB,UAAU,SAAS;AAAA,EACrB;AACF;AAWO,SAAS,iCACd,WACA,gBACS;AACT,SAAO,UAAU,KAAK,aAAW,0BAA0B,SAAS,cAAc,CAAC;AACrF;AAEA,SAAS,0BAA0B,SAAiB,gBAAkC;AACpF,MACE,QAAQ,WAAW,KAAK,QAAQ,SAAS,QAAS,YAAY,QAAQ,KAAK,KAC3E,CAAC,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,IAAI,KAC1E,QAAQ,SAAS,cAAc,EAC/B,QAAO;AACT,QAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE,MAAM,CAAC;AACxC,MAAI,MAAM,KAAK,UAAQ,KAAK,WAAW,KAAKE,6BAA4B,IAAI,CAAC,EAAG,QAAO;AAEvF,QAAM,eAAe,MAAM,CAAC;AAC5B,QAAM,OAAO,MAAM,CAAC,GAAG,YAAY;AACnC,MACE,SAAS,UACR,iBAAiB,SAAS,iBAAiB,SAAS,iBAAiB,SACpE,iBAAiB,UAAU,iBAAiB,OAC9C,QAAO;AACT,QAAM,aAAa,iBAAiB,QAChC,aAAa,IAAI,IACjB,iBAAiB,QACjB,aAAa,IAAI,IACjB,yBAAyB,IAAI;AACjC,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,YAAY,MAAM,CAAC;AACzB,QAAM,OAAO,UAAU,MAAM,CAAC,CAAC;AAC/B,MAAI,cAAc,SAAS,SAAS,OAAW,QAAO;AACtD,MAAI,QAAQ;AACZ,MAAI,MAAM,KAAK,MAAM,QAAQ,MAAM,KAAK,MAAM,MAAO,UAAS;AAE9D,MAAI,MAAM,KAAK,MAAM,OAAO;AAC1B,UAAM,SAAS,MAAM,QAAQ,CAAC;AAC9B,QAAI,CAAC,UAAUA,6BAA4B,MAAM,EAAG,QAAO;AAC3D,QAAI,mBAAmB,UAAa,WAAW,eAAgB,QAAO;AACtE,aAAS;AAAA,EACX;AACA,SAAO,UAAU,MAAM;AACzB;AAEA,SAAS,UAAU,OAA+C;AAChE,MAAI,UAAU,UAAa,CAAC,aAAa,KAAK,KAAK,EAAG,QAAO;AAC7D,QAAM,OAAO,OAAO,KAAK;AACzB,SAAO,QAAQ,KAAK,QAAQ,QAAS,OAAO;AAC9C;AAEA,SAASA,6BAA4B,OAAwB;AAC3D,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,MAAM,SAAS,IAAK,QAAO;AAAA,EACzC;AACA,SAAO;AACT;AAEA,SAAS,aAAa,MAAuB;AAC3C,QAAM,SAAS,KAAK,MAAM,GAAG,EAAE,IAAI,UAAQ,OAAO,IAAI,CAAC;AACvD,MAAI,OAAO,WAAW,KAAK,OAAO,KAAK,WAAS,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,GAAG,GAAG;AACrG,WAAO;AAAA,EACT;AACA,QAAM,CAAC,OAAO,MAAM,IAAI;AACxB,SAAO,UAAU,KAAK,UAAU,MAAM,UAAU,OAAO,QAAQ,OAC7D,EAAE,UAAU,OAAO,UAAU,MAAM,UAAU,QAC7C,EAAE,UAAU,OAAO,WAAW,QAC9B,EAAE,UAAU,OAAO,UAAU,MAAM,UAAU,OAC7C,EAAE,UAAU,OAAO,WAAW,KAAK,OAAO,CAAC,MAAM,MACjD,EAAE,UAAU,OAAO,WAAW,KAAK,OAAO,CAAC,MAAM,MACjD,EAAE,UAAU,OAAO,WAAW,MAAM,OAAO,CAAC,MAAM,OAClD,EAAE,UAAU,OAAO,WAAW,QAC9B,EAAE,UAAU,QAAQ,WAAW,MAAM,WAAW,QAChD,EAAE,UAAU,OAAO,WAAW,MAAM,OAAO,CAAC,MAAM,QAClD,EAAE,UAAU,OAAO,WAAW,KAAK,OAAO,CAAC,MAAM;AACrD;AAEA,SAAS,aAAa,MAAuB;AAC3C,QAAM,SAAS,UAAU,IAAI;AAC7B,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,CAAC,OAAO,MAAM,IAAI;AACxB,OAAK,QAAQ,WAAY,KAAQ,QAAO;AAExC,SAAO,EAAE,UAAU,QAAU,WAAW;AAC1C;AAEA,SAAS,UAAU,MAAoC;AACrD,QAAM,aAAa,KAAK,YAAY;AACpC,MAAI,WAAW,SAAS,GAAG,KAAK,WAAW,SAAS,GAAG,EAAG,QAAO;AACjE,QAAM,SAAS,WAAW,MAAM,IAAI;AACpC,MAAI,OAAO,SAAS,EAAG,QAAO;AAC9B,QAAM,YAAY,CAAC,SAAuC;AACxD,QAAI,SAAS,GAAI,QAAO,CAAC;AACzB,UAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,QAAI,MAAM,KAAK,UAAQ,CAAC,mBAAmB,KAAK,IAAI,CAAC,EAAG,QAAO;AAC/D,WAAO,MAAM,IAAI,UAAQ,OAAO,SAAS,MAAM,EAAE,CAAC;AAAA,EACpD;AACA,QAAM,OAAO,UAAU,OAAO,CAAC,KAAK,EAAE;AACtC,QAAM,QAAQ,UAAU,OAAO,CAAC,KAAK,EAAE;AACvC,MAAI,CAAC,QAAQ,CAAC,MAAO,QAAO;AAC5B,MAAI,OAAO,WAAW,EAAG,QAAO,KAAK,WAAW,IAAI,OAAO;AAC3D,QAAM,UAAU,IAAI,KAAK,SAAS,MAAM;AACxC,MAAI,UAAU,EAAG,QAAO;AACxB,SAAO,CAAC,GAAG,MAAM,GAAG,MAAM,KAAK,EAAE,QAAQ,QAAQ,GAAG,MAAM,CAAC,GAAG,GAAG,KAAK;AACxE;AAEA,SAAS,yBAAyB,MAAuB;AACvD,QAAM,aAAa,KAAK,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI;AAC5D,MAAI,aAAa,UAAU,EAAG,QAAO,aAAa,UAAU;AAC5D,MAAI,WAAW,SAAS,GAAG,EAAG,QAAO,aAAa,UAAU;AAC5D,QAAM,qBAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,mBAAmB,KAAK,YAAU,eAAe,UAAU,WAAW,SAAS,IAAI,MAAM,EAAE,CAAC,EAAG,QAAO;AAC1G,QAAM,SAAS,WAAW,MAAM,GAAG;AACnC,SAAO,OAAO,SAAS,KAAK,OAAO;AAAA,IAAM,WACvC,MAAM,SAAS,KAAK,MAAM,UAAU,MACpC,qCAAqC,KAAK,KAAK;AAAA,EACjD;AACF;AAEA,SAAS,aAAa,MAAuB;AAC3C,SAAO,6BAA6B,KAAK,IAAI;AAC/C;AAEA,SAAS,sBAAsB,WAAyC;AACtE,MACE,OAAO,cAAc,YAAY,UAAU,WAAW,KACtD,UAAU,SAAS,wBAAwB,uBAC3C,cAAc,UAAU,KAAK,GAC7B;AACA,WAAO;AAAA,EACT;AACA,WAAS,QAAQ,GAAG,QAAQ,UAAU,QAAQ,SAAS,GAAG;AACxD,UAAM,OAAO,UAAU,WAAW,KAAK;AACvC,QAAI,QAAQ,MAAM,SAAS,IAAK,QAAO;AAAA,EACzC;AACA,SAAO;AACT;AAEA,eAAe,kBACb,WACA,QACe;AACf,MAAI;AACF,UAAM,UAAU;AAAA,EAClB,SAAS,OAAO;AACd,WAAO,KAAK,KAAK;AAAA,EACnB;AACF;AAEA,SAASF,gBAAe,QAA2B;AACjD,MAAI,CAAC,OAAO,QAAS;AACrB,QAAM,OAAO,kBAAkB,QAAQ,OAAO,SAAS,IAAI,MAAM,gCAAgC;AACnG;;;ACzUO,IAAM,gCAAN,cAA4C,MAAM;AAAA,EACvC;AAAA,EAEhB,YAAY,MAAoC;AAC9C,UAAM,IAAI;AACV,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;;;ACvOO,SAAS,wBACd,QAC+E;AAC/E,MAAI,UAAU,QAAQ,OAAO,WAAW,SAAU,QAAO;AACzD,QAAM,IAAI;AAQV,MAAI,EAAE,SAAS,CAAC,EAAE,SAAS,OAAO,EAAE,eAAe,SAAU,QAAO;AACpE,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,KAAK,EAAE,UAAU;AAChC,QAAI,CAAC,OAAO,OAAQ,QAAO;AAC3B,WAAO,WAAW,KAAK,QAAQ,CAAC,cAAc,UAAU,WAAW,CAAC,CAAC;AAAA,EACvE,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL;AAAA,IACA,UAAU,OAAO,EAAE,aAAa,WAAW,EAAE,WAAW;AAAA,IACxD,UAAU,OAAO,EAAE,aAAa,WAAW,EAAE,WAAW;AAAA,IACxD,MAAM,OAAO,EAAE,SAAS,YAAY,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AAAA,EACjE;AACF;;;ACpBO,SAAS,iBAAiB,gBAAwB,cAA8B;AACrF,SAAO,KAAK,UAAU,CAAC,gBAAgB,YAAY,CAAC;AACtD;AAEO,SAAS,sBACd,KAC8D;AAC9D,MAAI;AACF,UAAM,QAAiB,KAAK,MAAM,GAAG;AACrC,QACE,CAAC,MAAM,QAAQ,KAAK,KACpB,MAAM,WAAW,KACjB,OAAO,MAAM,CAAC,MAAM,YACpB,MAAM,CAAC,EAAE,WAAW,KACpB,OAAO,MAAM,CAAC,MAAM,YACpB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAO;AACT,WAAO,EAAE,gBAAgB,MAAM,CAAC,GAAG,cAAc,MAAM,CAAC,EAAE;AAAA,EAC5D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAqBO,SAAS,mBAAmB,OAA2C;AAC5E,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,QAAM,IAAI;AACV,SACE,OAAO,EAAE,mBAAmB,YAC5B,OAAO,EAAE,UAAU,YACnB,OAAO,EAAE,iBAAiB,YAC1B,OAAO,EAAE,gBAAgB,YACzB,OAAO,EAAE,iBAAiB,YAC1B,OAAO,EAAE,iBAAiB,YAC1B,OAAO,EAAE,yBAAyB,YAClC,OAAO,EAAE,oBAAoB;AAEjC;AASO,SAAS,4BACd,gBACA,kBACgB;AAChB,QAAM,SAAyB,CAAC;AAChC,aAAW,CAAC,KAAK,cAAc,KAAK,OAAO,QAAQ,gBAAgB,GAAG;AACpE,UAAM,WAAW,sBAAsB,GAAG;AAC1C,QAAI,CAAC,SAAU;AACf,UAAM,eAAe,eAAe,GAAG,KAAK;AAC5C,QAAI,iBAAiB,cAAc;AACjC,aAAO,KAAK,EAAE,GAAG,UAAU,eAAe,cAAc,aAAa,eAAe,CAAC;AAAA,IACvF;AAAA,EACF;AACA,SAAO,OAAO;AAAA,IAAK,CAAC,MAAM,UACxB,iBAAiB,KAAK,gBAAgB,MAAM,cAAc,KAC1D,iBAAiB,KAAK,cAAc,MAAM,YAAY;AAAA,EACxD;AACF;AAEO,SAAS,yBACd,QACA,OACS;AACT,QAAM,MAAM,iBAAiB,MAAM,gBAAgB,MAAM,YAAY;AACrE,UAAQ,OAAO,GAAG,KAAK,MAAM,MAAM;AACrC;AAEA,SAAS,iBAAiB,MAAc,OAAuB;AAC7D,SAAO,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;AAChD;;;AC1FA,IAAM,4BAA4B,KAAK,OAAO;AAC9C,IAAM,uBAAuB;AAC7B,IAAM,0BAA0B;AAChC,IAAM,qBAAqB;AAC3B,IAAM,8BAA8B;AACpC,IAAM,oCAAoC;AAO1C,IAAM,6CAA6C;AACnD,IAAM,gCAAgC;AACtC,IAAM,+BAA+B,KAAK,OAAO;AACjD,IAAM,0BAA0B;AAChC,IAAMG,eAAc,IAAI,YAAY;AA2H7B,IAAM,iBAAN,MAAqB;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACS;AAAA,EACA;AAAA,EACA,gBAAgB,oBAAI,IAAkC;AAAA,EACtD,0BAA0B,oBAAI,IAAyB;AAAA,EAChE;AAAA,EACA;AAAA,EAER,YAAY,SAAgC;AAC1C,QAAI,CAAC,sBAAsB,QAAQ,MAAM,EAAG,OAAM,IAAI,MAAM,sBAAsB;AAClF,SAAK,SAAS,QAAQ;AACtB,SAAK,UAAU,QAAQ;AACvB,SAAK,WAAW,QAAQ;AACxB,SAAK,yBAAyB,QAAQ,0BAA0B;AAChE,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,aAAa,kBAAkB,QAAQ,UAAU;AACtD,SAAK,kBAAkB,QAAQ,oBAAoB,SAC/C,SACA,CAAC,GAAG,IAAI,IAAI,QAAQ,eAAe,CAAC,EAAE,KAAKC,iBAAgB;AAC/D,QACE,KAAK,oBAAoB,WACxB,KAAK,gBAAgB,SAAS,+BAC7B,KAAK,gBAAgB,KAAK,oBAAkB,CAAC,sBAAsB,cAAc,CAAC,IACpF;AACA,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAAA,EACF;AAAA,EAEO,SAAS,UAAyB,CAAC,GAAgC;AACxE,QAAI,KAAK,aAAc,QAAO,KAAK;AACnC,SAAK,eAAe,QAAQ,UAAU,KAAK;AAC3C,UAAM,UAAU,KAAK,YAAY;AACjC,SAAK,eAAe;AACpB,UAAM,UAAU,MAAY;AAC1B,UAAI,KAAK,iBAAiB,SAAS;AACjC,aAAK,eAAe;AACpB,aAAK,eAAe;AAAA,MACtB;AAAA,IACF;AACA,SAAK,QAAQ,KAAK,SAAS,OAAO;AAClC,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,cAA2C;AACvD,SAAK,eAAe;AACpB,UAAM,QAAQ,KAAK,aAAa;AAChC,UAAM,gBAAgB,IAAI,IAAI,MAAM,IAAI,UAAQ,KAAK,MAAM,CAAC;AAC5D,SAAK,wBAAwB,aAAa;AAC1C,QAAI,KAAK,iBAAiB,WAAW,GAAG;AACtC,aAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU,EAAE,OAAO,GAAG,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,EAAE;AAAA,MACxE;AAAA,IACF;AACA,QAAI,CAAC,KAAK,QAAQ,+BAA+B,CAAC,KAAK,QAAQ,iCAAiC;AAC9F,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AACA,UAAM,eAAe,YAAY,OAAO,KAAK,aAAa;AAC1D,UAAM,eAAe,yBAAyB,KAAK,UAAU;AAC7D,UAAM,WAAiC;AAAA,MACrC,OAAO;AAAA,MACP,eAAe;AAAA,MACf,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,IACT;AACA,UAAM,iBAA2B,CAAC;AAClC,QAAI,WAAW;AACf,QAAI,iBAAiB;AACrB,UAAM,iBAAiB,aAAa,MAAM,GAAG,KAAK,WAAW,QAAQ;AACrE,eAAW,QAAQ,gBAAgB;AACjC,UAAI,aAAa,iBAAiB,aAAa,OAAO,kBAAkB;AACtE,qBAAa,YAAY;AACzB,mBAAW;AACX;AAAA,MACF;AACA,YAAM,SAAS,yBAAyB,YAAY;AACpD,UAAI;AACF,cAAM,eAAe,MAAM,KAAK,sBAAsB,MAAM,gBAAgB,MAAM;AAClF,YAAI,CAAC,cAAc;AACjB,qBAAW;AACX,cAAI,OAAO,WAAW;AACpB,2BAAe,KAAK,KAAK,MAAM;AAAA,UACjC,WAAW,KAAK,wBAAwB;AACtC,kBAAM,IAAI,MAAM,yBAAyB,KAAK,MAAM,EAAE;AAAA,UACxD;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,aAAK,eAAe;AACpB,YAAI,KAAK,uBAAwB,OAAM;AACvC,mBAAW;AAAA,MACb,UAAE;AACA,0BAAkB;AAClB,aAAK,gBAAgB,KAAK;AAC1B,iBAAS,SAAS;AAClB,iBAAS,iBAAiB,OAAO;AACjC,iBAAS,SAAS,OAAO;AACzB,iBAAS,UAAU,OAAO;AAC1B,iBAAS,SAAS,OAAO;AAAA,MAC3B;AACA,UAAI,aAAa,UAAW;AAAA,IAC9B;AACA,UAAM,eAAe,aAAa,MAAM,cAAc;AACtD,QAAI,aAAa,SAAS,GAAG;AAC3B,iBAAW;AACX,iBAAW,QAAQ,aAAa,MAAM,GAAG,KAAK,WAAW,QAAQ,GAAG;AAClE,uBAAe,KAAK,KAAK,MAAM;AAAA,MACjC;AAAA,IACF,WAAW,UAAU;AACnB,WAAK,gBAAgB;AAAA,IACvB;AACA,UAAM,wBAAwB,CAAC,GAAG,IAAI,IAAI,cAAc,CAAC,EAAE,MAAM,GAAG,KAAK,WAAW,QAAQ;AAC5F,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,GAAI,sBAAsB,SAAS,IAC/B,EAAE,cAAc,EAAE,QAAQ,eAAwB,gBAAgB,sBAAsB,EAAE,IAC1F,CAAC;AAAA,IACP;AAAA,EACF;AAAA,EAEO,gBAAgB,UAAyB,CAAC,GAAgC;AAC/E,WAAO,KAAK,SAAS,OAAO;AAAA,EAC9B;AAAA,EAEA,MAAc,sBACZ,MACA,iBACA,QACkB;AAClB,UAAM,eAAe,KAAK,cAAc,IAAI,KAAK,MAAM;AACvD,QAAI,aAAa,cAAc;AAC/B,QAAI,cAAc,cAAc;AAChC,QAAI,YAAY,cAAc,aAAa;AAC3C,QAAI,aAAa,cAAc,cAAc;AAC7C,OAAG;AACD,WAAK,eAAe;AACpB,UAAI,CAAC,wBAAwB,MAAM,GAAG;AACpC,aAAK,iBAAiB,KAAK,QAAQ,EAAE,YAAY,aAAa,WAAW,WAAW,CAAC;AACrF,eAAO;AAAA,MACT;AACA,YAAM,YAAwC,YAC1C,EAAE,OAAO,CAAC,EAAE,IACZ,MAAM,KAAK,QAAQ,4BAA4B;AAAA,QAC/C,OAAO;AAAA,QACP,GAAI,aAAa,EAAE,OAAO,WAAW,IAAI,CAAC;AAAA,QAC1C,GAAI,KAAK,kBAAkB,EAAE,iBAAiB,KAAK,gBAAgB,IAAI,CAAC;AAAA,QACxE,QAAQ,KAAK;AAAA,MACf,CAAC;AACH,WAAK,wBAAwB,WAAW,YAAY,SAAS;AAC7D,YAAM,WAAW,MAAM,KAAK;AAAA,QAC1B,UAAU;AAAA,QACV;AAAA,QACA,CAAC;AAAA,QACD,KAAK;AAAA,QACL,EAAE,QAAQ,KAAK,aAAa;AAAA,MAC9B;AACA,WAAK,wBAAwB,SAAS,YAAY,aAAa,KAAK,QAAQ,UAAU;AACtF,UACE,CAAC,qBAAqB,SAAS,gBAAgB,KAC/C,CAAC,4BAA4B,SAAS,kBAAkB,UAAU,KAAK,GACvE;AACA,cAAM,IAAI,MAAM,8BAA8B,KAAK,MAAM,EAAE;AAAA,MAC7D;AACA,WAAK,mBAAmB,SAAS,kBAAkB,KAAK,MAAM;AAC9D,YAAM,eAAe,MAAM,KAAK,iBAAiB,MAAM,SAAS,kBAAkB,MAAM;AACxF,UAAI,CAAC,cAAc;AACjB,aAAK,iBAAiB,KAAK,QAAQ,EAAE,YAAY,aAAa,WAAW,WAAW,CAAC;AACrF,eAAO;AAAA,MACT;AAEA,YAAM,iBAAiB,MAAM,KAAK,QAAQ;AAAA,QACxC,SAAS,WAAW,MAAM,IAAI,eAAa;AAAA,UACzC,gBAAgB,SAAS;AAAA,UACzB,cAAc,SAAS;AAAA,QACzB,EAAE;AAAA,QACF,EAAE,QAAQ,KAAK,aAAa;AAAA,MAC9B;AACA,YAAM,aAAa,IAAI,IAAI,eAAe,IAAI,cAAY;AAAA,QACxD,iBAAiB,SAAS,gBAAgB,SAAS,YAAY;AAAA,QAC/D,SAAS;AAAA,MACX,CAAC,CAAC;AACF,YAAM,kBAAkB,SAAS,WAAW,MAAM,QAAQ,cAAY;AACpE,cAAM,UAAU,WAAW,IAAI;AAAA,UAC7B,SAAS;AAAA,UACT,SAAS;AAAA,QACX,CAAC,KAAK;AACN,eAAO,SAAS,8BAA8B,UAC1C,CAAC;AAAA,UACD,gBAAgB,SAAS;AAAA,UACzB,cAAc,SAAS;AAAA,UACvB,eAAe;AAAA,UACf,aAAa,SAAS;AAAA,QACxB,CAAC,IACC,CAAC;AAAA,MACP,CAAC;AACD,WAAK,mBAAmB,iBAAiB,KAAK,MAAM;AACpD,YAAM,eAAe,MAAM,KAAK;AAAA,QAC9B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,CAAC,cAAc;AACjB,aAAK,iBAAiB,KAAK,QAAQ,EAAE,YAAY,aAAa,WAAW,WAAW,CAAC;AACrF,eAAO;AAAA,MACT;AAEA,mBAAa,UAAU;AACvB,oBAAc,SAAS,WAAW;AAClC,kBAAY,aAAa,eAAe;AACxC,mBAAa,cAAc,gBAAgB;AAAA,IAC7C,SAAS,CAAC,aAAa,CAAC;AACxB,SAAK,cAAc,OAAO,KAAK,MAAM;AACrC,SAAK,wBAAwB,OAAO,KAAK,MAAM;AAC/C,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,iBACZ,MACA,QACA,QACkB;AAClB,QAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,QAAQ,yBAA0B,QAAO;AACvE,QAAI;AACF,YAAM,uBAAuB,0BAA0B,MAAM;AAC7D,YAAM,WAAW,uBAAuB,MAAM;AAC9C,YAAM,eAAe,oBAAI,IAAY;AACrC,YAAM,gBAAgB,KAAK,wBAAwB,IAAI,KAAK,MAAM,KAAK,oBAAI,IAAY;AACvF,WAAK,wBAAwB,IAAI,KAAK,QAAQ,aAAa;AAC3D,UAAI,QAA6B,CAAC;AAClC,YAAM,QAAQ,YAA2B;AACvC,YAAI,MAAM,WAAW,EAAG;AACxB,cAAM,UAAU;AAChB,cAAM,KAAK,WAAY,SAAS,EAAE,QAAQ,KAAK,aAAa,CAAC;AAC7D,mBAAW,SAAS,SAAS;AAC3B,qBAAW,cAAc,sCAAsC,KAAK,GAAG;AACrE,0BAAc,OAAO,GAAG,MAAM,cAAc,KAAS,WAAW,WAAW,EAAE;AAAA,UAC/E;AAAA,QACF;AACA,gBAAQ,CAAC;AAAA,MACX;AAEA,iBAAW,CAAC,gBAAgB,kBAAkB,KAAK,sBAAsB;AACvE,YAAI;AACJ,WAAG;AACD,eAAK,eAAe;AACpB,cAAI,CAAC,iBAAiB,QAAQ,CAAC,GAAG;AAChC,kBAAM,MAAM;AACZ,mBAAO;AAAA,UACT;AACA,gBAAM,OAAO,MAAM,KAAK,QAAQ,yBAAyB,gBAAgB;AAAA,YACvE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,WAAW;AAAA,YACX,QAAQ,KAAK;AAAA,YACb,QAAQ,mBAAmB,IAAI,YAAU;AAAA,cACvC,cAAc,MAAM;AAAA,cACpB,eAAe,MAAM;AAAA,cACrB,aAAa,MAAM;AAAA,YACrB,EAAE;AAAA,UACJ,CAAC;AACD,eAAK,2BAA2B,MAAM,gBAAgB,MAAM;AAC5D,qBAAW,SAAS,KAAK,OAAO;AAC9B,gBAAI,CAAC,iBAAiB,QAAQ,KAAK,GAAG;AACpC,oBAAM,MAAM;AACZ,qBAAO;AAAA,YACT;AACA,kBAAM,QAAQ,mBAAmB,KAAK,CAAAC,eAAa,aAAa,OAAOA,UAAS,CAAC;AACjF,gBAAI,CAAC,MAAO;AACZ,mCAAuB,UAAU,KAAK;AACtC,uBAAW,cAAc,sCAAsC,KAAK,GAAG;AACrE,oBAAM,gBAAgB,GAAG,cAAc,KAAS,WAAW,WAAW;AACtE,kBAAI,aAAa,IAAI,aAAa,KAAK,cAAc,IAAI,aAAa,EAAG;AACzE,kBAAI,CAAC,MAAM,KAAK,qBAAqB,MAAM,gBAAgB,YAAY,MAAM,GAAG;AAC9E,sBAAM,MAAM;AACZ,uBAAO;AAAA,cACT;AACA,2BAAa,IAAI,aAAa;AAC9B,4BAAc,IAAI,aAAa;AAAA,YACjC;AAEA,kBAAM,YAAY,CAAC,GAAG,OAAO,KAAK;AAClC,gBAAI,UAAU,SAAS,wBAAwBC,gBAAe,SAAS,IAAI,2BAA2B;AACpG,kBAAI,MAAM,WAAW,EAAG,OAAM,IAAI,MAAM,sBAAsB;AAC9D,oBAAM,MAAM;AACZ,sBAAQ,CAAC,KAAK;AACd,kBAAIA,gBAAe,KAAK,IAAI,2BAA2B;AACrD,sBAAM,IAAI,MAAM,sBAAsB;AAAA,cACxC;AAAA,YACF,OAAO;AACL,sBAAQ;AAAA,YACV;AAAA,UACF;AACA,mBAAS,KAAK,eAAe,KAAK,YAAY;AAAA,QAChD,SAAS,WAAW;AAAA,MACtB;AACA,YAAM,MAAM;AACZ,aAAO,wBAAwB,QAAQ;AAAA,IACzC,SAAS,OAAO;AACd,WAAK,eAAe;AACpB,UAAI,KAAK,uBAAwB,OAAM;AACvC,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,mBACZ,MACA,QACA,iBACA,QACkB;AAClB,QAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAI,CAAC,KAAK,qBAAqB,CAAC,KAAK,QAAQ,qBAAsB,QAAO;AAC1E,QAAI;AACF,YAAM,uBAAuB,0BAA0B,MAAM;AAC7D,UAAI,WAAW,uBAAuB,MAAM;AAC5C,iBAAW,CAAC,gBAAgB,kBAAkB,KAAK,sBAAsB;AACvE,YAAI;AACJ,WAAG;AACD,eAAK,eAAe;AACpB,cAAI,CAAC,iBAAiB,QAAQ,CAAC,EAAG,QAAO;AACzC,gBAAM,OAAO,MAAM,KAAK;AAAA,YACtB;AAAA,YACA;AAAA,YACA;AAAA,YACA,EAAE,QAAQ,KAAK,aAAa;AAAA,UAC9B;AACA,eAAK,qBAAqB,MAAM,gBAAgB,oBAAoB,QAAQ,KAAK,MAAM;AACvF,4CAAkC,KAAK,KAAK;AAC5C,gBAAM,oBAAoB,sBAAsB,QAAQ;AACxD,gBAAM,iBAAsC,CAAC;AAC7C,qBAAW,SAAS,KAAK,OAAO;AAC9B,gBAAI,CAAC,iBAAiB,QAAQ,KAAK,EAAG;AACtC,mCAAuB,mBAAmB,KAAK;AAC/C,2BAAe,KAAK,KAAK;AAAA,UAC3B;AAGA,cAAI,CAAC,MAAM,KAAK,4BAA4B,gBAAgB,iBAAiB,MAAM,GAAG;AACpF,mBAAO;AAAA,UACT;AACA,cAAI,eAAe,SAAS,GAAG;AAC7B,kBAAM,KAAK,QAAQ,qBAAqB,cAAc;AAAA,UACxD;AACA,qBAAW;AACX,cAAI,eAAe,WAAW,KAAK,MAAM,OAAQ,QAAO;AACxD,mBAAS,KAAK;AAAA,QAChB,SAAS,WAAW;AAAA,MACtB;AACA,aAAO,wBAAwB,QAAQ;AAAA,IACzC,SAAS,OAAO;AACd,WAAK,eAAe;AACpB,UAAI,KAAK,uBAAwB,OAAM;AACvC,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,4BACZ,QACA,OACA,QACkB;AAClB,UAAM,aAAa,oBAAI,IAAwE;AAC/F,eAAW,SAAS,QAAQ;AAC1B,iBAAW,aAAa,sCAAsC,KAAK,GAAG;AACpE,mBAAW,IAAI,GAAG,MAAM,cAAc,KAAS,UAAU,WAAW,IAAI;AAAA,UACtE,gBAAgB,MAAM;AAAA,UACtB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA,eAAW,EAAE,gBAAgB,UAAU,KAAK,WAAW,OAAO,GAAG;AAC/D,UAAI,MAAM,KAAK,mBAAmB,SAAS,EAAG;AAC9C,UACE,CAAC,KAAK,QAAQ,wBAAwB,CAAC,KAAK,QAAQ,0BACpD,UAAU,OAAO,0BACjB,QAAO;AACT,YAAM,eAAe,MAAM,OAAO,UAAQ,KAAK,wBAAwB,MAAS;AAChF,UAAI,aAAa,WAAW,EAAG,QAAO;AACtC,UAAI,CAAC,sBAAsB,QAAQ,UAAU,IAAI,EAAG,QAAO;AAC3D,UAAI,UAAU;AACd,iBAAW,QAAQ,cAAc;AAC/B,cAAM,OAAO,KAAK,qBAAqB,KAAK,IAAI;AAChD,YAAI,CAAC,KAAM;AACX,YAAI;AACF,cAAI,SAAS;AACb,iBAAO,UAAU,UAAU,MAAM;AAC/B,iBAAK,eAAe;AACpB,kBAAM,QAAQ,MAAM;AAAA,cAClB;AAAA,cACA,UAAU;AAAA,cACV;AAAA,cACA;AAAA,cACA,EAAE,QAAQ,KAAK,aAAa;AAAA,YAC9B;AACA,gBACE,CAAC,SAAS,MAAM,WAAW,UAAU,MAAM,cAAc,UAAU,QACnE,MAAM,aAAa,UAAU,YAAY,MAAM,aAAa,UAAU,YACtE,MAAM,KAAK,aAAa,mCACxB,MAAM,UAAU,SAAS,MAAM,KAAK,eAAe,UAAU,SAC5D,CAAC,MAAM,QAAQ,MAAM,KAAK,eAAe,GAC1C;AACA,oBAAM,IAAI,MAAM,+BAA+B;AAAA,YACjD;AACA,kBAAM,aAAa,MAAM,KAAK,QAAQ;AAAA,cACpC;AAAA,cACA;AAAA,cACA,MAAM;AAAA,cACN,EAAE,QAAQ,KAAK,aAAa;AAAA,YAC9B;AACA,iBAAK,eAAe;AACpB,gBACE,CAAC,OAAO,cAAc,UAAU,KAAK,eAAe,SAAS,MAAM,KAAK,cACxE,aAAa,UAAU,MACvB;AACA,oBAAM,IAAI,MAAM,iCAAiC;AAAA,YACnD;AACA,qBAAS;AACT,gBAAI,WAAW,UAAU,MAAM;AAC7B,oBAAM,KAAK,QAAQ;AAAA,gBACjB,UAAU;AAAA,gBACV,EAAE,QAAQ,KAAK,aAAa;AAAA,cAC9B;AACA,mBAAK,eAAe;AACpB,wBAAU,MAAM,KAAK,mBAAmB,SAAS;AACjD;AAAA,YACF;AAAA,UACF;AAAA,QACF,QAAQ;AACN,eAAK,eAAe;AAAA,QAEtB;AACA,YAAI,QAAS;AAAA,MACf;AACA,UAAI,CAAC,QAAS,QAAO;AAAA,IACvB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,mBAAmB,WAAkD;AACjF,UAAM,SAAS,MAAM,KAAK,QAAQ,cAAc,UAAU,WAAW;AACrE,WAAO,WAAW,QAAQ,OAAO,SAAS,UAAU,QAAQ,OAAO,aAAa,UAAU,YACxF,OAAO,aAAa,UAAU,YAAY,KAAK,QAAQ,qBAAqB,UAC5E,MAAM,KAAK,QAAQ,iBAAiB,UAAU,aAAa,EAAE,QAAQ,KAAK,aAAa,CAAC;AAAA,EAC5F;AAAA,EAEA,MAAc,qBACZ,MACA,gBACA,WACA,QACkB;AAClB,QACE,CAAC,KAAK,uBAAuB,CAAC,KAAK,QAAQ,uBAC3C,UAAU,OAAO,6BAA6B,CAAC,MAAM,KAAK,mBAAmB,SAAS,GACtF;AACA,aAAO;AAAA,IACT;AACA,QAAI,CAAC,sBAAsB,QAAQ,UAAU,IAAI,EAAG,QAAO;AAC3D,QAAI,SAAS;AACb,WAAO,UAAU,UAAU,MAAM;AAC/B,WAAK,eAAe;AACpB,YAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,QAC9B,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA,EAAE,QAAQ,KAAK,aAAa;AAAA,MAC9B;AACA,WAAK,eAAe;AACpB,UACE,CAAC,QAAQ,KAAK,aAAa,mCAC3B,SAAS,KAAK,aAAa,UAAU,QACpC,KAAK,eAAe,KAAK,WAAW,UAAU,KAC/C,QAAO;AACT,YAAM,OAAO,SAAS,KAAK,eAAe,UAAU;AACpD,YAAM,KAAK;AAAA,QACT;AAAA,QACA,UAAU;AAAA,QACV;AAAA,UACE;AAAA,UACA;AAAA,UACA,WAAW,UAAU;AAAA,UACrB;AAAA,UACA,UAAU,UAAU;AAAA,UACpB,UAAU,UAAU;AAAA,QACtB;AAAA,QACA,EAAE,QAAQ,KAAK,aAAa;AAAA,MAC9B;AACA,gBAAU,KAAK;AACf,UAAI,KAAM,QAAO;AAAA,IACnB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,qBACN,MACA,gBACA,QACA,gBACA,QACM;AACN,QACE,CAAC,cAAc,IAAI,KAAK,CAACC,aAAY,MAAM,CAAC,SAAS,YAAY,CAAC,KAClE,CAAC,MAAM,QAAQ,KAAK,KAAK,KAAK,KAAK,MAAM,SAAS,sBAClD;AACA,YAAM,IAAI,MAAM,2BAA2B,MAAM,EAAE;AAAA,IACrD;AACA,qCAAiC,KAAK,OAAO,2BAA2B,MAAM,EAAE;AAChF,QAAI,aAAa;AACjB,eAAW,SAAS,KAAK,OAAO;AAC9B,UAAI;AACF,yCAAiC,KAAK;AACtC,+CAAuC,KAAK;AAAA,MAC9C,QAAQ;AACN,cAAM,IAAI,MAAM,2BAA2B,MAAM,EAAE;AAAA,MACrD;AACA,UACE,MAAM,mBAAmB,kBACzB,CAAC,OAAO,KAAK,WAAS,aAAa,OAAO,KAAK,CAAC,GAChD;AACA,cAAM,IAAI,MAAM,2BAA2B,MAAM,EAAE;AAAA,MACrD;AACA,YAAM,gBAAgB,YAAY,KAAK;AACvC,UAAI,cAAc,mBAAmB,eAAe,UAAU,KAAK,GAAG;AACpE,cAAM,IAAI,MAAM,4BAA4B,MAAM,EAAE;AAAA,MACtD;AACA,mBAAa;AAAA,IACf;AACA,QAAI,KAAK,eAAe,OAAW;AACnC,QAAI,CAAC,0BAA0B,KAAK,UAAU,EAAG,OAAM,IAAI,MAAM,6BAA6B,MAAM,EAAE;AACtG,QAAI,kBAAkB,mBAAmB,KAAK,YAAY,cAAc,KAAK,GAAG;AAC9E,YAAM,IAAI,MAAM,qCAAqC,MAAM,EAAE;AAAA,IAC/D;AACA,UAAM,WAAW,KAAK,MAAM,GAAG,EAAE;AACjC,QAAI,CAAC,YAAY,mBAAmB,KAAK,YAAY,YAAY,QAAQ,CAAC,MAAM,GAAG;AACjF,YAAM,IAAI,MAAM,mCAAmC,MAAM,EAAE;AAAA,IAC7D;AAAA,EACF;AAAA,EAEQ,2BACN,MACA,gBACA,gBACM;AACN,QACE,CAAC,cAAc,IAAI,KAAK,CAACA,aAAY,MAAM;AAAA,MACzC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC,KAAK,CAAC,MAAM,QAAQ,KAAK,KAAK,KAAK,KAAK,MAAM,SAAS,wBACxD,OAAO,KAAK,kBAAkB,aAAa,OAAO,KAAK,iBAAiB,aACxE,KAAK,MAAM,KAAK,WAAS;AACvB,UAAI;AACF,yCAAiC,KAAK;AACtC,+CAAuC,KAAK;AAC5C,eAAO,MAAM,mBAAmB;AAAA,MAClC,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,CAAC,GACD;AACA,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AACA,qCAAiC,KAAK,OAAO,4BAA4B;AACzE,QAAI,aAAa;AACjB,eAAW,SAAS,KAAK,OAAO;AAC9B,YAAM,gBAAgB,YAAY,KAAK;AACvC,UAAI,cAAc,mBAAmB,eAAe,UAAU,KAAK,GAAG;AACpE,cAAM,IAAI,MAAM,6BAA6B;AAAA,MAC/C;AACA,mBAAa;AAAA,IACf;AACA,QAAI,CAAC,KAAK,aAAc;AACxB,QACE,KAAK,MAAM,WAAW,KAAK,CAAC,KAAK,aAAa,CAAC,0BAA0B,KAAK,SAAS,KACvF,kBAAkB,mBAAmB,KAAK,WAAW,cAAc,KAAK,KACxE,cAAc,mBAAmB,KAAK,WAAW,UAAU,MAAM,GACjE;AACA,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AAAA,EACF;AAAA,EAEO,aAA4B;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,mBAAmB,QAAwB,QAAsB;AACvE,QAAI,KAAK,oBAAoB,OAAW;AACxC,UAAM,UAAU,IAAI,IAAI,KAAK,eAAe;AAC5C,QAAI,OAAO,KAAK,WAAS,CAAC,QAAQ,IAAI,MAAM,cAAc,CAAC,GAAG;AAC5D,YAAM,IAAI,MAAM,8BAA8B,MAAM,EAAE;AAAA,IACxD;AAAA,EACF;AAAA,EAEQ,wBACN,MACA,UACA,QACA,gBAAgB,OACV;AACN,QACE,CAAC,cAAc,IAAI,KAAK,CAACA,aAAY,MAAM,CAAC,SAAS,YAAY,CAAC,KAClE,CAAC,MAAM,QAAQ,KAAK,KAAK,KAAK,KAAK,MAAM,SAAS,2BAClD,kBAAkB,KAAK,MAAM,SAAS,KAAK,KAAK,eAAe,SAC/D;AACA,YAAM,IAAI,MAAM,8BAA8B,MAAM,EAAE;AAAA,IACxD;AACA,QAAI,OAAO;AACX,eAAW,YAAY,KAAK,OAAO;AACjC,UAAI,CAAC,gBAAgB,QAAQ,EAAG,OAAM,IAAI,MAAM,yBAAyB,MAAM,EAAE;AACjF,YAAM,SAAS,EAAE,gBAAgB,SAAS,gBAAgB,cAAc,SAAS,aAAa;AAC9F,UAAI,QAAQ,sBAAsB,QAAQ,IAAI,KAAK,GAAG;AACpD,cAAM,IAAI,MAAM,+BAA+B,MAAM,EAAE;AAAA,MACzD;AACA,aAAO;AAAA,IACT;AACA,QAAI,KAAK,eAAe,OAAW;AACnC,QACE,CAAC,QAAQ,CAAC,sBAAsB,KAAK,UAAU,KAC/C,sBAAsB,KAAK,YAAY,IAAI,MAAM,KACjD,YAAY,sBAAsB,KAAK,YAAY,QAAQ,KAAK,GAChE;AACA,YAAM,IAAI,MAAM,wCAAwC,MAAM,EAAE;AAAA,IAClE;AAAA,EACF;AAAA,EAEQ,iBAAiB,QAAgB,cAA0C;AACjF,SAAK,cAAc,IAAI,QAAQ;AAAA,MAC7B,WAAW,aAAa;AAAA,MACxB,YAAY,aAAa;AAAA,MACzB,GAAI,aAAa,aAAa,EAAE,YAAY,EAAE,GAAG,aAAa,WAAW,EAAE,IAAI,CAAC;AAAA,MAChF,GAAI,aAAa,cAAc,EAAE,aAAa,EAAE,GAAG,aAAa,YAAY,EAAE,IAAI,CAAC;AAAA,IACrF,CAAC;AAAA,EACH;AAAA,EAEQ,eAA+B;AACrC,UAAM,SAAS,oBAAI,IAA0B;AAC7C,eAAW,QAAQ,KAAK,SAAS,GAAG;AAClC,UAAI,CAAC,sBAAsB,KAAK,MAAM,EAAG,OAAM,IAAI,MAAM,sBAAsB;AAC/E,UAAI,KAAK,WAAW,KAAK,UAAU,OAAO,IAAI,KAAK,MAAM,EAAG;AAC5D,aAAO,IAAI,KAAK,QAAQ,IAAI;AAAA,IAC9B;AACA,WAAO,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,UAAUH,kBAAiB,KAAK,QAAQ,MAAM,MAAM,CAAC;AAAA,EAC/F;AAAA,EAEQ,wBAAwB,eAA0C;AACxE,eAAW,UAAU,KAAK,cAAc,KAAK,GAAG;AAC9C,UAAI,CAAC,cAAc,IAAI,MAAM,EAAG,MAAK,cAAc,OAAO,MAAM;AAAA,IAClE;AACA,eAAW,UAAU,KAAK,wBAAwB,KAAK,GAAG;AACxD,UAAI,CAAC,cAAc,IAAI,MAAM,EAAG,MAAK,wBAAwB,OAAO,MAAM;AAAA,IAC5E;AACA,QAAI,KAAK,kBAAkB,UAAa,CAAC,cAAc,IAAI,KAAK,aAAa,GAAG;AAC9E,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,CAAC,KAAK,cAAc,QAAS;AACjC,UAAM,KAAK,aAAa,kBAAkB,QACtC,KAAK,aAAa,SAClB,IAAI,MAAM,mBAAmB;AAAA,EACnC;AACF;AAEA,SAAS,uCAAuC,OAAgC;AAC9E,MAAI,MAAM,SAAS,UAAW;AAC9B,QAAM,UAAU;AAAA,IACd,GAAG,MAAM;AAAA,IACT,gBAAgB,MAAM;AAAA,IACtB,cAAc,MAAM;AAAA,IACpB,gBAAgB,MAAM;AAAA,IACtB,cAAc,MAAM;AAAA,IACpB,WAAW,MAAM;AAAA,EACnB;AACA,MAAI,MAAM,QAAQ,SAAS,OAAQ,oCAAmC,OAAO;AAAA,MACxE,6CAA4C,OAAO;AAC1D;AAEA,SAAS,gBAAgB,OAAiD;AACxE,MACE,CAAC,cAAc,KAAK,KAAK,CAACG,aAAY,OAAO;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,EACD,QAAO;AACT,QAAM,WAAW;AACjB,SAAO,sBAAsB,SAAS,cAAc,KAClD,sBAAsB,SAAS,YAAY,KAC3C,OAAO,SAAS,gCAAgC,YAChD,OAAO,cAAc,SAAS,2BAA2B,KACzD,SAAS,8BAA8B;AAC3C;AAEA,SAAS,qBAAqB,OAAyC;AACrE,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,wBAAyB,QAAO;AAC5E,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,QAAQ,OAAO;AACxB,QACE,CAAC,cAAc,IAAI,KAAK,CAACA,aAAY,MAAM;AAAA,MACzC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC,EACD,QAAO;AACT,UAAM,QAAQ;AACd,QACE,CAAC,sBAAsB,MAAM,cAAc,KAC3C,CAAC,sBAAsB,MAAM,YAAY,KACzC,OAAO,MAAM,kBAAkB,YAAY,CAAC,OAAO,cAAc,MAAM,aAAa,KACpF,MAAM,gBAAgB,KAAK,OAAO,MAAM,gBAAgB,YACxD,CAAC,OAAO,cAAc,MAAM,WAAW,KAAK,MAAM,eAAe,MAAM,cACvE,QAAO;AACT,UAAM,MAAM,iBAAiB,MAAM,gBAAgB,MAAM,YAAY;AACrE,QAAI,WAAW,IAAI,GAAG,EAAG,QAAO;AAChC,eAAW,IAAI,GAAG;AAAA,EACpB;AACA,SAAO;AACT;AAEA,SAAS,4BACP,QACA,WACS;AACT,QAAM,UAAU,IAAI,IAAI,UAAU,IAAI,cAAY;AAAA,IAChD,iBAAiB,SAAS,gBAAgB,SAAS,YAAY;AAAA,IAC/D,SAAS;AAAA,EACX,CAAC,CAAC;AACF,SAAO,OAAO,MAAM,WAAS,QAAQ,IAAI,iBAAiB,MAAM,gBAAgB,MAAM,YAAY,CAAC,MAAM,MAAM,WAAW;AAC5H;AAEA,SAAS,sBAAsB,OAAuD;AACpF,MAAI,CAAC,cAAc,KAAK,KAAK,CAACA,aAAY,OAAO,CAAC,kBAAkB,cAAc,CAAC,EAAG,QAAO;AAC7F,QAAM,SAAS;AACf,SAAO,sBAAsB,OAAO,cAAc,KAChD,sBAAsB,OAAO,YAAY;AAC7C;AAEA,SAAS,sBACP,MACA,OACQ;AACR,SAAO,iBAAiB,KAAK,gBAAgB,MAAM,cAAc,KAC/D,iBAAiB,KAAK,cAAc,MAAM,YAAY;AAC1D;AAEA,SAAS,kBAAkB,OAAoE;AAC7F,QAAM,SAA6B;AAAA,IACjC,UAAU,OAAO,YAAY;AAAA,IAC7B,kBAAkB,OAAO,oBAAoB;AAAA,IAC7C,UAAU,OAAO,YAAY;AAAA,IAC7B,WAAW,OAAO,aAAa;AAAA,IAC/B,UAAU,OAAO,YAAY;AAAA,EAC/B;AACA,QAAM,aAAiC;AAAA,IACrC,UAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AACA,aAAW,OAAO,OAAO,KAAK,MAAM,GAAsC;AACxE,QAAI,CAAC,OAAO,cAAc,OAAO,GAAG,CAAC,KAAK,OAAO,GAAG,KAAK,KAAK,OAAO,GAAG,IAAI,WAAW,GAAG,GAAG;AAC3F,YAAM,IAAI,MAAM,2BAA2B,GAAG,EAAE;AAAA,IAClD;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,yBAAyB,QAAgD;AAChF,SAAO,EAAE,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,WAAW,OAAO,OAAO;AACrF;AAEA,SAAS,yBAAyB,QAAgD;AAChF,SAAO,EAAE,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,WAAW,OAAO,OAAO;AACrF;AAEA,SAAS,wBAAwB,QAAqC;AACpE,MACE,OAAO,gBAAgB,IAAI,8CAC3B,OAAO,OAAO,gBAAgB,IAAI,OAAO,OAAO,OAAO,kBACvD;AACA,WAAO,YAAY;AACnB,QAAI,OAAO,OAAO,gBAAgB,IAAI,OAAO,OAAO,OAAO,kBAAkB;AAC3E,aAAO,OAAO,YAAY;AAAA,IAC5B;AACA,WAAO;AAAA,EACT;AACA,SAAO,iBAAiB;AACxB,SAAO,OAAO,iBAAiB;AAC/B,SAAO;AACT;AAEA,SAAS,iBAAiB,QAA4B,OAAwB;AAC5E,MACE,OAAO,QAAQ,QAAQ,qCACvB,OAAO,OAAO,QAAQ,QAAQ,OAAO,OAAO,OAAO,UACnD;AACA,WAAO,YAAY;AACnB,QAAI,OAAO,OAAO,QAAQ,QAAQ,OAAO,OAAO,OAAO,SAAU,QAAO,OAAO,YAAY;AAC3F,WAAO;AAAA,EACT;AACA,SAAO,SAAS;AAChB,SAAO,OAAO,SAAS;AACvB,SAAO;AACT;AAEA,SAAS,iBAAiB,QAA4B,OAAmC;AACvF,QAAM,QAAQ,gCAAgC,KAAK,EAAE;AACrD,MACE,OAAO,SAAS,IAAI,iCACpB,OAAO,QAAQ,QAAQ,gCACvB,OAAO,OAAO,SAAS,IAAI,OAAO,OAAO,OAAO,aAChD,OAAO,OAAO,QAAQ,QAAQ,OAAO,OAAO,OAAO,UACnD;AACA,WAAO,YAAY;AACnB,QACE,OAAO,OAAO,SAAS,IAAI,OAAO,OAAO,OAAO,aAChD,OAAO,OAAO,QAAQ,QAAQ,OAAO,OAAO,OAAO,SACnD,QAAO,OAAO,YAAY;AAC5B,WAAO;AAAA,EACT;AACA,SAAO,UAAU;AACjB,SAAO,SAAS;AAChB,SAAO,OAAO,UAAU;AACxB,SAAO,OAAO,SAAS;AACvB,SAAO;AACT;AAEA,SAAS,sBAAsB,QAA4B,OAAwB;AACjF,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,+BAA+B,CAAC;AAC7E,MACE,OAAO,QAAQ,SAAS,qCACxB,OAAO,QAAQ,QAAQ,gCACvB,OAAO,OAAO,QAAQ,SAAS,OAAO,OAAO,OAAO,YACpD,OAAO,OAAO,QAAQ,QAAQ,OAAO,OAAO,OAAO,UACnD;AACA,WAAO,YAAY;AACnB,QACE,OAAO,OAAO,QAAQ,SAAS,OAAO,OAAO,OAAO,YACpD,OAAO,OAAO,QAAQ,QAAQ,OAAO,OAAO,OAAO,SACnD,QAAO,OAAO,YAAY;AAC5B,WAAO;AAAA,EACT;AACA,SAAO,SAAS;AAChB,SAAO,SAAS;AAChB,SAAO,OAAO,SAAS;AACvB,SAAO,OAAO,SAAS;AACvB,SAAO;AACT;AAEA,SAAS,YAAY,OAAuB,OAA2C;AACrF,MAAI,MAAM,WAAW,KAAK,UAAU,OAAW,QAAO;AACtD,QAAM,QAAQ,MAAM,UAAU,UAAQH,kBAAiB,KAAK,QAAQ,KAAK,IAAI,CAAC;AAC9E,MAAI,QAAQ,EAAG,QAAO;AACtB,SAAO,CAAC,GAAG,MAAM,MAAM,KAAK,GAAG,GAAG,MAAM,MAAM,GAAG,KAAK,CAAC;AACzD;AAEA,SAAS,0BAA0B,QAAqD;AACtF,QAAM,UAAU,oBAAI,IAA4B;AAChD,aAAW,SAAS,QAAQ;AAC1B,UAAM,SAAS,QAAQ,IAAI,MAAM,cAAc,KAAK,CAAC;AACrD,WAAO,KAAK,KAAK;AACjB,YAAQ,IAAI,MAAM,gBAAgB,MAAM;AAAA,EAC1C;AACA,SAAO;AACT;AAEA,SAAS,aAAa,OAA0B,OAA8B;AAC5E,SAAO,MAAM,mBAAmB,MAAM,kBACpC,MAAM,iBAAiB,MAAM,gBAC7B,MAAM,iBAAiB,MAAM,iBAC7B,MAAM,kBAAkB,MAAM;AAClC;AAOA,SAAS,uBAAuB,QAAuD;AACrF,QAAM,WAAW,oBAAI,IAA8B;AACnD,aAAW,SAAS,QAAQ;AAC1B,UAAM,MAAM,iBAAiB,MAAM,gBAAgB,MAAM,YAAY;AACrE,QAAI,SAAS,IAAI,GAAG,EAAG,OAAM,IAAI,MAAM,8BAA8B;AACrE,aAAS,IAAI,KAAK;AAAA,MAChB,cAAc,MAAM,gBAAgB;AAAA,MACpC,aAAa,MAAM;AAAA,IACrB,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,sBACP,UAC+B;AAC/B,SAAO,IAAI,IAAI,CAAC,GAAG,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;AACzE;AAEA,SAAS,uBACP,UACA,OACM;AACN,QAAM,MAAM,iBAAiB,MAAM,gBAAgB,MAAM,YAAY;AACrE,QAAM,WAAW,SAAS,IAAI,GAAG;AACjC,MAAI,CAAC,YAAY,MAAM,mBAAmB,SAAS,cAAc;AAC/D,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AACA,WAAS,gBAAgB;AAC3B;AAEA,SAAS,wBACP,UACS;AACT,SAAO,CAAC,GAAG,SAAS,OAAO,CAAC,EAAE,MAAM,cAAY,SAAS,iBAAiB,SAAS,cAAc,CAAC;AACpG;AAEA,SAAS,0BAA0B,OAAkD;AACnF,MACE,CAAC,cAAc,KAAK,KAAK,CAACG,aAAY,OAAO;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,EACD,QAAO;AACT,QAAM,SAAS;AACf,SAAO,sBAAsB,OAAO,YAAY,KAC9C,OAAO,OAAO,mBAAmB,YAAY,OAAO,cAAc,OAAO,cAAc,KACvF,OAAO,iBAAiB,KAAK,sBAAsB,OAAO,OAAO;AACrE;AAEA,SAAS,YAAY,OAAmD;AACtE,SAAO;AAAA,IACL,cAAc,MAAM;AAAA,IACpB,gBAAgB,MAAM;AAAA,IACtB,SAAS,MAAM;AAAA,EACjB;AACF;AAEA,SAAS,mBAAmB,MAA+B,OAAwC;AACjG,SAAO,iBAAiB,KAAK,cAAc,MAAM,YAAY,KAC3D,KAAK,iBAAiB,MAAM,kBAC5B,iBAAiB,KAAK,SAAS,MAAM,OAAO;AAChD;AAGA,SAAS,iBAAiB,MAAc,OAAuB;AAC7D,MAAI,SAAS,MAAO,QAAO;AAC3B,QAAM,YAAYJ,aAAY,OAAO,IAAI;AACzC,QAAM,aAAaA,aAAY,OAAO,KAAK;AAC3C,QAAM,SAAS,KAAK,IAAI,UAAU,QAAQ,WAAW,MAAM;AAC3D,WAAS,QAAQ,GAAG,QAAQ,QAAQ,SAAS,GAAG;AAC9C,UAAM,aAAa,UAAU,KAAK,IAAI,WAAW,KAAK;AACtD,QAAI,eAAe,EAAG,QAAO;AAAA,EAC/B;AACA,SAAO,UAAU,SAAS,WAAW;AACvC;AAEA,SAASC,kBAAiB,MAAc,OAAuB;AAC7D,SAAO,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;AAChD;AAEA,SAASE,gBAAe,QAA8C;AACpE,SAAO,yBAAyB,MAAM;AACxC;AAEA,SAAS,yBAAyB,QAA8C;AAC9E,MAAI,QAAQ,IAAI,KAAK,IAAI,GAAG,OAAO,SAAS,CAAC;AAC7C,aAAW,SAAS,OAAQ,UAAS,gCAAgC,KAAK,EAAE;AAC5E,SAAO;AACT;AAEA,SAAS,iCACP,QACA,WACM;AACN,MAAI,yBAAyB,MAAM,IAAI,0BAA2B,OAAM,IAAI,MAAM,SAAS;AAC7F;AAEA,SAAS,sBAAsB,OAAiC;AAC9D,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,KACjDH,aAAY,OAAO,KAAK,EAAE,cAAc,sBACxC,CAAC,MAAM,KAAK,KAAK,EAAE,KAAK,eAAa;AACnC,UAAM,YAAY,UAAU,YAAY,CAAC,KAAK;AAC9C,WAAO,aAAa,MAAM,cAAc;AAAA,EAC1C,CAAC;AACL;AAEA,SAAS,cAAc,OAAkD;AACvE,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,MAAI;AACF,UAAM,YAAY,OAAO,eAAe,KAAK;AAC7C,WAAO,cAAc,OAAO,aAAa,cAAc;AAAA,EACzD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAASI,aAAY,OAAgC,SAAqC;AACxF,QAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,SAAO,OAAO,KAAK,KAAK,EAAE,MAAM,SAAO,KAAK,IAAI,GAAG,CAAC;AACtD;;;AC3lCO,IAAM,sBAAN,MAAkD;AAAA,EACvC;AAAA,EACC;AAAA,EAEjB,YAAY,QAAgB,WAA8B;AACxD,SAAK,SAAS;AACd,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,4BACE,gBACA,aACA,mBACA,iBACA,SACA;AACA,WAAO,KAAK,UAAU;AAAA,MACpB,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,kBACE,gBACA,QACA,QACA,SACoC;AACpC,UAAM,YAAY,KAAK,UAAU,mBAAmB,KAAK,KAAK,SAAS;AACvE,QAAI,CAAC,WAAW;AACd,aAAO,QAAQ,OAAO,IAAI,MAAM,uDAAuD,CAAC;AAAA,IAC1F;AACA,WAAO,UAAU,KAAK,QAAQ,gBAAgB,QAAQ,QAAQ,OAAO;AAAA,EACvE;AAAA,EAEA,oBACE,gBACA,aACA,QACA,UACA,SACA;AACA,UAAM,YAAY,KAAK,UAAU,qBAAqB,KAAK,KAAK,SAAS;AACzE,QAAI,CAAC,WAAW;AACd,aAAO,QAAQ,QAAQ,IAAI;AAAA,IAC7B;AACA,WAAO,UAAU,KAAK,QAAQ,gBAAgB,aAAa,QAAQ,UAAU,OAAO;AAAA,EACtF;AAAA,EAEA,WAAW,QAA6B,SAAwC;AAC9E,UAAM,YAAY,KAAK,UAAU,YAAY,KAAK,KAAK,SAAS;AAChE,QAAI,CAAC,UAAW,QAAO,QAAQ,OAAO,IAAI,MAAM,4CAA4C,CAAC;AAC7F,WAAO,UAAU,KAAK,QAAQ,QAAQ,OAAO;AAAA,EAC/C;AAAA,EAEA,oBACE,gBACA,aACA,OACA,SACe;AACf,UAAM,YAAY,KAAK,UAAU,qBAAqB,KAAK,KAAK,SAAS;AACzE,QAAI,CAAC,UAAW,QAAO,QAAQ,OAAO,IAAI,MAAM,iDAAiD,CAAC;AAClG,WAAO,UAAU,KAAK,QAAQ,gBAAgB,aAAa,OAAO,OAAO;AAAA,EAC3E;AACF;","names":["assertExactKeys","asRecord","assertIdentifier","fail","asRecord","assertOnlyKeys","assertIdentifier","fail","value","assertArray","optionalBoolean","assertAttachmentReference","hasOnlyKeys","text","isRecord","assertExactKeys","copied","throwIfAborted","hasOnlyKeys","hasOnlyKeys","containsAsciiControlOrSpace","peerId","throwIfAborted","fence","containsAsciiControlOrSpace","utf8Encoder","compareCodeUnits","candidate","jsonByteLength","hasOnlyKeys"]}
|