@agimon-ai/doompi-session 0.0.1-alpha.17 → 0.0.1-alpha.19

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.
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_sessionDelivery = require("../sessionDelivery-DNbpgU5C.cjs");
5
+ const require_sessionDelivery = require("../sessionDelivery-C_2qtUoE.cjs");
6
6
  const require_backgroundWorkService = require("../backgroundWorkService-BC0743Nn.cjs");
7
7
  let node_fs = require("node:fs");
8
8
  node_fs = require_sessionDelivery.__toESM(node_fs, 1);
@@ -1,5 +1,5 @@
1
1
  import { n as provideBackgroundWorkService } from "../backgroundWorkService-ChVXCzxj.mjs";
2
- import { a as createSessionGroupDeliveryAuthorizer, f as createSessionDirectory, g as parseSessionPeerEnvelope, h as parseRemoteSessionReference, m as createPeerReplayGuard, n as provideSessionDeliveryService, o as createSessionIntercom, p as createPeerCommunication, s as DOOM_SESSION_INTERCOM_SERVICE, u as createSessionGroupStore, v as peerSessionReference, x as verifyPeerRequest, y as readSessionPeerConfig } from "../sessionDelivery-C_rANfaY.mjs";
2
+ import { a as createSessionGroupDeliveryAuthorizer, f as createSessionDirectory, g as parseSessionPeerEnvelope, h as parseRemoteSessionReference, m as createPeerReplayGuard, n as provideSessionDeliveryService, o as createSessionIntercom, p as createPeerCommunication, s as DOOM_SESSION_INTERCOM_SERVICE, u as createSessionGroupStore, v as peerSessionReference, x as verifyPeerRequest, y as readSessionPeerConfig } from "../sessionDelivery-DNq4a8LB.mjs";
3
3
  import fs from "node:fs";
4
4
  import path from "node:path";
5
5
  import { composeRootHooks, defineRoot, defineRoute } from "@agimon-ai/doompi-core/extensionFile";
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sessionDelivery = require("./sessionDelivery-DNbpgU5C.cjs");
2
+ const require_sessionDelivery = require("./sessionDelivery-C_2qtUoE.cjs");
3
3
  const require_backgroundWorkService = require("./backgroundWorkService-BC0743Nn.cjs");
4
4
  exports.DOOM_SESSION_DELIVERY_SERVICE = require_sessionDelivery.DOOM_SESSION_DELIVERY_SERVICE;
5
5
  exports.DOOM_SESSION_INTERCOM_SERVICE = require_sessionDelivery.DOOM_SESSION_INTERCOM_SERVICE;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/services/backgroundWorkService/index.ts","../src/services/peerTransport/index.ts","../src/services/sessionDirectory/type.ts","../src/services/sessionDirectory/index.ts","../src/services/sessionGroups/type.ts","../src/services/sessionGroups/index.ts","../src/services/sessionDelivery/type.ts","../src/services/sessionDelivery/index.ts","../src/services/sessionIntercom/type.ts","../src/services/sessionIntercom/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/services/backgroundWorkService/index.ts","../src/services/peerTransport/index.ts","../src/services/sessionDirectory/type.ts","../src/services/sessionDirectory/index.ts","../src/services/sessionGroups/type.ts","../src/services/sessionGroups/index.ts","../src/services/sessionDelivery/type.ts","../src/services/sessionDelivery/index.ts","../src/services/sessionIntercom/type.ts","../src/services/sessionIntercom/index.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  import { n as provideBackgroundWorkService, t as createBackgroundWorkService } from "./backgroundWorkService-ChVXCzxj.mjs";
2
- import { _ as peerRequestHeaders, a as createSessionGroupDeliveryAuthorizer, b as sessionPeerConfigPath, c as readSessionIntercom, d as SessionGroupRevisionError, f as createSessionDirectory, h as parseRemoteSessionReference, i as readDoomSessionDelivery, l as requireSessionIntercom, m as createPeerReplayGuard, n as provideSessionDeliveryService, o as createSessionIntercom, p as createPeerCommunication, r as DOOM_SESSION_DELIVERY_SERVICE, s as DOOM_SESSION_INTERCOM_SERVICE, t as createSessionDeliveryService, u as createSessionGroupStore, v as peerSessionReference, x as verifyPeerRequest, y as readSessionPeerConfig } from "./sessionDelivery-C_rANfaY.mjs";
2
+ import { _ as peerRequestHeaders, a as createSessionGroupDeliveryAuthorizer, b as sessionPeerConfigPath, c as readSessionIntercom, d as SessionGroupRevisionError, f as createSessionDirectory, h as parseRemoteSessionReference, i as readDoomSessionDelivery, l as requireSessionIntercom, m as createPeerReplayGuard, n as provideSessionDeliveryService, o as createSessionIntercom, p as createPeerCommunication, r as DOOM_SESSION_DELIVERY_SERVICE, s as DOOM_SESSION_INTERCOM_SERVICE, t as createSessionDeliveryService, u as createSessionGroupStore, v as peerSessionReference, x as verifyPeerRequest, y as readSessionPeerConfig } from "./sessionDelivery-DNq4a8LB.mjs";
3
3
  export { DOOM_SESSION_DELIVERY_SERVICE, DOOM_SESSION_INTERCOM_SERVICE, SessionGroupRevisionError, createBackgroundWorkService, createPeerCommunication, createPeerReplayGuard, createSessionDeliveryService, createSessionDirectory, createSessionGroupDeliveryAuthorizer, createSessionGroupStore, createSessionIntercom, parseRemoteSessionReference, peerRequestHeaders, peerSessionReference, provideBackgroundWorkService, provideSessionDeliveryService, readDoomSessionDelivery, readSessionIntercom, readSessionPeerConfig, requireSessionIntercom, sessionPeerConfigPath, verifyPeerRequest };
