statewire 0.18.2 → 0.19.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.
- package/dist/client/connection.d.ts +8 -5
- package/dist/client/connection.d.ts.map +1 -1
- package/dist/client/connection.js +24 -13
- package/dist/client/connection.js.map +1 -1
- package/dist/client/session.d.ts +13 -15
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/session.js +291 -256
- package/dist/client/session.js.map +1 -1
- package/dist/client/timing.d.ts +2 -1
- package/dist/client/timing.d.ts.map +1 -1
- package/dist/client/timing.js +2 -1
- package/dist/client/timing.js.map +1 -1
- package/dist/host/engine.d.ts +2 -0
- package/dist/host/engine.d.ts.map +1 -1
- package/dist/host/engine.js +2 -0
- package/dist/host/engine.js.map +1 -1
- package/dist/host/host.d.ts +3 -1
- package/dist/host/host.d.ts.map +1 -1
- package/dist/host/host.js +38 -7
- package/dist/host/host.js.map +1 -1
- package/dist/host/http.d.ts.map +1 -1
- package/dist/host/http.js +8 -17
- package/dist/host/http.js.map +1 -1
- package/dist/host/socket.d.ts +47 -23
- package/dist/host/socket.d.ts.map +1 -1
- package/dist/host/socket.js +389 -245
- package/dist/host/socket.js.map +1 -1
- package/dist/host/synced.d.ts +9 -0
- package/dist/host/synced.d.ts.map +1 -0
- package/dist/host/synced.js +45 -0
- package/dist/host/synced.js.map +1 -0
- package/dist/host-internal.d.ts +20 -8
- package/dist/host-internal.d.ts.map +1 -1
- package/dist/host.d.ts +33 -9
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +2 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -1
- package/dist/statewire.d.ts +8 -10
- package/dist/statewire.d.ts.map +1 -1
- package/dist/statewire.js +0 -14
- package/dist/statewire.js.map +1 -1
- package/dist/storage.d.ts +2 -5
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +55 -41
- package/dist/storage.js.map +1 -1
- package/dist/transports/remote.d.ts.map +1 -1
- package/dist/transports/remote.js +1 -6
- package/dist/transports/remote.js.map +1 -1
- package/dist/transports/sse.d.ts +2 -5
- package/dist/transports/sse.d.ts.map +1 -1
- package/dist/transports/sse.js.map +1 -1
- package/dist/transports/testing.d.ts +7 -5
- package/dist/transports/testing.d.ts.map +1 -1
- package/dist/transports/testing.js +19 -19
- package/dist/transports/testing.js.map +1 -1
- package/dist/types.d.ts +3 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/wire/limits.d.ts +2 -2
- package/dist/wire/limits.js +2 -2
- package/dist/wire/limits.js.map +1 -1
- package/dist/wire/protocol.d.ts +6 -1
- package/dist/wire/protocol.d.ts.map +1 -1
- package/dist/wire/protocol.js +33 -12
- package/dist/wire/protocol.js.map +1 -1
- package/package.json +1 -1
- package/src/client/connection.ts +46 -33
- package/src/client/session.ts +434 -365
- package/src/client/timing.ts +2 -0
- package/src/host/engine.ts +3 -1
- package/src/host/host.ts +50 -3
- package/src/host/http.ts +22 -23
- package/src/host/socket.ts +550 -321
- package/src/host/synced.ts +60 -0
- package/src/host-internal.ts +21 -3
- package/src/host.ts +40 -8
- package/src/index.ts +1 -0
- package/src/statewire.ts +8 -30
- package/src/storage.ts +96 -79
- package/src/transports/remote.ts +0 -7
- package/src/transports/sse.ts +8 -3
- package/src/transports/testing.ts +34 -19
- package/src/types.ts +3 -5
- package/src/wire/limits.ts +1 -1
- package/src/wire/protocol.ts +40 -11
package/dist/storage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","names":["useEffect","useMemo","useRef","wrapStorageError","resource","StatewireClient","StatewireProtocol","negotiationHeaders","protocolToken","isRecord","value","Record","Array","isArray","isOptionalString","undefined","isPositiveSafeInteger","Number","isSafeInteger","isSessionCommand","SessionCommand","isProtocol","isProducer","isSessionVerdict","SessionVerdict","isSendFailure","SendFailure","isFailedCommand","FailedCommand","isFinite","isSessionRecord","SessionRecord","length","every","test","wireVersion","Range","applicationProtocols","Offer","decode","raw","legacyProtocol","KeyValueSessionStorage","Options","parsed","JSON","parse","Error","statewireStorageVersion","format","savedAt","_savedAt","ctxNextSeq","_ctxNextSeq","context","_context","produced","wire","version","protocols","commands","map","command","protocol","name","failed","entry","active","WeakMap","Backend","Map","sweep","options","currentKey","quota","backend","retention","namespace","getAllKeys","entries","key","candidate","startsWith","get","has","getItem","push","sort","a","b","now","Date","retained","quotaStart","Math","floor","index","expired","maxAgeMs","overflow","maxEntries","remove","removeItem","withUnused","isQuotaError","error","useKeyValueSessionStorage","SessionStorage","suppliedLegacyProtocol","migrate","suppliedRetention","onError","latestErrorHandler","current","reportError","legacyName","legacyVersion","retain","configured","storageKey","state","Promise","cause","record","ready","queue","resolve","pending","failure","asynchronous","hydrated","then","catch","set","count","delete","load","save","encoded","stringify","recoverQuota","setItem","write","result","finally","flush","action"],"sources":["../src/storage.ts"],"sourcesContent":["import { useEffect, useMemo, useRef } from \"react\";\nimport { wrapStorageError } from \"./client/storageError\";\nimport { resource } from \"@assistant-ui/tap\";\nimport type { StatewireClient } from \"./statewire\";\nimport type { StatewireProtocol } from \"./wire/protocol\";\nimport { negotiationHeaders, protocolToken } from \"./wire/protocol\";\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isOptionalString = (value: unknown): boolean =>\n value === undefined || typeof value === \"string\";\n\nconst isPositiveSafeInteger = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isSafeInteger(value) && value > 0;\n\nconst isSessionCommand = (\n value: unknown,\n): value is StatewireClient.SessionCommand =>\n isRecord(value) &&\n isPositiveSafeInteger(value[\"seq\"]) &&\n isProtocol(value[\"protocol\"]) &&\n isProducer(value[\"produced\"]) &&\n typeof value[\"method\"] === \"string\" &&\n Array.isArray(value[\"params\"]);\n\nconst isSessionVerdict = (\n value: unknown,\n): value is StatewireClient.SessionVerdict =>\n isRecord(value) &&\n isPositiveSafeInteger(value[\"seq\"]) &&\n (value[\"type\"] === \"result\" ||\n value[\"type\"] === \"rejected\" ||\n value[\"type\"] === \"failed\" ||\n value[\"type\"] === \"crashed\" ||\n value[\"type\"] === \"expired\") &&\n isOptionalString(value[\"code\"]) &&\n isOptionalString(value[\"message\"]);\n\nconst isSendFailure = (\n value: unknown,\n): value is StatewireClient.SendFailure => {\n if (!isRecord(value)) return false;\n switch (value[\"fate\"]) {\n case \"rejected\":\n return (\n value[\"cause\"] === \"server\" &&\n isOptionalString(value[\"code\"]) &&\n isOptionalString(value[\"message\"])\n );\n case \"failed\":\n return value[\"cause\"] === \"server\" && isOptionalString(value[\"message\"]);\n case \"crashed\":\n case \"expired\":\n return value[\"cause\"] === \"server\";\n case \"aborted\":\n return (\n (value[\"cause\"] === \"unmount\" ||\n value[\"cause\"] === \"stream-gone\" ||\n value[\"cause\"] === \"session-lost\") &&\n (value[\"predecessorLost\"] === undefined ||\n value[\"predecessorLost\"] === true)\n );\n case \"lost\":\n return (\n value[\"cause\"] === \"unmount\" ||\n value[\"cause\"] === \"stream-gone\" ||\n value[\"cause\"] === \"session-lost\"\n );\n default:\n return false;\n }\n};\n\nconst isFailedCommand = (\n value: unknown,\n): value is StatewireClient.FailedCommand =>\n isRecord(value) &&\n isProtocol(value[\"protocol\"]) &&\n isProducer(value[\"produced\"]) &&\n typeof value[\"command\"] === \"string\" &&\n Array.isArray(value[\"params\"]) &&\n isSendFailure(value[\"failure\"]) &&\n typeof value[\"ts\"] === \"number\" &&\n Number.isFinite(value[\"ts\"]) &&\n isPositiveSafeInteger(value[\"seq\"]);\n\nconst isSessionRecord = (\n value: unknown,\n): value is StatewireClient.SessionRecord =>\n isRecord(value) &&\n typeof value[\"clientId\"] === \"string\" &&\n value[\"clientId\"].length > 0 &&\n isPositiveSafeInteger(value[\"nextSeq\"]) &&\n Array.isArray(value[\"commands\"]) &&\n value[\"commands\"].every(isSessionCommand) &&\n (value[\"verdicts\"] === undefined ||\n (Array.isArray(value[\"verdicts\"]) &&\n value[\"verdicts\"].every(isSessionVerdict))) &&\n (value[\"failed\"] === undefined ||\n (Array.isArray(value[\"failed\"]) && value[\"failed\"].every(isFailedCommand)));\n\nconst isProtocol = (value: unknown) =>\n value === undefined ||\n (typeof value === \"string\" && value !== \"*\" && protocolToken.test(value));\n\nconst isProducer = (value: unknown) => {\n if (value === undefined) return true;\n if (!isRecord(value) || !isRecord(value[\"wire\"])) return false;\n try {\n negotiationHeaders({\n wireVersion: value[\"wire\"] as StatewireProtocol.Range,\n applicationProtocols: value[\"protocols\"] as\n | readonly StatewireProtocol.Offer[]\n | \"*\",\n });\n return value[\"protocols\"] !== undefined;\n } catch {\n return false;\n }\n};\n\nconst decode = (\n raw: string | null,\n legacyProtocol: KeyValueSessionStorage.Options[\"legacyProtocol\"],\n): StatewireClient.SessionRecord | null => {\n if (raw === null) return null;\n const parsed: unknown = JSON.parse(raw);\n if (!isSessionRecord(parsed))\n throw new Error(\"statewire: invalid stored session record\");\n const {\n statewireStorageVersion: format,\n savedAt: _savedAt,\n ctxNextSeq: _ctxNextSeq,\n context: _context,\n ...value\n } = parsed as StatewireClient.SessionRecord & {\n statewireStorageVersion?: unknown;\n savedAt?: unknown;\n ctxNextSeq?: unknown;\n context?: unknown;\n };\n if (!isSessionRecord(value))\n throw new Error(\"statewire: invalid stored session record\");\n if (format !== undefined && format !== 1 && format !== 2)\n throw new Error(\"statewire: unsupported session storage version\");\n if (legacyProtocol === undefined || format !== undefined) return value;\n const produced = {\n wire: { version: \"2026-09-07\" },\n protocols: [legacyProtocol],\n };\n return {\n ...value,\n commands: value.commands.map((command) =>\n command.produced === undefined\n ? {\n ...command,\n protocol: command.protocol ?? legacyProtocol.name,\n produced,\n }\n : command,\n ),\n ...(value.failed === undefined\n ? {}\n : {\n failed: value.failed.map((entry) => ({\n ...entry,\n protocol: entry.protocol ?? legacyProtocol.name,\n produced: entry.produced ?? produced,\n })),\n }),\n };\n};\n\nconst active = new WeakMap<\n KeyValueSessionStorage.Backend,\n Map<string, number>\n>();\n\nconst sweep = async (\n options: KeyValueSessionStorage.Options,\n currentKey: string,\n quota = false,\n) => {\n const { backend, retention, namespace = \"\" } = options;\n if (!retention || !backend.getAllKeys) return;\n const entries: { key: string; savedAt: number }[] = [];\n const candidate = (raw: string | null) => {\n if (raw === null) return undefined;\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n return undefined;\n }\n const format = isRecord(value)\n ? value[\"statewireStorageVersion\"]\n : undefined;\n if (format !== undefined && format !== 1 && format !== 2) return undefined;\n if (\n !isSessionRecord(value) ||\n value.commands.length ||\n value.failed?.length\n )\n return undefined;\n const savedAt =\n (value as Record<string, unknown>)[\"savedAt\"] ??\n (value as Record<string, unknown>)[\"updatedAt\"];\n return typeof savedAt === \"number\" && Number.isFinite(savedAt)\n ? savedAt\n : undefined;\n };\n for (const key of await backend.getAllKeys()) {\n if (\n !key.startsWith(namespace) ||\n key === currentKey ||\n active.get(backend)?.has(key)\n )\n continue;\n const savedAt = candidate(await backend.getItem(key));\n if (savedAt !== undefined) entries.push({ key, savedAt });\n }\n entries.sort((a, b) => b.savedAt - a.savedAt);\n const now = Date.now();\n let retained = 1;\n const quotaStart = Math.floor(entries.length / 2);\n for (const [index, entry] of entries.entries()) {\n const expired =\n retention.maxAgeMs !== undefined &&\n now - entry.savedAt > retention.maxAgeMs;\n const overflow =\n retention.maxEntries !== undefined && retained >= retention.maxEntries;\n if (expired || overflow || (quota && index >= quotaStart)) {\n const remove = async () => {\n if (active.get(backend)?.has(entry.key)) return;\n if (candidate(await backend.getItem(entry.key)) !== entry.savedAt)\n return;\n if (active.get(backend)?.has(entry.key)) return;\n await backend.removeItem(entry.key);\n };\n if (backend.withUnused) await backend.withUnused(entry.key, remove);\n else await remove();\n } else retained++;\n }\n};\n\nconst isQuotaError = (error: unknown) =>\n error instanceof Error && error.name === \"QuotaExceededError\";\n\nconst useKeyValueSessionStorage = (\n options: KeyValueSessionStorage.Options,\n): StatewireClient.SessionStorage => {\n const {\n backend,\n key,\n namespace = \"\",\n legacyProtocol: suppliedLegacyProtocol,\n migrate,\n retention: suppliedRetention,\n onError,\n } = options;\n const latestErrorHandler = useRef(onError);\n latestErrorHandler.current = onError;\n const reportError = useMemo(\n () => (error: unknown) => latestErrorHandler.current?.(error),\n [],\n );\n const legacyName = suppliedLegacyProtocol?.name;\n const legacyVersion = suppliedLegacyProtocol?.version;\n const legacyProtocol = useMemo(\n () =>\n legacyName === undefined\n ? undefined\n : { name: legacyName, version: legacyVersion! },\n [legacyName, legacyVersion],\n );\n const retain = suppliedRetention !== undefined;\n const maxAgeMs = suppliedRetention?.maxAgeMs;\n const maxEntries = suppliedRetention?.maxEntries;\n const retention = useMemo(\n () =>\n retain\n ? {\n ...(maxAgeMs === undefined ? {} : { maxAgeMs }),\n ...(maxEntries === undefined ? {} : { maxEntries }),\n }\n : undefined,\n [retain, maxAgeMs, maxEntries],\n );\n const configured = useMemo(\n () => ({\n backend,\n key,\n namespace,\n ...(retention === undefined ? {} : { retention }),\n }),\n [backend, key, namespace, retention],\n );\n const storageKey = namespace + key;\n if (legacyProtocol !== undefined)\n negotiationHeaders({ applicationProtocols: [legacyProtocol] });\n if (retention !== undefined) {\n if (!namespace)\n throw new Error(\"statewire: session retention requires a namespace\");\n if (!backend.getAllKeys)\n throw new Error(\"statewire: session retention requires getAllKeys\");\n if (\n retention.maxAgeMs !== undefined &&\n (!Number.isFinite(retention.maxAgeMs) || retention.maxAgeMs < 0)\n )\n throw new Error(\"statewire: invalid session retention maxAgeMs\");\n if (\n retention.maxEntries !== undefined &&\n (!Number.isSafeInteger(retention.maxEntries) || retention.maxEntries < 1)\n )\n throw new Error(\"statewire: invalid session retention maxEntries\");\n }\n const state = useMemo(() => {\n let raw: string | null | Promise<string | null>;\n try {\n raw = backend.getItem(storageKey);\n } catch (cause) {\n const error = wrapStorageError(cause);\n reportError(error);\n throw error;\n }\n const state = {\n record: null as StatewireClient.SessionRecord | null,\n ready: undefined as Promise<void> | undefined,\n queue: Promise.resolve(),\n pending: 0,\n failure: undefined as unknown,\n asynchronous: typeof raw !== \"string\" && raw !== null,\n hydrated: typeof raw === \"string\" || raw === null,\n };\n if (state.asynchronous) {\n state.ready = Promise.resolve(raw)\n .then((value) => {\n state.record = decode(value, legacyProtocol);\n state.hydrated = true;\n })\n .catch((cause: unknown) => {\n const error = wrapStorageError(cause);\n if (state.failure !== error) reportError(error);\n state.failure = error;\n throw error;\n });\n state.ready.catch(() => {});\n } else {\n try {\n state.record = decode(raw as string | null, legacyProtocol);\n } catch (cause) {\n const error = wrapStorageError(cause);\n reportError(error);\n throw error;\n }\n }\n return state;\n }, [backend, storageKey, legacyProtocol, reportError]);\n\n useEffect(() => {\n const entries = active.get(backend) ?? new Map<string, number>();\n active.set(backend, entries);\n entries.set(storageKey, (entries.get(storageKey) ?? 0) + 1);\n return () => {\n const count = entries.get(storageKey)! - 1;\n if (count === 0) entries.delete(storageKey);\n else entries.set(storageKey, count);\n };\n }, [backend, storageKey]);\n\n useEffect(() => {\n if (retention !== undefined)\n void sweep(configured, storageKey).catch((cause: unknown) => {\n const error = wrapStorageError(cause);\n state.failure = error;\n reportError(error);\n });\n }, [state, configured, storageKey, retention, reportError]);\n\n return useMemo(\n () => ({\n ...(state.ready === undefined ? {} : { ready: state.ready }),\n load: () => {\n if (state.failure !== undefined) throw state.failure;\n if (!state.hydrated)\n throw new Error(\n \"statewire: await session storage readiness before loading\",\n );\n if (state.asynchronous || state.pending > 0) return state.record;\n let raw: string | null | Promise<string | null>;\n try {\n raw = backend.getItem(storageKey);\n } catch (cause) {\n const error = wrapStorageError(cause);\n reportError(error);\n throw error;\n }\n if (typeof raw !== \"string\" && raw !== null)\n throw new Error(\n \"statewire: storage backend changed from synchronous to asynchronous\",\n );\n try {\n return decode(raw, legacyProtocol);\n } catch (cause) {\n const error = wrapStorageError(cause);\n reportError(error);\n throw error;\n }\n },\n save: (record: StatewireClient.SessionRecord) => {\n if (state.failure !== undefined) throw state.failure;\n if (!state.hydrated)\n throw new Error(\n \"statewire: await session storage readiness before saving\",\n );\n if (!isSessionRecord(record))\n throw new Error(\"statewire: invalid session record\");\n const encoded = JSON.stringify({\n ...record,\n statewireStorageVersion: 2,\n savedAt: Date.now(),\n });\n state.record = record;\n const recoverQuota = async (error: unknown) => {\n if (!isQuotaError(error) || retention === undefined) throw error;\n await sweep(configured, storageKey, true);\n await backend.setItem(storageKey, encoded);\n };\n const write = async () => {\n try {\n await backend.setItem(storageKey, encoded);\n } catch (error) {\n await recoverQuota(error);\n }\n };\n if (!state.asynchronous && state.pending === 0) {\n let result: void | Promise<void>;\n try {\n result = backend.setItem(storageKey, encoded);\n } catch (error) {\n if (!isQuotaError(error) || retention === undefined) {\n state.failure = wrapStorageError(error);\n reportError(state.failure);\n throw state.failure;\n }\n result = recoverQuota(error);\n }\n if (result === undefined) return;\n state.pending++;\n state.queue = result;\n } else {\n state.pending++;\n state.queue = state.queue.then(() => state.ready).then(write);\n }\n state.queue = state.queue\n .catch((cause: unknown) => {\n const error = wrapStorageError(cause);\n if (state.failure !== error) reportError(error);\n state.failure = error;\n throw error;\n })\n .finally(() => {\n state.pending--;\n });\n state.queue.catch(() => {});\n },\n flush: () => {\n if (state.failure !== undefined) throw state.failure;\n if (!state.asynchronous && state.pending === 0) return;\n return (async () => {\n await state.ready;\n for (;;) {\n const queue = state.queue;\n await queue;\n if (queue === state.queue) return;\n }\n })();\n },\n ...(migrate === undefined ? {} : { migrate }),\n }),\n [\n state,\n backend,\n storageKey,\n legacyProtocol,\n migrate,\n retention,\n configured,\n reportError,\n ],\n );\n};\n\n/** Persist sessions through a synchronous or asynchronous string storage backend. */\nexport const KeyValueSessionStorage = resource(useKeyValueSessionStorage);\n\nexport namespace KeyValueSessionStorage {\n export type Backend = {\n getItem: (key: string) => string | null | Promise<string | null>;\n setItem: (key: string, value: string) => void | Promise<void>;\n removeItem: (key: string) => void | Promise<void>;\n getAllKeys?: () => readonly string[] | Promise<readonly string[]>;\n /** Runs cleanup under exclusive access, skipping keys in use by another runtime. */\n withUnused?: (key: string, action: () => Promise<void>) => Promise<void>;\n };\n export type Options = {\n backend: Backend;\n key: string;\n namespace?: string;\n /** The application format used by sessions saved before version negotiation. */\n legacyProtocol?: { name: string; version: string };\n migrate?: StatewireClient.SessionStorage[\"migrate\"];\n retention?: { maxAgeMs?: number; maxEntries?: number };\n onError?: (error: unknown) => void;\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"storage.js","names":["useEffect","useMemo","useRef","wrapStorageError","resource","StatewireClient","StatewireProtocol","DEFAULT_PROTOCOL","negotiationHeaders","protocolToken","isRecord","value","Record","Array","isArray","isOptionalString","undefined","isPositiveSafeInteger","Number","isSafeInteger","isSessionCommand","SessionCommand","isProtocol","isProducer","isSessionVerdict","SessionVerdict","isSendFailure","SendFailure","isFailedCommand","FailedCommand","isFinite","isSessionLane","SessionLane","every","isClientId","length","isSessionRecord","SessionRecord","Object","keys","values","test","wireVersion","Range","applicationProtocols","Offer","invalid","Error","liftLegacy","protocol","clientId","nextSeq","commands","verdicts","failed","lane","legacyCommands","lanes","filter","command","map","_protocol","entry","target","normalize","parsed","statewireStorageVersion","format","savedAt","_savedAt","ctxNextSeq","_ctxNextSeq","context","_context","legacy","decode","raw","JSON","parse","isEmpty","record","active","WeakMap","KeyValueSessionStorage","Backend","Map","sweep","options","Options","currentKey","quota","backend","retention","namespace","getAllKeys","entries","key","candidate","startsWith","get","has","getItem","push","sort","a","b","now","Date","retained","quotaStart","Math","floor","index","expired","maxAgeMs","overflow","maxEntries","remove","removeItem","withUnused","isQuotaError","error","name","useKeyValueSessionStorage","SessionStorage","migrate","suppliedRetention","onError","latestErrorHandler","current","reportError","retain","configured","storageKey","state","Promise","cause","ready","queue","resolve","pending","failure","asynchronous","hydrated","then","catch","set","count","delete","load","save","encoded","stringify","recoverQuota","setItem","write","result","finally","flush","action"],"sources":["../src/storage.ts"],"sourcesContent":["import { useEffect, useMemo, useRef } from \"react\";\nimport { wrapStorageError } from \"./client/storageError\";\nimport { resource } from \"@assistant-ui/tap\";\nimport type { StatewireClient } from \"./statewire\";\nimport type { StatewireProtocol } from \"./wire/protocol\";\nimport {\n DEFAULT_PROTOCOL,\n negotiationHeaders,\n protocolToken,\n} from \"./wire/protocol\";\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isOptionalString = (value: unknown): boolean =>\n value === undefined || typeof value === \"string\";\n\nconst isPositiveSafeInteger = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isSafeInteger(value) && value > 0;\n\nconst isSessionCommand = (\n value: unknown,\n): value is StatewireClient.SessionCommand =>\n isRecord(value) &&\n isPositiveSafeInteger(value[\"seq\"]) &&\n isProtocol(value[\"protocol\"]) &&\n isProducer(value[\"produced\"]) &&\n typeof value[\"method\"] === \"string\" &&\n Array.isArray(value[\"params\"]);\n\nconst isSessionVerdict = (\n value: unknown,\n): value is StatewireClient.SessionVerdict =>\n isRecord(value) &&\n isPositiveSafeInteger(value[\"seq\"]) &&\n (value[\"type\"] === \"result\" ||\n value[\"type\"] === \"rejected\" ||\n value[\"type\"] === \"failed\" ||\n value[\"type\"] === \"crashed\" ||\n value[\"type\"] === \"expired\") &&\n isOptionalString(value[\"code\"]) &&\n isOptionalString(value[\"message\"]);\n\nconst isSendFailure = (\n value: unknown,\n): value is StatewireClient.SendFailure => {\n if (!isRecord(value)) return false;\n switch (value[\"fate\"]) {\n case \"rejected\":\n return (\n value[\"cause\"] === \"server\" &&\n isOptionalString(value[\"code\"]) &&\n isOptionalString(value[\"message\"])\n );\n case \"failed\":\n return value[\"cause\"] === \"server\" && isOptionalString(value[\"message\"]);\n case \"crashed\":\n case \"expired\":\n return value[\"cause\"] === \"server\";\n case \"aborted\":\n return (\n (value[\"cause\"] === \"unmount\" ||\n value[\"cause\"] === \"stream-gone\" ||\n value[\"cause\"] === \"session-lost\") &&\n (value[\"predecessorLost\"] === undefined ||\n value[\"predecessorLost\"] === true)\n );\n case \"lost\":\n return (\n value[\"cause\"] === \"unmount\" ||\n value[\"cause\"] === \"stream-gone\" ||\n value[\"cause\"] === \"session-lost\"\n );\n default:\n return false;\n }\n};\n\nconst isFailedCommand = (\n value: unknown,\n): value is StatewireClient.FailedCommand =>\n isRecord(value) &&\n isProtocol(value[\"protocol\"]) &&\n isProducer(value[\"produced\"]) &&\n typeof value[\"command\"] === \"string\" &&\n Array.isArray(value[\"params\"]) &&\n isSendFailure(value[\"failure\"]) &&\n typeof value[\"ts\"] === \"number\" &&\n Number.isFinite(value[\"ts\"]) &&\n isPositiveSafeInteger(value[\"seq\"]);\n\nconst isSessionLane = (value: unknown): value is StatewireClient.SessionLane =>\n isRecord(value) &&\n isPositiveSafeInteger(value[\"nextSeq\"]) &&\n Array.isArray(value[\"commands\"]) &&\n value[\"commands\"].every(isSessionCommand) &&\n (value[\"verdicts\"] === undefined ||\n (Array.isArray(value[\"verdicts\"]) &&\n value[\"verdicts\"].every(isSessionVerdict))) &&\n (value[\"failed\"] === undefined ||\n (Array.isArray(value[\"failed\"]) && value[\"failed\"].every(isFailedCommand)));\n\nconst isClientId = (value: unknown): value is string =>\n typeof value === \"string\" && value.length > 0;\n\nconst isSessionRecord = (\n value: unknown,\n): value is StatewireClient.SessionRecord =>\n isRecord(value) &&\n isClientId(value[\"clientId\"]) &&\n isRecord(value[\"lanes\"]) &&\n Object.keys(value[\"lanes\"]).every(isProtocol) &&\n Object.values(value[\"lanes\"]).every(isSessionLane);\n\nconst isProtocol = (value: unknown) =>\n value === undefined ||\n (typeof value === \"string\" && value !== \"*\" && protocolToken.test(value));\n\nconst isProducer = (value: unknown) => {\n if (value === undefined) return true;\n if (!isRecord(value) || !isRecord(value[\"wire\"])) return false;\n try {\n negotiationHeaders({\n wireVersion: value[\"wire\"] as StatewireProtocol.Range,\n applicationProtocols: value[\"protocols\"] as\n | readonly StatewireProtocol.Offer[]\n | \"*\",\n });\n return value[\"protocols\"] !== undefined;\n } catch {\n return false;\n }\n};\n\nconst invalid = (): never => {\n throw new Error(\"statewire: invalid stored session record\");\n};\n\n// Formats 1 and 2 held one lane: it lifts under the primary protocol, failed\n// entries under their own.\nconst liftLegacy = (\n value: Record<string, unknown>,\n protocol: string,\n): StatewireClient.SessionRecord => {\n const { clientId, nextSeq, commands, verdicts, failed } = value;\n const lane = {\n nextSeq,\n commands: [],\n ...(verdicts !== undefined && { verdicts }),\n };\n if (!isClientId(clientId) || !isSessionLane(lane) || !Array.isArray(commands))\n return invalid();\n const legacyCommands = commands as (StatewireClient.SessionCommand & {\n protocol?: string;\n })[];\n if (!legacyCommands.every(isSessionCommand)) return invalid();\n if (\n failed !== undefined &&\n (!Array.isArray(failed) || !failed.every(isFailedCommand))\n )\n return invalid();\n const lanes: Record<string, StatewireClient.SessionLane> = {\n [protocol]: {\n ...lane,\n commands: legacyCommands\n .filter((command) => (command.protocol ?? protocol) === protocol)\n .map(({ protocol: _protocol, ...command }) => command),\n },\n };\n for (const entry of failed ?? []) {\n const target = lanes[entry.protocol] ?? { nextSeq: 1, commands: [] };\n lanes[entry.protocol] = {\n ...target,\n failed: [...(target.failed ?? []), entry],\n };\n }\n return { clientId, lanes };\n};\n\nconst normalize = (\n parsed: unknown,\n protocol: string,\n): StatewireClient.SessionRecord => {\n if (!isRecord(parsed)) return invalid();\n const {\n statewireStorageVersion: format,\n savedAt: _savedAt,\n ...value\n } = parsed;\n if (format === 3) return isSessionRecord(value) ? value : invalid();\n if (format !== undefined && format !== 1 && format !== 2)\n throw new Error(\"statewire: unsupported session storage version\");\n const { ctxNextSeq: _ctxNextSeq, context: _context, ...legacy } = value;\n return liftLegacy(legacy, protocol);\n};\n\nconst decode = (\n raw: string | null,\n protocol: string,\n): StatewireClient.SessionRecord | null =>\n raw === null ? null : normalize(JSON.parse(raw), protocol);\n\nconst isEmpty = (record: StatewireClient.SessionRecord) =>\n Object.values(record.lanes).every(\n (lane) => lane.commands.length === 0 && !lane.failed?.length,\n );\n\nconst active = new WeakMap<\n KeyValueSessionStorage.Backend,\n Map<string, number>\n>();\n\nconst sweep = async (\n options: KeyValueSessionStorage.Options,\n currentKey: string,\n quota = false,\n) => {\n const { backend, retention, namespace = \"\" } = options;\n if (!retention || !backend.getAllKeys) return;\n const entries: { key: string; savedAt: number }[] = [];\n const candidate = (raw: string | null) => {\n if (raw === null) return undefined;\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n return undefined;\n }\n try {\n if (!isEmpty(normalize(value, DEFAULT_PROTOCOL))) return undefined;\n } catch {\n return undefined;\n }\n const savedAt =\n (value as Record<string, unknown>)[\"savedAt\"] ??\n (value as Record<string, unknown>)[\"updatedAt\"];\n return typeof savedAt === \"number\" && Number.isFinite(savedAt)\n ? savedAt\n : undefined;\n };\n for (const key of await backend.getAllKeys()) {\n if (\n !key.startsWith(namespace) ||\n key === currentKey ||\n active.get(backend)?.has(key)\n )\n continue;\n const savedAt = candidate(await backend.getItem(key));\n if (savedAt !== undefined) entries.push({ key, savedAt });\n }\n entries.sort((a, b) => b.savedAt - a.savedAt);\n const now = Date.now();\n let retained = 1;\n const quotaStart = Math.floor(entries.length / 2);\n for (const [index, entry] of entries.entries()) {\n const expired =\n retention.maxAgeMs !== undefined &&\n now - entry.savedAt > retention.maxAgeMs;\n const overflow =\n retention.maxEntries !== undefined && retained >= retention.maxEntries;\n if (expired || overflow || (quota && index >= quotaStart)) {\n const remove = async () => {\n if (active.get(backend)?.has(entry.key)) return;\n if (candidate(await backend.getItem(entry.key)) !== entry.savedAt)\n return;\n if (active.get(backend)?.has(entry.key)) return;\n await backend.removeItem(entry.key);\n };\n if (backend.withUnused) await backend.withUnused(entry.key, remove);\n else await remove();\n } else retained++;\n }\n};\n\nconst isQuotaError = (error: unknown) =>\n error instanceof Error && error.name === \"QuotaExceededError\";\n\nconst useKeyValueSessionStorage = (\n options: KeyValueSessionStorage.Options,\n): StatewireClient.SessionStorage => {\n const {\n backend,\n key,\n namespace = \"\",\n protocol = DEFAULT_PROTOCOL,\n migrate,\n retention: suppliedRetention,\n onError,\n } = options;\n const latestErrorHandler = useRef(onError);\n latestErrorHandler.current = onError;\n const reportError = useMemo(\n () => (error: unknown) => latestErrorHandler.current?.(error),\n [],\n );\n const retain = suppliedRetention !== undefined;\n const maxAgeMs = suppliedRetention?.maxAgeMs;\n const maxEntries = suppliedRetention?.maxEntries;\n const retention = useMemo(\n () =>\n retain\n ? {\n ...(maxAgeMs === undefined ? {} : { maxAgeMs }),\n ...(maxEntries === undefined ? {} : { maxEntries }),\n }\n : undefined,\n [retain, maxAgeMs, maxEntries],\n );\n const configured = useMemo(\n () => ({\n backend,\n key,\n namespace,\n ...(retention === undefined ? {} : { retention }),\n }),\n [backend, key, namespace, retention],\n );\n const storageKey = namespace + key;\n if (retention !== undefined) {\n if (!namespace)\n throw new Error(\"statewire: session retention requires a namespace\");\n if (!backend.getAllKeys)\n throw new Error(\"statewire: session retention requires getAllKeys\");\n if (\n retention.maxAgeMs !== undefined &&\n (!Number.isFinite(retention.maxAgeMs) || retention.maxAgeMs < 0)\n )\n throw new Error(\"statewire: invalid session retention maxAgeMs\");\n if (\n retention.maxEntries !== undefined &&\n (!Number.isSafeInteger(retention.maxEntries) || retention.maxEntries < 1)\n )\n throw new Error(\"statewire: invalid session retention maxEntries\");\n }\n const state = useMemo(() => {\n let raw: string | null | Promise<string | null>;\n try {\n raw = backend.getItem(storageKey);\n } catch (cause) {\n const error = wrapStorageError(cause);\n reportError(error);\n throw error;\n }\n const state = {\n record: null as StatewireClient.SessionRecord | null,\n ready: undefined as Promise<void> | undefined,\n queue: Promise.resolve(),\n pending: 0,\n failure: undefined as unknown,\n asynchronous: typeof raw !== \"string\" && raw !== null,\n hydrated: typeof raw === \"string\" || raw === null,\n };\n if (state.asynchronous) {\n state.ready = Promise.resolve(raw)\n .then((value) => {\n state.record = decode(value, protocol);\n state.hydrated = true;\n })\n .catch((cause: unknown) => {\n const error = wrapStorageError(cause);\n if (state.failure !== error) reportError(error);\n state.failure = error;\n throw error;\n });\n state.ready.catch(() => {});\n } else {\n try {\n state.record = decode(raw as string | null, protocol);\n } catch (cause) {\n const error = wrapStorageError(cause);\n reportError(error);\n throw error;\n }\n }\n return state;\n }, [backend, storageKey, protocol, reportError]);\n\n useEffect(() => {\n const entries = active.get(backend) ?? new Map<string, number>();\n active.set(backend, entries);\n entries.set(storageKey, (entries.get(storageKey) ?? 0) + 1);\n return () => {\n const count = entries.get(storageKey)! - 1;\n if (count === 0) entries.delete(storageKey);\n else entries.set(storageKey, count);\n };\n }, [backend, storageKey]);\n\n useEffect(() => {\n if (retention !== undefined)\n void sweep(configured, storageKey).catch((cause: unknown) => {\n const error = wrapStorageError(cause);\n state.failure = error;\n reportError(error);\n });\n }, [state, configured, storageKey, retention, reportError]);\n\n return useMemo(\n () => ({\n ...(state.ready === undefined ? {} : { ready: state.ready }),\n load: () => {\n if (state.failure !== undefined) throw state.failure;\n if (!state.hydrated)\n throw new Error(\n \"statewire: await session storage readiness before loading\",\n );\n if (state.asynchronous || state.pending > 0) return state.record;\n let raw: string | null | Promise<string | null>;\n try {\n raw = backend.getItem(storageKey);\n } catch (cause) {\n const error = wrapStorageError(cause);\n reportError(error);\n throw error;\n }\n if (typeof raw !== \"string\" && raw !== null)\n throw new Error(\n \"statewire: storage backend changed from synchronous to asynchronous\",\n );\n try {\n return decode(raw, protocol);\n } catch (cause) {\n const error = wrapStorageError(cause);\n reportError(error);\n throw error;\n }\n },\n save: (record: StatewireClient.SessionRecord) => {\n if (state.failure !== undefined) throw state.failure;\n if (!state.hydrated)\n throw new Error(\n \"statewire: await session storage readiness before saving\",\n );\n if (!isSessionRecord(record))\n throw new Error(\"statewire: invalid session record\");\n const encoded = JSON.stringify({\n ...record,\n statewireStorageVersion: 3,\n savedAt: Date.now(),\n });\n state.record = record;\n const recoverQuota = async (error: unknown) => {\n if (!isQuotaError(error) || retention === undefined) throw error;\n await sweep(configured, storageKey, true);\n await backend.setItem(storageKey, encoded);\n };\n const write = async () => {\n try {\n await backend.setItem(storageKey, encoded);\n } catch (error) {\n await recoverQuota(error);\n }\n };\n if (!state.asynchronous && state.pending === 0) {\n let result: void | Promise<void>;\n try {\n result = backend.setItem(storageKey, encoded);\n } catch (error) {\n if (!isQuotaError(error) || retention === undefined) {\n state.failure = wrapStorageError(error);\n reportError(state.failure);\n throw state.failure;\n }\n result = recoverQuota(error);\n }\n if (result === undefined) return;\n state.pending++;\n state.queue = result;\n } else {\n state.pending++;\n state.queue = state.queue.then(() => state.ready).then(write);\n }\n state.queue = state.queue\n .catch((cause: unknown) => {\n const error = wrapStorageError(cause);\n if (state.failure !== error) reportError(error);\n state.failure = error;\n throw error;\n })\n .finally(() => {\n state.pending--;\n });\n state.queue.catch(() => {});\n },\n flush: () => {\n if (state.failure !== undefined) throw state.failure;\n if (!state.asynchronous && state.pending === 0) return;\n return (async () => {\n await state.ready;\n for (;;) {\n const queue = state.queue;\n await queue;\n if (queue === state.queue) return;\n }\n })();\n },\n ...(migrate === undefined ? {} : { migrate }),\n }),\n [\n state,\n backend,\n storageKey,\n protocol,\n migrate,\n retention,\n configured,\n reportError,\n ],\n );\n};\n\n/** Persist sessions through a synchronous or asynchronous string storage backend. */\nexport const KeyValueSessionStorage = resource(useKeyValueSessionStorage);\n\nexport namespace KeyValueSessionStorage {\n export type Backend = {\n getItem: (key: string) => string | null | Promise<string | null>;\n setItem: (key: string, value: string) => void | Promise<void>;\n removeItem: (key: string) => void | Promise<void>;\n getAllKeys?: () => readonly string[] | Promise<readonly string[]>;\n /** Runs cleanup under exclusive access, skipping keys in use by another runtime. */\n withUnused?: (key: string, action: () => Promise<void>) => Promise<void>;\n };\n export type Options = {\n backend: Backend;\n key: string;\n namespace?: string;\n /** The lane that sessions saved in a single-lane format lift into; defaults to the client's default protocol. */\n protocol?: string;\n migrate?: StatewireClient.SessionStorage[\"migrate\"];\n retention?: { maxAgeMs?: number; maxEntries?: number };\n onError?: (error: unknown) => void;\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote.d.ts","names":[],"sources":["../../src/transports/remote.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"remote.d.ts","names":[],"sources":["../../src/transports/remote.ts"],"mappings":";;;;;cAgBa,qBACX;EACE;EACA,YAAY,YAAY,gBAAgB;EACxC;IACE,yBAEJ,SAAS,UACT,UAAU,SAAS,UAAU,KAAK,yBAAyB,eAC1D"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ProtocolContext } from "../client/sessionStore.js";
|
|
2
|
-
import { discardFailed, documentSource, failedCommands, invokeProtocol, retryFailed,
|
|
2
|
+
import { discardFailed, documentSource, failedCommands, invokeProtocol, retryFailed, setTransport, useStatewireSession } from "../client/session.js";
|
|
3
3
|
import { useContext, useEffect } from "@assistant-ui/tap/react-shim";
|
|
4
4
|
//#region src/transports/remote.ts
|
|
5
5
|
const useStatewireRemote = (options, useLink) => {
|
|
@@ -17,17 +17,12 @@ const useStatewireRemote = (options, useLink) => {
|
|
|
17
17
|
return s.selection;
|
|
18
18
|
},
|
|
19
19
|
invoke: (protocol, method, params) => invokeProtocol(s, protocol, method, params),
|
|
20
|
-
updateContext: (ops) => updateContext(s, ops),
|
|
21
20
|
commands: s.commands,
|
|
22
21
|
connection: conn.connection,
|
|
23
22
|
source: s.source,
|
|
24
|
-
get durableSeq() {
|
|
25
|
-
return s.durableSeq;
|
|
26
|
-
},
|
|
27
23
|
get isBusy() {
|
|
28
24
|
return !s.idle;
|
|
29
25
|
},
|
|
30
|
-
setContext: (value) => setContext(s, value),
|
|
31
26
|
failures: {
|
|
32
27
|
list: () => failedCommands(s),
|
|
33
28
|
retry: (entry) => retryFailed(s, entry),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote.js","names":["useContext","useEffect","ProtocolContext","Statewire","documentSource","invokeProtocol","
|
|
1
|
+
{"version":3,"file":"remote.js","names":["useContext","useEffect","ProtocolContext","Statewire","documentSource","invokeProtocol","discardFailed","failedCommands","retryFailed","setTransport","useStatewireSession","StatewireSessionOptions","StatewireClient","RemoteLink","StatewireRemoteProps","useStatewireRemote","url","onChange","connection","Connection","onDone","options","TOptions","useLink","ctx","inherited","configured","s","conn","state","canonical","documents","selection","invoke","protocol","method","params","commands","source","isBusy","idle","failures","list","retry","entry","discard"],"sources":["../../src/transports/remote.ts"],"sourcesContent":["import { useContext, useEffect } from \"react\";\nimport { ProtocolContext } from \"../client/sessionStore\";\nimport type { Statewire } from \"../types\";\nimport {\n documentSource,\n invokeProtocol,\n discardFailed,\n failedCommands,\n retryFailed,\n setTransport,\n useStatewireSession,\n} from \"../client/session\";\nimport type { StatewireSessionOptions } from \"../client/session\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { RemoteLink, StatewireRemoteProps } from \"./sse\";\n\nexport const useStatewireRemote = <\n TOptions extends {\n url: string;\n onChange?: (connection: StatewireClient.Connection) => void;\n onDone?: () => void;\n } & StatewireSessionOptions,\n>(\n options: TOptions,\n useLink: (options: TOptions, ctx: StatewireRemoteProps) => RemoteLink,\n): Statewire<any, any> => {\n const inherited = useContext(ProtocolContext);\n const configured = { ...inherited, ...options };\n const s = useStatewireSession(configured);\n const conn = useLink(configured, s.ctx);\n useEffect(() => setTransport(s, conn), [s, conn]);\n\n return {\n state: s.canonical,\n documents: documentSource(s),\n get selection() {\n return s.selection;\n },\n invoke: (protocol, method, params) =>\n invokeProtocol(s, protocol, method, params),\n commands: s.commands,\n connection: conn.connection,\n source: s.source,\n get isBusy() {\n return !s.idle;\n },\n failures: {\n list: () => failedCommands(s),\n retry: (entry) => retryFailed(s, entry),\n discard: (entry) => discardFailed(s, entry),\n },\n };\n};\n"],"mappings":";;;;AAgBA,MAAae,sBAOXM,SACAE,YACwB;CAExB,MAAMG,aAAa;EAAE,GADH1B,WAAWE,eACLuB;EAAW,GAAGJ;CAAQ;CAC9C,MAAMM,IAAIjB,oBAAoBgB,UAAU;CACxC,MAAME,OAAOL,QAAQG,YAAYC,EAAEH,GAAG;CACtCvB,gBAAgBQ,aAAakB,GAAGC,IAAI,GAAG,CAACD,GAAGC,IAAI,CAAC;CAEhD,OAAO;EACLC,OAAOF,EAAEG;EACTC,WAAW3B,eAAeuB,CAAC;EAC3B,IAAIK,YAAY;GACd,OAAOL,EAAEK;EACX;EACAC,SAASC,UAAUC,QAAQC,WACzB/B,eAAesB,GAAGO,UAAUC,QAAQC,MAAM;EAC5CC,UAAUV,EAAEU;EACZnB,YAAYU,KAAKV;EACjBoB,QAAQX,EAAEW;EACV,IAAIC,SAAS;GACX,OAAO,CAACZ,EAAEa;EACZ;EACAC,UAAU;GACRC,YAAYnC,eAAeoB,CAAC;GAC5BgB,QAAQC,UAAUpC,YAAYmB,GAAGiB,KAAK;GACtCC,UAAUD,YAAUtC,cAAcqB,GAAGiB,OAAK;EAC5C;CACF;AACF"}
|
package/dist/transports/sse.d.ts
CHANGED
|
@@ -6,11 +6,8 @@ import { ResourceElement } from "@assistant-ui/tap";
|
|
|
6
6
|
//#region src/transports/sse.d.ts
|
|
7
7
|
/** A client frame's lanes: stamped statements, strictly consecutive per lane. */
|
|
8
8
|
type StatewireFrame = {
|
|
9
|
-
ctx?: {
|
|
10
|
-
ops: unknown[];
|
|
11
|
-
seq: number;
|
|
12
|
-
}[];
|
|
13
9
|
cmd?: {
|
|
10
|
+
protocol: string;
|
|
14
11
|
method: string;
|
|
15
12
|
params: unknown[];
|
|
16
13
|
meta?: unknown;
|
|
@@ -20,7 +17,7 @@ type StatewireFrame = {
|
|
|
20
17
|
type StatewireRemoteProps = {
|
|
21
18
|
beforeAttach?: () => void | Promise<void>;
|
|
22
19
|
clientId: string;
|
|
23
|
-
/** Lanes to ride the attach frame:
|
|
20
|
+
/** Lanes to ride the attach frame: ephemeral-lane statements, plus durable cmds on no-lease supersession; records the included entries. */
|
|
24
21
|
takeAttachLanes: () => StatewireFrame | null;
|
|
25
22
|
onHello: (args: {
|
|
26
23
|
ops: unknown[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.d.ts","names":[],"sources":["../../src/transports/sse.ts"],"mappings":";;;;;;;KA0BY;EACV;
|
|
1
|
+
{"version":3,"file":"sse.d.ts","names":[],"sources":["../../src/transports/sse.ts"],"mappings":";;;;;;;KA0BY;EACV;IACE;IACA;IACA;IACA;IACA;;;KAIQ;EACV,4BAA4B;EAC5B;;EAEA,uBAAuB;EACvB,UAAU;IAAQ;IAAgB,KAAK;;EACvC,QAAQ;IAAQ;IAAgB,MAAM;;EACtC,SAAS,MAAM;EACf,YAAY,KAAK;EACjB,SAAS;EACT;EACA,WAAW,MAAM,cAAc;;KAGrB;EACN;;EACA;EAAiB,KAAK;;EACtB;;EACA;;KAEM,kBAAkB,gBAAgB;;KAGlC;EACV,gBAAgB,OAAO;EACvB,YAAY,gBAAgB;;EAE5B;EACA,OAAO,OAAO,mBAAmB,QAAQ;;cAoP9B,gBACX,cACA,kBAAkB,UAAU,WAAW,UAAU,UAEjD,SAAS,gBAAgB,gBACtB,gBAAgB,UAAU,oBAAoB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.js","names":["flushTapSync","resource","ResourceElement","createSseParser","timing","settleFin","classify","handleEnvelope","resolveHeaders","useLink","validateRefusalSyn","AttemptOutcome","Conn","StatewireCmd","StatewireEnvelope","StatewireSyn","Statewire","StatewireClient","StatewireHost","useStatewireRemote","negotiationHeaders","parseNegotiation","StatewireFrame","ctx","ops","seq","cmd","method","params","meta","StatewireRemoteProps","beforeAttach","Promise","clientId","takeAttachLanes","onHello","args","syn","onOps","cmds","onCmds","onRefusal","onIdle","level","onDetach","onFinish","Fin","StatewireSubmitResult","type","ConnectionState","RemoteLink","storageFailed","error","Error","connection","Connection","parked","send","frame","LEASE_HEADER","baseUrl","options","HttpOptions","url","replace","withExtra","headers","Headers","extra","Record","merged","name","value","Object","entries","set","timedFetch","input","init","RequestInit","signal","AbortSignal","timeout","Response","fetch","globalThis","consume","c","reader","ReadableStreamDefaultReader","Uint8Array","heartbeat","AbortController","dead","decoder","TextDecoder","parse","timer","setTimeout","abort","heartbeatTimeoutMs","result","ReadableStreamReadResult","read","clearTimeout","done","data","decode","stream","env","JSON","attemptStream","persistence","aborted","lease","authStale","has","negotiation","lanes","body","undefined","stringify","headerTimer","res","accept","cache","any","ok","clone","json","catch","fin","httpFin","get","getReader","cancel","postFrame","lifetime","retryAfterMs","header","trim","test","retry","Number","isSafeInteger","reason","status","message","code","refusalSyn","sendFrame","headerRetry","useSseLink","attemptOnce","SyntaxError","startsWith","useStatewireHttp","StatewireHttp","Commands","TState","TCommands"],"sources":["../../src/transports/sse.ts"],"sourcesContent":["import { flushTapSync, resource } from \"@assistant-ui/tap\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\nimport { createSseParser } from \"./sse-parser\";\nimport { timing } from \"../client/timing\";\nimport {\n settleFin,\n classify,\n handleEnvelope,\n resolveHeaders,\n useLink,\n validateRefusalSyn,\n} from \"../client/connection\";\nimport type {\n AttemptOutcome,\n Conn,\n StatewireCmd,\n StatewireEnvelope,\n StatewireSyn,\n} from \"../client/connection\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\nimport { useStatewireRemote } from \"./remote\";\nimport { negotiationHeaders, parseNegotiation } from \"../wire/protocol\";\n\n/** A client frame's lanes: stamped statements, strictly consecutive per lane. */\nexport type StatewireFrame = {\n ctx?: { ops: unknown[]; seq: number }[];\n cmd?: { method: string; params: unknown[]; meta?: unknown; seq: number }[];\n};\n\nexport type StatewireRemoteProps = {\n beforeAttach?: () => void | Promise<void>;\n clientId: string;\n /** Lanes to ride the attach frame: the context restatement, plus cmds on no-lease supersession; records the included seqs. */\n takeAttachLanes: () => StatewireFrame | null;\n onHello: (args: { ops: unknown[]; syn: StatewireSyn }) => void;\n onOps: (args: { ops: unknown[]; cmds: StatewireCmd[] }) => void;\n onCmds: (cmds: StatewireCmd[]) => void;\n onRefusal: (syn: StatewireSyn) => void;\n onIdle: (level: boolean) => void;\n onDetach: () => void;\n onFinish: (args: StatewireHost.Fin) => void;\n};\n\nexport type StatewireSubmitResult =\n | { type: \"ok\" }\n | { type: \"refusal\"; syn: StatewireSyn }\n | { type: \"stale-lease\" }\n | { type: \"no-lease\" };\n\nexport type ConnectionState = StatewireClient.ConnectionState;\n\n/** The live wire a remote session drives: connection status plus frame submission. */\nexport type RemoteLink = {\n storageFailed: (error: Error) => void;\n connection: StatewireClient.Connection;\n /** A deferred first attach still waiting; `reconnect()` releases it. */\n parked: boolean;\n send: (frame: StatewireFrame) => Promise<StatewireSubmitResult>;\n};\n\nconst LEASE_HEADER = \"Statewire-Lease\";\n\nconst baseUrl = (options: StatewireClient.HttpOptions) =>\n options.url.replace(/\\/$/, \"\");\n\nconst withExtra = (headers: Headers, extra: Record<string, string>) => {\n const merged = new Headers(headers);\n for (const [name, value] of Object.entries(extra)) merged.set(name, value);\n return merged;\n};\n\nconst timedFetch = async (\n options: StatewireClient.HttpOptions,\n input: string,\n init: RequestInit & { signal: AbortSignal },\n timeout: AbortSignal,\n): Promise<Response> => {\n try {\n return await (options.fetch ?? globalThis.fetch)(input, init);\n } catch {\n throw classify(timeout);\n }\n};\n\nconst consume = async (\n c: Conn,\n reader: ReadableStreamDefaultReader<Uint8Array>,\n heartbeat: AbortController,\n dead: () => boolean,\n): Promise<AttemptOutcome> => {\n const decoder = new TextDecoder();\n const parse = createSseParser();\n for (;;) {\n const timer = setTimeout(\n () => heartbeat.abort(),\n timing.heartbeatTimeoutMs,\n );\n let result: ReadableStreamReadResult<Uint8Array>;\n try {\n result = await reader.read();\n } catch {\n throw classify(heartbeat.signal);\n } finally {\n clearTimeout(timer);\n }\n if (result.done) return \"ended\";\n for (const data of parse(decoder.decode(result.value, { stream: true }))) {\n if (dead()) return \"ended\";\n const env = JSON.parse(data) as StatewireEnvelope;\n const done = flushTapSync(() => handleEnvelope(c, env));\n if (done) return done;\n }\n }\n};\n\nconst attemptStream = async (\n c: Conn,\n options: StatewireClient.HttpOptions,\n abort: AbortController,\n): Promise<AttemptOutcome> => {\n const persistence = c.ctx.beforeAttach?.();\n if (persistence) await persistence;\n if (abort.signal.aborted) return \"ended\";\n c.lease = null;\n const headers = await resolveHeaders(options.headers, c.authStale);\n for (const [name, value] of Object.entries(negotiationHeaders(options))) {\n if (!headers.has(name)) headers.set(name, value);\n }\n c.negotiation = parseNegotiation(headers);\n c.authStale = false;\n const lanes = flushTapSync(() => c.ctx.takeAttachLanes());\n const body = lanes === null ? undefined : JSON.stringify(lanes);\n const heartbeat = new AbortController();\n const headerTimer = setTimeout(\n () => heartbeat.abort(),\n timing.heartbeatTimeoutMs,\n );\n let res: Response;\n try {\n res = await timedFetch(\n options,\n `${baseUrl(options)}/stream`,\n {\n method: body === undefined ? \"GET\" : \"POST\",\n headers: withExtra(headers, {\n \"content-type\": \"application/json\",\n \"Statewire-Client-Id\": c.ctx.clientId,\n accept: \"text/event-stream\",\n }),\n ...(body === undefined ? {} : { body }),\n cache: \"no-store\",\n signal: AbortSignal.any([abort.signal, heartbeat.signal]),\n },\n heartbeat.signal,\n );\n } finally {\n clearTimeout(headerTimer);\n }\n if (!res.ok) {\n const body = await res\n .clone()\n .json()\n .catch(() => null);\n return (\n flushTapSync(() =>\n body?.fin === undefined\n ? settleFin(c, httpFin(res))\n : handleEnvelope(c, body),\n ) ?? \"stop\"\n );\n }\n if (!res.body)\n throw new Error(\"statewire: protocol error: stream response has no body\");\n c.lease = res.headers.get(LEASE_HEADER);\n const reader = res.body.getReader();\n try {\n return await consume(c, reader, heartbeat, () => abort.signal.aborted);\n } finally {\n reader.cancel().catch(() => {});\n }\n};\n\nconst postFrame = async (\n c: Conn,\n options: StatewireClient.HttpOptions,\n lease: string,\n frame: StatewireFrame,\n timeout: AbortSignal,\n): Promise<Response> =>\n timedFetch(\n options,\n `${baseUrl(options)}/frames`,\n {\n method: \"POST\",\n headers: withExtra(new Headers(), {\n \"content-type\": \"application/json\",\n [LEASE_HEADER]: lease,\n }),\n body: JSON.stringify(frame),\n signal: AbortSignal.any([\n c.lifetime?.signal ?? AbortSignal.abort(),\n timeout,\n ]),\n },\n timeout,\n );\n\n// Delta-seconds only; anything else reads as absent.\nconst retryAfterMs = (res: Response): number | null => {\n const header = res.headers.get(\"retry-after\")?.trim();\n if (header === undefined || !/^\\d+$/.test(header)) return null;\n const retry = Number(header) * 1000;\n return Number.isSafeInteger(retry) ? retry : null;\n};\n\nconst httpFin = (res: Response): StatewireHost.Fin => ({\n reason:\n res.status === 401\n ? \"unauthorized\"\n : res.status === 403\n ? \"forbidden\"\n : res.status === 429 || res.status === 503\n ? \"reconnect\"\n : res.status >= 400 && res.status < 500\n ? \"protocol-error\"\n : \"error\",\n status: res.status,\n message: `HTTP ${res.status}`,\n ...(res.status === 429 || res.status === 503 ? { code: \"overloaded\" } : {}),\n ...(retryAfterMs(res) !== null ? { retry: retryAfterMs(res)! } : {}),\n});\n\nconst refusalSyn = async (res: Response): Promise<StatewireSyn> => {\n const body = (await res.json().catch(() => null)) as {\n syn?: StatewireSyn;\n } | null;\n const syn = body?.syn;\n if (typeof syn !== \"object\" || syn === null) {\n throw new Error(`HTTP ${res.status}`);\n }\n return validateRefusalSyn(syn);\n};\n\nconst sendFrame = async (\n c: Conn,\n options: StatewireClient.HttpOptions,\n frame: StatewireFrame,\n): Promise<StatewireSubmitResult> => {\n const lease = c.lease;\n if (lease === null) return { type: \"no-lease\" };\n const timeout = AbortSignal.timeout(timing.heartbeatTimeoutMs);\n const res = await postFrame(c, options, lease, frame, timeout);\n if (res.ok) return { type: \"ok\" };\n if (res.status === 429 || res.status === 409) {\n // The syn body retry wins; Retry-After covers 429s minted below the host.\n const headerRetry = res.status === 429 ? retryAfterMs(res) : null;\n const syn: StatewireSyn = await refusalSyn(res).catch((error: unknown) => {\n if (headerRetry === null) throw error;\n return { retry: headerRetry };\n });\n if (syn.retry === undefined && headerRetry !== null)\n syn.retry = headerRetry;\n return { type: \"refusal\", syn };\n }\n if (res.status === 423) return { type: \"stale-lease\" };\n flushTapSync(() => settleFin(c, httpFin(res)));\n c.abort?.abort();\n throw new Error(`HTTP ${res.status}`);\n};\n\nconst useSseLink = (\n options: StatewireClient.HttpOptions,\n ctx: StatewireRemoteProps,\n): RemoteLink =>\n useLink({\n ...options,\n ctx,\n attemptOnce: (c, abort) => attemptStream(c, options, abort),\n send: async (c, frame) => {\n try {\n return await sendFrame(c, options, frame);\n } catch (error) {\n if (\n error instanceof SyntaxError ||\n (error instanceof Error &&\n error.message.startsWith(\"statewire: protocol error:\"))\n ) {\n flushTapSync(() =>\n settleFin(c, { reason: \"protocol-error\", message: error.message }),\n );\n c.abort?.abort();\n }\n throw error;\n }\n },\n });\n\nconst useStatewireHttp = (\n options: StatewireClient.HttpOptions,\n): Statewire<any, any> => useStatewireRemote(options, useSseLink);\n\nexport const StatewireHttp = resource(useStatewireHttp) as <\n TState = any,\n TCommands extends Statewire.Commands = Statewire.Commands,\n>(\n options: StatewireClient.HttpOptions,\n) => ResourceElement<Statewire<TState | undefined, TCommands>>;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sse.js","names":["flushTapSync","resource","ResourceElement","createSseParser","timing","settleFin","classify","handleEnvelope","resolveHeaders","useLink","validateRefusalSyn","AttemptOutcome","Conn","StatewireCmd","StatewireEnvelope","StatewireSyn","Statewire","StatewireClient","StatewireHost","useStatewireRemote","negotiationHeaders","parseNegotiation","StatewireFrame","cmd","protocol","method","params","meta","seq","StatewireRemoteProps","beforeAttach","Promise","clientId","takeAttachLanes","onHello","args","ops","syn","onOps","cmds","onCmds","onRefusal","onIdle","level","onDetach","onFinish","Fin","StatewireSubmitResult","type","ConnectionState","RemoteLink","storageFailed","error","Error","connection","Connection","parked","send","frame","LEASE_HEADER","baseUrl","options","HttpOptions","url","replace","withExtra","headers","Headers","extra","Record","merged","name","value","Object","entries","set","timedFetch","input","init","RequestInit","signal","AbortSignal","timeout","Response","fetch","globalThis","consume","c","reader","ReadableStreamDefaultReader","Uint8Array","heartbeat","AbortController","dead","decoder","TextDecoder","parse","timer","setTimeout","abort","heartbeatTimeoutMs","result","ReadableStreamReadResult","read","clearTimeout","done","data","decode","stream","env","JSON","attemptStream","persistence","ctx","aborted","lease","authStale","has","negotiation","lanes","body","undefined","stringify","headerTimer","res","accept","cache","any","ok","clone","json","catch","fin","httpFin","get","getReader","cancel","postFrame","lifetime","retryAfterMs","header","trim","test","retry","Number","isSafeInteger","reason","status","message","code","refusalSyn","sendFrame","headerRetry","useSseLink","attemptOnce","SyntaxError","startsWith","useStatewireHttp","StatewireHttp","Commands","TState","TCommands"],"sources":["../../src/transports/sse.ts"],"sourcesContent":["import { flushTapSync, resource } from \"@assistant-ui/tap\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\nimport { createSseParser } from \"./sse-parser\";\nimport { timing } from \"../client/timing\";\nimport {\n settleFin,\n classify,\n handleEnvelope,\n resolveHeaders,\n useLink,\n validateRefusalSyn,\n} from \"../client/connection\";\nimport type {\n AttemptOutcome,\n Conn,\n StatewireCmd,\n StatewireEnvelope,\n StatewireSyn,\n} from \"../client/connection\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\nimport { useStatewireRemote } from \"./remote\";\nimport { negotiationHeaders, parseNegotiation } from \"../wire/protocol\";\n\n/** A client frame's lanes: stamped statements, strictly consecutive per lane. */\nexport type StatewireFrame = {\n cmd?: {\n protocol: string;\n method: string;\n params: unknown[];\n meta?: unknown;\n seq: number;\n }[];\n};\n\nexport type StatewireRemoteProps = {\n beforeAttach?: () => void | Promise<void>;\n clientId: string;\n /** Lanes to ride the attach frame: ephemeral-lane statements, plus durable cmds on no-lease supersession; records the included entries. */\n takeAttachLanes: () => StatewireFrame | null;\n onHello: (args: { ops: unknown[]; syn: StatewireSyn }) => void;\n onOps: (args: { ops: unknown[]; cmds: StatewireCmd[] }) => void;\n onCmds: (cmds: StatewireCmd[]) => void;\n onRefusal: (syn: StatewireSyn) => void;\n onIdle: (level: boolean) => void;\n onDetach: () => void;\n onFinish: (args: StatewireHost.Fin) => void;\n};\n\nexport type StatewireSubmitResult =\n | { type: \"ok\" }\n | { type: \"refusal\"; syn: StatewireSyn }\n | { type: \"stale-lease\" }\n | { type: \"no-lease\" };\n\nexport type ConnectionState = StatewireClient.ConnectionState;\n\n/** The live wire a remote session drives: connection status plus frame submission. */\nexport type RemoteLink = {\n storageFailed: (error: Error) => void;\n connection: StatewireClient.Connection;\n /** A deferred first attach still waiting; `reconnect()` releases it. */\n parked: boolean;\n send: (frame: StatewireFrame) => Promise<StatewireSubmitResult>;\n};\n\nconst LEASE_HEADER = \"Statewire-Lease\";\n\nconst baseUrl = (options: StatewireClient.HttpOptions) =>\n options.url.replace(/\\/$/, \"\");\n\nconst withExtra = (headers: Headers, extra: Record<string, string>) => {\n const merged = new Headers(headers);\n for (const [name, value] of Object.entries(extra)) merged.set(name, value);\n return merged;\n};\n\nconst timedFetch = async (\n options: StatewireClient.HttpOptions,\n input: string,\n init: RequestInit & { signal: AbortSignal },\n timeout: AbortSignal,\n): Promise<Response> => {\n try {\n return await (options.fetch ?? globalThis.fetch)(input, init);\n } catch {\n throw classify(timeout);\n }\n};\n\nconst consume = async (\n c: Conn,\n reader: ReadableStreamDefaultReader<Uint8Array>,\n heartbeat: AbortController,\n dead: () => boolean,\n): Promise<AttemptOutcome> => {\n const decoder = new TextDecoder();\n const parse = createSseParser();\n for (;;) {\n const timer = setTimeout(\n () => heartbeat.abort(),\n timing.heartbeatTimeoutMs,\n );\n let result: ReadableStreamReadResult<Uint8Array>;\n try {\n result = await reader.read();\n } catch {\n throw classify(heartbeat.signal);\n } finally {\n clearTimeout(timer);\n }\n if (result.done) return \"ended\";\n for (const data of parse(decoder.decode(result.value, { stream: true }))) {\n if (dead()) return \"ended\";\n const env = JSON.parse(data) as StatewireEnvelope;\n const done = flushTapSync(() => handleEnvelope(c, env));\n if (done) return done;\n }\n }\n};\n\nconst attemptStream = async (\n c: Conn,\n options: StatewireClient.HttpOptions,\n abort: AbortController,\n): Promise<AttemptOutcome> => {\n const persistence = c.ctx.beforeAttach?.();\n if (persistence) await persistence;\n if (abort.signal.aborted) return \"ended\";\n c.lease = null;\n const headers = await resolveHeaders(options.headers, c.authStale);\n for (const [name, value] of Object.entries(negotiationHeaders(options))) {\n if (!headers.has(name)) headers.set(name, value);\n }\n c.negotiation = parseNegotiation(headers);\n c.authStale = false;\n const lanes = flushTapSync(() => c.ctx.takeAttachLanes());\n const body = lanes === null ? undefined : JSON.stringify(lanes);\n const heartbeat = new AbortController();\n const headerTimer = setTimeout(\n () => heartbeat.abort(),\n timing.heartbeatTimeoutMs,\n );\n let res: Response;\n try {\n res = await timedFetch(\n options,\n `${baseUrl(options)}/stream`,\n {\n method: body === undefined ? \"GET\" : \"POST\",\n headers: withExtra(headers, {\n \"content-type\": \"application/json\",\n \"Statewire-Client-Id\": c.ctx.clientId,\n accept: \"text/event-stream\",\n }),\n ...(body === undefined ? {} : { body }),\n cache: \"no-store\",\n signal: AbortSignal.any([abort.signal, heartbeat.signal]),\n },\n heartbeat.signal,\n );\n } finally {\n clearTimeout(headerTimer);\n }\n if (!res.ok) {\n const body = await res\n .clone()\n .json()\n .catch(() => null);\n return (\n flushTapSync(() =>\n body?.fin === undefined\n ? settleFin(c, httpFin(res))\n : handleEnvelope(c, body),\n ) ?? \"stop\"\n );\n }\n if (!res.body)\n throw new Error(\"statewire: protocol error: stream response has no body\");\n c.lease = res.headers.get(LEASE_HEADER);\n const reader = res.body.getReader();\n try {\n return await consume(c, reader, heartbeat, () => abort.signal.aborted);\n } finally {\n reader.cancel().catch(() => {});\n }\n};\n\nconst postFrame = async (\n c: Conn,\n options: StatewireClient.HttpOptions,\n lease: string,\n frame: StatewireFrame,\n timeout: AbortSignal,\n): Promise<Response> =>\n timedFetch(\n options,\n `${baseUrl(options)}/frames`,\n {\n method: \"POST\",\n headers: withExtra(new Headers(), {\n \"content-type\": \"application/json\",\n [LEASE_HEADER]: lease,\n }),\n body: JSON.stringify(frame),\n signal: AbortSignal.any([\n c.lifetime?.signal ?? AbortSignal.abort(),\n timeout,\n ]),\n },\n timeout,\n );\n\n// Delta-seconds only; anything else reads as absent.\nconst retryAfterMs = (res: Response): number | null => {\n const header = res.headers.get(\"retry-after\")?.trim();\n if (header === undefined || !/^\\d+$/.test(header)) return null;\n const retry = Number(header) * 1000;\n return Number.isSafeInteger(retry) ? retry : null;\n};\n\nconst httpFin = (res: Response): StatewireHost.Fin => ({\n reason:\n res.status === 401\n ? \"unauthorized\"\n : res.status === 403\n ? \"forbidden\"\n : res.status === 429 || res.status === 503\n ? \"reconnect\"\n : res.status >= 400 && res.status < 500\n ? \"protocol-error\"\n : \"error\",\n status: res.status,\n message: `HTTP ${res.status}`,\n ...(res.status === 429 || res.status === 503 ? { code: \"overloaded\" } : {}),\n ...(retryAfterMs(res) !== null ? { retry: retryAfterMs(res)! } : {}),\n});\n\nconst refusalSyn = async (res: Response): Promise<StatewireSyn> => {\n const body = (await res.json().catch(() => null)) as {\n syn?: StatewireSyn;\n } | null;\n const syn = body?.syn;\n if (typeof syn !== \"object\" || syn === null) {\n throw new Error(`HTTP ${res.status}`);\n }\n return validateRefusalSyn(syn);\n};\n\nconst sendFrame = async (\n c: Conn,\n options: StatewireClient.HttpOptions,\n frame: StatewireFrame,\n): Promise<StatewireSubmitResult> => {\n const lease = c.lease;\n if (lease === null) return { type: \"no-lease\" };\n const timeout = AbortSignal.timeout(timing.heartbeatTimeoutMs);\n const res = await postFrame(c, options, lease, frame, timeout);\n if (res.ok) return { type: \"ok\" };\n if (res.status === 429 || res.status === 409) {\n // The syn body retry wins; Retry-After covers 429s minted below the host.\n const headerRetry = res.status === 429 ? retryAfterMs(res) : null;\n const syn: StatewireSyn = await refusalSyn(res).catch((error: unknown) => {\n if (headerRetry === null) throw error;\n return { retry: headerRetry };\n });\n if (syn.retry === undefined && headerRetry !== null)\n syn.retry = headerRetry;\n return { type: \"refusal\", syn };\n }\n if (res.status === 423) return { type: \"stale-lease\" };\n flushTapSync(() => settleFin(c, httpFin(res)));\n c.abort?.abort();\n throw new Error(`HTTP ${res.status}`);\n};\n\nconst useSseLink = (\n options: StatewireClient.HttpOptions,\n ctx: StatewireRemoteProps,\n): RemoteLink =>\n useLink({\n ...options,\n ctx,\n attemptOnce: (c, abort) => attemptStream(c, options, abort),\n send: async (c, frame) => {\n try {\n return await sendFrame(c, options, frame);\n } catch (error) {\n if (\n error instanceof SyntaxError ||\n (error instanceof Error &&\n error.message.startsWith(\"statewire: protocol error:\"))\n ) {\n flushTapSync(() =>\n settleFin(c, { reason: \"protocol-error\", message: error.message }),\n );\n c.abort?.abort();\n }\n throw error;\n }\n },\n });\n\nconst useStatewireHttp = (\n options: StatewireClient.HttpOptions,\n): Statewire<any, any> => useStatewireRemote(options, useSseLink);\n\nexport const StatewireHttp = resource(useStatewireHttp) as <\n TState = any,\n TCommands extends Statewire.Commands = Statewire.Commands,\n>(\n options: StatewireClient.HttpOptions,\n) => ResourceElement<Statewire<TState | undefined, TCommands>>;\n"],"mappings":"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"}
|
|
@@ -9,11 +9,11 @@ declare const tick: () => Promise<void>;
|
|
|
9
9
|
type MockTransport<TState> = {
|
|
10
10
|
/** Pass as the `transport:` option of useStatewire / Harness. */
|
|
11
11
|
transport: ResourceElement<Statewire<TState | undefined, any>>;
|
|
12
|
-
/** Captured statements in arrival order
|
|
12
|
+
/** Captured statements in arrival order. */
|
|
13
13
|
commands: {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
protocol: string;
|
|
15
|
+
method: string;
|
|
16
|
+
params: unknown[];
|
|
17
17
|
}[];
|
|
18
18
|
/** Replace the replicated state and broadcast it as a root snapshot op. */
|
|
19
19
|
setState: (state: TState) => Promise<void>;
|
|
@@ -28,7 +28,9 @@ type MockTransport<TState> = {
|
|
|
28
28
|
readonly clientId: string;
|
|
29
29
|
readonly attached: boolean;
|
|
30
30
|
};
|
|
31
|
-
declare const createMockTransport: <TState>(initialState: TState, protocol?: string
|
|
31
|
+
declare const createMockTransport: <TState>(initialState: TState, protocol?: string, options?: {
|
|
32
|
+
ephemeral?: readonly string[];
|
|
33
|
+
}) => MockTransport<TState>;
|
|
32
34
|
//#endregion
|
|
33
35
|
export { MockTransport, SocketRecorder, applyOptimistic, commandFrame, createCounterElement, createMockTransport, createSocketRecorder, settle, tick };
|
|
34
36
|
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","names":[],"sources":["../../src/transports/testing.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"testing.d.ts","names":[],"sources":["../../src/transports/testing.ts"],"mappings":";;;;;;;cAYa,YAAI;KAIL,cAAc;;EAExB,WAAW,gBAAgB,UAAU;;EAErC;IAAY;IAAkB;IAAgB;;;EAE9C,WAAW,OAAO,WAAW;;EAE7B,UAAU,gBAAgB;;EAE1B,SAAS,aAAa,sBAAsB;;EAE5C,eAAe,UAAU,sBAAsB;;EAE/C,SAAS,gBAAgB,qBAAqB;WACrC;WACA;;cAUE,sBAAuB,QAClC,cAAc,QACd,mBACA;EAAW;MACV,cAAc"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { WIRE_VERSION } from "../wire/protocol.js";
|
|
1
2
|
import { applyOptimistic } from "../util/recordMutations.js";
|
|
2
3
|
import { StatewireHttp } from "./sse.js";
|
|
3
4
|
import { openSSEStream, sseFrame } from "./fake-sse.js";
|
|
@@ -11,7 +12,8 @@ const tick = () => new Promise((r) => setTimeout(r, 0));
|
|
|
11
12
|
* from test code), and exposes the wire as a transport ResourceElement.
|
|
12
13
|
*/
|
|
13
14
|
let mockCount = 0;
|
|
14
|
-
const createMockTransport = (initialState, protocol = "default") => {
|
|
15
|
+
const createMockTransport = (initialState, protocol = "default", options = {}) => {
|
|
16
|
+
const ephemeral = (options.ephemeral ?? []).map((child) => `${protocol}/${child}`);
|
|
15
17
|
let state = initialState;
|
|
16
18
|
let clientId = "";
|
|
17
19
|
let finished = false;
|
|
@@ -24,16 +26,11 @@ const createMockTransport = (initialState, protocol = "default") => {
|
|
|
24
26
|
};
|
|
25
27
|
const admit = (id, frame) => {
|
|
26
28
|
const rec = clients.get(id);
|
|
27
|
-
for (const statement of frame.ctx ?? []) {
|
|
28
|
-
if (statement.seq <= rec.ctxSeq) continue;
|
|
29
|
-
rec.ctxSeq = Math.max(rec.ctxSeq, statement.seq);
|
|
30
|
-
const root = statement.ops[0];
|
|
31
|
-
commands.push({ context: root?.value });
|
|
32
|
-
}
|
|
33
29
|
for (const statement of frame.cmd ?? []) {
|
|
34
|
-
if (statement.seq <= rec.
|
|
35
|
-
rec.
|
|
30
|
+
if (statement.seq <= (rec[statement.protocol] ?? 0)) continue;
|
|
31
|
+
rec[statement.protocol] = statement.seq;
|
|
36
32
|
commands.push({
|
|
33
|
+
protocol: statement.protocol,
|
|
37
34
|
method: statement.method,
|
|
38
35
|
params: statement.params
|
|
39
36
|
});
|
|
@@ -45,12 +42,9 @@ const createMockTransport = (initialState, protocol = "default") => {
|
|
|
45
42
|
const id = new Headers(init?.headers).get("Statewire-Client-Id") ?? "";
|
|
46
43
|
if (url.endsWith("/stream")) {
|
|
47
44
|
clientId = id;
|
|
48
|
-
if (!clients.has(id)) clients.set(id, {
|
|
49
|
-
seq: 0,
|
|
50
|
-
ctxSeq: 0
|
|
51
|
-
});
|
|
45
|
+
if (!clients.has(id)) clients.set(id, {});
|
|
52
46
|
const rec = clients.get(id);
|
|
53
|
-
|
|
47
|
+
for (const lane of ephemeral) delete rec[lane];
|
|
54
48
|
const frame = JSON.parse(String(init?.body ?? "{}"));
|
|
55
49
|
admit(id, frame);
|
|
56
50
|
return openSSEStream(streams, id, (handle) => {
|
|
@@ -62,13 +56,17 @@ const createMockTransport = (initialState, protocol = "default") => {
|
|
|
62
56
|
value: state
|
|
63
57
|
}],
|
|
64
58
|
syn: {
|
|
65
|
-
|
|
66
|
-
ctxSeq: 0,
|
|
67
|
-
version: "2026-09-07",
|
|
59
|
+
version: WIRE_VERSION,
|
|
68
60
|
protocols: [{
|
|
69
61
|
name: protocol,
|
|
70
|
-
version:
|
|
71
|
-
|
|
62
|
+
version: WIRE_VERSION,
|
|
63
|
+
seq: rec[protocol] ?? 0
|
|
64
|
+
}, ...ephemeral.map((name) => ({
|
|
65
|
+
name,
|
|
66
|
+
version: WIRE_VERSION,
|
|
67
|
+
record: "ephemeral",
|
|
68
|
+
seq: 0
|
|
69
|
+
}))]
|
|
72
70
|
}
|
|
73
71
|
}));
|
|
74
72
|
}, init?.signal ?? void 0, { "Statewire-Lease": "mock-lease" });
|
|
@@ -94,10 +92,12 @@ const createMockTransport = (initialState, protocol = "default") => {
|
|
|
94
92
|
}] });
|
|
95
93
|
},
|
|
96
94
|
applied: (seq) => sendEnvelope({ cmd: [{
|
|
95
|
+
protocol,
|
|
97
96
|
seq,
|
|
98
97
|
type: "applied"
|
|
99
98
|
}] }),
|
|
100
99
|
settle: (seq, payload) => sendEnvelope({ cmd: [{
|
|
100
|
+
protocol,
|
|
101
101
|
seq,
|
|
102
102
|
type: "result",
|
|
103
103
|
...payload !== void 0 && { payload }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.js","names":["ResourceElement","StatewireEnvelope","StatewireHttp","StatewireFrame","Statewire","openSSEStream","sseFrame","FakeStreamHandle","tick","Promise","r","setTimeout","applyOptimistic","MockTransport","transport","TState","commands","
|
|
1
|
+
{"version":3,"file":"testing.js","names":["ResourceElement","StatewireEnvelope","StatewireHttp","StatewireFrame","Statewire","openSSEStream","sseFrame","FakeStreamHandle","WIRE_VERSION","tick","Promise","r","setTimeout","applyOptimistic","MockTransport","transport","TState","commands","protocol","method","params","setState","state","applied","seq","settle","payload","sendEnvelope","envelope","finish","reason","message","clientId","attached","mockCount","createMockTransport","initialState","options","ephemeral","map","child","finished","clients","Map","Record","streams","Set","stream","send","admit","id","frame","rec","get","statement","cmd","push","fakeFetch","input","RequestInfo","URL","init","RequestInit","Response","TypeError","url","String","headers","Headers","endsWith","has","set","lane","JSON","parse","body","handle","ops","op","main","value","syn","version","protocols","name","record","const","signal","undefined","json","status","fetch","next","path","type","fin","close","size"],"sources":["../../src/transports/testing.ts"],"sourcesContent":["import type { ResourceElement } from \"@assistant-ui/tap\";\nimport type { StatewireEnvelope } from \"../client/connection\";\nimport { StatewireHttp } from \"./sse\";\nimport type { StatewireFrame } from \"./sse\";\nimport type { Statewire } from \"../types\";\nimport { openSSEStream, sseFrame } from \"./fake-sse\";\nimport type { FakeStreamHandle } from \"./fake-sse\";\nimport { WIRE_VERSION } from \"../wire/protocol\";\n\nexport * from \"./fixtures\";\n\n/** Let queued microtasks and op batches drain through the statewire client. */\nexport const tick = () => new Promise<void>((r) => setTimeout(r, 0));\n\nexport { applyOptimistic } from \"../util/recordMutations\";\n\nexport type MockTransport<TState> = {\n /** Pass as the `transport:` option of useStatewire / Harness. */\n transport: ResourceElement<Statewire<TState | undefined, any>>;\n /** Captured statements in arrival order. */\n commands: { protocol: string; method: string; params: unknown[] }[];\n /** Replace the replicated state and broadcast it as a root snapshot op. */\n setState: (state: TState) => Promise<void>;\n /** Deliver a bare ack cmd packet on the stream. */\n applied: (seq: number) => Promise<void>;\n /** Deliver a terminal result cmd packet on the stream. */\n settle: (seq: number, payload?: unknown) => Promise<void>;\n /** Deliver an arbitrary envelope on the stream. */\n sendEnvelope: (envelope: StatewireEnvelope) => Promise<void>;\n /** End the stream with a fin; further attaches fail like a dead server. */\n finish: (reason: string, message?: string) => Promise<void>;\n readonly clientId: string;\n readonly attached: boolean;\n};\n\n/**\n * A mock statewire backend: serves `initialState` as the attach snapshot,\n * records submitted frames (receipt only — acks and results are delivered\n * from test code), and exposes the wire as a transport ResourceElement.\n */\nlet mockCount = 0;\n\nexport const createMockTransport = <TState>(\n initialState: TState,\n protocol = \"default\",\n options: { ephemeral?: readonly string[] } = {},\n): MockTransport<TState> => {\n const ephemeral = (options.ephemeral ?? []).map(\n (child) => `${protocol}/${child}`,\n );\n let state: unknown = initialState;\n let clientId = \"\";\n let finished = false;\n const clients = new Map<string, Record<string, number>>();\n const streams = new Set<FakeStreamHandle>();\n const commands: MockTransport<unknown>[\"commands\"] = [];\n\n const sendEnvelope = (envelope: StatewireEnvelope) => {\n for (const stream of streams) stream.send(sseFrame(envelope));\n return tick();\n };\n\n const admit = (id: string, frame: StatewireFrame) => {\n const rec = clients.get(id)!;\n for (const statement of frame.cmd ?? []) {\n if (statement.seq <= (rec[statement.protocol] ?? 0)) continue;\n rec[statement.protocol] = statement.seq;\n commands.push({\n protocol: statement.protocol,\n method: statement.method,\n params: statement.params,\n });\n }\n };\n\n const fakeFetch = (async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n if (finished) throw new TypeError(\"fetch failed (finished)\");\n const url = String(input);\n const headers = new Headers(init?.headers);\n const id = headers.get(\"Statewire-Client-Id\") ?? \"\";\n if (url.endsWith(\"/stream\")) {\n clientId = id;\n if (!clients.has(id)) clients.set(id, {});\n const rec = clients.get(id)!;\n for (const lane of ephemeral) delete rec[lane];\n const frame = JSON.parse(String(init?.body ?? \"{}\")) as StatewireFrame;\n admit(id, frame);\n return openSSEStream(\n streams,\n id,\n (handle) => {\n handle.send(\n sseFrame({\n ops: [{ op: \"mount\", protocol, main: true, value: state }],\n syn: {\n version: WIRE_VERSION,\n protocols: [\n {\n name: protocol,\n version: WIRE_VERSION,\n seq: rec[protocol] ?? 0,\n },\n ...ephemeral.map((name) => ({\n name,\n version: WIRE_VERSION,\n record: \"ephemeral\" as const,\n seq: 0,\n })),\n ],\n },\n }),\n );\n },\n init?.signal ?? undefined,\n { \"Statewire-Lease\": \"mock-lease\" },\n );\n }\n if (url.endsWith(\"/frames\")) {\n admit(clientId, JSON.parse(String(init?.body ?? \"{}\")) as StatewireFrame);\n return Response.json({});\n }\n return new Response(null, { status: 404 });\n }) as typeof fetch;\n\n return {\n transport: StatewireHttp({\n url: `http://mock-${++mockCount}/api`,\n fetch: fakeFetch,\n }),\n commands,\n setState: (next) => {\n state = next;\n return sendEnvelope({ ops: [{ op: \"replace\", path: [], value: next }] });\n },\n applied: (seq) =>\n sendEnvelope({ cmd: [{ protocol, seq, type: \"applied\" }] }),\n settle: (seq, payload) =>\n sendEnvelope({\n cmd: [\n {\n protocol,\n seq,\n type: \"result\",\n ...(payload !== undefined && { payload }),\n },\n ],\n }),\n sendEnvelope,\n finish: async (reason, message) => {\n await sendEnvelope({\n fin: { reason, ...(message !== undefined && { message }) },\n });\n finished = true;\n for (const stream of [...streams]) stream.close();\n await tick();\n },\n get clientId() {\n return clientId;\n },\n get attached() {\n return streams.size > 0;\n },\n };\n};\n"],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { StatewireDocuments } from "./wire/documents.js";
|
|
2
|
+
import { StatewireHost } from "./host.js";
|
|
2
3
|
import { StatewireProtocol } from "./wire/protocol.js";
|
|
3
4
|
import { StatewireClient } from "./statewire.js";
|
|
4
5
|
import { StatewirePath } from "./wire/ops.js";
|
|
@@ -49,19 +50,16 @@ interface Statewire<TState = any, TCommands extends Statewire.Commands = Statewi
|
|
|
49
50
|
documents?: StatewireDocuments.Source;
|
|
50
51
|
selection?: StatewireProtocol.Selection | undefined;
|
|
51
52
|
invoke?: (protocol: string, method: string, params: readonly unknown[]) => Promise<unknown>;
|
|
52
|
-
updateContext?: (ops: readonly unknown[]) => void;
|
|
53
53
|
commands: Statewire.CommandsProxy<TCommands>;
|
|
54
54
|
connection?: StatewireClient.Connection;
|
|
55
55
|
source?: Statewire.StateSource;
|
|
56
|
-
/** Highest command seq the server's dur flag states durably admitted — never lost, never run again — and released from the resend queue. */
|
|
57
|
-
durableSeq?: number;
|
|
58
56
|
/** Negation of the server's broadcast idle level; absent means always busy. */
|
|
59
57
|
isBusy?: boolean;
|
|
60
58
|
work?: {
|
|
61
59
|
readonly isIdle: boolean;
|
|
62
60
|
};
|
|
63
|
-
/**
|
|
64
|
-
|
|
61
|
+
/** Called by the serving host when an attach ends; its ephemeral documents and includes are gone. */
|
|
62
|
+
detached?: (attach: StatewireHost.Attach) => void;
|
|
65
63
|
/** The retained failed-send lane; present on transports with a durable session. */
|
|
66
64
|
failures?: {
|
|
67
65
|
list: () => readonly StatewireClient.FailedCommand[];
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;kBAMiB;OACH,WAAW,mBAAmB;OAE9B,QAAQ,kBAAkB,WAAW,eAC9C,WAAW;IAAc,QAAQ;IAAG,QAAQ,WAAW,UAAU;aAC5D;OAEI,cAAc,kBAAkB,eACzC,WAAW,gBACP,MAAM,WAAW,UAAU,QAC3B,QAAQ,QAAQ,WAAW,UAAU;OAGhC,cAAc,kBAAkB,WAAW,eACpD,WAAW;aACD;IACT,QAAQ;IACR,QAAQ,WAAW,UAAU;IAC7B;IACA;IACA;IACA,UAAU,gBAAgB;aAEtB;;OAGI;IACV;;IAEA,mBAAmB;;IAEnB,cAAc;;OAGJ;IACN;IAAe,MAAM;IAAe;;IACpC;IAAW,MAAM;IAAe;;IAChC;IAAc,MAAM;;OAEd;IACV,YAAY;IACZ,eAAe;;;UAIF,UACf,cACA,kBAAkB,UAAU,WAAW,UAAU;EAEjD,OAAO;EACP,YAAY,mBAAmB;EAC/B,YAAY,kBAAkB;EAC9B,UACE,kBACA,gBACA,+BACG;EACL,UAAU,UAAU,cAAc;EAClC,aAAa,gBAAgB;EAC7B,SAAS,UAAU;;EAEnB;EACA;aAAkB;;;EAElB,YAAY,QAAQ,cAAc;;EAElC;IACE,qBAAqB,gBAAgB;IACrC,QAAQ,OAAO,gBAAgB,kBAAkB;IACjD,UAAU,OAAO,gBAAgB;;;cAuBxB,2BAA2B;WAC7B,SAAS,gBAAgB;EAEtB,YAAA,SAAS,gBAAgB"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":["StatewireDocuments","StatewireProtocol","StatewireClient","StatewirePath","Statewire","Commands","Record","args","Command","TCommands","method","K","params","Parameters","CommandsProxy","Promise","Awaited","ReturnType","CommandUpdate","protocol","seq","status","result","failure","SendFailure","StateSource","snapshot","takeChanged","setOnChange","listener","Op","op","path","value","Changes","isChangedAt","getChangedKeys","state","TState","documents","Source","selection","Selection","invoke","
|
|
1
|
+
{"version":3,"file":"types.js","names":["StatewireDocuments","StatewireHost","StatewireProtocol","StatewireClient","StatewirePath","Statewire","Commands","Record","args","Command","TCommands","method","K","params","Parameters","CommandsProxy","Promise","Awaited","ReturnType","CommandUpdate","protocol","seq","status","result","failure","SendFailure","StateSource","snapshot","takeChanged","setOnChange","listener","Op","op","path","value","Changes","isChangedAt","getChangedKeys","state","TState","documents","Source","selection","Selection","invoke","commands","connection","Connection","source","isBusy","work","isIdle","detached","attach","Attach","failures","list","FailedCommand","retry","entry","discard","describe","fate","code","message","cause","StatewireSendError","Error","constructor","name"],"sources":["../src/types.ts"],"sourcesContent":["import type { StatewireDocuments } from \"./wire/documents\";\nimport type { StatewireHost } from \"./host\";\nimport type { StatewireProtocol } from \"./wire/protocol\";\nimport type { StatewireClient } from \"./statewire\";\nimport type { StatewirePath } from \"./wire/ops\";\n\nexport namespace Statewire {\n export type Commands = Record<string, (...args: never[]) => unknown>;\n\n export type Command<TCommands extends Commands = Commands> = {\n [K in keyof TCommands]: { method: K; params: Parameters<TCommands[K]> };\n }[keyof TCommands];\n\n export type CommandsProxy<TCommands extends Commands> = {\n [K in keyof TCommands]: (\n ...args: Parameters<TCommands[K]>\n ) => Promise<Awaited<ReturnType<TCommands[K]>>>;\n };\n\n export type CommandUpdate<TCommands extends Commands = Commands> = {\n [K in keyof TCommands]: {\n readonly protocol?: string;\n method: K;\n params: Parameters<TCommands[K]>;\n seq: number;\n status: \"queued\" | \"posted\" | \"applied\" | \"settled\";\n result?: unknown;\n failure?: StatewireClient.SendFailure;\n };\n }[keyof TCommands];\n\n /** Push-based canonical state feed a statewire hands to the client core. */\n export type StateSource = {\n snapshot: () => unknown;\n /** Drain the paths changed since the last take (`[]` entry = whole state). */\n takeChanged: () => StatewirePath[];\n /** Synchronous, per change; the consumer owns coalescing. */\n setOnChange: (listener: (() => void) | null) => void;\n };\n\n export type Op =\n | { op: \"replace\"; path: StatewirePath; value: unknown }\n | { op: \"add\"; path: StatewirePath; value: unknown }\n | { op: \"remove\"; path: StatewirePath };\n\n export type Changes = {\n isChangedAt(path: readonly (string | number)[]): boolean;\n getChangedKeys(path: readonly (string | number)[]): string[];\n };\n}\n\nexport interface Statewire<\n TState = any,\n TCommands extends Statewire.Commands = Statewire.Commands,\n> {\n state: TState;\n documents?: StatewireDocuments.Source;\n selection?: StatewireProtocol.Selection | undefined;\n invoke?: (\n protocol: string,\n method: string,\n params: readonly unknown[],\n ) => Promise<unknown>;\n commands: Statewire.CommandsProxy<TCommands>;\n connection?: StatewireClient.Connection;\n source?: Statewire.StateSource;\n /** Negation of the server's broadcast idle level; absent means always busy. */\n isBusy?: boolean;\n work?: { readonly isIdle: boolean };\n /** Called by the serving host when an attach ends; its ephemeral documents and includes are gone. */\n detached?: (attach: StatewireHost.Attach) => void;\n /** The retained failed-send lane; present on transports with a durable session. */\n failures?: {\n list: () => readonly StatewireClient.FailedCommand[];\n retry: (entry: StatewireClient.FailedCommand) => Promise<unknown>;\n discard: (entry: StatewireClient.FailedCommand) => void;\n };\n}\n\nconst describe = (failure: StatewireClient.SendFailure): string => {\n switch (failure.fate) {\n case \"rejected\":\n return `statewire: command rejected${failure.code ? ` (${failure.code})` : \"\"}${failure.message ? `: ${failure.message}` : \"\"}`;\n case \"aborted\":\n return `statewire: command aborted (${failure.cause})`;\n case \"lost\":\n return `statewire: command lost (${failure.cause})`;\n case \"failed\":\n return failure.message\n ? `statewire: command failed: ${failure.message}`\n : \"statewire: command failed\";\n case \"crashed\":\n return \"statewire: command crashed\";\n case \"expired\":\n return `statewire: command result expired (${failure.cause})`;\n }\n};\n\nexport class StatewireSendError extends Error {\n readonly failure: StatewireClient.SendFailure;\n\n constructor(failure: StatewireClient.SendFailure) {\n super(describe(failure));\n this.name = \"StatewireSendError\";\n this.failure = failure;\n }\n}\n"],"mappings":";AA+EA,MAAM6D,YAAYrC,YAAiD;CACjE,QAAQA,QAAQsC,MAAhB;EACE,KAAK,YACH,OAAO,8BAA8BtC,QAAQuC,OAAO,KAAKvC,QAAQuC,KAAI,KAAM,KAAKvC,QAAQwC,UAAU,KAAKxC,QAAQwC,YAAY;EAC7H,KAAK,WACH,OAAO,+BAA+BxC,QAAQyC,MAAK;EACrD,KAAK,QACH,OAAO,4BAA4BzC,QAAQyC,MAAK;EAClD,KAAK,UACH,OAAOzC,QAAQwC,UACX,8BAA8BxC,QAAQwC,YACtC;EACN,KAAK,WACH,OAAO;EACT,KAAK,WACH,OAAO,sCAAsCxC,QAAQyC,MAAK;CAC9D;AACF;AAEA,IAAaC,qBAAb,cAAwCC,MAAM;CAC5C;CAEAC,YAAY5C,SAAsC;EAChD,MAAMqC,SAASrC,OAAO,CAAC;EACvB,KAAK6C,OAAO;EACZ,KAAK7C,UAAUA;CACjB;AACF"}
|
package/dist/wire/limits.d.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
declare const MAX_COMMANDS_PER_FRAME = 256;
|
|
3
3
|
declare const MAX_INFLIGHT_COMMANDS_PER_CLIENT = 256;
|
|
4
4
|
declare const MAX_FRAME_BODY_BYTES: number;
|
|
5
|
-
declare const
|
|
5
|
+
declare const MAX_EPHEMERAL_DOCUMENT_BYTES: number;
|
|
6
6
|
declare const MAX_INFLIGHT_COMMANDS_PER_HOST = 1024;
|
|
7
7
|
declare const COMMAND_CAPACITY_RETRY_MS = 1000;
|
|
8
8
|
//#endregion
|
|
9
|
-
export { COMMAND_CAPACITY_RETRY_MS, MAX_COMMANDS_PER_FRAME,
|
|
9
|
+
export { COMMAND_CAPACITY_RETRY_MS, MAX_COMMANDS_PER_FRAME, MAX_EPHEMERAL_DOCUMENT_BYTES, MAX_FRAME_BODY_BYTES, MAX_INFLIGHT_COMMANDS_PER_CLIENT, MAX_INFLIGHT_COMMANDS_PER_HOST };
|
|
10
10
|
//# sourceMappingURL=limits.d.ts.map
|