memeloop 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/browser.cjs +1 -1
  2. package/dist/browser.cjs.map +1 -1
  3. package/dist/browser.d.cts +5 -5
  4. package/dist/browser.d.ts +5 -5
  5. package/dist/browser.js +1 -1
  6. package/dist/{chunk-ECNKBH5A.js → chunk-E5R24U4I.js} +76 -19
  7. package/dist/chunk-E5R24U4I.js.map +1 -0
  8. package/dist/{chunk-CCEFAOSH.js → chunk-WHXFUMDE.js} +2 -2
  9. package/dist/{chunk-CCEFAOSH.js.map → chunk-WHXFUMDE.js.map} +1 -1
  10. package/dist/device-network-portable.cjs +75 -18
  11. package/dist/device-network-portable.cjs.map +1 -1
  12. package/dist/device-network-portable.d.cts +3 -3
  13. package/dist/device-network-portable.d.ts +3 -3
  14. package/dist/device-network-portable.js +1 -1
  15. package/dist/device-network.cjs +75 -18
  16. package/dist/device-network.cjs.map +1 -1
  17. package/dist/device-network.d.cts +2 -2
  18. package/dist/device-network.d.ts +2 -2
  19. package/dist/device-network.js +1 -1
  20. package/dist/index.cjs +77 -20
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +4 -4
  23. package/dist/index.d.ts +4 -4
  24. package/dist/index.js +3 -3
  25. package/dist/index.js.map +1 -1
  26. package/dist/loop-api.cjs.map +1 -1
  27. package/dist/{orchestration-portable-BbkwLbC9.d.ts → orchestration-portable-B4udCSVd.d.ts} +1 -1
  28. package/dist/{orchestration-portable-DNKzAtNq.d.cts → orchestration-portable-BWaCsCGK.d.cts} +1 -1
  29. package/dist/orchestration-portable.cjs +1 -1
  30. package/dist/orchestration-portable.cjs.map +1 -1
  31. package/dist/orchestration-portable.d.cts +2 -2
  32. package/dist/orchestration-portable.d.ts +2 -2
  33. package/dist/orchestration-portable.js +1 -1
  34. package/dist/{pairingInvite-DDx_-IAp.d.cts → pairingInvite-DENOiqa0.d.cts} +1 -1
  35. package/dist/{pairingInvite-Dkz8CLsb.d.ts → pairingInvite-DZy77i0p.d.ts} +1 -1
  36. package/dist/{remoteClient-BKmQEQY9.d.cts → remoteClient-DFIyCZEv.d.cts} +1 -1
  37. package/dist/{remoteClient-D5hco6cS.d.ts → remoteClient-DwBCoHpc.d.ts} +1 -1
  38. package/package.json +1 -1
  39. package/dist/chunk-ECNKBH5A.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/device-network-portable.ts","../src/device-network/deviceCloudConnectionCoordinator.ts","../src/orchestration/errors.ts","../src/device-network/jsonFrame.ts","../src/device-network/deviceOrchestrationTransport.ts","../src/device-network/deviceSyncStateStore.ts","../src/device-network/libp2pSyncProtocol.ts","../src/device-network/libp2pDeviceSyncTransport.ts","../src/device-network/libp2pRpcProtocol.ts","../src/device-network/localTrustDeviceAuthorizer.ts","../src/device-network/pairingInvite.ts","../src/sync/attachmentRpcCodec.ts","../src/sync/chatSyncEngine.ts","../src/sync/peerNodeAdapter.ts","../src/sync/protocol.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 * from './device-network/deviceCloudConnectionCoordinator.js';\nexport * from './device-network/deviceOrchestrationTransport.js';\nexport * from './device-network/deviceSyncStateStore.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/pairingInvite.js';\nexport * from './device-network/types.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","export 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 interface DeviceCloudConnectionSnapshot {\n status: DeviceCloudConnectionStatus;\n generation: number;\n components: Record<DeviceCloudConnectionComponent, DeviceCloudComponentStatus>;\n lastError?: unknown;\n nextRetryAt?: number;\n}\n\n/**\n * A step performs remote or otherwise reversible work first. Durable host\n * state must only be changed by commit(), which the coordinator invokes after\n * confirming that the configuration generation is still current.\n */\nexport interface DeviceCloudStepResult {\n commit?: () => 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 classifyError?(error: unknown): 'offline' | 'error';\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 now?: () => number;\n random?: () => number;\n onStatus?: (snapshot: DeviceCloudConnectionSnapshot) => void | Promise<void>;\n logWarning?: (message: string, error: unknown) => 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;\n\nfunction emptyComponents(): DeviceCloudConnectionSnapshot['components'] {\n return {\n authorizer: 'not-run',\n registration: 'not-run',\n relay: 'not-run',\n heartbeat: 'not-run',\n directory: 'not-run',\n };\n}\n\nfunction assertNonNegativeFinite(value: number, name: string): void {\n if (!Number.isFinite(value) || value < 0) {\n throw new TypeError(`${name} must be a finite non-negative number`);\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 generation = 0;\n private controller = new AbortController();\n private timer?: ReturnType<typeof setTimeout>;\n private inFlight?: Promise<void>;\n private started = false;\n private consecutiveFailures = 0;\n private snapshotValue: DeviceCloudConnectionSnapshot = {\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 now: () => number;\n private readonly random: () => number;\n\n constructor(private readonly options: DeviceCloudConnectionCoordinatorOptions<Configuration>) {\n this.configuration = 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.now = options.now ?? Date.now;\n this.random = options.random ?? Math.random;\n assertNonNegativeFinite(this.heartbeatIntervalMs, 'heartbeatIntervalMs');\n assertNonNegativeFinite(this.initialBackoffMs, 'initialBackoffMs');\n assertNonNegativeFinite(this.maxBackoffMs, 'maxBackoffMs');\n assertNonNegativeFinite(this.jitterRatio, 'jitterRatio');\n if (this.jitterRatio > 1) throw new TypeError('jitterRatio must not exceed 1');\n this.resetSnapshot();\n }\n\n public get snapshot(): DeviceCloudConnectionSnapshot {\n return {\n ...this.snapshotValue,\n components: { ...this.snapshotValue.components },\n };\n }\n\n public async start(): Promise<void> {\n if (this.started) return this.runNow();\n this.started = true;\n await this.runNow();\n }\n\n public async stop(): Promise<void> {\n this.started = false;\n this.clearTimer();\n this.controller.abort(new Error('device cloud coordinator stopped'));\n await this.inFlight?.catch(() => undefined);\n }\n\n public async setConfiguration(configuration: Configuration | undefined): Promise<void> {\n this.configuration = configuration;\n this.generation += 1;\n this.consecutiveFailures = 0;\n this.clearTimer();\n this.controller.abort(new Error('device cloud configuration changed'));\n this.controller = new AbortController();\n this.inFlight = undefined;\n this.resetSnapshot();\n if (this.started && this.options.adapter.isConfigured(configuration)) await this.runNow();\n }\n\n public runNow(): 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 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 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 try {\n if (this.snapshotValue.components.authorizer !== 'ready') {\n await this.runStep('authorizer', generation, signal, () => this.options.adapter.ensureAuthorizer(configuration, signal));\n }\n if (this.snapshotValue.components.registration !== 'ready') {\n await this.runStep('registration', generation, signal, () => this.options.adapter.registerDevice(configuration, signal));\n }\n\n let relayError: unknown;\n try {\n await this.runStep('relay', generation, signal, () => this.options.adapter.ensureRelay(configuration, signal));\n } catch (error) {\n relayError = error;\n this.options.logWarning?.('Cloud relay maintenance failed', error);\n }\n\n await this.runStep('heartbeat', generation, signal, () => this.options.adapter.heartbeat(configuration, signal));\n\n let directoryError: unknown;\n try {\n await this.runStep('directory', generation, signal, () => this.options.adapter.syncDirectory(configuration, signal));\n } catch (error) {\n directoryError = error;\n this.options.logWarning?.('Cloud directory synchronization failed', error);\n }\n\n if (!this.isCurrent(generation, signal)) return;\n this.consecutiveFailures = 0;\n const relayRequired = this.options.adapter.relayRequiredForOnline(configuration);\n await this.updateSnapshot(generation, {\n status: directoryError || (relayRequired && relayError) ? 'degraded' : 'online',\n lastError: directoryError ?? relayError,\n nextRetryAt: this.now() + this.heartbeatIntervalMs,\n });\n this.schedule(this.heartbeatIntervalMs, generation);\n } catch (error) {\n if (!this.isCurrent(generation, signal)) return;\n this.consecutiveFailures += 1;\n if (this.snapshotValue.components.heartbeat === 'failed') {\n this.snapshotValue.components.registration = 'not-run';\n }\n const status = this.options.adapter.classifyError?.(error) ?? 'offline';\n const delay = this.backoffDelay();\n await this.updateSnapshot(generation, {\n status,\n lastError: error,\n nextRetryAt: this.now() + 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 await result?.commit?.();\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 backoffDelay(): number {\n const exponential = Math.min(\n this.maxBackoffMs,\n this.initialBackoffMs * 2 ** Math.max(0, this.consecutiveFailures - 1),\n );\n const jitter = exponential * this.jitterRatio * (this.random() * 2 - 1);\n return Math.max(0, Math.round(exponential + jitter));\n }\n\n private schedule(delayMs: number, generation: number): void {\n if (!this.started || generation !== this.generation) return;\n this.clearTimer();\n this.timer = setTimeout(() => {\n if (generation !== this.generation) return;\n void this.runNow().catch((error: unknown) => {\n this.options.logWarning?.('Cloud maintenance failed', error);\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 && !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) return;\n this.snapshotValue = {\n ...this.snapshotValue,\n components: { ...this.snapshotValue.components, [component]: status },\n };\n await 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) return;\n this.snapshotValue = { ...this.snapshotValue, ...update };\n await this.emit();\n }\n\n private resetSnapshot(): void {\n this.snapshotValue = {\n status: this.options.adapter.isConfigured(this.configuration)\n ? 'offline'\n : 'not-configured',\n generation: this.generation,\n components: emptyComponents(),\n };\n void this.emit();\n }\n\n private async emit(): Promise<void> {\n await this.options.onStatus?.(this.snapshot);\n }\n}\n","export 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: error instanceof Error ? error.message : String(error),\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 concatBytes(left: Uint8Array, right: Uint8Array): Uint8Array {\n if (left.byteLength === 0) return right.slice();\n if (right.byteLength === 0) return left;\n const combined = new Uint8Array(left.byteLength + right.byteLength);\n combined.set(left);\n combined.set(right, left.byteLength);\n return combined;\n}\n\nfunction abortedError(signal?: AbortSignal): JsonFrameError {\n return new JsonFrameError('ABORTED', 'JSON frame reading was aborted', {\n cause: signal?.reason,\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 = totalDeadline === undefined\n ? idleDeadline\n : Math.min(idleDeadline, totalDeadline);\n if (deadline <= now) {\n throw new JsonFrameError(\n totalDeadline !== undefined && totalDeadline <= idleDeadline ? 'TOTAL_TIMEOUT' : 'IDLE_TIMEOUT',\n totalDeadline !== undefined && totalDeadline <= idleDeadline\n ? 'JSON frame total timeout expired'\n : 'JSON frame idle timeout expired',\n );\n }\n\n return new Promise<IteratorResult<Uint8Array>>((resolve, reject) => {\n let settled = false;\n const finish = (callback: () => void) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n callback();\n };\n const onAbort = () => {\n finish(() => {\n reject(abortedError(signal));\n });\n };\n const timer = setTimeout(() => {\n const currentTime = Date.now();\n const totalExpired = totalDeadline !== undefined && currentTime >= totalDeadline;\n finish(() => {\n reject(\n new JsonFrameError(\n totalExpired ? 'TOTAL_TIMEOUT' : 'IDLE_TIMEOUT',\n totalExpired ? 'JSON frame total timeout expired' : 'JSON frame idle timeout expired',\n ),\n );\n });\n }, Math.max(1, deadline - now));\n signal?.addEventListener('abort', onAbort, { once: true });\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 let buffered: Uint8Array = new Uint8Array(0);\n let expectedPayloadBytes: number | undefined;\n let idleDeadline = Date.now() + options.idleTimeoutMs;\n let totalDeadline: number | undefined;\n let abortCalled = false;\n\n const abortOnce = async (error: JsonFrameError): Promise<void> => {\n if (abortCalled) return;\n abortCalled = true;\n await Promise.resolve(options.abort?.(error)).catch(() => undefined);\n };\n\n try {\n for (;;) {\n if (expectedPayloadBytes === undefined && buffered.byteLength >= HEADER_BYTES) {\n expectedPayloadBytes = new DataView(\n buffered.buffer,\n buffered.byteOffset,\n HEADER_BYTES,\n ).getUint32(0, false);\n buffered = buffered.slice(HEADER_BYTES);\n totalDeadline ??= Date.now() + options.totalTimeoutMs;\n if (expectedPayloadBytes > options.maxPayloadBytes) {\n throw new JsonFrameError(\n 'FRAME_TOO_LARGE',\n `JSON frame payload exceeds ${options.maxPayloadBytes} bytes`,\n );\n }\n }\n\n if (\n expectedPayloadBytes !== undefined &&\n buffered.byteLength >= expectedPayloadBytes\n ) {\n const payload = buffered.slice(0, expectedPayloadBytes);\n buffered = buffered.slice(expectedPayloadBytes);\n expectedPayloadBytes = undefined;\n totalDeadline = buffered.byteLength > 0\n ? Date.now() + options.totalTimeoutMs\n : undefined;\n let text: string;\n try {\n text = new TextDecoder('utf-8', { fatal: true }).decode(payload);\n } catch (error) {\n throw new JsonFrameError('INVALID_UTF8', 'JSON frame payload is not valid UTF-8', {\n cause: error,\n });\n }\n let value: unknown;\n try {\n value = 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 yield value;\n idleDeadline = Date.now() + options.idleTimeoutMs;\n continue;\n }\n\n const result = await readNextChunk(\n iterator,\n idleDeadline,\n totalDeadline,\n options.signal,\n );\n if (result.done) {\n if (buffered.byteLength > 0 || expectedPayloadBytes !== undefined) {\n throw new JsonFrameError('TRUNCATED_FRAME', 'JSON frame stream ended mid-frame');\n }\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 buffered = concatBytes(buffered, result.value);\n }\n } catch (error) {\n const frameError = error instanceof JsonFrameError\n ? error\n : new JsonFrameError('ABORTED', 'JSON frame source failed', { cause: error });\n await abortOnce(frameError);\n throw frameError;\n } finally {\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 void iterator.return?.().catch(() => undefined);\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 ) => 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(request: RemoteOrchestrationRequest): 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 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(options: DeviceOrchestrationTransportOptions): Promise<{\n stream: MemeLoopDuplexStream;\n grant: DeviceConnectionGrant | undefined;\n}> {\n const grant = await options.grantProvider?.(options.peerId);\n return {\n stream: await options.deviceNetwork.openStream(\n options.peerId,\n DEVICE_ORCHESTRATION_PROTOCOL,\n grant,\n ),\n grant,\n };\n}\n\nasync function writeRequest(\n stream: MemeLoopDuplexStream,\n request: RemoteOrchestrationRequest,\n grant: DeviceConnectionGrant | undefined,\n maxFrameBytes: number,\n): Promise<void> {\n const envelope: DeviceOrchestrationRequestEnvelope = {\n type: 'memeloop-device-orchestration-request-v2',\n request,\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 { stream, grant } = await openAuthenticatedStream(options);\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, 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);\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(stream, request, grant, maxFrameBytes);\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 let pending = iterator.next();\n try {\n for (;;) {\n const result = await Promise.race([\n pending.then((value) => ({ kind: 'value' as const, value })),\n new Promise<{ kind: 'bookmark' }>((resolve) => {\n const timer = setTimeout(() => {\n resolve({ kind: 'bookmark' });\n }, WATCH_BOOKMARK_INTERVAL_MS);\n signal.addEventListener('abort', () => {\n clearTimeout(timer);\n resolve({ kind: 'bookmark' });\n }, { once: true });\n }),\n ]);\n if (signal.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: String(Date.now()) },\n };\n continue;\n }\n if (result.value.done) return;\n yield result.value.value;\n pending = iterator.next();\n }\n } finally {\n void iterator.return?.();\n }\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 await stream.sink(encodeJsonFrames([await handler.request(request)], maxFrameBytes));\n }\n } finally {\n abort.abort();\n await stream.close().catch(() => undefined);\n }\n };\n}\n","import type { VersionVector } from '../sync/protocol.js';\n\nexport interface DeviceSyncStateStore {\n loadVersionVector(): Promise<VersionVector>;\n saveVersionVector(versionVector: VersionVector): Promise<void>;\n}\n\nexport class MemoryDeviceSyncStateStore implements DeviceSyncStateStore {\n private versionVector: VersionVector;\n\n constructor(initial: VersionVector = {}) {\n this.versionVector = { ...initial };\n }\n\n public async loadVersionVector(): Promise<VersionVector> {\n return { ...this.versionVector };\n }\n\n public async saveVersionVector(versionVector: VersionVector): Promise<void> {\n this.versionVector = { ...versionVector };\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 | 'exchangeVersionVector'\n | 'pullMissingMetadata'\n | 'pullMissingMessages'\n | 'pullAttachmentBlob';\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: string;\n };\n\nexport interface AttachmentBlobWire {\n dataBase64Url: string;\n filename: string;\n mimeType: string;\n size: number;\n}\n\nconst syncMethods = new Set<Libp2pSyncMethod>([\n 'exchangeVersionVector',\n 'pullMissingMetadata',\n 'pullMissingMessages',\n 'pullAttachmentBlob',\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 record.type === LIBP2P_SYNC_REQUEST_TYPE &&\n typeof record.id === 'string' &&\n typeof record.method === 'string' &&\n syncMethods.has(record.method as Libp2pSyncMethod)\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 (record.type !== LIBP2P_SYNC_RESPONSE_TYPE || typeof record.id !== 'string' || typeof record.ok !== 'boolean') return false;\n if (record.ok) return 'result' in record;\n return typeof record.error === 'string';\n}\n\nfunction isAttachmentBlobWire(value: unknown): value is AttachmentBlobWire {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n typeof record.dataBase64Url === 'string' &&\n typeof record.filename === 'string' &&\n typeof record.mimeType === 'string' &&\n typeof record.size === 'number'\n );\n}\n\nexport async function attachmentBlobFromWire(value: unknown): Promise<\n {\n data: Uint8Array;\n filename: string;\n mimeType: string;\n size: number;\n } | null\n> {\n if (value === null) return null;\n if (!isAttachmentBlobWire(value)) throw new Error('invalid_sync_response');\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_response');\n }\n return {\n data,\n filename: value.filename,\n mimeType: value.mimeType,\n size: value.size,\n };\n}\n","import type { ChatMessage } from '../conversation/index.js';\nimport type { ConversationMetadataPage, VersionVector } from '../sync/protocol.js';\nimport { createJsonFrameReader, encodeJsonFrames, JsonFrameError } from './jsonFrame.js';\nimport { attachmentBlobFromWire, isLibp2pSyncResponse, LIBP2P_SYNC_REQUEST_TYPE, type Libp2pSyncMethod, type Libp2pSyncRequest } from './libp2pSyncProtocol.js';\nimport type { AttachmentBlob, Device, DeviceConnectionGrant, DeviceNetworkService, DeviceSyncTransport, ExchangeVersionVectorResult } from './types.js';\n\nexport interface Libp2pDeviceSyncTransportOptions {\n nodeId: string;\n deviceNetwork: Pick<DeviceNetworkService, 'listDevices' | 'openStream'>;\n grantProvider?: (peerId: string) => Promise<DeviceConnectionGrant | undefined>;\n}\n\nexport class Libp2pDeviceSyncTransport implements DeviceSyncTransport {\n public readonly nodeId: string;\n private readonly deviceNetwork: Pick<DeviceNetworkService, 'listDevices' | 'openStream'>;\n private readonly grantProvider?: (peerId: string) => Promise<DeviceConnectionGrant | undefined>;\n\n constructor(options: Libp2pDeviceSyncTransportOptions) {\n this.nodeId = options.nodeId;\n this.deviceNetwork = options.deviceNetwork;\n this.grantProvider = options.grantProvider;\n }\n\n public listPeers(): Promise<Device[]> {\n return this.deviceNetwork.listDevices();\n }\n\n public exchangeVersionVector(peerId: string, localVersion: VersionVector): Promise<ExchangeVersionVectorResult> {\n return this.request(peerId, 'exchangeVersionVector', { localVersion }) as Promise<ExchangeVersionVectorResult>;\n }\n\n public pullMissingMetadata(\n peerId: string,\n sinceVersion: VersionVector,\n cursor?: string,\n ): Promise<ConversationMetadataPage> {\n return this.request(peerId, 'pullMissingMetadata', {\n sinceVersion,\n cursor,\n }) as Promise<ConversationMetadataPage>;\n }\n\n public pullMissingMessages(peerId: string, conversationId: string, knownMessageIds: string[]): Promise<ChatMessage[]> {\n return this.request(peerId, 'pullMissingMessages', { conversationId, knownMessageIds }) as Promise<ChatMessage[]>;\n }\n\n public async pullAttachmentBlob(peerId: string, contentHash: string): Promise<AttachmentBlob | null> {\n const result = await this.request(peerId, 'pullAttachmentBlob', { contentHash });\n return attachmentBlobFromWire(result);\n }\n\n private async request(peerId: string, method: Libp2pSyncMethod, parameters: unknown): Promise<unknown> {\n const grant = await this.grantProvider?.(peerId);\n const stream = await this.deviceNetwork.openStream(peerId, '/memeloop/sync/2.0.0', grant);\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 abort: async (error) => stream.abort(error),\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);\n return response.result;\n } catch (error) {\n if (error instanceof JsonFrameError) await stream.abort(error);\n throw error;\n } finally {\n await stream.close().catch(() => undefined);\n }\n }\n}\n","import 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: string;\n };\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 record.type === LIBP2P_RPC_REQUEST_TYPE &&\n typeof record.id === 'string' &&\n typeof record.method === 'string'\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 (record.type !== LIBP2P_RPC_RESPONSE_TYPE || typeof record.id !== 'string' || typeof record.ok !== 'boolean') return false;\n if (record.ok) return 'result' in record;\n return typeof record.error === 'string';\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) return false;\n if (input.protocol === PAIRING_PROTOCOL) return this.allowPairingProtocol;\n return record !== undefined;\n }\n}\n","import 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;\nconst MAX_INVITE_LENGTH = 16 * 1024;\nconst MAX_ADDRESSES = 8;\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 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 finalPeerId(address: string): string | undefined {\n const parts = address.split('/');\n for (let index = parts.length - 2; index >= 0; index -= 1) {\n if (parts[index] === 'p2p') return parts[index + 1];\n }\n return undefined;\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) =>\n address.length > 2048 ||\n !address.startsWith('/') ||\n (!address.includes('/ws') && !address.includes('/wss')) ||\n finalPeerId(address) !== peerId\n )\n ) {\n throw new Error('device pairing invite requires PeerId-bound WebSocket multiaddrs');\n }\n return unique;\n}\n\nfunction validateLifetime(createdAt: number, expiresAt: number, now: number): void {\n if (\n !Number.isSafeInteger(createdAt) ||\n !Number.isSafeInteger(expiresAt) ||\n expiresAt <= createdAt ||\n expiresAt - createdAt > DEVICE_PAIRING_INVITE_TTL_MS\n ) {\n throw new Error('invalid device pairing invite lifetime');\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 const canonical = [\n DEVICE_PAIRING_INVITE_PROTOCOL,\n `peerId=${payload.peerId}`,\n `publicKey=${payload.publicKeyMultibase}`,\n `deviceName=${payload.deviceName}`,\n `multiaddrs=${payload.multiaddrs.join(',')}`,\n `createdAt=${payload.createdAt}`,\n `expiresAt=${payload.expiresAt}`,\n ].join('\\n');\n return new TextEncoder().encode(canonical);\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 - 1);\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 JSON.stringify({ ...payload, signature });\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 if (\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","/**\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 { AttachmentReference, ChatMessage } from '../conversation/index.js';\nimport { type DeviceSyncStateStore, MemoryDeviceSyncStateStore } from '../device-network/deviceSyncStateStore.js';\nimport type { ConversationMetadataPage, VersionRange, VersionVector } from './protocol.js';\n\nimport type { IAgentStorage } from '../types.js';\n\nexport interface ChatSyncPeer {\n nodeId: string;\n /**\n * 取远端当前的 versionVector,并返回对方缺失的会话元数据。\n */\n exchangeVersionVector(localVersion: Record<string, number>): Promise<{\n remoteVersion: Record<string, number>;\n missingForRemote: VersionRange[];\n missingForLocal: VersionRange[];\n }>;\n\n /**\n * 将本地缺失的 metadata 从该 peer 拉回来。\n */\n pullMissingMetadata(\n sinceVersion: Record<string, number>,\n cursor?: string,\n ): Promise<ConversationMetadataPage>;\n\n /**\n * 按需拉取消息正文(TidGi / 审查单 Phase 4:消息级同步)。\n * 返回远端有而本地 unknownMessageIds 之外的新消息。\n */\n pullMissingMessages?(conversationId: string, knownMessageIds: string[]): Promise<ChatMessage[]>;\n\n /**\n * 按 contentHash 拉取附件二进制(与 `ChatMessage.attachments` / `AttachmentRef` 对齐)。\n * 典型实现:对 peer 发 `memeloop.storage.getAttachmentBlob` RPC。\n */\n pullAttachmentBlob?(\n contentHash: string,\n ): Promise<{ data: Uint8Array; filename: string; mimeType: string; size: number } | null>;\n}\n\nexport interface ChatSyncEngineOptions {\n nodeId: string;\n storage: IAgentStorage;\n peers: () => ChatSyncPeer[];\n stateStore?: DeviceSyncStateStore;\n}\n\nexport class ChatSyncEngine {\n private readonly nodeId: string;\n private readonly storage: IAgentStorage;\n private readonly getPeers: () => ChatSyncPeer[];\n private readonly stateStore: DeviceSyncStateStore;\n private versionVector: VersionVector = {};\n private loadStatePromise?: Promise<void>;\n private stateMutation: Promise<void> = Promise.resolve();\n\n constructor(options: ChatSyncEngineOptions) {\n this.nodeId = options.nodeId;\n this.storage = options.storage;\n this.getPeers = options.peers;\n this.stateStore = options.stateStore ?? new MemoryDeviceSyncStateStore();\n }\n\n /**\n * 在本节点新产生一条消息时调用,增加本节点的 lamportClock。\n */\n public bumpLocalVersion(): Promise<number> {\n let nextClock = 0;\n const mutation = this.stateMutation.then(async () => {\n await this.ensureStateLoaded();\n nextClock = (this.versionVector[this.nodeId] ?? 0) + 1;\n this.versionVector[this.nodeId] = nextClock;\n await this.stateStore.saveVersionVector(this.versionVector);\n });\n this.stateMutation = mutation.catch(() => undefined);\n return mutation.then(() => nextClock);\n }\n\n /**\n * 执行一次与所有 peer 的增量同步(metadata 级别),并尽力拉取缺失消息。\n */\n public async syncOnce(): Promise<void> {\n await this.ensureStateLoaded();\n await this.stateMutation;\n await this.reconcileVersionVectorFromStorage();\n const peers = this.getPeers();\n if (peers.length === 0) return;\n\n const pulledConversations = new Set<string>();\n\n for (const peer of peers) {\n const { remoteVersion } = await peer.exchangeVersionVector({ ...this.versionVector });\n\n let cursor: string | undefined;\n do {\n const page = await peer.pullMissingMetadata(this.versionVector, cursor);\n for (const meta of page.items) {\n await this.storage.upsertConversationMetadata(meta);\n pulledConversations.add(meta.conversationId);\n }\n cursor = page.nextCursor;\n } while (cursor !== undefined);\n\n for (const [nodeId, clock] of Object.entries(remoteVersion)) {\n const current = this.versionVector[nodeId] ?? 0;\n if (clock > current) this.versionVector[nodeId] = clock;\n }\n await this.stateStore.saveVersionVector(this.versionVector);\n }\n\n const pageSize = 100;\n let offset = 0;\n for (;;) {\n const conversations = await this.storage.listConversations({ limit: pageSize, offset });\n for (const conversation of conversations) {\n pulledConversations.add(conversation.conversationId);\n }\n if (conversations.length < pageSize) break;\n offset += conversations.length;\n }\n\n for (const conversationId of pulledConversations) {\n await this.pullMessagesForConversationFromPeers(conversationId, peers);\n }\n }\n\n /**\n * Anti-entropy:先 syncOnce,再对已知会话逐个向各 peer 拉取缺失消息(参考审查单「定期对账」)。\n */\n public async antiEntropyOnce(): Promise<void> {\n await this.syncOnce();\n }\n\n private async pullMessagesForConversationFromPeers(\n conversationId: string,\n peers: ChatSyncPeer[],\n ): Promise<void> {\n const localMsgs = await this.storage.getMessages(conversationId, { mode: 'full-content' });\n const knownIds = localMsgs.map((m) => m.messageId);\n\n for (const peer of peers) {\n if (!peer.pullMissingMessages) continue;\n try {\n const incoming = await peer.pullMissingMessages(conversationId, knownIds);\n if (incoming.length > 0) {\n await this.storage.insertMessagesIfAbsent(incoming);\n await this.ensureAttachmentsFromMessages(incoming, peers);\n }\n } catch {\n /* 单 peer 失败不阻塞 */\n }\n }\n }\n\n /** 从消息元数据收集 `attachments[].contentHash`,对本地缺失 BLOB 的哈希向各 peer 拉取并 `saveAttachment`。 */\n private async ensureAttachmentsFromMessages(\n messages: ChatMessage[],\n peers: ChatSyncPeer[],\n ): Promise<void> {\n const hashes = new Set<string>();\n for (const m of messages) {\n for (const a of m.attachments ?? []) {\n if (a.contentHash) hashes.add(a.contentHash);\n }\n }\n for (const h of hashes) {\n const reference = await this.storage.getAttachment(h);\n if (reference) {\n const reader = this.storage.readAttachmentData?.bind(this.storage);\n if (!reader) continue;\n const bytes = await reader(h);\n if (bytes && bytes.length > 0) continue;\n }\n\n for (const peer of peers) {\n const pull = peer.pullAttachmentBlob?.bind(peer);\n if (!pull) continue;\n try {\n const blob = await pull(h);\n if (blob?.data?.length) {\n const ar: AttachmentReference = {\n contentHash: h,\n filename: blob.filename,\n mimeType: blob.mimeType,\n size: blob.size > 0 ? blob.size : blob.data.length,\n };\n await this.storage.saveAttachment(ar, blob.data);\n break;\n }\n } catch {\n /* try next peer */\n }\n }\n }\n }\n\n public async getVersionVector(): Promise<Record<string, number>> {\n await this.ensureStateLoaded();\n await this.stateMutation;\n return { ...this.versionVector };\n }\n\n public getStorage(): IAgentStorage {\n return this.storage;\n }\n\n private ensureStateLoaded(): Promise<void> {\n this.loadStatePromise ??= (async () => {\n const stored = await this.stateStore.loadVersionVector();\n this.versionVector = { ...stored, [this.nodeId]: stored[this.nodeId] ?? 0 };\n })();\n return this.loadStatePromise;\n }\n\n private async reconcileVersionVectorFromStorage(): Promise<void> {\n const pageSize = 100;\n let offset = 0;\n let changed = false;\n for (;;) {\n const conversations = await this.storage.listConversations({ limit: pageSize, offset });\n for (const conversation of conversations) {\n const current = this.versionVector[conversation.originNodeId] ?? 0;\n if (conversation.originClock > current) {\n this.versionVector[conversation.originNodeId] = conversation.originClock;\n changed = true;\n }\n }\n if (conversations.length < pageSize) break;\n offset += conversations.length;\n }\n if (changed) await this.stateStore.saveVersionVector(this.versionVector);\n }\n}\n","import type { ChatMessage } from '../conversation/index.js';\nimport type { ConversationMetadataPage, VersionRange } from './protocol.js';\n\nimport type { ChatSyncPeer } from './chatSyncEngine.js';\n\nexport interface PeerNodeTransport {\n nodeId: string;\n exchangeVersionVector(\n targetNodeId: string,\n localVersion: Record<string, number>,\n ): Promise<{\n remoteVersion: Record<string, number>;\n missingForRemote: VersionRange[];\n missingForLocal: VersionRange[];\n }>;\n pullMissingMetadata(\n targetNodeId: string,\n sinceVersion: Record<string, number>,\n cursor?: string,\n ): Promise<ConversationMetadataPage>;\n pullMissingMessages?(\n targetNodeId: string,\n conversationId: string,\n knownMessageIds: string[],\n ): Promise<ChatMessage[]>;\n\n /** 从指定节点拉取附件 BLOB(如 `memeloop.storage.getAttachmentBlob`)。 */\n pullAttachmentBlob?(\n targetNodeId: string,\n contentHash: string,\n ): Promise<{ data: Uint8Array; filename: string; mimeType: string; size: number } | null>;\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 exchangeVersionVector(localVersion: Record<string, number>) {\n return this.transport.exchangeVersionVector(this.nodeId, localVersion);\n }\n\n pullMissingMetadata(sinceVersion: Record<string, number>, cursor?: string) {\n return this.transport.pullMissingMetadata(this.nodeId, sinceVersion, cursor);\n }\n\n pullMissingMessages(conversationId: string, knownMessageIds: string[]): Promise<ChatMessage[]> {\n const function_ = this.transport.pullMissingMessages?.bind(this.transport);\n if (!function_) {\n return Promise.resolve([]);\n }\n return function_(this.nodeId, conversationId, knownMessageIds);\n }\n\n pullAttachmentBlob(contentHash: string) {\n const function_ = this.transport.pullAttachmentBlob?.bind(this.transport);\n if (!function_) {\n return Promise.resolve(null);\n }\n return function_(this.nodeId, contentHash);\n }\n}\n","export type VersionVector = Record<string, number>;\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 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 [originNodeId, availableClock] of Object.entries(availableVersion)) {\n const currentClock = currentVersion[originNodeId] ?? 0;\n if (availableClock > currentClock) {\n ranges.push({ originNodeId, fromExclusive: currentClock, toInclusive: availableClock });\n }\n }\n return ranges.sort((left, right) => left.originNodeId.localeCompare(right.originNodeId));\n}\n\nexport interface ConversationMetadataPage {\n items: ConversationMeta[];\n nextCursor?: string;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/device-network-portable.ts","../src/device-network/deviceCloudConnectionCoordinator.ts","../src/orchestration/errors.ts","../src/device-network/jsonFrame.ts","../src/device-network/deviceOrchestrationTransport.ts","../src/device-network/deviceSyncStateStore.ts","../src/device-network/libp2pSyncProtocol.ts","../src/device-network/libp2pDeviceSyncTransport.ts","../src/device-network/libp2pRpcProtocol.ts","../src/device-network/localTrustDeviceAuthorizer.ts","../src/device-network/pairingInvite.ts","../src/sync/attachmentRpcCodec.ts","../src/sync/chatSyncEngine.ts","../src/sync/peerNodeAdapter.ts","../src/sync/protocol.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 * from './device-network/deviceCloudConnectionCoordinator.js';\nexport * from './device-network/deviceOrchestrationTransport.js';\nexport * from './device-network/deviceSyncStateStore.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/pairingInvite.js';\nexport * from './device-network/types.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","export 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 interface DeviceCloudConnectionSnapshot {\n status: DeviceCloudConnectionStatus;\n generation: number;\n components: Record<DeviceCloudConnectionComponent, DeviceCloudComponentStatus>;\n lastError?: unknown;\n nextRetryAt?: number;\n}\n\n/**\n * A step performs remote or otherwise reversible work first. Durable host\n * state must only be changed by commit(), which the coordinator invokes after\n * confirming that the configuration generation is still current.\n */\nexport interface DeviceCloudStepResult {\n commit?: () => 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 classifyError?(error: unknown): 'offline' | 'error';\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 now?: () => number;\n random?: () => number;\n onStatus?: (snapshot: DeviceCloudConnectionSnapshot) => void | Promise<void>;\n logWarning?: (message: string, error: unknown) => 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;\n\nfunction emptyComponents(): DeviceCloudConnectionSnapshot['components'] {\n return {\n authorizer: 'not-run',\n registration: 'not-run',\n relay: 'not-run',\n heartbeat: 'not-run',\n directory: 'not-run',\n };\n}\n\nfunction assertNonNegativeFinite(value: number, name: string): void {\n if (!Number.isFinite(value) || value < 0) {\n throw new TypeError(`${name} must be a finite non-negative number`);\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 generation = 0;\n private controller = new AbortController();\n private timer?: ReturnType<typeof setTimeout>;\n private inFlight?: Promise<void>;\n private started = false;\n private consecutiveFailures = 0;\n private snapshotValue: DeviceCloudConnectionSnapshot = {\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 now: () => number;\n private readonly random: () => number;\n\n constructor(private readonly options: DeviceCloudConnectionCoordinatorOptions<Configuration>) {\n this.configuration = 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.now = options.now ?? Date.now;\n this.random = options.random ?? Math.random;\n assertNonNegativeFinite(this.heartbeatIntervalMs, 'heartbeatIntervalMs');\n assertNonNegativeFinite(this.initialBackoffMs, 'initialBackoffMs');\n assertNonNegativeFinite(this.maxBackoffMs, 'maxBackoffMs');\n assertNonNegativeFinite(this.jitterRatio, 'jitterRatio');\n if (this.jitterRatio > 1) throw new TypeError('jitterRatio must not exceed 1');\n this.resetSnapshot();\n }\n\n public get snapshot(): DeviceCloudConnectionSnapshot {\n return {\n ...this.snapshotValue,\n components: { ...this.snapshotValue.components },\n };\n }\n\n public async start(): Promise<void> {\n if (this.started) return this.runNow();\n this.started = true;\n await this.runNow();\n }\n\n public async stop(): Promise<void> {\n this.started = false;\n this.clearTimer();\n const stoppedController = this.controller;\n stoppedController.abort(new Error('device cloud coordinator stopped'));\n await this.inFlight?.catch(() => undefined);\n if (this.controller === stoppedController) {\n this.controller = new AbortController();\n }\n }\n\n public async setConfiguration(configuration: Configuration | undefined): Promise<void> {\n this.configuration = configuration;\n this.generation += 1;\n this.consecutiveFailures = 0;\n this.clearTimer();\n this.controller.abort(new Error('device cloud configuration changed'));\n this.controller = new AbortController();\n this.inFlight = undefined;\n this.resetSnapshot();\n if (this.started && this.options.adapter.isConfigured(configuration)) await this.runNow();\n }\n\n public runNow(): 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 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 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 try {\n if (this.snapshotValue.components.authorizer !== 'ready') {\n await this.runStep('authorizer', generation, signal, () => this.options.adapter.ensureAuthorizer(configuration, signal));\n }\n if (this.snapshotValue.components.registration !== 'ready') {\n await this.runStep('registration', generation, signal, () => this.options.adapter.registerDevice(configuration, signal));\n }\n\n let relayError: unknown;\n try {\n await this.runStep('relay', generation, signal, () => this.options.adapter.ensureRelay(configuration, signal));\n } catch (error) {\n relayError = error;\n this.options.logWarning?.('Cloud relay maintenance failed', error);\n }\n\n await this.runStep('heartbeat', generation, signal, () => this.options.adapter.heartbeat(configuration, signal));\n\n let directoryError: unknown;\n try {\n await this.runStep('directory', generation, signal, () => this.options.adapter.syncDirectory(configuration, signal));\n } catch (error) {\n directoryError = error;\n this.options.logWarning?.('Cloud directory synchronization failed', error);\n }\n\n if (!this.isCurrent(generation, signal)) return;\n this.consecutiveFailures = 0;\n const relayRequired = this.options.adapter.relayRequiredForOnline(configuration);\n await this.updateSnapshot(generation, {\n status: directoryError || (relayRequired && relayError) ? 'degraded' : 'online',\n lastError: directoryError ?? relayError,\n nextRetryAt: this.now() + this.heartbeatIntervalMs,\n });\n this.schedule(this.heartbeatIntervalMs, generation);\n } catch (error) {\n if (!this.isCurrent(generation, signal)) return;\n this.consecutiveFailures += 1;\n if (this.snapshotValue.components.heartbeat === 'failed') {\n this.snapshotValue.components.registration = 'not-run';\n }\n const status = this.options.adapter.classifyError?.(error) ?? 'offline';\n const delay = this.backoffDelay();\n await this.updateSnapshot(generation, {\n status,\n lastError: error,\n nextRetryAt: this.now() + 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 await result?.commit?.();\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 backoffDelay(): number {\n const exponential = Math.min(\n this.maxBackoffMs,\n this.initialBackoffMs * 2 ** Math.max(0, this.consecutiveFailures - 1),\n );\n const jitter = exponential * this.jitterRatio * (this.random() * 2 - 1);\n return Math.max(0, Math.round(exponential + jitter));\n }\n\n private schedule(delayMs: number, generation: number): void {\n if (!this.started || generation !== this.generation) return;\n this.clearTimer();\n this.timer = setTimeout(() => {\n if (generation !== this.generation) return;\n void this.runNow().catch((error: unknown) => {\n this.options.logWarning?.('Cloud maintenance failed', error);\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 && !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) return;\n this.snapshotValue = {\n ...this.snapshotValue,\n components: { ...this.snapshotValue.components, [component]: status },\n };\n await 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) return;\n this.snapshotValue = { ...this.snapshotValue, ...update };\n await this.emit();\n }\n\n private resetSnapshot(): void {\n this.snapshotValue = {\n status: this.options.adapter.isConfigured(this.configuration)\n ? 'offline'\n : 'not-configured',\n generation: this.generation,\n components: emptyComponents(),\n };\n void this.emit();\n }\n\n private async emit(): Promise<void> {\n await this.options.onStatus?.(this.snapshot);\n }\n}\n","export 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: error instanceof Error ? error.message : String(error),\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 concatBytes(left: Uint8Array, right: Uint8Array): Uint8Array {\n if (left.byteLength === 0) return right.slice();\n if (right.byteLength === 0) return left;\n const combined = new Uint8Array(left.byteLength + right.byteLength);\n combined.set(left);\n combined.set(right, left.byteLength);\n return combined;\n}\n\nfunction abortedError(signal?: AbortSignal): JsonFrameError {\n return new JsonFrameError('ABORTED', 'JSON frame reading was aborted', {\n cause: signal?.reason,\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 = totalDeadline === undefined\n ? idleDeadline\n : Math.min(idleDeadline, totalDeadline);\n if (deadline <= now) {\n throw new JsonFrameError(\n totalDeadline !== undefined && totalDeadline <= idleDeadline ? 'TOTAL_TIMEOUT' : 'IDLE_TIMEOUT',\n totalDeadline !== undefined && totalDeadline <= idleDeadline\n ? 'JSON frame total timeout expired'\n : 'JSON frame idle timeout expired',\n );\n }\n\n return new Promise<IteratorResult<Uint8Array>>((resolve, reject) => {\n let settled = false;\n const finish = (callback: () => void) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n callback();\n };\n const onAbort = () => {\n finish(() => {\n reject(abortedError(signal));\n });\n };\n const timer = setTimeout(() => {\n const currentTime = Date.now();\n const totalExpired = totalDeadline !== undefined && currentTime >= totalDeadline;\n finish(() => {\n reject(\n new JsonFrameError(\n totalExpired ? 'TOTAL_TIMEOUT' : 'IDLE_TIMEOUT',\n totalExpired ? 'JSON frame total timeout expired' : 'JSON frame idle timeout expired',\n ),\n );\n });\n }, Math.max(1, deadline - now));\n signal?.addEventListener('abort', onAbort, { once: true });\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 let buffered: Uint8Array = new Uint8Array(0);\n let expectedPayloadBytes: number | undefined;\n let idleDeadline = Date.now() + options.idleTimeoutMs;\n let totalDeadline: number | undefined;\n let abortCalled = false;\n\n const abortOnce = async (error: JsonFrameError): Promise<void> => {\n if (abortCalled) return;\n abortCalled = true;\n await Promise.resolve(options.abort?.(error)).catch(() => undefined);\n };\n\n try {\n for (;;) {\n if (expectedPayloadBytes === undefined && buffered.byteLength >= HEADER_BYTES) {\n expectedPayloadBytes = new DataView(\n buffered.buffer,\n buffered.byteOffset,\n HEADER_BYTES,\n ).getUint32(0, false);\n buffered = buffered.slice(HEADER_BYTES);\n totalDeadline ??= Date.now() + options.totalTimeoutMs;\n if (expectedPayloadBytes > options.maxPayloadBytes) {\n throw new JsonFrameError(\n 'FRAME_TOO_LARGE',\n `JSON frame payload exceeds ${options.maxPayloadBytes} bytes`,\n );\n }\n }\n\n if (\n expectedPayloadBytes !== undefined &&\n buffered.byteLength >= expectedPayloadBytes\n ) {\n const payload = buffered.slice(0, expectedPayloadBytes);\n buffered = buffered.slice(expectedPayloadBytes);\n expectedPayloadBytes = undefined;\n totalDeadline = buffered.byteLength > 0\n ? Date.now() + options.totalTimeoutMs\n : undefined;\n let text: string;\n try {\n text = new TextDecoder('utf-8', { fatal: true }).decode(payload);\n } catch (error) {\n throw new JsonFrameError('INVALID_UTF8', 'JSON frame payload is not valid UTF-8', {\n cause: error,\n });\n }\n let value: unknown;\n try {\n value = 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 yield value;\n idleDeadline = Date.now() + options.idleTimeoutMs;\n continue;\n }\n\n const result = await readNextChunk(\n iterator,\n idleDeadline,\n totalDeadline,\n options.signal,\n );\n if (result.done) {\n if (buffered.byteLength > 0 || expectedPayloadBytes !== undefined) {\n throw new JsonFrameError('TRUNCATED_FRAME', 'JSON frame stream ended mid-frame');\n }\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 buffered = concatBytes(buffered, result.value);\n }\n } catch (error) {\n const frameError = error instanceof JsonFrameError\n ? error\n : new JsonFrameError('ABORTED', 'JSON frame source failed', { cause: error });\n await abortOnce(frameError);\n throw frameError;\n } finally {\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 void iterator.return?.().catch(() => undefined);\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 ) => 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(request: RemoteOrchestrationRequest): 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 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(options: DeviceOrchestrationTransportOptions): Promise<{\n stream: MemeLoopDuplexStream;\n grant: DeviceConnectionGrant | undefined;\n}> {\n const grant = await options.grantProvider?.(options.peerId);\n return {\n stream: await options.deviceNetwork.openStream(\n options.peerId,\n DEVICE_ORCHESTRATION_PROTOCOL,\n grant,\n ),\n grant,\n };\n}\n\nasync function writeRequest(\n stream: MemeLoopDuplexStream,\n request: RemoteOrchestrationRequest,\n grant: DeviceConnectionGrant | undefined,\n maxFrameBytes: number,\n): Promise<void> {\n const envelope: DeviceOrchestrationRequestEnvelope = {\n type: 'memeloop-device-orchestration-request-v2',\n request,\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 { stream, grant } = await openAuthenticatedStream(options);\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, 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);\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(stream, request, grant, maxFrameBytes);\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 await stream.sink(encodeJsonFrames([await handler.request(request)], maxFrameBytes));\n }\n } finally {\n abort.abort();\n await stream.close().catch(() => undefined);\n }\n };\n}\n","import type { VersionVector } from '../sync/protocol.js';\n\nexport interface DeviceSyncStateStore {\n loadVersionVector(): Promise<VersionVector>;\n saveVersionVector(versionVector: VersionVector): Promise<void>;\n}\n\nexport class MemoryDeviceSyncStateStore implements DeviceSyncStateStore {\n private versionVector: VersionVector;\n\n constructor(initial: VersionVector = {}) {\n this.versionVector = { ...initial };\n }\n\n public async loadVersionVector(): Promise<VersionVector> {\n return { ...this.versionVector };\n }\n\n public async saveVersionVector(versionVector: VersionVector): Promise<void> {\n this.versionVector = { ...versionVector };\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 | 'exchangeVersionVector'\n | 'pullMissingMetadata'\n | 'pullMissingMessages'\n | 'pullAttachmentBlob';\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: string;\n };\n\nexport interface AttachmentBlobWire {\n dataBase64Url: string;\n filename: string;\n mimeType: string;\n size: number;\n}\n\nconst syncMethods = new Set<Libp2pSyncMethod>([\n 'exchangeVersionVector',\n 'pullMissingMetadata',\n 'pullMissingMessages',\n 'pullAttachmentBlob',\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 record.type === LIBP2P_SYNC_REQUEST_TYPE &&\n typeof record.id === 'string' &&\n typeof record.method === 'string' &&\n syncMethods.has(record.method as Libp2pSyncMethod)\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 (record.type !== LIBP2P_SYNC_RESPONSE_TYPE || typeof record.id !== 'string' || typeof record.ok !== 'boolean') return false;\n if (record.ok) return 'result' in record;\n return typeof record.error === 'string';\n}\n\nfunction isAttachmentBlobWire(value: unknown): value is AttachmentBlobWire {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;\n const record = value as Record<string, unknown>;\n return (\n typeof record.dataBase64Url === 'string' &&\n typeof record.filename === 'string' &&\n typeof record.mimeType === 'string' &&\n typeof record.size === 'number'\n );\n}\n\nexport async function attachmentBlobFromWire(value: unknown): Promise<\n {\n data: Uint8Array;\n filename: string;\n mimeType: string;\n size: number;\n } | null\n> {\n if (value === null) return null;\n if (!isAttachmentBlobWire(value)) throw new Error('invalid_sync_response');\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_response');\n }\n return {\n data,\n filename: value.filename,\n mimeType: value.mimeType,\n size: value.size,\n };\n}\n","import type { ChatMessage } from '../conversation/index.js';\nimport type { ConversationMetadataPage, VersionVector } from '../sync/protocol.js';\nimport { createJsonFrameReader, encodeJsonFrames, JsonFrameError } from './jsonFrame.js';\nimport { attachmentBlobFromWire, isLibp2pSyncResponse, LIBP2P_SYNC_REQUEST_TYPE, type Libp2pSyncMethod, type Libp2pSyncRequest } from './libp2pSyncProtocol.js';\nimport type { AttachmentBlob, Device, DeviceConnectionGrant, DeviceNetworkService, DeviceSyncTransport, ExchangeVersionVectorResult } from './types.js';\n\nexport interface Libp2pDeviceSyncTransportOptions {\n nodeId: string;\n deviceNetwork: Pick<DeviceNetworkService, 'listDevices' | 'openStream'>;\n grantProvider?: (peerId: string) => Promise<DeviceConnectionGrant | undefined>;\n}\n\nexport class Libp2pDeviceSyncTransport implements DeviceSyncTransport {\n public readonly nodeId: string;\n private readonly deviceNetwork: Pick<DeviceNetworkService, 'listDevices' | 'openStream'>;\n private readonly grantProvider?: (peerId: string) => Promise<DeviceConnectionGrant | undefined>;\n\n constructor(options: Libp2pDeviceSyncTransportOptions) {\n this.nodeId = options.nodeId;\n this.deviceNetwork = options.deviceNetwork;\n this.grantProvider = options.grantProvider;\n }\n\n public listPeers(): Promise<Device[]> {\n return this.deviceNetwork.listDevices();\n }\n\n public exchangeVersionVector(peerId: string, localVersion: VersionVector): Promise<ExchangeVersionVectorResult> {\n return this.request(peerId, 'exchangeVersionVector', { localVersion }) as Promise<ExchangeVersionVectorResult>;\n }\n\n public pullMissingMetadata(\n peerId: string,\n sinceVersion: VersionVector,\n cursor?: string,\n ): Promise<ConversationMetadataPage> {\n return this.request(peerId, 'pullMissingMetadata', {\n sinceVersion,\n cursor,\n }) as Promise<ConversationMetadataPage>;\n }\n\n public pullMissingMessages(peerId: string, conversationId: string, knownMessageIds: string[]): Promise<ChatMessage[]> {\n return this.request(peerId, 'pullMissingMessages', { conversationId, knownMessageIds }) as Promise<ChatMessage[]>;\n }\n\n public async pullAttachmentBlob(peerId: string, contentHash: string): Promise<AttachmentBlob | null> {\n const result = await this.request(peerId, 'pullAttachmentBlob', { contentHash });\n return attachmentBlobFromWire(result);\n }\n\n private async request(peerId: string, method: Libp2pSyncMethod, parameters: unknown): Promise<unknown> {\n const grant = await this.grantProvider?.(peerId);\n const stream = await this.deviceNetwork.openStream(peerId, '/memeloop/sync/2.0.0', grant);\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 abort: async (error) => stream.abort(error),\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);\n return response.result;\n } catch (error) {\n if (error instanceof JsonFrameError) await stream.abort(error);\n throw error;\n } finally {\n await stream.close().catch(() => undefined);\n }\n }\n}\n","import 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: string;\n };\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 record.type === LIBP2P_RPC_REQUEST_TYPE &&\n typeof record.id === 'string' &&\n typeof record.method === 'string'\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 (record.type !== LIBP2P_RPC_RESPONSE_TYPE || typeof record.id !== 'string' || typeof record.ok !== 'boolean') return false;\n if (record.ok) return 'result' in record;\n return typeof record.error === 'string';\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) return false;\n if (input.protocol === PAIRING_PROTOCOL) return this.allowPairingProtocol;\n return record !== undefined;\n }\n}\n","import 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;\nconst MAX_INVITE_LENGTH = 16 * 1024;\nconst MAX_ADDRESSES = 8;\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 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 finalPeerId(address: string): string | undefined {\n const parts = address.split('/');\n for (let index = parts.length - 2; index >= 0; index -= 1) {\n if (parts[index] === 'p2p') return parts[index + 1];\n }\n return undefined;\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) =>\n address.length > 2048 ||\n !address.startsWith('/') ||\n (!address.includes('/ws') && !address.includes('/wss')) ||\n finalPeerId(address) !== peerId\n )\n ) {\n throw new Error('device pairing invite requires PeerId-bound WebSocket multiaddrs');\n }\n return unique;\n}\n\nfunction validateLifetime(createdAt: number, expiresAt: number, now: number): void {\n if (\n !Number.isSafeInteger(createdAt) ||\n !Number.isSafeInteger(expiresAt) ||\n expiresAt <= createdAt ||\n expiresAt - createdAt > DEVICE_PAIRING_INVITE_TTL_MS\n ) {\n throw new Error('invalid device pairing invite lifetime');\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 const canonical = [\n DEVICE_PAIRING_INVITE_PROTOCOL,\n `peerId=${payload.peerId}`,\n `publicKey=${payload.publicKeyMultibase}`,\n `deviceName=${payload.deviceName}`,\n `multiaddrs=${payload.multiaddrs.join(',')}`,\n `createdAt=${payload.createdAt}`,\n `expiresAt=${payload.expiresAt}`,\n ].join('\\n');\n return new TextEncoder().encode(canonical);\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 - 1);\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 JSON.stringify({ ...payload, signature });\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 if (\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","/**\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 { AttachmentReference, ChatMessage } from '../conversation/index.js';\nimport { type DeviceSyncStateStore, MemoryDeviceSyncStateStore } from '../device-network/deviceSyncStateStore.js';\nimport type { ConversationMetadataPage, VersionRange, VersionVector } from './protocol.js';\n\nimport type { IAgentStorage } from '../types.js';\n\nexport interface ChatSyncPeer {\n nodeId: string;\n /**\n * 取远端当前的 versionVector,并返回对方缺失的会话元数据。\n */\n exchangeVersionVector(localVersion: Record<string, number>): Promise<{\n remoteVersion: Record<string, number>;\n missingForRemote: VersionRange[];\n missingForLocal: VersionRange[];\n }>;\n\n /**\n * 将本地缺失的 metadata 从该 peer 拉回来。\n */\n pullMissingMetadata(\n sinceVersion: Record<string, number>,\n cursor?: string,\n ): Promise<ConversationMetadataPage>;\n\n /**\n * 按需拉取消息正文(TidGi / 审查单 Phase 4:消息级同步)。\n * 返回远端有而本地 unknownMessageIds 之外的新消息。\n */\n pullMissingMessages?(conversationId: string, knownMessageIds: string[]): Promise<ChatMessage[]>;\n\n /**\n * 按 contentHash 拉取附件二进制(与 `ChatMessage.attachments` / `AttachmentRef` 对齐)。\n * 典型实现:对 peer 发 `memeloop.storage.getAttachmentBlob` RPC。\n */\n pullAttachmentBlob?(\n contentHash: string,\n ): Promise<{ data: Uint8Array; filename: string; mimeType: string; size: number } | null>;\n}\n\nexport interface ChatSyncEngineOptions {\n nodeId: string;\n storage: IAgentStorage;\n peers: () => ChatSyncPeer[];\n stateStore?: DeviceSyncStateStore;\n}\n\nexport class ChatSyncEngine {\n private readonly nodeId: string;\n private readonly storage: IAgentStorage;\n private readonly getPeers: () => ChatSyncPeer[];\n private readonly stateStore: DeviceSyncStateStore;\n private versionVector: VersionVector = {};\n private loadStatePromise?: Promise<void>;\n private stateMutation: Promise<void> = Promise.resolve();\n\n constructor(options: ChatSyncEngineOptions) {\n this.nodeId = options.nodeId;\n this.storage = options.storage;\n this.getPeers = options.peers;\n this.stateStore = options.stateStore ?? new MemoryDeviceSyncStateStore();\n }\n\n /**\n * 在本节点新产生一条消息时调用,增加本节点的 lamportClock。\n */\n public bumpLocalVersion(): Promise<number> {\n let nextClock = 0;\n const mutation = this.stateMutation.then(async () => {\n await this.ensureStateLoaded();\n nextClock = (this.versionVector[this.nodeId] ?? 0) + 1;\n this.versionVector[this.nodeId] = nextClock;\n await this.stateStore.saveVersionVector(this.versionVector);\n });\n this.stateMutation = mutation.catch(() => undefined);\n return mutation.then(() => nextClock);\n }\n\n /**\n * 执行一次与所有 peer 的增量同步(metadata 级别),并尽力拉取缺失消息。\n */\n public async syncOnce(): Promise<void> {\n await this.ensureStateLoaded();\n await this.stateMutation;\n await this.reconcileVersionVectorFromStorage();\n const peers = this.getPeers();\n if (peers.length === 0) return;\n\n const pulledConversations = new Set<string>();\n\n for (const peer of peers) {\n const { remoteVersion } = await peer.exchangeVersionVector({ ...this.versionVector });\n\n let cursor: string | undefined;\n do {\n const page = await peer.pullMissingMetadata(this.versionVector, cursor);\n for (const meta of page.items) {\n await this.storage.upsertConversationMetadata(meta);\n pulledConversations.add(meta.conversationId);\n }\n cursor = page.nextCursor;\n } while (cursor !== undefined);\n\n for (const [nodeId, clock] of Object.entries(remoteVersion)) {\n const current = this.versionVector[nodeId] ?? 0;\n if (clock > current) this.versionVector[nodeId] = clock;\n }\n await this.stateStore.saveVersionVector(this.versionVector);\n }\n\n const pageSize = 100;\n let offset = 0;\n for (;;) {\n const conversations = await this.storage.listConversations({ limit: pageSize, offset });\n for (const conversation of conversations) {\n pulledConversations.add(conversation.conversationId);\n }\n if (conversations.length < pageSize) break;\n offset += conversations.length;\n }\n\n for (const conversationId of pulledConversations) {\n await this.pullMessagesForConversationFromPeers(conversationId, peers);\n }\n }\n\n /**\n * Anti-entropy:先 syncOnce,再对已知会话逐个向各 peer 拉取缺失消息(参考审查单「定期对账」)。\n */\n public async antiEntropyOnce(): Promise<void> {\n await this.syncOnce();\n }\n\n private async pullMessagesForConversationFromPeers(\n conversationId: string,\n peers: ChatSyncPeer[],\n ): Promise<void> {\n const localMsgs = await this.storage.getMessages(conversationId, { mode: 'full-content' });\n const knownIds = localMsgs.map((m) => m.messageId);\n\n for (const peer of peers) {\n if (!peer.pullMissingMessages) continue;\n try {\n const incoming = await peer.pullMissingMessages(conversationId, knownIds);\n if (incoming.length > 0) {\n await this.storage.insertMessagesIfAbsent(incoming);\n await this.ensureAttachmentsFromMessages(incoming, peers);\n }\n } catch {\n /* 单 peer 失败不阻塞 */\n }\n }\n }\n\n /** 从消息元数据收集 `attachments[].contentHash`,对本地缺失 BLOB 的哈希向各 peer 拉取并 `saveAttachment`。 */\n private async ensureAttachmentsFromMessages(\n messages: ChatMessage[],\n peers: ChatSyncPeer[],\n ): Promise<void> {\n const hashes = new Set<string>();\n for (const m of messages) {\n for (const a of m.attachments ?? []) {\n if (a.contentHash) hashes.add(a.contentHash);\n }\n }\n for (const h of hashes) {\n const reference = await this.storage.getAttachment(h);\n if (reference) {\n const reader = this.storage.readAttachmentData?.bind(this.storage);\n if (!reader) continue;\n const bytes = await reader(h);\n if (bytes && bytes.length > 0) continue;\n }\n\n for (const peer of peers) {\n const pull = peer.pullAttachmentBlob?.bind(peer);\n if (!pull) continue;\n try {\n const blob = await pull(h);\n if (blob?.data?.length) {\n const ar: AttachmentReference = {\n contentHash: h,\n filename: blob.filename,\n mimeType: blob.mimeType,\n size: blob.size > 0 ? blob.size : blob.data.length,\n };\n await this.storage.saveAttachment(ar, blob.data);\n break;\n }\n } catch {\n /* try next peer */\n }\n }\n }\n }\n\n public async getVersionVector(): Promise<Record<string, number>> {\n await this.ensureStateLoaded();\n await this.stateMutation;\n return { ...this.versionVector };\n }\n\n public getStorage(): IAgentStorage {\n return this.storage;\n }\n\n private ensureStateLoaded(): Promise<void> {\n this.loadStatePromise ??= (async () => {\n const stored = await this.stateStore.loadVersionVector();\n this.versionVector = { ...stored, [this.nodeId]: stored[this.nodeId] ?? 0 };\n })();\n return this.loadStatePromise;\n }\n\n private async reconcileVersionVectorFromStorage(): Promise<void> {\n const pageSize = 100;\n let offset = 0;\n let changed = false;\n for (;;) {\n const conversations = await this.storage.listConversations({ limit: pageSize, offset });\n for (const conversation of conversations) {\n const current = this.versionVector[conversation.originNodeId] ?? 0;\n if (conversation.originClock > current) {\n this.versionVector[conversation.originNodeId] = conversation.originClock;\n changed = true;\n }\n }\n if (conversations.length < pageSize) break;\n offset += conversations.length;\n }\n if (changed) await this.stateStore.saveVersionVector(this.versionVector);\n }\n}\n","import type { ChatMessage } from '../conversation/index.js';\nimport type { ConversationMetadataPage, VersionRange } from './protocol.js';\n\nimport type { ChatSyncPeer } from './chatSyncEngine.js';\n\nexport interface PeerNodeTransport {\n nodeId: string;\n exchangeVersionVector(\n targetNodeId: string,\n localVersion: Record<string, number>,\n ): Promise<{\n remoteVersion: Record<string, number>;\n missingForRemote: VersionRange[];\n missingForLocal: VersionRange[];\n }>;\n pullMissingMetadata(\n targetNodeId: string,\n sinceVersion: Record<string, number>,\n cursor?: string,\n ): Promise<ConversationMetadataPage>;\n pullMissingMessages?(\n targetNodeId: string,\n conversationId: string,\n knownMessageIds: string[],\n ): Promise<ChatMessage[]>;\n\n /** 从指定节点拉取附件 BLOB(如 `memeloop.storage.getAttachmentBlob`)。 */\n pullAttachmentBlob?(\n targetNodeId: string,\n contentHash: string,\n ): Promise<{ data: Uint8Array; filename: string; mimeType: string; size: number } | null>;\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 exchangeVersionVector(localVersion: Record<string, number>) {\n return this.transport.exchangeVersionVector(this.nodeId, localVersion);\n }\n\n pullMissingMetadata(sinceVersion: Record<string, number>, cursor?: string) {\n return this.transport.pullMissingMetadata(this.nodeId, sinceVersion, cursor);\n }\n\n pullMissingMessages(conversationId: string, knownMessageIds: string[]): Promise<ChatMessage[]> {\n const function_ = this.transport.pullMissingMessages?.bind(this.transport);\n if (!function_) {\n return Promise.resolve([]);\n }\n return function_(this.nodeId, conversationId, knownMessageIds);\n }\n\n pullAttachmentBlob(contentHash: string) {\n const function_ = this.transport.pullAttachmentBlob?.bind(this.transport);\n if (!function_) {\n return Promise.resolve(null);\n }\n return function_(this.nodeId, contentHash);\n }\n}\n","export type VersionVector = Record<string, number>;\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 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 [originNodeId, availableClock] of Object.entries(availableVersion)) {\n const currentClock = currentVersion[originNodeId] ?? 0;\n if (availableClock > currentClock) {\n ranges.push({ originNodeId, fromExclusive: currentClock, toInclusive: availableClock });\n }\n }\n return ranges.sort((left, right) => left.originNodeId.localeCompare(right.originNodeId));\n}\n\nexport interface ConversationMetadataPage {\n items: ConversationMeta[];\n nextCursor?: string;\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,9 @@
1
- import { s as DeviceSyncStateStore } from './pairingInvite-DDx_-IAp.cjs';
2
- export { A as AttachmentBlobWire, C as CreateDevicePairingInviteOptions, D as DEVICE_ORCHESTRATION_PROTOCOL, a as DEVICE_PAIRING_INVITE_PROTOCOL, b as DEVICE_PAIRING_INVITE_TTL_MS, c as DeviceCloudComponentStatus, d as DeviceCloudConnectionAdapter, e as DeviceCloudConnectionComponent, f as DeviceCloudConnectionCoordinator, g as DeviceCloudConnectionCoordinatorOptions, h as DeviceCloudConnectionSnapshot, i as DeviceCloudConnectionStatus, j as DeviceCloudStepResult, k as DeviceOrchestrationStreamHandler, l as DeviceOrchestrationStreamHandlerInput, m as DeviceOrchestrationStreamHandlerOptions, n as DeviceOrchestrationTransportOptions, o as DevicePairingInvite, p as DevicePairingInviteIdentityVerifier, q as DevicePairingInviteIdentityVerifierInput, r as DevicePairingInviteUnsignedPayload, J as JsonFrameError, t as JsonFrameErrorCode, u as JsonFrameReaderOptions, L as LIBP2P_RPC_REQUEST_TYPE, v as LIBP2P_RPC_RESPONSE_TYPE, w as LIBP2P_SYNC_REQUEST_TYPE, x as LIBP2P_SYNC_RESPONSE_TYPE, y as Libp2pDeviceSyncTransport, z as Libp2pDeviceSyncTransportOptions, B as Libp2pRpcRequest, E as Libp2pRpcResponse, F as Libp2pSyncMethod, G as Libp2pSyncRequest, H as Libp2pSyncResponse, I as LocalTrustDeviceAuthorizer, K as LocalTrustDeviceAuthorizerOptions, M as MemoryDeviceSyncStateStore, P as ParseDevicePairingInviteOptions, R as RemoteOrchestrationHandler, N as attachmentBlobFromWire, O as canonicalDevicePairingInviteBytes, Q as createDeviceOrchestrationStreamHandler, S as createDeviceOrchestrationTransport, T as createDevicePairingInvite, U as createJsonFrameReader, V as encodeDevicePairingInvite, W as encodeJsonFrame, X as encodeJsonFrames, Y as isLibp2pRpcRequest, Z as isLibp2pRpcResponse, _ as isLibp2pSyncRequest, $ as isLibp2pSyncResponse, a0 as parseDevicePairingInvite } from './pairingInvite-DDx_-IAp.cjs';
1
+ import { s as DeviceSyncStateStore } from './pairingInvite-DENOiqa0.cjs';
2
+ export { A as AttachmentBlobWire, C as CreateDevicePairingInviteOptions, D as DEVICE_ORCHESTRATION_PROTOCOL, a as DEVICE_PAIRING_INVITE_PROTOCOL, b as DEVICE_PAIRING_INVITE_TTL_MS, c as DeviceCloudComponentStatus, d as DeviceCloudConnectionAdapter, e as DeviceCloudConnectionComponent, f as DeviceCloudConnectionCoordinator, g as DeviceCloudConnectionCoordinatorOptions, h as DeviceCloudConnectionSnapshot, i as DeviceCloudConnectionStatus, j as DeviceCloudStepResult, k as DeviceOrchestrationStreamHandler, l as DeviceOrchestrationStreamHandlerInput, m as DeviceOrchestrationStreamHandlerOptions, n as DeviceOrchestrationTransportOptions, o as DevicePairingInvite, p as DevicePairingInviteIdentityVerifier, q as DevicePairingInviteIdentityVerifierInput, r as DevicePairingInviteUnsignedPayload, J as JsonFrameError, t as JsonFrameErrorCode, u as JsonFrameReaderOptions, L as LIBP2P_RPC_REQUEST_TYPE, v as LIBP2P_RPC_RESPONSE_TYPE, w as LIBP2P_SYNC_REQUEST_TYPE, x as LIBP2P_SYNC_RESPONSE_TYPE, y as Libp2pDeviceSyncTransport, z as Libp2pDeviceSyncTransportOptions, B as Libp2pRpcRequest, E as Libp2pRpcResponse, F as Libp2pSyncMethod, G as Libp2pSyncRequest, H as Libp2pSyncResponse, I as LocalTrustDeviceAuthorizer, K as LocalTrustDeviceAuthorizerOptions, M as MemoryDeviceSyncStateStore, P as ParseDevicePairingInviteOptions, R as RemoteOrchestrationHandler, N as attachmentBlobFromWire, O as canonicalDevicePairingInviteBytes, Q as createDeviceOrchestrationStreamHandler, S as createDeviceOrchestrationTransport, T as createDevicePairingInvite, U as createJsonFrameReader, V as encodeDevicePairingInvite, W as encodeJsonFrame, X as encodeJsonFrames, Y as isLibp2pRpcRequest, Z as isLibp2pRpcResponse, _ as isLibp2pSyncRequest, $ as isLibp2pSyncResponse, a0 as parseDevicePairingInvite } from './pairingInvite-DENOiqa0.cjs';
3
3
  export { A as AgentExecutionLocation, a as AgentExecutionState, b as AttachmentBlob, C as CloudDeviceClient, c as CloudDeviceRecord, d as ConversationExecutionPlacement, D as Device, e as DeviceAccountBindingRequest, f as DeviceAuthorizer, g as DeviceCapabilities, h as DeviceConnectionGrant, i as DeviceConnectionGrantVerificationInput, j as DeviceNetworkListenOptions, k as DeviceNetworkPath, l as DeviceNetworkService, m as DevicePlatform, n as DeviceProtocolDirection, o as DeviceReachability, p as DeviceReachabilityState, q as DeviceRelayReservationToken, r as DeviceRelayReservationTokenVerificationInput, s as DeviceRpcHandler, t as DeviceRpcHandlerInput, u as DeviceSyncTransport, v as DeviceTrustMode, w as DeviceTrustStore, E as ExchangeVersionVectorResult, L as LocalDeviceIdentity, x as LocalPairingRequestOptions, M as MemeLoopDuplexStream, y as MemeLoopProtocol, P as PairingSession, z as PairingSessionDirection, B as PairingSessionStatus, S as SyncResult, T as TrustedDeviceRecord } from './types-C8gnhG9M.cjs';
4
4
  import { I as IAgentStorage, V as VersionRange, a as ConversationMetadataPage, e as ChatMessage } from './interface-3C3eG8Hn.cjs';
5
5
  export { C as ConversationMeta, b as VersionVector, c as computeMissingVersionRanges, i as isConversationMeta } from './interface-3C3eG8Hn.cjs';
6
- import './remoteClient-BKmQEQY9.cjs';
6
+ import './remoteClient-DFIyCZEv.cjs';
7
7
 
8
8
  /**
9
9
  * 将节点 RPC `memeloop.storage.getAttachmentBlob` 的返回值解码为同步引擎可用的 BLOB。
@@ -1,9 +1,9 @@
1
- import { s as DeviceSyncStateStore } from './pairingInvite-Dkz8CLsb.js';
2
- export { A as AttachmentBlobWire, C as CreateDevicePairingInviteOptions, D as DEVICE_ORCHESTRATION_PROTOCOL, a as DEVICE_PAIRING_INVITE_PROTOCOL, b as DEVICE_PAIRING_INVITE_TTL_MS, c as DeviceCloudComponentStatus, d as DeviceCloudConnectionAdapter, e as DeviceCloudConnectionComponent, f as DeviceCloudConnectionCoordinator, g as DeviceCloudConnectionCoordinatorOptions, h as DeviceCloudConnectionSnapshot, i as DeviceCloudConnectionStatus, j as DeviceCloudStepResult, k as DeviceOrchestrationStreamHandler, l as DeviceOrchestrationStreamHandlerInput, m as DeviceOrchestrationStreamHandlerOptions, n as DeviceOrchestrationTransportOptions, o as DevicePairingInvite, p as DevicePairingInviteIdentityVerifier, q as DevicePairingInviteIdentityVerifierInput, r as DevicePairingInviteUnsignedPayload, J as JsonFrameError, t as JsonFrameErrorCode, u as JsonFrameReaderOptions, L as LIBP2P_RPC_REQUEST_TYPE, v as LIBP2P_RPC_RESPONSE_TYPE, w as LIBP2P_SYNC_REQUEST_TYPE, x as LIBP2P_SYNC_RESPONSE_TYPE, y as Libp2pDeviceSyncTransport, z as Libp2pDeviceSyncTransportOptions, B as Libp2pRpcRequest, E as Libp2pRpcResponse, F as Libp2pSyncMethod, G as Libp2pSyncRequest, H as Libp2pSyncResponse, I as LocalTrustDeviceAuthorizer, K as LocalTrustDeviceAuthorizerOptions, M as MemoryDeviceSyncStateStore, P as ParseDevicePairingInviteOptions, R as RemoteOrchestrationHandler, N as attachmentBlobFromWire, O as canonicalDevicePairingInviteBytes, Q as createDeviceOrchestrationStreamHandler, S as createDeviceOrchestrationTransport, T as createDevicePairingInvite, U as createJsonFrameReader, V as encodeDevicePairingInvite, W as encodeJsonFrame, X as encodeJsonFrames, Y as isLibp2pRpcRequest, Z as isLibp2pRpcResponse, _ as isLibp2pSyncRequest, $ as isLibp2pSyncResponse, a0 as parseDevicePairingInvite } from './pairingInvite-Dkz8CLsb.js';
1
+ import { s as DeviceSyncStateStore } from './pairingInvite-DZy77i0p.js';
2
+ export { A as AttachmentBlobWire, C as CreateDevicePairingInviteOptions, D as DEVICE_ORCHESTRATION_PROTOCOL, a as DEVICE_PAIRING_INVITE_PROTOCOL, b as DEVICE_PAIRING_INVITE_TTL_MS, c as DeviceCloudComponentStatus, d as DeviceCloudConnectionAdapter, e as DeviceCloudConnectionComponent, f as DeviceCloudConnectionCoordinator, g as DeviceCloudConnectionCoordinatorOptions, h as DeviceCloudConnectionSnapshot, i as DeviceCloudConnectionStatus, j as DeviceCloudStepResult, k as DeviceOrchestrationStreamHandler, l as DeviceOrchestrationStreamHandlerInput, m as DeviceOrchestrationStreamHandlerOptions, n as DeviceOrchestrationTransportOptions, o as DevicePairingInvite, p as DevicePairingInviteIdentityVerifier, q as DevicePairingInviteIdentityVerifierInput, r as DevicePairingInviteUnsignedPayload, J as JsonFrameError, t as JsonFrameErrorCode, u as JsonFrameReaderOptions, L as LIBP2P_RPC_REQUEST_TYPE, v as LIBP2P_RPC_RESPONSE_TYPE, w as LIBP2P_SYNC_REQUEST_TYPE, x as LIBP2P_SYNC_RESPONSE_TYPE, y as Libp2pDeviceSyncTransport, z as Libp2pDeviceSyncTransportOptions, B as Libp2pRpcRequest, E as Libp2pRpcResponse, F as Libp2pSyncMethod, G as Libp2pSyncRequest, H as Libp2pSyncResponse, I as LocalTrustDeviceAuthorizer, K as LocalTrustDeviceAuthorizerOptions, M as MemoryDeviceSyncStateStore, P as ParseDevicePairingInviteOptions, R as RemoteOrchestrationHandler, N as attachmentBlobFromWire, O as canonicalDevicePairingInviteBytes, Q as createDeviceOrchestrationStreamHandler, S as createDeviceOrchestrationTransport, T as createDevicePairingInvite, U as createJsonFrameReader, V as encodeDevicePairingInvite, W as encodeJsonFrame, X as encodeJsonFrames, Y as isLibp2pRpcRequest, Z as isLibp2pRpcResponse, _ as isLibp2pSyncRequest, $ as isLibp2pSyncResponse, a0 as parseDevicePairingInvite } from './pairingInvite-DZy77i0p.js';
3
3
  export { A as AgentExecutionLocation, a as AgentExecutionState, b as AttachmentBlob, C as CloudDeviceClient, c as CloudDeviceRecord, d as ConversationExecutionPlacement, D as Device, e as DeviceAccountBindingRequest, f as DeviceAuthorizer, g as DeviceCapabilities, h as DeviceConnectionGrant, i as DeviceConnectionGrantVerificationInput, j as DeviceNetworkListenOptions, k as DeviceNetworkPath, l as DeviceNetworkService, m as DevicePlatform, n as DeviceProtocolDirection, o as DeviceReachability, p as DeviceReachabilityState, q as DeviceRelayReservationToken, r as DeviceRelayReservationTokenVerificationInput, s as DeviceRpcHandler, t as DeviceRpcHandlerInput, u as DeviceSyncTransport, v as DeviceTrustMode, w as DeviceTrustStore, E as ExchangeVersionVectorResult, L as LocalDeviceIdentity, x as LocalPairingRequestOptions, M as MemeLoopDuplexStream, y as MemeLoopProtocol, P as PairingSession, z as PairingSessionDirection, B as PairingSessionStatus, S as SyncResult, T as TrustedDeviceRecord } from './types-CcFFIk8W.js';
4
4
  import { I as IAgentStorage, V as VersionRange, a as ConversationMetadataPage, e as ChatMessage } from './interface-3C3eG8Hn.js';
5
5
  export { C as ConversationMeta, b as VersionVector, c as computeMissingVersionRanges, i as isConversationMeta } from './interface-3C3eG8Hn.js';
6
- import './remoteClient-D5hco6cS.js';
6
+ import './remoteClient-DwBCoHpc.js';
7
7
 
8
8
  /**
9
9
  * 将节点 RPC `memeloop.storage.getAttachmentBlob` 的返回值解码为同步引擎可用的 BLOB。
@@ -31,7 +31,7 @@ import {
31
31
  isLibp2pSyncRequest,
32
32
  isLibp2pSyncResponse,
33
33
  parseDevicePairingInvite
34
- } from "./chunk-ECNKBH5A.js";
34
+ } from "./chunk-E5R24U4I.js";
35
35
  import "./chunk-FWSY5HOA.js";
36
36
  export {
37
37
  ChatSyncEngine,