@@ -685,10 +685,13 @@ function createSessionDeliveryService(options) {
685
685
  if (closed || !ack) return;
686
686
  database.prepare(`UPDATE session_delivery_outbox
687
687
  SET state = 'acknowledged', recipient_state = ?, acknowledged_at = ?
688
- WHERE delivery_id = ? AND recipient_key = ?`).run(ack.state, Date.now(), ack.deliveryId, recipientKey);
688
+ WHERE delivery_id = ? AND recipient_key = ?
689
+ AND (recipient_state IS NULL
690
+ OR (recipient_state = 'accepted' AND ? != 'accepted')
691
+ OR (recipient_state = 'admitting' AND ? IN ('admitted', 'recovery_required')))`).run(ack.state, Date.now(), ack.deliveryId, recipientKey, ack.state, ack.state);
689
692
  };
690
693
  const publishOutbox = (deliveryId) => {
691
- const row = database.prepare("SELECT * FROM session_delivery_outbox WHERE delivery_id = ? AND state = 'queued'").get(deliveryId);
694
+ const row = database.prepare("SELECT * FROM session_delivery_outbox WHERE delivery_id = ? AND (recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required'))").get(deliveryId);
692
695
  if (!row) return;
693
696
  const metadata = JSON.parse(row.metadata_json);
694
697
  if (!options.authorizePeer(row.recipient_key, metadata)) return;
@@ -701,10 +704,10 @@ function createSessionDeliveryService(options) {
701
704
  });
702
705
  };
703
706
  const publishQueued = (recipientKey) => {
704
- for (const row of database.prepare("SELECT delivery_id FROM session_delivery_outbox WHERE recipient_key = ? AND state = 'queued'").all(recipientKey)) publishOutbox(row.delivery_id);
707
+ for (const row of database.prepare("SELECT delivery_id FROM session_delivery_outbox WHERE recipient_key = ? AND (recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required'))").all(recipientKey)) publishOutbox(row.delivery_id);
705
708
  };
706
709
  const publishAllQueued = () => {
707
- for (const row of database.prepare("SELECT delivery_id FROM session_delivery_outbox WHERE state = 'queued'").all()) publishOutbox(row.delivery_id);
710
+ for (const row of database.prepare("SELECT delivery_id FROM session_delivery_outbox WHERE recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required')").all()) publishOutbox(row.delivery_id);
708
711
  };
709
712
  const releaseEnvelope = options.communication.subscribe(DELIVERY_EVENT, receiveEnvelope);
710
713
  const releaseAck = options.communication.subscribe(ACK_EVENT, receiveAck);
@@ -948,4 +951,4 @@ Object.defineProperty(exports, "verifyPeerRequest", {
948
951
  }
949
952
  });
950
953
 
951
- //# sourceMappingURL=sessionDelivery-DNbpgU5C.cjs.map
954
+ //# sourceMappingURL=sessionDelivery-C_2qtUoE.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessionDelivery-DNbpgU5C.cjs","names":["path","fs","createHash","createHmac","DatabaseSync","timingSafeEqual","envelopeOf","DatabaseSync","DatabaseSync"],"sources":["../src/services/peerTransport/index.ts","../src/services/sessionDirectory/index.ts","../src/services/sessionGroups/type.ts","../src/services/sessionGroups/index.ts","../src/services/sessionIntercom/type.ts","../src/services/sessionIntercom/index.ts","../src/services/sessionDelivery/type.ts","../src/services/sessionDelivery/index.ts"],"sourcesContent":["import { createHash, createHmac, timingSafeEqual } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\n\nimport type { DoomSessionCommunicationEndpoint } from '@agimon-ai/doompi-core/hubChannel';\n\nconst PEER_CONFIG_VERSION = 1;\nconst PEER_CONFIG_FILE = 'peers.json';\nconst PEER_ROUTE = '/api/plugins/session-peer/inbox';\nconst PEER_HEADER = 'x-doompi-session-peer';\nconst TIMESTAMP_HEADER = 'x-doompi-session-timestamp';\nconst SIGNATURE_HEADER = 'x-doompi-session-signature';\nconst MAX_CLOCK_SKEW_MS = 5 * 60_000;\nconst MAX_REPLAY_ENTRIES = 10_000;\nconst REPLAY_DATABASE_FILE = 'peer-replay.sqlite';\n\nexport interface SessionPeer {\n readonly hostId: string;\n readonly url: string;\n readonly secret: string;\n /** Explicit remote durable-message targets. Empty means no delivery grant. */\n readonly allowedSessionIds: readonly string[];\n /** Explicit remote Voice media targets. Empty means no media grant. */\n readonly allowedVoiceSessionIds: readonly string[];\n}\n\nexport interface SessionPeerConfig {\n readonly version: typeof PEER_CONFIG_VERSION;\n readonly hostId: string;\n readonly peers: readonly SessionPeer[];\n}\n\nexport interface RemoteSessionReference {\n readonly hostId: string;\n readonly sessionId: string;\n}\n\nexport interface SessionPeerEnvelope {\n readonly sourceSessionId: string;\n readonly targetSessionId: string;\n readonly type: string;\n readonly payload: unknown;\n}\n\nexport interface SessionPeerReplayGuard {\n admit(request: Request, now?: number): boolean;\n close(): void;\n}\n\nfunction validId(value: unknown): value is string {\n return typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(value);\n}\n\nfunction peerOf(value: unknown): SessionPeer | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n if (!validId(record.hostId) || typeof record.url !== 'string' || typeof record.secret !== 'string') return undefined;\n let url: URL;\n try {\n url = new URL(record.url);\n } catch {\n return undefined;\n }\n if (url.protocol !== 'https:' || url.username !== '' || url.password !== '' || url.search !== '' || url.hash !== '')\n return undefined;\n const allowedSessionIds =\n Array.isArray(record.allowedSessionIds) && record.allowedSessionIds.every(validId)\n ? record.allowedSessionIds\n : undefined;\n const allowedVoiceSessionIds =\n Array.isArray(record.allowedVoiceSessionIds) && record.allowedVoiceSessionIds.every(validId)\n ? record.allowedVoiceSessionIds\n : [];\n if (allowedSessionIds === undefined || record.secret.length < 32) return undefined;\n return {\n hostId: record.hostId,\n url: url.toString(),\n secret: record.secret,\n allowedSessionIds,\n allowedVoiceSessionIds,\n };\n}\n\nexport function sessionPeerConfigPath(homeDirectory: string): string {\n return path.join(homeDirectory, '.pi', '.doom', 'session', PEER_CONFIG_FILE);\n}\n\n/** Reads operator-provisioned peers. Invalid or unreadable config fails closed. */\nexport function readSessionPeerConfig(homeDirectory: string): SessionPeerConfig | undefined {\n let parsed: unknown;\n try {\n const file = sessionPeerConfigPath(homeDirectory);\n if ((fs.statSync(file).mode & 0o077) !== 0) return undefined;\n parsed = JSON.parse(fs.readFileSync(file, 'utf8')) as unknown;\n } catch {\n return undefined;\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return undefined;\n const record = parsed as Record<string, unknown>;\n if (record.version !== PEER_CONFIG_VERSION || !validId(record.hostId) || !Array.isArray(record.peers))\n return undefined;\n const peers = record.peers.map(peerOf);\n if (peers.some((peer) => peer === undefined)) return undefined;\n const resolved = peers as SessionPeer[];\n if (\n new Set(resolved.map((peer) => peer.hostId)).size !== resolved.length ||\n resolved.some((peer) => peer.hostId === record.hostId)\n )\n return undefined;\n return { version: PEER_CONFIG_VERSION, hostId: record.hostId, peers: resolved };\n}\n\n/** `peer/<host-id>/<session-id>` is the only remote target spelling. */\nexport function parseRemoteSessionReference(value: string): RemoteSessionReference | undefined {\n const match = /^peer\\/([^/]+)\\/([^/]+)$/u.exec(value);\n return match && validId(match[1]) && validId(match[2]) ? { hostId: match[1], sessionId: match[2] } : undefined;\n}\n\nexport function peerSessionReference(hostId: string, sessionId: string): string {\n if (!validId(hostId) || !validId(sessionId))\n throw new TypeError('Remote host and session identifiers must be safe opaque IDs.');\n return `peer/${hostId}/${sessionId}`;\n}\n\nfunction signature(secret: string, method: string, pathname: string, timestamp: string, body: string): string {\n const digest = createHash('sha256').update(body).digest('base64url');\n return createHmac('sha256', secret).update(`${method}\\n${pathname}\\n${timestamp}\\n${digest}`).digest('base64url');\n}\n\nexport function peerRequestHeaders(\n sourceHostId: string,\n peer: SessionPeer,\n method: string,\n pathname: string,\n body: string,\n now = Date.now(),\n): Headers {\n if (!validId(sourceHostId)) throw new TypeError('Source host identity must be a safe opaque ID.');\n const timestamp = String(now);\n return new Headers({\n 'content-type': 'application/json',\n [PEER_HEADER]: sourceHostId,\n [TIMESTAMP_HEADER]: timestamp,\n [SIGNATURE_HEADER]: signature(peer.secret, method, pathname, timestamp, body),\n });\n}\n\n/** Persists accepted peer signatures so a valid request cannot be replayed within its clock-skew window. */\nexport function createPeerReplayGuard(homeDirectory: string): SessionPeerReplayGuard {\n const directory = path.dirname(sessionPeerConfigPath(homeDirectory));\n fs.mkdirSync(directory, { recursive: true, mode: 0o700 });\n const database = new DatabaseSync(path.join(directory, REPLAY_DATABASE_FILE));\n database.exec(`\n PRAGMA journal_mode = WAL;\n CREATE TABLE IF NOT EXISTS peer_request_replays (\n signature TEXT PRIMARY KEY,\n expires_at INTEGER NOT NULL\n );\n `);\n const removeExpired = database.prepare('DELETE FROM peer_request_replays WHERE expires_at < ?');\n const insert = database.prepare('INSERT OR IGNORE INTO peer_request_replays (signature, expires_at) VALUES (?, ?)');\n const count = database.prepare('SELECT COUNT(*) AS count FROM peer_request_replays');\n const trim = database.prepare(`\n DELETE FROM peer_request_replays\n WHERE signature IN (\n SELECT signature FROM peer_request_replays ORDER BY expires_at ASC, signature ASC LIMIT ?\n )\n `);\n return {\n admit(request, now = Date.now()) {\n const supplied = request.headers.get(SIGNATURE_HEADER);\n if (!supplied) return false;\n database.exec('BEGIN IMMEDIATE');\n try {\n removeExpired.run(now);\n const accepted = insert.run(supplied, now + MAX_CLOCK_SKEW_MS).changes === 1;\n const total = Number((count.get() as { count: number | bigint }).count);\n if (total > MAX_REPLAY_ENTRIES) trim.run(total - MAX_REPLAY_ENTRIES);\n database.exec('COMMIT');\n return accepted;\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n },\n close: () => database.close(),\n };\n}\n\nexport function verifyPeerRequest(\n config: SessionPeerConfig,\n request: Request,\n body: string,\n now = Date.now(),\n): SessionPeer | undefined {\n const hostId = request.headers.get(PEER_HEADER);\n const timestamp = request.headers.get(TIMESTAMP_HEADER);\n const supplied = request.headers.get(SIGNATURE_HEADER);\n if (!hostId || !timestamp || !supplied || !/^\\d{1,16}$/u.test(timestamp)) return undefined;\n const sentAt = Number(timestamp);\n if (!Number.isSafeInteger(sentAt) || Math.abs(now - sentAt) > MAX_CLOCK_SKEW_MS) return undefined;\n const peer = config.peers.find((candidate) => candidate.hostId === hostId);\n if (!peer) return undefined;\n const expected = Buffer.from(signature(peer.secret, request.method, new URL(request.url).pathname, timestamp, body));\n const actual = Buffer.from(supplied);\n return actual.byteLength === expected.byteLength && timingSafeEqual(actual, expected) ? peer : undefined;\n}\n\nfunction envelopeOf(value: unknown): SessionPeerEnvelope | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n return validId(record.sourceSessionId) &&\n validId(record.targetSessionId) &&\n typeof record.type === 'string' &&\n record.type !== ''\n ? {\n sourceSessionId: record.sourceSessionId,\n targetSessionId: record.targetSessionId,\n type: record.type,\n payload: record.payload,\n }\n : undefined;\n}\n\nexport function parseSessionPeerEnvelope(value: unknown): SessionPeerEnvelope | undefined {\n return envelopeOf(value);\n}\n\n/** Adds asynchronous tunnel publication to a host-bound local communication endpoint. */\nexport function createPeerCommunication(options: {\n readonly local: DoomSessionCommunicationEndpoint;\n readonly homeDirectory: string;\n readonly fetch?: typeof fetch;\n}): DoomSessionCommunicationEndpoint {\n const config = readSessionPeerConfig(options.homeDirectory);\n const send = options.fetch ?? fetch;\n return {\n sessionId: options.local.sessionId,\n publish(target, type, payload) {\n const remote = parseRemoteSessionReference(target);\n if (!remote) return options.local.publish(target, type, payload);\n const peer = config?.peers.find((candidate) => candidate.hostId === remote.hostId);\n // Pairing is not a grant. Outbound delivery needs the same explicit target\n // allowlist that the receiver enforces for inbound envelopes.\n if (!config || !peer || !peer.allowedSessionIds.includes(remote.sessionId)) return false;\n const body = JSON.stringify({\n sourceSessionId: options.local.sessionId,\n targetSessionId: remote.sessionId,\n type,\n payload,\n });\n const url = new URL(PEER_ROUTE, peer.url);\n void send(url, {\n method: 'POST',\n headers: peerRequestHeaders(config.hostId, peer, 'POST', '/inbox', body),\n body,\n }).catch(() => undefined);\n return true;\n },\n subscribe: (type, listener) => options.local.subscribe(type, listener),\n onPeerReady: (listener) => options.local.onPeerReady(listener),\n close: () => options.local.close(),\n };\n}\n","import { peerSessionReference } from '../peerTransport';\nimport type {\n DiscoveredSession,\n SessionDirectory,\n SessionDirectoryOptions,\n SessionPresenceFacts,\n SessionPresenceObservation,\n} from './type';\n\nconst UNKNOWN_FACTS: SessionPresenceFacts = Object.freeze({\n reachability: 'unknown',\n runtime: 'unknown',\n activity: 'unknown',\n voice: Object.freeze({ eligible: 'unknown', readiness: 'unknown' }),\n});\n\nfunction keyOf(observation: Pick<SessionPresenceObservation, 'hostId' | 'sessionId'>): string {\n return peerSessionReference(observation.hostId, observation.sessionId);\n}\n\nfunction publicEntry(\n observation: SessionPresenceObservation,\n now: number,\n label: string | undefined,\n capabilities: readonly string[],\n): DiscoveredSession {\n const freshUntil = observation.observedAt + observation.staleAfterMs;\n const fresh = now <= freshUntil;\n const facts: SessionPresenceFacts = fresh ? observation : UNKNOWN_FACTS;\n return Object.freeze({\n reference: keyOf(observation),\n ...(label === undefined ? {} : { label }),\n capabilities: Object.freeze([...capabilities]),\n hostIncarnation: observation.hostIncarnation,\n sessionIncarnation: observation.sessionIncarnation,\n sequence: observation.sequence,\n observedAt: observation.observedAt,\n freshUntil,\n fresh,\n reachability: facts.reachability,\n runtime: facts.runtime,\n activity: facts.activity,\n voice: Object.freeze({ ...facts.voice }),\n });\n}\n\n/** In-memory authenticated presence cache. Restart deliberately forgets every observation. */\nexport function createSessionDirectory(options: SessionDirectoryOptions): SessionDirectory {\n const now = options.now ?? Date.now;\n const observations = new Map<string, SessionPresenceObservation>();\n const snapshotRequired = new Set<string>();\n const subscribers = new Set<{\n callerReference: string;\n listener: (sessions: readonly DiscoveredSession[]) => void;\n }>();\n\n const discover = (callerReference: string, allowedReferences?: ReadonlySet<string>): readonly DiscoveredSession[] => {\n const result: DiscoveredSession[] = [];\n for (const observation of observations.values()) {\n const reference = keyOf(observation);\n if (allowedReferences && !allowedReferences.has(reference)) continue;\n const grant = options.authorizeDiscovery(callerReference, observation);\n if (!grant) continue;\n result.push(publicEntry(observation, now(), grant.label ?? observation.label, grant.capabilities));\n }\n return result.sort((left, right) => left.reference.localeCompare(right.reference));\n };\n const notify = (): void => {\n for (const subscriber of subscribers) subscriber.listener(discover(subscriber.callerReference));\n };\n\n return {\n observe(observation) {\n const key = keyOf(observation);\n const current = observations.get(key);\n if (snapshotRequired.has(observation.hostId)) return false;\n if (current?.hostIncarnation === observation.hostIncarnation) {\n if (current.sessionIncarnation === observation.sessionIncarnation && observation.sequence <= current.sequence)\n return false;\n if (observation.sequence !== current.sequence + 1) {\n snapshotRequired.add(observation.hostId);\n for (const [reference, candidate] of observations)\n if (candidate.hostId === observation.hostId)\n observations.set(reference, { ...candidate, ...UNKNOWN_FACTS, observedAt: now(), staleAfterMs: 0 });\n notify();\n return false;\n }\n }\n observations.set(key, Object.freeze({ ...observation, voice: Object.freeze({ ...observation.voice }) }));\n notify();\n return true;\n },\n replaceHostSnapshot(hostId, hostIncarnation, replacements) {\n if (\n replacements.some(\n (observation) => observation.hostId !== hostId || observation.hostIncarnation !== hostIncarnation,\n )\n ) {\n throw new TypeError('A presence snapshot must contain only the declared host incarnation.');\n }\n for (const [reference, observation] of observations)\n if (observation.hostId === hostId) observations.delete(reference);\n for (const observation of replacements)\n observations.set(\n keyOf(observation),\n Object.freeze({ ...observation, voice: Object.freeze({ ...observation.voice }) }),\n );\n snapshotRequired.delete(hostId);\n notify();\n },\n hostDisconnected(hostId) {\n for (const [reference, observation] of observations) {\n if (observation.hostId !== hostId) continue;\n observations.set(reference, { ...observation, reachability: 'unreachable' });\n }\n notify();\n },\n discover,\n resolveDeliveryTarget(callerReference, reference) {\n const observation = observations.get(reference);\n return observation && options.authorizeDiscovery(callerReference, observation)\n ? observation.deliveryTarget\n : undefined;\n },\n subscribe(callerReference, listener) {\n const subscriber = { callerReference, listener };\n subscribers.add(subscriber);\n listener(discover(callerReference));\n return () => subscribers.delete(subscriber);\n },\n };\n}\n\nexport type {\n DiscoveredSession,\n SessionActivityState,\n SessionDirectory,\n SessionDirectoryOptions,\n SessionDiscoveryGrant,\n SessionHostReachability,\n SessionPresenceFacts,\n SessionPresenceObservation,\n SessionRuntimeState,\n SessionVoiceReadiness,\n} from './type';\n","export interface SessionCommunicationGroup {\n readonly id: string;\n readonly ownerAuthority: string;\n readonly revision: number;\n readonly members: readonly string[];\n}\n\nexport interface SessionGroupMutation {\n readonly groupId: string;\n readonly authority: string;\n readonly expectedRevision: number;\n readonly add?: readonly string[];\n readonly remove?: readonly string[];\n}\n\nexport interface SessionGroupStoreOptions {\n readonly databasePath: string;\n readonly authorizeManagement?: (authority: string, group: SessionCommunicationGroup) => boolean;\n readonly validateEnrollment?: (groupId: string, memberReference: string) => boolean;\n}\n\nexport interface SessionGroupStore {\n create(groupId: string, ownerAuthority: string, members: readonly string[]): SessionCommunicationGroup;\n mutate(mutation: SessionGroupMutation): SessionCommunicationGroup;\n get(groupId: string): SessionCommunicationGroup | undefined;\n groupsFor(memberReference: string): readonly SessionCommunicationGroup[];\n canMessage(groupId: string, sourceReference: string, targetReference: string): boolean;\n close(): void;\n}\n\nexport class SessionGroupRevisionError extends Error {\n constructor(groupId: string, expected: number, actual: number) {\n super(`Session group '${groupId}' revision conflict: expected ${expected}, current ${actual}.`);\n this.name = 'SessionGroupRevisionError';\n }\n}\n","import { DatabaseSync } from 'node:sqlite';\n\nimport {\n SessionGroupRevisionError,\n type SessionCommunicationGroup,\n type SessionGroupMutation,\n type SessionGroupStore,\n type SessionGroupStoreOptions,\n} from './type';\n\ninterface GroupRow {\n group_id: string;\n owner_authority: string;\n revision: number;\n}\n\nconst ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;\nconst REFERENCE_PATTERN = /^peer\\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}\\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;\n\nfunction validateGroupId(value: string): void {\n if (!ID_PATTERN.test(value)) throw new TypeError('Session group IDs must be safe opaque IDs.');\n}\n\nfunction validateReference(value: string): void {\n if (!REFERENCE_PATTERN.test(value))\n throw new TypeError(`Session group member '${value}' is not a qualified reference.`);\n}\n\n/** Opens a revisioned SQLite registry for communication-only group membership. */\nexport function createSessionGroupStore(options: SessionGroupStoreOptions): SessionGroupStore {\n const database = new DatabaseSync(options.databasePath);\n database.exec(`\n PRAGMA journal_mode = WAL;\n PRAGMA foreign_keys = ON;\n CREATE TABLE IF NOT EXISTS session_groups (\n group_id TEXT PRIMARY KEY,\n owner_authority TEXT NOT NULL,\n revision INTEGER NOT NULL\n );\n CREATE TABLE IF NOT EXISTS session_group_members (\n group_id TEXT NOT NULL REFERENCES session_groups(group_id) ON DELETE CASCADE,\n member_reference TEXT NOT NULL,\n PRIMARY KEY (group_id, member_reference)\n );\n `);\n\n const read = (groupId: string): SessionCommunicationGroup | undefined => {\n const row = database.prepare('SELECT * FROM session_groups WHERE group_id = ?').get(groupId) as\n | GroupRow\n | undefined;\n if (!row) return undefined;\n const members = database\n .prepare('SELECT member_reference FROM session_group_members WHERE group_id = ? ORDER BY member_reference')\n .all(groupId) as { member_reference: string }[];\n return Object.freeze({\n id: row.group_id,\n ownerAuthority: row.owner_authority,\n revision: row.revision,\n members: Object.freeze(members.map((member) => member.member_reference)),\n });\n };\n\n const enroll = (groupId: string, members: readonly string[]): void => {\n const insert = database.prepare(\n 'INSERT OR IGNORE INTO session_group_members (group_id, member_reference) VALUES (?, ?)',\n );\n for (const member of new Set(members)) {\n validateReference(member);\n if (options.validateEnrollment?.(groupId, member) === false)\n throw new Error(`Session group enrollment policy rejected '${member}'.`);\n insert.run(groupId, member);\n }\n };\n\n return {\n create(groupId, ownerAuthority, members) {\n validateGroupId(groupId);\n if (!ownerAuthority.trim()) throw new TypeError('Session group owner authority is required.');\n database.exec('BEGIN IMMEDIATE');\n try {\n database\n .prepare('INSERT INTO session_groups (group_id, owner_authority, revision) VALUES (?, ?, 1)')\n .run(groupId, ownerAuthority);\n enroll(groupId, members);\n database.exec('COMMIT');\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n return read(groupId)!;\n },\n mutate(mutation: SessionGroupMutation) {\n database.exec('BEGIN IMMEDIATE');\n try {\n const current = read(mutation.groupId);\n if (!current) throw new Error(`Session group '${mutation.groupId}' does not exist.`);\n if (\n mutation.authority !== current.ownerAuthority &&\n options.authorizeManagement?.(mutation.authority, current) !== true\n ) {\n throw new Error(`Authority '${mutation.authority}' cannot manage Session group '${mutation.groupId}'.`);\n }\n if (mutation.expectedRevision !== current.revision)\n throw new SessionGroupRevisionError(mutation.groupId, mutation.expectedRevision, current.revision);\n enroll(mutation.groupId, mutation.add ?? []);\n const remove = database.prepare(\n 'DELETE FROM session_group_members WHERE group_id = ? AND member_reference = ?',\n );\n for (const member of new Set(mutation.remove ?? [])) {\n validateReference(member);\n remove.run(mutation.groupId, member);\n }\n database\n .prepare('UPDATE session_groups SET revision = revision + 1 WHERE group_id = ? AND revision = ?')\n .run(mutation.groupId, current.revision);\n database.exec('COMMIT');\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n return read(mutation.groupId)!;\n },\n get: read,\n groupsFor(memberReference) {\n validateReference(memberReference);\n const rows = database\n .prepare(\n `SELECT g.group_id FROM session_groups g\n INNER JOIN session_group_members m ON m.group_id = g.group_id\n WHERE m.member_reference = ? ORDER BY g.group_id`,\n )\n .all(memberReference) as { group_id: string }[];\n return rows.map((row) => read(row.group_id)!);\n },\n canMessage(groupId, sourceReference, targetReference) {\n validateReference(sourceReference);\n validateReference(targetReference);\n const row = database\n .prepare(\n `SELECT COUNT(*) AS count FROM session_group_members\n WHERE group_id = ? AND member_reference IN (?, ?)`,\n )\n .get(groupId, sourceReference, targetReference) as { count: number | bigint };\n return Number(row.count) === (sourceReference === targetReference ? 1 : 2);\n },\n close: () => database.close(),\n };\n}\n\nexport {\n SessionGroupRevisionError,\n type SessionCommunicationGroup,\n type SessionGroupMutation,\n type SessionGroupStore,\n type SessionGroupStoreOptions,\n} from './type';\n","import type { Context } from '@deepseek-ai/cordis';\n\nimport type {\n DoomSessionDeliveryMetadata,\n DoomSessionDeliveryService,\n DoomSessionInboxEntry,\n DoomSessionOutboxEntry,\n} from '../sessionDelivery';\nimport type { DiscoveredSession, SessionDirectory } from '../sessionDirectory';\nimport type { SessionGroupStore } from '../sessionGroups';\n\nexport const DOOM_SESSION_INTERCOM_SERVICE = 'doom/session-intercom';\n\nexport type SessionReportStatus = 'done' | 'blocked' | 'failed';\n\nexport interface SessionIntercomMessage {\n readonly deliveryId: string;\n readonly sourceReference: string;\n readonly targetReference: string;\n readonly groupId: string;\n readonly correlationId?: string;\n readonly text: string;\n readonly reportStatus?: SessionReportStatus;\n readonly state: DoomSessionInboxEntry['state'];\n readonly consumed: boolean;\n}\n\nexport interface SessionIntercomSendRequest {\n readonly targetReference: string;\n readonly groupId: string;\n readonly text: string;\n readonly correlationId?: string;\n readonly deliveryId?: string;\n}\n\nexport interface SessionIntercomOptions {\n readonly selfReference: string;\n readonly directory: SessionDirectory;\n readonly groups: SessionGroupStore;\n readonly delivery: DoomSessionDeliveryService;\n}\n\nexport interface SessionIntercom {\n discover(): readonly DiscoveredSession[];\n send(request: SessionIntercomSendRequest): Promise<{ deliveryId: string }>;\n report(\n request: SessionIntercomSendRequest & { readonly status: SessionReportStatus },\n ): Promise<{ deliveryId: string }>;\n messages(): readonly SessionIntercomMessage[];\n delivery(deliveryId: string): DoomSessionOutboxEntry | undefined;\n}\n\nexport interface SessionGroupDeliveryAuthorizationOptions {\n readonly selfReference: string;\n readonly groups: SessionGroupStore;\n readonly peerReference: (peerKey: string) => string | undefined;\n readonly fallback?: (peerKey: string, metadata: DoomSessionDeliveryMetadata | undefined) => boolean;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/session-intercom': SessionIntercom;\n }\n}\n\nexport function readSessionIntercom(context: Context): SessionIntercom | undefined {\n return context.get(DOOM_SESSION_INTERCOM_SERVICE) as SessionIntercom | undefined;\n}\n\nexport function requireSessionIntercom(context: Context): SessionIntercom {\n const service = readSessionIntercom(context);\n if (!service)\n throw new Error('Session intercom is unavailable. Activate Session with a configured persistent host identity.');\n return service;\n}\n","import type { DoomSessionDeliveryMetadata } from '../sessionDelivery';\nimport type { SessionIntercomMessage } from './type';\nimport type {\n SessionGroupDeliveryAuthorizationOptions,\n SessionIntercom,\n SessionIntercomOptions,\n SessionIntercomSendRequest,\n SessionReportStatus,\n} from './type';\n\nconst MESSAGE_KIND = 'session-message';\nconst REPORT_KIND = 'session-report';\n\nfunction metadataFor(\n options: SessionIntercomOptions,\n request: SessionIntercomSendRequest,\n reportStatus?: SessionReportStatus,\n): DoomSessionDeliveryMetadata {\n const group = options.groups.get(request.groupId);\n if (!group || !options.groups.canMessage(request.groupId, options.selfReference, request.targetReference))\n throw new Error(`Session group '${request.groupId}' does not authorize this message.`);\n return {\n sourceReference: options.selfReference,\n targetReference: request.targetReference,\n groupId: request.groupId,\n groupRevision: String(group.revision),\n ...(request.correlationId === undefined ? {} : { correlationId: request.correlationId }),\n ...(reportStatus === undefined ? {} : { reportStatus }),\n };\n}\n\n/** Agent-facing intercom operations. A composition may acquire this service without gaining session controls. */\nexport function createSessionIntercom(options: SessionIntercomOptions): SessionIntercom {\n const deliver = async (\n request: SessionIntercomSendRequest,\n kind: typeof MESSAGE_KIND | typeof REPORT_KIND,\n status?: SessionReportStatus,\n ): Promise<{ deliveryId: string }> => {\n const recipientKey = options.directory.resolveDeliveryTarget(options.selfReference, request.targetReference);\n if (!recipientKey) throw new Error(`Session '${request.targetReference}' is not discoverable.`);\n const metadata = metadataFor(options, request, status);\n return options.delivery.deliver({\n ...(request.deliveryId === undefined ? {} : { deliveryId: request.deliveryId }),\n recipientKey,\n kind,\n prompt: `[Session ${status === undefined ? 'message' : `report: ${status}`} from ${options.selfReference}] ${request.text}`,\n metadata,\n });\n };\n\n const intercom: SessionIntercom = {\n discover() {\n const members = new Set(\n options.groups\n .groupsFor(options.selfReference)\n .flatMap((group) => group.members)\n .filter((reference) => reference !== options.selfReference),\n );\n return options.directory.discover(options.selfReference, members);\n },\n send: (request) => deliver(request, MESSAGE_KIND),\n report: (request) => deliver(request, REPORT_KIND, request.status),\n messages() {\n return options.delivery\n .inbox()\n .filter((entry) => entry.kind === MESSAGE_KIND || entry.kind === REPORT_KIND)\n .filter((entry) => {\n const groupId = entry.metadata.groupId;\n return groupId !== undefined && options.groups.get(groupId)?.members.includes(options.selfReference) === true;\n })\n .flatMap((entry): SessionIntercomMessage[] => {\n const sourceReference = entry.metadata.sourceReference;\n const targetReference = entry.metadata.targetReference;\n const groupId = entry.metadata.groupId;\n if (!sourceReference || !targetReference || !groupId) return [];\n const reportStatus = entry.metadata.reportStatus;\n return [\n {\n deliveryId: entry.deliveryId,\n sourceReference,\n targetReference,\n groupId,\n ...(entry.metadata.correlationId === undefined ? {} : { correlationId: entry.metadata.correlationId }),\n text: entry.prompt,\n ...(reportStatus === 'done' || reportStatus === 'blocked' || reportStatus === 'failed'\n ? { reportStatus }\n : {}),\n state: entry.state,\n consumed: entry.consumed,\n },\n ];\n });\n },\n delivery(deliveryId) {\n const entry = options.delivery.outbox(deliveryId);\n const groupId = entry?.metadata.groupId;\n return entry &&\n groupId !== undefined &&\n options.groups.get(groupId)?.members.includes(options.selfReference) === true\n ? entry\n : undefined;\n },\n };\n return Object.freeze(intercom);\n}\n\n/** Builds the dynamic delivery check used before every send, retry, and recipient acceptance. */\nexport function createSessionGroupDeliveryAuthorizer(\n options: SessionGroupDeliveryAuthorizationOptions,\n): (peerKey: string, metadata: DoomSessionDeliveryMetadata | undefined) => boolean {\n return (peerKey, metadata) => {\n const sourceReference = metadata?.sourceReference;\n const targetReference = metadata?.targetReference;\n const groupId = metadata?.groupId;\n if (sourceReference && targetReference && groupId) {\n const peerReference = options.peerReference(peerKey);\n if (!peerReference) return false;\n const directionMatches =\n (sourceReference === options.selfReference && targetReference === peerReference) ||\n (targetReference === options.selfReference && sourceReference === peerReference);\n return directionMatches && options.groups.canMessage(groupId, sourceReference, targetReference);\n }\n return options.fallback?.(peerKey, metadata) === true;\n };\n}\n\nexport { DOOM_SESSION_INTERCOM_SERVICE, readSessionIntercom, requireSessionIntercom } from './type';\nexport type {\n SessionGroupDeliveryAuthorizationOptions,\n SessionIntercom,\n SessionIntercomMessage,\n SessionIntercomOptions,\n SessionIntercomSendRequest,\n SessionReportStatus,\n} from './type';\n","import type { DoomSessionCommunicationEndpoint } from '@agimon-ai/doompi-core/hubChannel';\nimport type { Context } from '@deepseek-ai/cordis';\n\nexport const DOOM_SESSION_DELIVERY_SERVICE = 'doom/session-delivery';\n\nexport type DoomSessionDeliveryInboxState = 'accepted' | 'admitting' | 'admitted' | 'recovery_required';\nexport type DoomSessionDeliveryMode = 'prompt' | 'steer' | 'followUp';\n\nexport interface DoomSessionDeliveryMetadata extends Readonly<Record<string, string | undefined>> {\n readonly worktreeId?: string;\n readonly fromRole?: string;\n}\n\nexport interface DoomSessionDeliveryRequest {\n readonly deliveryId?: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery?: DoomSessionDeliveryMode;\n readonly metadata?: DoomSessionDeliveryMetadata;\n}\n\nexport interface DoomSessionInboxQuery {\n readonly kind?: string;\n readonly metadata?: DoomSessionDeliveryMetadata;\n readonly state?: DoomSessionDeliveryInboxState;\n readonly consumed?: boolean;\n}\n\nexport interface DoomSessionInboxEntry {\n readonly deliveryId: string;\n readonly senderKey: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery: DoomSessionDeliveryMode;\n readonly metadata: DoomSessionDeliveryMetadata;\n readonly state: DoomSessionDeliveryInboxState;\n readonly consumed: boolean;\n}\n\nexport interface DoomSessionOutboxEntry {\n readonly deliveryId: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly metadata: DoomSessionDeliveryMetadata;\n readonly state: 'queued' | 'acknowledged';\n readonly recipientState?: DoomSessionDeliveryInboxState;\n}\n\nexport interface DoomSessionDeliveryService {\n readonly recipientKey: string;\n deliver(request: DoomSessionDeliveryRequest): Promise<{ deliveryId: string }>;\n waitForAdmission(deliveryId: string, timeoutMs?: number): Promise<DoomSessionDeliveryInboxState | undefined>;\n inbox(query?: DoomSessionInboxQuery): readonly DoomSessionInboxEntry[];\n /** Optional host-routed peer envelope admission. Local-only consumers need no transport receiver. */\n receive?(senderKey: string, kind: string, payload: unknown): DoomSessionDeliveryInboxState | undefined;\n consume(deliveryId: string): boolean;\n outbox(deliveryId: string): DoomSessionOutboxEntry | undefined;\n close(): Promise<void>;\n}\n\nexport interface SessionDeliveryServiceOptions {\n readonly databasePath: string;\n readonly recipientKey: string;\n readonly communication: DoomSessionCommunicationEndpoint;\n /** Host-owned relationship check applied before sends, retries, and recipient acceptance. */\n readonly authorizePeer: (peerKey: string, metadata?: DoomSessionDeliveryMetadata) => boolean;\n readonly admitPrompt: (prompt: string, delivery?: DoomSessionDeliveryMode) => Promise<void>;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/session-delivery': DoomSessionDeliveryService;\n }\n}\n\n/** Reads the currently active provider each time, without retaining a stale binding. */\nexport function readDoomSessionDelivery(context: Context): DoomSessionDeliveryService | undefined {\n return context.get(DOOM_SESSION_DELIVERY_SERVICE) as DoomSessionDeliveryService | undefined;\n}\n","import { DatabaseSync } from 'node:sqlite';\n\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport {\n DOOM_SESSION_DELIVERY_SERVICE,\n type DoomSessionDeliveryInboxState,\n type DoomSessionDeliveryMetadata,\n type DoomSessionDeliveryMode,\n type DoomSessionDeliveryRequest,\n type DoomSessionDeliveryService,\n type DoomSessionInboxEntry,\n type DoomSessionInboxQuery,\n type DoomSessionOutboxEntry,\n type SessionDeliveryServiceOptions,\n} from './type';\n\nconst DELIVERY_EVENT = 'doom/session-delivery/envelope';\nconst ACK_EVENT = 'doom/session-delivery/ack';\nconst DEFAULT_DELIVERY: DoomSessionDeliveryMode = 'prompt';\nconst INBOX_STATES = new Set<DoomSessionDeliveryInboxState>(['accepted', 'admitting', 'admitted', 'recovery_required']);\n\ninterface DeliveryEnvelope {\n readonly deliveryId: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery: DoomSessionDeliveryMode;\n readonly metadata: DoomSessionDeliveryMetadata;\n}\n\ninterface DeliveryAck {\n readonly deliveryId: string;\n readonly state: DoomSessionDeliveryInboxState;\n}\n\ninterface InboxRow {\n delivery_id: string;\n sender_key: string;\n recipient_key: string;\n kind: string;\n prompt: string;\n delivery_mode: DoomSessionDeliveryMode;\n metadata_json: string;\n state: DoomSessionDeliveryInboxState;\n consumed_at: number | null;\n}\n\ninterface OutboxRow {\n delivery_id: string;\n recipient_key: string;\n kind: string;\n prompt: string;\n delivery_mode: DoomSessionDeliveryMode;\n metadata_json: string;\n state: 'queued' | 'acknowledged';\n recipient_state: DoomSessionDeliveryInboxState | null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isMode(value: unknown): value is DoomSessionDeliveryMode {\n return value === 'prompt' || value === 'steer' || value === 'followUp';\n}\n\nfunction metadataOf(value: unknown): DoomSessionDeliveryMetadata | undefined {\n if (!isRecord(value)) return undefined;\n const metadata: Record<string, string> = {};\n for (const [key, item] of Object.entries(value)) {\n if (typeof item !== 'string') return undefined;\n metadata[key] = item;\n }\n return metadata;\n}\n\nfunction envelopeOf(value: unknown): DeliveryEnvelope | undefined {\n if (!isRecord(value)) return undefined;\n const metadata = metadataOf(value.metadata);\n if (\n typeof value.deliveryId !== 'string' ||\n !value.deliveryId ||\n typeof value.kind !== 'string' ||\n !value.kind ||\n typeof value.prompt !== 'string' ||\n !isMode(value.delivery) ||\n metadata === undefined\n ) {\n return undefined;\n }\n return {\n deliveryId: value.deliveryId,\n kind: value.kind,\n prompt: value.prompt,\n delivery: value.delivery,\n metadata,\n };\n}\n\nfunction ackOf(value: unknown): DeliveryAck | undefined {\n if (!isRecord(value)) return undefined;\n if (\n typeof value.deliveryId !== 'string' ||\n typeof value.state !== 'string' ||\n !INBOX_STATES.has(value.state as DoomSessionDeliveryInboxState)\n ) {\n return undefined;\n }\n return value as unknown as DeliveryAck;\n}\n\nfunction normalizedMetadata(metadata: DoomSessionDeliveryMetadata | undefined): DoomSessionDeliveryMetadata {\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata ?? {})) {\n if (value !== undefined) normalized[key] = value;\n }\n return normalized;\n}\n\nfunction matchesMetadata(entry: DoomSessionDeliveryMetadata, query: DoomSessionDeliveryMetadata | undefined): boolean {\n return Object.entries(query ?? {}).every(([key, value]) => value === undefined || entry[key] === value);\n}\n\nfunction sameMetadata(left: DoomSessionDeliveryMetadata, right: DoomSessionDeliveryMetadata): boolean {\n return matchesMetadata(left, right) && matchesMetadata(right, left);\n}\n\n/** Opens and starts one durable delivery endpoint. */\nexport function createSessionDeliveryService(options: SessionDeliveryServiceOptions): DoomSessionDeliveryService {\n if (!options.recipientKey.trim() || options.recipientKey !== options.recipientKey.trim()) {\n throw new TypeError('Session delivery requires a trimmed, non-empty recipient key.');\n }\n const database = new DatabaseSync(options.databasePath);\n database.exec(`\n PRAGMA journal_mode = WAL;\n CREATE TABLE IF NOT EXISTS session_delivery_outbox (\n delivery_id TEXT PRIMARY KEY,\n recipient_key TEXT NOT NULL,\n kind TEXT NOT NULL,\n prompt TEXT NOT NULL,\n delivery_mode TEXT NOT NULL,\n metadata_json TEXT NOT NULL,\n state TEXT NOT NULL,\n recipient_state TEXT,\n created_at INTEGER NOT NULL,\n acknowledged_at INTEGER\n );\n CREATE TABLE IF NOT EXISTS session_delivery_inbox (\n delivery_id TEXT PRIMARY KEY,\n sender_key TEXT NOT NULL,\n recipient_key TEXT NOT NULL,\n kind TEXT NOT NULL,\n prompt TEXT NOT NULL,\n delivery_mode TEXT NOT NULL,\n metadata_json TEXT NOT NULL,\n state TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n consumed_at INTEGER\n );\n `);\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE state = 'admitting'\")\n .run(Date.now());\n\n let closed = false;\n const scheduled = new Set<string>();\n let admissionQueue = Promise.resolve();\n\n const publishAck = (deliveryId: string, senderKey: string, state: DoomSessionDeliveryInboxState): void => {\n options.communication.publish(senderKey, ACK_EVENT, { deliveryId, state } satisfies DeliveryAck);\n };\n\n const readInboxRow = (deliveryId: string): InboxRow | undefined =>\n database.prepare('SELECT * FROM session_delivery_inbox WHERE delivery_id = ?').get(deliveryId) as\n | InboxRow\n | undefined;\n\n const scheduleAdmission = (deliveryId: string): void => {\n if (closed || scheduled.has(deliveryId)) return;\n scheduled.add(deliveryId);\n admissionQueue = admissionQueue\n .then(async () => {\n try {\n if (closed) return;\n const row = readInboxRow(deliveryId);\n if (!row || row.state !== 'accepted') return;\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'admitting', updated_at = ? WHERE delivery_id = ?\")\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'admitting');\n try {\n await options.admitPrompt(row.prompt, row.delivery_mode);\n } catch {\n database\n .prepare(\n \"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE delivery_id = ?\",\n )\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'recovery_required');\n return;\n }\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'admitted', updated_at = ? WHERE delivery_id = ?\")\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'admitted');\n } finally {\n scheduled.delete(deliveryId);\n }\n })\n .catch(() => {\n scheduled.delete(deliveryId);\n try {\n const row = readInboxRow(deliveryId);\n if (row?.state !== 'admitting') return;\n database\n .prepare(\n \"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE delivery_id = ?\",\n )\n .run(Date.now(), deliveryId);\n try {\n publishAck(deliveryId, row.sender_key, 'recovery_required');\n } catch {\n // The durable state is authoritative; readiness replay can request another acknowledgement.\n }\n } catch {\n // A database failure remains recoverable on restart when the schema can be opened again.\n }\n });\n };\n\n const receiveEnvelope = (senderKey: string, value: unknown): DoomSessionDeliveryInboxState | undefined => {\n if (closed) return undefined;\n const envelope = envelopeOf(value);\n if (!envelope || !options.authorizePeer(senderKey, envelope.metadata)) return undefined;\n database\n .prepare(\n `INSERT OR IGNORE INTO session_delivery_inbox\n (delivery_id, sender_key, recipient_key, kind, prompt, delivery_mode, metadata_json, state, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, 'accepted', ?, ?)`,\n )\n .run(\n envelope.deliveryId,\n senderKey,\n options.recipientKey,\n envelope.kind,\n envelope.prompt,\n envelope.delivery,\n JSON.stringify(envelope.metadata),\n Date.now(),\n Date.now(),\n );\n const current = readInboxRow(envelope.deliveryId);\n if (!current) return undefined;\n const sameEnvelope =\n current.sender_key === senderKey &&\n current.recipient_key === options.recipientKey &&\n current.kind === envelope.kind &&\n current.prompt === envelope.prompt &&\n current.delivery_mode === envelope.delivery &&\n sameMetadata(JSON.parse(current.metadata_json) as DoomSessionDeliveryMetadata, envelope.metadata);\n if (!sameEnvelope) return undefined;\n publishAck(envelope.deliveryId, current.sender_key, current.state);\n if (current.state === 'accepted') scheduleAdmission(envelope.deliveryId);\n return current.state;\n };\n\n const receiveAck = (recipientKey: string, value: unknown): void => {\n const ack = ackOf(value);\n if (closed || !ack) return;\n database\n .prepare(\n `UPDATE session_delivery_outbox\n SET state = 'acknowledged', recipient_state = ?, acknowledged_at = ?\n WHERE delivery_id = ? AND recipient_key = ?`,\n )\n .run(ack.state, Date.now(), ack.deliveryId, recipientKey);\n };\n\n const publishOutbox = (deliveryId: string): void => {\n const row = database\n .prepare(\"SELECT * FROM session_delivery_outbox WHERE delivery_id = ? AND state = 'queued'\")\n .get(deliveryId) as OutboxRow | undefined;\n if (!row) return;\n const metadata = JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata;\n if (!options.authorizePeer(row.recipient_key, metadata)) return;\n options.communication.publish(row.recipient_key, DELIVERY_EVENT, {\n deliveryId: row.delivery_id,\n kind: row.kind,\n prompt: row.prompt,\n delivery: row.delivery_mode,\n metadata,\n } satisfies DeliveryEnvelope);\n };\n\n const publishQueued = (recipientKey: string): void => {\n for (const row of database\n .prepare(\"SELECT delivery_id FROM session_delivery_outbox WHERE recipient_key = ? AND state = 'queued'\")\n .all(recipientKey) as { delivery_id: string }[]) {\n publishOutbox(row.delivery_id);\n }\n };\n const publishAllQueued = (): void => {\n for (const row of database\n .prepare(\"SELECT delivery_id FROM session_delivery_outbox WHERE state = 'queued'\")\n .all() as { delivery_id: string }[]) {\n publishOutbox(row.delivery_id);\n }\n };\n const releaseEnvelope = options.communication.subscribe(DELIVERY_EVENT, receiveEnvelope);\n const releaseAck = options.communication.subscribe(ACK_EVENT, receiveAck);\n const releaseReady = options.communication.onPeerReady(publishQueued);\n\n for (const row of database\n .prepare(\"SELECT delivery_id, sender_key FROM session_delivery_inbox WHERE state = 'recovery_required'\")\n .all() as { delivery_id: string; sender_key: string }[]) {\n publishAck(row.delivery_id, row.sender_key, 'recovery_required');\n }\n for (const row of database\n .prepare(\"SELECT delivery_id FROM session_delivery_inbox WHERE state = 'accepted'\")\n .all() as {\n delivery_id: string;\n }[]) {\n scheduleAdmission(row.delivery_id);\n }\n publishAllQueued();\n // A publish only means the transport accepted the envelope. Repeat stable delivery\n // IDs until the durable acknowledgement arrives, including after a tunnel restart.\n const retryTimer = setInterval(publishAllQueued, 1_000);\n retryTimer.unref();\n\n return Object.freeze({\n recipientKey: options.recipientKey,\n async deliver(request: DoomSessionDeliveryRequest): Promise<{ deliveryId: string }> {\n if (closed) throw new Error('Session delivery service is closed.');\n const deliveryId = request.deliveryId ?? crypto.randomUUID();\n const mode = request.delivery ?? DEFAULT_DELIVERY;\n if (!deliveryId.trim() || !request.recipientKey.trim() || !request.kind.trim() || !isMode(mode)) {\n throw new TypeError('Delivery id, recipient key, kind, and mode must be valid.');\n }\n if (!options.authorizePeer(request.recipientKey, request.metadata)) {\n throw new Error(`Session '${request.recipientKey}' is not an authorized communication peer.`);\n }\n const metadata = normalizedMetadata(request.metadata);\n database\n .prepare(\n `INSERT OR IGNORE INTO session_delivery_outbox\n (delivery_id, recipient_key, kind, prompt, delivery_mode, metadata_json, state, created_at)\n VALUES (?, ?, ?, ?, ?, ?, 'queued', ?)`,\n )\n .run(\n deliveryId,\n request.recipientKey,\n request.kind,\n request.prompt,\n mode,\n JSON.stringify(metadata),\n Date.now(),\n );\n const current = database\n .prepare('SELECT * FROM session_delivery_outbox WHERE delivery_id = ?')\n .get(deliveryId) as OutboxRow | undefined;\n if (\n !current ||\n current.recipient_key !== request.recipientKey ||\n current.kind !== request.kind ||\n current.prompt !== request.prompt ||\n current.delivery_mode !== mode ||\n !sameMetadata(JSON.parse(current.metadata_json) as DoomSessionDeliveryMetadata, metadata)\n ) {\n throw new TypeError(`Delivery id '${deliveryId}' is already bound to another envelope.`);\n }\n publishOutbox(deliveryId);\n return { deliveryId };\n },\n async waitForAdmission(deliveryId: string, timeoutMs = 5_000): Promise<DoomSessionDeliveryInboxState | undefined> {\n const deadline = Date.now() + Math.max(0, timeoutMs);\n let state: DoomSessionDeliveryInboxState | undefined;\n do {\n const row = database\n .prepare('SELECT recipient_state FROM session_delivery_outbox WHERE delivery_id = ?')\n .get(deliveryId) as { recipient_state: DoomSessionDeliveryInboxState | null } | undefined;\n state = row?.recipient_state ?? undefined;\n if (state === 'admitted' || state === 'recovery_required') return state;\n if (Date.now() >= deadline) return state;\n await new Promise((resolve) => setTimeout(resolve, Math.min(10, deadline - Date.now())));\n } while (!closed);\n return state;\n },\n receive(senderKey: string, kind: string, payload: unknown) {\n if (kind === DELIVERY_EVENT) return receiveEnvelope(senderKey, payload);\n if (kind === ACK_EVENT) {\n receiveAck(senderKey, payload);\n return 'accepted';\n }\n return undefined;\n },\n inbox(query: DoomSessionInboxQuery = {}): readonly DoomSessionInboxEntry[] {\n const rows = database\n .prepare('SELECT * FROM session_delivery_inbox ORDER BY created_at, delivery_id')\n .all() as unknown as InboxRow[];\n return rows\n .map((row): DoomSessionInboxEntry => {\n const metadata = JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata;\n return {\n deliveryId: row.delivery_id,\n senderKey: row.sender_key,\n recipientKey: row.recipient_key,\n kind: row.kind,\n prompt: row.prompt,\n delivery: row.delivery_mode,\n metadata,\n state: row.state,\n consumed: row.consumed_at !== null,\n };\n })\n .filter(\n (entry) =>\n (query.kind === undefined || entry.kind === query.kind) &&\n (query.state === undefined || entry.state === query.state) &&\n (query.consumed === undefined || entry.consumed === query.consumed) &&\n matchesMetadata(entry.metadata, query.metadata),\n );\n },\n consume(deliveryId: string): boolean {\n const result = database\n .prepare(\n \"UPDATE session_delivery_inbox SET consumed_at = ? WHERE delivery_id = ? AND state IN ('admitted', 'recovery_required') AND consumed_at IS NULL\",\n )\n .run(Date.now(), deliveryId);\n return result.changes === 1;\n },\n outbox(deliveryId: string): DoomSessionOutboxEntry | undefined {\n const row = database\n .prepare(\n 'SELECT delivery_id, recipient_key, kind, metadata_json, state, recipient_state FROM session_delivery_outbox WHERE delivery_id = ?',\n )\n .get(deliveryId) as OutboxRow | undefined;\n if (!row) return undefined;\n return {\n deliveryId: row.delivery_id,\n recipientKey: row.recipient_key,\n kind: row.kind,\n metadata: JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata,\n state: row.state,\n ...(row.recipient_state === null ? {} : { recipientState: row.recipient_state }),\n };\n },\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n clearInterval(retryTimer);\n releaseEnvelope();\n releaseAck();\n releaseReady();\n try {\n await admissionQueue;\n } finally {\n database.close();\n }\n },\n });\n}\n\n/**\n * Installs a provider-owned endpoint in the current Cordis context.\n *\n * Returns the instance because a provider cannot read its own service back out:\n * `ctx.get` is strict and hides an implementation while its providing fiber is\n * LOADING, which is the whole of that fiber's own callback.\n */\nexport function provideSessionDeliveryService(\n context: Context,\n options: SessionDeliveryServiceOptions,\n): { readonly service: DoomSessionDeliveryService; readonly close: () => Promise<void> } {\n const service = createSessionDeliveryService(options);\n const unprovide = context.provide(DOOM_SESSION_DELIVERY_SERVICE, service);\n // A caller that throws before returning its disposer would otherwise leave the\n // database, its WAL files and its retry timer open for the life of the process.\n // close() is idempotent, so this net never conflicts with the ordered close below.\n context.effect(() => () => service.close(), 'session delivery database');\n return {\n service,\n close: async () => {\n unprovide();\n await service.close();\n },\n };\n}\n\nexport type {\n DoomSessionDeliveryInboxState,\n DoomSessionDeliveryMetadata,\n DoomSessionDeliveryMode,\n DoomSessionDeliveryRequest,\n DoomSessionDeliveryService,\n DoomSessionInboxEntry,\n DoomSessionInboxQuery,\n DoomSessionOutboxEntry,\n SessionDeliveryServiceOptions,\n} from './type';\nexport { DOOM_SESSION_DELIVERY_SERVICE, readDoomSessionDelivery } from './type';\n"],"mappings":"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"}
1
+ {"version":3,"file":"sessionDelivery-C_2qtUoE.cjs","names":["path","fs","createHash","createHmac","DatabaseSync","timingSafeEqual","envelopeOf","DatabaseSync","DatabaseSync"],"sources":["../src/services/peerTransport/index.ts","../src/services/sessionDirectory/index.ts","../src/services/sessionGroups/type.ts","../src/services/sessionGroups/index.ts","../src/services/sessionIntercom/type.ts","../src/services/sessionIntercom/index.ts","../src/services/sessionDelivery/type.ts","../src/services/sessionDelivery/index.ts"],"sourcesContent":["import { createHash, createHmac, timingSafeEqual } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\n\nimport type { DoomSessionCommunicationEndpoint } from '@agimon-ai/doompi-core/hubChannel';\n\nconst PEER_CONFIG_VERSION = 1;\nconst PEER_CONFIG_FILE = 'peers.json';\nconst PEER_ROUTE = '/api/plugins/session-peer/inbox';\nconst PEER_HEADER = 'x-doompi-session-peer';\nconst TIMESTAMP_HEADER = 'x-doompi-session-timestamp';\nconst SIGNATURE_HEADER = 'x-doompi-session-signature';\nconst MAX_CLOCK_SKEW_MS = 5 * 60_000;\nconst MAX_REPLAY_ENTRIES = 10_000;\nconst REPLAY_DATABASE_FILE = 'peer-replay.sqlite';\n\nexport interface SessionPeer {\n readonly hostId: string;\n readonly url: string;\n readonly secret: string;\n /** Explicit remote durable-message targets. Empty means no delivery grant. */\n readonly allowedSessionIds: readonly string[];\n /** Explicit remote Voice media targets. Empty means no media grant. */\n readonly allowedVoiceSessionIds: readonly string[];\n}\n\nexport interface SessionPeerConfig {\n readonly version: typeof PEER_CONFIG_VERSION;\n readonly hostId: string;\n readonly peers: readonly SessionPeer[];\n}\n\nexport interface RemoteSessionReference {\n readonly hostId: string;\n readonly sessionId: string;\n}\n\nexport interface SessionPeerEnvelope {\n readonly sourceSessionId: string;\n readonly targetSessionId: string;\n readonly type: string;\n readonly payload: unknown;\n}\n\nexport interface SessionPeerReplayGuard {\n admit(request: Request, now?: number): boolean;\n close(): void;\n}\n\nfunction validId(value: unknown): value is string {\n return typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(value);\n}\n\nfunction peerOf(value: unknown): SessionPeer | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n if (!validId(record.hostId) || typeof record.url !== 'string' || typeof record.secret !== 'string') return undefined;\n let url: URL;\n try {\n url = new URL(record.url);\n } catch {\n return undefined;\n }\n if (url.protocol !== 'https:' || url.username !== '' || url.password !== '' || url.search !== '' || url.hash !== '')\n return undefined;\n const allowedSessionIds =\n Array.isArray(record.allowedSessionIds) && record.allowedSessionIds.every(validId)\n ? record.allowedSessionIds\n : undefined;\n const allowedVoiceSessionIds =\n Array.isArray(record.allowedVoiceSessionIds) && record.allowedVoiceSessionIds.every(validId)\n ? record.allowedVoiceSessionIds\n : [];\n if (allowedSessionIds === undefined || record.secret.length < 32) return undefined;\n return {\n hostId: record.hostId,\n url: url.toString(),\n secret: record.secret,\n allowedSessionIds,\n allowedVoiceSessionIds,\n };\n}\n\nexport function sessionPeerConfigPath(homeDirectory: string): string {\n return path.join(homeDirectory, '.pi', '.doom', 'session', PEER_CONFIG_FILE);\n}\n\n/** Reads operator-provisioned peers. Invalid or unreadable config fails closed. */\nexport function readSessionPeerConfig(homeDirectory: string): SessionPeerConfig | undefined {\n let parsed: unknown;\n try {\n const file = sessionPeerConfigPath(homeDirectory);\n if ((fs.statSync(file).mode & 0o077) !== 0) return undefined;\n parsed = JSON.parse(fs.readFileSync(file, 'utf8')) as unknown;\n } catch {\n return undefined;\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return undefined;\n const record = parsed as Record<string, unknown>;\n if (record.version !== PEER_CONFIG_VERSION || !validId(record.hostId) || !Array.isArray(record.peers))\n return undefined;\n const peers = record.peers.map(peerOf);\n if (peers.some((peer) => peer === undefined)) return undefined;\n const resolved = peers as SessionPeer[];\n if (\n new Set(resolved.map((peer) => peer.hostId)).size !== resolved.length ||\n resolved.some((peer) => peer.hostId === record.hostId)\n )\n return undefined;\n return { version: PEER_CONFIG_VERSION, hostId: record.hostId, peers: resolved };\n}\n\n/** `peer/<host-id>/<session-id>` is the only remote target spelling. */\nexport function parseRemoteSessionReference(value: string): RemoteSessionReference | undefined {\n const match = /^peer\\/([^/]+)\\/([^/]+)$/u.exec(value);\n return match && validId(match[1]) && validId(match[2]) ? { hostId: match[1], sessionId: match[2] } : undefined;\n}\n\nexport function peerSessionReference(hostId: string, sessionId: string): string {\n if (!validId(hostId) || !validId(sessionId))\n throw new TypeError('Remote host and session identifiers must be safe opaque IDs.');\n return `peer/${hostId}/${sessionId}`;\n}\n\nfunction signature(secret: string, method: string, pathname: string, timestamp: string, body: string): string {\n const digest = createHash('sha256').update(body).digest('base64url');\n return createHmac('sha256', secret).update(`${method}\\n${pathname}\\n${timestamp}\\n${digest}`).digest('base64url');\n}\n\nexport function peerRequestHeaders(\n sourceHostId: string,\n peer: SessionPeer,\n method: string,\n pathname: string,\n body: string,\n now = Date.now(),\n): Headers {\n if (!validId(sourceHostId)) throw new TypeError('Source host identity must be a safe opaque ID.');\n const timestamp = String(now);\n return new Headers({\n 'content-type': 'application/json',\n [PEER_HEADER]: sourceHostId,\n [TIMESTAMP_HEADER]: timestamp,\n [SIGNATURE_HEADER]: signature(peer.secret, method, pathname, timestamp, body),\n });\n}\n\n/** Persists accepted peer signatures so a valid request cannot be replayed within its clock-skew window. */\nexport function createPeerReplayGuard(homeDirectory: string): SessionPeerReplayGuard {\n const directory = path.dirname(sessionPeerConfigPath(homeDirectory));\n fs.mkdirSync(directory, { recursive: true, mode: 0o700 });\n const database = new DatabaseSync(path.join(directory, REPLAY_DATABASE_FILE));\n database.exec(`\n PRAGMA journal_mode = WAL;\n CREATE TABLE IF NOT EXISTS peer_request_replays (\n signature TEXT PRIMARY KEY,\n expires_at INTEGER NOT NULL\n );\n `);\n const removeExpired = database.prepare('DELETE FROM peer_request_replays WHERE expires_at < ?');\n const insert = database.prepare('INSERT OR IGNORE INTO peer_request_replays (signature, expires_at) VALUES (?, ?)');\n const count = database.prepare('SELECT COUNT(*) AS count FROM peer_request_replays');\n const trim = database.prepare(`\n DELETE FROM peer_request_replays\n WHERE signature IN (\n SELECT signature FROM peer_request_replays ORDER BY expires_at ASC, signature ASC LIMIT ?\n )\n `);\n return {\n admit(request, now = Date.now()) {\n const supplied = request.headers.get(SIGNATURE_HEADER);\n if (!supplied) return false;\n database.exec('BEGIN IMMEDIATE');\n try {\n removeExpired.run(now);\n const accepted = insert.run(supplied, now + MAX_CLOCK_SKEW_MS).changes === 1;\n const total = Number((count.get() as { count: number | bigint }).count);\n if (total > MAX_REPLAY_ENTRIES) trim.run(total - MAX_REPLAY_ENTRIES);\n database.exec('COMMIT');\n return accepted;\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n },\n close: () => database.close(),\n };\n}\n\nexport function verifyPeerRequest(\n config: SessionPeerConfig,\n request: Request,\n body: string,\n now = Date.now(),\n): SessionPeer | undefined {\n const hostId = request.headers.get(PEER_HEADER);\n const timestamp = request.headers.get(TIMESTAMP_HEADER);\n const supplied = request.headers.get(SIGNATURE_HEADER);\n if (!hostId || !timestamp || !supplied || !/^\\d{1,16}$/u.test(timestamp)) return undefined;\n const sentAt = Number(timestamp);\n if (!Number.isSafeInteger(sentAt) || Math.abs(now - sentAt) > MAX_CLOCK_SKEW_MS) return undefined;\n const peer = config.peers.find((candidate) => candidate.hostId === hostId);\n if (!peer) return undefined;\n const expected = Buffer.from(signature(peer.secret, request.method, new URL(request.url).pathname, timestamp, body));\n const actual = Buffer.from(supplied);\n return actual.byteLength === expected.byteLength && timingSafeEqual(actual, expected) ? peer : undefined;\n}\n\nfunction envelopeOf(value: unknown): SessionPeerEnvelope | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n return validId(record.sourceSessionId) &&\n validId(record.targetSessionId) &&\n typeof record.type === 'string' &&\n record.type !== ''\n ? {\n sourceSessionId: record.sourceSessionId,\n targetSessionId: record.targetSessionId,\n type: record.type,\n payload: record.payload,\n }\n : undefined;\n}\n\nexport function parseSessionPeerEnvelope(value: unknown): SessionPeerEnvelope | undefined {\n return envelopeOf(value);\n}\n\n/** Adds asynchronous tunnel publication to a host-bound local communication endpoint. */\nexport function createPeerCommunication(options: {\n readonly local: DoomSessionCommunicationEndpoint;\n readonly homeDirectory: string;\n readonly fetch?: typeof fetch;\n}): DoomSessionCommunicationEndpoint {\n const config = readSessionPeerConfig(options.homeDirectory);\n const send = options.fetch ?? fetch;\n return {\n sessionId: options.local.sessionId,\n publish(target, type, payload) {\n const remote = parseRemoteSessionReference(target);\n if (!remote) return options.local.publish(target, type, payload);\n const peer = config?.peers.find((candidate) => candidate.hostId === remote.hostId);\n // Pairing is not a grant. Outbound delivery needs the same explicit target\n // allowlist that the receiver enforces for inbound envelopes.\n if (!config || !peer || !peer.allowedSessionIds.includes(remote.sessionId)) return false;\n const body = JSON.stringify({\n sourceSessionId: options.local.sessionId,\n targetSessionId: remote.sessionId,\n type,\n payload,\n });\n const url = new URL(PEER_ROUTE, peer.url);\n void send(url, {\n method: 'POST',\n headers: peerRequestHeaders(config.hostId, peer, 'POST', '/inbox', body),\n body,\n }).catch(() => undefined);\n return true;\n },\n subscribe: (type, listener) => options.local.subscribe(type, listener),\n onPeerReady: (listener) => options.local.onPeerReady(listener),\n close: () => options.local.close(),\n };\n}\n","import { peerSessionReference } from '../peerTransport';\nimport type {\n DiscoveredSession,\n SessionDirectory,\n SessionDirectoryOptions,\n SessionPresenceFacts,\n SessionPresenceObservation,\n} from './type';\n\nconst UNKNOWN_FACTS: SessionPresenceFacts = Object.freeze({\n reachability: 'unknown',\n runtime: 'unknown',\n activity: 'unknown',\n voice: Object.freeze({ eligible: 'unknown', readiness: 'unknown' }),\n});\n\nfunction keyOf(observation: Pick<SessionPresenceObservation, 'hostId' | 'sessionId'>): string {\n return peerSessionReference(observation.hostId, observation.sessionId);\n}\n\nfunction publicEntry(\n observation: SessionPresenceObservation,\n now: number,\n label: string | undefined,\n capabilities: readonly string[],\n): DiscoveredSession {\n const freshUntil = observation.observedAt + observation.staleAfterMs;\n const fresh = now <= freshUntil;\n const facts: SessionPresenceFacts = fresh ? observation : UNKNOWN_FACTS;\n return Object.freeze({\n reference: keyOf(observation),\n ...(label === undefined ? {} : { label }),\n capabilities: Object.freeze([...capabilities]),\n hostIncarnation: observation.hostIncarnation,\n sessionIncarnation: observation.sessionIncarnation,\n sequence: observation.sequence,\n observedAt: observation.observedAt,\n freshUntil,\n fresh,\n reachability: facts.reachability,\n runtime: facts.runtime,\n activity: facts.activity,\n voice: Object.freeze({ ...facts.voice }),\n });\n}\n\n/** In-memory authenticated presence cache. Restart deliberately forgets every observation. */\nexport function createSessionDirectory(options: SessionDirectoryOptions): SessionDirectory {\n const now = options.now ?? Date.now;\n const observations = new Map<string, SessionPresenceObservation>();\n const snapshotRequired = new Set<string>();\n const subscribers = new Set<{\n callerReference: string;\n listener: (sessions: readonly DiscoveredSession[]) => void;\n }>();\n\n const discover = (callerReference: string, allowedReferences?: ReadonlySet<string>): readonly DiscoveredSession[] => {\n const result: DiscoveredSession[] = [];\n for (const observation of observations.values()) {\n const reference = keyOf(observation);\n if (allowedReferences && !allowedReferences.has(reference)) continue;\n const grant = options.authorizeDiscovery(callerReference, observation);\n if (!grant) continue;\n result.push(publicEntry(observation, now(), grant.label ?? observation.label, grant.capabilities));\n }\n return result.sort((left, right) => left.reference.localeCompare(right.reference));\n };\n const notify = (): void => {\n for (const subscriber of subscribers) subscriber.listener(discover(subscriber.callerReference));\n };\n\n return {\n observe(observation) {\n const key = keyOf(observation);\n const current = observations.get(key);\n if (snapshotRequired.has(observation.hostId)) return false;\n if (current?.hostIncarnation === observation.hostIncarnation) {\n if (current.sessionIncarnation === observation.sessionIncarnation && observation.sequence <= current.sequence)\n return false;\n if (observation.sequence !== current.sequence + 1) {\n snapshotRequired.add(observation.hostId);\n for (const [reference, candidate] of observations)\n if (candidate.hostId === observation.hostId)\n observations.set(reference, { ...candidate, ...UNKNOWN_FACTS, observedAt: now(), staleAfterMs: 0 });\n notify();\n return false;\n }\n }\n observations.set(key, Object.freeze({ ...observation, voice: Object.freeze({ ...observation.voice }) }));\n notify();\n return true;\n },\n replaceHostSnapshot(hostId, hostIncarnation, replacements) {\n if (\n replacements.some(\n (observation) => observation.hostId !== hostId || observation.hostIncarnation !== hostIncarnation,\n )\n ) {\n throw new TypeError('A presence snapshot must contain only the declared host incarnation.');\n }\n for (const [reference, observation] of observations)\n if (observation.hostId === hostId) observations.delete(reference);\n for (const observation of replacements)\n observations.set(\n keyOf(observation),\n Object.freeze({ ...observation, voice: Object.freeze({ ...observation.voice }) }),\n );\n snapshotRequired.delete(hostId);\n notify();\n },\n hostDisconnected(hostId) {\n for (const [reference, observation] of observations) {\n if (observation.hostId !== hostId) continue;\n observations.set(reference, { ...observation, reachability: 'unreachable' });\n }\n notify();\n },\n discover,\n resolveDeliveryTarget(callerReference, reference) {\n const observation = observations.get(reference);\n return observation && options.authorizeDiscovery(callerReference, observation)\n ? observation.deliveryTarget\n : undefined;\n },\n subscribe(callerReference, listener) {\n const subscriber = { callerReference, listener };\n subscribers.add(subscriber);\n listener(discover(callerReference));\n return () => subscribers.delete(subscriber);\n },\n };\n}\n\nexport type {\n DiscoveredSession,\n SessionActivityState,\n SessionDirectory,\n SessionDirectoryOptions,\n SessionDiscoveryGrant,\n SessionHostReachability,\n SessionPresenceFacts,\n SessionPresenceObservation,\n SessionRuntimeState,\n SessionVoiceReadiness,\n} from './type';\n","export interface SessionCommunicationGroup {\n readonly id: string;\n readonly ownerAuthority: string;\n readonly revision: number;\n readonly members: readonly string[];\n}\n\nexport interface SessionGroupMutation {\n readonly groupId: string;\n readonly authority: string;\n readonly expectedRevision: number;\n readonly add?: readonly string[];\n readonly remove?: readonly string[];\n}\n\nexport interface SessionGroupStoreOptions {\n readonly databasePath: string;\n readonly authorizeManagement?: (authority: string, group: SessionCommunicationGroup) => boolean;\n readonly validateEnrollment?: (groupId: string, memberReference: string) => boolean;\n}\n\nexport interface SessionGroupStore {\n create(groupId: string, ownerAuthority: string, members: readonly string[]): SessionCommunicationGroup;\n mutate(mutation: SessionGroupMutation): SessionCommunicationGroup;\n get(groupId: string): SessionCommunicationGroup | undefined;\n groupsFor(memberReference: string): readonly SessionCommunicationGroup[];\n canMessage(groupId: string, sourceReference: string, targetReference: string): boolean;\n close(): void;\n}\n\nexport class SessionGroupRevisionError extends Error {\n constructor(groupId: string, expected: number, actual: number) {\n super(`Session group '${groupId}' revision conflict: expected ${expected}, current ${actual}.`);\n this.name = 'SessionGroupRevisionError';\n }\n}\n","import { DatabaseSync } from 'node:sqlite';\n\nimport {\n SessionGroupRevisionError,\n type SessionCommunicationGroup,\n type SessionGroupMutation,\n type SessionGroupStore,\n type SessionGroupStoreOptions,\n} from './type';\n\ninterface GroupRow {\n group_id: string;\n owner_authority: string;\n revision: number;\n}\n\nconst ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;\nconst REFERENCE_PATTERN = /^peer\\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}\\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;\n\nfunction validateGroupId(value: string): void {\n if (!ID_PATTERN.test(value)) throw new TypeError('Session group IDs must be safe opaque IDs.');\n}\n\nfunction validateReference(value: string): void {\n if (!REFERENCE_PATTERN.test(value))\n throw new TypeError(`Session group member '${value}' is not a qualified reference.`);\n}\n\n/** Opens a revisioned SQLite registry for communication-only group membership. */\nexport function createSessionGroupStore(options: SessionGroupStoreOptions): SessionGroupStore {\n const database = new DatabaseSync(options.databasePath);\n database.exec(`\n PRAGMA journal_mode = WAL;\n PRAGMA foreign_keys = ON;\n CREATE TABLE IF NOT EXISTS session_groups (\n group_id TEXT PRIMARY KEY,\n owner_authority TEXT NOT NULL,\n revision INTEGER NOT NULL\n );\n CREATE TABLE IF NOT EXISTS session_group_members (\n group_id TEXT NOT NULL REFERENCES session_groups(group_id) ON DELETE CASCADE,\n member_reference TEXT NOT NULL,\n PRIMARY KEY (group_id, member_reference)\n );\n `);\n\n const read = (groupId: string): SessionCommunicationGroup | undefined => {\n const row = database.prepare('SELECT * FROM session_groups WHERE group_id = ?').get(groupId) as\n | GroupRow\n | undefined;\n if (!row) return undefined;\n const members = database\n .prepare('SELECT member_reference FROM session_group_members WHERE group_id = ? ORDER BY member_reference')\n .all(groupId) as { member_reference: string }[];\n return Object.freeze({\n id: row.group_id,\n ownerAuthority: row.owner_authority,\n revision: row.revision,\n members: Object.freeze(members.map((member) => member.member_reference)),\n });\n };\n\n const enroll = (groupId: string, members: readonly string[]): void => {\n const insert = database.prepare(\n 'INSERT OR IGNORE INTO session_group_members (group_id, member_reference) VALUES (?, ?)',\n );\n for (const member of new Set(members)) {\n validateReference(member);\n if (options.validateEnrollment?.(groupId, member) === false)\n throw new Error(`Session group enrollment policy rejected '${member}'.`);\n insert.run(groupId, member);\n }\n };\n\n return {\n create(groupId, ownerAuthority, members) {\n validateGroupId(groupId);\n if (!ownerAuthority.trim()) throw new TypeError('Session group owner authority is required.');\n database.exec('BEGIN IMMEDIATE');\n try {\n database\n .prepare('INSERT INTO session_groups (group_id, owner_authority, revision) VALUES (?, ?, 1)')\n .run(groupId, ownerAuthority);\n enroll(groupId, members);\n database.exec('COMMIT');\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n return read(groupId)!;\n },\n mutate(mutation: SessionGroupMutation) {\n database.exec('BEGIN IMMEDIATE');\n try {\n const current = read(mutation.groupId);\n if (!current) throw new Error(`Session group '${mutation.groupId}' does not exist.`);\n if (\n mutation.authority !== current.ownerAuthority &&\n options.authorizeManagement?.(mutation.authority, current) !== true\n ) {\n throw new Error(`Authority '${mutation.authority}' cannot manage Session group '${mutation.groupId}'.`);\n }\n if (mutation.expectedRevision !== current.revision)\n throw new SessionGroupRevisionError(mutation.groupId, mutation.expectedRevision, current.revision);\n enroll(mutation.groupId, mutation.add ?? []);\n const remove = database.prepare(\n 'DELETE FROM session_group_members WHERE group_id = ? AND member_reference = ?',\n );\n for (const member of new Set(mutation.remove ?? [])) {\n validateReference(member);\n remove.run(mutation.groupId, member);\n }\n database\n .prepare('UPDATE session_groups SET revision = revision + 1 WHERE group_id = ? AND revision = ?')\n .run(mutation.groupId, current.revision);\n database.exec('COMMIT');\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n return read(mutation.groupId)!;\n },\n get: read,\n groupsFor(memberReference) {\n validateReference(memberReference);\n const rows = database\n .prepare(\n `SELECT g.group_id FROM session_groups g\n INNER JOIN session_group_members m ON m.group_id = g.group_id\n WHERE m.member_reference = ? ORDER BY g.group_id`,\n )\n .all(memberReference) as { group_id: string }[];\n return rows.map((row) => read(row.group_id)!);\n },\n canMessage(groupId, sourceReference, targetReference) {\n validateReference(sourceReference);\n validateReference(targetReference);\n const row = database\n .prepare(\n `SELECT COUNT(*) AS count FROM session_group_members\n WHERE group_id = ? AND member_reference IN (?, ?)`,\n )\n .get(groupId, sourceReference, targetReference) as { count: number | bigint };\n return Number(row.count) === (sourceReference === targetReference ? 1 : 2);\n },\n close: () => database.close(),\n };\n}\n\nexport {\n SessionGroupRevisionError,\n type SessionCommunicationGroup,\n type SessionGroupMutation,\n type SessionGroupStore,\n type SessionGroupStoreOptions,\n} from './type';\n","import type { Context } from '@deepseek-ai/cordis';\n\nimport type {\n DoomSessionDeliveryMetadata,\n DoomSessionDeliveryService,\n DoomSessionInboxEntry,\n DoomSessionOutboxEntry,\n} from '../sessionDelivery';\nimport type { DiscoveredSession, SessionDirectory } from '../sessionDirectory';\nimport type { SessionGroupStore } from '../sessionGroups';\n\nexport const DOOM_SESSION_INTERCOM_SERVICE = 'doom/session-intercom';\n\nexport type SessionReportStatus = 'done' | 'blocked' | 'failed';\n\nexport interface SessionIntercomMessage {\n readonly deliveryId: string;\n readonly sourceReference: string;\n readonly targetReference: string;\n readonly groupId: string;\n readonly correlationId?: string;\n readonly text: string;\n readonly reportStatus?: SessionReportStatus;\n readonly state: DoomSessionInboxEntry['state'];\n readonly consumed: boolean;\n}\n\nexport interface SessionIntercomSendRequest {\n readonly targetReference: string;\n readonly groupId: string;\n readonly text: string;\n readonly correlationId?: string;\n readonly deliveryId?: string;\n}\n\nexport interface SessionIntercomOptions {\n readonly selfReference: string;\n readonly directory: SessionDirectory;\n readonly groups: SessionGroupStore;\n readonly delivery: DoomSessionDeliveryService;\n}\n\nexport interface SessionIntercom {\n discover(): readonly DiscoveredSession[];\n send(request: SessionIntercomSendRequest): Promise<{ deliveryId: string }>;\n report(\n request: SessionIntercomSendRequest & { readonly status: SessionReportStatus },\n ): Promise<{ deliveryId: string }>;\n messages(): readonly SessionIntercomMessage[];\n delivery(deliveryId: string): DoomSessionOutboxEntry | undefined;\n}\n\nexport interface SessionGroupDeliveryAuthorizationOptions {\n readonly selfReference: string;\n readonly groups: SessionGroupStore;\n readonly peerReference: (peerKey: string) => string | undefined;\n readonly fallback?: (peerKey: string, metadata: DoomSessionDeliveryMetadata | undefined) => boolean;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/session-intercom': SessionIntercom;\n }\n}\n\nexport function readSessionIntercom(context: Context): SessionIntercom | undefined {\n return context.get(DOOM_SESSION_INTERCOM_SERVICE) as SessionIntercom | undefined;\n}\n\nexport function requireSessionIntercom(context: Context): SessionIntercom {\n const service = readSessionIntercom(context);\n if (!service)\n throw new Error('Session intercom is unavailable. Activate Session with a configured persistent host identity.');\n return service;\n}\n","import type { DoomSessionDeliveryMetadata } from '../sessionDelivery';\nimport type { SessionIntercomMessage } from './type';\nimport type {\n SessionGroupDeliveryAuthorizationOptions,\n SessionIntercom,\n SessionIntercomOptions,\n SessionIntercomSendRequest,\n SessionReportStatus,\n} from './type';\n\nconst MESSAGE_KIND = 'session-message';\nconst REPORT_KIND = 'session-report';\n\nfunction metadataFor(\n options: SessionIntercomOptions,\n request: SessionIntercomSendRequest,\n reportStatus?: SessionReportStatus,\n): DoomSessionDeliveryMetadata {\n const group = options.groups.get(request.groupId);\n if (!group || !options.groups.canMessage(request.groupId, options.selfReference, request.targetReference))\n throw new Error(`Session group '${request.groupId}' does not authorize this message.`);\n return {\n sourceReference: options.selfReference,\n targetReference: request.targetReference,\n groupId: request.groupId,\n groupRevision: String(group.revision),\n ...(request.correlationId === undefined ? {} : { correlationId: request.correlationId }),\n ...(reportStatus === undefined ? {} : { reportStatus }),\n };\n}\n\n/** Agent-facing intercom operations. A composition may acquire this service without gaining session controls. */\nexport function createSessionIntercom(options: SessionIntercomOptions): SessionIntercom {\n const deliver = async (\n request: SessionIntercomSendRequest,\n kind: typeof MESSAGE_KIND | typeof REPORT_KIND,\n status?: SessionReportStatus,\n ): Promise<{ deliveryId: string }> => {\n const recipientKey = options.directory.resolveDeliveryTarget(options.selfReference, request.targetReference);\n if (!recipientKey) throw new Error(`Session '${request.targetReference}' is not discoverable.`);\n const metadata = metadataFor(options, request, status);\n return options.delivery.deliver({\n ...(request.deliveryId === undefined ? {} : { deliveryId: request.deliveryId }),\n recipientKey,\n kind,\n prompt: `[Session ${status === undefined ? 'message' : `report: ${status}`} from ${options.selfReference}] ${request.text}`,\n metadata,\n });\n };\n\n const intercom: SessionIntercom = {\n discover() {\n const members = new Set(\n options.groups\n .groupsFor(options.selfReference)\n .flatMap((group) => group.members)\n .filter((reference) => reference !== options.selfReference),\n );\n return options.directory.discover(options.selfReference, members);\n },\n send: (request) => deliver(request, MESSAGE_KIND),\n report: (request) => deliver(request, REPORT_KIND, request.status),\n messages() {\n return options.delivery\n .inbox()\n .filter((entry) => entry.kind === MESSAGE_KIND || entry.kind === REPORT_KIND)\n .filter((entry) => {\n const groupId = entry.metadata.groupId;\n return groupId !== undefined && options.groups.get(groupId)?.members.includes(options.selfReference) === true;\n })\n .flatMap((entry): SessionIntercomMessage[] => {\n const sourceReference = entry.metadata.sourceReference;\n const targetReference = entry.metadata.targetReference;\n const groupId = entry.metadata.groupId;\n if (!sourceReference || !targetReference || !groupId) return [];\n const reportStatus = entry.metadata.reportStatus;\n return [\n {\n deliveryId: entry.deliveryId,\n sourceReference,\n targetReference,\n groupId,\n ...(entry.metadata.correlationId === undefined ? {} : { correlationId: entry.metadata.correlationId }),\n text: entry.prompt,\n ...(reportStatus === 'done' || reportStatus === 'blocked' || reportStatus === 'failed'\n ? { reportStatus }\n : {}),\n state: entry.state,\n consumed: entry.consumed,\n },\n ];\n });\n },\n delivery(deliveryId) {\n const entry = options.delivery.outbox(deliveryId);\n const groupId = entry?.metadata.groupId;\n return entry &&\n groupId !== undefined &&\n options.groups.get(groupId)?.members.includes(options.selfReference) === true\n ? entry\n : undefined;\n },\n };\n return Object.freeze(intercom);\n}\n\n/** Builds the dynamic delivery check used before every send, retry, and recipient acceptance. */\nexport function createSessionGroupDeliveryAuthorizer(\n options: SessionGroupDeliveryAuthorizationOptions,\n): (peerKey: string, metadata: DoomSessionDeliveryMetadata | undefined) => boolean {\n return (peerKey, metadata) => {\n const sourceReference = metadata?.sourceReference;\n const targetReference = metadata?.targetReference;\n const groupId = metadata?.groupId;\n if (sourceReference && targetReference && groupId) {\n const peerReference = options.peerReference(peerKey);\n if (!peerReference) return false;\n const directionMatches =\n (sourceReference === options.selfReference && targetReference === peerReference) ||\n (targetReference === options.selfReference && sourceReference === peerReference);\n return directionMatches && options.groups.canMessage(groupId, sourceReference, targetReference);\n }\n return options.fallback?.(peerKey, metadata) === true;\n };\n}\n\nexport { DOOM_SESSION_INTERCOM_SERVICE, readSessionIntercom, requireSessionIntercom } from './type';\nexport type {\n SessionGroupDeliveryAuthorizationOptions,\n SessionIntercom,\n SessionIntercomMessage,\n SessionIntercomOptions,\n SessionIntercomSendRequest,\n SessionReportStatus,\n} from './type';\n","import type { DoomSessionCommunicationEndpoint } from '@agimon-ai/doompi-core/hubChannel';\nimport type { Context } from '@deepseek-ai/cordis';\n\nexport const DOOM_SESSION_DELIVERY_SERVICE = 'doom/session-delivery';\n\nexport type DoomSessionDeliveryInboxState = 'accepted' | 'admitting' | 'admitted' | 'recovery_required';\nexport type DoomSessionDeliveryMode = 'prompt' | 'steer' | 'followUp';\n\nexport interface DoomSessionDeliveryMetadata extends Readonly<Record<string, string | undefined>> {\n readonly worktreeId?: string;\n readonly fromRole?: string;\n}\n\nexport interface DoomSessionDeliveryRequest {\n readonly deliveryId?: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery?: DoomSessionDeliveryMode;\n readonly metadata?: DoomSessionDeliveryMetadata;\n}\n\nexport interface DoomSessionInboxQuery {\n readonly kind?: string;\n readonly metadata?: DoomSessionDeliveryMetadata;\n readonly state?: DoomSessionDeliveryInboxState;\n readonly consumed?: boolean;\n}\n\nexport interface DoomSessionInboxEntry {\n readonly deliveryId: string;\n readonly senderKey: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery: DoomSessionDeliveryMode;\n readonly metadata: DoomSessionDeliveryMetadata;\n readonly state: DoomSessionDeliveryInboxState;\n readonly consumed: boolean;\n}\n\nexport interface DoomSessionOutboxEntry {\n readonly deliveryId: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly metadata: DoomSessionDeliveryMetadata;\n readonly state: 'queued' | 'acknowledged';\n readonly recipientState?: DoomSessionDeliveryInboxState;\n}\n\nexport interface DoomSessionDeliveryService {\n readonly recipientKey: string;\n deliver(request: DoomSessionDeliveryRequest): Promise<{ deliveryId: string }>;\n waitForAdmission(deliveryId: string, timeoutMs?: number): Promise<DoomSessionDeliveryInboxState | undefined>;\n inbox(query?: DoomSessionInboxQuery): readonly DoomSessionInboxEntry[];\n /** Optional host-routed peer envelope admission. Local-only consumers need no transport receiver. */\n receive?(senderKey: string, kind: string, payload: unknown): DoomSessionDeliveryInboxState | undefined;\n consume(deliveryId: string): boolean;\n outbox(deliveryId: string): DoomSessionOutboxEntry | undefined;\n close(): Promise<void>;\n}\n\nexport interface SessionDeliveryServiceOptions {\n readonly databasePath: string;\n readonly recipientKey: string;\n readonly communication: DoomSessionCommunicationEndpoint;\n /** Host-owned relationship check applied before sends, retries, and recipient acceptance. */\n readonly authorizePeer: (peerKey: string, metadata?: DoomSessionDeliveryMetadata) => boolean;\n readonly admitPrompt: (prompt: string, delivery?: DoomSessionDeliveryMode) => Promise<void>;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/session-delivery': DoomSessionDeliveryService;\n }\n}\n\n/** Reads the currently active provider each time, without retaining a stale binding. */\nexport function readDoomSessionDelivery(context: Context): DoomSessionDeliveryService | undefined {\n return context.get(DOOM_SESSION_DELIVERY_SERVICE) as DoomSessionDeliveryService | undefined;\n}\n","import { DatabaseSync } from 'node:sqlite';\n\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport {\n DOOM_SESSION_DELIVERY_SERVICE,\n type DoomSessionDeliveryInboxState,\n type DoomSessionDeliveryMetadata,\n type DoomSessionDeliveryMode,\n type DoomSessionDeliveryRequest,\n type DoomSessionDeliveryService,\n type DoomSessionInboxEntry,\n type DoomSessionInboxQuery,\n type DoomSessionOutboxEntry,\n type SessionDeliveryServiceOptions,\n} from './type';\n\nconst DELIVERY_EVENT = 'doom/session-delivery/envelope';\nconst ACK_EVENT = 'doom/session-delivery/ack';\nconst DEFAULT_DELIVERY: DoomSessionDeliveryMode = 'prompt';\nconst INBOX_STATES = new Set<DoomSessionDeliveryInboxState>(['accepted', 'admitting', 'admitted', 'recovery_required']);\n\ninterface DeliveryEnvelope {\n readonly deliveryId: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery: DoomSessionDeliveryMode;\n readonly metadata: DoomSessionDeliveryMetadata;\n}\n\ninterface DeliveryAck {\n readonly deliveryId: string;\n readonly state: DoomSessionDeliveryInboxState;\n}\n\ninterface InboxRow {\n delivery_id: string;\n sender_key: string;\n recipient_key: string;\n kind: string;\n prompt: string;\n delivery_mode: DoomSessionDeliveryMode;\n metadata_json: string;\n state: DoomSessionDeliveryInboxState;\n consumed_at: number | null;\n}\n\ninterface OutboxRow {\n delivery_id: string;\n recipient_key: string;\n kind: string;\n prompt: string;\n delivery_mode: DoomSessionDeliveryMode;\n metadata_json: string;\n state: 'queued' | 'acknowledged';\n recipient_state: DoomSessionDeliveryInboxState | null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isMode(value: unknown): value is DoomSessionDeliveryMode {\n return value === 'prompt' || value === 'steer' || value === 'followUp';\n}\n\nfunction metadataOf(value: unknown): DoomSessionDeliveryMetadata | undefined {\n if (!isRecord(value)) return undefined;\n const metadata: Record<string, string> = {};\n for (const [key, item] of Object.entries(value)) {\n if (typeof item !== 'string') return undefined;\n metadata[key] = item;\n }\n return metadata;\n}\n\nfunction envelopeOf(value: unknown): DeliveryEnvelope | undefined {\n if (!isRecord(value)) return undefined;\n const metadata = metadataOf(value.metadata);\n if (\n typeof value.deliveryId !== 'string' ||\n !value.deliveryId ||\n typeof value.kind !== 'string' ||\n !value.kind ||\n typeof value.prompt !== 'string' ||\n !isMode(value.delivery) ||\n metadata === undefined\n ) {\n return undefined;\n }\n return {\n deliveryId: value.deliveryId,\n kind: value.kind,\n prompt: value.prompt,\n delivery: value.delivery,\n metadata,\n };\n}\n\nfunction ackOf(value: unknown): DeliveryAck | undefined {\n if (!isRecord(value)) return undefined;\n if (\n typeof value.deliveryId !== 'string' ||\n typeof value.state !== 'string' ||\n !INBOX_STATES.has(value.state as DoomSessionDeliveryInboxState)\n ) {\n return undefined;\n }\n return value as unknown as DeliveryAck;\n}\n\nfunction normalizedMetadata(metadata: DoomSessionDeliveryMetadata | undefined): DoomSessionDeliveryMetadata {\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata ?? {})) {\n if (value !== undefined) normalized[key] = value;\n }\n return normalized;\n}\n\nfunction matchesMetadata(entry: DoomSessionDeliveryMetadata, query: DoomSessionDeliveryMetadata | undefined): boolean {\n return Object.entries(query ?? {}).every(([key, value]) => value === undefined || entry[key] === value);\n}\n\nfunction sameMetadata(left: DoomSessionDeliveryMetadata, right: DoomSessionDeliveryMetadata): boolean {\n return matchesMetadata(left, right) && matchesMetadata(right, left);\n}\n\n/** Opens and starts one durable delivery endpoint. */\nexport function createSessionDeliveryService(options: SessionDeliveryServiceOptions): DoomSessionDeliveryService {\n if (!options.recipientKey.trim() || options.recipientKey !== options.recipientKey.trim()) {\n throw new TypeError('Session delivery requires a trimmed, non-empty recipient key.');\n }\n const database = new DatabaseSync(options.databasePath);\n database.exec(`\n PRAGMA journal_mode = WAL;\n CREATE TABLE IF NOT EXISTS session_delivery_outbox (\n delivery_id TEXT PRIMARY KEY,\n recipient_key TEXT NOT NULL,\n kind TEXT NOT NULL,\n prompt TEXT NOT NULL,\n delivery_mode TEXT NOT NULL,\n metadata_json TEXT NOT NULL,\n state TEXT NOT NULL,\n recipient_state TEXT,\n created_at INTEGER NOT NULL,\n acknowledged_at INTEGER\n );\n CREATE TABLE IF NOT EXISTS session_delivery_inbox (\n delivery_id TEXT PRIMARY KEY,\n sender_key TEXT NOT NULL,\n recipient_key TEXT NOT NULL,\n kind TEXT NOT NULL,\n prompt TEXT NOT NULL,\n delivery_mode TEXT NOT NULL,\n metadata_json TEXT NOT NULL,\n state TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n consumed_at INTEGER\n );\n `);\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE state = 'admitting'\")\n .run(Date.now());\n\n let closed = false;\n const scheduled = new Set<string>();\n let admissionQueue = Promise.resolve();\n\n const publishAck = (deliveryId: string, senderKey: string, state: DoomSessionDeliveryInboxState): void => {\n options.communication.publish(senderKey, ACK_EVENT, { deliveryId, state } satisfies DeliveryAck);\n };\n\n const readInboxRow = (deliveryId: string): InboxRow | undefined =>\n database.prepare('SELECT * FROM session_delivery_inbox WHERE delivery_id = ?').get(deliveryId) as\n | InboxRow\n | undefined;\n\n const scheduleAdmission = (deliveryId: string): void => {\n if (closed || scheduled.has(deliveryId)) return;\n scheduled.add(deliveryId);\n admissionQueue = admissionQueue\n .then(async () => {\n try {\n if (closed) return;\n const row = readInboxRow(deliveryId);\n if (!row || row.state !== 'accepted') return;\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'admitting', updated_at = ? WHERE delivery_id = ?\")\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'admitting');\n try {\n await options.admitPrompt(row.prompt, row.delivery_mode);\n } catch {\n database\n .prepare(\n \"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE delivery_id = ?\",\n )\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'recovery_required');\n return;\n }\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'admitted', updated_at = ? WHERE delivery_id = ?\")\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'admitted');\n } finally {\n scheduled.delete(deliveryId);\n }\n })\n .catch(() => {\n scheduled.delete(deliveryId);\n try {\n const row = readInboxRow(deliveryId);\n if (row?.state !== 'admitting') return;\n database\n .prepare(\n \"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE delivery_id = ?\",\n )\n .run(Date.now(), deliveryId);\n try {\n publishAck(deliveryId, row.sender_key, 'recovery_required');\n } catch {\n // The durable state is authoritative; readiness replay can request another acknowledgement.\n }\n } catch {\n // A database failure remains recoverable on restart when the schema can be opened again.\n }\n });\n };\n\n const receiveEnvelope = (senderKey: string, value: unknown): DoomSessionDeliveryInboxState | undefined => {\n if (closed) return undefined;\n const envelope = envelopeOf(value);\n if (!envelope || !options.authorizePeer(senderKey, envelope.metadata)) return undefined;\n database\n .prepare(\n `INSERT OR IGNORE INTO session_delivery_inbox\n (delivery_id, sender_key, recipient_key, kind, prompt, delivery_mode, metadata_json, state, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, 'accepted', ?, ?)`,\n )\n .run(\n envelope.deliveryId,\n senderKey,\n options.recipientKey,\n envelope.kind,\n envelope.prompt,\n envelope.delivery,\n JSON.stringify(envelope.metadata),\n Date.now(),\n Date.now(),\n );\n const current = readInboxRow(envelope.deliveryId);\n if (!current) return undefined;\n const sameEnvelope =\n current.sender_key === senderKey &&\n current.recipient_key === options.recipientKey &&\n current.kind === envelope.kind &&\n current.prompt === envelope.prompt &&\n current.delivery_mode === envelope.delivery &&\n sameMetadata(JSON.parse(current.metadata_json) as DoomSessionDeliveryMetadata, envelope.metadata);\n if (!sameEnvelope) return undefined;\n publishAck(envelope.deliveryId, current.sender_key, current.state);\n if (current.state === 'accepted') scheduleAdmission(envelope.deliveryId);\n return current.state;\n };\n\n const receiveAck = (recipientKey: string, value: unknown): void => {\n const ack = ackOf(value);\n if (closed || !ack) return;\n database\n .prepare(\n `UPDATE session_delivery_outbox\n SET state = 'acknowledged', recipient_state = ?, acknowledged_at = ?\n WHERE delivery_id = ? AND recipient_key = ?\n AND (recipient_state IS NULL\n OR (recipient_state = 'accepted' AND ? != 'accepted')\n OR (recipient_state = 'admitting' AND ? IN ('admitted', 'recovery_required')))`,\n )\n .run(ack.state, Date.now(), ack.deliveryId, recipientKey, ack.state, ack.state);\n };\n\n const publishOutbox = (deliveryId: string): void => {\n const row = database\n .prepare(\n \"SELECT * FROM session_delivery_outbox WHERE delivery_id = ? AND (recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required'))\",\n )\n .get(deliveryId) as OutboxRow | undefined;\n if (!row) return;\n const metadata = JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata;\n if (!options.authorizePeer(row.recipient_key, metadata)) return;\n options.communication.publish(row.recipient_key, DELIVERY_EVENT, {\n deliveryId: row.delivery_id,\n kind: row.kind,\n prompt: row.prompt,\n delivery: row.delivery_mode,\n metadata,\n } satisfies DeliveryEnvelope);\n };\n\n const publishQueued = (recipientKey: string): void => {\n for (const row of database\n .prepare(\n \"SELECT delivery_id FROM session_delivery_outbox WHERE recipient_key = ? AND (recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required'))\",\n )\n .all(recipientKey) as { delivery_id: string }[]) {\n publishOutbox(row.delivery_id);\n }\n };\n const publishAllQueued = (): void => {\n for (const row of database\n .prepare(\n \"SELECT delivery_id FROM session_delivery_outbox WHERE recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required')\",\n )\n .all() as { delivery_id: string }[]) {\n publishOutbox(row.delivery_id);\n }\n };\n const releaseEnvelope = options.communication.subscribe(DELIVERY_EVENT, receiveEnvelope);\n const releaseAck = options.communication.subscribe(ACK_EVENT, receiveAck);\n const releaseReady = options.communication.onPeerReady(publishQueued);\n\n for (const row of database\n .prepare(\"SELECT delivery_id, sender_key FROM session_delivery_inbox WHERE state = 'recovery_required'\")\n .all() as { delivery_id: string; sender_key: string }[]) {\n publishAck(row.delivery_id, row.sender_key, 'recovery_required');\n }\n for (const row of database\n .prepare(\"SELECT delivery_id FROM session_delivery_inbox WHERE state = 'accepted'\")\n .all() as {\n delivery_id: string;\n }[]) {\n scheduleAdmission(row.delivery_id);\n }\n publishAllQueued();\n // A publish only means the transport accepted the envelope. Repeat stable delivery\n // IDs until a terminal acknowledgement arrives, including after a tunnel restart.\n const retryTimer = setInterval(publishAllQueued, 1_000);\n retryTimer.unref();\n\n return Object.freeze({\n recipientKey: options.recipientKey,\n async deliver(request: DoomSessionDeliveryRequest): Promise<{ deliveryId: string }> {\n if (closed) throw new Error('Session delivery service is closed.');\n const deliveryId = request.deliveryId ?? crypto.randomUUID();\n const mode = request.delivery ?? DEFAULT_DELIVERY;\n if (!deliveryId.trim() || !request.recipientKey.trim() || !request.kind.trim() || !isMode(mode)) {\n throw new TypeError('Delivery id, recipient key, kind, and mode must be valid.');\n }\n if (!options.authorizePeer(request.recipientKey, request.metadata)) {\n throw new Error(`Session '${request.recipientKey}' is not an authorized communication peer.`);\n }\n const metadata = normalizedMetadata(request.metadata);\n database\n .prepare(\n `INSERT OR IGNORE INTO session_delivery_outbox\n (delivery_id, recipient_key, kind, prompt, delivery_mode, metadata_json, state, created_at)\n VALUES (?, ?, ?, ?, ?, ?, 'queued', ?)`,\n )\n .run(\n deliveryId,\n request.recipientKey,\n request.kind,\n request.prompt,\n mode,\n JSON.stringify(metadata),\n Date.now(),\n );\n const current = database\n .prepare('SELECT * FROM session_delivery_outbox WHERE delivery_id = ?')\n .get(deliveryId) as OutboxRow | undefined;\n if (\n !current ||\n current.recipient_key !== request.recipientKey ||\n current.kind !== request.kind ||\n current.prompt !== request.prompt ||\n current.delivery_mode !== mode ||\n !sameMetadata(JSON.parse(current.metadata_json) as DoomSessionDeliveryMetadata, metadata)\n ) {\n throw new TypeError(`Delivery id '${deliveryId}' is already bound to another envelope.`);\n }\n publishOutbox(deliveryId);\n return { deliveryId };\n },\n async waitForAdmission(deliveryId: string, timeoutMs = 5_000): Promise<DoomSessionDeliveryInboxState | undefined> {\n const deadline = Date.now() + Math.max(0, timeoutMs);\n let state: DoomSessionDeliveryInboxState | undefined;\n do {\n const row = database\n .prepare('SELECT recipient_state FROM session_delivery_outbox WHERE delivery_id = ?')\n .get(deliveryId) as { recipient_state: DoomSessionDeliveryInboxState | null } | undefined;\n state = row?.recipient_state ?? undefined;\n if (state === 'admitted' || state === 'recovery_required') return state;\n if (Date.now() >= deadline) return state;\n await new Promise((resolve) => setTimeout(resolve, Math.min(10, deadline - Date.now())));\n } while (!closed);\n return state;\n },\n receive(senderKey: string, kind: string, payload: unknown) {\n if (kind === DELIVERY_EVENT) return receiveEnvelope(senderKey, payload);\n if (kind === ACK_EVENT) {\n receiveAck(senderKey, payload);\n return 'accepted';\n }\n return undefined;\n },\n inbox(query: DoomSessionInboxQuery = {}): readonly DoomSessionInboxEntry[] {\n const rows = database\n .prepare('SELECT * FROM session_delivery_inbox ORDER BY created_at, delivery_id')\n .all() as unknown as InboxRow[];\n return rows\n .map((row): DoomSessionInboxEntry => {\n const metadata = JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata;\n return {\n deliveryId: row.delivery_id,\n senderKey: row.sender_key,\n recipientKey: row.recipient_key,\n kind: row.kind,\n prompt: row.prompt,\n delivery: row.delivery_mode,\n metadata,\n state: row.state,\n consumed: row.consumed_at !== null,\n };\n })\n .filter(\n (entry) =>\n (query.kind === undefined || entry.kind === query.kind) &&\n (query.state === undefined || entry.state === query.state) &&\n (query.consumed === undefined || entry.consumed === query.consumed) &&\n matchesMetadata(entry.metadata, query.metadata),\n );\n },\n consume(deliveryId: string): boolean {\n const result = database\n .prepare(\n \"UPDATE session_delivery_inbox SET consumed_at = ? WHERE delivery_id = ? AND state IN ('admitted', 'recovery_required') AND consumed_at IS NULL\",\n )\n .run(Date.now(), deliveryId);\n return result.changes === 1;\n },\n outbox(deliveryId: string): DoomSessionOutboxEntry | undefined {\n const row = database\n .prepare(\n 'SELECT delivery_id, recipient_key, kind, metadata_json, state, recipient_state FROM session_delivery_outbox WHERE delivery_id = ?',\n )\n .get(deliveryId) as OutboxRow | undefined;\n if (!row) return undefined;\n return {\n deliveryId: row.delivery_id,\n recipientKey: row.recipient_key,\n kind: row.kind,\n metadata: JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata,\n state: row.state,\n ...(row.recipient_state === null ? {} : { recipientState: row.recipient_state }),\n };\n },\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n clearInterval(retryTimer);\n releaseEnvelope();\n releaseAck();\n releaseReady();\n try {\n await admissionQueue;\n } finally {\n database.close();\n }\n },\n });\n}\n\n/**\n * Installs a provider-owned endpoint in the current Cordis context.\n *\n * Returns the instance because a provider cannot read its own service back out:\n * `ctx.get` is strict and hides an implementation while its providing fiber is\n * LOADING, which is the whole of that fiber's own callback.\n */\nexport function provideSessionDeliveryService(\n context: Context,\n options: SessionDeliveryServiceOptions,\n): { readonly service: DoomSessionDeliveryService; readonly close: () => Promise<void> } {\n const service = createSessionDeliveryService(options);\n const unprovide = context.provide(DOOM_SESSION_DELIVERY_SERVICE, service);\n // A caller that throws before returning its disposer would otherwise leave the\n // database, its WAL files and its retry timer open for the life of the process.\n // close() is idempotent, so this net never conflicts with the ordered close below.\n context.effect(() => () => service.close(), 'session delivery database');\n return {\n service,\n close: async () => {\n unprovide();\n await service.close();\n },\n };\n}\n\nexport type {\n DoomSessionDeliveryInboxState,\n DoomSessionDeliveryMetadata,\n DoomSessionDeliveryMode,\n DoomSessionDeliveryRequest,\n DoomSessionDeliveryService,\n DoomSessionInboxEntry,\n DoomSessionInboxQuery,\n DoomSessionOutboxEntry,\n SessionDeliveryServiceOptions,\n} from './type';\nexport { DOOM_SESSION_DELIVERY_SERVICE, readDoomSessionDelivery } from './type';\n"],"mappings":"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"}
@@ -661,10 +661,13 @@ function createSessionDeliveryService(options) {
661
661
  if (closed || !ack) return;
662
662
  database.prepare(`UPDATE session_delivery_outbox
663
663
  SET state = 'acknowledged', recipient_state = ?, acknowledged_at = ?
664
- WHERE delivery_id = ? AND recipient_key = ?`).run(ack.state, Date.now(), ack.deliveryId, recipientKey);
664
+ WHERE delivery_id = ? AND recipient_key = ?
665
+ AND (recipient_state IS NULL
666
+ OR (recipient_state = 'accepted' AND ? != 'accepted')
667
+ OR (recipient_state = 'admitting' AND ? IN ('admitted', 'recovery_required')))`).run(ack.state, Date.now(), ack.deliveryId, recipientKey, ack.state, ack.state);
665
668
  };
