statewire 0.13.1 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +29 -78
  2. package/dist/client/connection.d.ts +20 -6
  3. package/dist/client/connection.d.ts.map +1 -1
  4. package/dist/client/connection.js +120 -52
  5. package/dist/client/connection.js.map +1 -1
  6. package/dist/client/core.d.ts +3 -2
  7. package/dist/client/core.d.ts.map +1 -1
  8. package/dist/client/core.js +10 -4
  9. package/dist/client/core.js.map +1 -1
  10. package/dist/client/session.d.ts +2 -0
  11. package/dist/client/session.d.ts.map +1 -1
  12. package/dist/client/session.js +97 -17
  13. package/dist/client/session.js.map +1 -1
  14. package/dist/host/adapter.d.ts +1 -1
  15. package/dist/host/adapter.d.ts.map +1 -1
  16. package/dist/host/adapter.js +7 -1
  17. package/dist/host/adapter.js.map +1 -1
  18. package/dist/host/host.d.ts +1 -0
  19. package/dist/host/host.d.ts.map +1 -1
  20. package/dist/host/host.js +45 -5
  21. package/dist/host/host.js.map +1 -1
  22. package/dist/host/http.d.ts +2 -1
  23. package/dist/host/http.d.ts.map +1 -1
  24. package/dist/host/http.js +108 -47
  25. package/dist/host/http.js.map +1 -1
  26. package/dist/host/socket.d.ts +33 -8
  27. package/dist/host/socket.d.ts.map +1 -1
  28. package/dist/host/socket.js +388 -58
  29. package/dist/host/socket.js.map +1 -1
  30. package/dist/host/work.d.ts +7 -0
  31. package/dist/host/work.d.ts.map +1 -0
  32. package/dist/host/work.js +53 -0
  33. package/dist/host/work.js.map +1 -0
  34. package/dist/host-internal.d.ts +42 -4
  35. package/dist/host-internal.d.ts.map +1 -1
  36. package/dist/host-internal.js +2 -1
  37. package/dist/host.d.ts +16 -3
  38. package/dist/host.d.ts.map +1 -1
  39. package/dist/host.js +2 -1
  40. package/dist/statewire.d.ts +21 -11
  41. package/dist/statewire.d.ts.map +1 -1
  42. package/dist/statewire.js +2 -2
  43. package/dist/statewire.js.map +1 -1
  44. package/dist/transports/sse.d.ts +1 -4
  45. package/dist/transports/sse.d.ts.map +1 -1
  46. package/dist/transports/sse.js +47 -56
  47. package/dist/transports/sse.js.map +1 -1
  48. package/dist/transports/testing.js +2 -2
  49. package/dist/transports/testing.js.map +1 -1
  50. package/dist/transports/ws.d.ts +1 -1
  51. package/dist/transports/ws.d.ts.map +1 -1
  52. package/dist/transports/ws.js +54 -41
  53. package/dist/transports/ws.js.map +1 -1
  54. package/dist/types.d.ts +3 -0
  55. package/dist/types.d.ts.map +1 -1
  56. package/dist/types.js.map +1 -1
  57. package/dist/wire/documents.d.ts +20 -0
  58. package/dist/wire/documents.d.ts.map +1 -0
  59. package/dist/wire/documents.js +74 -0
  60. package/dist/wire/documents.js.map +1 -0
  61. package/dist/wire/limits.d.ts +10 -0
  62. package/dist/wire/limits.d.ts.map +1 -0
  63. package/dist/wire/limits.js +11 -0
  64. package/dist/wire/limits.js.map +1 -0
  65. package/dist/wire/meta.d.ts.map +1 -1
  66. package/dist/wire/meta.js +1 -1
  67. package/dist/wire/meta.js.map +1 -1
  68. package/dist/wire/ops.d.ts.map +1 -1
  69. package/dist/wire/ops.js +1 -2
  70. package/dist/wire/ops.js.map +1 -1
  71. package/dist/wire/version.d.ts +7 -0
  72. package/dist/wire/version.d.ts.map +1 -0
  73. package/dist/wire/version.js +8 -0
  74. package/dist/wire/version.js.map +1 -0
  75. package/package.json +1 -1
  76. package/src/client/connection.ts +213 -67
  77. package/src/client/core.ts +10 -3
  78. package/src/client/session.ts +106 -30
  79. package/src/host/adapter.ts +10 -2
  80. package/src/host/host.ts +54 -4
  81. package/src/host/http.ts +168 -64
  82. package/src/host/socket.ts +603 -60
  83. package/src/host/work.ts +50 -0
  84. package/src/host-internal.ts +44 -3
  85. package/src/host.ts +18 -2
  86. package/src/statewire.ts +33 -10
  87. package/src/transports/sse.ts +60 -68
  88. package/src/transports/testing.ts +2 -2
  89. package/src/transports/ws.ts +29 -48
  90. package/src/types.ts +1 -0
  91. package/src/wire/documents.ts +109 -0
  92. package/src/wire/limits.ts +6 -0
  93. package/src/wire/meta.ts +6 -1
  94. package/src/wire/ops.ts +1 -2
  95. package/src/wire/version.ts +3 -0
