effect-durable-agent-cloudflare 0.1.0-alpha.23 → 0.1.0-alpha.25

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"durable-object-CkrxIOH4.js","names":["#wakeup","#write","#rows","#tail","#controller","#webSocketProjectionId","#alarms","#transcriptOptions","#transcriptEnabled","#transcript"],"sources":["../src/durable-object-alarm-handler.ts","../src/durable-object-alarms.ts","../src/durable-object.ts"],"sourcesContent":["import type { DurableObjectAlarmScheduler } from \"./durable-object-alarms\";\n\n/** What one session object's alarm fires for, and the policy bounding builder retries. */\nexport interface EDASessionAlarmParticipants {\n readonly alarms: DurableObjectAlarmScheduler;\n readonly now: () => number;\n /** The runtime's alarm work: keep-alive and run-scheduling redelivery. */\n readonly runRuntime: () => Promise<void>;\n /**\n * Bounded builder slices; resolves whether work remains. Undefined when this object's session\n * maintains no transcript (it is not enabled, or the object is unnamed).\n */\n readonly runBuilderSlices: (() => Promise<boolean>) | undefined;\n /** Consecutive failed builder alarms before the builder stops scheduling itself. */\n readonly maxBuilderFailures: number;\n /** First retry delay after a failed builder alarm; doubled per consecutive failure. */\n readonly builderRetryDelayMs: number;\n readonly onBuilderFailure: (failure: {\n readonly error: unknown;\n readonly consecutiveFailures: number;\n readonly stopped: boolean;\n }) => void;\n}\n\n/** Longest delay between builder retries. */\nconst maxBuilderRetryDelayMs = 3_600_000;\n\n/**\n * Handle one platform alarm shared by the runtime and the transcript builder.\n *\n * - The runtime runs for its own wakeup, or for an alarm no owner recorded (one armed by a\n * release before wakeups were recorded). The builder runs for its wakeup even when the runtime\n * failed.\n * - No wakeup is consumed up front: each owner's is cleared only after its work succeeds, so a\n * handler that throws or dies mid-work leaves the platform's retry attributed to every owner it\n * fired for.\n * - A failed builder retries with exponential backoff; its consecutive failures persist with its\n * wakeup, so eviction cannot reset them, and at `maxBuilderFailures` it stops scheduling itself.\n * No failure re-arms the alarm sooner than the backoff, so no object can loop on its alarm.\n * - A failed runtime rethrows without re-arming the platform alarm, so the platform's own retry\n * (backoff and retry cap) applies; otherwise the alarm is pointed at the earliest wakeup left.\n */\nexport const runEDASessionAlarm = async (participants: EDASessionAlarmParticipants) => {\n const { alarms } = participants;\n const now = participants.now();\n const due = alarms.due(now);\n let runtimeFailure: { readonly error: unknown } | undefined;\n if (due.has(\"runtime\") || due.size === 0) {\n try {\n await participants.runRuntime();\n alarms.clearThrough(\"runtime\", due.get(\"runtime\") ?? now);\n } catch (error) {\n runtimeFailure = { error };\n }\n }\n const builderWakeup = due.get(\"transcript\");\n if (builderWakeup !== undefined) {\n const runBuilderSlices = participants.runBuilderSlices;\n if (runBuilderSlices === undefined) {\n alarms.clear(\"transcript\");\n } else {\n try {\n if (await runBuilderSlices()) alarms.retain(\"transcript\", participants.now());\n else alarms.clearThrough(\"transcript\", builderWakeup);\n } catch (error) {\n const consecutiveFailures = alarms.failures(\"transcript\") + 1;\n const stopped = consecutiveFailures >= participants.maxBuilderFailures;\n if (stopped) {\n alarms.clear(\"transcript\");\n } else {\n const delayMs = Math.min(\n participants.builderRetryDelayMs * 2 ** (consecutiveFailures - 1),\n maxBuilderRetryDelayMs,\n );\n alarms.retain(\"transcript\", participants.now() + delayMs, consecutiveFailures);\n }\n participants.onBuilderFailure({ error, consecutiveFailures, stopped });\n }\n }\n }\n if (runtimeFailure !== undefined) throw runtimeFailure.error;\n await alarms.sync();\n};\n","import type { DurableObjectAlarmStorage } from \"./durable-object-keepalive\";\nimport type { DurableObjectSessionStorage } from \"./durable-object-storage\";\n\n/**\n * The independent owners of a session object's single platform alarm.\n *\n * - `runtime`: the keep-alive heartbeat and run-scheduling redelivery; its wakeup builds the model\n * runtime.\n * - `transcript`: the transcript builder; its wakeup runs storage-only slices and must never\n * build the model runtime.\n */\nexport type DurableObjectAlarmOwner = \"runtime\" | \"transcript\";\n\n/**\n * Shares one Durable Object alarm between owners that each keep a durable wakeup.\n *\n * Each owner's wakeup is a row in `_eda_alarm_wakeups`, and the platform alarm is always set to the\n * earliest row, so no owner can delete or postpone another's wakeup, and after an eviction the\n * alarm handler still knows which owners it fired for. An owner's view (`owner(...)`) has the\n * same shape as the platform alarm API, so the keep-alive heartbeat uses it unchanged.\n */\nexport class DurableObjectAlarmScheduler {\n #tail: Promise<void> = Promise.resolve();\n\n constructor(\n private readonly storage: DurableObjectSessionStorage & DurableObjectAlarmStorage,\n private readonly now: () => number = () => Date.now(),\n ) {}\n\n /**\n * One owner's alarm, behaving like the platform alarm restricted to that owner. Like the\n * platform's, it reports no alarm once its time has passed: a wakeup left behind when the\n * platform gave up retrying a failed alarm must not look armed, or its owner would never re-arm.\n */\n owner(owner: DurableObjectAlarmOwner): DurableObjectAlarmStorage {\n return {\n getAlarm: () => {\n const wakeup = this.#wakeup(owner);\n return wakeup === undefined || wakeup < this.now() ? null : wakeup;\n },\n setAlarm: (scheduledTimeMs) => {\n this.#write(owner, scheduledTimeMs);\n return this.sync();\n },\n deleteAlarm: () => {\n this.#write(owner, undefined);\n return this.sync();\n },\n };\n }\n\n /**\n * Adopt a platform alarm no owner recorded (one armed before wakeups were recorded) as the\n * runtime's, so the first wakeup another owner requests cannot replace it. Call once at startup,\n * before any owner writes a wakeup.\n */\n async adoptUnrecordedAlarm(): Promise<void> {\n if (this.#rows().length > 0) return;\n const armed = await this.storage.getAlarm();\n if (armed !== null && this.#rows().length === 0) this.#write(\"runtime\", armed);\n }\n\n /**\n * Record `owner`'s wakeup without touching the platform alarm, for use inside `alarm()`: the\n * caller syncs once at the end, or not at all when it rethrows, which leaves the platform's own\n * retry (with its backoff and cap) in force.\n */\n retain(owner: DurableObjectAlarmOwner, atMs: number, failures = 0): void {\n this.#write(owner, atMs, failures);\n }\n\n /** Consecutive failures recorded with `owner`'s wakeup; 0 without one. */\n failures(owner: DurableObjectAlarmOwner): number {\n return (\n this.storage.sql\n .exec<{ readonly failures: number }>(\n \"SELECT failures FROM _eda_alarm_wakeups WHERE owner = ?\",\n owner,\n )\n .toArray()[0]?.failures ?? 0\n );\n }\n\n /** Remove `owner`'s wakeup whatever its time; call `sync` afterwards. */\n clear(owner: DurableObjectAlarmOwner): void {\n this.#write(owner, undefined);\n }\n\n /** Wake `owner` no later than `atMs`; an earlier wakeup it already holds is kept. */\n request(owner: DurableObjectAlarmOwner, atMs: number): Promise<void> {\n const current = this.#wakeup(owner);\n if (current !== undefined && current <= atMs) return this.sync();\n this.#write(owner, atMs);\n return this.sync();\n }\n\n /**\n * Called when the platform alarm fires: the owners it fired for (every wakeup at or before now,\n * and always the earliest one) and the wakeup each held. Nothing is consumed here: each owner\n * `clearThrough`s its wakeup only after its work succeeds, so a handler that throws, or dies\n * mid-work (eviction, deploy, a resource limit), leaves the platform's retry attributed to every\n * owner it fired for. An owner's view already reports a past wakeup as no alarm, so the runtime's\n * keep-alive re-arms during its work as it did with the platform alarm.\n */\n due(nowMs: number): ReadonlyMap<DurableObjectAlarmOwner, number> {\n const rows = this.#rows();\n const earliest = rows.reduce((min, row) => Math.min(min, row.at_ms), Number.POSITIVE_INFINITY);\n const threshold = Math.max(nowMs, earliest);\n const due = new Map<DurableObjectAlarmOwner, number>();\n for (const row of rows) {\n if (row.at_ms <= threshold && isOwner(row.owner)) due.set(row.owner, row.at_ms);\n }\n return due;\n }\n\n /**\n * Remove `owner`'s wakeup if it is still at or before `atMs`, once the work it fired for has\n * succeeded. A later wakeup the owner re-armed during that work is kept.\n */\n clearThrough(owner: DurableObjectAlarmOwner, atMs: number): void {\n this.storage.sql.exec(\n \"DELETE FROM _eda_alarm_wakeups WHERE owner = ? AND at_ms <= ?\",\n owner,\n atMs,\n );\n }\n\n /** Point the platform alarm at the earliest wakeup, or clear it when none remains. */\n sync(): Promise<void> {\n this.#tail = this.#tail\n .catch(() => undefined)\n .then(async () => {\n const earliest = this.storage.sql\n .exec<{ readonly at_ms: number | null }>(\n \"SELECT MIN(at_ms) AS at_ms FROM _eda_alarm_wakeups\",\n )\n .one().at_ms;\n if (earliest === null) {\n await this.storage.deleteAlarm();\n return;\n }\n if ((await this.storage.getAlarm()) !== earliest) {\n await this.storage.setAlarm(earliest);\n }\n });\n return this.#tail;\n }\n\n #rows(): ReadonlyArray<{ readonly owner: string; readonly at_ms: number }> {\n return this.storage.sql\n .exec<{ readonly owner: string; readonly at_ms: number }>(\n \"SELECT owner, at_ms FROM _eda_alarm_wakeups\",\n )\n .toArray();\n }\n\n #wakeup(owner: DurableObjectAlarmOwner): number | undefined {\n return this.storage.sql\n .exec<{ readonly at_ms: number }>(\n \"SELECT at_ms FROM _eda_alarm_wakeups WHERE owner = ?\",\n owner,\n )\n .toArray()[0]?.at_ms;\n }\n\n /** Upsert or delete `owner`'s wakeup. Without `failures`, an existing count is kept. */\n #write(owner: DurableObjectAlarmOwner, atMs: number | undefined, failures?: number): void {\n if (atMs === undefined) {\n this.storage.sql.exec(\"DELETE FROM _eda_alarm_wakeups WHERE owner = ?\", owner);\n return;\n }\n if (failures === undefined) {\n this.storage.sql.exec(\n `INSERT INTO _eda_alarm_wakeups (owner, at_ms) VALUES (?, ?)\n ON CONFLICT(owner) DO UPDATE SET at_ms = excluded.at_ms`,\n owner,\n atMs,\n );\n return;\n }\n this.storage.sql.exec(\n `INSERT INTO _eda_alarm_wakeups (owner, at_ms, failures) VALUES (?, ?, ?)\n ON CONFLICT(owner) DO UPDATE SET at_ms = excluded.at_ms, failures = excluded.failures`,\n owner,\n atMs,\n failures,\n );\n }\n}\n\nconst isOwner = (owner: string): owner is DurableObjectAlarmOwner =>\n owner === \"runtime\" || owner === \"transcript\";\n","import type { CommittedDurableEvent } from \"effect-durable-agent/services/session-store\";\nimport { durableEventEnvelope } from \"effect-durable-agent/types/events/durable\";\nimport { encodeEdaRpcDurableEvent } from \"./rpc-codec\";\nimport {\n SessionScopedInput,\n SessionTranscriptBodyInput,\n SessionTranscriptSummaryInput,\n SessionTranscriptWindowInput,\n SessionCommandInput,\n SessionGrantRunInput,\n SessionBatchInput,\n SessionBlockInput,\n SessionOutcomeInput,\n edaSessionRpc,\n} from \"./rpc-spec\";\nimport { DurableObject } from \"cloudflare:workers\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\n\nimport type { EDARuntimeConfig } from \"effect-durable-agent/services/runtime\";\nimport {\n CommandId,\n RunRequestId,\n SequenceNumber,\n SessionId,\n} from \"effect-durable-agent/types/core\";\nimport {\n EDATraceMetadata,\n makeEDATraceMetadataFromParent,\n makeRootEDATraceMetadata,\n parseEDATraceparent,\n} from \"effect-durable-agent/types/tracing\";\nimport {\n EDASessionController,\n type EDASessionControllerOptions,\n type EDASessionDurableObjectStorage,\n} from \"./session-controller\";\nimport {\n EDA_WEB_SOCKET_PING_MESSAGE,\n EDA_WEB_SOCKET_PONG_MESSAGE,\n} from \"effect-durable-agent/websocket\";\nimport * as Result from \"effect/Result\";\nimport {\n defaultTranscriptWindowLimits,\n emptyTranscriptMappings,\n makeTranscriptDefinition,\n resolveTranscriptBody,\n type EDATranscriptStoreShape,\n type TranscriptLogIncarnation,\n type TranscriptMaintenanceConfig,\n} from \"effect-durable-agent/transcript\";\nimport { runEDASessionAlarm } from \"./durable-object-alarm-handler\";\nimport { DurableObjectAlarmScheduler } from \"./durable-object-alarms\";\nimport { readDurableObjectCommittedEvent, readDurableObjectSummary } from \"./durable-object-store\";\nimport type { EDATranscriptSocketOptions } from \"./websocket/transcript-sockets\";\nimport { EDASessionStoreError } from \"effect-durable-agent/services/session-store\";\nimport {\n DurableObjectTranscriptBuilder,\n DurableObjectTranscriptStore,\n} from \"./durable-object-transcript\";\nimport {\n defaultTranscriptSliceLimits,\n resolveTranscriptSliceLimits,\n type DurableObjectTranscriptObserver,\n type DurableObjectTranscriptOptions,\n type DurableObjectTranscriptSliceLimits,\n type TranscriptAlert,\n} from \"./durable-object-transcript-maintenance\";\n\nexport type { EDAWebSocketProjection } from \"./websocket/projection\";\n/** Internal Worker-to-object header selecting an app-owned WebSocket projection. */\nexport const EDA_WEB_SOCKET_PROJECTION_HEADER = \"x-eda-websocket-projection\";\n\n/**\n * Upgrade query parameter selecting the socket's stream: `transcript` selects the ordered\n * transcript-window stream; anything else keeps the raw event stream.\n */\nexport const EDA_WEB_SOCKET_STREAM_PARAM = \"stream\";\n\n/** Encoded session RPC inputs, decoded before invoking the controller. */\nexport type EDASessionCommandRpcInput = typeof SessionCommandInput.Encoded;\nexport type EDASessionGrantRunRpcInput = typeof SessionGrantRunInput.Encoded;\nexport type EDASessionSubmitBatchRpcInput = typeof SessionBatchInput.Encoded;\nexport type EDASessionScopedRpcInput = typeof SessionScopedInput.Encoded;\nexport type EDASessionEventsRpcInput = EDASessionScopedRpcInput & { readonly afterSeq?: number };\nexport type EDASessionBlockOnCommandRpcInput = typeof SessionBlockInput.Encoded;\nexport type EDASessionRunRequestOutcomeRpcInput = typeof SessionOutcomeInput.Encoded;\n\n/** EDA RPC methods required by the session namespace helper. */\nexport interface EDASessionRpcSurface {\n readonly runRequestOutcome: (\n input: EDASessionRunRequestOutcomeRpcInput,\n ) => Promise<typeof edaSessionRpc.runRequestOutcome.output.Encoded>;\n readonly grantRun: (\n input: EDASessionGrantRunRpcInput,\n ) => Promise<typeof edaSessionRpc.grantRun.output.Encoded>;\n readonly submit: (\n input: EDASessionCommandRpcInput,\n ) => Promise<typeof edaSessionRpc.submit.output.Encoded>;\n readonly submitBatch: (\n input: EDASessionSubmitBatchRpcInput,\n ) => Promise<typeof edaSessionRpc.submitBatch.output.Encoded>;\n readonly submitAndBlock: (\n input: EDASessionCommandRpcInput,\n ) => Promise<typeof edaSessionRpc.submitAndBlock.output.Encoded>;\n readonly blockOnCommand: (\n input: EDASessionBlockOnCommandRpcInput,\n ) => Promise<typeof edaSessionRpc.blockOnCommand.output.Encoded>;\n readonly snapshot: (\n input: EDASessionScopedRpcInput,\n ) => Promise<typeof edaSessionRpc.snapshot.output.Encoded>;\n readonly messages: (\n input: EDASessionScopedRpcInput,\n ) => Promise<typeof edaSessionRpc.messages.output.Encoded>;\n readonly destroySession: (\n input: EDASessionScopedRpcInput,\n ) => Promise<typeof edaSessionRpc.destroySession.output.Encoded>;\n readonly transcriptStatus: (\n input: EDASessionScopedRpcInput,\n ) => Promise<typeof edaSessionRpc.transcriptStatus.output.Encoded>;\n readonly readTranscriptWindow: (\n input: typeof SessionTranscriptWindowInput.Encoded,\n ) => Promise<typeof edaSessionRpc.readTranscriptWindow.output.Encoded>;\n readonly readTranscriptBody: (\n input: typeof SessionTranscriptBodyInput.Encoded,\n ) => Promise<typeof edaSessionRpc.readTranscriptBody.output.Encoded>;\n readonly readTranscriptSummary: (\n input: typeof SessionTranscriptSummaryInput.Encoded,\n ) => Promise<typeof edaSessionRpc.readTranscriptSummary.output.Encoded>;\n}\n\n/** Host transcript configuration of a session Durable Object. */\nexport interface EDASessionTranscriptOptions {\n /**\n * Which sessions maintain a transcript; default **off**. A disabled session gets no transcript\n * writes, builder slices or wakeups: `readTranscriptWindow` answers `Disabled`,\n * `transcriptStatus` reports `Disabled` without writing, and transcript sockets are\n * refused. Enabling a session takes the first-introduction path (a build from the log, then\n * activation). Rollout rings use a deterministic predicate (for example a hash of the session\n * id under a percentage); disabling leaves a session's rows untouched, and re-enabling catches\n * an active version up to the head before it is served as current. Evaluated once per object\n * instance, so a change takes effect when the object next starts.\n */\n readonly enabled?: boolean | ((sessionId: SessionId) => boolean);\n /**\n * Builder bounds: events per slice, rows deleted per slice, and `maxSliceFailures` (default 5),\n * the consecutive failures after which a build freezes as failed and a failing builder alarm\n * stops scheduling itself.\n */\n readonly sliceLimits?: Partial<DurableObjectTranscriptSliceLimits>;\n /**\n * The transcript definitions this release carries. Defaults to the definition with no host\n * mappings. A host changing its mappings ships `current` = new, `previous` = old, then runs\n * its backfill through `transcriptStatus` (see `docs/transcript-history.md` §7).\n */\n readonly definitions?: TranscriptMaintenanceConfig;\n /**\n * Adopt the host's existing log incarnation from this `ctx.storage.kv` key (Gia:\n * `gia.log_incarnation`). Without it the adapter mints its own.\n */\n readonly adoptIncarnationKey?: string;\n /** Alerts (frozen versions, missed sessions). Defaults to `console.error`. */\n readonly onAlert?: (alert: TranscriptAlert) => void;\n /** A rebuilt version became active. */\n readonly onActivated?: DurableObjectTranscriptObserver[\"onActivated\"];\n}\n\n/** Constructor options for concrete app subclasses of the EDA Durable Object base. */\nexport type EDASessionDurableObjectOptions<ProjectionState extends object = never> = Omit<\n EDASessionControllerOptions<ProjectionState>,\n \"alarmStorage\" | \"background\" | \"getWebSockets\" | \"storage\" | \"transcript\" | \"transcriptSockets\"\n> & {\n readonly transcript?: EDASessionTranscriptOptions;\n /**\n * Serve transcript-window sockets (`?stream=transcript`). `transcriptStore` defaults to this\n * object's own runtime-free Durable Object transcript store.\n */\n readonly transcriptSockets?: Omit<EDATranscriptSocketOptions, \"transcriptStore\"> & {\n readonly transcriptStore?: EDATranscriptSocketOptions[\"transcriptStore\"];\n };\n};\n\n/** Slices a backfill `transcriptStatus` call may run before it returns. */\nconst transcriptStatusMaxSlices = 16;\n/** Server bounds on one `readTranscriptWindow` RPC, whatever limits the caller asks for. */\nconst transcriptWindowMaxRecords = 500;\nconst transcriptWindowMaxBytes = 8 * 1_048_576;\n/** First retry delay after a failed builder alarm; doubled per consecutive failure. */\nconst transcriptBuilderRetryDelayMs = 30_000;\n/** Slices one builder alarm runs before rescheduling itself. */\nconst transcriptAlarmMaxSlices = 4;\n\n/** Resolve a concrete EDA session Durable Object binding by domain session id. */\nexport const getEDASessionDurableObjectByName = <\n T extends Rpc.DurableObjectBranded & EDASessionRpcSurface,\n>(\n namespace: DurableObjectNamespace<T>,\n sessionId: string,\n): DurableObjectStub<T> => namespace.getByName(sessionId);\n\n/**\n * Base class for raw Cloudflare Durable Object hosts of one EDA session.\n *\n * Concrete products should extend this class, pass provider/tool layers from\n * their own constructor, and register only that subclass in Wrangler. The base\n * class is deliberately not exported from `workers/app.ts` and owns no binding\n * name or routing convention.\n */\nexport abstract class EDASessionDurableObject<\n EnvType extends object = object,\n ProjectionState extends object = never,\n> extends DurableObject<EnvType> {\n readonly #controller: EDASessionController<ProjectionState>;\n readonly #webSocketProjectionId: string | undefined;\n readonly #alarms: DurableObjectAlarmScheduler;\n readonly #transcriptOptions: DurableObjectTranscriptOptions;\n #transcript:\n | {\n readonly sessionId: SessionId;\n /** Whether the host enabled transcript maintenance for this session. */\n readonly enabled: boolean;\n readonly store: DurableObjectTranscriptStore;\n readonly builder: DurableObjectTranscriptBuilder;\n }\n | undefined;\n readonly #transcriptEnabled: (sessionId: SessionId) => boolean;\n\n protected constructor(\n ctx: DurableObjectState,\n env: EnvType,\n options: EDASessionDurableObjectOptions<ProjectionState>,\n ) {\n super(ctx, env);\n this.#webSocketProjectionId = options.webSocketProjection?.id;\n const storage = toEDASessionStorage(this.ctx.storage);\n this.#alarms = new DurableObjectAlarmScheduler(storage);\n const { transcript: transcriptHostOptions, transcriptSockets, ...controllerOptions } = options;\n const transcript = this.transcriptOptions(transcriptHostOptions);\n this.#transcriptOptions = transcript;\n const enabled = transcriptHostOptions?.enabled ?? false;\n this.#transcriptEnabled = typeof enabled === \"function\" ? enabled : () => enabled;\n this.#controller = new EDASessionController({\n ...controllerOptions,\n alarmStorage: this.#alarms.owner(\"runtime\"),\n background: this.ctx,\n getWebSockets: () => this.ctx.getWebSockets(),\n storage,\n // The runtime's store maintains the transcript only for an enabled session.\n transcript: ({ sessionId }) =>\n this.transcriptFor(sessionId).enabled ? transcript : undefined,\n ...(transcriptSockets === undefined\n ? {}\n : {\n transcriptSockets: {\n ...transcriptSockets,\n transcriptStore: transcriptSockets.transcriptStore ?? this.transcriptPort(),\n },\n }),\n });\n\n // Answer client liveness pings at the runtime layer so idle sockets never\n // wake a hibernated object.\n this.ctx.setWebSocketAutoResponse(\n new WebSocketRequestResponsePair(EDA_WEB_SOCKET_PING_MESSAGE, EDA_WEB_SOCKET_PONG_MESSAGE),\n );\n\n this.ctx.blockConcurrencyWhile(async () => {\n await Effect.runPromise(EDASessionController.migrate(storage));\n // Keep an alarm armed by an earlier release for the runtime, then resume any builder\n // work an earlier instance left (or a new release created).\n await this.#alarms.adoptUnrecordedAlarm();\n await this.maintainedTranscript()?.builder.start();\n });\n }\n\n async fetch(request: Request): Promise<Response> {\n const upgrade = request.headers.get(\"Upgrade\");\n if (upgrade?.toLowerCase() !== \"websocket\") {\n return new Response(\"Expected WebSocket upgrade.\", { status: 426 });\n }\n\n const url = new URL(request.url);\n const sessionIdRaw = url.searchParams.get(\"sessionId\");\n if (sessionIdRaw === null) {\n return new Response(\"Missing sessionId.\", { status: 400 });\n }\n const afterSeqRaw = url.searchParams.get(\"afterSeq\");\n const afterSeq = afterSeqRaw === null ? undefined : Number(afterSeqRaw);\n if (afterSeq !== undefined && (!Number.isInteger(afterSeq) || afterSeq < 0)) {\n return new Response(\"Invalid afterSeq.\", { status: 400 });\n }\n const projectionId = request.headers.get(EDA_WEB_SOCKET_PROJECTION_HEADER) ?? undefined;\n if (projectionId !== undefined && projectionId !== this.#webSocketProjectionId) {\n return new Response(\"Unsupported WebSocket projection.\", { status: 400 });\n }\n\n const sessionId = this.parseSessionIdOrUndefined(sessionIdRaw);\n if (sessionId === undefined) {\n return new Response(\"This object does not serve that session.\", { status: 400 });\n }\n const trace = traceMetadataFromRequest(request);\n\n if (url.searchParams.get(EDA_WEB_SOCKET_STREAM_PARAM) === \"transcript\") {\n if (projectionId !== undefined || !this.#controller.supportsTranscriptWebSocket) {\n return new Response(\"Unsupported transcript stream.\", { status: 400 });\n }\n if (!this.transcriptFor(sessionId).enabled) {\n return new Response(\"Transcript is not enabled for this session.\", { status: 409 });\n }\n const pair = new WebSocketPair();\n this.ctx.acceptWebSocket(pair[1]);\n this.#controller.acceptTranscriptWebSocket({ sessionId, trace, webSocket: pair[1] });\n return new Response(null, { status: 101, webSocket: pair[0] });\n }\n\n const prepared = await this.#controller.prepareEventWebSocket({\n ...(afterSeq === undefined ? {} : { afterSeq: SequenceNumber.make(afterSeq) }),\n sessionId,\n trace,\n ...(projectionId === undefined ? {} : { projectionId }),\n });\n\n const pair = new WebSocketPair();\n const client = pair[0];\n const server = pair[1];\n this.ctx.acceptWebSocket(server);\n await this.#controller.acceptPreparedEventWebSocket({\n ...prepared,\n webSocket: server,\n });\n return new Response(null, { status: 101, webSocket: client });\n }\n\n async submit(\n raw: typeof SessionCommandInput.Encoded,\n ): Promise<typeof edaSessionRpc.submit.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionCommandInput)(raw);\n const committed = await this.#controller.submit({\n command: input.command,\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return encodeEdaRpcCommittedDurableEvent(committed);\n }\n\n /** Reconcile lost grant replies from durable request and run facts. */\n async runRequestOutcome(\n raw: typeof SessionOutcomeInput.Encoded,\n ): Promise<typeof edaSessionRpc.runRequestOutcome.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionOutcomeInput)(raw);\n const result = await this.#controller.runRequestOutcome({\n requestId: Schema.decodeUnknownSync(RunRequestId)(input.requestId),\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return Schema.encodeSync(edaSessionRpc.runRequestOutcome.output)(result);\n }\n\n /** Trusted RPC only: the calling Worker owns scheduler authentication and authorization. */\n async grantRun(\n raw: typeof SessionGrantRunInput.Encoded,\n ): Promise<typeof edaSessionRpc.grantRun.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionGrantRunInput)(raw);\n const command = input.command;\n const result = await this.#controller.grantRun({\n command,\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return Schema.encodeSync(edaSessionRpc.grantRun.output)(result);\n }\n\n async submitBatch(\n raw: typeof SessionBatchInput.Encoded,\n ): Promise<typeof edaSessionRpc.submitBatch.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionBatchInput)(raw);\n const committed = await this.#controller.submitBatch({\n items: input.items,\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return committed.map(encodeEdaRpcCommittedDurableEvent);\n }\n\n async submitAndBlock(\n raw: typeof SessionCommandInput.Encoded,\n ): Promise<typeof edaSessionRpc.submitAndBlock.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionCommandInput)(raw);\n const committed = await this.#controller.submitAndBlock({\n command: input.command,\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return Schema.encodeSync(edaSessionRpc.submitAndBlock.output)(committed);\n }\n\n async blockOnCommand(\n raw: typeof SessionBlockInput.Encoded,\n ): Promise<typeof edaSessionRpc.blockOnCommand.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionBlockInput)(raw);\n const committed = await this.#controller.blockOnCommand({\n ...(input.afterSeq === undefined ? {} : { afterSeq: SequenceNumber.make(input.afterSeq) }),\n commandId: CommandId.make(input.commandId),\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return Schema.encodeSync(edaSessionRpc.blockOnCommand.output)(committed);\n }\n\n async snapshot(\n raw: typeof SessionScopedInput.Encoded,\n ): Promise<typeof edaSessionRpc.snapshot.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionScopedInput)(raw);\n const snapshot = await this.#controller.snapshot({\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return Schema.encodeSync(edaSessionRpc.snapshot.output)(snapshot);\n }\n\n async messages(\n raw: typeof SessionScopedInput.Encoded,\n ): Promise<typeof edaSessionRpc.messages.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionScopedInput)(raw);\n const result = await this.#controller.messages({\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return Schema.encodeSync(edaSessionRpc.messages.output)(result);\n }\n\n async webSocketMessage(webSocket: WebSocket, message: string | ArrayBuffer): Promise<void> {\n await this.#controller.webSocketMessage(webSocket, message);\n }\n\n async webSocketClose(\n webSocket: WebSocket,\n _code: number,\n _reason: string,\n _wasClean: boolean,\n ): Promise<void> {\n this.#controller.webSocketClose(webSocket);\n }\n\n async webSocketError(webSocket: WebSocket, _error: unknown): Promise<void> {\n this.#controller.webSocketError(webSocket);\n }\n\n async destroySession(\n raw: typeof SessionScopedInput.Encoded,\n ): Promise<typeof edaSessionRpc.destroySession.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionScopedInput)(raw);\n await this.#controller.destroy({\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n await this.ctx.storage.deleteAlarm();\n await this.ctx.storage.deleteAll();\n // The wiped storage is a brand-new log: recreate the tables storage-only entry points read,\n // synchronously, so no other work observes the object without them.\n Effect.runSync(EDASessionController.migrate(toEDASessionStorage(this.ctx.storage)));\n }\n\n /**\n * Storage-only backfill entry point: advance pending transcript build work by bounded slices\n * and return the transcript status. It never starts the model runtime, reducers or sinks.\n */\n async transcriptStatus(\n raw: typeof SessionScopedInput.Encoded,\n ): Promise<typeof edaSessionRpc.transcriptStatus.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionScopedInput)(raw);\n const transcript = this.transcriptFor(this.parseSessionId(input.sessionId));\n if (!transcript.enabled) {\n return Schema.encodeSync(edaSessionRpc.transcriptStatus.output)(\n transcript.store.disabledStatus(),\n );\n }\n await transcript.builder.run(transcriptStatusMaxSlices);\n return Schema.encodeSync(edaSessionRpc.transcriptStatus.output)(transcript.store.status());\n }\n\n /** Runtime-free transcript window read for SSR and CLIs. Hosts authorize the caller. */\n async readTranscriptWindow(\n raw: typeof SessionTranscriptWindowInput.Encoded,\n ): Promise<typeof edaSessionRpc.readTranscriptWindow.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionTranscriptWindowInput)(raw);\n const transcript = this.transcriptFor(this.parseSessionId(input.sessionId));\n if (!transcript.enabled) {\n return Schema.encodeSync(edaSessionRpc.readTranscriptWindow.output)({ _tag: \"Disabled\" });\n }\n const limits = input.limits ?? defaultTranscriptWindowLimits;\n const window = transcript.store.readWindow(input.selector, {\n ...limits,\n maxRecords: Math.min(limits.maxRecords, transcriptWindowMaxRecords),\n maxBytes: Math.min(limits.maxBytes, transcriptWindowMaxBytes),\n });\n return Schema.encodeSync(edaSessionRpc.readTranscriptWindow.output)(\n Result.isSuccess(window)\n ? { _tag: \"Window\", window: window.success }\n : { _tag: \"CursorMismatch\", message: window.failure.message },\n );\n }\n\n /**\n * Runtime-free read of the body a transcript `Ref` names, resolved through the immutable log\n * (so it stays valid after projection rows are rebuilt). Hosts authorize the caller.\n */\n async readTranscriptBody(\n raw: typeof SessionTranscriptBodyInput.Encoded,\n ): Promise<typeof edaSessionRpc.readTranscriptBody.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionTranscriptBodyInput)(raw);\n const scope = this.transcriptReadScope(input.sessionId, input.incarnation);\n if (scope._tag !== \"Scope\") {\n return Schema.encodeSync(edaSessionRpc.readTranscriptBody.output)(scope);\n }\n const sessionId = scope.sessionId;\n const committed = readDurableObjectCommittedEvent(\n toEDASessionStorage(this.ctx.storage).sql,\n sessionId,\n input.source.seq,\n );\n const resolved =\n committed === undefined\n ? ({ _tag: \"Missing\", message: `no event at seq ${input.source.seq}` } as const)\n : resolveTranscriptBody(committed.event, input.source.path);\n return Schema.encodeSync(edaSessionRpc.readTranscriptBody.output)(\n resolved._tag === \"Found\"\n ? { _tag: \"Body\", value: resolved.value }\n : { _tag: \"NotFound\", message: resolved.message },\n );\n }\n\n /** Runtime-free read of a compaction summary's text. Hosts authorize the caller. */\n async readTranscriptSummary(\n raw: typeof SessionTranscriptSummaryInput.Encoded,\n ): Promise<typeof edaSessionRpc.readTranscriptSummary.output.Encoded> {\n const input = Schema.decodeUnknownSync(SessionTranscriptSummaryInput)(raw);\n const scope = this.transcriptReadScope(input.sessionId, input.incarnation);\n if (scope._tag !== \"Scope\") {\n return Schema.encodeSync(edaSessionRpc.readTranscriptSummary.output)(scope);\n }\n const artifact = readDurableObjectSummary(\n toEDASessionStorage(this.ctx.storage).sql,\n input.summaryId,\n );\n return Schema.encodeSync(edaSessionRpc.readTranscriptSummary.output)(\n artifact === undefined\n ? { _tag: \"NotFound\", message: `no summary ${input.summaryId}` }\n : {\n _tag: \"Summary\",\n summary: {\n compactionId: artifact.compactionId,\n summaryId: artifact.summaryId,\n text: artifact.text,\n sourceFromSeq: artifact.sourceFromSeq,\n sourceToSeq: artifact.sourceToSeq,\n },\n },\n );\n }\n\n /**\n * The alarm is shared by the runtime heartbeat and the transcript builder; see\n * `runEDASessionAlarm`.\n */\n async alarm(): Promise<void> {\n const transcript = this.maintainedTranscript();\n await runEDASessionAlarm({\n alarms: this.#alarms,\n now: () => Date.now(),\n runRuntime: async () => {\n const sessionId = this.sessionIdFromObjectName();\n await this.#controller.alarm(\n sessionId === undefined ? undefined : { sessionId, trace: makeRootEDATraceMetadata() },\n );\n },\n runBuilderSlices:\n transcript === undefined\n ? undefined\n : () => transcript.builder.runSlices(transcriptAlarmMaxSlices),\n maxBuilderFailures:\n this.#transcriptOptions.sliceLimits?.maxSliceFailures ??\n defaultTranscriptSliceLimits.maxSliceFailures,\n builderRetryDelayMs: transcriptBuilderRetryDelayMs,\n onBuilderFailure: ({ error, consecutiveFailures, stopped }) => {\n console.error(\"EDA transcript builder slice failed\", error);\n if (stopped) {\n transcript?.store.alert({\n _tag: \"BuilderStopped\",\n consecutiveFailures,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n },\n });\n }\n\n private transcriptOptions(\n options: EDASessionTranscriptOptions | undefined,\n ): DurableObjectTranscriptOptions {\n const key = options?.adoptIncarnationKey;\n return {\n definitions: options?.definitions ?? {\n current: Effect.runSync(makeTranscriptDefinition(emptyTranscriptMappings)),\n },\n ...(key === undefined ? {} : { adoptIncarnation: { key, kv: this.ctx.storage.kv } }),\n // Validated here so a misconfigured host fails at construction, not on a failing slice.\n sliceLimits: resolveTranscriptSliceLimits(options?.sliceLimits),\n observer: {\n onAlert:\n options?.onAlert ??\n ((alert) => console.error(\"EDA transcript alert\", JSON.stringify(alert))),\n onPendingWork: () => {\n const builder = this.maintainedTranscript()?.builder;\n if (builder !== undefined) this.ctx.waitUntil(builder.kick());\n },\n onServedChanged: () => {\n // A behind active version reached the head, or the active version froze: sockets re-read.\n this.ctx.waitUntil(this.#controller.refreshTranscriptWebSockets());\n },\n onActivated: (activation) => {\n // Connected transcript sockets get one complete replacement in the new version.\n this.ctx.waitUntil(this.#controller.refreshTranscriptWebSockets());\n options?.onActivated?.(activation);\n },\n },\n };\n }\n\n /** This object's transcript store as the port transcript sockets read, resolved per call. */\n private transcriptPort(): EDATranscriptStoreShape {\n const port = () => this.maintainedTranscript()?.store.port;\n const unbound = () =>\n Effect.fail(\n new EDASessionStoreError({\n message:\n this.objectTranscript()?.enabled === false\n ? \"EDA transcript is not enabled for this session\"\n : \"EDA transcript read before the session was named\",\n }),\n );\n return {\n readTranscriptWindow: (selector, limits) =>\n Effect.suspend(() => port()?.readTranscriptWindow(selector, limits) ?? unbound()),\n readTranscriptMeta: Effect.suspend(() => port()?.readTranscriptMeta ?? unbound()),\n };\n }\n\n /**\n * The session and log a body or summary read may serve: pinned to the session this object's\n * transcript serves, like window reads, and to the incarnation the caller's reference names.\n */\n private transcriptReadScope(\n rawSessionId: string,\n incarnation: TranscriptLogIncarnation,\n ):\n | { readonly _tag: \"Scope\"; readonly sessionId: SessionId }\n | { readonly _tag: \"Disabled\" }\n | { readonly _tag: \"IncarnationMismatch\"; readonly incarnation: TranscriptLogIncarnation } {\n const transcript = this.transcriptFor(this.parseSessionId(rawSessionId));\n // Outside the rollout nothing is initialized or minted, and no reference was ever served.\n if (!transcript.enabled) return { _tag: \"Disabled\" };\n const current = transcript.store.incarnation();\n return incarnation === current\n ? { _tag: \"Scope\", sessionId: transcript.sessionId }\n : { _tag: \"IncarnationMismatch\", incarnation: current };\n }\n\n /** The transcript service of this object's session, created on first use. */\n private transcriptFor(sessionId: SessionId) {\n if (this.#transcript !== undefined) {\n if (this.#transcript.sessionId !== sessionId) {\n throw new Error(\n `EDA transcript is scoped to session ${this.#transcript.sessionId}; received ${sessionId}`,\n );\n }\n return this.#transcript;\n }\n const store = new DurableObjectTranscriptStore({\n sessionId,\n storage: toEDASessionStorage(this.ctx.storage),\n transcript: this.#transcriptOptions,\n });\n const builder = new DurableObjectTranscriptBuilder(store, () =>\n this.#alarms.request(\"transcript\", Date.now()),\n );\n this.#transcript = { sessionId, enabled: this.#transcriptEnabled(sessionId), store, builder };\n return this.#transcript;\n }\n\n /** The transcript service when this object's session is enabled for maintenance. */\n private maintainedTranscript() {\n const transcript = this.objectTranscript();\n return transcript?.enabled === true ? transcript : undefined;\n }\n\n /** The transcript service when the object is named by a valid session id. */\n private objectTranscript() {\n if (this.#transcript !== undefined) return this.#transcript;\n const name = this.ctx.id.name;\n return name !== undefined && Schema.is(SessionId)(name)\n ? this.transcriptFor(SessionId.make(name))\n : undefined;\n }\n\n /** `parseSessionId` for request paths that answer a foreign session with a 400. */\n private parseSessionIdOrUndefined(input: string): SessionId | undefined {\n if (!Schema.is(SessionId)(input)) return undefined;\n const name = this.ctx.id.name;\n if (name !== undefined && name !== input) return undefined;\n const bound = this.#transcript?.sessionId;\n return bound === undefined || bound === input ? SessionId.make(input) : undefined;\n }\n\n private parseSessionId(input: string): SessionId {\n const sessionId = SessionId.make(input);\n const objectName = this.ctx.id.name;\n if (objectName !== undefined && objectName !== sessionId) {\n throw new Error(`EDA Durable Object name ${objectName} cannot serve session ${sessionId}`);\n }\n return sessionId;\n }\n\n private sessionIdFromObjectName(): SessionId | undefined {\n return this.ctx.id.name === undefined ? undefined : SessionId.make(this.ctx.id.name);\n }\n}\n\nconst toEDASessionStorage = (storage: DurableObjectStorage): EDASessionDurableObjectStorage => {\n // SAFETY: the adapter interface is the exact SQL, transaction, and alarm subset\n // of DurableObjectStorage; its looser row generic also supports test implementations.\n return storage as EDASessionDurableObjectStorage;\n};\n\nconst decodeTraceMetadata = (input: unknown): EDATraceMetadata =>\n Schema.decodeUnknownSync(EDATraceMetadata)(input);\n\nconst traceMetadataFromRequest = (request: Request): EDATraceMetadata => {\n const parent = parseEDATraceparent(\n request.headers.get(\"traceparent\"),\n request.headers.get(\"tracestate\"),\n );\n return parent === null ? makeRootEDATraceMetadata() : makeEDATraceMetadataFromParent(parent);\n};\n\n/** Convenience config constructor for subclasses that need only provider/model ids. */\nexport const edaRuntimeConfig = (input: {\n readonly maxToolCallsPerRun?: number;\n readonly modelId: string;\n readonly provider: string;\n readonly systemPrompt?: string;\n}): EDARuntimeConfig => ({\n modelSelection: { modelId: input.modelId, provider: input.provider },\n ...(input.maxToolCallsPerRun === undefined\n ? {}\n : { maxToolCallsPerRun: input.maxToolCallsPerRun }),\n ...(input.systemPrompt === undefined ? {} : { systemPrompt: input.systemPrompt }),\n});\n\n/** Encode committed events into the existing structured-clone envelope. */\nexport const encodeEdaRpcCommittedDurableEvent = (\n entry: CommittedDurableEvent,\n): typeof edaSessionRpc.submit.output.Encoded => ({\n position: entry.position,\n event: encodeEdaRpcDurableEvent(durableEventEnvelope(entry.event)),\n});\n/** Encode query snapshots without asserting that encoded command values are decoded classes. */\nexport const encodeEdaRpcSessionSnapshot = Schema.encodeSync(edaSessionRpc.snapshot.output);\n"],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ import { SequenceNumber, SessionId } from "effect-durable-agent/types/core";
2
+ import { CommittedDurableEvent } from "effect-durable-agent/services/session-store";
3
+ import { TranscriptLogIncarnation, TranscriptMaintenanceConfig, TranscriptVersion, TranscriptVersionMeta } from "effect-durable-agent/transcript";
4
+ //#region src/durable-object-transcript-tables.d.ts
5
+ /**
6
+ * A host's existing synchronous key/value incarnation to adopt (Gia: `gia.log_incarnation` in the
7
+ * Durable Object's `ctx.storage.kv`). The adapter adopts the host's value when one exists and
8
+ * otherwise writes the value it mints there too, so host and adapter always name the same log.
9
+ */
10
+ interface AdoptedLogIncarnation {
11
+ readonly key: string;
12
+ readonly kv: {
13
+ readonly get: (key: string) => unknown;
14
+ readonly put: (key: string, value: string) => void;
15
+ };
16
+ }
17
+ //#endregion
18
+ //#region src/durable-object-transcript-maintenance.d.ts
19
+ /**
20
+ * Something an operator must look at, raised after the transaction that caused it commits.
21
+ *
22
+ * - `ProjectionFailed`: a version froze at its last good cursor (§5.2). On the active version
23
+ * readers see a degraded tail until a new definition rebuilds it; on a building version the
24
+ * active version keeps serving and the backfill reports it.
25
+ * - `MissedSession`: the active version is one this release no longer carries, so its history is
26
+ * frozen behind the log and `current` is being built at once (§7 safety net).
27
+ * - `BuilderStopped`: the builder alarm failed `consecutiveFailures` times in a row, typically
28
+ * for a reason no build is charged for (cleanup or reconciliation, or a failure record storage
29
+ * refused), so the builder stopped scheduling itself. A later object start, `transcriptStatus`
30
+ * call or pending-work kick tries again, bounded the same way, and may raise it again.
31
+ */
32
+ type TranscriptAlert = {
33
+ readonly _tag: "ProjectionFailed";
34
+ readonly version: TranscriptVersion;
35
+ readonly role: "active" | "building";
36
+ readonly failedAtSeq: SequenceNumber;
37
+ readonly error: string;
38
+ } | {
39
+ readonly _tag: "MissedSession";
40
+ readonly activeVersion: TranscriptVersion;
41
+ readonly currentVersion: TranscriptVersion;
42
+ } | {
43
+ readonly _tag: "BuilderStopped";
44
+ readonly consecutiveFailures: number;
45
+ readonly error: string;
46
+ };
47
+ /**
48
+ * Host hooks for transcript maintenance. Every hook runs only after the transaction that caused
49
+ * it has committed, so nothing observed here can be rolled back afterwards.
50
+ */
51
+ interface DurableObjectTranscriptObserver {
52
+ readonly onAlert?: (alert: TranscriptAlert) => void;
53
+ /** A built version became active; connected clients need a window replacement (§9.4). */
54
+ readonly onActivated?: (activation: {
55
+ readonly version: TranscriptVersion;
56
+ readonly previousVersion: TranscriptVersion | undefined;
57
+ }) => void;
58
+ /** Bounded builder or cleanup work is pending; the host schedules a slice. */
59
+ readonly onPendingWork?: () => void;
60
+ /**
61
+ * What reads serve changed without a publication, so connected clients need a re-read: an
62
+ * active version that was behind the head (a re-enabled session) reached it (`UpdatingHistory`
63
+ * becomes `Ready`), or the active version froze (it becomes `Degraded`).
64
+ */
65
+ readonly onServedChanged?: () => void;
66
+ }
67
+ /** Bounds on one builder slice. */
68
+ interface DurableObjectTranscriptSliceLimits {
69
+ /** Log events projected into the building version per slice. */
70
+ readonly maxEvents: number;
71
+ /** Events decoded and planned together; matches the store's bounded event read page. */
72
+ readonly pageEvents: number;
73
+ /** Rows of retired versions deleted per slice. */
74
+ readonly maxDeletedRows: number;
75
+ /**
76
+ * Consecutive slices that may throw while advancing one build target before it is frozen as
77
+ * failed (and so never retried). The session object also stops its builder alarm after this
78
+ * many consecutive failed alarms.
79
+ */
80
+ readonly maxSliceFailures: number;
81
+ }
82
+ /** Transcript maintenance configuration of one session store. */
83
+ interface DurableObjectTranscriptOptions {
84
+ /** The definitions this release carries; supplied by the host. */
85
+ readonly definitions: TranscriptMaintenanceConfig;
86
+ /** Adopt a host's existing log incarnation instead of minting a new one. */
87
+ readonly adoptIncarnation?: AdoptedLogIncarnation;
88
+ readonly observer?: DurableObjectTranscriptObserver;
89
+ readonly sliceLimits?: Partial<DurableObjectTranscriptSliceLimits>;
90
+ }
91
+ //#endregion
92
+ //#region src/durable-object-storage.d.ts
93
+ /**
94
+ * Minimal synchronous SQL cursor surface used by Cloudflare Durable Object storage.
95
+ *
96
+ * This type is host-only on purpose: framework services should depend on
97
+ * `EDASessionStore`, not Cloudflare's SQL API.
98
+ */
99
+ interface DurableObjectSqlCursor<Row> {
100
+ readonly one: () => Row;
101
+ readonly toArray: () => Array<Row>;
102
+ }
103
+ /** Minimal synchronous SQL executor surface used by Cloudflare Durable Object storage. */
104
+ interface DurableObjectSqlStorage {
105
+ readonly exec: <Row = Record<string, unknown>>(query: string, ...bindings: ReadonlyArray<unknown>) => DurableObjectSqlCursor<Row>;
106
+ }
107
+ /**
108
+ * Durable Object storage capabilities needed by EDA SQL adapters.
109
+ *
110
+ * The `transactionSync` callback must remain purely synchronous. Adapter code
111
+ * may run SQL here; model calls, live publish, and Effect suspension must stay
112
+ * outside the callback.
113
+ */
114
+ interface DurableObjectSessionStorage {
115
+ readonly sql: DurableObjectSqlStorage;
116
+ readonly transactionSync: <A>(closure: () => A) => A;
117
+ }
118
+ /**
119
+ * Construction options for one session-scoped Durable Object session store.
120
+ *
121
+ * One Durable Object SQLite database represents one EDA session, so `sessionId`
122
+ * is fixed at layer construction and not a method parameter.
123
+ */
124
+ interface DurableObjectSessionStoreOptions {
125
+ readonly sessionId: SessionId;
126
+ readonly storage: DurableObjectSessionStorage;
127
+ /**
128
+ * Transcript definitions to maintain inside every append. Without it the store maintains no
129
+ * transcript; the Durable Object host always supplies one.
130
+ */
131
+ readonly transcript?: DurableObjectTranscriptOptions;
132
+ }
133
+ //#endregion
134
+ export { DurableObjectTranscriptObserver as a, TranscriptAlert as c, DurableObjectSqlStorage as i, AdoptedLogIncarnation as l, DurableObjectSessionStoreOptions as n, DurableObjectTranscriptOptions as o, DurableObjectSqlCursor as r, DurableObjectTranscriptSliceLimits as s, DurableObjectSessionStorage as t };
135
+ //# sourceMappingURL=durable-object-storage-BVsu5oAV.d.ts.map