666
669
  const publishOutbox = (deliveryId) => {
667
- const row = database.prepare("SELECT * FROM session_delivery_outbox WHERE delivery_id = ? AND state = 'queued'").get(deliveryId);
670
+ const row = database.prepare("SELECT * FROM session_delivery_outbox WHERE delivery_id = ? AND (recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required'))").get(deliveryId);
668
671
  if (!row) return;
669
672
  const metadata = JSON.parse(row.metadata_json);
670
673
  if (!options.authorizePeer(row.recipient_key, metadata)) return;
@@ -677,10 +680,10 @@ function createSessionDeliveryService(options) {
677
680
  });
678
681
  };
679
682
  const publishQueued = (recipientKey) => {
680
- for (const row of database.prepare("SELECT delivery_id FROM session_delivery_outbox WHERE recipient_key = ? AND state = 'queued'").all(recipientKey)) publishOutbox(row.delivery_id);
683
+ for (const row of database.prepare("SELECT delivery_id FROM session_delivery_outbox WHERE recipient_key = ? AND (recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required'))").all(recipientKey)) publishOutbox(row.delivery_id);
681
684
  };
682
685
  const publishAllQueued = () => {
683
- for (const row of database.prepare("SELECT delivery_id FROM session_delivery_outbox WHERE state = 'queued'").all()) publishOutbox(row.delivery_id);
686
+ for (const row of database.prepare("SELECT delivery_id FROM session_delivery_outbox WHERE recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required')").all()) publishOutbox(row.delivery_id);
684
687
  };