@@ -1 +1 @@
1
- {"version":3,"file":"socket.js","names":["useEffect","useState","createTapRoot","flushTapSync","useResource","ResourceElement","getCommandsHost","getStateHost","CommandsHost","CommandsOutcome","StatewireSendError","Statewire","StatewireHost","StatewireHostInternal","encodeValue","reviveValue","createMacrotaskPoster","StatewireMetaEntry","StatewirePath","StatewireCmd","StatewireEnvelope","frames","serveFrames","stream","serveStream","CLIENT_ID_RE","RESULT_TTL_MS","RESULT_LIMIT","CLIENT_RECORD_LIMIT","WireOp","op","path","value","meta","Admission","seq","method","applied","appliedSent","settled","ClientRec","id","lastSeq","ctxSeq","touched","context","Record","results","Map","ts","cmd","inflight","Conn","clientId","socket","Socket","open","sawFrame","lastSentAt","lease","violation","reason","Object","assign","Error","name","violationReason","error","message","CtxStatement","CmdStatement","params","ParsedFrame","headers","ctx","isPlainObject","Array","isArray","parseLane","length","statements","prev","statement","Number","isInteger","push","contextValue","ops","undefined","rejectUnknown","parseFrameValue","frame","first","keys","unknown","filter","key","sort","raw","values","some","parseFrame","JSON","parse","encodePayload","payload","cmdOf","adm","outcome","type","failure","fate","code","String","SocketHostState","heartbeatMs","clientRecordLimit","finOnIdle","authorize","SocketHostOptions","clients","conns","Set","pendingOps","pendingApplied","pendingCmds","idleWire","finished","Fin","disposed","flushScheduled","heartbeatTimer","ReturnType","setInterval","stateHost","StateHost","commandsHost","current","post","connect","SocketConnection","finish","fin","request","Request","Promise","Response","scheduleFlush","h","recordOp","attach","next","nextState","state","nextCommands","commands","submit","setOnOp","closeConn","conn","delete","close","size","clearInterval","sendTo","data","Date","now","send","ensureHeartbeat","unref","setHeartbeatMs","ms","idleLevel","rec","flush","takeChanged","queueApplied","level","edge","cmds","appliedEntries","get","map","packet","idle","stringify","verdicts","list","set","queueCmd","retain","newest","Math","max","entry","min","admittedThrough","reemit","cached","settleCmd","settleWire","callerOf","Caller","isConnected","rejectStatement","admitCmd","names","methods","caller","onApplied","onSettle","catch","FrameAdmission","syn","admitFrame","through","ctxNew","s","cmdNew","at","dur","admission","gcClients","excess","live","oldest","a","b","has","Registration","connection","register","refuse","test","known","created","add","snapshot","hello","registration","resume","suspend","useSocketHost","transport","options","Pick","SocketHost","host","heartbeatIntervalMs","StatewireSocketHost","SocketHostRoot","root","getValue","dispose","unmount"],"sources":["../../src/host/socket.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { createTapRoot, flushTapSync, useResource } from \"@assistant-ui/tap\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\nimport { getCommandsHost, getStateHost } from \"./host\";\nimport type { CommandsHost, CommandsOutcome } from \"./host\";\nimport { StatewireSendError } from \"../types\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireHost } from \"../host\";\nimport type { StatewireHostInternal } from \"../host-internal\";\nimport { encodeValue, reviveValue } from \"../wire/meta\";\nimport { createMacrotaskPoster } from \"../util/macrotask\";\nimport type { StatewireMetaEntry } from \"../wire/meta\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport type { StatewireCmd, StatewireEnvelope } from \"../client/connection\";\nimport { frames as serveFrames, stream as serveStream } from \"./http\";\n\nexport const CLIENT_ID_RE = /^[A-Za-z0-9._~-]{1,256}$/;\nconst RESULT_TTL_MS = 30_000;\nconst RESULT_LIMIT = 256;\nconst CLIENT_RECORD_LIMIT = 1024;\n\ntype WireOp = {\n op: string;\n path?: StatewirePath;\n value?: unknown;\n meta?: StatewireMetaEntry[];\n};\n\ntype Admission = {\n seq: number;\n method: string;\n applied: boolean;\n appliedSent: boolean;\n settled: boolean;\n};\n\nexport type ClientRec = {\n id: string;\n lastSeq: number;\n ctxSeq: number;\n touched: number;\n context: Record<string, unknown> | null;\n results: Map<number, { ts: number; cmd: StatewireCmd }>;\n inflight: Map<number, Admission>;\n};\n\nexport type Conn = {\n clientId: string;\n socket: StatewireHostInternal.Socket;\n open: boolean;\n sawFrame: boolean;\n lastSentAt: number;\n lease: string | null;\n};\n\n// ─── frame parsing ──────────────────────────────────────\n\nconst violation = (reason: string): never => {\n throw Object.assign(new Error(reason), { name: \"StatewireViolation\" });\n};\n\nconst violationReason = (error: unknown): string | null =>\n error instanceof Error && error.name === \"StatewireViolation\"\n ? error.message\n : null;\n\ntype CtxStatement = { seq: number; value: Record<string, unknown> };\ntype CmdStatement = {\n seq: number;\n method: string;\n params: unknown;\n meta?: unknown;\n};\n\nexport type ParsedFrame = {\n headers: Record<string, string> | null;\n ctx: CtxStatement[];\n cmd: CmdStatement[];\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst parseLane = (value: unknown): Record<string, unknown>[] => {\n if (!Array.isArray(value)) return violation(\"malformed frame\");\n if (value.length === 0) return violation(\"empty lane\");\n const statements: Record<string, unknown>[] = [];\n let prev: number | null = null;\n for (const statement of value) {\n if (!isPlainObject(statement)) return violation(\"malformed statement\");\n const seq = statement[\"seq\"];\n if (typeof seq !== \"number\" || !Number.isInteger(seq) || seq < 1) {\n return violation(\"malformed statement\");\n }\n if (prev !== null && seq !== prev + 1) return violation(\"malformed frame\");\n prev = seq;\n statements.push(statement);\n }\n return statements;\n};\n\n/** v1 ctx statements state the context whole: one root replace with an object value. */\nconst contextValue = (ops: unknown): Record<string, unknown> => {\n if (!Array.isArray(ops) || ops.length !== 1) {\n throw new Error(\"context must be a single-op array\");\n }\n const op = ops[0] as Record<string, unknown> | null;\n if (\n !isPlainObject(op) ||\n op[\"op\"] !== \"replace\" ||\n !Array.isArray(op[\"path\"]) ||\n op[\"path\"].length !== 0\n ) {\n throw new Error(\"context op must be a root replace\");\n }\n const value =\n op[\"meta\"] !== undefined\n ? reviveValue(op[\"value\"], op[\"meta\"], { rejectUnknown: true })\n : op[\"value\"];\n if (!isPlainObject(value)) {\n throw new Error(\"context value must be an object\");\n }\n return value;\n};\n\nexport const parseFrameValue = (\n frame: unknown,\n first: boolean,\n): ParsedFrame => {\n if (!isPlainObject(frame)) return violation(\"malformed frame\");\n const keys = Object.keys(frame);\n if (keys.length === 0) return violation(\"malformed frame\");\n const unknown = keys\n .filter((key) => key !== \"headers\" && key !== \"ctx\" && key !== \"cmd\")\n .sort();\n if (unknown.length > 0)\n return violation(`unknown frame key: '${unknown[0]}'`);\n let headers: Record<string, string> | null = null;\n if (frame[\"headers\"] !== undefined) {\n if (!first) return violation(\"mid-session headers\");\n const raw = frame[\"headers\"];\n if (\n !isPlainObject(raw) ||\n Object.values(raw).some((value) => typeof value !== \"string\")\n ) {\n return violation(\"malformed headers\");\n }\n headers = raw as Record<string, string>;\n }\n const ctx: CtxStatement[] = [];\n if (frame[\"ctx\"] !== undefined) {\n for (const statement of parseLane(frame[\"ctx\"])) {\n try {\n ctx.push({\n seq: statement[\"seq\"] as number,\n value: contextValue(statement[\"ops\"]),\n });\n } catch {\n return violation(\"invalid-context\");\n }\n }\n }\n const cmd: CmdStatement[] = [];\n if (frame[\"cmd\"] !== undefined) {\n for (const statement of parseLane(frame[\"cmd\"])) {\n const method = statement[\"method\"];\n if (typeof method !== \"string\" || !(\"params\" in statement)) {\n return violation(\"malformed statement\");\n }\n cmd.push({\n seq: statement[\"seq\"] as number,\n method,\n params: statement[\"params\"],\n ...(statement[\"meta\"] !== undefined && { meta: statement[\"meta\"] }),\n });\n }\n }\n return { headers, ctx, cmd };\n};\n\nexport const parseFrame = (raw: string, first: boolean): ParsedFrame => {\n let frame: unknown;\n try {\n frame = JSON.parse(raw);\n } catch {\n return violation(\"malformed frame\");\n }\n return parseFrameValue(frame, first);\n};\n\n// ─── verdict encoding ───────────────────────────────────\n\nconst encodePayload = (\n payload: unknown,\n): { payload?: unknown; meta?: StatewireMetaEntry[] } => {\n if (payload === undefined) return {};\n const { value, meta } = encodeValue(payload);\n return { payload: value, ...(meta !== undefined && { meta }) };\n};\n\nconst cmdOf = (adm: Admission, outcome: CommandsOutcome): StatewireCmd => {\n if (outcome.type === \"accepted\") {\n return { seq: adm.seq, type: \"result\", ...encodePayload(outcome.payload) };\n }\n const failure =\n outcome.error instanceof StatewireSendError ? outcome.error.failure : null;\n switch (failure?.fate) {\n case \"failed\":\n return {\n seq: adm.seq,\n type: \"failed\",\n ...(failure.message !== undefined && { message: failure.message }),\n };\n case \"rejected\": {\n if (failure.code !== undefined) {\n const message =\n failure.code === \"unknown-command\"\n ? `unknown method: '${adm.method}'`\n : failure.message;\n return {\n seq: adm.seq,\n type: \"rejected\",\n code: failure.code,\n ...(message !== undefined && { message }),\n };\n }\n return {\n seq: adm.seq,\n type: \"rejected\",\n ...(failure.message !== undefined && { message: failure.message }),\n ...encodePayload(failure.payload),\n };\n }\n default:\n return {\n seq: adm.seq,\n type: \"failed\",\n message:\n outcome.error instanceof Error\n ? outcome.error.message\n : String(outcome.error),\n };\n }\n};\n\n// ─── host ───────────────────────────────────────────────\n\nexport type SocketHostState = {\n heartbeatMs: number;\n clientRecordLimit: number;\n finOnIdle: boolean;\n authorize: StatewireHostInternal.SocketHostOptions[\"authorize\"];\n clients: Map<string, ClientRec>;\n conns: Set<Conn>;\n pendingOps: WireOp[];\n pendingApplied: Map<string, number[]>;\n pendingCmds: Map<string, StatewireCmd[]>;\n idleWire: boolean;\n finished: StatewireHost.Fin | null;\n disposed: boolean;\n flushScheduled: boolean;\n heartbeatTimer: ReturnType<typeof setInterval> | null;\n stateHost: StatewireHost.StateHost | null;\n commandsHost: CommandsHost | null;\n current: Statewire<unknown> | null;\n post: () => void;\n connect: (\n clientId: string,\n socket: StatewireHostInternal.Socket,\n ) => StatewireHostInternal.SocketConnection | null;\n finish: (fin: StatewireHost.Fin) => void;\n stream: (request: Request) => Promise<Response>;\n frames: (request: Request) => Promise<Response>;\n};\n\nconst scheduleFlush = (h: SocketHostState) => {\n if (h.flushScheduled || h.disposed) return;\n h.flushScheduled = true;\n h.post();\n};\n\nconst recordOp = (\n h: SocketHostState,\n op: {\n op: string;\n path?: StatewirePath;\n value?: unknown;\n },\n) => {\n if (op.op === \"replace\" || op.op === \"add\") {\n const { value, meta } = encodeValue(op.value);\n h.pendingOps.push({ ...op, value, ...(meta !== undefined && { meta }) });\n } else {\n h.pendingOps.push(op);\n }\n scheduleFlush(h);\n};\n\nconst attach = (h: SocketHostState, next: Statewire<unknown>) => {\n if (next === h.current) return;\n h.current = next;\n const nextState =\n typeof next.state === \"object\" && next.state !== null\n ? getStateHost(next.state)\n : undefined;\n const nextCommands = getCommandsHost(next.commands);\n if (!nextState || !nextCommands?.submit) {\n throw new Error(\n \"StatewireSocketHost requires a statewire/host transport (useStatewireState with object state, useStatewireCommands)\",\n );\n }\n if (nextState !== h.stateHost) {\n h.stateHost?.setOnOp(null);\n h.stateHost = nextState;\n h.stateHost.setOnOp((op) => recordOp(h, op));\n }\n h.commandsHost = nextCommands;\n};\n\nexport const closeConn = (\n h: SocketHostState,\n conn: Conn,\n code?: number,\n reason?: string,\n) => {\n if (!conn.open) return;\n conn.open = false;\n h.conns.delete(conn);\n try {\n conn.socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n if (h.conns.size === 0 && h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n }\n};\n\nexport const sendTo = (h: SocketHostState, conn: Conn, data: string) => {\n if (!conn.open) return;\n conn.lastSentAt = Date.now();\n try {\n conn.socket.send(data);\n } catch {\n closeConn(h, conn);\n }\n};\n\nconst ensureHeartbeat = (h: SocketHostState) => {\n if (h.heartbeatTimer !== null || h.heartbeatMs <= 0) return;\n h.heartbeatTimer = setInterval(() => {\n const now = Date.now();\n for (const conn of [...h.conns]) {\n if (now - conn.lastSentAt >= h.heartbeatMs) sendTo(h, conn, \"{}\");\n }\n }, h.heartbeatMs);\n (h.heartbeatTimer as unknown as { unref?: () => void }).unref?.();\n};\n\nconst setHeartbeatMs = (h: SocketHostState, ms: number) => {\n if (ms === h.heartbeatMs) return;\n h.heartbeatMs = ms;\n if (h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n ensureHeartbeat(h);\n }\n};\n\nconst idleLevel = (h: SocketHostState): boolean => {\n for (const rec of h.clients.values()) {\n if (rec.inflight.size > 0) return false;\n }\n return true;\n};\n\nexport const flush = (h: SocketHostState, fin?: StatewireHost.Fin) => {\n flushTapSync(() => {});\n h.stateHost?.takeChanged();\n for (const rec of h.clients.values()) {\n for (const adm of rec.inflight.values()) {\n if (adm.applied && !adm.settled && !adm.appliedSent) {\n adm.appliedSent = true;\n queueApplied(h, rec.id, adm.seq);\n }\n }\n }\n const level = idleLevel(h);\n const edge = level !== h.idleWire;\n if (\n h.pendingOps.length === 0 &&\n h.pendingApplied.size === 0 &&\n h.pendingCmds.size === 0 &&\n fin === undefined &&\n !edge\n ) {\n return;\n }\n h.idleWire = level;\n if (fin === undefined && edge && level && h.finOnIdle) {\n fin = { reason: \"idle\" };\n }\n const ops = h.pendingOps;\n const applied = h.pendingApplied;\n const cmds = h.pendingCmds;\n h.pendingOps = [];\n h.pendingApplied = new Map();\n h.pendingCmds = new Map();\n // Applied entries anchor to their effects: piggybacked on the ops packet\n // when one is flushing, standalone otherwise. Terminal verdicts ride their\n // own packet.\n for (const conn of [...h.conns]) {\n const appliedEntries: StatewireCmd[] = (\n applied.get(conn.clientId) ?? []\n ).map((seq) => ({ seq, type: \"applied\" }));\n if (ops.length > 0) {\n const packet: StatewireEnvelope = {\n ops,\n ...(appliedEntries.length > 0 && { cmd: appliedEntries }),\n ...(edge && { idle: level }),\n };\n sendTo(h, conn, JSON.stringify(packet));\n } else if (appliedEntries.length > 0) {\n sendTo(h, conn, JSON.stringify({ cmd: appliedEntries }));\n }\n const verdicts = cmds.get(conn.clientId) ?? [];\n if (verdicts.length > 0) {\n sendTo(h, conn, JSON.stringify({ cmd: verdicts }));\n }\n if (edge && ops.length === 0) {\n sendTo(h, conn, JSON.stringify({ idle: level }));\n }\n if (fin !== undefined) {\n sendTo(h, conn, JSON.stringify({ fin }));\n closeConn(h, conn);\n }\n }\n};\n\nconst queueApplied = (h: SocketHostState, clientId: string, seq: number) => {\n const list = h.pendingApplied.get(clientId);\n if (list) list.push(seq);\n else h.pendingApplied.set(clientId, [seq]);\n scheduleFlush(h);\n};\n\nconst queueCmd = (h: SocketHostState, clientId: string, cmd: StatewireCmd) => {\n const list = h.pendingCmds.get(clientId);\n if (list) list.push(cmd);\n else h.pendingCmds.set(clientId, [cmd]);\n scheduleFlush(h);\n};\n\nconst retain = (rec: ClientRec, cmd: StatewireCmd) => {\n const now = Date.now();\n rec.results.set(cmd.seq, { ts: now, cmd });\n const newest = Math.max(...rec.results.keys());\n for (const [seq, entry] of rec.results) {\n if (seq !== newest && now - entry.ts > RESULT_TTL_MS) {\n rec.results.delete(seq);\n }\n }\n while (rec.results.size > RESULT_LIMIT) {\n rec.results.delete(Math.min(...rec.results.keys()));\n }\n};\n\n/** Cmd-lane watermark: the last statement admitted, settled or not. */\nconst admittedThrough = (rec: ClientRec): number =>\n Math.max(rec.lastSeq, ...rec.inflight.keys());\n\n// A re-asked seq never re-runs: the stored verdict re-emits, an applied\n// inflight run re-answers applied; one not yet applied answers nothing (its\n// answers ride the stream when ready), an evicted verdict answers expired.\nconst reemit = (h: SocketHostState, rec: ClientRec, seq: number) => {\n const cached = rec.results.get(seq);\n if (cached) {\n const newest = Math.max(...rec.results.keys());\n if (seq === newest || Date.now() - cached.ts <= RESULT_TTL_MS) {\n queueCmd(h, rec.id, cached.cmd);\n return;\n }\n rec.results.delete(seq);\n }\n const adm = rec.inflight.get(seq);\n if (adm) {\n if (adm.applied) queueApplied(h, rec.id, seq);\n return;\n }\n queueCmd(h, rec.id, { seq, type: \"expired\" });\n};\n\nconst settleCmd = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n cmd: StatewireCmd,\n) => {\n if (adm.settled) return;\n adm.settled = true;\n rec.inflight.delete(adm.seq);\n retain(rec, cmd);\n rec.lastSeq = Math.max(rec.lastSeq, adm.seq);\n adm.applied = true;\n queueCmd(h, rec.id, cmd);\n};\n\nconst settleWire = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n outcome: CommandsOutcome,\n) => settleCmd(h, rec, adm, cmdOf(adm, outcome));\n\nconst callerOf = (\n h: SocketHostState,\n rec: ClientRec,\n): StatewireHost.Caller => ({\n clientId: rec.id,\n get context() {\n return rec.context;\n },\n get isConnected() {\n if (h.clients.get(rec.id) !== rec) return false;\n for (const conn of h.conns) {\n if (conn.clientId === rec.id && conn.open) return true;\n }\n return false;\n },\n});\n\nconst rejectStatement = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n message: string,\n) =>\n settleCmd(h, rec, adm, {\n seq: adm.seq,\n type: \"rejected\",\n code: \"invalid-params\",\n message,\n });\n\nconst admitCmd = (\n h: SocketHostState,\n rec: ClientRec,\n statement: CmdStatement,\n) => {\n const adm: Admission = {\n seq: statement.seq,\n method: statement.method,\n applied: false,\n appliedSent: false,\n settled: false,\n };\n rec.inflight.set(statement.seq, adm);\n if (!Array.isArray(statement.params)) {\n rejectStatement(h, rec, adm, \"params must be an array\");\n return;\n }\n let params = statement.params;\n if (statement.meta !== undefined) {\n try {\n params = reviveValue(params, statement.meta, {\n rejectUnknown: true,\n }) as unknown[];\n } catch (error) {\n rejectStatement(\n h,\n rec,\n adm,\n `invalid params: ${(error as Error).message}`,\n );\n return;\n }\n }\n if (statement.method === \"statewire/commands\") {\n if (params.length > 0) {\n rejectStatement(h, rec, adm, \"statewire/commands takes no params\");\n return;\n }\n const names = [\n ...(h.commandsHost?.methods?.() ?? []),\n \"statewire/commands\",\n ].sort();\n settleCmd(h, rec, adm, { seq: adm.seq, type: \"result\", payload: names });\n return;\n }\n h.commandsHost!.submit!({\n method: statement.method,\n params,\n clientId: rec.id,\n caller: callerOf(h, rec),\n onApplied: () => {\n if (adm.settled || adm.applied) return;\n adm.applied = true;\n rec.lastSeq = Math.max(rec.lastSeq, adm.seq);\n scheduleFlush(h);\n },\n onSettle: (outcome) => settleWire(h, rec, adm, outcome),\n }).catch((error: unknown) => {\n if (!adm.settled) settleWire(h, rec, adm, { type: \"rejected\", error });\n });\n};\n\n// One admission law, both lanes: absorbed statements answer from the record,\n// then the new suffix is admitted whole or the frame is refused whole via a\n// {syn} stating both watermarks, nothing consumed. A gap is never a close.\nexport type FrameAdmission =\n | { type: \"ok\" }\n | { type: \"refused\"; syn: { syn: { seq: number; ctxSeq: number } } };\n\nexport const admitFrame = (\n h: SocketHostState,\n rec: ClientRec,\n frame: ParsedFrame,\n): FrameAdmission => {\n rec.touched = Date.now();\n const through = admittedThrough(rec);\n for (const statement of frame.cmd) {\n if (statement.seq <= through) reemit(h, rec, statement.seq);\n }\n const ctxNew = frame.ctx.filter((s) => s.seq > rec.ctxSeq);\n const cmdNew = frame.cmd.filter((s) => s.seq > through);\n if (\n (ctxNew.length > 0 && ctxNew[0]!.seq !== rec.ctxSeq + 1) ||\n (cmdNew.length > 0 && cmdNew[0]!.seq !== through + 1)\n ) {\n return {\n type: \"refused\",\n syn: { syn: { seq: through, ctxSeq: rec.ctxSeq } },\n };\n }\n for (const statement of ctxNew) {\n rec.context = statement.value;\n rec.ctxSeq = statement.seq;\n }\n for (const statement of cmdNew) admitCmd(h, rec, statement);\n if (cmdNew.length > 0) {\n // Memory host: admitted means retained — dur rides the admitting flush.\n queueCmd(h, rec.id, { seq: cmdNew.at(-1)!.seq, dur: true });\n }\n scheduleFlush(h);\n return { type: \"ok\" };\n};\n\nconst message = (h: SocketHostState, conn: Conn, data: string) => {\n if (!conn.open || h.disposed || h.finished !== null) return;\n const first = !conn.sawFrame;\n conn.sawFrame = true;\n let frame: ParsedFrame;\n try {\n frame = parseFrame(data, first);\n } catch (error) {\n const reason = violationReason(error);\n if (reason === null) throw error;\n closeConn(h, conn, 1008, reason);\n return;\n }\n if (frame.ctx.length === 0 && frame.cmd.length === 0) return;\n const rec = h.clients.get(conn.clientId)!;\n const admission = admitFrame(h, rec, frame);\n if (admission.type === \"refused\") {\n sendTo(h, conn, JSON.stringify(admission.syn));\n }\n};\n\nconst gcClients = (h: SocketHostState) => {\n let excess = h.clients.size - h.clientRecordLimit;\n if (excess <= 0) return;\n const live = new Set([...h.conns].map((conn) => conn.clientId));\n const oldest = [...h.clients.values()].sort((a, b) => a.touched - b.touched);\n for (const rec of oldest) {\n if (excess <= 0) return;\n if (live.has(rec.id) || rec.inflight.size > 0) continue;\n h.clients.delete(rec.id);\n excess -= 1;\n }\n};\n\nexport type Registration = {\n rec: ClientRec;\n conn: Conn;\n connection: StatewireHostInternal.SocketConnection;\n};\n\nexport const register = (\n h: SocketHostState,\n clientId: string,\n socket: StatewireHostInternal.Socket,\n): Registration | null => {\n const refuse = (code: number, reason: string) => {\n try {\n socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n return null;\n };\n if (h.disposed) return refuse(1001, \"disposed\");\n if (!CLIENT_ID_RE.test(clientId)) return refuse(1008, \"invalid client id\");\n flush(h);\n if (h.finished !== null) {\n try {\n socket.send(JSON.stringify({ fin: h.finished }));\n } catch {\n /* peer already gone */\n }\n refuse(1000, \"finished\");\n return null;\n }\n const known = h.clients.has(clientId);\n const rec = known\n ? h.clients.get(clientId)!\n : (() => {\n const created: ClientRec = {\n id: clientId,\n lastSeq: 0,\n ctxSeq: 0,\n touched: Date.now(),\n context: null,\n results: new Map(),\n inflight: new Map(),\n };\n h.clients.set(clientId, created);\n return created;\n })();\n rec.touched = Date.now();\n const conn: Conn = {\n clientId,\n socket,\n open: true,\n sawFrame: false,\n lastSentAt: 0,\n lease: null,\n };\n h.conns.add(conn);\n gcClients(h);\n ensureHeartbeat(h);\n const { value, meta } = encodeValue(h.stateHost!.snapshot());\n const hello: StatewireEnvelope = {\n ops: [\n {\n op: \"replace\",\n path: [],\n value,\n ...(meta !== undefined && { meta }),\n },\n ],\n syn: {\n seq: admittedThrough(rec),\n ctxSeq: rec.ctxSeq,\n ...(h.idleWire && { idle: true }),\n },\n };\n sendTo(h, conn, JSON.stringify(hello));\n const connection: StatewireHostInternal.SocketConnection = {\n clientId,\n message: (data) => message(h, conn, data),\n close: () => closeConn(h, conn),\n };\n return { rec, conn, connection };\n};\n\nconst connect = (\n h: SocketHostState,\n clientId: string,\n socket: StatewireHostInternal.Socket,\n): StatewireHostInternal.SocketConnection | null => {\n const registration = register(h, clientId, socket);\n return registration?.connection ?? null;\n};\n\nconst finish = (h: SocketHostState, fin: StatewireHost.Fin) => {\n if (h.finished !== null || h.disposed) return;\n h.finished = fin;\n flush(h, fin);\n};\n\nconst resume = (h: SocketHostState) => {\n h.disposed = false;\n h.stateHost?.setOnOp((op) => recordOp(h, op));\n};\n\nconst suspend = (h: SocketHostState) => {\n h.disposed = true;\n if (h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n }\n h.stateHost?.setOnOp(null);\n};\n\nconst useSocketHost = (\n transport: ResourceElement<Statewire>,\n options?: StatewireHostInternal.SocketHostOptions,\n): Pick<\n StatewireHostInternal.SocketHost,\n \"connect\" | \"finish\" | \"stream\" | \"frames\"\n> => {\n const [h] = useState((): SocketHostState => {\n const host: SocketHostState = {\n heartbeatMs: 15_000,\n clientRecordLimit: CLIENT_RECORD_LIMIT,\n finOnIdle: false,\n authorize: undefined,\n clients: new Map(),\n conns: new Set(),\n pendingOps: [],\n pendingApplied: new Map(),\n pendingCmds: new Map(),\n idleWire: true,\n finished: null,\n disposed: false,\n flushScheduled: false,\n heartbeatTimer: null,\n stateHost: null,\n commandsHost: null,\n current: null,\n post: createMacrotaskPoster(() => {\n host.flushScheduled = false;\n flush(host);\n }),\n connect: (clientId, socket) => connect(host, clientId, socket),\n finish: (fin) => finish(host, fin),\n stream: (request) => serveStream(host, request),\n frames: (request) => serveFrames(host, request),\n };\n return host;\n });\n setHeartbeatMs(h, options?.heartbeatIntervalMs ?? 15_000);\n h.clientRecordLimit = options?.clientRecordLimit ?? CLIENT_RECORD_LIMIT;\n h.finOnIdle = options?.finOnIdle ?? false;\n h.authorize = options?.authorize;\n const value = useResource(transport) as Statewire<unknown>;\n attach(h, value);\n useEffect(() => {\n attach(h, value);\n });\n useEffect(() => {\n resume(h);\n return () => suspend(h);\n }, [h]);\n return h;\n};\n\n/**\n * Transport-agnostic WS binding over a statewire/host transport:\n * feed it sockets (anything with `send`/`close`) and raw text frames, and it\n * speaks the Statewire packet protocol — snapshot-first hello with `syn`,\n * statement-lane client frames under one admission law, `{cmd}` answer\n * arrays fanned out to every attach of a client id, idle edges, and `fin` on\n * finish.\n */\nexport const StatewireSocketHost = (\n transport: ResourceElement<Statewire>,\n options?: StatewireHostInternal.SocketHostOptions,\n): StatewireHostInternal.SocketHost => {\n const SocketHostRoot = () => useSocketHost(transport, options);\n const root = createTapRoot(SocketHostRoot);\n let disposed = false;\n return {\n connect: (clientId, socket) =>\n flushTapSync(() => root.getValue().connect(clientId, socket)),\n stream: (request) => flushTapSync(() => root.getValue().stream(request)),\n frames: (request) => flushTapSync(() => root.getValue().frames(request)),\n finish: (fin) => flushTapSync(() => root.getValue().finish(fin)),\n dispose: () => {\n if (disposed) return;\n disposed = true;\n flushTapSync(() => root.getValue().finish({ reason: \"evicted\" }));\n root.unmount();\n },\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"socket.js","names":["useEffect","useState","createTapRoot","flushTapSync","useResource","ResourceElement","getCommandsHost","getStateHost","CommandsHost","CommandsOutcome","StatewireSendError","Statewire","StatewireHost","StatewireHostInternal","encodeValue","reviveValue","COMMAND_CAPACITY_RETRY_MS","MAX_COMMANDS_PER_FRAME","MAX_CONTEXT_VALUE_BYTES","MAX_FRAME_BODY_BYTES","MAX_INFLIGHT_COMMANDS_PER_CLIENT","MAX_INFLIGHT_COMMANDS_PER_HOST","createMacrotaskPoster","StatewireMetaEntry","StatewirePath","StatewireCmd","StatewireEnvelope","frames","serveFrames","stream","serveStream","CLIENT_ID_RE","PRINCIPAL_MISMATCH_MESSAGE","authEquals","a","b","Object","is","Date","getTime","Array","isArray","length","every","v","i","getPrototypeOf","prototype","keysA","keys","keysB","key","Record","RESULT_TTL_MS","RESULT_LIMIT","CLIENT_RECORD_LIMIT","MAX_SUBSCRIBERS","SUBSCRIBER_LIMIT_MESSAGE","STREAM_QUEUE_SIZE","WireOp","op","path","value","meta","Admission","seq","method","applied","appliedSent","settled","ClientRec","id","lastSeq","ctxSeq","touched","context","results","Map","ts","cmd","inflight","principal","Conn","clientId","socket","Socket","open","sawFrame","lastSentAt","lease","auth","PendingConn","authorizing","queued","timer","ReturnType","setTimeout","connection","SocketConnection","violation","reason","assign","Error","name","violationReason","error","message","CtxStatement","CmdStatement","params","ParsedFrame","ctx","isPlainObject","parseLane","statements","prev","statement","Number","isInteger","push","frameEncoder","TextEncoder","contextValue","ops","undefined","rejectUnknown","parseFrameValue","frame","unknown","filter","sort","lane","encode","JSON","stringify","byteLength","parseFrame","raw","parse","frameIsOversized","encodePayload","payload","cmdOf","adm","outcome","type","failure","fate","code","String","parseInitialFrame","headers","lanes","Response","status","values","some","SocketHostState","heartbeatMs","wsInitTimeoutMs","maxSubscribers","maxInflightCommands","streamQueueSize","clientRecordLimit","finOnIdle","pushback","authorize","SocketHostOptions","clients","conns","Set","pendingConns","pendingOps","pendingApplied","pendingCmds","idleWire","finished","Fin","disposed","flushScheduled","heartbeatTimer","setInterval","stateHost","StateHost","commandsHost","current","persistence","SocketHostPersistence","post","connect","options","SocketConnectOptions","finish","fin","request","Request","Promise","scheduleFlush","h","recordOp","attach","next","nextState","state","nextCommands","commands","submit","setOnOp","closeConn","conn","delete","close","size","clearInterval","sendTo","data","now","send","atSubscriberLimit","ensureHeartbeat","unref","setHeartbeatMs","ms","idleLevel","work","isIdle","rec","flush","takeChanged","queueApplied","level","edge","cmds","appliedEntries","get","map","packet","idle","verdicts","list","set","queueCmd","notifyClientRecords","onClientRecordsChange","admittedThrough","entry","retain","newest","Math","max","min","reemit","cached","settleCmd","settleWire","callerOf","Caller","isConnected","rejectStatement","admitCmd","names","methods","caller","onApplied","onSettle","catch","FrameAdmission","syn","retry","admitFrame","through","ctxNew","s","cmdNew","hostCommandLoad","client","isSafeInteger","TypeError","at","dur","first","admission","closePending","pending","clearTimeout","sendPending","refuseSubscriberLimit","rejectPendingAuthorization","response","unauthorized","statusText","normalizedHeaders","seen","toLowerCase","has","add","fromEntries","Headers","connectAuthorized","authorized","registration","register","refuse","test","initial","resolve","then","onAuthorized","splice","gcClients","excess","changed","live","oldest","Registration","known","created","snapshot","hello","abort","resume","suspend","restoreClientRecords","records","ClientRecord","record","useSocketHost","transport","Pick","SocketHost","host","clientRecords","connectOptions","heartbeatIntervalMs","StatewireSocketHost","SocketHostRoot","root","getValue","dispose","unmount"],"sources":["../../src/host/socket.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { createTapRoot, flushTapSync, useResource } from \"@assistant-ui/tap\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\nimport { getCommandsHost, getStateHost } from \"./host\";\nimport type { CommandsHost, CommandsOutcome } from \"./host\";\nimport { StatewireSendError } from \"../types\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireHost } from \"../host\";\nimport type { StatewireHostInternal } from \"../host-internal\";\nimport { encodeValue, reviveValue } from \"../wire/meta\";\nimport {\n COMMAND_CAPACITY_RETRY_MS,\n MAX_COMMANDS_PER_FRAME,\n MAX_CONTEXT_VALUE_BYTES,\n MAX_FRAME_BODY_BYTES,\n MAX_INFLIGHT_COMMANDS_PER_CLIENT,\n MAX_INFLIGHT_COMMANDS_PER_HOST,\n} from \"../wire/limits\";\nimport { createMacrotaskPoster } from \"../util/macrotask\";\nimport type { StatewireMetaEntry } from \"../wire/meta\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport type { StatewireCmd, StatewireEnvelope } from \"../client/connection\";\nimport { frames as serveFrames, stream as serveStream } from \"./http\";\n\nexport const CLIENT_ID_RE = /^[A-Za-z0-9._~-]{1,256}$/;\nexport const PRINCIPAL_MISMATCH_MESSAGE =\n \"client id is bound to another principal\";\n\n/** Structural equality over auth values: primitives, Dates, arrays, and plain\n * objects compare by value; anything else by identity. */\nexport const authEquals = (a: unknown, b: unknown): boolean => {\n if (Object.is(a, b)) return true;\n if (a instanceof Date && b instanceof Date)\n return a.getTime() === b.getTime();\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((v, i) => authEquals(v, b[i]));\n }\n if (\n typeof a === \"object\" &&\n typeof b === \"object\" &&\n a !== null &&\n b !== null &&\n Object.getPrototypeOf(a) === Object.prototype &&\n Object.getPrototypeOf(b) === Object.prototype\n ) {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n return (\n keysA.length === keysB.length &&\n keysA.every(\n (key) =>\n key in b &&\n authEquals(\n (a as Record<string, unknown>)[key],\n (b as Record<string, unknown>)[key],\n ),\n )\n );\n }\n return false;\n};\n\nconst RESULT_TTL_MS = 30_000;\nconst RESULT_LIMIT = 256;\nconst CLIENT_RECORD_LIMIT = 1024;\nconst MAX_SUBSCRIBERS = 1024;\nexport const SUBSCRIBER_LIMIT_MESSAGE = \"stream subscriber limit reached\";\nconst STREAM_QUEUE_SIZE = 256;\n\ntype WireOp = {\n op: string;\n path?: StatewirePath;\n value?: unknown;\n meta?: StatewireMetaEntry[];\n};\n\ntype Admission = {\n seq: number;\n method: string;\n applied: boolean;\n appliedSent: boolean;\n settled: boolean;\n};\n\nexport type ClientRec = {\n id: string;\n lastSeq: number;\n ctxSeq: number;\n touched: number;\n context: Record<string, unknown> | null;\n results: Map<number, { ts: number; cmd: StatewireCmd }>;\n inflight: Map<number, Admission>;\n /** The auth captured at the record's first attach; later attaches must match. */\n principal: unknown;\n};\n\nexport type Conn = {\n clientId: string;\n socket: StatewireHostInternal.Socket;\n open: boolean;\n sawFrame: boolean;\n lastSentAt: number;\n lease: string | null;\n /** The awaited `authorize` return captured at this attach's authorization. */\n auth: unknown;\n};\n\ntype PendingConn = {\n socket: StatewireHostInternal.Socket;\n open: boolean;\n authorizing: boolean;\n queued: string[];\n timer: ReturnType<typeof setTimeout> | null;\n connection: StatewireHostInternal.SocketConnection | null;\n};\n\n// ─── frame parsing ──────────────────────────────────────\n\nconst violation = (reason: string): never => {\n throw Object.assign(new Error(reason), { name: \"StatewireViolation\" });\n};\n\nconst violationReason = (error: unknown): string | null =>\n error instanceof Error && error.name === \"StatewireViolation\"\n ? error.message\n : null;\n\ntype CtxStatement = { seq: number; value: Record<string, unknown> };\ntype CmdStatement = {\n seq: number;\n method: string;\n params: unknown;\n meta?: unknown;\n};\n\nexport type ParsedFrame = {\n ctx: CtxStatement[];\n cmd: CmdStatement[];\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst parseLane = (value: unknown): Record<string, unknown>[] => {\n if (!Array.isArray(value)) return violation(\"malformed frame\");\n if (value.length === 0) return violation(\"empty lane\");\n const statements: Record<string, unknown>[] = [];\n let prev: number | null = null;\n for (const statement of value) {\n if (!isPlainObject(statement)) return violation(\"malformed statement\");\n const seq = statement[\"seq\"];\n if (typeof seq !== \"number\" || !Number.isInteger(seq) || seq < 1) {\n return violation(\"malformed statement\");\n }\n if (prev !== null && seq !== prev + 1) return violation(\"malformed frame\");\n prev = seq;\n statements.push(statement);\n }\n return statements;\n};\n\nconst frameEncoder = new TextEncoder();\n\n/** v1 ctx statements state the context whole: one root replace with an object value. */\nconst contextValue = (ops: unknown): Record<string, unknown> => {\n if (!Array.isArray(ops) || ops.length !== 1) {\n throw new Error(\"context must be a single-op array\");\n }\n const op = ops[0] as Record<string, unknown> | null;\n if (\n !isPlainObject(op) ||\n op[\"op\"] !== \"replace\" ||\n !Array.isArray(op[\"path\"]) ||\n op[\"path\"].length !== 0\n ) {\n throw new Error(\"context op must be a root replace\");\n }\n const value =\n op[\"meta\"] !== undefined\n ? reviveValue(op[\"value\"], op[\"meta\"], { rejectUnknown: true })\n : op[\"value\"];\n if (!isPlainObject(value)) {\n throw new Error(\"context value must be an object\");\n }\n return value;\n};\n\nexport const parseFrameValue = (frame: unknown): ParsedFrame => {\n if (!isPlainObject(frame)) return violation(\"malformed frame\");\n const keys = Object.keys(frame);\n if (keys.length === 0) return violation(\"malformed frame\");\n const unknown = keys.filter((key) => key !== \"ctx\" && key !== \"cmd\").sort();\n if (unknown.length > 0)\n return violation(`unknown frame key: '${unknown[0]}'`);\n const ctx: CtxStatement[] = [];\n if (frame[\"ctx\"] !== undefined) {\n const lane = frame[\"ctx\"];\n if (Array.isArray(lane) && lane.length > MAX_COMMANDS_PER_FRAME) {\n return violation(\"too many context statements\");\n }\n for (const statement of parseLane(lane)) {\n let value: Record<string, unknown>;\n try {\n value = contextValue(statement[\"ops\"]);\n } catch {\n return violation(\"invalid-context\");\n }\n if (\n frameEncoder.encode(JSON.stringify(value)).byteLength >\n MAX_CONTEXT_VALUE_BYTES\n ) {\n return violation(\"oversized-context\");\n }\n ctx.push({ seq: statement[\"seq\"] as number, value });\n }\n }\n const cmd: CmdStatement[] = [];\n if (frame[\"cmd\"] !== undefined) {\n const lane = frame[\"cmd\"];\n if (Array.isArray(lane) && lane.length > MAX_COMMANDS_PER_FRAME) {\n return violation(\"too many commands\");\n }\n for (const statement of parseLane(lane)) {\n const method = statement[\"method\"];\n if (typeof method !== \"string\" || !(\"params\" in statement)) {\n return violation(\"malformed statement\");\n }\n cmd.push({\n seq: statement[\"seq\"] as number,\n method,\n params: statement[\"params\"],\n ...(statement[\"meta\"] !== undefined && { meta: statement[\"meta\"] }),\n });\n }\n }\n return { ctx, cmd };\n};\n\nexport const parseFrame = (raw: string): ParsedFrame => {\n let frame: unknown;\n try {\n frame = JSON.parse(raw);\n } catch {\n return violation(\"malformed frame\");\n }\n return parseFrameValue(frame);\n};\n\nconst frameIsOversized = (raw: string): boolean =>\n raw.length > MAX_FRAME_BODY_BYTES ||\n frameEncoder.encode(raw).byteLength > MAX_FRAME_BODY_BYTES;\n\n// ─── verdict encoding ───────────────────────────────────\n\nconst encodePayload = (\n payload: unknown,\n): { payload?: unknown; meta?: StatewireMetaEntry[] } => {\n if (payload === undefined) return {};\n const { value, meta } = encodeValue(payload);\n return { payload: value, ...(meta !== undefined && { meta }) };\n};\n\nconst cmdOf = (adm: Admission, outcome: CommandsOutcome): StatewireCmd => {\n if (outcome.type === \"accepted\") {\n return { seq: adm.seq, type: \"result\", ...encodePayload(outcome.payload) };\n }\n const failure =\n outcome.error instanceof StatewireSendError ? outcome.error.failure : null;\n switch (failure?.fate) {\n case \"crashed\":\n return { seq: adm.seq, type: \"crashed\" };\n case \"failed\":\n return {\n seq: adm.seq,\n type: \"failed\",\n ...(failure.message !== undefined && { message: failure.message }),\n };\n case \"rejected\": {\n if (failure.code !== undefined) {\n const message =\n failure.code === \"unknown-command\"\n ? `unknown method: '${adm.method}'`\n : failure.message;\n return {\n seq: adm.seq,\n type: \"rejected\",\n code: failure.code,\n ...(message !== undefined && { message }),\n };\n }\n return {\n seq: adm.seq,\n type: \"rejected\",\n ...(failure.message !== undefined && { message: failure.message }),\n ...encodePayload(failure.payload),\n };\n }\n default:\n return {\n seq: adm.seq,\n type: \"failed\",\n message:\n outcome.error instanceof Error\n ? outcome.error.message\n : String(outcome.error),\n };\n }\n};\n\nconst parseInitialFrame = (raw: string) => {\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n return violation(\"malformed frame\");\n }\n if (!isPlainObject(value)) return violation(\"malformed frame\");\n const { headers, ...lanes } = value;\n if (headers === undefined) throw new Response(null, { status: 401 });\n if (\n !isPlainObject(headers) ||\n Object.values(headers).some((v) => typeof v !== \"string\")\n ) {\n return violation(\"malformed headers\");\n }\n return {\n headers: headers as Record<string, string>,\n frame: Object.keys(lanes).length\n ? parseFrameValue(lanes)\n : { ctx: [], cmd: [] },\n };\n};\n\n// ─── host ───────────────────────────────────────────────\n\nexport type SocketHostState = {\n heartbeatMs: number;\n wsInitTimeoutMs: number;\n maxSubscribers: number;\n maxInflightCommands: number;\n streamQueueSize: number;\n clientRecordLimit: number;\n finOnIdle: boolean;\n pushback: (() => number | null) | undefined;\n authorize: StatewireHostInternal.SocketHostOptions[\"authorize\"];\n clients: Map<string, ClientRec>;\n conns: Set<Conn>;\n pendingConns: Set<PendingConn>;\n pendingOps: WireOp[];\n pendingApplied: Map<string, number[]>;\n pendingCmds: Map<string, StatewireCmd[]>;\n idleWire: boolean;\n finished: StatewireHost.Fin | null;\n disposed: boolean;\n flushScheduled: boolean;\n heartbeatTimer: ReturnType<typeof setInterval> | null;\n stateHost: StatewireHost.StateHost | null;\n commandsHost: CommandsHost | null;\n current: Statewire<unknown> | null;\n persistence: StatewireHostInternal.SocketHostPersistence | undefined;\n post: () => void;\n connect: (\n clientId: string,\n socket: StatewireHostInternal.Socket,\n options?: StatewireHostInternal.SocketConnectOptions,\n ) => StatewireHostInternal.SocketConnection | null;\n finish: (fin: StatewireHost.Fin) => void;\n stream: (request: Request) => Promise<Response>;\n frames: (request: Request) => Promise<Response>;\n};\n\nconst scheduleFlush = (h: SocketHostState) => {\n if (h.flushScheduled || h.disposed) return;\n h.flushScheduled = true;\n h.post();\n};\n\nconst recordOp = (\n h: SocketHostState,\n op: {\n op: string;\n path?: StatewirePath;\n value?: unknown;\n },\n) => {\n if (op.op === \"replace\" || op.op === \"add\") {\n const { value, meta } = encodeValue(op.value);\n h.pendingOps.push({ ...op, value, ...(meta !== undefined && { meta }) });\n } else {\n h.pendingOps.push(op);\n }\n scheduleFlush(h);\n};\n\nconst attach = (h: SocketHostState, next: Statewire<unknown>) => {\n if (next === h.current) return;\n h.current = next;\n const nextState =\n typeof next.state === \"object\" && next.state !== null\n ? getStateHost(next.state)\n : undefined;\n const nextCommands = getCommandsHost(next.commands);\n if (!nextState || !nextCommands?.submit) {\n throw new Error(\n \"StatewireSocketHost requires a statewire/host transport (useStatewireState with object state, useStatewireCommands)\",\n );\n }\n if (nextState !== h.stateHost) {\n h.stateHost?.setOnOp(null);\n h.stateHost = nextState;\n h.stateHost.setOnOp((op) => recordOp(h, op));\n }\n h.commandsHost = nextCommands;\n};\n\nexport const closeConn = (\n h: SocketHostState,\n conn: Conn,\n code?: number,\n reason?: string,\n) => {\n if (!conn.open) return;\n conn.open = false;\n h.conns.delete(conn);\n try {\n conn.socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n if (h.conns.size === 0 && h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n }\n};\n\nexport const sendTo = (h: SocketHostState, conn: Conn, data: string) => {\n if (!conn.open) return;\n conn.lastSentAt = Date.now();\n try {\n conn.socket.send(data);\n } catch {\n closeConn(h, conn);\n }\n};\n\nexport const atSubscriberLimit = (h: SocketHostState): boolean =>\n h.conns.size +\n [...h.pendingConns].filter((conn) => conn.authorizing).length >=\n h.maxSubscribers;\n\nconst ensureHeartbeat = (h: SocketHostState) => {\n if (h.heartbeatTimer !== null || h.heartbeatMs <= 0) return;\n h.heartbeatTimer = setInterval(() => {\n const now = Date.now();\n for (const conn of [...h.conns]) {\n if (now - conn.lastSentAt >= h.heartbeatMs) sendTo(h, conn, \"{}\");\n }\n }, h.heartbeatMs);\n (h.heartbeatTimer as unknown as { unref?: () => void }).unref?.();\n};\n\nconst setHeartbeatMs = (h: SocketHostState, ms: number) => {\n if (ms === h.heartbeatMs) return;\n h.heartbeatMs = ms;\n if (h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n ensureHeartbeat(h);\n }\n};\n\nconst idleLevel = (h: SocketHostState): boolean => {\n if (h.current?.work?.isIdle === false) return false;\n for (const rec of h.clients.values()) {\n if (rec.inflight.size > 0) return false;\n }\n return true;\n};\n\nexport const flush = (h: SocketHostState, fin?: StatewireHost.Fin) => {\n flushTapSync(() => {});\n h.stateHost?.takeChanged();\n for (const rec of h.clients.values()) {\n for (const adm of rec.inflight.values()) {\n if (adm.applied && !adm.settled && !adm.appliedSent) {\n adm.appliedSent = true;\n queueApplied(h, rec.id, adm.seq);\n }\n }\n }\n const level = idleLevel(h);\n const edge = level !== h.idleWire;\n if (\n h.pendingOps.length === 0 &&\n h.pendingApplied.size === 0 &&\n h.pendingCmds.size === 0 &&\n fin === undefined &&\n !edge\n ) {\n return;\n }\n h.idleWire = level;\n if (fin === undefined && edge && level && h.finOnIdle) {\n fin = { reason: \"idle\" };\n }\n const ops = h.pendingOps;\n const applied = h.pendingApplied;\n const cmds = h.pendingCmds;\n h.pendingOps = [];\n h.pendingApplied = new Map();\n h.pendingCmds = new Map();\n // Applied entries anchor to their effects: piggybacked on the ops packet\n // when one is flushing, standalone otherwise. Terminal verdicts ride their\n // own packet.\n for (const conn of [...h.conns]) {\n const appliedEntries: StatewireCmd[] = (\n applied.get(conn.clientId) ?? []\n ).map((seq) => ({ seq, type: \"applied\" }));\n if (ops.length > 0) {\n const packet: StatewireEnvelope = {\n ops,\n ...(appliedEntries.length > 0 && { cmd: appliedEntries }),\n ...(edge && { idle: level }),\n };\n sendTo(h, conn, JSON.stringify(packet));\n } else if (appliedEntries.length > 0) {\n sendTo(h, conn, JSON.stringify({ cmd: appliedEntries }));\n }\n const verdicts = cmds.get(conn.clientId) ?? [];\n if (verdicts.length > 0) {\n sendTo(h, conn, JSON.stringify({ cmd: verdicts }));\n }\n if (edge && ops.length === 0) {\n sendTo(h, conn, JSON.stringify({ idle: level }));\n }\n if (fin !== undefined) {\n sendTo(h, conn, JSON.stringify({ fin }));\n closeConn(h, conn);\n }\n }\n};\n\nconst queueApplied = (h: SocketHostState, clientId: string, seq: number) => {\n const list = h.pendingApplied.get(clientId);\n if (list) list.push(seq);\n else h.pendingApplied.set(clientId, [seq]);\n scheduleFlush(h);\n};\n\nconst queueCmd = (h: SocketHostState, clientId: string, cmd: StatewireCmd) => {\n const list = h.pendingCmds.get(clientId);\n if (list) list.push(cmd);\n else h.pendingCmds.set(clientId, [cmd]);\n scheduleFlush(h);\n};\n\nconst notifyClientRecords = (h: SocketHostState) => {\n h.persistence?.onClientRecordsChange?.(\n [...h.clients.values()].map((rec) => ({\n id: rec.id,\n lastSeq: admittedThrough(rec),\n ctxSeq: rec.ctxSeq,\n touched: rec.touched,\n context: rec.context,\n results: [...rec.results].map(([seq, entry]) => ({\n seq,\n ts: entry.ts,\n cmd: entry.cmd,\n })),\n principal: rec.principal,\n })),\n );\n};\n\nconst retain = (rec: ClientRec, cmd: StatewireCmd) => {\n const now = Date.now();\n rec.results.set(cmd.seq, { ts: now, cmd });\n const newest = Math.max(...rec.results.keys());\n for (const [seq, entry] of rec.results) {\n if (seq !== newest && now - entry.ts > RESULT_TTL_MS) {\n rec.results.delete(seq);\n }\n }\n while (rec.results.size > RESULT_LIMIT) {\n rec.results.delete(Math.min(...rec.results.keys()));\n }\n};\n\n/** Cmd-lane watermark: the last statement admitted, settled or not. */\nconst admittedThrough = (rec: ClientRec): number =>\n Math.max(rec.lastSeq, ...rec.inflight.keys());\n\n// A re-asked seq never re-runs: the stored verdict re-emits, an applied\n// inflight run re-answers applied; one not yet applied answers nothing (its\n// answers ride the stream when ready), an evicted verdict answers expired.\nconst reemit = (h: SocketHostState, rec: ClientRec, seq: number) => {\n const cached = rec.results.get(seq);\n if (cached) {\n const newest = Math.max(...rec.results.keys());\n if (seq === newest || Date.now() - cached.ts <= RESULT_TTL_MS) {\n queueCmd(h, rec.id, cached.cmd);\n return;\n }\n rec.results.delete(seq);\n notifyClientRecords(h);\n }\n const adm = rec.inflight.get(seq);\n if (adm) {\n if (adm.applied) queueApplied(h, rec.id, seq);\n return;\n }\n queueCmd(h, rec.id, { seq, type: \"expired\" });\n};\n\nconst settleCmd = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n cmd: StatewireCmd,\n) => {\n if (adm.settled) return;\n adm.settled = true;\n rec.inflight.delete(adm.seq);\n retain(rec, cmd);\n rec.lastSeq = Math.max(rec.lastSeq, adm.seq);\n adm.applied = true;\n queueCmd(h, rec.id, cmd);\n notifyClientRecords(h);\n};\n\nconst settleWire = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n outcome: CommandsOutcome,\n) => settleCmd(h, rec, adm, cmdOf(adm, outcome));\n\nconst callerOf = (\n h: SocketHostState,\n rec: ClientRec,\n auth: unknown,\n): StatewireHost.Caller => ({\n clientId: rec.id,\n auth,\n get context() {\n return rec.context;\n },\n get isConnected() {\n if (h.clients.get(rec.id) !== rec) return false;\n for (const conn of h.conns) {\n if (conn.clientId === rec.id && conn.open) return true;\n }\n return false;\n },\n});\n\nconst rejectStatement = (\n h: SocketHostState,\n rec: ClientRec,\n adm: Admission,\n message: string,\n) =>\n settleCmd(h, rec, adm, {\n seq: adm.seq,\n type: \"rejected\",\n code: \"invalid-params\",\n message,\n });\n\nconst admitCmd = (\n h: SocketHostState,\n rec: ClientRec,\n statement: CmdStatement,\n auth: unknown,\n) => {\n const adm: Admission = {\n seq: statement.seq,\n method: statement.method,\n applied: false,\n appliedSent: false,\n settled: false,\n };\n rec.inflight.set(statement.seq, adm);\n notifyClientRecords(h);\n if (!Array.isArray(statement.params)) {\n rejectStatement(h, rec, adm, \"params must be an array\");\n return;\n }\n let params = statement.params;\n if (statement.meta !== undefined) {\n try {\n params = reviveValue(params, statement.meta, {\n rejectUnknown: true,\n }) as unknown[];\n } catch (error) {\n rejectStatement(\n h,\n rec,\n adm,\n `invalid params: ${(error as Error).message}`,\n );\n return;\n }\n }\n if (statement.method === \"statewire/commands\") {\n if (params.length > 0) {\n rejectStatement(h, rec, adm, \"statewire/commands takes no params\");\n return;\n }\n const names = [\n ...(h.commandsHost?.methods?.() ?? []),\n \"statewire/commands\",\n ].sort();\n settleCmd(h, rec, adm, { seq: adm.seq, type: \"result\", payload: names });\n return;\n }\n h.commandsHost!.submit!({\n method: statement.method,\n params,\n clientId: rec.id,\n caller: callerOf(h, rec, auth),\n onApplied: () => {\n if (adm.settled || adm.applied) return;\n adm.applied = true;\n rec.lastSeq = Math.max(rec.lastSeq, adm.seq);\n notifyClientRecords(h);\n scheduleFlush(h);\n },\n onSettle: (outcome) => settleWire(h, rec, adm, outcome),\n }).catch((error: unknown) => {\n if (!adm.settled) settleWire(h, rec, adm, { type: \"rejected\", error });\n });\n};\n\n// One admission law, both lanes: absorbed statements answer from the record,\n// then the new suffix is admitted whole or the frame is refused whole via a\n// {syn} stating both watermarks, nothing consumed. A gap is never a close.\nexport type FrameAdmission =\n | { type: \"ok\" }\n | {\n type: \"refused\";\n syn: {\n syn: { seq: number; ctxSeq: number; retry?: number };\n };\n };\n\nexport const admitFrame = (\n h: SocketHostState,\n rec: ClientRec,\n frame: ParsedFrame,\n auth: unknown,\n): FrameAdmission => {\n rec.touched = Date.now();\n const through = admittedThrough(rec);\n for (const statement of frame.cmd) {\n if (statement.seq <= through) reemit(h, rec, statement.seq);\n }\n const ctxNew = frame.ctx.filter((s) => s.seq > rec.ctxSeq);\n const cmdNew = frame.cmd.filter((s) => s.seq > through);\n if (\n (ctxNew.length > 0 && ctxNew[0]!.seq !== rec.ctxSeq + 1) ||\n (cmdNew.length > 0 && cmdNew[0]!.seq !== through + 1)\n ) {\n notifyClientRecords(h);\n return {\n type: \"refused\",\n syn: { syn: { seq: through, ctxSeq: rec.ctxSeq } },\n };\n }\n if (cmdNew.length > 0) {\n let hostCommandLoad = 0;\n for (const client of h.clients.values()) {\n hostCommandLoad += client.inflight.size;\n }\n if (\n rec.inflight.size + cmdNew.length > MAX_INFLIGHT_COMMANDS_PER_CLIENT ||\n hostCommandLoad + cmdNew.length > h.maxInflightCommands\n ) {\n return {\n type: \"refused\",\n syn: {\n syn: {\n seq: through,\n ctxSeq: rec.ctxSeq,\n retry: COMMAND_CAPACITY_RETRY_MS,\n },\n },\n };\n }\n }\n if ((ctxNew.length || cmdNew.length) && h.pushback) {\n const retry = h.pushback();\n if (retry !== null) {\n if (!Number.isSafeInteger(retry) || retry < 0)\n throw new TypeError(\n \"pushback must return a nonnegative safe integer or null\",\n );\n return {\n type: \"refused\",\n syn: { syn: { seq: through, ctxSeq: rec.ctxSeq, retry } },\n };\n }\n }\n for (const statement of ctxNew) {\n rec.context = statement.value;\n rec.ctxSeq = statement.seq;\n }\n for (const statement of cmdNew) admitCmd(h, rec, statement, auth);\n if (cmdNew.length > 0) {\n // Memory host: admitted means retained — dur rides the admitting flush.\n queueCmd(h, rec.id, { seq: cmdNew.at(-1)!.seq, dur: true });\n }\n notifyClientRecords(h);\n scheduleFlush(h);\n return { type: \"ok\" };\n};\n\nconst message = (h: SocketHostState, conn: Conn, data: string) => {\n if (!conn.open || h.disposed || h.finished !== null) return;\n if (frameIsOversized(data)) {\n sendTo(\n h,\n conn,\n JSON.stringify({\n fin: {\n reason: \"protocol-error\",\n message: \"frame too large\",\n },\n }),\n );\n closeConn(h, conn, 1009, \"frame too large\");\n return;\n }\n const first = !conn.sawFrame;\n conn.sawFrame = true;\n let frame: ParsedFrame;\n try {\n frame = first ? parseInitialFrame(data).frame : parseFrame(data);\n } catch (error) {\n const reason = violationReason(error);\n if (reason === null) throw error;\n sendTo(\n h,\n conn,\n JSON.stringify({\n fin: {\n reason: \"protocol-error\",\n message: reason,\n },\n }),\n );\n closeConn(h, conn, 1008, reason);\n return;\n }\n if (frame.ctx.length === 0 && frame.cmd.length === 0) return;\n const rec = h.clients.get(conn.clientId)!;\n const admission = admitFrame(h, rec, frame, conn.auth);\n if (admission.type === \"refused\") {\n sendTo(h, conn, JSON.stringify(admission.syn));\n }\n};\n\nconst closePending = (\n h: SocketHostState,\n pending: PendingConn,\n code?: number,\n reason?: string,\n) => {\n if (!pending.open) return;\n pending.open = false;\n h.pendingConns.delete(pending);\n if (pending.timer !== null) clearTimeout(pending.timer);\n try {\n pending.socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n};\n\nconst sendPending = (pending: PendingConn, data: string): boolean => {\n if (!pending.open) return false;\n try {\n pending.socket.send(data);\n return true;\n } catch {\n return false;\n }\n};\n\nconst refuseSubscriberLimit = (socket: StatewireHostInternal.Socket): null => {\n try {\n socket.send(\n JSON.stringify({\n fin: {\n reason: \"reconnect\",\n code: \"overloaded\",\n message: SUBSCRIBER_LIMIT_MESSAGE,\n },\n }),\n );\n } catch {\n /* peer already gone */\n }\n try {\n socket.close(1013, SUBSCRIBER_LIMIT_MESSAGE);\n } catch {\n /* peer already gone */\n }\n return null;\n};\n\nconst rejectPendingAuthorization = (\n h: SocketHostState,\n pending: PendingConn,\n error: unknown,\n) => {\n const response = error instanceof Response ? error : null;\n const unauthorized = response?.status === 401 || response?.status === 403;\n const status = response?.status;\n const message = unauthorized\n ? \"unauthorized\"\n : response?.statusText ||\n (status === undefined ? \"authorization failed\" : `HTTP ${status}`);\n sendPending(\n pending,\n JSON.stringify({\n fin: {\n reason:\n status === 403\n ? \"forbidden\"\n : unauthorized\n ? \"unauthorized\"\n : \"error\",\n message,\n ...(status !== undefined && { status }),\n },\n }),\n );\n closePending(h, pending, unauthorized ? 1008 : 1011, message);\n};\n\nconst normalizedHeaders = (\n headers: Record<string, string>,\n): Record<string, string> => {\n const seen = new Set<string>();\n for (const name of Object.keys(headers)) {\n const key = name.toLowerCase();\n if (seen.has(key)) throw new TypeError(\"duplicate header name\");\n seen.add(key);\n }\n return Object.fromEntries(new Headers(headers));\n};\n\nconst connectAuthorized = (\n h: SocketHostState,\n clientId: string,\n socket: StatewireHostInternal.Socket,\n options: StatewireHostInternal.SocketConnectOptions,\n): StatewireHostInternal.SocketConnection | null => {\n const authorize = h.authorize;\n if (options.authorized === true) {\n const registration = register(\n h,\n clientId,\n socket,\n options.authorized === true,\n options.auth,\n );\n return registration?.connection ?? null;\n }\n const refuse = (code: number, reason: string) => {\n try {\n socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n return null;\n };\n if (h.disposed) return refuse(1001, \"disposed\");\n if (!CLIENT_ID_RE.test(clientId)) return refuse(1008, \"invalid client id\");\n flush(h);\n if (h.finished !== null) {\n try {\n socket.send(JSON.stringify({ fin: h.finished }));\n } catch {\n /* peer already gone */\n }\n return refuse(1000, \"finished\");\n }\n const pending: PendingConn = {\n socket,\n open: true,\n authorizing: false,\n queued: [],\n timer: null,\n connection: null,\n };\n h.pendingConns.add(pending);\n pending.timer = setTimeout(\n () =>\n rejectPendingAuthorization(\n h,\n pending,\n new Response(null, { status: 401 }),\n ),\n h.wsInitTimeoutMs,\n );\n (pending.timer as unknown as { unref?: () => void }).unref?.();\n return {\n clientId,\n message: (data) => {\n if (pending.connection !== null) {\n pending.connection.message(data);\n return;\n }\n if (!pending.open || h.disposed || h.finished !== null) return;\n if (frameIsOversized(data)) {\n sendPending(\n pending,\n JSON.stringify({\n fin: {\n reason: \"protocol-error\",\n message: \"frame too large\",\n },\n }),\n );\n closePending(h, pending, 1009, \"frame too large\");\n return;\n }\n if (pending.authorizing) {\n pending.queued.push(data);\n return;\n }\n let initial: ReturnType<typeof parseInitialFrame>;\n try {\n initial = parseInitialFrame(data);\n } catch (error) {\n if (error instanceof Response) {\n rejectPendingAuthorization(h, pending, error);\n return;\n }\n const reason = violationReason(error);\n if (reason === null) throw error;\n sendPending(\n pending,\n JSON.stringify({\n fin: {\n reason: \"protocol-error\",\n message: reason,\n },\n }),\n );\n closePending(h, pending, 1008, reason);\n return;\n }\n const frame = initial.frame;\n let headers: Record<string, string>;\n try {\n headers = normalizedHeaders(initial.headers);\n } catch {\n sendPending(\n pending,\n JSON.stringify({\n fin: {\n reason: \"protocol-error\",\n message: \"malformed headers\",\n },\n }),\n );\n closePending(h, pending, 1008, \"malformed headers\");\n return;\n }\n if (atSubscriberLimit(h)) {\n sendPending(\n pending,\n JSON.stringify({\n fin: {\n reason: \"reconnect\",\n code: \"overloaded\",\n message: SUBSCRIBER_LIMIT_MESSAGE,\n },\n }),\n );\n closePending(h, pending, 1013, SUBSCRIBER_LIMIT_MESSAGE);\n return;\n }\n pending.authorizing = true;\n Promise.resolve()\n .then(() => authorize?.({ headers }))\n .then((auth) => {\n if (!pending.open || h.disposed || h.finished !== null) return;\n options.onAuthorized?.(auth);\n pending.open = false;\n h.pendingConns.delete(pending);\n if (pending.timer !== null) clearTimeout(pending.timer);\n const registration = register(h, clientId, socket, true, auth);\n if (registration === null) return;\n pending.connection = registration.connection;\n if (frame.ctx.length || frame.cmd.length) {\n const admission = admitFrame(h, registration.rec, frame, auth);\n if (admission.type === \"refused\")\n sendTo(h, registration.conn, JSON.stringify(admission.syn));\n }\n for (const data of pending.queued.splice(0))\n registration.connection.message(data);\n })\n .catch((error: unknown) => {\n if (pending.open) rejectPendingAuthorization(h, pending, error);\n });\n },\n close: () => {\n if (pending.connection !== null) pending.connection.close();\n else closePending(h, pending);\n },\n };\n};\n\nconst gcClients = (h: SocketHostState) => {\n let excess = h.clients.size - h.clientRecordLimit;\n if (excess <= 0) return;\n let changed = false;\n const live = new Set([...h.conns].map((conn) => conn.clientId));\n const oldest = [...h.clients.values()].sort((a, b) => a.touched - b.touched);\n for (const rec of oldest) {\n if (excess <= 0) break;\n if (live.has(rec.id) || rec.inflight.size > 0) continue;\n h.clients.delete(rec.id);\n changed = true;\n excess -= 1;\n }\n if (changed) notifyClientRecords(h);\n};\n\nexport type Registration = {\n rec: ClientRec;\n conn: Conn;\n connection: StatewireHostInternal.SocketConnection;\n};\n\nexport const register = (\n h: SocketHostState,\n clientId: string,\n socket: StatewireHostInternal.Socket,\n sawFrame = false,\n auth: unknown = undefined,\n): Registration | null => {\n const refuse = (code: number, reason: string) => {\n try {\n socket.close(code, reason);\n } catch {\n /* peer already gone */\n }\n return null;\n };\n if (h.disposed) return refuse(1001, \"disposed\");\n if (!CLIENT_ID_RE.test(clientId)) return refuse(1008, \"invalid client id\");\n flush(h);\n if (h.finished !== null) {\n try {\n socket.send(JSON.stringify({ fin: h.finished }));\n } catch {\n /* peer already gone */\n }\n refuse(1000, \"finished\");\n return null;\n }\n if (atSubscriberLimit(h)) {\n return refuseSubscriberLimit(socket);\n }\n const known = h.clients.get(clientId);\n if (known !== undefined && !authEquals(known.principal, auth)) {\n try {\n socket.send(\n JSON.stringify({\n fin: {\n reason: \"forbidden\",\n message: PRINCIPAL_MISMATCH_MESSAGE,\n status: 403,\n },\n }),\n );\n } catch {\n /* peer already gone */\n }\n return refuse(1008, PRINCIPAL_MISMATCH_MESSAGE);\n }\n const rec =\n known ??\n (() => {\n const created: ClientRec = {\n id: clientId,\n lastSeq: 0,\n ctxSeq: 0,\n touched: Date.now(),\n context: null,\n results: new Map(),\n inflight: new Map(),\n principal: auth,\n };\n h.clients.set(clientId, created);\n return created;\n })();\n rec.touched = Date.now();\n const conn: Conn = {\n clientId,\n socket,\n open: true,\n sawFrame,\n lastSentAt: 0,\n lease: null,\n auth,\n };\n h.conns.add(conn);\n gcClients(h);\n notifyClientRecords(h);\n ensureHeartbeat(h);\n const { value, meta } = encodeValue(h.stateHost!.snapshot());\n const hello: StatewireEnvelope = {\n ops: [\n {\n op: \"replace\",\n path: [],\n value,\n ...(meta !== undefined && { meta }),\n },\n ],\n syn: {\n seq: admittedThrough(rec),\n ctxSeq: rec.ctxSeq,\n ...(h.idleWire && { idle: true }),\n },\n };\n sendTo(h, conn, JSON.stringify(hello));\n const connection: StatewireHostInternal.SocketConnection = {\n clientId,\n message: (data) => message(h, conn, data),\n close: () => closeConn(h, conn),\n };\n return { rec, conn, connection };\n};\n\nconst connect = (\n h: SocketHostState,\n clientId: string,\n socket: StatewireHostInternal.Socket,\n options: StatewireHostInternal.SocketConnectOptions = {},\n): StatewireHostInternal.SocketConnection | null => {\n return connectAuthorized(h, clientId, socket, options);\n};\n\nconst finish = (h: SocketHostState, fin: StatewireHost.Fin) => {\n if (\n fin.retry !== undefined &&\n (!Number.isSafeInteger(fin.retry) || fin.retry < 0)\n ) {\n throw new Error(\"statewire: retry must be a nonnegative safe integer\");\n }\n if (h.finished !== null || h.disposed) return;\n h.commandsHost?.abort?.();\n h.finished = fin;\n for (const pending of [...h.pendingConns]) {\n sendPending(pending, JSON.stringify({ fin }));\n closePending(h, pending, 1000, fin.reason);\n }\n flush(h, fin);\n};\n\nconst resume = (h: SocketHostState) => {\n h.disposed = false;\n h.stateHost?.setOnOp((op) => recordOp(h, op));\n};\n\nconst suspend = (h: SocketHostState) => {\n h.disposed = true;\n if (h.heartbeatTimer !== null) {\n clearInterval(h.heartbeatTimer);\n h.heartbeatTimer = null;\n }\n h.stateHost?.setOnOp(null);\n};\n\nconst restoreClientRecords = (\n records: readonly StatewireHostInternal.ClientRecord[] = [],\n): Map<string, ClientRec> =>\n new Map(\n records.map((record) => [\n record.id,\n {\n ...record,\n results: new Map(\n record.results.map(({ seq, ts, cmd }) => [seq, { ts, cmd }]),\n ),\n inflight: new Map(),\n },\n ]),\n );\n\nconst useSocketHost = (\n transport: ResourceElement<Statewire>,\n options?: StatewireHostInternal.SocketHostOptions,\n persistence?: StatewireHostInternal.SocketHostPersistence,\n): Pick<\n StatewireHostInternal.SocketHost,\n \"connect\" | \"finish\" | \"stream\" | \"frames\"\n> => {\n const [h] = useState((): SocketHostState => {\n const host: SocketHostState = {\n heartbeatMs: 15_000,\n wsInitTimeoutMs: 5_000,\n maxSubscribers: MAX_SUBSCRIBERS,\n maxInflightCommands: MAX_INFLIGHT_COMMANDS_PER_HOST,\n streamQueueSize: STREAM_QUEUE_SIZE,\n clientRecordLimit: CLIENT_RECORD_LIMIT,\n finOnIdle: false,\n pushback: undefined,\n authorize: undefined,\n clients: restoreClientRecords(persistence?.clientRecords),\n conns: new Set(),\n pendingConns: new Set(),\n pendingOps: [],\n pendingApplied: new Map(),\n pendingCmds: new Map(),\n idleWire: true,\n finished: null,\n disposed: false,\n flushScheduled: false,\n heartbeatTimer: null,\n stateHost: null,\n commandsHost: null,\n current: null,\n persistence,\n post: createMacrotaskPoster(() => {\n host.flushScheduled = false;\n flush(host);\n }),\n connect: (clientId, socket, connectOptions) =>\n connect(host, clientId, socket, connectOptions),\n finish: (fin) => finish(host, fin),\n stream: (request) => serveStream(host, request),\n frames: (request) => serveFrames(host, request),\n };\n return host;\n });\n setHeartbeatMs(h, options?.heartbeatIntervalMs ?? 15_000);\n h.pushback = options?.pushback;\n h.wsInitTimeoutMs = options?.wsInitTimeoutMs ?? 5_000;\n const maxSubscribers =\n options?.maxSubscribers === undefined\n ? MAX_SUBSCRIBERS\n : options.maxSubscribers;\n if (!Number.isInteger(maxSubscribers) || maxSubscribers < 1) {\n throw new TypeError(\"maxSubscribers must be a positive integer\");\n }\n h.maxSubscribers = maxSubscribers;\n const maxInflightCommands =\n options?.maxInflightCommands === undefined\n ? MAX_INFLIGHT_COMMANDS_PER_HOST\n : options.maxInflightCommands;\n if (!Number.isInteger(maxInflightCommands) || maxInflightCommands < 1) {\n throw new TypeError(\"maxInflightCommands must be a positive integer\");\n }\n h.maxInflightCommands = maxInflightCommands;\n const streamQueueSize =\n options?.streamQueueSize === undefined\n ? STREAM_QUEUE_SIZE\n : options.streamQueueSize;\n if (!Number.isInteger(streamQueueSize) || streamQueueSize < 1) {\n throw new TypeError(\"streamQueueSize must be a positive integer\");\n }\n h.streamQueueSize = streamQueueSize;\n h.clientRecordLimit = options?.clientRecordLimit ?? CLIENT_RECORD_LIMIT;\n h.finOnIdle = options?.finOnIdle ?? false;\n h.authorize = options?.authorize;\n const value = useResource(transport) as Statewire<unknown>;\n attach(h, value);\n useEffect(() => {\n attach(h, value);\n scheduleFlush(h);\n });\n useEffect(() => {\n resume(h);\n return () => suspend(h);\n }, [h]);\n return h;\n};\n\n/**\n * Transport-agnostic WS binding over a statewire/host transport:\n * feed it sockets (anything with `send`/`close`) and raw text frames, and it\n * speaks the Statewire packet protocol — snapshot-first hello with `syn`,\n * statement-lane client frames under one admission law, `{cmd}` answer\n * arrays fanned out to every attach of a client id, idle edges, and `fin` on\n * finish.\n */\nexport const StatewireSocketHost = (\n transport: ResourceElement<Statewire>,\n options?: StatewireHostInternal.SocketHostOptions,\n persistence?: StatewireHostInternal.SocketHostPersistence,\n): StatewireHostInternal.SocketHost => {\n const SocketHostRoot = () => useSocketHost(transport, options, persistence);\n const root = createTapRoot(SocketHostRoot);\n let disposed = false;\n return {\n connect: (clientId, socket, connectOptions) =>\n flushTapSync(() =>\n root.getValue().connect(clientId, socket, connectOptions),\n ),\n stream: (request) => flushTapSync(() => root.getValue().stream(request)),\n frames: (request) => flushTapSync(() => root.getValue().frames(request)),\n finish: (fin) => flushTapSync(() => root.getValue().finish(fin)),\n dispose: () => {\n if (disposed) return;\n disposed = true;\n flushTapSync(() =>\n root.getValue().finish({ reason: \"reconnect\", code: \"evicted\" }),\n );\n root.unmount();\n },\n };\n};\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { StatewireHost } from "../host.js";
2
+ //#region src/host/work.d.ts
3
+ /** Track background tasks and scheduled callbacks in the host's idle status. */
4
+ declare const useStatewireWork: () => StatewireHost.Work;
5
+ //#endregion
6
+ export { useStatewireWork };
7
+ //# sourceMappingURL=work.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work.d.ts","names":[],"sources":["../../src/host/work.ts"],"mappings":";;;cAIa,wBAAuB,cAAc"}
@@ -0,0 +1,53 @@
1
+ import { useEffect, useState } from "@assistant-ui/tap/react-shim";
2
+ //#region src/host/work.ts
3
+ /** Track background tasks and scheduled callbacks in the host's idle status. */
4
+ const useStatewireWork = () => {
5
+ const [, notify] = useState(0);
6
+ const [cell] = useState(() => ({
7
+ tasks: /* @__PURE__ */ new Set(),
8
+ scheduled: /* @__PURE__ */ new Set(),
9
+ active: true
10
+ }));
11
+ useEffect(() => {
12
+ cell.active = true;
13
+ return () => {
14
+ cell.active = false;
15
+ cell.scheduled.clear();
16
+ };
17
+ }, [cell]);
18
+ const [work] = useState(() => ({
19
+ get isIdle() {
20
+ return cell.tasks.size === 0 && cell.scheduled.size === 0;
21
+ },
22
+ track: (task) => {
23
+ if (!cell.active) throw new Error("statewire: work called after unmount");
24
+ cell.tasks.add(task);
25
+ notify((n) => n + 1);
26
+ const release = () => {
27
+ cell.tasks.delete(task);
28
+ if (cell.active) notify((n_0) => n_0 + 1);
29
+ };
30
+ task.then(release, release);
31
+ return task;
32
+ },
33
+ schedule: (callback) => {
34
+ if (!cell.active) throw new Error("statewire: work called after unmount");
35
+ if (cell.scheduled.has(callback)) return;
36
+ cell.scheduled.add(callback);
37
+ notify((n_1) => n_1 + 1);
38
+ queueMicrotask(() => {
39
+ if (!cell.scheduled.delete(callback)) return;
40
+ try {
41
+ callback();
42
+ } finally {
43
+ if (cell.active) notify((n) => n + 1);
44
+ }
45
+ });
46
+ }
47
+ }));
48
+ return work;
49
+ };
50
+ //#endregion
51
+ export { useStatewireWork };
52
+
53
+ //# sourceMappingURL=work.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"work.js","names":["useEffect","useState","StatewireHost","useStatewireWork","Work","notify","cell","tasks","Set","Promise","scheduled","active","clear","work","isIdle","size","track","task","Error","add","n","release","delete","then","schedule","callback","has","queueMicrotask"],"sources":["../../src/host/work.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport type { StatewireHost } from \"../host\";\n\n/** Track background tasks and scheduled callbacks in the host's idle status. */\nexport const useStatewireWork = (): StatewireHost.Work => {\n const [, notify] = useState(0);\n const [cell] = useState(() => ({\n tasks: new Set<Promise<unknown>>(),\n scheduled: new Set<() => void>(),\n active: true,\n }));\n useEffect(() => {\n cell.active = true;\n return () => {\n cell.active = false;\n cell.scheduled.clear();\n };\n }, [cell]);\n const [work] = useState<StatewireHost.Work>(() => ({\n get isIdle() {\n return cell.tasks.size === 0 && cell.scheduled.size === 0;\n },\n track: (task) => {\n if (!cell.active) throw new Error(\"statewire: work called after unmount\");\n cell.tasks.add(task);\n notify((n) => n + 1);\n const release = () => {\n cell.tasks.delete(task);\n if (cell.active) notify((n) => n + 1);\n };\n void task.then(release, release);\n return task;\n },\n schedule: (callback) => {\n if (!cell.active) throw new Error(\"statewire: work called after unmount\");\n if (cell.scheduled.has(callback)) return;\n cell.scheduled.add(callback);\n notify((n) => n + 1);\n queueMicrotask(() => {\n if (!cell.scheduled.delete(callback)) return;\n try {\n callback();\n } finally {\n if (cell.active) notify((n) => n + 1);\n }\n });\n },\n }));\n return work;\n};\n"],"mappings":";;;AAIA,MAAaG,yBAA6C;CACxD,MAAM,GAAGE,UAAUJ,SAAS,CAAC;CAC7B,MAAM,CAACK,QAAQL,gBAAgB;EAC7BM,uBAAO,IAAIC,IAAsB;EACjCE,2BAAW,IAAIF,IAAgB;EAC/BG,QAAQ;CACV,EAAE;CACFX,gBAAgB;EACdM,KAAKK,SAAS;EACd,aAAa;GACXL,KAAKK,SAAS;GACdL,KAAKI,UAAUE,MAAM;EACvB;CACF,GAAG,CAACN,IAAI,CAAC;CACT,MAAM,CAACO,QAAQZ,gBAAoC;EACjD,IAAIa,SAAS;GACX,OAAOR,KAAKC,MAAMQ,SAAS,KAAKT,KAAKI,UAAUK,SAAS;EAC1D;EACAC,QAAQC,SAAS;GACf,IAAI,CAACX,KAAKK,QAAQ,MAAM,IAAIO,MAAM,sCAAsC;GACxEZ,KAAKC,MAAMY,IAAIF,IAAI;GACnBZ,QAAQe,MAAMA,IAAI,CAAC;GACnB,MAAMC,gBAAgB;IACpBf,KAAKC,MAAMe,OAAOL,IAAI;IACtB,IAAIX,KAAKK,QAAQN,QAAQe,QAAMA,MAAI,CAAC;GACtC;GACA,KAAUG,KAAKF,SAASA,OAAO;GAC/B,OAAOJ;EACT;EACAO,WAAWC,aAAa;GACtB,IAAI,CAACnB,KAAKK,QAAQ,MAAM,IAAIO,MAAM,sCAAsC;GACxE,IAAIZ,KAAKI,UAAUgB,IAAID,QAAQ,GAAG;GAClCnB,KAAKI,UAAUS,IAAIM,QAAQ;GAC3BpB,QAAQe,QAAMA,MAAI,CAAC;GACnBO,qBAAqB;IACnB,IAAI,CAACrB,KAAKI,UAAUY,OAAOG,QAAQ,GAAG;IACtC,IAAI;KACFA,SAAS;IACX,UAAU;KACR,IAAInB,KAAKK,QAAQN,QAAQe,MAAMA,IAAI,CAAC;IACtC;GACF,CAAC;EACH;CACF,EAAE;CACF,OAAOP;AACT"}
@@ -1,6 +1,8 @@
1
1
  import { StatewireHost } from "./host.js";
2
+ import { StatewireCmd } from "./client/connection.js";
2
3
  import { StatewireSocketHost } from "./host/socket.js";
3
4
  import { clientIdFromUrl, textFrameOrClose } from "./host/adapter.js";
5
+ import { WS_SUBPROTOCOL } from "./wire/version.js";
4
6
  //#region src/host-internal.d.ts
5
7
  declare namespace StatewireHostInternal {
6
8
  type Socket = {
@@ -12,26 +14,62 @@ declare namespace StatewireHostInternal {
12
14
  message: (data: string) => void;
13
15
  close: () => void;
14
16
  };
17
+ type SocketConnectOptions = {
18
+ /** The adapter restored this socket from an already-authorized session. */
19
+ authorized?: boolean;
20
+ /** The restored session's captured auth value; it must satisfy the client record's principal binding. */
21
+ auth?: unknown;
22
+ /** Persist authorization (and the captured auth value) before the first snapshot is released. */
23
+ onAuthorized?: (auth: unknown) => void;
24
+ };
15
25
  type SocketHost = {
16
26
  /** Null means refused: the socket was told (fin and/or close) and is dead. */
17
- connect: (clientId: string, socket: Socket) => SocketConnection | null;
27
+ connect: (clientId: string, socket: Socket, options?: SocketConnectOptions) => SocketConnection | null;
18
28
  stream: (request: Request) => Promise<Response>;
19
29
  frames: (request: Request) => Promise<Response>;
20
30
  finish: (fin: StatewireHost.Fin) => void;
21
31
  dispose: () => void;
22
32
  };
23
- type SocketHostOptions = {
33
+ type ClientRecord = {
34
+ id: string;
35
+ lastSeq: number;
36
+ ctxSeq: number;
37
+ touched: number;
38
+ context: Record<string, unknown> | null;
39
+ results: readonly {
40
+ seq: number;
41
+ ts: number;
42
+ cmd: StatewireCmd;
43
+ }[];
44
+ principal: unknown;
45
+ };
46
+ type SocketHostPersistence = {
47
+ clientRecords?: readonly ClientRecord[];
48
+ onClientRecordsChange?: (records: readonly ClientRecord[]) => void;
49
+ };
50
+ type SocketHostOptions<TAuth = unknown> = {
51
+ /** Gates every attach; the awaited return value is the attach's auth, exposed to command handlers as `this.caller.auth`. The first attach binds the client id's record to this value; a later attach whose value is not structurally equal is refused (HTTP 403, socket close 1008). */
24
52
  authorize?: (ctx: {
25
53
  headers: Record<string, string>;
26
- }) => void | Promise<void>;
54
+ }) => TAuth | Promise<TAuth>;
55
+ /** Time allowed to complete WebSocket initialization and authorization. */
56
+ wsInitTimeoutMs?: number;
27
57
  heartbeatIntervalMs?: number;
58
+ /** Maximum number of concurrently attached WebSocket and SSE streams. */
59
+ maxSubscribers?: number;
60
+ /** Maximum number of admitted commands still running across all clients. */
61
+ maxInflightCommands?: number;
62
+ /** Maximum number of queued SSE packets before a lagging stream is closed. */
63
+ streamQueueSize?: number;
28
64
  /** LRU cap on stored client records; live or in-flight records are exempt. */
29
65
  clientRecordLimit?: number;
30
66
  /** Hang every attach up with `fin: idle` at the idle flag's rising edge. */
31
67
  finOnIdle?: boolean;
68
+ /** Milliseconds to defer admission, or null to admit. */
69
+ pushback?: () => number | null;
32
70
  };
33
71
  type Fin = StatewireHost.Fin;
34
72
  }
35
73
  //#endregion
36
- export { StatewireHostInternal, StatewireSocketHost, clientIdFromUrl, textFrameOrClose };
74
+ export { StatewireHostInternal, StatewireSocketHost, WS_SUBPROTOCOL, clientIdFromUrl, textFrameOrClose };
37
75
  //# sourceMappingURL=host-internal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host-internal.d.ts","names":[],"sources":["../src/host-internal.ts"],"mappings":";;;;kBAIiB;OACH;IACV,OAAO;IACP,QAAQ,eAAe;;OAGb;aACD;IACT,UAAU;IACV;;OAGU;;IAEV,UAAU,kBAAkB,QAAQ,WAAW;IAC/C,SAAS,SAAS,YAAY,QAAQ;IACtC,SAAS,SAAS,YAAY,QAAQ;IACtC,SAAS,KAAK,cAAc;IAC5B;;OAGU;IACV,aAAa;MACX,SAAS;iBACE;IACb;;IAEA;;IAEA;;OAGU,MAAM,cAAc"}
1
+ {"version":3,"file":"host-internal.d.ts","names":[],"sources":["../src/host-internal.ts"],"mappings":";;;;;;kBAMiB;OACH;IACV,OAAO;IACP,QAAQ,eAAe;;OAGb;aACD;IACT,UAAU;IACV;;OAGU;;IAEV;;IAEA;;IAEA,gBAAgB;;OAGN;;IAEV,UACE,kBACA,QAAQ,QACR,UAAU,yBACP;IACL,SAAS,SAAS,YAAY,QAAQ;IACtC,SAAS,SAAS,YAAY,QAAQ;IACtC,SAAS,KAAK,cAAc;IAC5B;;OAGU;IACV;IACA;IACA;IACA;IACA,SAAS;IACT;MAAoB;MAAa;MAAY,KAAK;;IAClD;;OAGU;IACV,yBAAyB;IACzB,yBAAyB,kBAAkB;;OAGjC,kBAAkB;;IAE5B,aAAa;MACX,SAAS;UACL,QAAQ,QAAQ;;IAEtB;IACA;;IAEA;;IAEA;;IAEA;;IAEA;;IAEA;;IAEA;;OAGU,MAAM,cAAc"}
@@ -1,3 +1,4 @@
1
+ import { WS_SUBPROTOCOL } from "./wire/version.js";
1
2
  import { StatewireSocketHost } from "./host/socket.js";
2
3
  import { clientIdFromUrl, textFrameOrClose } from "./host/adapter.js";
3
- export { StatewireSocketHost, clientIdFromUrl, textFrameOrClose };
4
+ export { StatewireSocketHost, WS_SUBPROTOCOL, clientIdFromUrl, textFrameOrClose };
package/dist/host.d.ts CHANGED
@@ -1,9 +1,15 @@
1
1
  import { StatewireReject } from "./host/engine.js";
2
+ import { useStatewireWork } from "./host/work.js";
2
3
  import { append } from "./host/draft.js";
3
4
  import { getStateHost, useStatewireCommands, useStatewireState } from "./host/host.js";
4
5
  import { Statewire } from "./types.js";
5
6
  //#region src/host.d.ts
6
7
  declare namespace StatewireHost {
8
+ type Work = {
9
+ readonly isIdle: boolean;
10
+ track: <T>(task: Promise<T>) => Promise<T>;
11
+ schedule: (callback: () => void) => void;
12
+ };
7
13
  type StateCtl<TState = unknown> = {
8
14
  /** Apply server-vocabulary ops (root replace = whole-state swap). */
9
15
  apply: (ops: readonly Statewire.Op[]) => void;
@@ -23,28 +29,35 @@ declare namespace StatewireHost {
23
29
  */
24
30
  type Ctx = {
25
31
  readonly caller: Caller;
32
+ readonly signal: AbortSignal;
26
33
  readonly applied: () => void;
27
34
  };
28
35
  /**
29
36
  * The submitting client (`this.caller` in a command handler). Holdable
30
37
  * across a long run: `clientId` is the client's `Statewire-Client-Id`
31
- * (in-process dispatch has none — reading it throws), `context` reads the
38
+ * (in-process dispatch has none — reading it throws), `auth` is the value
39
+ * `authorize` returned for the attach that admitted the command (undefined
40
+ * for a void `authorize` and for in-process dispatch), `context` reads the
32
41
  * client's current ambient context live (null until the client sends one),
33
42
  * `isConnected` reports whether the client has an active stream attachment.
34
43
  */
35
44
  type Caller = {
36
45
  readonly clientId: string;
46
+ readonly auth: unknown;
37
47
  readonly context: Record<string, unknown> | null;
38
48
  readonly isConnected: boolean;
39
49
  };
40
50
  type HandledCommands<THandlers extends Statewire.Commands> = { [K in keyof THandlers]: (...args: Parameters<THandlers[K]>) => Awaited<ReturnType<THandlers[K]>>; };
41
51
  type Fin = {
42
- reason: "evicted" | "error" | "unauthorized" | "gone" | "idle" | (string & {});
52
+ reason: "reconnect" | "error" | "protocol-error" | "forbidden" | "unauthorized" | "gone" | "idle" | (string & {});
43
53
  message?: string;
54
+ code?: string;
55
+ status?: number;
56
+ retry?: number;
44
57
  payload?: unknown;
45
58
  meta?: unknown;
46
59
  };
47
60
  }
48
61
  //#endregion
49
- export { StatewireHost, StatewireReject, append, getStateHost, useStatewireCommands, useStatewireState };
62
+ export { StatewireHost, StatewireReject, append, getStateHost, useStatewireCommands, useStatewireState, useStatewireWork };
50
63
  //# sourceMappingURL=host.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","names":[],"sources":["../src/host.ts"],"mappings":";;;;;kBAUiB;OACH,SAAS;;IAEnB,QAAQ,cAAc,UAAU;;IAEhC,gBAAgB;;OAGN,YAAY,UAAU;;IAEhC,UAAU,YAAY,IAAI,UAAU;;;;;;;;;OAU1B;aACD,QAAQ;aACR;;;;;;;;;OAUC;aACD;aACA,SAAS;aACT;;OAGC,gBAAgB,kBAAkB,UAAU,eACrD,WAAW,gBACP,MAAM,WAAW,UAAU,QAC3B,QAAQ,WAAW,UAAU;OAGxB;IACV;IAOA;IACA;IACA"}
1
+ {"version":3,"file":"host.d.ts","names":[],"sources":["../src/host.ts"],"mappings":";;;;;;kBAWiB;OACH;aACD;IACT,QAAQ,GAAG,MAAM,QAAQ,OAAO,QAAQ;IACxC,WAAW;;OAGD,SAAS;;IAEnB,QAAQ,cAAc,UAAU;;IAEhC,gBAAgB;;OAGN,YAAY,UAAU;;IAEhC,UAAU,YAAY,IAAI,UAAU;;;;;;;;;OAU1B;aACD,QAAQ;aACR,QAAQ;aACR;;;;;;;;;;;OAYC;aACD;aACA;aACA,SAAS;aACT;;OAGC,gBAAgB,kBAAkB,UAAU,eACrD,WAAW,gBACP,MAAM,WAAW,UAAU,QAC3B,QAAQ,WAAW,UAAU;OAGxB;IACV;IASA;IACA;IACA;IACA;IACA;IACA"}
package/dist/host.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { StatewireReject } from "./host/engine.js";
2
2
  import { append } from "./host/draft.js";
3
3
  import { getStateHost, useStatewireCommands, useStatewireState } from "./host/host.js";
4
- export { StatewireReject, append, getStateHost, useStatewireCommands, useStatewireState };
4
+ import { useStatewireWork } from "./host/work.js";
5
+ export { StatewireReject, append, getStateHost, useStatewireCommands, useStatewireState, useStatewireWork };
@@ -1,3 +1,4 @@
1
+ import { StatewireHost } from "./host.js";
1
2
  import { TERMINAL } from "./client/connection.js";
2
3
  import { Statewire } from "./types.js";
3
4
  import { ResourceElement } from "@assistant-ui/tap";
@@ -37,6 +38,7 @@ declare namespace StatewireClient {
37
38
  state: NonNullable<TState>;
38
39
  }) => void;
39
40
  onConnectionChange?: (connection: Connection) => void;
41
+ onError?: (error: ConnectionError) => void;
40
42
  /** Drops a retained failed entry once a canonical snapshot shows its effect landed; checked against each new snapshot. */
41
43
  failureCovered?: (state: NonNullable<TState>, entry: FailedCommand) => boolean;
42
44
  };
@@ -58,26 +60,29 @@ declare namespace StatewireClient {
58
60
  /** Removes the entry. */
59
61
  discardFailed: (entry: FailedCommand) => void;
60
62
  };
63
+ /** `cause`/`nextRetryAt`/`lastError` are present only while waiting out the backoff timer; a dial in flight carries `attempt` alone. */
61
64
  type ConnectionState = {
62
- status: "connecting";
63
- } | {
64
- status: "live";
65
- } | {
66
- status: "idle";
65
+ status: "disconnected";
66
+ reason: "deferred" | "idle" | "gone" | "forbidden" | "protocol-error" | "unauthorized";
67
+ message?: string;
68
+ payload?: unknown;
67
69
  } | {
68
- status: "reconnecting";
69
- cause: "dropped" | "evicted" | "error" | "unauthorized";
70
+ status: "connecting";
71
+ /** 0 = the episode's first dial, >0 = retry. */
70
72
  attempt: number;
71
- nextRetryAt: number;
73
+ cause?: "dropped" | "reconnect" | "error" | "unauthorized";
74
+ code?: string;
75
+ nextRetryAt?: number;
72
76
  lastError?: string;
73
77
  message?: string;
74
78
  } | {
75
- status: "gone";
76
- message?: string;
77
- payload?: unknown;
79
+ status: "connected";
78
80
  };
79
81
  type Connection = ConnectionState & {
82
+ error?: ConnectionError;
80
83
  reconnect: () => void;
84
+ /** True while retrying (`connecting` with `attempt > 0`) or parked `gone`. */
85
+ degraded: boolean;
81
86
  };
82
87
  type ConnectionStatus = Connection["status"];
83
88
  /**
@@ -186,6 +191,9 @@ declare namespace StatewireClient {
186
191
  subscribe?: (listener: () => void) => () => void;
187
192
  };
188
193
  /** Static headers, or a resolver invoked per request/attach; `staleAuth` is true right after an auth rejection. */
194
+ type ConnectionError = Error & {
195
+ fin: StatewireHost.Fin;
196
+ };
189
197
  type HeadersOption = HeadersInit | ((ctx: {
190
198
  staleAuth: boolean;
191
199
  }) => HeadersInit | Promise<HeadersInit>);
@@ -198,6 +206,7 @@ declare namespace StatewireClient {
198
206
  fetch?: typeof globalThis.fetch;
199
207
  onSessionLost?: OnSessionLost;
200
208
  onChange?: (connection: Connection) => void;
209
+ onError?: (error: ConnectionError) => void;
201
210
  /** The broadcast idle flag's rising edge: the instance went quiet. */
202
211
  onDone?: () => void;
203
212
  };
@@ -212,6 +221,7 @@ declare namespace StatewireClient {
212
221
  webSocket?: new (url: string, protocols?: string | string[]) => WebSocket;
213
222
  onSessionLost?: OnSessionLost;
214
223
  onChange?: (connection: Connection) => void;
224
+ onError?: (error: ConnectionError) => void;
215
225
  /** The broadcast idle flag's rising edge: the instance went quiet. */
216
226
  onDone?: () => void;
217
227
  };