685
688
  const releaseEnvelope = options.communication.subscribe(DELIVERY_EVENT, receiveEnvelope);
686
689
  const releaseAck = options.communication.subscribe(ACK_EVENT, receiveAck);
@@ -793,4 +796,4 @@ function provideSessionDeliveryService(context, options) {
793
796
  //#endregion
794
797
  export { peerRequestHeaders as _, createSessionGroupDeliveryAuthorizer as a, sessionPeerConfigPath as b, readSessionIntercom as c, SessionGroupRevisionError as d, createSessionDirectory as f, parseSessionPeerEnvelope as g, parseRemoteSessionReference as h, readDoomSessionDelivery as i, requireSessionIntercom as l, createPeerReplayGuard as m, provideSessionDeliveryService as n, createSessionIntercom as o, createPeerCommunication as p, DOOM_SESSION_DELIVERY_SERVICE as r, DOOM_SESSION_INTERCOM_SERVICE as s, createSessionDeliveryService as t, createSessionGroupStore as u, peerSessionReference as v, verifyPeerRequest as x, readSessionPeerConfig as y };
795
798
 
796
- //# sourceMappingURL=sessionDelivery-C_rANfaY.mjs.map
799
+ //# sourceMappingURL=sessionDelivery-DNq4a8LB.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessionDelivery-C_rANfaY.mjs","names":["envelopeOf"],"sources":["../src/services/peerTransport/index.ts","../src/services/sessionDirectory/index.ts","../src/services/sessionGroups/type.ts","../src/services/sessionGroups/index.ts","../src/services/sessionIntercom/type.ts","../src/services/sessionIntercom/index.ts","../src/services/sessionDelivery/type.ts","../src/services/sessionDelivery/index.ts"],"sourcesContent":["import { createHash, createHmac, timingSafeEqual } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\n\nimport type { DoomSessionCommunicationEndpoint } from '@agimon-ai/doompi-core/hubChannel';\n\nconst PEER_CONFIG_VERSION = 1;\nconst PEER_CONFIG_FILE = 'peers.json';\nconst PEER_ROUTE = '/api/plugins/session-peer/inbox';\nconst PEER_HEADER = 'x-doompi-session-peer';\nconst TIMESTAMP_HEADER = 'x-doompi-session-timestamp';\nconst SIGNATURE_HEADER = 'x-doompi-session-signature';\nconst MAX_CLOCK_SKEW_MS = 5 * 60_000;\nconst MAX_REPLAY_ENTRIES = 10_000;\nconst REPLAY_DATABASE_FILE = 'peer-replay.sqlite';\n\nexport interface SessionPeer {\n readonly hostId: string;\n readonly url: string;\n readonly secret: string;\n /** Explicit remote durable-message targets. Empty means no delivery grant. */\n readonly allowedSessionIds: readonly string[];\n /** Explicit remote Voice media targets. Empty means no media grant. */\n readonly allowedVoiceSessionIds: readonly string[];\n}\n\nexport interface SessionPeerConfig {\n readonly version: typeof PEER_CONFIG_VERSION;\n readonly hostId: string;\n readonly peers: readonly SessionPeer[];\n}\n\nexport interface RemoteSessionReference {\n readonly hostId: string;\n readonly sessionId: string;\n}\n\nexport interface SessionPeerEnvelope {\n readonly sourceSessionId: string;\n readonly targetSessionId: string;\n readonly type: string;\n readonly payload: unknown;\n}\n\nexport interface SessionPeerReplayGuard {\n admit(request: Request, now?: number): boolean;\n close(): void;\n}\n\nfunction validId(value: unknown): value is string {\n return typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(value);\n}\n\nfunction peerOf(value: unknown): SessionPeer | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n if (!validId(record.hostId) || typeof record.url !== 'string' || typeof record.secret !== 'string') return undefined;\n let url: URL;\n try {\n url = new URL(record.url);\n } catch {\n return undefined;\n }\n if (url.protocol !== 'https:' || url.username !== '' || url.password !== '' || url.search !== '' || url.hash !== '')\n return undefined;\n const allowedSessionIds =\n Array.isArray(record.allowedSessionIds) && record.allowedSessionIds.every(validId)\n ? record.allowedSessionIds\n : undefined;\n const allowedVoiceSessionIds =\n Array.isArray(record.allowedVoiceSessionIds) && record.allowedVoiceSessionIds.every(validId)\n ? record.allowedVoiceSessionIds\n : [];\n if (allowedSessionIds === undefined || record.secret.length < 32) return undefined;\n return {\n hostId: record.hostId,\n url: url.toString(),\n secret: record.secret,\n allowedSessionIds,\n allowedVoiceSessionIds,\n };\n}\n\nexport function sessionPeerConfigPath(homeDirectory: string): string {\n return path.join(homeDirectory, '.pi', '.doom', 'session', PEER_CONFIG_FILE);\n}\n\n/** Reads operator-provisioned peers. Invalid or unreadable config fails closed. */\nexport function readSessionPeerConfig(homeDirectory: string): SessionPeerConfig | undefined {\n let parsed: unknown;\n try {\n const file = sessionPeerConfigPath(homeDirectory);\n if ((fs.statSync(file).mode & 0o077) !== 0) return undefined;\n parsed = JSON.parse(fs.readFileSync(file, 'utf8')) as unknown;\n } catch {\n return undefined;\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return undefined;\n const record = parsed as Record<string, unknown>;\n if (record.version !== PEER_CONFIG_VERSION || !validId(record.hostId) || !Array.isArray(record.peers))\n return undefined;\n const peers = record.peers.map(peerOf);\n if (peers.some((peer) => peer === undefined)) return undefined;\n const resolved = peers as SessionPeer[];\n if (\n new Set(resolved.map((peer) => peer.hostId)).size !== resolved.length ||\n resolved.some((peer) => peer.hostId === record.hostId)\n )\n return undefined;\n return { version: PEER_CONFIG_VERSION, hostId: record.hostId, peers: resolved };\n}\n\n/** `peer/<host-id>/<session-id>` is the only remote target spelling. */\nexport function parseRemoteSessionReference(value: string): RemoteSessionReference | undefined {\n const match = /^peer\\/([^/]+)\\/([^/]+)$/u.exec(value);\n return match && validId(match[1]) && validId(match[2]) ? { hostId: match[1], sessionId: match[2] } : undefined;\n}\n\nexport function peerSessionReference(hostId: string, sessionId: string): string {\n if (!validId(hostId) || !validId(sessionId))\n throw new TypeError('Remote host and session identifiers must be safe opaque IDs.');\n return `peer/${hostId}/${sessionId}`;\n}\n\nfunction signature(secret: string, method: string, pathname: string, timestamp: string, body: string): string {\n const digest = createHash('sha256').update(body).digest('base64url');\n return createHmac('sha256', secret).update(`${method}\\n${pathname}\\n${timestamp}\\n${digest}`).digest('base64url');\n}\n\nexport function peerRequestHeaders(\n sourceHostId: string,\n peer: SessionPeer,\n method: string,\n pathname: string,\n body: string,\n now = Date.now(),\n): Headers {\n if (!validId(sourceHostId)) throw new TypeError('Source host identity must be a safe opaque ID.');\n const timestamp = String(now);\n return new Headers({\n 'content-type': 'application/json',\n [PEER_HEADER]: sourceHostId,\n [TIMESTAMP_HEADER]: timestamp,\n [SIGNATURE_HEADER]: signature(peer.secret, method, pathname, timestamp, body),\n });\n}\n\n/** Persists accepted peer signatures so a valid request cannot be replayed within its clock-skew window. */\nexport function createPeerReplayGuard(homeDirectory: string): SessionPeerReplayGuard {\n const directory = path.dirname(sessionPeerConfigPath(homeDirectory));\n fs.mkdirSync(directory, { recursive: true, mode: 0o700 });\n const database = new DatabaseSync(path.join(directory, REPLAY_DATABASE_FILE));\n database.exec(`\n PRAGMA journal_mode = WAL;\n CREATE TABLE IF NOT EXISTS peer_request_replays (\n signature TEXT PRIMARY KEY,\n expires_at INTEGER NOT NULL\n );\n `);\n const removeExpired = database.prepare('DELETE FROM peer_request_replays WHERE expires_at < ?');\n const insert = database.prepare('INSERT OR IGNORE INTO peer_request_replays (signature, expires_at) VALUES (?, ?)');\n const count = database.prepare('SELECT COUNT(*) AS count FROM peer_request_replays');\n const trim = database.prepare(`\n DELETE FROM peer_request_replays\n WHERE signature IN (\n SELECT signature FROM peer_request_replays ORDER BY expires_at ASC, signature ASC LIMIT ?\n )\n `);\n return {\n admit(request, now = Date.now()) {\n const supplied = request.headers.get(SIGNATURE_HEADER);\n if (!supplied) return false;\n database.exec('BEGIN IMMEDIATE');\n try {\n removeExpired.run(now);\n const accepted = insert.run(supplied, now + MAX_CLOCK_SKEW_MS).changes === 1;\n const total = Number((count.get() as { count: number | bigint }).count);\n if (total > MAX_REPLAY_ENTRIES) trim.run(total - MAX_REPLAY_ENTRIES);\n database.exec('COMMIT');\n return accepted;\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n },\n close: () => database.close(),\n };\n}\n\nexport function verifyPeerRequest(\n config: SessionPeerConfig,\n request: Request,\n body: string,\n now = Date.now(),\n): SessionPeer | undefined {\n const hostId = request.headers.get(PEER_HEADER);\n const timestamp = request.headers.get(TIMESTAMP_HEADER);\n const supplied = request.headers.get(SIGNATURE_HEADER);\n if (!hostId || !timestamp || !supplied || !/^\\d{1,16}$/u.test(timestamp)) return undefined;\n const sentAt = Number(timestamp);\n if (!Number.isSafeInteger(sentAt) || Math.abs(now - sentAt) > MAX_CLOCK_SKEW_MS) return undefined;\n const peer = config.peers.find((candidate) => candidate.hostId === hostId);\n if (!peer) return undefined;\n const expected = Buffer.from(signature(peer.secret, request.method, new URL(request.url).pathname, timestamp, body));\n const actual = Buffer.from(supplied);\n return actual.byteLength === expected.byteLength && timingSafeEqual(actual, expected) ? peer : undefined;\n}\n\nfunction envelopeOf(value: unknown): SessionPeerEnvelope | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n return validId(record.sourceSessionId) &&\n validId(record.targetSessionId) &&\n typeof record.type === 'string' &&\n record.type !== ''\n ? {\n sourceSessionId: record.sourceSessionId,\n targetSessionId: record.targetSessionId,\n type: record.type,\n payload: record.payload,\n }\n : undefined;\n}\n\nexport function parseSessionPeerEnvelope(value: unknown): SessionPeerEnvelope | undefined {\n return envelopeOf(value);\n}\n\n/** Adds asynchronous tunnel publication to a host-bound local communication endpoint. */\nexport function createPeerCommunication(options: {\n readonly local: DoomSessionCommunicationEndpoint;\n readonly homeDirectory: string;\n readonly fetch?: typeof fetch;\n}): DoomSessionCommunicationEndpoint {\n const config = readSessionPeerConfig(options.homeDirectory);\n const send = options.fetch ?? fetch;\n return {\n sessionId: options.local.sessionId,\n publish(target, type, payload) {\n const remote = parseRemoteSessionReference(target);\n if (!remote) return options.local.publish(target, type, payload);\n const peer = config?.peers.find((candidate) => candidate.hostId === remote.hostId);\n // Pairing is not a grant. Outbound delivery needs the same explicit target\n // allowlist that the receiver enforces for inbound envelopes.\n if (!config || !peer || !peer.allowedSessionIds.includes(remote.sessionId)) return false;\n const body = JSON.stringify({\n sourceSessionId: options.local.sessionId,\n targetSessionId: remote.sessionId,\n type,\n payload,\n });\n const url = new URL(PEER_ROUTE, peer.url);\n void send(url, {\n method: 'POST',\n headers: peerRequestHeaders(config.hostId, peer, 'POST', '/inbox', body),\n body,\n }).catch(() => undefined);\n return true;\n },\n subscribe: (type, listener) => options.local.subscribe(type, listener),\n onPeerReady: (listener) => options.local.onPeerReady(listener),\n close: () => options.local.close(),\n };\n}\n","import { peerSessionReference } from '../peerTransport';\nimport type {\n DiscoveredSession,\n SessionDirectory,\n SessionDirectoryOptions,\n SessionPresenceFacts,\n SessionPresenceObservation,\n} from './type';\n\nconst UNKNOWN_FACTS: SessionPresenceFacts = Object.freeze({\n reachability: 'unknown',\n runtime: 'unknown',\n activity: 'unknown',\n voice: Object.freeze({ eligible: 'unknown', readiness: 'unknown' }),\n});\n\nfunction keyOf(observation: Pick<SessionPresenceObservation, 'hostId' | 'sessionId'>): string {\n return peerSessionReference(observation.hostId, observation.sessionId);\n}\n\nfunction publicEntry(\n observation: SessionPresenceObservation,\n now: number,\n label: string | undefined,\n capabilities: readonly string[],\n): DiscoveredSession {\n const freshUntil = observation.observedAt + observation.staleAfterMs;\n const fresh = now <= freshUntil;\n const facts: SessionPresenceFacts = fresh ? observation : UNKNOWN_FACTS;\n return Object.freeze({\n reference: keyOf(observation),\n ...(label === undefined ? {} : { label }),\n capabilities: Object.freeze([...capabilities]),\n hostIncarnation: observation.hostIncarnation,\n sessionIncarnation: observation.sessionIncarnation,\n sequence: observation.sequence,\n observedAt: observation.observedAt,\n freshUntil,\n fresh,\n reachability: facts.reachability,\n runtime: facts.runtime,\n activity: facts.activity,\n voice: Object.freeze({ ...facts.voice }),\n });\n}\n\n/** In-memory authenticated presence cache. Restart deliberately forgets every observation. */\nexport function createSessionDirectory(options: SessionDirectoryOptions): SessionDirectory {\n const now = options.now ?? Date.now;\n const observations = new Map<string, SessionPresenceObservation>();\n const snapshotRequired = new Set<string>();\n const subscribers = new Set<{\n callerReference: string;\n listener: (sessions: readonly DiscoveredSession[]) => void;\n }>();\n\n const discover = (callerReference: string, allowedReferences?: ReadonlySet<string>): readonly DiscoveredSession[] => {\n const result: DiscoveredSession[] = [];\n for (const observation of observations.values()) {\n const reference = keyOf(observation);\n if (allowedReferences && !allowedReferences.has(reference)) continue;\n const grant = options.authorizeDiscovery(callerReference, observation);\n if (!grant) continue;\n result.push(publicEntry(observation, now(), grant.label ?? observation.label, grant.capabilities));\n }\n return result.sort((left, right) => left.reference.localeCompare(right.reference));\n };\n const notify = (): void => {\n for (const subscriber of subscribers) subscriber.listener(discover(subscriber.callerReference));\n };\n\n return {\n observe(observation) {\n const key = keyOf(observation);\n const current = observations.get(key);\n if (snapshotRequired.has(observation.hostId)) return false;\n if (current?.hostIncarnation === observation.hostIncarnation) {\n if (current.sessionIncarnation === observation.sessionIncarnation && observation.sequence <= current.sequence)\n return false;\n if (observation.sequence !== current.sequence + 1) {\n snapshotRequired.add(observation.hostId);\n for (const [reference, candidate] of observations)\n if (candidate.hostId === observation.hostId)\n observations.set(reference, { ...candidate, ...UNKNOWN_FACTS, observedAt: now(), staleAfterMs: 0 });\n notify();\n return false;\n }\n }\n observations.set(key, Object.freeze({ ...observation, voice: Object.freeze({ ...observation.voice }) }));\n notify();\n return true;\n },\n replaceHostSnapshot(hostId, hostIncarnation, replacements) {\n if (\n replacements.some(\n (observation) => observation.hostId !== hostId || observation.hostIncarnation !== hostIncarnation,\n )\n ) {\n throw new TypeError('A presence snapshot must contain only the declared host incarnation.');\n }\n for (const [reference, observation] of observations)\n if (observation.hostId === hostId) observations.delete(reference);\n for (const observation of replacements)\n observations.set(\n keyOf(observation),\n Object.freeze({ ...observation, voice: Object.freeze({ ...observation.voice }) }),\n );\n snapshotRequired.delete(hostId);\n notify();\n },\n hostDisconnected(hostId) {\n for (const [reference, observation] of observations) {\n if (observation.hostId !== hostId) continue;\n observations.set(reference, { ...observation, reachability: 'unreachable' });\n }\n notify();\n },\n discover,\n resolveDeliveryTarget(callerReference, reference) {\n const observation = observations.get(reference);\n return observation && options.authorizeDiscovery(callerReference, observation)\n ? observation.deliveryTarget\n : undefined;\n },\n subscribe(callerReference, listener) {\n const subscriber = { callerReference, listener };\n subscribers.add(subscriber);\n listener(discover(callerReference));\n return () => subscribers.delete(subscriber);\n },\n };\n}\n\nexport type {\n DiscoveredSession,\n SessionActivityState,\n SessionDirectory,\n SessionDirectoryOptions,\n SessionDiscoveryGrant,\n SessionHostReachability,\n SessionPresenceFacts,\n SessionPresenceObservation,\n SessionRuntimeState,\n SessionVoiceReadiness,\n} from './type';\n","export interface SessionCommunicationGroup {\n readonly id: string;\n readonly ownerAuthority: string;\n readonly revision: number;\n readonly members: readonly string[];\n}\n\nexport interface SessionGroupMutation {\n readonly groupId: string;\n readonly authority: string;\n readonly expectedRevision: number;\n readonly add?: readonly string[];\n readonly remove?: readonly string[];\n}\n\nexport interface SessionGroupStoreOptions {\n readonly databasePath: string;\n readonly authorizeManagement?: (authority: string, group: SessionCommunicationGroup) => boolean;\n readonly validateEnrollment?: (groupId: string, memberReference: string) => boolean;\n}\n\nexport interface SessionGroupStore {\n create(groupId: string, ownerAuthority: string, members: readonly string[]): SessionCommunicationGroup;\n mutate(mutation: SessionGroupMutation): SessionCommunicationGroup;\n get(groupId: string): SessionCommunicationGroup | undefined;\n groupsFor(memberReference: string): readonly SessionCommunicationGroup[];\n canMessage(groupId: string, sourceReference: string, targetReference: string): boolean;\n close(): void;\n}\n\nexport class SessionGroupRevisionError extends Error {\n constructor(groupId: string, expected: number, actual: number) {\n super(`Session group '${groupId}' revision conflict: expected ${expected}, current ${actual}.`);\n this.name = 'SessionGroupRevisionError';\n }\n}\n","import { DatabaseSync } from 'node:sqlite';\n\nimport {\n SessionGroupRevisionError,\n type SessionCommunicationGroup,\n type SessionGroupMutation,\n type SessionGroupStore,\n type SessionGroupStoreOptions,\n} from './type';\n\ninterface GroupRow {\n group_id: string;\n owner_authority: string;\n revision: number;\n}\n\nconst ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;\nconst REFERENCE_PATTERN = /^peer\\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}\\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;\n\nfunction validateGroupId(value: string): void {\n if (!ID_PATTERN.test(value)) throw new TypeError('Session group IDs must be safe opaque IDs.');\n}\n\nfunction validateReference(value: string): void {\n if (!REFERENCE_PATTERN.test(value))\n throw new TypeError(`Session group member '${value}' is not a qualified reference.`);\n}\n\n/** Opens a revisioned SQLite registry for communication-only group membership. */\nexport function createSessionGroupStore(options: SessionGroupStoreOptions): SessionGroupStore {\n const database = new DatabaseSync(options.databasePath);\n database.exec(`\n PRAGMA journal_mode = WAL;\n PRAGMA foreign_keys = ON;\n CREATE TABLE IF NOT EXISTS session_groups (\n group_id TEXT PRIMARY KEY,\n owner_authority TEXT NOT NULL,\n revision INTEGER NOT NULL\n );\n CREATE TABLE IF NOT EXISTS session_group_members (\n group_id TEXT NOT NULL REFERENCES session_groups(group_id) ON DELETE CASCADE,\n member_reference TEXT NOT NULL,\n PRIMARY KEY (group_id, member_reference)\n );\n `);\n\n const read = (groupId: string): SessionCommunicationGroup | undefined => {\n const row = database.prepare('SELECT * FROM session_groups WHERE group_id = ?').get(groupId) as\n | GroupRow\n | undefined;\n if (!row) return undefined;\n const members = database\n .prepare('SELECT member_reference FROM session_group_members WHERE group_id = ? ORDER BY member_reference')\n .all(groupId) as { member_reference: string }[];\n return Object.freeze({\n id: row.group_id,\n ownerAuthority: row.owner_authority,\n revision: row.revision,\n members: Object.freeze(members.map((member) => member.member_reference)),\n });\n };\n\n const enroll = (groupId: string, members: readonly string[]): void => {\n const insert = database.prepare(\n 'INSERT OR IGNORE INTO session_group_members (group_id, member_reference) VALUES (?, ?)',\n );\n for (const member of new Set(members)) {\n validateReference(member);\n if (options.validateEnrollment?.(groupId, member) === false)\n throw new Error(`Session group enrollment policy rejected '${member}'.`);\n insert.run(groupId, member);\n }\n };\n\n return {\n create(groupId, ownerAuthority, members) {\n validateGroupId(groupId);\n if (!ownerAuthority.trim()) throw new TypeError('Session group owner authority is required.');\n database.exec('BEGIN IMMEDIATE');\n try {\n database\n .prepare('INSERT INTO session_groups (group_id, owner_authority, revision) VALUES (?, ?, 1)')\n .run(groupId, ownerAuthority);\n enroll(groupId, members);\n database.exec('COMMIT');\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n return read(groupId)!;\n },\n mutate(mutation: SessionGroupMutation) {\n database.exec('BEGIN IMMEDIATE');\n try {\n const current = read(mutation.groupId);\n if (!current) throw new Error(`Session group '${mutation.groupId}' does not exist.`);\n if (\n mutation.authority !== current.ownerAuthority &&\n options.authorizeManagement?.(mutation.authority, current) !== true\n ) {\n throw new Error(`Authority '${mutation.authority}' cannot manage Session group '${mutation.groupId}'.`);\n }\n if (mutation.expectedRevision !== current.revision)\n throw new SessionGroupRevisionError(mutation.groupId, mutation.expectedRevision, current.revision);\n enroll(mutation.groupId, mutation.add ?? []);\n const remove = database.prepare(\n 'DELETE FROM session_group_members WHERE group_id = ? AND member_reference = ?',\n );\n for (const member of new Set(mutation.remove ?? [])) {\n validateReference(member);\n remove.run(mutation.groupId, member);\n }\n database\n .prepare('UPDATE session_groups SET revision = revision + 1 WHERE group_id = ? AND revision = ?')\n .run(mutation.groupId, current.revision);\n database.exec('COMMIT');\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n return read(mutation.groupId)!;\n },\n get: read,\n groupsFor(memberReference) {\n validateReference(memberReference);\n const rows = database\n .prepare(\n `SELECT g.group_id FROM session_groups g\n INNER JOIN session_group_members m ON m.group_id = g.group_id\n WHERE m.member_reference = ? ORDER BY g.group_id`,\n )\n .all(memberReference) as { group_id: string }[];\n return rows.map((row) => read(row.group_id)!);\n },\n canMessage(groupId, sourceReference, targetReference) {\n validateReference(sourceReference);\n validateReference(targetReference);\n const row = database\n .prepare(\n `SELECT COUNT(*) AS count FROM session_group_members\n WHERE group_id = ? AND member_reference IN (?, ?)`,\n )\n .get(groupId, sourceReference, targetReference) as { count: number | bigint };\n return Number(row.count) === (sourceReference === targetReference ? 1 : 2);\n },\n close: () => database.close(),\n };\n}\n\nexport {\n SessionGroupRevisionError,\n type SessionCommunicationGroup,\n type SessionGroupMutation,\n type SessionGroupStore,\n type SessionGroupStoreOptions,\n} from './type';\n","import type { Context } from '@deepseek-ai/cordis';\n\nimport type {\n DoomSessionDeliveryMetadata,\n DoomSessionDeliveryService,\n DoomSessionInboxEntry,\n DoomSessionOutboxEntry,\n} from '../sessionDelivery';\nimport type { DiscoveredSession, SessionDirectory } from '../sessionDirectory';\nimport type { SessionGroupStore } from '../sessionGroups';\n\nexport const DOOM_SESSION_INTERCOM_SERVICE = 'doom/session-intercom';\n\nexport type SessionReportStatus = 'done' | 'blocked' | 'failed';\n\nexport interface SessionIntercomMessage {\n readonly deliveryId: string;\n readonly sourceReference: string;\n readonly targetReference: string;\n readonly groupId: string;\n readonly correlationId?: string;\n readonly text: string;\n readonly reportStatus?: SessionReportStatus;\n readonly state: DoomSessionInboxEntry['state'];\n readonly consumed: boolean;\n}\n\nexport interface SessionIntercomSendRequest {\n readonly targetReference: string;\n readonly groupId: string;\n readonly text: string;\n readonly correlationId?: string;\n readonly deliveryId?: string;\n}\n\nexport interface SessionIntercomOptions {\n readonly selfReference: string;\n readonly directory: SessionDirectory;\n readonly groups: SessionGroupStore;\n readonly delivery: DoomSessionDeliveryService;\n}\n\nexport interface SessionIntercom {\n discover(): readonly DiscoveredSession[];\n send(request: SessionIntercomSendRequest): Promise<{ deliveryId: string }>;\n report(\n request: SessionIntercomSendRequest & { readonly status: SessionReportStatus },\n ): Promise<{ deliveryId: string }>;\n messages(): readonly SessionIntercomMessage[];\n delivery(deliveryId: string): DoomSessionOutboxEntry | undefined;\n}\n\nexport interface SessionGroupDeliveryAuthorizationOptions {\n readonly selfReference: string;\n readonly groups: SessionGroupStore;\n readonly peerReference: (peerKey: string) => string | undefined;\n readonly fallback?: (peerKey: string, metadata: DoomSessionDeliveryMetadata | undefined) => boolean;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/session-intercom': SessionIntercom;\n }\n}\n\nexport function readSessionIntercom(context: Context): SessionIntercom | undefined {\n return context.get(DOOM_SESSION_INTERCOM_SERVICE) as SessionIntercom | undefined;\n}\n\nexport function requireSessionIntercom(context: Context): SessionIntercom {\n const service = readSessionIntercom(context);\n if (!service)\n throw new Error('Session intercom is unavailable. Activate Session with a configured persistent host identity.');\n return service;\n}\n","import type { DoomSessionDeliveryMetadata } from '../sessionDelivery';\nimport type { SessionIntercomMessage } from './type';\nimport type {\n SessionGroupDeliveryAuthorizationOptions,\n SessionIntercom,\n SessionIntercomOptions,\n SessionIntercomSendRequest,\n SessionReportStatus,\n} from './type';\n\nconst MESSAGE_KIND = 'session-message';\nconst REPORT_KIND = 'session-report';\n\nfunction metadataFor(\n options: SessionIntercomOptions,\n request: SessionIntercomSendRequest,\n reportStatus?: SessionReportStatus,\n): DoomSessionDeliveryMetadata {\n const group = options.groups.get(request.groupId);\n if (!group || !options.groups.canMessage(request.groupId, options.selfReference, request.targetReference))\n throw new Error(`Session group '${request.groupId}' does not authorize this message.`);\n return {\n sourceReference: options.selfReference,\n targetReference: request.targetReference,\n groupId: request.groupId,\n groupRevision: String(group.revision),\n ...(request.correlationId === undefined ? {} : { correlationId: request.correlationId }),\n ...(reportStatus === undefined ? {} : { reportStatus }),\n };\n}\n\n/** Agent-facing intercom operations. A composition may acquire this service without gaining session controls. */\nexport function createSessionIntercom(options: SessionIntercomOptions): SessionIntercom {\n const deliver = async (\n request: SessionIntercomSendRequest,\n kind: typeof MESSAGE_KIND | typeof REPORT_KIND,\n status?: SessionReportStatus,\n ): Promise<{ deliveryId: string }> => {\n const recipientKey = options.directory.resolveDeliveryTarget(options.selfReference, request.targetReference);\n if (!recipientKey) throw new Error(`Session '${request.targetReference}' is not discoverable.`);\n const metadata = metadataFor(options, request, status);\n return options.delivery.deliver({\n ...(request.deliveryId === undefined ? {} : { deliveryId: request.deliveryId }),\n recipientKey,\n kind,\n prompt: `[Session ${status === undefined ? 'message' : `report: ${status}`} from ${options.selfReference}] ${request.text}`,\n metadata,\n });\n };\n\n const intercom: SessionIntercom = {\n discover() {\n const members = new Set(\n options.groups\n .groupsFor(options.selfReference)\n .flatMap((group) => group.members)\n .filter((reference) => reference !== options.selfReference),\n );\n return options.directory.discover(options.selfReference, members);\n },\n send: (request) => deliver(request, MESSAGE_KIND),\n report: (request) => deliver(request, REPORT_KIND, request.status),\n messages() {\n return options.delivery\n .inbox()\n .filter((entry) => entry.kind === MESSAGE_KIND || entry.kind === REPORT_KIND)\n .filter((entry) => {\n const groupId = entry.metadata.groupId;\n return groupId !== undefined && options.groups.get(groupId)?.members.includes(options.selfReference) === true;\n })\n .flatMap((entry): SessionIntercomMessage[] => {\n const sourceReference = entry.metadata.sourceReference;\n const targetReference = entry.metadata.targetReference;\n const groupId = entry.metadata.groupId;\n if (!sourceReference || !targetReference || !groupId) return [];\n const reportStatus = entry.metadata.reportStatus;\n return [\n {\n deliveryId: entry.deliveryId,\n sourceReference,\n targetReference,\n groupId,\n ...(entry.metadata.correlationId === undefined ? {} : { correlationId: entry.metadata.correlationId }),\n text: entry.prompt,\n ...(reportStatus === 'done' || reportStatus === 'blocked' || reportStatus === 'failed'\n ? { reportStatus }\n : {}),\n state: entry.state,\n consumed: entry.consumed,\n },\n ];\n });\n },\n delivery(deliveryId) {\n const entry = options.delivery.outbox(deliveryId);\n const groupId = entry?.metadata.groupId;\n return entry &&\n groupId !== undefined &&\n options.groups.get(groupId)?.members.includes(options.selfReference) === true\n ? entry\n : undefined;\n },\n };\n return Object.freeze(intercom);\n}\n\n/** Builds the dynamic delivery check used before every send, retry, and recipient acceptance. */\nexport function createSessionGroupDeliveryAuthorizer(\n options: SessionGroupDeliveryAuthorizationOptions,\n): (peerKey: string, metadata: DoomSessionDeliveryMetadata | undefined) => boolean {\n return (peerKey, metadata) => {\n const sourceReference = metadata?.sourceReference;\n const targetReference = metadata?.targetReference;\n const groupId = metadata?.groupId;\n if (sourceReference && targetReference && groupId) {\n const peerReference = options.peerReference(peerKey);\n if (!peerReference) return false;\n const directionMatches =\n (sourceReference === options.selfReference && targetReference === peerReference) ||\n (targetReference === options.selfReference && sourceReference === peerReference);\n return directionMatches && options.groups.canMessage(groupId, sourceReference, targetReference);\n }\n return options.fallback?.(peerKey, metadata) === true;\n };\n}\n\nexport { DOOM_SESSION_INTERCOM_SERVICE, readSessionIntercom, requireSessionIntercom } from './type';\nexport type {\n SessionGroupDeliveryAuthorizationOptions,\n SessionIntercom,\n SessionIntercomMessage,\n SessionIntercomOptions,\n SessionIntercomSendRequest,\n SessionReportStatus,\n} from './type';\n","import type { DoomSessionCommunicationEndpoint } from '@agimon-ai/doompi-core/hubChannel';\nimport type { Context } from '@deepseek-ai/cordis';\n\nexport const DOOM_SESSION_DELIVERY_SERVICE = 'doom/session-delivery';\n\nexport type DoomSessionDeliveryInboxState = 'accepted' | 'admitting' | 'admitted' | 'recovery_required';\nexport type DoomSessionDeliveryMode = 'prompt' | 'steer' | 'followUp';\n\nexport interface DoomSessionDeliveryMetadata extends Readonly<Record<string, string | undefined>> {\n readonly worktreeId?: string;\n readonly fromRole?: string;\n}\n\nexport interface DoomSessionDeliveryRequest {\n readonly deliveryId?: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery?: DoomSessionDeliveryMode;\n readonly metadata?: DoomSessionDeliveryMetadata;\n}\n\nexport interface DoomSessionInboxQuery {\n readonly kind?: string;\n readonly metadata?: DoomSessionDeliveryMetadata;\n readonly state?: DoomSessionDeliveryInboxState;\n readonly consumed?: boolean;\n}\n\nexport interface DoomSessionInboxEntry {\n readonly deliveryId: string;\n readonly senderKey: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery: DoomSessionDeliveryMode;\n readonly metadata: DoomSessionDeliveryMetadata;\n readonly state: DoomSessionDeliveryInboxState;\n readonly consumed: boolean;\n}\n\nexport interface DoomSessionOutboxEntry {\n readonly deliveryId: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly metadata: DoomSessionDeliveryMetadata;\n readonly state: 'queued' | 'acknowledged';\n readonly recipientState?: DoomSessionDeliveryInboxState;\n}\n\nexport interface DoomSessionDeliveryService {\n readonly recipientKey: string;\n deliver(request: DoomSessionDeliveryRequest): Promise<{ deliveryId: string }>;\n waitForAdmission(deliveryId: string, timeoutMs?: number): Promise<DoomSessionDeliveryInboxState | undefined>;\n inbox(query?: DoomSessionInboxQuery): readonly DoomSessionInboxEntry[];\n /** Optional host-routed peer envelope admission. Local-only consumers need no transport receiver. */\n receive?(senderKey: string, kind: string, payload: unknown): DoomSessionDeliveryInboxState | undefined;\n consume(deliveryId: string): boolean;\n outbox(deliveryId: string): DoomSessionOutboxEntry | undefined;\n close(): Promise<void>;\n}\n\nexport interface SessionDeliveryServiceOptions {\n readonly databasePath: string;\n readonly recipientKey: string;\n readonly communication: DoomSessionCommunicationEndpoint;\n /** Host-owned relationship check applied before sends, retries, and recipient acceptance. */\n readonly authorizePeer: (peerKey: string, metadata?: DoomSessionDeliveryMetadata) => boolean;\n readonly admitPrompt: (prompt: string, delivery?: DoomSessionDeliveryMode) => Promise<void>;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/session-delivery': DoomSessionDeliveryService;\n }\n}\n\n/** Reads the currently active provider each time, without retaining a stale binding. */\nexport function readDoomSessionDelivery(context: Context): DoomSessionDeliveryService | undefined {\n return context.get(DOOM_SESSION_DELIVERY_SERVICE) as DoomSessionDeliveryService | undefined;\n}\n","import { DatabaseSync } from 'node:sqlite';\n\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport {\n DOOM_SESSION_DELIVERY_SERVICE,\n type DoomSessionDeliveryInboxState,\n type DoomSessionDeliveryMetadata,\n type DoomSessionDeliveryMode,\n type DoomSessionDeliveryRequest,\n type DoomSessionDeliveryService,\n type DoomSessionInboxEntry,\n type DoomSessionInboxQuery,\n type DoomSessionOutboxEntry,\n type SessionDeliveryServiceOptions,\n} from './type';\n\nconst DELIVERY_EVENT = 'doom/session-delivery/envelope';\nconst ACK_EVENT = 'doom/session-delivery/ack';\nconst DEFAULT_DELIVERY: DoomSessionDeliveryMode = 'prompt';\nconst INBOX_STATES = new Set<DoomSessionDeliveryInboxState>(['accepted', 'admitting', 'admitted', 'recovery_required']);\n\ninterface DeliveryEnvelope {\n readonly deliveryId: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery: DoomSessionDeliveryMode;\n readonly metadata: DoomSessionDeliveryMetadata;\n}\n\ninterface DeliveryAck {\n readonly deliveryId: string;\n readonly state: DoomSessionDeliveryInboxState;\n}\n\ninterface InboxRow {\n delivery_id: string;\n sender_key: string;\n recipient_key: string;\n kind: string;\n prompt: string;\n delivery_mode: DoomSessionDeliveryMode;\n metadata_json: string;\n state: DoomSessionDeliveryInboxState;\n consumed_at: number | null;\n}\n\ninterface OutboxRow {\n delivery_id: string;\n recipient_key: string;\n kind: string;\n prompt: string;\n delivery_mode: DoomSessionDeliveryMode;\n metadata_json: string;\n state: 'queued' | 'acknowledged';\n recipient_state: DoomSessionDeliveryInboxState | null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isMode(value: unknown): value is DoomSessionDeliveryMode {\n return value === 'prompt' || value === 'steer' || value === 'followUp';\n}\n\nfunction metadataOf(value: unknown): DoomSessionDeliveryMetadata | undefined {\n if (!isRecord(value)) return undefined;\n const metadata: Record<string, string> = {};\n for (const [key, item] of Object.entries(value)) {\n if (typeof item !== 'string') return undefined;\n metadata[key] = item;\n }\n return metadata;\n}\n\nfunction envelopeOf(value: unknown): DeliveryEnvelope | undefined {\n if (!isRecord(value)) return undefined;\n const metadata = metadataOf(value.metadata);\n if (\n typeof value.deliveryId !== 'string' ||\n !value.deliveryId ||\n typeof value.kind !== 'string' ||\n !value.kind ||\n typeof value.prompt !== 'string' ||\n !isMode(value.delivery) ||\n metadata === undefined\n ) {\n return undefined;\n }\n return {\n deliveryId: value.deliveryId,\n kind: value.kind,\n prompt: value.prompt,\n delivery: value.delivery,\n metadata,\n };\n}\n\nfunction ackOf(value: unknown): DeliveryAck | undefined {\n if (!isRecord(value)) return undefined;\n if (\n typeof value.deliveryId !== 'string' ||\n typeof value.state !== 'string' ||\n !INBOX_STATES.has(value.state as DoomSessionDeliveryInboxState)\n ) {\n return undefined;\n }\n return value as unknown as DeliveryAck;\n}\n\nfunction normalizedMetadata(metadata: DoomSessionDeliveryMetadata | undefined): DoomSessionDeliveryMetadata {\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata ?? {})) {\n if (value !== undefined) normalized[key] = value;\n }\n return normalized;\n}\n\nfunction matchesMetadata(entry: DoomSessionDeliveryMetadata, query: DoomSessionDeliveryMetadata | undefined): boolean {\n return Object.entries(query ?? {}).every(([key, value]) => value === undefined || entry[key] === value);\n}\n\nfunction sameMetadata(left: DoomSessionDeliveryMetadata, right: DoomSessionDeliveryMetadata): boolean {\n return matchesMetadata(left, right) && matchesMetadata(right, left);\n}\n\n/** Opens and starts one durable delivery endpoint. */\nexport function createSessionDeliveryService(options: SessionDeliveryServiceOptions): DoomSessionDeliveryService {\n if (!options.recipientKey.trim() || options.recipientKey !== options.recipientKey.trim()) {\n throw new TypeError('Session delivery requires a trimmed, non-empty recipient key.');\n }\n const database = new DatabaseSync(options.databasePath);\n database.exec(`\n PRAGMA journal_mode = WAL;\n CREATE TABLE IF NOT EXISTS session_delivery_outbox (\n delivery_id TEXT PRIMARY KEY,\n recipient_key TEXT NOT NULL,\n kind TEXT NOT NULL,\n prompt TEXT NOT NULL,\n delivery_mode TEXT NOT NULL,\n metadata_json TEXT NOT NULL,\n state TEXT NOT NULL,\n recipient_state TEXT,\n created_at INTEGER NOT NULL,\n acknowledged_at INTEGER\n );\n CREATE TABLE IF NOT EXISTS session_delivery_inbox (\n delivery_id TEXT PRIMARY KEY,\n sender_key TEXT NOT NULL,\n recipient_key TEXT NOT NULL,\n kind TEXT NOT NULL,\n prompt TEXT NOT NULL,\n delivery_mode TEXT NOT NULL,\n metadata_json TEXT NOT NULL,\n state TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n consumed_at INTEGER\n );\n `);\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE state = 'admitting'\")\n .run(Date.now());\n\n let closed = false;\n const scheduled = new Set<string>();\n let admissionQueue = Promise.resolve();\n\n const publishAck = (deliveryId: string, senderKey: string, state: DoomSessionDeliveryInboxState): void => {\n options.communication.publish(senderKey, ACK_EVENT, { deliveryId, state } satisfies DeliveryAck);\n };\n\n const readInboxRow = (deliveryId: string): InboxRow | undefined =>\n database.prepare('SELECT * FROM session_delivery_inbox WHERE delivery_id = ?').get(deliveryId) as\n | InboxRow\n | undefined;\n\n const scheduleAdmission = (deliveryId: string): void => {\n if (closed || scheduled.has(deliveryId)) return;\n scheduled.add(deliveryId);\n admissionQueue = admissionQueue\n .then(async () => {\n try {\n if (closed) return;\n const row = readInboxRow(deliveryId);\n if (!row || row.state !== 'accepted') return;\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'admitting', updated_at = ? WHERE delivery_id = ?\")\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'admitting');\n try {\n await options.admitPrompt(row.prompt, row.delivery_mode);\n } catch {\n database\n .prepare(\n \"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE delivery_id = ?\",\n )\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'recovery_required');\n return;\n }\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'admitted', updated_at = ? WHERE delivery_id = ?\")\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'admitted');\n } finally {\n scheduled.delete(deliveryId);\n }\n })\n .catch(() => {\n scheduled.delete(deliveryId);\n try {\n const row = readInboxRow(deliveryId);\n if (row?.state !== 'admitting') return;\n database\n .prepare(\n \"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE delivery_id = ?\",\n )\n .run(Date.now(), deliveryId);\n try {\n publishAck(deliveryId, row.sender_key, 'recovery_required');\n } catch {\n // The durable state is authoritative; readiness replay can request another acknowledgement.\n }\n } catch {\n // A database failure remains recoverable on restart when the schema can be opened again.\n }\n });\n };\n\n const receiveEnvelope = (senderKey: string, value: unknown): DoomSessionDeliveryInboxState | undefined => {\n if (closed) return undefined;\n const envelope = envelopeOf(value);\n if (!envelope || !options.authorizePeer(senderKey, envelope.metadata)) return undefined;\n database\n .prepare(\n `INSERT OR IGNORE INTO session_delivery_inbox\n (delivery_id, sender_key, recipient_key, kind, prompt, delivery_mode, metadata_json, state, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, 'accepted', ?, ?)`,\n )\n .run(\n envelope.deliveryId,\n senderKey,\n options.recipientKey,\n envelope.kind,\n envelope.prompt,\n envelope.delivery,\n JSON.stringify(envelope.metadata),\n Date.now(),\n Date.now(),\n );\n const current = readInboxRow(envelope.deliveryId);\n if (!current) return undefined;\n const sameEnvelope =\n current.sender_key === senderKey &&\n current.recipient_key === options.recipientKey &&\n current.kind === envelope.kind &&\n current.prompt === envelope.prompt &&\n current.delivery_mode === envelope.delivery &&\n sameMetadata(JSON.parse(current.metadata_json) as DoomSessionDeliveryMetadata, envelope.metadata);\n if (!sameEnvelope) return undefined;\n publishAck(envelope.deliveryId, current.sender_key, current.state);\n if (current.state === 'accepted') scheduleAdmission(envelope.deliveryId);\n return current.state;\n };\n\n const receiveAck = (recipientKey: string, value: unknown): void => {\n const ack = ackOf(value);\n if (closed || !ack) return;\n database\n .prepare(\n `UPDATE session_delivery_outbox\n SET state = 'acknowledged', recipient_state = ?, acknowledged_at = ?\n WHERE delivery_id = ? AND recipient_key = ?`,\n )\n .run(ack.state, Date.now(), ack.deliveryId, recipientKey);\n };\n\n const publishOutbox = (deliveryId: string): void => {\n const row = database\n .prepare(\"SELECT * FROM session_delivery_outbox WHERE delivery_id = ? AND state = 'queued'\")\n .get(deliveryId) as OutboxRow | undefined;\n if (!row) return;\n const metadata = JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata;\n if (!options.authorizePeer(row.recipient_key, metadata)) return;\n options.communication.publish(row.recipient_key, DELIVERY_EVENT, {\n deliveryId: row.delivery_id,\n kind: row.kind,\n prompt: row.prompt,\n delivery: row.delivery_mode,\n metadata,\n } satisfies DeliveryEnvelope);\n };\n\n const publishQueued = (recipientKey: string): void => {\n for (const row of database\n .prepare(\"SELECT delivery_id FROM session_delivery_outbox WHERE recipient_key = ? AND state = 'queued'\")\n .all(recipientKey) as { delivery_id: string }[]) {\n publishOutbox(row.delivery_id);\n }\n };\n const publishAllQueued = (): void => {\n for (const row of database\n .prepare(\"SELECT delivery_id FROM session_delivery_outbox WHERE state = 'queued'\")\n .all() as { delivery_id: string }[]) {\n publishOutbox(row.delivery_id);\n }\n };\n const releaseEnvelope = options.communication.subscribe(DELIVERY_EVENT, receiveEnvelope);\n const releaseAck = options.communication.subscribe(ACK_EVENT, receiveAck);\n const releaseReady = options.communication.onPeerReady(publishQueued);\n\n for (const row of database\n .prepare(\"SELECT delivery_id, sender_key FROM session_delivery_inbox WHERE state = 'recovery_required'\")\n .all() as { delivery_id: string; sender_key: string }[]) {\n publishAck(row.delivery_id, row.sender_key, 'recovery_required');\n }\n for (const row of database\n .prepare(\"SELECT delivery_id FROM session_delivery_inbox WHERE state = 'accepted'\")\n .all() as {\n delivery_id: string;\n }[]) {\n scheduleAdmission(row.delivery_id);\n }\n publishAllQueued();\n // A publish only means the transport accepted the envelope. Repeat stable delivery\n // IDs until the durable acknowledgement arrives, including after a tunnel restart.\n const retryTimer = setInterval(publishAllQueued, 1_000);\n retryTimer.unref();\n\n return Object.freeze({\n recipientKey: options.recipientKey,\n async deliver(request: DoomSessionDeliveryRequest): Promise<{ deliveryId: string }> {\n if (closed) throw new Error('Session delivery service is closed.');\n const deliveryId = request.deliveryId ?? crypto.randomUUID();\n const mode = request.delivery ?? DEFAULT_DELIVERY;\n if (!deliveryId.trim() || !request.recipientKey.trim() || !request.kind.trim() || !isMode(mode)) {\n throw new TypeError('Delivery id, recipient key, kind, and mode must be valid.');\n }\n if (!options.authorizePeer(request.recipientKey, request.metadata)) {\n throw new Error(`Session '${request.recipientKey}' is not an authorized communication peer.`);\n }\n const metadata = normalizedMetadata(request.metadata);\n database\n .prepare(\n `INSERT OR IGNORE INTO session_delivery_outbox\n (delivery_id, recipient_key, kind, prompt, delivery_mode, metadata_json, state, created_at)\n VALUES (?, ?, ?, ?, ?, ?, 'queued', ?)`,\n )\n .run(\n deliveryId,\n request.recipientKey,\n request.kind,\n request.prompt,\n mode,\n JSON.stringify(metadata),\n Date.now(),\n );\n const current = database\n .prepare('SELECT * FROM session_delivery_outbox WHERE delivery_id = ?')\n .get(deliveryId) as OutboxRow | undefined;\n if (\n !current ||\n current.recipient_key !== request.recipientKey ||\n current.kind !== request.kind ||\n current.prompt !== request.prompt ||\n current.delivery_mode !== mode ||\n !sameMetadata(JSON.parse(current.metadata_json) as DoomSessionDeliveryMetadata, metadata)\n ) {\n throw new TypeError(`Delivery id '${deliveryId}' is already bound to another envelope.`);\n }\n publishOutbox(deliveryId);\n return { deliveryId };\n },\n async waitForAdmission(deliveryId: string, timeoutMs = 5_000): Promise<DoomSessionDeliveryInboxState | undefined> {\n const deadline = Date.now() + Math.max(0, timeoutMs);\n let state: DoomSessionDeliveryInboxState | undefined;\n do {\n const row = database\n .prepare('SELECT recipient_state FROM session_delivery_outbox WHERE delivery_id = ?')\n .get(deliveryId) as { recipient_state: DoomSessionDeliveryInboxState | null } | undefined;\n state = row?.recipient_state ?? undefined;\n if (state === 'admitted' || state === 'recovery_required') return state;\n if (Date.now() >= deadline) return state;\n await new Promise((resolve) => setTimeout(resolve, Math.min(10, deadline - Date.now())));\n } while (!closed);\n return state;\n },\n receive(senderKey: string, kind: string, payload: unknown) {\n if (kind === DELIVERY_EVENT) return receiveEnvelope(senderKey, payload);\n if (kind === ACK_EVENT) {\n receiveAck(senderKey, payload);\n return 'accepted';\n }\n return undefined;\n },\n inbox(query: DoomSessionInboxQuery = {}): readonly DoomSessionInboxEntry[] {\n const rows = database\n .prepare('SELECT * FROM session_delivery_inbox ORDER BY created_at, delivery_id')\n .all() as unknown as InboxRow[];\n return rows\n .map((row): DoomSessionInboxEntry => {\n const metadata = JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata;\n return {\n deliveryId: row.delivery_id,\n senderKey: row.sender_key,\n recipientKey: row.recipient_key,\n kind: row.kind,\n prompt: row.prompt,\n delivery: row.delivery_mode,\n metadata,\n state: row.state,\n consumed: row.consumed_at !== null,\n };\n })\n .filter(\n (entry) =>\n (query.kind === undefined || entry.kind === query.kind) &&\n (query.state === undefined || entry.state === query.state) &&\n (query.consumed === undefined || entry.consumed === query.consumed) &&\n matchesMetadata(entry.metadata, query.metadata),\n );\n },\n consume(deliveryId: string): boolean {\n const result = database\n .prepare(\n \"UPDATE session_delivery_inbox SET consumed_at = ? WHERE delivery_id = ? AND state IN ('admitted', 'recovery_required') AND consumed_at IS NULL\",\n )\n .run(Date.now(), deliveryId);\n return result.changes === 1;\n },\n outbox(deliveryId: string): DoomSessionOutboxEntry | undefined {\n const row = database\n .prepare(\n 'SELECT delivery_id, recipient_key, kind, metadata_json, state, recipient_state FROM session_delivery_outbox WHERE delivery_id = ?',\n )\n .get(deliveryId) as OutboxRow | undefined;\n if (!row) return undefined;\n return {\n deliveryId: row.delivery_id,\n recipientKey: row.recipient_key,\n kind: row.kind,\n metadata: JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata,\n state: row.state,\n ...(row.recipient_state === null ? {} : { recipientState: row.recipient_state }),\n };\n },\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n clearInterval(retryTimer);\n releaseEnvelope();\n releaseAck();\n releaseReady();\n try {\n await admissionQueue;\n } finally {\n database.close();\n }\n },\n });\n}\n\n/**\n * Installs a provider-owned endpoint in the current Cordis context.\n *\n * Returns the instance because a provider cannot read its own service back out:\n * `ctx.get` is strict and hides an implementation while its providing fiber is\n * LOADING, which is the whole of that fiber's own callback.\n */\nexport function provideSessionDeliveryService(\n context: Context,\n options: SessionDeliveryServiceOptions,\n): { readonly service: DoomSessionDeliveryService; readonly close: () => Promise<void> } {\n const service = createSessionDeliveryService(options);\n const unprovide = context.provide(DOOM_SESSION_DELIVERY_SERVICE, service);\n // A caller that throws before returning its disposer would otherwise leave the\n // database, its WAL files and its retry timer open for the life of the process.\n // close() is idempotent, so this net never conflicts with the ordered close below.\n context.effect(() => () => service.close(), 'session delivery database');\n return {\n service,\n close: async () => {\n unprovide();\n await service.close();\n },\n };\n}\n\nexport type {\n DoomSessionDeliveryInboxState,\n DoomSessionDeliveryMetadata,\n DoomSessionDeliveryMode,\n DoomSessionDeliveryRequest,\n DoomSessionDeliveryService,\n DoomSessionInboxEntry,\n DoomSessionInboxQuery,\n DoomSessionOutboxEntry,\n SessionDeliveryServiceOptions,\n} from './type';\nexport { DOOM_SESSION_DELIVERY_SERVICE, readDoomSessionDelivery } from './type';\n"],"mappings":"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"}
1
+ {"version":3,"file":"sessionDelivery-DNq4a8LB.mjs","names":["envelopeOf"],"sources":["../src/services/peerTransport/index.ts","../src/services/sessionDirectory/index.ts","../src/services/sessionGroups/type.ts","../src/services/sessionGroups/index.ts","../src/services/sessionIntercom/type.ts","../src/services/sessionIntercom/index.ts","../src/services/sessionDelivery/type.ts","../src/services/sessionDelivery/index.ts"],"sourcesContent":["import { createHash, createHmac, timingSafeEqual } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\n\nimport type { DoomSessionCommunicationEndpoint } from '@agimon-ai/doompi-core/hubChannel';\n\nconst PEER_CONFIG_VERSION = 1;\nconst PEER_CONFIG_FILE = 'peers.json';\nconst PEER_ROUTE = '/api/plugins/session-peer/inbox';\nconst PEER_HEADER = 'x-doompi-session-peer';\nconst TIMESTAMP_HEADER = 'x-doompi-session-timestamp';\nconst SIGNATURE_HEADER = 'x-doompi-session-signature';\nconst MAX_CLOCK_SKEW_MS = 5 * 60_000;\nconst MAX_REPLAY_ENTRIES = 10_000;\nconst REPLAY_DATABASE_FILE = 'peer-replay.sqlite';\n\nexport interface SessionPeer {\n readonly hostId: string;\n readonly url: string;\n readonly secret: string;\n /** Explicit remote durable-message targets. Empty means no delivery grant. */\n readonly allowedSessionIds: readonly string[];\n /** Explicit remote Voice media targets. Empty means no media grant. */\n readonly allowedVoiceSessionIds: readonly string[];\n}\n\nexport interface SessionPeerConfig {\n readonly version: typeof PEER_CONFIG_VERSION;\n readonly hostId: string;\n readonly peers: readonly SessionPeer[];\n}\n\nexport interface RemoteSessionReference {\n readonly hostId: string;\n readonly sessionId: string;\n}\n\nexport interface SessionPeerEnvelope {\n readonly sourceSessionId: string;\n readonly targetSessionId: string;\n readonly type: string;\n readonly payload: unknown;\n}\n\nexport interface SessionPeerReplayGuard {\n admit(request: Request, now?: number): boolean;\n close(): void;\n}\n\nfunction validId(value: unknown): value is string {\n return typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(value);\n}\n\nfunction peerOf(value: unknown): SessionPeer | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n if (!validId(record.hostId) || typeof record.url !== 'string' || typeof record.secret !== 'string') return undefined;\n let url: URL;\n try {\n url = new URL(record.url);\n } catch {\n return undefined;\n }\n if (url.protocol !== 'https:' || url.username !== '' || url.password !== '' || url.search !== '' || url.hash !== '')\n return undefined;\n const allowedSessionIds =\n Array.isArray(record.allowedSessionIds) && record.allowedSessionIds.every(validId)\n ? record.allowedSessionIds\n : undefined;\n const allowedVoiceSessionIds =\n Array.isArray(record.allowedVoiceSessionIds) && record.allowedVoiceSessionIds.every(validId)\n ? record.allowedVoiceSessionIds\n : [];\n if (allowedSessionIds === undefined || record.secret.length < 32) return undefined;\n return {\n hostId: record.hostId,\n url: url.toString(),\n secret: record.secret,\n allowedSessionIds,\n allowedVoiceSessionIds,\n };\n}\n\nexport function sessionPeerConfigPath(homeDirectory: string): string {\n return path.join(homeDirectory, '.pi', '.doom', 'session', PEER_CONFIG_FILE);\n}\n\n/** Reads operator-provisioned peers. Invalid or unreadable config fails closed. */\nexport function readSessionPeerConfig(homeDirectory: string): SessionPeerConfig | undefined {\n let parsed: unknown;\n try {\n const file = sessionPeerConfigPath(homeDirectory);\n if ((fs.statSync(file).mode & 0o077) !== 0) return undefined;\n parsed = JSON.parse(fs.readFileSync(file, 'utf8')) as unknown;\n } catch {\n return undefined;\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return undefined;\n const record = parsed as Record<string, unknown>;\n if (record.version !== PEER_CONFIG_VERSION || !validId(record.hostId) || !Array.isArray(record.peers))\n return undefined;\n const peers = record.peers.map(peerOf);\n if (peers.some((peer) => peer === undefined)) return undefined;\n const resolved = peers as SessionPeer[];\n if (\n new Set(resolved.map((peer) => peer.hostId)).size !== resolved.length ||\n resolved.some((peer) => peer.hostId === record.hostId)\n )\n return undefined;\n return { version: PEER_CONFIG_VERSION, hostId: record.hostId, peers: resolved };\n}\n\n/** `peer/<host-id>/<session-id>` is the only remote target spelling. */\nexport function parseRemoteSessionReference(value: string): RemoteSessionReference | undefined {\n const match = /^peer\\/([^/]+)\\/([^/]+)$/u.exec(value);\n return match && validId(match[1]) && validId(match[2]) ? { hostId: match[1], sessionId: match[2] } : undefined;\n}\n\nexport function peerSessionReference(hostId: string, sessionId: string): string {\n if (!validId(hostId) || !validId(sessionId))\n throw new TypeError('Remote host and session identifiers must be safe opaque IDs.');\n return `peer/${hostId}/${sessionId}`;\n}\n\nfunction signature(secret: string, method: string, pathname: string, timestamp: string, body: string): string {\n const digest = createHash('sha256').update(body).digest('base64url');\n return createHmac('sha256', secret).update(`${method}\\n${pathname}\\n${timestamp}\\n${digest}`).digest('base64url');\n}\n\nexport function peerRequestHeaders(\n sourceHostId: string,\n peer: SessionPeer,\n method: string,\n pathname: string,\n body: string,\n now = Date.now(),\n): Headers {\n if (!validId(sourceHostId)) throw new TypeError('Source host identity must be a safe opaque ID.');\n const timestamp = String(now);\n return new Headers({\n 'content-type': 'application/json',\n [PEER_HEADER]: sourceHostId,\n [TIMESTAMP_HEADER]: timestamp,\n [SIGNATURE_HEADER]: signature(peer.secret, method, pathname, timestamp, body),\n });\n}\n\n/** Persists accepted peer signatures so a valid request cannot be replayed within its clock-skew window. */\nexport function createPeerReplayGuard(homeDirectory: string): SessionPeerReplayGuard {\n const directory = path.dirname(sessionPeerConfigPath(homeDirectory));\n fs.mkdirSync(directory, { recursive: true, mode: 0o700 });\n const database = new DatabaseSync(path.join(directory, REPLAY_DATABASE_FILE));\n database.exec(`\n PRAGMA journal_mode = WAL;\n CREATE TABLE IF NOT EXISTS peer_request_replays (\n signature TEXT PRIMARY KEY,\n expires_at INTEGER NOT NULL\n );\n `);\n const removeExpired = database.prepare('DELETE FROM peer_request_replays WHERE expires_at < ?');\n const insert = database.prepare('INSERT OR IGNORE INTO peer_request_replays (signature, expires_at) VALUES (?, ?)');\n const count = database.prepare('SELECT COUNT(*) AS count FROM peer_request_replays');\n const trim = database.prepare(`\n DELETE FROM peer_request_replays\n WHERE signature IN (\n SELECT signature FROM peer_request_replays ORDER BY expires_at ASC, signature ASC LIMIT ?\n )\n `);\n return {\n admit(request, now = Date.now()) {\n const supplied = request.headers.get(SIGNATURE_HEADER);\n if (!supplied) return false;\n database.exec('BEGIN IMMEDIATE');\n try {\n removeExpired.run(now);\n const accepted = insert.run(supplied, now + MAX_CLOCK_SKEW_MS).changes === 1;\n const total = Number((count.get() as { count: number | bigint }).count);\n if (total > MAX_REPLAY_ENTRIES) trim.run(total - MAX_REPLAY_ENTRIES);\n database.exec('COMMIT');\n return accepted;\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n },\n close: () => database.close(),\n };\n}\n\nexport function verifyPeerRequest(\n config: SessionPeerConfig,\n request: Request,\n body: string,\n now = Date.now(),\n): SessionPeer | undefined {\n const hostId = request.headers.get(PEER_HEADER);\n const timestamp = request.headers.get(TIMESTAMP_HEADER);\n const supplied = request.headers.get(SIGNATURE_HEADER);\n if (!hostId || !timestamp || !supplied || !/^\\d{1,16}$/u.test(timestamp)) return undefined;\n const sentAt = Number(timestamp);\n if (!Number.isSafeInteger(sentAt) || Math.abs(now - sentAt) > MAX_CLOCK_SKEW_MS) return undefined;\n const peer = config.peers.find((candidate) => candidate.hostId === hostId);\n if (!peer) return undefined;\n const expected = Buffer.from(signature(peer.secret, request.method, new URL(request.url).pathname, timestamp, body));\n const actual = Buffer.from(supplied);\n return actual.byteLength === expected.byteLength && timingSafeEqual(actual, expected) ? peer : undefined;\n}\n\nfunction envelopeOf(value: unknown): SessionPeerEnvelope | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n return validId(record.sourceSessionId) &&\n validId(record.targetSessionId) &&\n typeof record.type === 'string' &&\n record.type !== ''\n ? {\n sourceSessionId: record.sourceSessionId,\n targetSessionId: record.targetSessionId,\n type: record.type,\n payload: record.payload,\n }\n : undefined;\n}\n\nexport function parseSessionPeerEnvelope(value: unknown): SessionPeerEnvelope | undefined {\n return envelopeOf(value);\n}\n\n/** Adds asynchronous tunnel publication to a host-bound local communication endpoint. */\nexport function createPeerCommunication(options: {\n readonly local: DoomSessionCommunicationEndpoint;\n readonly homeDirectory: string;\n readonly fetch?: typeof fetch;\n}): DoomSessionCommunicationEndpoint {\n const config = readSessionPeerConfig(options.homeDirectory);\n const send = options.fetch ?? fetch;\n return {\n sessionId: options.local.sessionId,\n publish(target, type, payload) {\n const remote = parseRemoteSessionReference(target);\n if (!remote) return options.local.publish(target, type, payload);\n const peer = config?.peers.find((candidate) => candidate.hostId === remote.hostId);\n // Pairing is not a grant. Outbound delivery needs the same explicit target\n // allowlist that the receiver enforces for inbound envelopes.\n if (!config || !peer || !peer.allowedSessionIds.includes(remote.sessionId)) return false;\n const body = JSON.stringify({\n sourceSessionId: options.local.sessionId,\n targetSessionId: remote.sessionId,\n type,\n payload,\n });\n const url = new URL(PEER_ROUTE, peer.url);\n void send(url, {\n method: 'POST',\n headers: peerRequestHeaders(config.hostId, peer, 'POST', '/inbox', body),\n body,\n }).catch(() => undefined);\n return true;\n },\n subscribe: (type, listener) => options.local.subscribe(type, listener),\n onPeerReady: (listener) => options.local.onPeerReady(listener),\n close: () => options.local.close(),\n };\n}\n","import { peerSessionReference } from '../peerTransport';\nimport type {\n DiscoveredSession,\n SessionDirectory,\n SessionDirectoryOptions,\n SessionPresenceFacts,\n SessionPresenceObservation,\n} from './type';\n\nconst UNKNOWN_FACTS: SessionPresenceFacts = Object.freeze({\n reachability: 'unknown',\n runtime: 'unknown',\n activity: 'unknown',\n voice: Object.freeze({ eligible: 'unknown', readiness: 'unknown' }),\n});\n\nfunction keyOf(observation: Pick<SessionPresenceObservation, 'hostId' | 'sessionId'>): string {\n return peerSessionReference(observation.hostId, observation.sessionId);\n}\n\nfunction publicEntry(\n observation: SessionPresenceObservation,\n now: number,\n label: string | undefined,\n capabilities: readonly string[],\n): DiscoveredSession {\n const freshUntil = observation.observedAt + observation.staleAfterMs;\n const fresh = now <= freshUntil;\n const facts: SessionPresenceFacts = fresh ? observation : UNKNOWN_FACTS;\n return Object.freeze({\n reference: keyOf(observation),\n ...(label === undefined ? {} : { label }),\n capabilities: Object.freeze([...capabilities]),\n hostIncarnation: observation.hostIncarnation,\n sessionIncarnation: observation.sessionIncarnation,\n sequence: observation.sequence,\n observedAt: observation.observedAt,\n freshUntil,\n fresh,\n reachability: facts.reachability,\n runtime: facts.runtime,\n activity: facts.activity,\n voice: Object.freeze({ ...facts.voice }),\n });\n}\n\n/** In-memory authenticated presence cache. Restart deliberately forgets every observation. */\nexport function createSessionDirectory(options: SessionDirectoryOptions): SessionDirectory {\n const now = options.now ?? Date.now;\n const observations = new Map<string, SessionPresenceObservation>();\n const snapshotRequired = new Set<string>();\n const subscribers = new Set<{\n callerReference: string;\n listener: (sessions: readonly DiscoveredSession[]) => void;\n }>();\n\n const discover = (callerReference: string, allowedReferences?: ReadonlySet<string>): readonly DiscoveredSession[] => {\n const result: DiscoveredSession[] = [];\n for (const observation of observations.values()) {\n const reference = keyOf(observation);\n if (allowedReferences && !allowedReferences.has(reference)) continue;\n const grant = options.authorizeDiscovery(callerReference, observation);\n if (!grant) continue;\n result.push(publicEntry(observation, now(), grant.label ?? observation.label, grant.capabilities));\n }\n return result.sort((left, right) => left.reference.localeCompare(right.reference));\n };\n const notify = (): void => {\n for (const subscriber of subscribers) subscriber.listener(discover(subscriber.callerReference));\n };\n\n return {\n observe(observation) {\n const key = keyOf(observation);\n const current = observations.get(key);\n if (snapshotRequired.has(observation.hostId)) return false;\n if (current?.hostIncarnation === observation.hostIncarnation) {\n if (current.sessionIncarnation === observation.sessionIncarnation && observation.sequence <= current.sequence)\n return false;\n if (observation.sequence !== current.sequence + 1) {\n snapshotRequired.add(observation.hostId);\n for (const [reference, candidate] of observations)\n if (candidate.hostId === observation.hostId)\n observations.set(reference, { ...candidate, ...UNKNOWN_FACTS, observedAt: now(), staleAfterMs: 0 });\n notify();\n return false;\n }\n }\n observations.set(key, Object.freeze({ ...observation, voice: Object.freeze({ ...observation.voice }) }));\n notify();\n return true;\n },\n replaceHostSnapshot(hostId, hostIncarnation, replacements) {\n if (\n replacements.some(\n (observation) => observation.hostId !== hostId || observation.hostIncarnation !== hostIncarnation,\n )\n ) {\n throw new TypeError('A presence snapshot must contain only the declared host incarnation.');\n }\n for (const [reference, observation] of observations)\n if (observation.hostId === hostId) observations.delete(reference);\n for (const observation of replacements)\n observations.set(\n keyOf(observation),\n Object.freeze({ ...observation, voice: Object.freeze({ ...observation.voice }) }),\n );\n snapshotRequired.delete(hostId);\n notify();\n },\n hostDisconnected(hostId) {\n for (const [reference, observation] of observations) {\n if (observation.hostId !== hostId) continue;\n observations.set(reference, { ...observation, reachability: 'unreachable' });\n }\n notify();\n },\n discover,\n resolveDeliveryTarget(callerReference, reference) {\n const observation = observations.get(reference);\n return observation && options.authorizeDiscovery(callerReference, observation)\n ? observation.deliveryTarget\n : undefined;\n },\n subscribe(callerReference, listener) {\n const subscriber = { callerReference, listener };\n subscribers.add(subscriber);\n listener(discover(callerReference));\n return () => subscribers.delete(subscriber);\n },\n };\n}\n\nexport type {\n DiscoveredSession,\n SessionActivityState,\n SessionDirectory,\n SessionDirectoryOptions,\n SessionDiscoveryGrant,\n SessionHostReachability,\n SessionPresenceFacts,\n SessionPresenceObservation,\n SessionRuntimeState,\n SessionVoiceReadiness,\n} from './type';\n","export interface SessionCommunicationGroup {\n readonly id: string;\n readonly ownerAuthority: string;\n readonly revision: number;\n readonly members: readonly string[];\n}\n\nexport interface SessionGroupMutation {\n readonly groupId: string;\n readonly authority: string;\n readonly expectedRevision: number;\n readonly add?: readonly string[];\n readonly remove?: readonly string[];\n}\n\nexport interface SessionGroupStoreOptions {\n readonly databasePath: string;\n readonly authorizeManagement?: (authority: string, group: SessionCommunicationGroup) => boolean;\n readonly validateEnrollment?: (groupId: string, memberReference: string) => boolean;\n}\n\nexport interface SessionGroupStore {\n create(groupId: string, ownerAuthority: string, members: readonly string[]): SessionCommunicationGroup;\n mutate(mutation: SessionGroupMutation): SessionCommunicationGroup;\n get(groupId: string): SessionCommunicationGroup | undefined;\n groupsFor(memberReference: string): readonly SessionCommunicationGroup[];\n canMessage(groupId: string, sourceReference: string, targetReference: string): boolean;\n close(): void;\n}\n\nexport class SessionGroupRevisionError extends Error {\n constructor(groupId: string, expected: number, actual: number) {\n super(`Session group '${groupId}' revision conflict: expected ${expected}, current ${actual}.`);\n this.name = 'SessionGroupRevisionError';\n }\n}\n","import { DatabaseSync } from 'node:sqlite';\n\nimport {\n SessionGroupRevisionError,\n type SessionCommunicationGroup,\n type SessionGroupMutation,\n type SessionGroupStore,\n type SessionGroupStoreOptions,\n} from './type';\n\ninterface GroupRow {\n group_id: string;\n owner_authority: string;\n revision: number;\n}\n\nconst ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;\nconst REFERENCE_PATTERN = /^peer\\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}\\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;\n\nfunction validateGroupId(value: string): void {\n if (!ID_PATTERN.test(value)) throw new TypeError('Session group IDs must be safe opaque IDs.');\n}\n\nfunction validateReference(value: string): void {\n if (!REFERENCE_PATTERN.test(value))\n throw new TypeError(`Session group member '${value}' is not a qualified reference.`);\n}\n\n/** Opens a revisioned SQLite registry for communication-only group membership. */\nexport function createSessionGroupStore(options: SessionGroupStoreOptions): SessionGroupStore {\n const database = new DatabaseSync(options.databasePath);\n database.exec(`\n PRAGMA journal_mode = WAL;\n PRAGMA foreign_keys = ON;\n CREATE TABLE IF NOT EXISTS session_groups (\n group_id TEXT PRIMARY KEY,\n owner_authority TEXT NOT NULL,\n revision INTEGER NOT NULL\n );\n CREATE TABLE IF NOT EXISTS session_group_members (\n group_id TEXT NOT NULL REFERENCES session_groups(group_id) ON DELETE CASCADE,\n member_reference TEXT NOT NULL,\n PRIMARY KEY (group_id, member_reference)\n );\n `);\n\n const read = (groupId: string): SessionCommunicationGroup | undefined => {\n const row = database.prepare('SELECT * FROM session_groups WHERE group_id = ?').get(groupId) as\n | GroupRow\n | undefined;\n if (!row) return undefined;\n const members = database\n .prepare('SELECT member_reference FROM session_group_members WHERE group_id = ? ORDER BY member_reference')\n .all(groupId) as { member_reference: string }[];\n return Object.freeze({\n id: row.group_id,\n ownerAuthority: row.owner_authority,\n revision: row.revision,\n members: Object.freeze(members.map((member) => member.member_reference)),\n });\n };\n\n const enroll = (groupId: string, members: readonly string[]): void => {\n const insert = database.prepare(\n 'INSERT OR IGNORE INTO session_group_members (group_id, member_reference) VALUES (?, ?)',\n );\n for (const member of new Set(members)) {\n validateReference(member);\n if (options.validateEnrollment?.(groupId, member) === false)\n throw new Error(`Session group enrollment policy rejected '${member}'.`);\n insert.run(groupId, member);\n }\n };\n\n return {\n create(groupId, ownerAuthority, members) {\n validateGroupId(groupId);\n if (!ownerAuthority.trim()) throw new TypeError('Session group owner authority is required.');\n database.exec('BEGIN IMMEDIATE');\n try {\n database\n .prepare('INSERT INTO session_groups (group_id, owner_authority, revision) VALUES (?, ?, 1)')\n .run(groupId, ownerAuthority);\n enroll(groupId, members);\n database.exec('COMMIT');\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n return read(groupId)!;\n },\n mutate(mutation: SessionGroupMutation) {\n database.exec('BEGIN IMMEDIATE');\n try {\n const current = read(mutation.groupId);\n if (!current) throw new Error(`Session group '${mutation.groupId}' does not exist.`);\n if (\n mutation.authority !== current.ownerAuthority &&\n options.authorizeManagement?.(mutation.authority, current) !== true\n ) {\n throw new Error(`Authority '${mutation.authority}' cannot manage Session group '${mutation.groupId}'.`);\n }\n if (mutation.expectedRevision !== current.revision)\n throw new SessionGroupRevisionError(mutation.groupId, mutation.expectedRevision, current.revision);\n enroll(mutation.groupId, mutation.add ?? []);\n const remove = database.prepare(\n 'DELETE FROM session_group_members WHERE group_id = ? AND member_reference = ?',\n );\n for (const member of new Set(mutation.remove ?? [])) {\n validateReference(member);\n remove.run(mutation.groupId, member);\n }\n database\n .prepare('UPDATE session_groups SET revision = revision + 1 WHERE group_id = ? AND revision = ?')\n .run(mutation.groupId, current.revision);\n database.exec('COMMIT');\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n return read(mutation.groupId)!;\n },\n get: read,\n groupsFor(memberReference) {\n validateReference(memberReference);\n const rows = database\n .prepare(\n `SELECT g.group_id FROM session_groups g\n INNER JOIN session_group_members m ON m.group_id = g.group_id\n WHERE m.member_reference = ? ORDER BY g.group_id`,\n )\n .all(memberReference) as { group_id: string }[];\n return rows.map((row) => read(row.group_id)!);\n },\n canMessage(groupId, sourceReference, targetReference) {\n validateReference(sourceReference);\n validateReference(targetReference);\n const row = database\n .prepare(\n `SELECT COUNT(*) AS count FROM session_group_members\n WHERE group_id = ? AND member_reference IN (?, ?)`,\n )\n .get(groupId, sourceReference, targetReference) as { count: number | bigint };\n return Number(row.count) === (sourceReference === targetReference ? 1 : 2);\n },\n close: () => database.close(),\n };\n}\n\nexport {\n SessionGroupRevisionError,\n type SessionCommunicationGroup,\n type SessionGroupMutation,\n type SessionGroupStore,\n type SessionGroupStoreOptions,\n} from './type';\n","import type { Context } from '@deepseek-ai/cordis';\n\nimport type {\n DoomSessionDeliveryMetadata,\n DoomSessionDeliveryService,\n DoomSessionInboxEntry,\n DoomSessionOutboxEntry,\n} from '../sessionDelivery';\nimport type { DiscoveredSession, SessionDirectory } from '../sessionDirectory';\nimport type { SessionGroupStore } from '../sessionGroups';\n\nexport const DOOM_SESSION_INTERCOM_SERVICE = 'doom/session-intercom';\n\nexport type SessionReportStatus = 'done' | 'blocked' | 'failed';\n\nexport interface SessionIntercomMessage {\n readonly deliveryId: string;\n readonly sourceReference: string;\n readonly targetReference: string;\n readonly groupId: string;\n readonly correlationId?: string;\n readonly text: string;\n readonly reportStatus?: SessionReportStatus;\n readonly state: DoomSessionInboxEntry['state'];\n readonly consumed: boolean;\n}\n\nexport interface SessionIntercomSendRequest {\n readonly targetReference: string;\n readonly groupId: string;\n readonly text: string;\n readonly correlationId?: string;\n readonly deliveryId?: string;\n}\n\nexport interface SessionIntercomOptions {\n readonly selfReference: string;\n readonly directory: SessionDirectory;\n readonly groups: SessionGroupStore;\n readonly delivery: DoomSessionDeliveryService;\n}\n\nexport interface SessionIntercom {\n discover(): readonly DiscoveredSession[];\n send(request: SessionIntercomSendRequest): Promise<{ deliveryId: string }>;\n report(\n request: SessionIntercomSendRequest & { readonly status: SessionReportStatus },\n ): Promise<{ deliveryId: string }>;\n messages(): readonly SessionIntercomMessage[];\n delivery(deliveryId: string): DoomSessionOutboxEntry | undefined;\n}\n\nexport interface SessionGroupDeliveryAuthorizationOptions {\n readonly selfReference: string;\n readonly groups: SessionGroupStore;\n readonly peerReference: (peerKey: string) => string | undefined;\n readonly fallback?: (peerKey: string, metadata: DoomSessionDeliveryMetadata | undefined) => boolean;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/session-intercom': SessionIntercom;\n }\n}\n\nexport function readSessionIntercom(context: Context): SessionIntercom | undefined {\n return context.get(DOOM_SESSION_INTERCOM_SERVICE) as SessionIntercom | undefined;\n}\n\nexport function requireSessionIntercom(context: Context): SessionIntercom {\n const service = readSessionIntercom(context);\n if (!service)\n throw new Error('Session intercom is unavailable. Activate Session with a configured persistent host identity.');\n return service;\n}\n","import type { DoomSessionDeliveryMetadata } from '../sessionDelivery';\nimport type { SessionIntercomMessage } from './type';\nimport type {\n SessionGroupDeliveryAuthorizationOptions,\n SessionIntercom,\n SessionIntercomOptions,\n SessionIntercomSendRequest,\n SessionReportStatus,\n} from './type';\n\nconst MESSAGE_KIND = 'session-message';\nconst REPORT_KIND = 'session-report';\n\nfunction metadataFor(\n options: SessionIntercomOptions,\n request: SessionIntercomSendRequest,\n reportStatus?: SessionReportStatus,\n): DoomSessionDeliveryMetadata {\n const group = options.groups.get(request.groupId);\n if (!group || !options.groups.canMessage(request.groupId, options.selfReference, request.targetReference))\n throw new Error(`Session group '${request.groupId}' does not authorize this message.`);\n return {\n sourceReference: options.selfReference,\n targetReference: request.targetReference,\n groupId: request.groupId,\n groupRevision: String(group.revision),\n ...(request.correlationId === undefined ? {} : { correlationId: request.correlationId }),\n ...(reportStatus === undefined ? {} : { reportStatus }),\n };\n}\n\n/** Agent-facing intercom operations. A composition may acquire this service without gaining session controls. */\nexport function createSessionIntercom(options: SessionIntercomOptions): SessionIntercom {\n const deliver = async (\n request: SessionIntercomSendRequest,\n kind: typeof MESSAGE_KIND | typeof REPORT_KIND,\n status?: SessionReportStatus,\n ): Promise<{ deliveryId: string }> => {\n const recipientKey = options.directory.resolveDeliveryTarget(options.selfReference, request.targetReference);\n if (!recipientKey) throw new Error(`Session '${request.targetReference}' is not discoverable.`);\n const metadata = metadataFor(options, request, status);\n return options.delivery.deliver({\n ...(request.deliveryId === undefined ? {} : { deliveryId: request.deliveryId }),\n recipientKey,\n kind,\n prompt: `[Session ${status === undefined ? 'message' : `report: ${status}`} from ${options.selfReference}] ${request.text}`,\n metadata,\n });\n };\n\n const intercom: SessionIntercom = {\n discover() {\n const members = new Set(\n options.groups\n .groupsFor(options.selfReference)\n .flatMap((group) => group.members)\n .filter((reference) => reference !== options.selfReference),\n );\n return options.directory.discover(options.selfReference, members);\n },\n send: (request) => deliver(request, MESSAGE_KIND),\n report: (request) => deliver(request, REPORT_KIND, request.status),\n messages() {\n return options.delivery\n .inbox()\n .filter((entry) => entry.kind === MESSAGE_KIND || entry.kind === REPORT_KIND)\n .filter((entry) => {\n const groupId = entry.metadata.groupId;\n return groupId !== undefined && options.groups.get(groupId)?.members.includes(options.selfReference) === true;\n })\n .flatMap((entry): SessionIntercomMessage[] => {\n const sourceReference = entry.metadata.sourceReference;\n const targetReference = entry.metadata.targetReference;\n const groupId = entry.metadata.groupId;\n if (!sourceReference || !targetReference || !groupId) return [];\n const reportStatus = entry.metadata.reportStatus;\n return [\n {\n deliveryId: entry.deliveryId,\n sourceReference,\n targetReference,\n groupId,\n ...(entry.metadata.correlationId === undefined ? {} : { correlationId: entry.metadata.correlationId }),\n text: entry.prompt,\n ...(reportStatus === 'done' || reportStatus === 'blocked' || reportStatus === 'failed'\n ? { reportStatus }\n : {}),\n state: entry.state,\n consumed: entry.consumed,\n },\n ];\n });\n },\n delivery(deliveryId) {\n const entry = options.delivery.outbox(deliveryId);\n const groupId = entry?.metadata.groupId;\n return entry &&\n groupId !== undefined &&\n options.groups.get(groupId)?.members.includes(options.selfReference) === true\n ? entry\n : undefined;\n },\n };\n return Object.freeze(intercom);\n}\n\n/** Builds the dynamic delivery check used before every send, retry, and recipient acceptance. */\nexport function createSessionGroupDeliveryAuthorizer(\n options: SessionGroupDeliveryAuthorizationOptions,\n): (peerKey: string, metadata: DoomSessionDeliveryMetadata | undefined) => boolean {\n return (peerKey, metadata) => {\n const sourceReference = metadata?.sourceReference;\n const targetReference = metadata?.targetReference;\n const groupId = metadata?.groupId;\n if (sourceReference && targetReference && groupId) {\n const peerReference = options.peerReference(peerKey);\n if (!peerReference) return false;\n const directionMatches =\n (sourceReference === options.selfReference && targetReference === peerReference) ||\n (targetReference === options.selfReference && sourceReference === peerReference);\n return directionMatches && options.groups.canMessage(groupId, sourceReference, targetReference);\n }\n return options.fallback?.(peerKey, metadata) === true;\n };\n}\n\nexport { DOOM_SESSION_INTERCOM_SERVICE, readSessionIntercom, requireSessionIntercom } from './type';\nexport type {\n SessionGroupDeliveryAuthorizationOptions,\n SessionIntercom,\n SessionIntercomMessage,\n SessionIntercomOptions,\n SessionIntercomSendRequest,\n SessionReportStatus,\n} from './type';\n","import type { DoomSessionCommunicationEndpoint } from '@agimon-ai/doompi-core/hubChannel';\nimport type { Context } from '@deepseek-ai/cordis';\n\nexport const DOOM_SESSION_DELIVERY_SERVICE = 'doom/session-delivery';\n\nexport type DoomSessionDeliveryInboxState = 'accepted' | 'admitting' | 'admitted' | 'recovery_required';\nexport type DoomSessionDeliveryMode = 'prompt' | 'steer' | 'followUp';\n\nexport interface DoomSessionDeliveryMetadata extends Readonly<Record<string, string | undefined>> {\n readonly worktreeId?: string;\n readonly fromRole?: string;\n}\n\nexport interface DoomSessionDeliveryRequest {\n readonly deliveryId?: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery?: DoomSessionDeliveryMode;\n readonly metadata?: DoomSessionDeliveryMetadata;\n}\n\nexport interface DoomSessionInboxQuery {\n readonly kind?: string;\n readonly metadata?: DoomSessionDeliveryMetadata;\n readonly state?: DoomSessionDeliveryInboxState;\n readonly consumed?: boolean;\n}\n\nexport interface DoomSessionInboxEntry {\n readonly deliveryId: string;\n readonly senderKey: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery: DoomSessionDeliveryMode;\n readonly metadata: DoomSessionDeliveryMetadata;\n readonly state: DoomSessionDeliveryInboxState;\n readonly consumed: boolean;\n}\n\nexport interface DoomSessionOutboxEntry {\n readonly deliveryId: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly metadata: DoomSessionDeliveryMetadata;\n readonly state: 'queued' | 'acknowledged';\n readonly recipientState?: DoomSessionDeliveryInboxState;\n}\n\nexport interface DoomSessionDeliveryService {\n readonly recipientKey: string;\n deliver(request: DoomSessionDeliveryRequest): Promise<{ deliveryId: string }>;\n waitForAdmission(deliveryId: string, timeoutMs?: number): Promise<DoomSessionDeliveryInboxState | undefined>;\n inbox(query?: DoomSessionInboxQuery): readonly DoomSessionInboxEntry[];\n /** Optional host-routed peer envelope admission. Local-only consumers need no transport receiver. */\n receive?(senderKey: string, kind: string, payload: unknown): DoomSessionDeliveryInboxState | undefined;\n consume(deliveryId: string): boolean;\n outbox(deliveryId: string): DoomSessionOutboxEntry | undefined;\n close(): Promise<void>;\n}\n\nexport interface SessionDeliveryServiceOptions {\n readonly databasePath: string;\n readonly recipientKey: string;\n readonly communication: DoomSessionCommunicationEndpoint;\n /** Host-owned relationship check applied before sends, retries, and recipient acceptance. */\n readonly authorizePeer: (peerKey: string, metadata?: DoomSessionDeliveryMetadata) => boolean;\n readonly admitPrompt: (prompt: string, delivery?: DoomSessionDeliveryMode) => Promise<void>;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/session-delivery': DoomSessionDeliveryService;\n }\n}\n\n/** Reads the currently active provider each time, without retaining a stale binding. */\nexport function readDoomSessionDelivery(context: Context): DoomSessionDeliveryService | undefined {\n return context.get(DOOM_SESSION_DELIVERY_SERVICE) as DoomSessionDeliveryService | undefined;\n}\n","import { DatabaseSync } from 'node:sqlite';\n\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport {\n DOOM_SESSION_DELIVERY_SERVICE,\n type DoomSessionDeliveryInboxState,\n type DoomSessionDeliveryMetadata,\n type DoomSessionDeliveryMode,\n type DoomSessionDeliveryRequest,\n type DoomSessionDeliveryService,\n type DoomSessionInboxEntry,\n type DoomSessionInboxQuery,\n type DoomSessionOutboxEntry,\n type SessionDeliveryServiceOptions,\n} from './type';\n\nconst DELIVERY_EVENT = 'doom/session-delivery/envelope';\nconst ACK_EVENT = 'doom/session-delivery/ack';\nconst DEFAULT_DELIVERY: DoomSessionDeliveryMode = 'prompt';\nconst INBOX_STATES = new Set<DoomSessionDeliveryInboxState>(['accepted', 'admitting', 'admitted', 'recovery_required']);\n\ninterface DeliveryEnvelope {\n readonly deliveryId: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery: DoomSessionDeliveryMode;\n readonly metadata: DoomSessionDeliveryMetadata;\n}\n\ninterface DeliveryAck {\n readonly deliveryId: string;\n readonly state: DoomSessionDeliveryInboxState;\n}\n\ninterface InboxRow {\n delivery_id: string;\n sender_key: string;\n recipient_key: string;\n kind: string;\n prompt: string;\n delivery_mode: DoomSessionDeliveryMode;\n metadata_json: string;\n state: DoomSessionDeliveryInboxState;\n consumed_at: number | null;\n}\n\ninterface OutboxRow {\n delivery_id: string;\n recipient_key: string;\n kind: string;\n prompt: string;\n delivery_mode: DoomSessionDeliveryMode;\n metadata_json: string;\n state: 'queued' | 'acknowledged';\n recipient_state: DoomSessionDeliveryInboxState | null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isMode(value: unknown): value is DoomSessionDeliveryMode {\n return value === 'prompt' || value === 'steer' || value === 'followUp';\n}\n\nfunction metadataOf(value: unknown): DoomSessionDeliveryMetadata | undefined {\n if (!isRecord(value)) return undefined;\n const metadata: Record<string, string> = {};\n for (const [key, item] of Object.entries(value)) {\n if (typeof item !== 'string') return undefined;\n metadata[key] = item;\n }\n return metadata;\n}\n\nfunction envelopeOf(value: unknown): DeliveryEnvelope | undefined {\n if (!isRecord(value)) return undefined;\n const metadata = metadataOf(value.metadata);\n if (\n typeof value.deliveryId !== 'string' ||\n !value.deliveryId ||\n typeof value.kind !== 'string' ||\n !value.kind ||\n typeof value.prompt !== 'string' ||\n !isMode(value.delivery) ||\n metadata === undefined\n ) {\n return undefined;\n }\n return {\n deliveryId: value.deliveryId,\n kind: value.kind,\n prompt: value.prompt,\n delivery: value.delivery,\n metadata,\n };\n}\n\nfunction ackOf(value: unknown): DeliveryAck | undefined {\n if (!isRecord(value)) return undefined;\n if (\n typeof value.deliveryId !== 'string' ||\n typeof value.state !== 'string' ||\n !INBOX_STATES.has(value.state as DoomSessionDeliveryInboxState)\n ) {\n return undefined;\n }\n return value as unknown as DeliveryAck;\n}\n\nfunction normalizedMetadata(metadata: DoomSessionDeliveryMetadata | undefined): DoomSessionDeliveryMetadata {\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata ?? {})) {\n if (value !== undefined) normalized[key] = value;\n }\n return normalized;\n}\n\nfunction matchesMetadata(entry: DoomSessionDeliveryMetadata, query: DoomSessionDeliveryMetadata | undefined): boolean {\n return Object.entries(query ?? {}).every(([key, value]) => value === undefined || entry[key] === value);\n}\n\nfunction sameMetadata(left: DoomSessionDeliveryMetadata, right: DoomSessionDeliveryMetadata): boolean {\n return matchesMetadata(left, right) && matchesMetadata(right, left);\n}\n\n/** Opens and starts one durable delivery endpoint. */\nexport function createSessionDeliveryService(options: SessionDeliveryServiceOptions): DoomSessionDeliveryService {\n if (!options.recipientKey.trim() || options.recipientKey !== options.recipientKey.trim()) {\n throw new TypeError('Session delivery requires a trimmed, non-empty recipient key.');\n }\n const database = new DatabaseSync(options.databasePath);\n database.exec(`\n PRAGMA journal_mode = WAL;\n CREATE TABLE IF NOT EXISTS session_delivery_outbox (\n delivery_id TEXT PRIMARY KEY,\n recipient_key TEXT NOT NULL,\n kind TEXT NOT NULL,\n prompt TEXT NOT NULL,\n delivery_mode TEXT NOT NULL,\n metadata_json TEXT NOT NULL,\n state TEXT NOT NULL,\n recipient_state TEXT,\n created_at INTEGER NOT NULL,\n acknowledged_at INTEGER\n );\n CREATE TABLE IF NOT EXISTS session_delivery_inbox (\n delivery_id TEXT PRIMARY KEY,\n sender_key TEXT NOT NULL,\n recipient_key TEXT NOT NULL,\n kind TEXT NOT NULL,\n prompt TEXT NOT NULL,\n delivery_mode TEXT NOT NULL,\n metadata_json TEXT NOT NULL,\n state TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n consumed_at INTEGER\n );\n `);\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE state = 'admitting'\")\n .run(Date.now());\n\n let closed = false;\n const scheduled = new Set<string>();\n let admissionQueue = Promise.resolve();\n\n const publishAck = (deliveryId: string, senderKey: string, state: DoomSessionDeliveryInboxState): void => {\n options.communication.publish(senderKey, ACK_EVENT, { deliveryId, state } satisfies DeliveryAck);\n };\n\n const readInboxRow = (deliveryId: string): InboxRow | undefined =>\n database.prepare('SELECT * FROM session_delivery_inbox WHERE delivery_id = ?').get(deliveryId) as\n | InboxRow\n | undefined;\n\n const scheduleAdmission = (deliveryId: string): void => {\n if (closed || scheduled.has(deliveryId)) return;\n scheduled.add(deliveryId);\n admissionQueue = admissionQueue\n .then(async () => {\n try {\n if (closed) return;\n const row = readInboxRow(deliveryId);\n if (!row || row.state !== 'accepted') return;\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'admitting', updated_at = ? WHERE delivery_id = ?\")\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'admitting');\n try {\n await options.admitPrompt(row.prompt, row.delivery_mode);\n } catch {\n database\n .prepare(\n \"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE delivery_id = ?\",\n )\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'recovery_required');\n return;\n }\n database\n .prepare(\"UPDATE session_delivery_inbox SET state = 'admitted', updated_at = ? WHERE delivery_id = ?\")\n .run(Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'admitted');\n } finally {\n scheduled.delete(deliveryId);\n }\n })\n .catch(() => {\n scheduled.delete(deliveryId);\n try {\n const row = readInboxRow(deliveryId);\n if (row?.state !== 'admitting') return;\n database\n .prepare(\n \"UPDATE session_delivery_inbox SET state = 'recovery_required', updated_at = ? WHERE delivery_id = ?\",\n )\n .run(Date.now(), deliveryId);\n try {\n publishAck(deliveryId, row.sender_key, 'recovery_required');\n } catch {\n // The durable state is authoritative; readiness replay can request another acknowledgement.\n }\n } catch {\n // A database failure remains recoverable on restart when the schema can be opened again.\n }\n });\n };\n\n const receiveEnvelope = (senderKey: string, value: unknown): DoomSessionDeliveryInboxState | undefined => {\n if (closed) return undefined;\n const envelope = envelopeOf(value);\n if (!envelope || !options.authorizePeer(senderKey, envelope.metadata)) return undefined;\n database\n .prepare(\n `INSERT OR IGNORE INTO session_delivery_inbox\n (delivery_id, sender_key, recipient_key, kind, prompt, delivery_mode, metadata_json, state, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, 'accepted', ?, ?)`,\n )\n .run(\n envelope.deliveryId,\n senderKey,\n options.recipientKey,\n envelope.kind,\n envelope.prompt,\n envelope.delivery,\n JSON.stringify(envelope.metadata),\n Date.now(),\n Date.now(),\n );\n const current = readInboxRow(envelope.deliveryId);\n if (!current) return undefined;\n const sameEnvelope =\n current.sender_key === senderKey &&\n current.recipient_key === options.recipientKey &&\n current.kind === envelope.kind &&\n current.prompt === envelope.prompt &&\n current.delivery_mode === envelope.delivery &&\n sameMetadata(JSON.parse(current.metadata_json) as DoomSessionDeliveryMetadata, envelope.metadata);\n if (!sameEnvelope) return undefined;\n publishAck(envelope.deliveryId, current.sender_key, current.state);\n if (current.state === 'accepted') scheduleAdmission(envelope.deliveryId);\n return current.state;\n };\n\n const receiveAck = (recipientKey: string, value: unknown): void => {\n const ack = ackOf(value);\n if (closed || !ack) return;\n database\n .prepare(\n `UPDATE session_delivery_outbox\n SET state = 'acknowledged', recipient_state = ?, acknowledged_at = ?\n WHERE delivery_id = ? AND recipient_key = ?\n AND (recipient_state IS NULL\n OR (recipient_state = 'accepted' AND ? != 'accepted')\n OR (recipient_state = 'admitting' AND ? IN ('admitted', 'recovery_required')))`,\n )\n .run(ack.state, Date.now(), ack.deliveryId, recipientKey, ack.state, ack.state);\n };\n\n const publishOutbox = (deliveryId: string): void => {\n const row = database\n .prepare(\n \"SELECT * FROM session_delivery_outbox WHERE delivery_id = ? AND (recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required'))\",\n )\n .get(deliveryId) as OutboxRow | undefined;\n if (!row) return;\n const metadata = JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata;\n if (!options.authorizePeer(row.recipient_key, metadata)) return;\n options.communication.publish(row.recipient_key, DELIVERY_EVENT, {\n deliveryId: row.delivery_id,\n kind: row.kind,\n prompt: row.prompt,\n delivery: row.delivery_mode,\n metadata,\n } satisfies DeliveryEnvelope);\n };\n\n const publishQueued = (recipientKey: string): void => {\n for (const row of database\n .prepare(\n \"SELECT delivery_id FROM session_delivery_outbox WHERE recipient_key = ? AND (recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required'))\",\n )\n .all(recipientKey) as { delivery_id: string }[]) {\n publishOutbox(row.delivery_id);\n }\n };\n const publishAllQueued = (): void => {\n for (const row of database\n .prepare(\n \"SELECT delivery_id FROM session_delivery_outbox WHERE recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required')\",\n )\n .all() as { delivery_id: string }[]) {\n publishOutbox(row.delivery_id);\n }\n };\n const releaseEnvelope = options.communication.subscribe(DELIVERY_EVENT, receiveEnvelope);\n const releaseAck = options.communication.subscribe(ACK_EVENT, receiveAck);\n const releaseReady = options.communication.onPeerReady(publishQueued);\n\n for (const row of database\n .prepare(\"SELECT delivery_id, sender_key FROM session_delivery_inbox WHERE state = 'recovery_required'\")\n .all() as { delivery_id: string; sender_key: string }[]) {\n publishAck(row.delivery_id, row.sender_key, 'recovery_required');\n }\n for (const row of database\n .prepare(\"SELECT delivery_id FROM session_delivery_inbox WHERE state = 'accepted'\")\n .all() as {\n delivery_id: string;\n }[]) {\n scheduleAdmission(row.delivery_id);\n }\n publishAllQueued();\n // A publish only means the transport accepted the envelope. Repeat stable delivery\n // IDs until a terminal acknowledgement arrives, including after a tunnel restart.\n const retryTimer = setInterval(publishAllQueued, 1_000);\n retryTimer.unref();\n\n return Object.freeze({\n recipientKey: options.recipientKey,\n async deliver(request: DoomSessionDeliveryRequest): Promise<{ deliveryId: string }> {\n if (closed) throw new Error('Session delivery service is closed.');\n const deliveryId = request.deliveryId ?? crypto.randomUUID();\n const mode = request.delivery ?? DEFAULT_DELIVERY;\n if (!deliveryId.trim() || !request.recipientKey.trim() || !request.kind.trim() || !isMode(mode)) {\n throw new TypeError('Delivery id, recipient key, kind, and mode must be valid.');\n }\n if (!options.authorizePeer(request.recipientKey, request.metadata)) {\n throw new Error(`Session '${request.recipientKey}' is not an authorized communication peer.`);\n }\n const metadata = normalizedMetadata(request.metadata);\n database\n .prepare(\n `INSERT OR IGNORE INTO session_delivery_outbox\n (delivery_id, recipient_key, kind, prompt, delivery_mode, metadata_json, state, created_at)\n VALUES (?, ?, ?, ?, ?, ?, 'queued', ?)`,\n )\n .run(\n deliveryId,\n request.recipientKey,\n request.kind,\n request.prompt,\n mode,\n JSON.stringify(metadata),\n Date.now(),\n );\n const current = database\n .prepare('SELECT * FROM session_delivery_outbox WHERE delivery_id = ?')\n .get(deliveryId) as OutboxRow | undefined;\n if (\n !current ||\n current.recipient_key !== request.recipientKey ||\n current.kind !== request.kind ||\n current.prompt !== request.prompt ||\n current.delivery_mode !== mode ||\n !sameMetadata(JSON.parse(current.metadata_json) as DoomSessionDeliveryMetadata, metadata)\n ) {\n throw new TypeError(`Delivery id '${deliveryId}' is already bound to another envelope.`);\n }\n publishOutbox(deliveryId);\n return { deliveryId };\n },\n async waitForAdmission(deliveryId: string, timeoutMs = 5_000): Promise<DoomSessionDeliveryInboxState | undefined> {\n const deadline = Date.now() + Math.max(0, timeoutMs);\n let state: DoomSessionDeliveryInboxState | undefined;\n do {\n const row = database\n .prepare('SELECT recipient_state FROM session_delivery_outbox WHERE delivery_id = ?')\n .get(deliveryId) as { recipient_state: DoomSessionDeliveryInboxState | null } | undefined;\n state = row?.recipient_state ?? undefined;\n if (state === 'admitted' || state === 'recovery_required') return state;\n if (Date.now() >= deadline) return state;\n await new Promise((resolve) => setTimeout(resolve, Math.min(10, deadline - Date.now())));\n } while (!closed);\n return state;\n },\n receive(senderKey: string, kind: string, payload: unknown) {\n if (kind === DELIVERY_EVENT) return receiveEnvelope(senderKey, payload);\n if (kind === ACK_EVENT) {\n receiveAck(senderKey, payload);\n return 'accepted';\n }\n return undefined;\n },\n inbox(query: DoomSessionInboxQuery = {}): readonly DoomSessionInboxEntry[] {\n const rows = database\n .prepare('SELECT * FROM session_delivery_inbox ORDER BY created_at, delivery_id')\n .all() as unknown as InboxRow[];\n return rows\n .map((row): DoomSessionInboxEntry => {\n const metadata = JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata;\n return {\n deliveryId: row.delivery_id,\n senderKey: row.sender_key,\n recipientKey: row.recipient_key,\n kind: row.kind,\n prompt: row.prompt,\n delivery: row.delivery_mode,\n metadata,\n state: row.state,\n consumed: row.consumed_at !== null,\n };\n })\n .filter(\n (entry) =>\n (query.kind === undefined || entry.kind === query.kind) &&\n (query.state === undefined || entry.state === query.state) &&\n (query.consumed === undefined || entry.consumed === query.consumed) &&\n matchesMetadata(entry.metadata, query.metadata),\n );\n },\n consume(deliveryId: string): boolean {\n const result = database\n .prepare(\n \"UPDATE session_delivery_inbox SET consumed_at = ? WHERE delivery_id = ? AND state IN ('admitted', 'recovery_required') AND consumed_at IS NULL\",\n )\n .run(Date.now(), deliveryId);\n return result.changes === 1;\n },\n outbox(deliveryId: string): DoomSessionOutboxEntry | undefined {\n const row = database\n .prepare(\n 'SELECT delivery_id, recipient_key, kind, metadata_json, state, recipient_state FROM session_delivery_outbox WHERE delivery_id = ?',\n )\n .get(deliveryId) as OutboxRow | undefined;\n if (!row) return undefined;\n return {\n deliveryId: row.delivery_id,\n recipientKey: row.recipient_key,\n kind: row.kind,\n metadata: JSON.parse(row.metadata_json) as DoomSessionDeliveryMetadata,\n state: row.state,\n ...(row.recipient_state === null ? {} : { recipientState: row.recipient_state }),\n };\n },\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n clearInterval(retryTimer);\n releaseEnvelope();\n releaseAck();\n releaseReady();\n try {\n await admissionQueue;\n } finally {\n database.close();\n }\n },\n });\n}\n\n/**\n * Installs a provider-owned endpoint in the current Cordis context.\n *\n * Returns the instance because a provider cannot read its own service back out:\n * `ctx.get` is strict and hides an implementation while its providing fiber is\n * LOADING, which is the whole of that fiber's own callback.\n */\nexport function provideSessionDeliveryService(\n context: Context,\n options: SessionDeliveryServiceOptions,\n): { readonly service: DoomSessionDeliveryService; readonly close: () => Promise<void> } {\n const service = createSessionDeliveryService(options);\n const unprovide = context.provide(DOOM_SESSION_DELIVERY_SERVICE, service);\n // A caller that throws before returning its disposer would otherwise leave the\n // database, its WAL files and its retry timer open for the life of the process.\n // close() is idempotent, so this net never conflicts with the ordered close below.\n context.effect(() => () => service.close(), 'session delivery database');\n return {\n service,\n close: async () => {\n unprovide();\n await service.close();\n },\n };\n}\n\nexport type {\n DoomSessionDeliveryInboxState,\n DoomSessionDeliveryMetadata,\n DoomSessionDeliveryMode,\n DoomSessionDeliveryRequest,\n DoomSessionDeliveryService,\n DoomSessionInboxEntry,\n DoomSessionInboxQuery,\n DoomSessionOutboxEntry,\n SessionDeliveryServiceOptions,\n} from './type';\nexport { DOOM_SESSION_DELIVERY_SERVICE, readDoomSessionDelivery } from './type';\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-session",
3
- "version": "0.0.1-alpha.17",
3
+ "version": "0.0.1-alpha.19",
4
4
  "description": "Shared session coordination services for DoomPi.",
5
5
  "keywords": [
6
6
  "ai",
@@ -62,13 +62,13 @@
62
62
  "access": "public"
63
63
  },
64
64
  "dependencies": {
65
- "@agimon-ai/doompi-core": "0.0.1-alpha.93",
65
+ "@agimon-ai/doompi-core": "0.0.1-alpha.95",
66
66
  "@deepseek-ai/cordis": "4.0.2",
67
67
  "typebox": "1.3.34"
68
68
  },
69
69
  "devDependencies": {
70
- "@agimon-ai/doompi-build": "0.0.1-alpha.16",
71
- "@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.1-alpha.82",
70
+ "@agimon-ai/doompi-build": "0.0.1-alpha.18",
71
+ "@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.1-alpha.84",
72
72
  "@earendil-works/pi-coding-agent": "0.87.1",
73
73
  "@types/node": "26.6.1",
74
74
  "@vitest/coverage-v8": "5.0.1",