@effect-agent/platform-cloudflare 0.1.0-beta.55 → 0.1.0-beta.57

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":"ThreadObject-J5thaFpm.mjs","names":["EffectCfDurableObjectState","EffectCfDurableObject"],"sources":["../src/internal/message-delivery.ts","../src/internal/progress-wait.ts","../src/internal/transport.ts","../src/internal/layers.ts","../src/ThreadObject.ts"],"sourcesContent":["import {\n MessageDeliveryDriver,\n MessageDeliveryError,\n MessageDeliveryStore,\n} from \"@effect-agent/thread/MessageDelivery\";\nimport { Clock, Context, Effect, Layer, Option, Ref, Semaphore } from \"effect\";\n\nimport { DurableAlarmError, ThreadMessageDelivery, ThreadMutationGate } from \"../Alarm.ts\";\nimport { ThreadObjectIdentity } from \"../CloudflareBindings.ts\";\n\n/** Every externally requested write prearms the owning Object's maintenance generation. */\nexport const guardedMessageDeliveryStoreLayer = Layer.effect(\n MessageDeliveryStore,\n Effect.gen(function* () {\n const store = yield* MessageDeliveryStore;\n const mutations = yield* ThreadMutationGate;\n const { threadId } = yield* ThreadObjectIdentity;\n // Reconstructed as unknown on every incarnation. The gate prevents a racing read from\n // caching an empty deadline across a write; SQL remains the recovery authority.\n const deadline = yield* Ref.make<number | null | undefined>(undefined);\n const cacheGate = yield* Semaphore.make(1);\n\n const local = <A, E>(owner: string, body: Effect.Effect<A, E>) =>\n owner === threadId\n ? body\n : Effect.fail(\n MessageDeliveryError.make({ reason: \"validation\", operation: \"message owner\" }),\n );\n\n const mutate = <A, E>(body: Effect.Effect<A, E>) =>\n mutations\n .withMutation(cacheGate.withPermit(Ref.set(deadline, undefined).pipe(Effect.andThen(body))))\n .pipe(\n Effect.catchTag(\"DurableAlarmError\", () =>\n MessageDeliveryError.make({ reason: \"storage\", operation: \"prearm message delivery\" }),\n ),\n );\n\n const nextDeadline = cacheGate.withPermit(\n Effect.gen(function* () {\n const cached = yield* Ref.get(deadline);\n\n if (cached !== undefined) return cached;\n const current = yield* store.nextDeadline(threadId);\n\n yield* Ref.set(deadline, current);\n\n return current;\n }),\n );\n\n return MessageDeliveryStore.of({\n insert: (record) => local(record.key.ownerThreadId, mutate(store.insert(record))),\n get: (key) => local(key.ownerThreadId, store.get(key)),\n list: (request) => local(request.ownerThreadId, store.list(request)),\n change: (key, change) => local(key.ownerThreadId, mutate(store.change(key, change))),\n due: (nowMillis, limit, owner = threadId) =>\n local(owner, store.due(nowMillis, limit, threadId)),\n nextDeadline: (owner = threadId) => local(owner, nextDeadline),\n });\n }),\n);\n\n/** Message progress shares the native alarm slot without blocking source runtime work. */\nexport const threadMessageDeliveryLayer = Layer.effectContext(\n Effect.gen(function* () {\n const driver = yield* MessageDeliveryDriver;\n const store = yield* MessageDeliveryStore;\n const { threadId } = yield* ThreadObjectIdentity;\n\n const failure = (operation: string) => () =>\n DurableAlarmError.make({\n operation,\n message: \"Durable message recovery remains pending\",\n });\n\n return Context.make(ThreadMessageDelivery, {\n drain: Effect.gen(function* () {\n const deadline = yield* store.nextDeadline(threadId);\n\n if (deadline !== null && deadline <= (yield* Clock.currentTimeMillis)) {\n yield* driver.runDue(threadId);\n }\n }).pipe(Effect.mapError(failure(\"drain message delivery\"))),\n pendingDeadline: store\n .nextDeadline(threadId)\n .pipe(Effect.map(Option.fromNullishOr), Effect.mapError(failure(\"read message deadline\"))),\n });\n }),\n);\n","import { Context, Deferred, Effect, Layer, Ref, type Scope } from \"effect\";\n\n/** Cancellation tombstones are bounded hints, never durable authority. */\nconst MAX_CANCELLATION_TOMBSTONES = 1_024;\n\ntype ActiveRegistration = ReadonlySet<Deferred.Deferred<void>>;\ntype Registration = ActiveRegistration | \"cancelled\";\ntype Registrations = ReadonlyMap<string, Registration>;\n\n/**\n * Per-incarnation cancellation registry for long-lived progress RPCs. The public runtime owns\n * the actual wake registration; this host-only registry lets an interrupted Worker Effect ask\n * the Object to interrupt its scoped wait before the Worker execution context itself ends.\n */\nexport class ProgressWaitRegistry extends Context.Service<\n ProgressWaitRegistry,\n {\n /** Register a Scope-owned cancellation signal, observing any early cancel tombstone. */\n readonly subscribe: (\n waiterId: string,\n ) => Effect.Effect<Effect.Effect<void>, never, Scope.Scope>;\n /** Cancel every attempt and retain a bounded tombstone for later transport attempts. */\n readonly cancel: (waiterId: string) => Effect.Effect<void>;\n }\n>()(\"@effect-agent/platform-cloudflare/ProgressWaitRegistry\") {\n static readonly layer: Layer.Layer<ProgressWaitRegistry> = Layer.effect(\n ProgressWaitRegistry,\n Effect.gen(function* () {\n const registrations = yield* Ref.make<Registrations>(new Map());\n\n const remove = (waiterId: string, deferred: Deferred.Deferred<void>) =>\n Ref.update(registrations, (current) => {\n const existing = current.get(waiterId);\n\n if (existing === undefined || existing === \"cancelled\" || !existing.has(deferred)) {\n return current;\n }\n const next = new Map(current);\n const active = new Set(existing);\n\n active.delete(deferred);\n if (active.size === 0) {\n next.delete(waiterId);\n } else {\n next.set(waiterId, active);\n }\n\n return next;\n });\n\n const subscribe = Effect.fn(\"ProgressWaitRegistry.subscribe\")(\n (waiterId: string): Effect.Effect<Effect.Effect<void>, never, Scope.Scope> =>\n Effect.gen(function* () {\n const deferred = yield* Deferred.make<void>();\n\n yield* Effect.addFinalizer(() => remove(waiterId, deferred));\n\n const cancelled = yield* Ref.modify(registrations, (current) => {\n const existing = current.get(waiterId);\n const next = new Map(current);\n\n if (existing === \"cancelled\") {\n return [true, current] as const;\n }\n const active = new Set(existing ?? []);\n\n active.add(deferred);\n next.set(waiterId, active);\n\n return [false, next] as const;\n });\n\n return { cancelled, deferred };\n }).pipe(\n Effect.map(({ cancelled, deferred }) =>\n cancelled ? Effect.void : Deferred.await(deferred),\n ),\n ),\n );\n\n // Updating the registry and completing captured signals form one nonblocking operation;\n // interruption between them must not strand attempts removed from the active registry.\n const cancel = Effect.fn(\"ProgressWaitRegistry.cancel\")(function* (waiterId: string) {\n const waiters = yield* Ref.modify(\n registrations,\n (current): readonly [ReadonlyArray<Deferred.Deferred<void>>, Registrations] => {\n const existing = current.get(waiterId);\n\n if (existing === \"cancelled\") return [[], current] as const;\n const next = new Map(current);\n\n // A retry may arrive after an active attempt was cancelled. Retain the same\n // tombstone used for early cancellation, ordered by cancellation time.\n next.delete(waiterId);\n next.set(waiterId, \"cancelled\");\n let tombstones = 0;\n\n for (const registration of next.values()) {\n if (registration === \"cancelled\") tombstones += 1;\n }\n if (tombstones > MAX_CANCELLATION_TOMBSTONES) {\n for (const [id, registration] of next) {\n if (registration !== \"cancelled\") continue;\n next.delete(id);\n break;\n }\n }\n\n return [existing === undefined ? [] : [...existing], next] as const;\n },\n );\n\n yield* Effect.forEach(waiters, (waiter) => Deferred.succeed(waiter, undefined), {\n discard: true,\n });\n }, Effect.uninterruptible);\n\n return ProgressWaitRegistry.of({ subscribe, cancel });\n }),\n );\n}\n","import {\n ThreadPortTransport,\n portTransportFailure,\n} from \"@effect-agent/storage-cloudflare/PortRouting\";\nimport { Effect, Layer } from \"effect\";\n\nimport { ThreadObjectNamespace } from \"../CloudflareBindings.ts\";\n\n/**\n * `ThreadPortTransport` over native Durable Object JS RPC (decision D-P6-3): one\n * `portCall(envelope)` on the stub of the Object that owns the addressed Thread\n * (`namespace.idFromName(threadId)` — the identity rule, plan §1.2). The envelopes are\n * already Schema-encoded JSON, so the RPC boundary carries only structured-cloneable values;\n * the protocol module stays transport-agnostic and fetch-with-JSON remains the documented\n * fallback carrier.\n *\n * Every delivery problem — stub construction, RPC rejection, overload, deploy-in-progress —\n * surfaces as `PortTransportError` (preserving the platform stub's own `retryable` signal\n * when present) and NEVER as a fabricated answer: on `resolveAdmission` the routing layer\n * turns exactly this error into `AdmissionIndeterminate` (SUB-031).\n */\nexport const threadPortTransportLayer: Layer.Layer<\n ThreadPortTransport,\n never,\n ThreadObjectNamespace\n> = Layer.effect(ThreadPortTransport)(\n Effect.gen(function* () {\n const { namespace } = yield* ThreadObjectNamespace;\n\n return ThreadPortTransport.of({\n call: (threadId, request) =>\n Effect.tryPromise({\n try: () => namespace.get(namespace.idFromName(threadId)).portCall(request),\n catch: (cause) => portTransportFailure(threadId, cause),\n }).pipe(\n Effect.withSpan(\"CloudflarePortTransport.call\", {\n attributes: { threadId },\n }),\n ),\n });\n }),\n);\n","import { ThreadId } from \"@effect-agent/core/Identifiers\";\nimport {\n type RunContextPreparation,\n type RunCostEstimator,\n type RunToolFailureObserver,\n} from \"@effect-agent/engine/RunOptions\";\nimport {\n CurrentToolFailureObserver,\n RunContextPreparationPassthrough,\n RunToolAuthorization,\n toolFailureObserverLayer,\n} from \"@effect-agent/engine/RunOptions\";\nimport { doMessageDeliveryStoreLayer } from \"@effect-agent/storage-cloudflare/DoMessageDeliveryStore\";\nimport {\n type DoStorageFailpointHandler,\n type DoStorageFailpoint,\n} from \"@effect-agent/storage-cloudflare/DoStorageFailpoint\";\nimport { submissionLedgerLayer } from \"@effect-agent/storage-cloudflare/DoSubmissionLedger\";\nimport {\n threadStoreLayer,\n storageConfigLayer,\n storageFailpointLayer,\n type DoStorageInitializationError,\n type DoStorageOptions,\n} from \"@effect-agent/storage-cloudflare/DoThreadStore\";\nimport { type PortRequest, type PortResponse } from \"@effect-agent/storage-cloudflare/PortProtocol\";\nimport {\n executePortRequest,\n routedThreadStoreLayer,\n routedSubmissionLedgerLayer,\n} from \"@effect-agent/storage-cloudflare/PortRouting\";\nimport {\n compileRegistrations,\n type AgentRegistration,\n type ResolvedBinding,\n} from \"@effect-agent/thread/AgentRegistration\";\nimport { type DigestError } from \"@effect-agent/thread/Digest\";\nimport {\n DurableAgentRuntime,\n DurableRuntimeConfig,\n} from \"@effect-agent/thread/DurableAgentRuntime\";\nimport {\n DurableRuntimeFailpoint,\n type DurableRuntimeFailpointHandler,\n} from \"@effect-agent/thread/DurableFailpoint\";\nimport {\n type MessageDeliveryStore,\n MessageDeliveryDriver,\n type MessageDeliveryError,\n} from \"@effect-agent/thread/MessageDelivery\";\nimport {\n operationAuthorizerLayer,\n type OperationAuthorizerService,\n} from \"@effect-agent/thread/OperationAuthorizer\";\nimport { ProducerId } from \"@effect-agent/thread/Records\";\nimport { LedgerError, SubmissionLedger } from \"@effect-agent/thread/SubmissionLedger\";\nimport { ThreadStoreError, ThreadStore } from \"@effect-agent/thread/ThreadStore\";\nimport { ToolReconciler } from \"@effect-agent/thread/ToolReconciler\";\nimport { type WakeScheduler } from \"@effect-agent/thread/WakeScheduler\";\nimport { BrowserCrypto } from \"@effect/platform-browser\";\nimport { SqliteClient } from \"@effect/sql-sqlite-do\";\nimport type { Crypto } from \"effect\";\nimport { Context, Duration, Effect, Layer, Schema } from \"effect\";\nimport { SqlClient } from \"effect/unstable/sql/SqlClient\";\n\nimport {\n ThreadMaintenance,\n ThreadMutationGate,\n ThreadPublication,\n publishCommitted,\n ThreadMaintenanceFailpoint,\n DurableAlarmService,\n type ThreadMaintenanceFailpointHandler,\n} from \"../Alarm.ts\";\nimport {\n ThreadObjectIdentity,\n DurableObjectContext,\n type ThreadObjectNamespace,\n} from \"../CloudflareBindings.ts\";\nimport {\n CLOUDFLARE_RUNTIME_DEFAULTS,\n CloudflareDurableRuntimeConfig,\n CloudflareDurableRuntimeConfigValue,\n CloudflarePlatformConfigError,\n} from \"../CloudflareConfig.ts\";\nimport { CloudflareThreadClient } from \"../CloudflareThreadClient.ts\";\nimport { cloudflareWakeSchedulerLayer } from \"../WakeScheduler.ts\";\nimport {\n guardedMessageDeliveryStoreLayer,\n threadMessageDeliveryLayer,\n} from \"./message-delivery.ts\";\nimport { cloudflarePreparedInputAdmissionLayer } from \"./prepared-admission.ts\";\nimport { ProgressWaitRegistry } from \"./progress-wait.ts\";\nimport { threadPortTransportLayer } from \"./transport.ts\";\n\n/**\n * Raw (unvalidated) construction options for `ThreadObject.make`, mirroring\n * `NodeDurableAgentRuntimeOptions`. Optional fields default to the documented production values\n * (`CLOUDFLARE_RUNTIME_DEFAULTS`); everything is schema-decoded into\n * `CloudflareDurableRuntimeConfigValue` before any resource opens (deployment §5 gate 1).\n */\nexport interface CloudflareDurableRuntimeOptions {\n readonly deploymentId: string;\n /** Head of the minted producer identity `{producerPrefix}:{threadId}`. */\n readonly producerPrefix: string;\n /** Milliseconds; default 30s (D5). */\n readonly ownershipLeaseDuration?: number | undefined;\n /** Milliseconds; default 100. */\n readonly alarmBackoffBase?: number | undefined;\n /** Milliseconds; default 5000. */\n readonly alarmBackoffCap?: number | undefined;\n /** Milliseconds; default 1000. Bounds every alarm re-arm delay. */\n readonly wakeScanInterval?: number | undefined;\n /** Milliseconds; default 500. */\n readonly settlementPollInterval?: number | undefined;\n /** Milliseconds; default 10000. */\n readonly leaseRenewalInterval?: number | undefined;\n /** Milliseconds; default 500. */\n readonly abortPollInterval?: number | undefined;\n /** Deployment-owned pricing authority used by durable cost budgets and settlements. */\n readonly estimateCostMicrousd?: RunCostEstimator | undefined;\n /** Closed trusted Tool failure reporting. Omission masks ambient observers at construction. */\n readonly toolFailureObserver?: RunToolFailureObserver | undefined;\n /** Milliseconds; default 25. */\n readonly observationPollInterval?: number | undefined;\n /** Bytes; default just under the 2 MB platform value limit. */\n readonly maxStoredValueBytes?: number | undefined;\n /** Default false. */\n readonly verifyOnOpen?: boolean | undefined;\n /** Nonterminal Submissions per lane before admission refuses; default 256. */\n readonly maxQueueDepthPerLane?: number | undefined;\n /** Encoded input bytes per Submission; default = the stored-value bound. */\n readonly maxInputBytes?: number | undefined;\n /** `ctx.storage.sql.databaseSize` ceiling at admission; default 9 GB (10 GB platform cap). */\n readonly maxDatabaseBytes?: number | undefined;\n /**\n * Durable Object storage fault injection (`ledger:*` / `append:*` locations). Handlers are\n * constructed per incarnation WITH the live `DurableObjectState`, so eviction harnesses can\n * map an armed hit to `ctx.abort()` — the platform's real failure mode. Default none.\n */\n readonly storageFailpoint?: ((ctx: DurableObjectState) => DoStorageFailpointHandler) | undefined;\n /** Coordinator fault injection (`submit:*` / `terminalize:*` locations); default none. */\n readonly runtimeFailpoint?:\n | ((ctx: DurableObjectState) => DurableRuntimeFailpointHandler)\n | undefined;\n /** Thread-maintenance generation/alarm fault injection; default none. */\n readonly maintenanceFailpoint?:\n | ((ctx: DurableObjectState) => ThreadMaintenanceFailpointHandler)\n | undefined;\n /** Host-supplied fail-closed authorization policy; defaults to service possession. */\n readonly operationAuthorizer?: OperationAuthorizerService | undefined;\n /**\n * Reconciliation policy consulted for open ordinary Tool Calls before an Unknown Outcome\n * is recorded (durability §10, DUR-009). Defaults to the fail-closed\n * `ToolReconciler.uncertain`.\n */\n readonly toolReconciler?: Layer.Layer<ToolReconciler> | undefined;\n}\n\n/** Services supplied before the application graph is built, including its dependencies. */\nexport type CloudflareBootstrapServices =\n | CloudflareDurableRuntimeConfig\n | ThreadObjectIdentity\n | DurableRuntimeConfig\n | Crypto.Crypto\n | DoStorageFailpoint\n | DurableRuntimeFailpoint\n | ThreadMaintenanceFailpoint\n | RunContextPreparation\n | RunToolAuthorization\n | ToolReconciler;\n\n/** Every construction failure of the assembled Cloudflare durable runtime stack. */\nexport type CloudflareDurableRuntimeInitializationError =\n | CloudflarePlatformConfigError\n | DigestError\n | MessageDeliveryError\n | DoStorageInitializationError;\n\n/** The services `ThreadObject.layer` provides, including its single owner SQL client. */\nexport type CloudflareDurableRuntimeServices =\n | DurableAgentRuntime\n | SubmissionLedger\n | ThreadStore\n | MessageDeliveryStore\n | WakeScheduler\n | DurableAlarmService\n | ThreadMaintenance\n | ThreadMutationGate\n | ThreadPublication\n | ThreadObjectPorts\n | ProgressWaitRegistry\n | SqlClient;\n\n/**\n * Owner-side execution port for a `portCall` request the wire endpoint has already decoded.\n * It executes against THIS Object's LOCAL port facets — never the routed decorators, so a\n * request cannot bounce between Objects — and returns the typed response for the endpoint to\n * encode.\n */\nexport class ThreadObjectPorts extends Context.Service<\n ThreadObjectPorts,\n {\n readonly handle: (request: PortRequest) => Effect.Effect<PortResponse>;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadObjectPorts\") {}\n\nconst decodeConfigValue = Schema.decodeUnknownEffect(CloudflareDurableRuntimeConfigValue);\nconst decodeThreadId = Schema.decodeUnknownEffect(ThreadId);\nconst decodeProducerId = Schema.decodeUnknownEffect(ProducerId);\n\nconst configFromOptions = (\n options: CloudflareDurableRuntimeOptions,\n): Effect.Effect<CloudflareDurableRuntimeConfigValue, CloudflarePlatformConfigError> =>\n decodeConfigValue({\n deploymentId: options.deploymentId,\n producerPrefix: options.producerPrefix,\n ownershipLeaseDuration:\n options.ownershipLeaseDuration ?? CLOUDFLARE_RUNTIME_DEFAULTS.ownershipLeaseDuration,\n alarmBackoffBase: options.alarmBackoffBase ?? CLOUDFLARE_RUNTIME_DEFAULTS.alarmBackoffBase,\n alarmBackoffCap: options.alarmBackoffCap ?? CLOUDFLARE_RUNTIME_DEFAULTS.alarmBackoffCap,\n wakeScanInterval: options.wakeScanInterval ?? CLOUDFLARE_RUNTIME_DEFAULTS.wakeScanInterval,\n settlementPollInterval:\n options.settlementPollInterval ?? CLOUDFLARE_RUNTIME_DEFAULTS.settlementPollInterval,\n leaseRenewalInterval:\n options.leaseRenewalInterval ?? CLOUDFLARE_RUNTIME_DEFAULTS.leaseRenewalInterval,\n abortPollInterval: options.abortPollInterval ?? CLOUDFLARE_RUNTIME_DEFAULTS.abortPollInterval,\n observationPollInterval:\n options.observationPollInterval ?? CLOUDFLARE_RUNTIME_DEFAULTS.observationPollInterval,\n maxStoredValueBytes:\n options.maxStoredValueBytes ?? CLOUDFLARE_RUNTIME_DEFAULTS.maxStoredValueBytes,\n verifyOnOpen: options.verifyOnOpen ?? CLOUDFLARE_RUNTIME_DEFAULTS.verifyOnOpen,\n limits: {\n maxQueueDepthPerLane:\n options.maxQueueDepthPerLane ?? CLOUDFLARE_RUNTIME_DEFAULTS.maxQueueDepthPerLane,\n maxInputBytes: Math.min(\n options.maxInputBytes ?? CLOUDFLARE_RUNTIME_DEFAULTS.maxInputBytes,\n options.maxStoredValueBytes ?? CLOUDFLARE_RUNTIME_DEFAULTS.maxStoredValueBytes,\n ),\n maxDatabaseBytes: options.maxDatabaseBytes ?? CLOUDFLARE_RUNTIME_DEFAULTS.maxDatabaseBytes,\n },\n }).pipe(\n Effect.mapError((error) =>\n CloudflarePlatformConfigError.make({\n message: `Invalid Cloudflare durable runtime configuration: ${error.message}`,\n cause: error,\n }),\n ),\n );\n\n/**\n * The Thread this Object owns, from the Object identity rule (plan §1.2): Thread\n * Objects are addressed exclusively by `idFromName(threadId)`, so `ctx.id.name` IS the\n * Thread ID. An unnamed Object (from `newUniqueId`) is a deployment error, not a lane.\n */\nconst threadIdFromState = (\n ctx: DurableObjectState,\n): Effect.Effect<ThreadId, CloudflarePlatformConfigError> =>\n ctx.id.name === undefined\n ? Effect.fail(\n CloudflarePlatformConfigError.make({\n message:\n \"This Durable Object was not created via idFromName(threadId); Thread \" +\n \"Objects must be addressed by their Thread identity (plan §1.2).\",\n }),\n )\n : decodeThreadId(ctx.id.name).pipe(\n Effect.mapError((error) =>\n CloudflarePlatformConfigError.make({\n message: `The Durable Object name is not a valid ThreadId: ${error.message}`,\n cause: error,\n }),\n ),\n );\n\n/**\n * Validate deployment settings and derive services before building application dependencies.\n * The native class factory builds this Layer inside its constructor gate. Custom Effect hosts\n * can provide it around the complete application Layer with the native context already supplied.\n */\nexport const layerConfig = (\n options: CloudflareDurableRuntimeOptions,\n): Layer.Layer<CloudflareBootstrapServices, CloudflarePlatformConfigError, DurableObjectContext> =>\n Layer.unwrap(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n const config = yield* configFromOptions(options);\n const threadId = yield* threadIdFromState(ctx);\n\n const producerId = yield* decodeProducerId(`${config.producerPrefix}:${threadId}`).pipe(\n Effect.mapError((error) =>\n CloudflarePlatformConfigError.make({\n message: `The minted producer identity is invalid: ${error.message}`,\n cause: error,\n }),\n ),\n );\n\n return Layer.mergeAll(\n Layer.succeed(CloudflareDurableRuntimeConfig, config),\n Layer.succeed(ThreadObjectIdentity, { threadId, producerId }),\n DurableRuntimeConfig.layer({\n deploymentId: config.deploymentId,\n producerId,\n settlementPollInterval: Duration.millis(config.settlementPollInterval),\n leaseRenewalInterval: Duration.millis(config.leaseRenewalInterval),\n abortPollInterval: Duration.millis(config.abortPollInterval),\n ...(options.estimateCostMicrousd === undefined\n ? {}\n : { estimateCostMicrousd: options.estimateCostMicrousd }),\n }),\n BrowserCrypto.layer,\n storageFailpointLayer({ storage: ctx.storage, failpoint: options.storageFailpoint?.(ctx) }),\n options.runtimeFailpoint === undefined\n ? DurableRuntimeFailpoint.layer\n : Layer.succeed(DurableRuntimeFailpoint, { hit: options.runtimeFailpoint(ctx) }),\n options.maintenanceFailpoint === undefined\n ? ThreadMaintenanceFailpoint.layer\n : Layer.succeed(ThreadMaintenanceFailpoint, {\n hit: options.maintenanceFailpoint(ctx),\n }),\n options.toolReconciler ?? ToolReconciler.uncertain,\n options.operationAuthorizer === undefined\n ? Layer.empty\n : operationAuthorizerLayer(options.operationAuthorizer),\n options.toolFailureObserver === undefined\n ? Layer.succeed(CurrentToolFailureObserver, undefined)\n : toolFailureObserverLayer(options.toolFailureObserver),\n RunContextPreparationPassthrough,\n RunToolAuthorization.allowAll,\n );\n }),\n );\n\nexport interface ThreadPublicationOptions<E = never, R = never> {\n /**\n * Optional host outbox consumer, built once per incarnation with RAW LOCAL ThreadStore and\n * SubmissionLedger services. Yield DurableObjectContext and ThreadObjectIdentity for native\n * bindings and identity. Initialization is local-only, inside the constructor gate; setup\n * errors and additional requirements remain in the returned Layer. Layer.effect owns Scope.\n * Canonical appends and durable approval, abort and unknown-resolution intents invalidate\n * publication after commit. Custom host facts must use ThreadMaintenance.withMutation.\n */\n readonly publication?: Layer.Layer<ThreadPublication, E, R>;\n}\n\n/**\n * Register typed Agents and version declarations. Hashing and dependency capture happen in\n * this Layer's Scope, after application Layers have been provided. Every Agent's instruction,\n * Tool, Schema, and model requirements remain visible until satisfied by Layer composition.\n * Use Layer.unwrap for registration values that need effectful application setup.\n */\nexport const layer = <const Entries extends ReadonlyArray<AgentRegistration>, E = never, R = never>(\n registrations: Entries,\n options: ThreadPublicationOptions<E, R> = {},\n) =>\n Layer.unwrap(\n Effect.map(compileRegistrations(registrations), (bindings) =>\n layerFromBindings(bindings, options),\n ),\n );\n\n/**\n * Assemble the durable runtime from already-resolved Agent Bindings.\n * Use `ThreadObject.layer` to compile typed Agent registrations instead.\n * Supply host services through `ThreadObject.make` or `ThreadObject.layerConfig` and\n * the Durable Object context and namespace Layers when composing a custom host.\n */\nexport const layerFromBindings = <E = never, R = never>(\n bindings: ReadonlyArray<ResolvedBinding>,\n options: ThreadPublicationOptions<E, R> = {},\n): Layer.Layer<\n CloudflareDurableRuntimeServices,\n DoStorageInitializationError | MessageDeliveryError | E,\n | DurableObjectContext\n | ThreadObjectNamespace\n | CloudflareBootstrapServices\n | Exclude<R, ThreadStore | SubmissionLedger | SqlClient>\n> =>\n Layer.unwrap(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n const config = yield* CloudflareDurableRuntimeConfig;\n const { threadId } = yield* ThreadObjectIdentity;\n\n const storageOptions: DoStorageOptions = {\n storage: ctx.storage,\n observationPollInterval: config.observationPollInterval,\n ownershipLeaseDuration: config.ownershipLeaseDuration,\n maxStoredValueBytes: config.maxStoredValueBytes,\n verifyOnOpen: config.verifyOnOpen,\n };\n\n const infrastructure = Layer.mergeAll(\n storageConfigLayer(storageOptions),\n SqliteClient.layer({ storage: ctx.storage }),\n );\n\n // The same local ports serve routed decorators and owner-side RPC execution.\n // The RPC executor must never receive routed ports and bounce requests between Objects.\n const rawLocalPorts = Layer.mergeAll(threadStoreLayer, submissionLedgerLayer).pipe(\n Layer.provide(infrastructure),\n );\n\n const messageStore = guardedMessageDeliveryStoreLayer.pipe(\n Layer.provide(doMessageDeliveryStoreLayer().pipe(Layer.provide(infrastructure))),\n );\n\n const messageRecovery = threadMessageDeliveryLayer.pipe(\n // A single wave stays within the alarm event budget even at the policy's five-minute\n // attempt ceiling. More due rows retain their indexed deadline for the next alarm.\n Layer.provide(MessageDeliveryDriver.layer({ batchSize: 4, concurrency: 4 })),\n Layer.provide(cloudflarePreparedInputAdmissionLayer),\n Layer.provide(CloudflareThreadClient.layer),\n Layer.provide(messageStore),\n );\n\n const publication = (options.publication ?? ThreadPublication.layer).pipe(\n Layer.provide(Layer.mergeAll(rawLocalPorts, Layer.effect(SqlClient)(SqlClient))),\n );\n\n const localPorts =\n options.publication === undefined\n ? rawLocalPorts\n : Layer.effectContext(\n Effect.gen(function* () {\n const store = yield* ThreadStore;\n const ledger = yield* SubmissionLedger;\n const mutations = yield* ThreadMutationGate;\n const publish = yield* Effect.context<ThreadPublication>();\n const afterCommit = publishCommitted.pipe(Effect.provide(publish));\n\n // Every runtime-owned producer prearms too: a crash between commit and invalidation\n // leaves a NEW, uncertified generation. Source errors keep their native port types.\n const observedStore = ThreadStore.of({\n ...store,\n append: (request) =>\n mutations\n .withMutation(store.append(request).pipe(Effect.tap(() => afterCommit)))\n .pipe(\n Effect.catchTag(\"DurableAlarmError\", (cause) =>\n ThreadStoreError.make({\n operation: \"prearm publication append\",\n message: cause.message,\n cause,\n }),\n ),\n ),\n });\n\n const observeIntent = <A, Failure>(body: Effect.Effect<A, Failure>) =>\n mutations.withMutation(body.pipe(Effect.tap(() => afterCommit))).pipe(\n Effect.catchTag(\"DurableAlarmError\", (cause) =>\n LedgerError.make({\n operation: \"prearm publication intent\",\n message: \"The publication generation could not be armed\",\n cause,\n }),\n ),\n );\n\n return Context.make(ThreadStore, observedStore).pipe(\n Context.add(SubmissionLedger, {\n ...ledger,\n recordApprovalDecision: (request) =>\n observeIntent(ledger.recordApprovalDecision(request)),\n requestAbort: (request) => observeIntent(ledger.requestAbort(request)),\n recordUnknownResolution: (request) =>\n observeIntent(ledger.recordUnknownResolution(request)),\n }),\n );\n }),\n ).pipe(Layer.provide(rawLocalPorts));\n\n const portsEndpointLayer = Layer.effect(ThreadObjectPorts)(\n Effect.gen(function* () {\n const local = yield* Effect.context<SubmissionLedger | ThreadStore>();\n\n return ThreadObjectPorts.of({\n handle: (request) => executePortRequest(request).pipe(Effect.provide(local)),\n });\n }),\n ).pipe(Layer.provide(localPorts));\n\n const routedPorts = Layer.mergeAll(\n routedSubmissionLedgerLayer({ localThreadId: threadId }),\n routedThreadStoreLayer({ localThreadId: threadId }),\n ).pipe(Layer.provide(localPorts), Layer.provide(threadPortTransportLayer));\n\n const base = Layer.mergeAll(DurableAlarmService.layer, ProgressWaitRegistry.layer);\n\n const runtimeStack = DurableAgentRuntime.layerWithBindings(bindings).pipe(\n Layer.provide(\n cloudflarePreparedInputAdmissionLayer.pipe(Layer.provide(CloudflareThreadClient.layer)),\n ),\n Layer.provideMerge(messageStore),\n Layer.provideMerge(routedPorts),\n Layer.provideMerge(cloudflareWakeSchedulerLayer),\n Layer.provideMerge(base),\n );\n\n return Layer.mergeAll(\n runtimeStack,\n ThreadMaintenance.layer.pipe(Layer.provide(runtimeStack), Layer.provide(messageRecovery)),\n portsEndpointLayer,\n messageStore,\n ).pipe(\n Layer.provideMerge(publication),\n Layer.provideMerge(ThreadMutationGate.layer),\n Layer.provideMerge(infrastructure),\n );\n }),\n );\n","import { type AgentId } from \"@effect-agent/core/Identifiers\";\nimport { SubmissionId } from \"@effect-agent/core/Identifiers\";\nimport {\n decodePortRequest,\n encodePortResponse,\n type PortRequest,\n} from \"@effect-agent/storage-cloudflare/PortProtocol\";\nimport {\n IntegrityReport,\n ObligationReport,\n ObligationThresholds,\n RecoveryExplanation,\n RetryCommand,\n RetryRefused,\n} from \"@effect-agent/thread/Admin\";\nimport { DigestError } from \"@effect-agent/thread/Digest\";\nimport {\n DurableAgentRuntime,\n RecoveryReport,\n type DurableSubmitAgent,\n} from \"@effect-agent/thread/DurableAgentRuntime\";\nimport { DurableRuntimeFailpointError } from \"@effect-agent/thread/DurableFailpoint\";\nimport {\n OperationAuthorizationRequest,\n OperationAuthorizer,\n OperationDenied,\n} from \"@effect-agent/thread/OperationAuthorizer\";\nimport { PersistedJson } from \"@effect-agent/thread/Records\";\nimport { RunJournalError } from \"@effect-agent/thread/RunJournal\";\nimport {\n AdmissionPolicyError,\n LedgerError,\n OwnershipLost,\n SettlementConflict,\n SubmissionLedger,\n SubmissionLookupByKey,\n} from \"@effect-agent/thread/SubmissionLedger\";\nimport {\n AppendConflict,\n ThreadNotMaterialized,\n ThreadRead,\n ThreadStore,\n ThreadStoreError,\n FenceRejected,\n} from \"@effect-agent/thread/ThreadStore\";\nimport { WakeScheduler } from \"@effect-agent/thread/WakeScheduler\";\nimport { Effect, Layer, Option, Schema, Stream } from \"effect\";\nimport {\n DurableObject as EffectCfDurableObject,\n DurableObjectState as EffectCfDurableObjectState,\n WorkerEnvironment,\n} from \"effect-cf\";\n\nimport {\n ThreadMaintenance,\n DurableAlarmError,\n DurableAlarmService,\n type MaintenancePassFailure,\n} from \"./Alarm.ts\";\nimport {\n ThreadObjectIdentity,\n DurableObjectContext,\n ThreadObjectNamespace,\n threadNamespaceFromEnv,\n type CloudflareBindingError,\n} from \"./CloudflareBindings.ts\";\nimport { AdmissionLimitExceeded, CloudflareDurableRuntimeConfig } from \"./CloudflareConfig.ts\";\nimport {\n AbortRecorded,\n ApprovalRecorded,\n HostFailed,\n HostProtocolError,\n ObservedPage,\n ProgressObserved,\n ProgressCancelled,\n SettlementReached,\n SubmissionStatusResponse,\n SubmitSucceeded,\n UnknownResolutionRecorded,\n boundHostDiagnostic,\n decodeAbortCommand,\n decodeAwaitProgressRequest,\n decodeCancelProgressRequest,\n decodeApprovalDecisionCommand,\n decodeObservePageRequest,\n decodeReceipt,\n decodeSubmitRequest,\n decodeUnknownResolutionCommand,\n encodeHostResponse,\n type HostFailure,\n type HostResponse,\n} from \"./CloudflareThreadClient.ts\";\nimport {\n layerConfig,\n ThreadObjectPorts,\n type CloudflareDurableRuntimeInitializationError,\n type CloudflareDurableRuntimeOptions,\n type CloudflareDurableRuntimeServices,\n type CloudflareBootstrapServices,\n} from \"./internal/layers.ts\";\nimport { ProgressWaitRegistry } from \"./internal/progress-wait.ts\";\n\nexport {\n layer,\n layerConfig,\n type ThreadPublicationOptions as PublicationOptions,\n type CloudflareDurableRuntimeOptions as RuntimeOptions,\n type CloudflareDurableRuntimeServices as Services,\n type CloudflareDurableRuntimeInitializationError as InitializationError,\n type CloudflareBootstrapServices as BootstrapServices,\n} from \"./internal/layers.ts\";\n\n/**\n * `ThreadObject.make(application, options)` — the Thread Durable Object\n * (plan §1.4,\n * D-P6-1): a factory returning a class that applications export from their Worker entry.\n * One SQLite-backed Object per Thread is the serialized owner (durability §6); the\n * Object never runs `runResolvedWorker`'s infinite loop — each ingress event or alarm runs\n * ONE bounded `runRecovery` + `processThreadHead` pass, and the persisted alarm\n * (the single multiplexed slot, D-P6-2) finishes accepted work across evictions WITHOUT any\n * incoming request.\n * `Services` exposes the same owner `SqlClient` used by the Thread stores. Compose optional\n * local repositories after `ThreadObject.layer`; never acquire another independently locked\n * SQL client for the same Object. Exposing the client installs no additional storage schemas.\n *\n * Constructor gate (`blockConcurrencyWhile`) is LOCAL-ONLY: schema migration and the\n * exact-version check, configuration decode, and the defensive ensure-alarm half of the\n * alarm invariant. It deliberately does NOT run the recovery pass: parent recovery can\n * require child-Object reads and vice versa, and two Objects blocked in constructor gates\n * awaiting each other's RPC would deadlock (plan §1.4). Instead every pass runs\n * `runRecovery` BEFORE any claim, so reconciliation still strictly precedes new work.\n */\n\n/** Construction options for one deployed Thread Object class. */\nexport interface Options<\n ApplicationServices = never,\n EventServices = never,\n EventLayerError = never,\n> extends CloudflareDurableRuntimeOptions {\n /** Accept transient native RPC tracing through effect-cf; disabled by default. */\n readonly rpcTracing?: boolean;\n /**\n * Name of the Worker `env` binding carrying THIS class's `DurableObjectNamespace` — the\n * Object's route back to sibling Thread Objects for the WP2 cross-Object port calls\n * and remote wakes (DEPLOY-010: the binding enters through a Layer, never ambiently).\n */\n readonly namespaceBinding: string;\n /** Acquired and finalized per native event, with access to the complete application runtime. */\n readonly eventLayer?: Layer.Layer<\n EventServices,\n EventLayerError,\n | RuntimeServices\n | ApplicationServices\n | EffectCfDurableObjectState.DurableObjectState\n | WorkerEnvironment\n >;\n}\n\ntype EndpointServices =\n | CloudflareDurableRuntimeServices\n | CloudflareBootstrapServices\n | DurableObjectContext;\ntype RuntimeServices = EndpointServices | ThreadObjectNamespace;\ntype ThreadObjectInitializationError =\n | CloudflareDurableRuntimeInitializationError\n | CloudflareBindingError\n | MaintenancePassFailure;\n\n/** Classify only a decoded port request so new protocol members cannot bypass pre-arming. */\nconst isMutatingPortRequest = (request: PortRequest): boolean => {\n switch (request._tag) {\n case \"LedgerAdmit\":\n case \"LedgerMarkReady\":\n case \"LedgerRequestAbort\":\n case \"LedgerRecordChildSettled\":\n case \"StoreMaterialize\":\n case \"StoreAppend\":\n return true;\n case \"LedgerLookup\":\n case \"LedgerResolveAdmission\":\n case \"StoreReadPage\":\n case \"StoreInspectTail\":\n case \"StoreExport\":\n return false;\n }\n request satisfies never;\n\n return false;\n};\n\n/** The literal encoded `PortFailed(PortProtocolError)` fallback (same shape as WP2's). */\nconst encodedPortProtocolFailure = (message: string): unknown => ({\n _tag: \"PortFailed\",\n failure: { _tag: \"PortProtocolError\", message: boundHostDiagnostic(message) },\n});\n\nconst protocolFailure = (context: string) => (error: { readonly message: string }) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`${context}: ${error.message}`),\n });\n\n/** Fold one endpoint's typed failures into the uniform `HostResponse` envelope. */\nconst respond = <Result extends HostResponse, Failure extends HostFailure>(\n effect: Effect.Effect<Result, Failure, EndpointServices>,\n): Effect.Effect<HostResponse, never, EndpointServices> =>\n effect.pipe(\n Effect.map((result): HostResponse => result),\n Effect.catch((failure) => Effect.succeed<HostResponse>(HostFailed.make({ failure }))),\n );\n\n/** Encode the response envelope; an unencodable response degrades to a protocol failure. */\nconst encodeResponse = (response: HostResponse): Effect.Effect<unknown> =>\n encodeHostResponse(response).pipe(\n Effect.catch((error) =>\n Effect.succeed<unknown>({\n _tag: \"HostFailed\",\n failure: {\n _tag: \"HostProtocolError\",\n message: boundHostDiagnostic(`The host response could not be encoded: ${error.message}`),\n },\n }),\n ),\n );\n\nconst utf8Bytes = (value: PersistedJson): number =>\n new TextEncoder().encode(JSON.stringify(value)).length;\n\n/**\n * The admission-limits gate, BEFORE `runtime.submit` touches the ledger (exit gate\n * \"resource limits are checked before admission\"; DEPLOY-007). A replayed idempotency key is\n * exempt: its accepted-work obligation already exists, and returning the original Receipt\n * consumes no new quota. Refusals are typed `AdmissionLimitExceeded` and nothing is written.\n */\nconst gateAdmissionLimits = Effect.fn(\"ThreadObject.gateAdmissionLimits\")(function* (request: {\n readonly principal: SubmissionLookupByKey[\"principal\"];\n readonly idempotencyKey: SubmissionLookupByKey[\"idempotencyKey\"];\n readonly inputPayload: PersistedJson;\n}) {\n const identity = yield* ThreadObjectIdentity;\n const config = yield* CloudflareDurableRuntimeConfig;\n const ledger = yield* SubmissionLedger;\n const { ctx } = yield* DurableObjectContext;\n\n const existing = yield* ledger.lookup(\n SubmissionLookupByKey.make({\n threadId: identity.threadId,\n principal: request.principal,\n idempotencyKey: request.idempotencyKey,\n }),\n );\n\n if (Option.isSome(existing)) return;\n\n const inputBytes = utf8Bytes(request.inputPayload);\n\n if (inputBytes > config.limits.maxInputBytes) {\n return yield* AdmissionLimitExceeded.make({\n limit: \"input-bytes\",\n actual: inputBytes,\n maximum: config.limits.maxInputBytes,\n });\n }\n\n // One Thread per Object (durability §5): the local scan IS this lane's queue.\n const nonterminal = yield* Stream.runCollect(ledger.scanNonterminal);\n\n if (nonterminal.length >= config.limits.maxQueueDepthPerLane) {\n return yield* AdmissionLimitExceeded.make({\n limit: \"queue-depth\",\n actual: nonterminal.length,\n maximum: config.limits.maxQueueDepthPerLane,\n });\n }\n\n const databaseBytes = yield* Effect.sync(() => ctx.storage.sql.databaseSize);\n\n if (databaseBytes > config.limits.maxDatabaseBytes) {\n return yield* AdmissionLimitExceeded.make({\n limit: \"database-bytes\",\n actual: databaseBytes,\n maximum: config.limits.maxDatabaseBytes,\n });\n }\n});\n\n/**\n * The submit-capable projection of an Agent Binding on the OBJECT side: the input arrived\n * already encoded through the real input schema on the Worker side (`client.ts`), so the\n * Object admits the canonical `PersistedJson` payload as-is; the resolved Binding re-derives\n * everything else from the stored `(agentId, agentDigests)` at claim time (SUB-023).\n */\nconst passthroughSubmitAgent = (agentId: AgentId): DurableSubmitAgent<typeof PersistedJson> => ({\n definition: {\n id: agentId,\n input: PersistedJson,\n },\n});\n\nconst submitEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n decodeSubmitRequest(encoded).pipe(\n Effect.mapError(protocolFailure(\"The submit request could not be decoded\")),\n Effect.flatMap((request) =>\n Effect.gen(function* () {\n const identity = yield* ThreadObjectIdentity;\n const maintenance = yield* ThreadMaintenance;\n const runtime = yield* DurableAgentRuntime;\n\n yield* gateAdmissionLimits(request);\n\n // Alarm invariant: the generation + alarm commit BEFORE the admission, and maintenance\n // cannot acknowledge that generation until this mutation leaves its public RPC seam.\n const receipt = yield* maintenance.withMutation(\n runtime.submit(passthroughSubmitAgent(request.agentId), request.inputPayload, {\n threadId: identity.threadId,\n principal: request.principal,\n idempotencyKey: request.idempotencyKey,\n ...(request.admissionGroup === undefined\n ? {}\n : { admissionGroup: request.admissionGroup }),\n ...(request.admissionFence === undefined\n ? {}\n : { admissionFence: request.admissionFence }),\n ...(request.workerAdmission === undefined\n ? {}\n : { workerAdmission: request.workerAdmission }),\n ...(request.messageAdmission === undefined\n ? {}\n : { messageAdmission: request.messageAdmission }),\n definitions: request.definitions,\n }),\n );\n\n return SubmitSucceeded.make({ receipt });\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\nconst submissionStatusEndpoint = (\n encoded: unknown,\n): Effect.Effect<unknown, never, EndpointServices> =>\n decodeReceipt(encoded).pipe(\n Effect.mapError(protocolFailure(\"The receipt could not be decoded\")),\n Effect.flatMap((receipt) =>\n Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n\n return SubmissionStatusResponse.make({ status: yield* runtime.submissionStatus(receipt) });\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\nconst awaitSettlementEndpoint = (\n encoded: unknown,\n): Effect.Effect<unknown, never, EndpointServices> =>\n decodeReceipt(encoded).pipe(\n Effect.mapError(protocolFailure(\"The receipt could not be decoded\")),\n Effect.flatMap((receipt) =>\n Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n const settlement = yield* runtime.awaitSettlement(receipt);\n\n return SettlementReached.make({ settlement });\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\nconst awaitProgressEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n decodeAwaitProgressRequest(encoded).pipe(\n Effect.mapError(protocolFailure(\"The progress request could not be decoded\")),\n Effect.flatMap((request) =>\n Effect.gen(function* () {\n const identity = yield* ThreadObjectIdentity;\n const runtime = yield* DurableAgentRuntime;\n const registry = yield* ProgressWaitRegistry;\n\n yield* Effect.scoped(\n Effect.gen(function* () {\n const cancelled = yield* registry.subscribe(request.waiterId);\n\n yield* Effect.raceFirst(\n runtime.awaitProgress(identity.threadId, request.afterSequence),\n cancelled,\n );\n }),\n );\n\n return ProgressObserved.make();\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\nconst cancelProgressEndpoint = (\n encoded: unknown,\n): Effect.Effect<unknown, never, EndpointServices> =>\n decodeCancelProgressRequest(encoded).pipe(\n Effect.mapError(protocolFailure(\"The progress cancellation could not be decoded\")),\n Effect.flatMap((request) =>\n Effect.gen(function* () {\n const registry = yield* ProgressWaitRegistry;\n\n yield* registry.cancel(request.waiterId);\n\n return ProgressCancelled.make();\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\nconst observePageEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n decodeObservePageRequest(encoded).pipe(\n Effect.mapError(protocolFailure(\"The observe request could not be decoded\")),\n Effect.flatMap((request) =>\n Effect.gen(function* () {\n const identity = yield* ThreadObjectIdentity;\n const store = yield* ThreadStore;\n // The same fail-closed authorization seam the runtime's `observe` consults (P7 WP1);\n // the default reference preserves the possession behavior.\n const authorizer = yield* OperationAuthorizer;\n\n yield* authorizer.authorize(\n OperationAuthorizationRequest.make({\n operation: \"observe\",\n threadId: identity.threadId,\n }),\n );\n\n const records = yield* Stream.runCollect(\n store.read(\n ThreadRead.make({\n threadId: identity.threadId,\n ...(request.afterSequence === undefined\n ? {}\n : { afterSequence: request.afterSequence }),\n limit: request.limit,\n }),\n ),\n );\n\n return ObservedPage.make({ records: [...records] });\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\nconst abortEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n decodeAbortCommand(encoded).pipe(\n Effect.mapError(protocolFailure(\"The abort command could not be decoded\")),\n Effect.flatMap((command) =>\n Effect.gen(function* () {\n const maintenance = yield* ThreadMaintenance;\n const runtime = yield* DurableAgentRuntime;\n const intent = yield* maintenance.withMutation(runtime.abort(command));\n\n return AbortRecorded.make({ intent });\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\nconst resolveApprovalEndpoint = (\n encoded: unknown,\n): Effect.Effect<unknown, never, EndpointServices> =>\n decodeApprovalDecisionCommand(encoded).pipe(\n Effect.mapError(protocolFailure(\"The approval command could not be decoded\")),\n Effect.flatMap((command) =>\n Effect.gen(function* () {\n const maintenance = yield* ThreadMaintenance;\n const runtime = yield* DurableAgentRuntime;\n const intent = yield* maintenance.withMutation(runtime.resolveApproval(command));\n\n return ApprovalRecorded.make({ intent });\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\nconst resolveUnknownEndpoint = (\n encoded: unknown,\n): Effect.Effect<unknown, never, EndpointServices> =>\n decodeUnknownResolutionCommand(encoded).pipe(\n Effect.mapError(protocolFailure(\"The resolution command could not be decoded\")),\n Effect.flatMap((command) =>\n Effect.gen(function* () {\n const maintenance = yield* ThreadMaintenance;\n const runtime = yield* DurableAgentRuntime;\n const intent = yield* maintenance.withMutation(runtime.resolveUnknown(command));\n\n return UnknownResolutionRecorded.make({ intent });\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\n// ---------------------------------------------------------------------------\n// P7 administrative entry points (plan §3): explain/verify/retry/obligations over the SAME\n// envelope discipline as the host protocol — closed request/response Schema unions, typed\n// failures that re-decode to identical tags, protocol anomalies answered typed. The envelopes\n// live here (not `client.ts`) because no Worker-side client consumption exists yet; `wake`\n// already exists as the `wake()` entry point.\n// ---------------------------------------------------------------------------\n\n/** Explain one Submission (`submissionId` present) or every nonterminal lane member. */\nexport class AdminExplainRequest extends Schema.Class<AdminExplainRequest>(\n \"@effect-agent/platform-cloudflare/AdminExplainRequest\",\n)({\n submissionId: Schema.optionalKey(SubmissionId),\n}) {}\n\n/** Verify carries no parameters — the addressed Object IS the lane. */\nexport class AdminVerifyRequest extends Schema.Class<AdminVerifyRequest>(\n \"@effect-agent/platform-cloudflare/AdminVerifyRequest\",\n)({}) {}\n\n/** Every typed failure of the four admin entry points, plus the protocol's own errors. */\nexport const AdminFailure = Schema.Union([\n AdmissionPolicyError,\n OperationDenied,\n RetryRefused,\n LedgerError,\n RunJournalError,\n DigestError,\n OwnershipLost,\n SettlementConflict,\n ThreadStoreError,\n ThreadNotMaterialized,\n AppendConflict,\n FenceRejected,\n DurableRuntimeFailpointError,\n DurableAlarmError,\n HostProtocolError,\n]);\n\nexport type AdminFailure = typeof AdminFailure.Type;\n\nexport class ExplainedRecovery extends Schema.TaggedClass<ExplainedRecovery>(\n \"@effect-agent/platform-cloudflare/ExplainedRecovery\",\n)(\"ExplainedRecovery\", {\n explanations: Schema.Array(RecoveryExplanation).check(Schema.isMaxLength(1_024)),\n}) {}\n\nexport class VerifiedIntegrity extends Schema.TaggedClass<VerifiedIntegrity>(\n \"@effect-agent/platform-cloudflare/VerifiedIntegrity\",\n)(\"VerifiedIntegrity\", {\n report: IntegrityReport,\n}) {}\n\nexport class RetryExecuted extends Schema.TaggedClass<RetryExecuted>(\n \"@effect-agent/platform-cloudflare/RetryExecuted\",\n)(\"RetryExecuted\", {\n report: RecoveryReport,\n}) {}\n\nexport class ObligationsScanned extends Schema.TaggedClass<ObligationsScanned>(\n \"@effect-agent/platform-cloudflare/ObligationsScanned\",\n)(\"ObligationsScanned\", {\n report: ObligationReport,\n}) {}\n\n/** The admin entry point failed TYPED on the Object; the failure re-decodes verbatim. */\nexport class AdminFailed extends Schema.TaggedClass<AdminFailed>(\n \"@effect-agent/platform-cloudflare/AdminFailed\",\n)(\"AdminFailed\", {\n failure: AdminFailure,\n}) {}\n\n/** The uniform answer of one admin entry point. Callers narrow by the tag their call implies. */\nexport const AdminResponse = Schema.Union([\n ExplainedRecovery,\n VerifiedIntegrity,\n RetryExecuted,\n ObligationsScanned,\n AdminFailed,\n]);\n\nexport type AdminResponse = typeof AdminResponse.Type;\n\nexport const decodeAdminExplainRequest = Schema.decodeUnknownEffect(AdminExplainRequest);\nexport const decodeAdminVerifyRequest = Schema.decodeUnknownEffect(AdminVerifyRequest);\nexport const decodeRetryCommand = Schema.decodeUnknownEffect(RetryCommand);\nexport const decodeObligationThresholds = Schema.decodeUnknownEffect(ObligationThresholds);\nexport const encodeAdminResponse = Schema.encodeEffect(AdminResponse);\nexport const decodeAdminResponse = Schema.decodeUnknownEffect(AdminResponse);\n\n/** Fold one admin endpoint's typed failures into the uniform `AdminResponse` envelope. */\nconst respondAdmin = <Result extends AdminResponse, Failure extends AdminFailure>(\n effect: Effect.Effect<Result, Failure, EndpointServices>,\n): Effect.Effect<AdminResponse, never, EndpointServices> =>\n effect.pipe(\n Effect.map((result): AdminResponse => result),\n Effect.catch((failure) => Effect.succeed<AdminResponse>(AdminFailed.make({ failure }))),\n );\n\n/** Encode the admin response envelope; an unencodable response degrades to a protocol failure. */\nconst encodeAdminResponseTotal = (response: AdminResponse): Effect.Effect<unknown> =>\n encodeAdminResponse(response).pipe(\n Effect.catch((error) =>\n Effect.succeed<unknown>({\n _tag: \"AdminFailed\",\n failure: {\n _tag: \"HostProtocolError\",\n message: boundHostDiagnostic(`The admin response could not be encoded: ${error.message}`),\n },\n }),\n ),\n );\n\nconst explainEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n decodeAdminExplainRequest(encoded).pipe(\n Effect.mapError(protocolFailure(\"The explain request could not be decoded\")),\n Effect.flatMap((request) =>\n Effect.gen(function* () {\n const identity = yield* ThreadObjectIdentity;\n const runtime = yield* DurableAgentRuntime;\n\n const explanations =\n request.submissionId === undefined\n ? yield* runtime.explainThread(identity.threadId)\n : [yield* runtime.explain(request.submissionId)];\n\n return ExplainedRecovery.make({ explanations });\n }),\n ),\n respondAdmin,\n Effect.flatMap(encodeAdminResponseTotal),\n );\n\nconst verifyEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n decodeAdminVerifyRequest(encoded).pipe(\n Effect.mapError(protocolFailure(\"The verify request could not be decoded\")),\n Effect.flatMap(() =>\n Effect.gen(function* () {\n const identity = yield* ThreadObjectIdentity;\n const runtime = yield* DurableAgentRuntime;\n const report = yield* runtime.verify(identity.threadId);\n\n return VerifiedIntegrity.make({ report });\n }),\n ),\n respondAdmin,\n Effect.flatMap(encodeAdminResponseTotal),\n );\n\nconst retryEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n decodeRetryCommand(encoded).pipe(\n Effect.mapError(protocolFailure(\"The retry command could not be decoded\")),\n Effect.flatMap((command) =>\n Effect.gen(function* () {\n const maintenance = yield* ThreadMaintenance;\n const runtime = yield* DurableAgentRuntime;\n // Retry may repair durable state, so its generation + alarm commit before the mutation.\n const report = yield* maintenance.withMutation(runtime.retry(command));\n\n return RetryExecuted.make({ report });\n }),\n ),\n respondAdmin,\n Effect.flatMap(encodeAdminResponseTotal),\n );\n\nconst obligationsEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n decodeObligationThresholds(encoded).pipe(\n Effect.mapError(protocolFailure(\"The obligation thresholds could not be decoded\")),\n Effect.flatMap((thresholds) =>\n Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n const report = yield* runtime.scanObligations(thresholds);\n\n return ObligationsScanned.make({ report });\n }),\n ),\n respondAdmin,\n Effect.flatMap(encodeAdminResponseTotal),\n );\n\n/**\n * Owner-side `portCall`: wrap a mutating envelope in the same pre-armed generation protocol as\n * public RPC (a routed mutation committed by THIS Object must already carry the alarm that will\n * finish it), execute on the LOCAL facets (never the routed decorators), then arm an immediate\n * alarm so the mutated lane is processed promptly. Protocol anomalies answer\n * `PortFailed(PortProtocolError)`.\n */\nconst portCallEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n Effect.gen(function* () {\n const ports = yield* ThreadObjectPorts;\n const maintenance = yield* ThreadMaintenance;\n const alarm = yield* DurableAlarmService;\n\n const decoded = yield* decodePortRequest(encoded).pipe(\n Effect.map((request) => ({ _tag: \"success\" as const, request })),\n Effect.catch((error) => Effect.succeed({ _tag: \"failure\" as const, message: error.message })),\n );\n\n if (decoded._tag === \"failure\") {\n return encodedPortProtocolFailure(\n `The port request could not be decoded: ${decoded.message}`,\n );\n }\n const mutating = isMutatingPortRequest(decoded.request);\n\n const handled = yield* (\n mutating\n ? maintenance.withMutation(ports.handle(decoded.request))\n : ports.handle(decoded.request)\n ).pipe(Effect.exit);\n\n if (handled._tag === \"Failure\") {\n // Without the committed generation/alarm the invariant cannot be promised; refuse before\n // the port mutation runs. `ports.handle` itself is total, so this is the maintenance error.\n return encodedPortProtocolFailure(\n \"The owner Object could not arm its maintenance alarm before the mutation.\",\n );\n }\n\n const response = yield* encodePortResponse(handled.value).pipe(\n Effect.catch((error) =>\n Effect.succeed(\n encodedPortProtocolFailure(`The port response could not be encoded: ${error.message}`),\n ),\n ),\n );\n\n if (mutating) {\n // Prompt processing hint; the pre-armed alarm already guarantees convergence.\n yield* alarm.scheduleNow.pipe(\n Effect.catch((error) =>\n Effect.logWarning(\"ThreadObject.portCall: immediate re-arm failed\", error),\n ),\n );\n }\n\n return response;\n });\n\nconst wakeEndpoint: Effect.Effect<void, never, EndpointServices> = Effect.gen(function* () {\n const identity = yield* ThreadObjectIdentity;\n const wake = yield* WakeScheduler;\n\n // Route the remote hint through this incarnation's scheduler so scoped progress waiters and\n // the alarm receive the same hint. Delivery remains droppable; canonical storage is authority.\n yield* wake.notify(identity.threadId);\n});\n\nconst alarmEndpoint: Effect.Effect<void, MaintenancePassFailure, EndpointServices> = Effect.gen(\n function* () {\n const maintenance = yield* ThreadMaintenance;\n\n // Typed pass failures propagate: the rejected promise makes workerd retry the alarm\n // (at-least-once delivery), and the dirty generation retains a committed slot meanwhile.\n yield* maintenance.pass;\n },\n);\n\nconst gateEndpoint: Effect.Effect<void, MaintenancePassFailure, EndpointServices> = Effect.gen(\n function* () {\n // Forcing ThreadMaintenance forces the whole Layer stack: migration + exact-version\n // check + configuration decode (DEPLOY-008 fails typed here, before any mutation), then\n // the defensive local ensure-alarm half of the invariant. LOCAL-ONLY by construction.\n const maintenance = yield* ThreadMaintenance;\n\n yield* maintenance.ensureAlarm;\n },\n);\n\n/**\n * Adapter from effect-cf's native Durable Object services to Effect Agent's existing platform\n * ports. effect-cf owns the cached ManagedRuntime and supplies these values once per Object\n * incarnation; the durable runtime continues to depend only on the narrow services below.\n */\nconst effectCfPlatformLayer = (\n namespaceBinding: string,\n rpcTracing = false,\n): Layer.Layer<\n DurableObjectContext | ThreadObjectNamespace,\n CloudflareBindingError,\n EffectCfDurableObjectState.DurableObjectState | WorkerEnvironment\n> => {\n const context = Layer.effect(DurableObjectContext)(\n Effect.gen(function* () {\n const state = yield* EffectCfDurableObjectState.DurableObjectState;\n const env = yield* WorkerEnvironment;\n\n return DurableObjectContext.of({ ctx: state.raw, env });\n }),\n );\n\n const namespace = Layer.effect(ThreadObjectNamespace)(\n Effect.gen(function* () {\n const env = yield* WorkerEnvironment;\n const binding = yield* threadNamespaceFromEnv(env, namespaceBinding);\n\n return ThreadObjectNamespace.of({\n namespace: binding,\n ...(rpcTracing === true ? { rpcTracing: namespaceBinding } : {}),\n });\n }),\n );\n\n return Layer.merge(context, namespace);\n};\n\n/** The public endpoints and effect-cf invocation hook of one Thread Object instance. */\nexport interface Instance<EventServices = never> extends InstanceType<\n EffectCfDurableObject.DurableObjectClass<Record<never, never>, RuntimeServices | EventServices>\n> {\n submitEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n submissionStatusEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n awaitSettlementEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n awaitProgressEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n cancelProgressEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n observePage(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n abortEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n resolveApprovalEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n resolveUnknownEncoded(encoded: unknown, traceContext?: unknown): Promise<unknown>;\n explainEncoded(encoded: unknown): Promise<unknown>;\n verifyEncoded(encoded: unknown): Promise<unknown>;\n retryEncoded(encoded: unknown): Promise<unknown>;\n obligationsEncoded(encoded: unknown): Promise<unknown>;\n portCall(encoded: unknown): Promise<unknown>;\n wake(): Promise<void>;\n alarm(alarmInfo?: AlarmInvocationInfo): Promise<void> | void;\n}\n\n/** The constructor shape workerd instantiates for each Thread Object. */\nexport interface Class<EventServices = never> {\n new (ctx: DurableObjectState, env: Cloudflare.Env): Instance<EventServices>;\n}\n\n/**\n * Export a composed application Layer as a native Durable Object class.\n * Bootstrap services are provided to the whole graph before it acquires, so application Layers\n * can yield effect-cf's WorkerEnvironment and DurableObjectState, derived identity, and Crypto.\n * Application dependencies remain visible until Layer.provide satisfies them. effect-cf owns the\n * cached ManagedRuntime, native RPC methods, event scopes, and telemetry flushing.\n * Initialization is local and bounded inside the constructor gate. Cloudflare eviction does not\n * guarantee finalizers; put resources requiring timely release in scoped operations or eventLayer.\n */\nexport const make = <\n ApplicationServices,\n ApplicationError,\n EventServices = never,\n EventLayerError = never,\n>(\n applicationLayer: Layer.Layer<\n CloudflareDurableRuntimeServices | ApplicationServices,\n ApplicationError,\n | CloudflareBootstrapServices\n | EffectCfDurableObjectState.DurableObjectState\n | WorkerEnvironment\n | DurableObjectContext\n | ThreadObjectNamespace\n >,\n options: Options<ApplicationServices, EventServices, EventLayerError>,\n): Class<ApplicationServices | EventServices> => {\n const application = applicationLayer.pipe(\n Layer.provideMerge(layerConfig(options)),\n Layer.provideMerge(effectCfPlatformLayer(options.namespaceBinding, options.rpcTracing)),\n );\n\n // The storage/config Layer must acquire inside Cloudflare's constructor gate. effect-cf owns\n // the ManagedRuntime, while this effectContext ensures its first Layer build enters the gate\n // before migration, compatibility checks, or alarm inspection touch Object storage.\n const runtime: Layer.Layer<\n RuntimeServices | ApplicationServices,\n ThreadObjectInitializationError | ApplicationError,\n EffectCfDurableObjectState.DurableObjectState | WorkerEnvironment\n > = Layer.effectContext(\n Effect.gen(function* () {\n const state = yield* EffectCfDurableObjectState.DurableObjectState;\n const scope = yield* Effect.scope;\n\n return yield* state.blockConcurrencyWhile(\n Effect.gen(function* () {\n const services = yield* Layer.buildWithScope(application, scope);\n\n yield* gateEndpoint.pipe(Effect.provide(services));\n\n return services;\n }),\n );\n }),\n );\n\n const rpc = {\n submitEncoded: (encoded: unknown) => submitEndpoint(encoded),\n submissionStatusEncoded: (encoded: unknown) => submissionStatusEndpoint(encoded),\n awaitSettlementEncoded: (encoded: unknown) => awaitSettlementEndpoint(encoded),\n awaitProgressEncoded: (encoded: unknown) => awaitProgressEndpoint(encoded),\n cancelProgressEncoded: (encoded: unknown) => cancelProgressEndpoint(encoded),\n observePage: (encoded: unknown) => observePageEndpoint(encoded),\n abortEncoded: (encoded: unknown) => abortEndpoint(encoded),\n resolveApprovalEncoded: (encoded: unknown) => resolveApprovalEndpoint(encoded),\n resolveUnknownEncoded: (encoded: unknown) => resolveUnknownEndpoint(encoded),\n explainEncoded: (encoded: unknown) => explainEndpoint(encoded),\n verifyEncoded: (encoded: unknown) => verifyEndpoint(encoded),\n retryEncoded: (encoded: unknown) => retryEndpoint(encoded),\n obligationsEncoded: (encoded: unknown) => obligationsEndpoint(encoded),\n portCall: (encoded: unknown) => portCallEndpoint(encoded),\n wake: () => wakeEndpoint,\n } satisfies EffectCfDurableObject.DurableObjectRpc<\n RuntimeServices | ApplicationServices | EventServices\n >;\n\n type NativeOptions = EffectCfDurableObject.DurableObjectOptions<\n RuntimeServices | ApplicationServices,\n EventServices,\n EventLayerError,\n typeof rpc\n >;\n\n const EffectCfThreadObject = EffectCfDurableObject.make<\n RuntimeServices | ApplicationServices,\n ThreadObjectInitializationError | ApplicationError,\n EventServices,\n EventLayerError,\n typeof rpc\n >(runtime, {\n ...(options.rpcTracing === true ? { rpcTracing: { service: options.namespaceBinding } } : {}),\n ...(options.eventLayer === undefined ? {} : { eventLayer: options.eventLayer }),\n // Force the gated runtime Layer when Cloudflare loads this Object incarnation. Recovery stays\n // in each bounded pass so cross-Object initialization cannot deadlock.\n initialize: Effect.void,\n rpc,\n alarm: () => alarmEndpoint,\n // This host owns the raw alarm and supplies event services through options.eventLayer.\n // Upstream's conditional alarm-registration check cannot reduce over generic application\n // services. Options and the rpc satisfies check above retain their Effect requirements.\n } as NativeOptions);\n\n // effect-cf's class type keeps `alarm` optional even when the handler option is present. This\n // concrete override reflects this factory's stronger contract while delegating execution to\n // the effect-cf runtime unchanged.\n class ThreadObject extends EffectCfThreadObject {\n override alarm(alarmInfo?: AlarmInvocationInfo): Promise<void> | void {\n return super.alarm?.(alarmInfo);\n }\n }\n\n return ThreadObject;\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { C as CloudflareDurableRuntimeOptions, D as layerConfig, E as layer, S as CloudflareDurableRuntimeInitializationError, T as ThreadPublicationOptions, _ as decodeObligationThresholds, a as AdminVerifyRequest, b as make, c as Instance, d as RetryExecuted, g as decodeAdminVerifyRequest, h as decodeAdminResponse, i as AdminResponse, l as ObligationsScanned, m as decodeAdminExplainRequest, n as AdminFailed, o as Class, p as VerifiedIntegrity, r as AdminFailure, s as ExplainedRecovery, t as AdminExplainRequest, u as Options, v as decodeRetryCommand, w as CloudflareDurableRuntimeServices, x as CloudflareBootstrapServices, y as encodeAdminResponse } from "./ThreadObject-wDwMUV8v.mjs";
1
+ import { C as CloudflareDurableRuntimeOptions, D as layerConfig, E as layer, S as CloudflareDurableRuntimeInitializationError, T as ThreadPublicationOptions, _ as decodeObligationThresholds, a as AdminVerifyRequest, b as make, c as Instance, d as RetryExecuted, g as decodeAdminVerifyRequest, h as decodeAdminResponse, i as AdminResponse, l as ObligationsScanned, m as decodeAdminExplainRequest, n as AdminFailed, o as Class, p as VerifiedIntegrity, r as AdminFailure, s as ExplainedRecovery, t as AdminExplainRequest, u as Options, v as decodeRetryCommand, w as CloudflareDurableRuntimeServices, x as CloudflareBootstrapServices, y as encodeAdminResponse } from "./ThreadObject-Avjx5Gmk.mjs";
2
2
  export { AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, type CloudflareBootstrapServices as BootstrapServices, Class, ExplainedRecovery, type CloudflareDurableRuntimeInitializationError as InitializationError, Instance, ObligationsScanned, Options, type ThreadPublicationOptions as PublicationOptions, RetryExecuted, type CloudflareDurableRuntimeOptions as RuntimeOptions, type CloudflareDurableRuntimeServices as Services, VerifiedIntegrity, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeObligationThresholds, decodeRetryCommand, encodeAdminResponse, layer, layerConfig, make };
@@ -1,3 +1,3 @@
1
1
  import "./CloudflareThreadClient.mjs";
2
- import { _ as make, a as AdminVerifyRequest, c as RetryExecuted, d as decodeAdminExplainRequest, f as decodeAdminResponse, g as encodeAdminResponse, h as decodeRetryCommand, i as AdminResponse, m as decodeObligationThresholds, n as AdminFailed, o as ExplainedRecovery, p as decodeAdminVerifyRequest, r as AdminFailure, s as ObligationsScanned, t as AdminExplainRequest, u as VerifiedIntegrity, v as layer, y as layerConfig } from "./ThreadObject-Cm6tuhon.mjs";
2
+ import { _ as make, a as AdminVerifyRequest, c as RetryExecuted, d as decodeAdminExplainRequest, f as decodeAdminResponse, g as encodeAdminResponse, h as decodeRetryCommand, i as AdminResponse, m as decodeObligationThresholds, n as AdminFailed, o as ExplainedRecovery, p as decodeAdminVerifyRequest, r as AdminFailure, s as ObligationsScanned, t as AdminExplainRequest, u as VerifiedIntegrity, v as layer, y as layerConfig } from "./ThreadObject-J5thaFpm.mjs";
3
3
  export { AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, ExplainedRecovery, ObligationsScanned, RetryExecuted, VerifiedIntegrity, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeObligationThresholds, decodeRetryCommand, encodeAdminResponse, layer, layerConfig, make };
package/dist/index.d.mts CHANGED
@@ -7,6 +7,6 @@ import { t as CloudflareMemory_d_exports } from "./CloudflareMemory.mjs";
7
7
  import { t as CloudflareScheduling_d_exports } from "./CloudflareScheduling.mjs";
8
8
  import { t as CloudflareSubscriptions_d_exports } from "./CloudflareSubscriptions.mjs";
9
9
  import { t as CloudflareThreadClient_d_exports } from "./CloudflareThreadClient.mjs";
10
- import { f as ThreadObject_d_exports } from "./ThreadObject-wDwMUV8v.mjs";
10
+ import { f as ThreadObject_d_exports } from "./ThreadObject-Avjx5Gmk.mjs";
11
11
  import { t as WakeScheduler_d_exports } from "./WakeScheduler.mjs";
12
12
  export { Alarm_d_exports as Alarm, CloudflareBindings_d_exports as CloudflareBindings, CloudflareBrowser_d_exports as CloudflareBrowser, CloudflareCodeMode_d_exports as CloudflareCodeMode, CloudflareConfig_d_exports as CloudflareConfig, CloudflareMemory_d_exports as CloudflareMemory, CloudflareScheduling_d_exports as CloudflareScheduling, CloudflareSubscriptions_d_exports as CloudflareSubscriptions, CloudflareThreadClient_d_exports as CloudflareThreadClient, ThreadObject_d_exports as ThreadObject, WakeScheduler_d_exports as WakeScheduler };
package/dist/index.mjs CHANGED
@@ -8,5 +8,5 @@ import { t as CloudflareThreadClient_exports } from "./CloudflareThreadClient.mj
8
8
  import { t as CloudflareScheduling_exports } from "./CloudflareScheduling.mjs";
9
9
  import { t as CloudflareSubscriptions_exports } from "./CloudflareSubscriptions.mjs";
10
10
  import { t as WakeScheduler_exports } from "./WakeScheduler.mjs";
11
- import { l as ThreadObject_exports } from "./ThreadObject-Cm6tuhon.mjs";
11
+ import { l as ThreadObject_exports } from "./ThreadObject-J5thaFpm.mjs";
12
12
  export { Alarm_exports as Alarm, CloudflareBindings_exports as CloudflareBindings, CloudflareBrowser_exports as CloudflareBrowser, CloudflareCodeMode_exports as CloudflareCodeMode, CloudflareConfig_exports as CloudflareConfig, CloudflareMemory_exports as CloudflareMemory, CloudflareScheduling_exports as CloudflareScheduling, CloudflareSubscriptions_exports as CloudflareSubscriptions, CloudflareThreadClient_exports as CloudflareThreadClient, ThreadObject_exports as ThreadObject, WakeScheduler_exports as WakeScheduler };
@@ -22,6 +22,8 @@ const cloudflarePreparedInputAdmissionLayer = Layer.effect(PreparedInputAdmissio
22
22
  idempotencyKey: envelope.admissionKey,
23
23
  ...envelope.admissionGroup === void 0 ? {} : { admissionGroup: envelope.admissionGroup },
24
24
  ...envelope.admissionFence === void 0 ? {} : { admissionFence: envelope.admissionFence },
25
+ ...envelope.workerAdmission === void 0 ? {} : { workerAdmission: envelope.workerAdmission },
26
+ ...envelope.messageAdmission === void 0 ? {} : { messageAdmission: envelope.messageAdmission },
25
27
  definitions: envelope.definitions
26
28
  }).pipe(Effect.catchTags({
27
29
  AdmissionConflict: () => ScheduleStorageError.make({
@@ -68,4 +70,4 @@ const cloudflareScheduledInputAdmissionLayer = Layer.effect(ScheduledInputAdmiss
68
70
  //#endregion
69
71
  export { cloudflareScheduledInputAdmissionLayer as n, cloudflarePreparedInputAdmissionLayer as t };
70
72
 
71
- //# sourceMappingURL=prepared-admission-9rvlHI0y.mjs.map
73
+ //# sourceMappingURL=prepared-admission-G7N4DDqS.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepared-admission-G7N4DDqS.mjs","names":[],"sources":["../src/internal/prepared-admission.ts"],"sourcesContent":["import { type AgentId } from \"@effect-agent/core/Identifiers\";\nimport { type DurableSubmitAgent } from \"@effect-agent/thread/DurableAgentRuntime\";\nimport { PreparedInputAdmission } from \"@effect-agent/thread/PreparedInputAdmission\";\nimport { PersistedJson } from \"@effect-agent/thread/Records\";\nimport {\n type ScheduledEnvelope,\n ScheduledInputAdmission,\n ScheduledInputRetryable,\n ScheduledInputRefused,\n ScheduleStorageError,\n} from \"@effect-agent/thread/Schedule\";\nimport { type PreparedInput } from \"@effect-agent/thread/Subscription\";\nimport { Effect, Layer } from \"effect\";\n\nimport { CloudflareThreadClient, type ThreadClientError } from \"../CloudflareThreadClient.ts\";\n\nconst passthroughAgent = (agentId: AgentId): DurableSubmitAgent<typeof PersistedJson> => ({\n definition: { id: agentId, input: PersistedJson },\n});\n\n/** Ordinary prepared admission through one freshly addressed Thread Object call. */\nexport const cloudflarePreparedInputAdmissionLayer: Layer.Layer<\n PreparedInputAdmission,\n never,\n CloudflareThreadClient\n> = Layer.effect(\n PreparedInputAdmission,\n Effect.gen(function* () {\n const client = yield* CloudflareThreadClient;\n\n return PreparedInputAdmission.of({\n submissionStatus: (receipt) =>\n client\n .submissionStatus(receipt)\n .pipe(Effect.mapError(() => ScheduledInputRetryable.make({ reason: \"storage\" }))),\n submit: (envelope) =>\n client\n .submit(passthroughAgent(envelope.agentId), envelope.input, {\n threadId: envelope.threadId,\n principal: envelope.deliveryPrincipal,\n idempotencyKey: envelope.admissionKey,\n ...(envelope.admissionGroup === undefined\n ? {}\n : { admissionGroup: envelope.admissionGroup }),\n ...(envelope.admissionFence === undefined\n ? {}\n : { admissionFence: envelope.admissionFence }),\n ...(envelope.workerAdmission === undefined\n ? {}\n : { workerAdmission: envelope.workerAdmission }),\n ...(envelope.messageAdmission === undefined\n ? {}\n : { messageAdmission: envelope.messageAdmission }),\n definitions: envelope.definitions,\n })\n .pipe(\n Effect.catchTags({\n AdmissionConflict: () =>\n ScheduleStorageError.make({ operation: \"prepared admission\", reason: \"corrupt\" }),\n AdmissionLimitExceeded: () => ScheduledInputRetryable.make({ reason: \"capacity\" }),\n ThreadClientError: (error: ThreadClientError) =>\n ScheduledInputRetryable.make({\n reason: error.overloaded === true ? \"capacity\" : \"transport\",\n }),\n HostProtocolError: () => ScheduledInputRetryable.make({ reason: \"ambiguous\" }),\n AdmissionPolicyError: (error) =>\n error.reason === \"refused\"\n ? ScheduledInputRefused.make({ code: error.code })\n : ScheduledInputRetryable.make({\n reason: error.reason === \"occupied\" ? \"capacity\" : \"storage\",\n }),\n LedgerError: () => ScheduledInputRetryable.make({ reason: \"storage\" }),\n ThreadStoreError: () => ScheduledInputRetryable.make({ reason: \"storage\" }),\n DurableAlarmError: () => ScheduledInputRetryable.make({ reason: \"storage\" }),\n AgentInputError: () =>\n ScheduleStorageError.make({ operation: \"prepared admission\", reason: \"corrupt\" }),\n DigestError: () =>\n ScheduleStorageError.make({ operation: \"prepared admission\", reason: \"corrupt\" }),\n ThreadNotMaterialized: () => ScheduledInputRetryable.make({ reason: \"storage\" }),\n AppendConflict: () => ScheduledInputRetryable.make({ reason: \"ambiguous\" }),\n FenceRejected: () => ScheduledInputRetryable.make({ reason: \"ambiguous\" }),\n DurableRuntimeFailpointError: () =>\n ScheduledInputRetryable.make({ reason: \"ambiguous\" }),\n }),\n ),\n });\n }),\n);\n\nconst preparedFromSchedule = (envelope: ScheduledEnvelope): PreparedInput => ({\n schemaVersion: 1,\n threadId: envelope.threadId,\n deliveryPrincipal: envelope.deliveryPrincipal,\n ...(envelope.admissionGroup === undefined ? {} : { admissionGroup: envelope.admissionGroup }),\n ...(envelope.admissionFence === undefined ? {} : { admissionFence: envelope.admissionFence }),\n agentId: envelope.agentId,\n definitions: envelope.definitions,\n input: envelope.input,\n inputDigest: envelope.inputDigest,\n admissionKey: envelope.admissionKey,\n authorization: envelope.authorization,\n});\n\n/** Compatibility adapter retaining Scheduling's public admission port. */\nexport const cloudflareScheduledInputAdmissionLayer: Layer.Layer<\n ScheduledInputAdmission,\n never,\n PreparedInputAdmission\n> = Layer.effect(\n ScheduledInputAdmission,\n Effect.map(PreparedInputAdmission, (admission) =>\n ScheduledInputAdmission.of({\n submit: (envelope) => admission.submit(preparedFromSchedule(envelope)),\n }),\n ),\n);\n"],"mappings":";;;;;;;;;AAgBA,MAAM,oBAAoB,aAAgE,EACxF,YAAY;CAAE,IAAI;CAAS,OAAO;AAAc,EAClD;;AAGA,MAAa,wCAIT,MAAM,OACR,wBACA,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO;CAEtB,OAAO,uBAAuB,GAAG;EAC/B,mBAAmB,YACjB,OACG,iBAAiB,OAAO,CAAC,CACzB,KAAK,OAAO,eAAe,wBAAwB,KAAK,EAAE,QAAQ,UAAU,CAAC,CAAC,CAAC;EACpF,SAAS,aACP,OACG,OAAO,iBAAiB,SAAS,OAAO,GAAG,SAAS,OAAO;GAC1D,UAAU,SAAS;GACnB,WAAW,SAAS;GACpB,gBAAgB,SAAS;GACzB,GAAI,SAAS,mBAAmB,KAAA,IAC5B,CAAC,IACD,EAAE,gBAAgB,SAAS,eAAe;GAC9C,GAAI,SAAS,mBAAmB,KAAA,IAC5B,CAAC,IACD,EAAE,gBAAgB,SAAS,eAAe;GAC9C,GAAI,SAAS,oBAAoB,KAAA,IAC7B,CAAC,IACD,EAAE,iBAAiB,SAAS,gBAAgB;GAChD,GAAI,SAAS,qBAAqB,KAAA,IAC9B,CAAC,IACD,EAAE,kBAAkB,SAAS,iBAAiB;GAClD,aAAa,SAAS;EACxB,CAAC,CAAC,CACD,KACC,OAAO,UAAU;GACf,yBACE,qBAAqB,KAAK;IAAE,WAAW;IAAsB,QAAQ;GAAU,CAAC;GAClF,8BAA8B,wBAAwB,KAAK,EAAE,QAAQ,WAAW,CAAC;GACjF,oBAAoB,UAClB,wBAAwB,KAAK,EAC3B,QAAQ,MAAM,eAAe,OAAO,aAAa,YACnD,CAAC;GACH,yBAAyB,wBAAwB,KAAK,EAAE,QAAQ,YAAY,CAAC;GAC7E,uBAAuB,UACrB,MAAM,WAAW,YACb,sBAAsB,KAAK,EAAE,MAAM,MAAM,KAAK,CAAC,IAC/C,wBAAwB,KAAK,EAC3B,QAAQ,MAAM,WAAW,aAAa,aAAa,UACrD,CAAC;GACP,mBAAmB,wBAAwB,KAAK,EAAE,QAAQ,UAAU,CAAC;GACrE,wBAAwB,wBAAwB,KAAK,EAAE,QAAQ,UAAU,CAAC;GAC1E,yBAAyB,wBAAwB,KAAK,EAAE,QAAQ,UAAU,CAAC;GAC3E,uBACE,qBAAqB,KAAK;IAAE,WAAW;IAAsB,QAAQ;GAAU,CAAC;GAClF,mBACE,qBAAqB,KAAK;IAAE,WAAW;IAAsB,QAAQ;GAAU,CAAC;GAClF,6BAA6B,wBAAwB,KAAK,EAAE,QAAQ,UAAU,CAAC;GAC/E,sBAAsB,wBAAwB,KAAK,EAAE,QAAQ,YAAY,CAAC;GAC1E,qBAAqB,wBAAwB,KAAK,EAAE,QAAQ,YAAY,CAAC;GACzE,oCACE,wBAAwB,KAAK,EAAE,QAAQ,YAAY,CAAC;EACxD,CAAC,CACH;CACN,CAAC;AACH,CAAC,CACH;AAEA,MAAM,wBAAwB,cAAgD;CAC5E,eAAe;CACf,UAAU,SAAS;CACnB,mBAAmB,SAAS;CAC5B,GAAI,SAAS,mBAAmB,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB,SAAS,eAAe;CAC3F,GAAI,SAAS,mBAAmB,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB,SAAS,eAAe;CAC3F,SAAS,SAAS;CAClB,aAAa,SAAS;CACtB,OAAO,SAAS;CAChB,aAAa,SAAS;CACtB,cAAc,SAAS;CACvB,eAAe,SAAS;AAC1B;;AAGA,MAAa,yCAIT,MAAM,OACR,yBACA,OAAO,IAAI,yBAAyB,cAClC,wBAAwB,GAAG,EACzB,SAAS,aAAa,UAAU,OAAO,qBAAqB,QAAQ,CAAC,EACvE,CAAC,CACH,CACF"}
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@effect-agent/platform-cloudflare","version":"0.1.0-beta.55","dependencies":{"@effect-agent/core":"0.1.0-beta.55","@effect-agent/engine":"0.1.0-beta.55","@effect-agent/sandbox":"0.1.0-beta.55","@effect-agent/storage-cloudflare":"0.1.0-beta.55","@effect-agent/thread":"0.1.0-beta.55","@effect/platform-browser":"4.0.0-rc.112","@effect/sql-sqlite-do":"4.0.0-rc.112"},"devDependencies":{"@cloudflare/puppeteer":"1.1.0","@cloudflare/vitest-pool-workers":"0.21.3","@cloudflare/workers-types":"5.20260825.1","@effect-agent/capabilities":"0.1.0-beta.55","@effect-agent/testing":"0.1.0-beta.55","@effect/platform-node":"4.0.0-rc.112","@effect/sql-d1":"4.0.0-rc.112","@effect/vitest":"4.0.0-rc.112","effect":"4.0.0-rc.112","effect-cf":"0.40.0","esbuild":"0.28.1","miniflare":"5.20260811.1-alpha","typescript":"7.0.2","vite-plus":"0.3.0","vitest":"4.1.11"},"peerDependencies":{"@cloudflare/puppeteer":"^1.1.0","effect":"^4.0.0-rc.112","effect-cf":"^0.40.0"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./Alarm":{"types":"./dist/Alarm.d.mts","default":"./dist/Alarm.mjs"},"./BrowserRestCapture":{"types":"./dist/BrowserRestCapture.d.mts","default":"./dist/BrowserRestCapture.mjs"},"./BrowserRestCrawl":{"types":"./dist/BrowserRestCrawl.d.mts","default":"./dist/BrowserRestCrawl.mjs"},"./CloudflareBindings":{"types":"./dist/CloudflareBindings.d.mts","default":"./dist/CloudflareBindings.mjs"},"./CloudflareBrowser":{"types":"./dist/CloudflareBrowser.d.mts","default":"./dist/CloudflareBrowser.mjs"},"./CloudflareCodeMode":{"types":"./dist/CloudflareCodeMode.d.mts","default":"./dist/CloudflareCodeMode.mjs"},"./CloudflareConfig":{"types":"./dist/CloudflareConfig.d.mts","default":"./dist/CloudflareConfig.mjs"},"./CloudflareMemory":{"types":"./dist/CloudflareMemory.d.mts","default":"./dist/CloudflareMemory.mjs"},"./CloudflareScheduling":{"types":"./dist/CloudflareScheduling.d.mts","default":"./dist/CloudflareScheduling.mjs"},"./CloudflareSubscriptions":{"types":"./dist/CloudflareSubscriptions.d.mts","default":"./dist/CloudflareSubscriptions.mjs"},"./CloudflareThreadClient":{"types":"./dist/CloudflareThreadClient.d.mts","default":"./dist/CloudflareThreadClient.mjs"},"./InteractiveBrowser":{"types":"./dist/InteractiveBrowser.d.mts","default":"./dist/InteractiveBrowser.mjs"},"./ProtectedBrowser":{"types":"./dist/ProtectedBrowser.d.mts","default":"./dist/ProtectedBrowser.mjs"},"./ThreadObject":{"types":"./dist/ThreadObject.d.mts","default":"./dist/ThreadObject.mjs"},"./WakeScheduler":{"types":"./dist/WakeScheduler.d.mts","default":"./dist/WakeScheduler.mjs"}},"description":"Cloudflare Layer assembly for Effect Agent: Durable Objects and Browser Run adapters.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/platform-cloudflare"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json"},"peerDependenciesMeta":{"@cloudflare/puppeteer":{"optional":true}}}
1
+ {"name":"@effect-agent/platform-cloudflare","version":"0.1.0-beta.57","dependencies":{"@effect-agent/core":"0.1.0-beta.57","@effect-agent/engine":"0.1.0-beta.57","@effect-agent/sandbox":"0.1.0-beta.57","@effect-agent/storage-cloudflare":"0.1.0-beta.57","@effect-agent/thread":"0.1.0-beta.57","@effect/platform-browser":"4.0.0-rc.112","@effect/sql-sqlite-do":"4.0.0-rc.112"},"devDependencies":{"@cloudflare/puppeteer":"1.1.0","@cloudflare/vitest-pool-workers":"0.21.3","@cloudflare/workers-types":"5.20260825.1","@effect-agent/capabilities":"0.1.0-beta.57","@effect-agent/testing":"0.1.0-beta.57","@effect/platform-node":"4.0.0-rc.112","@effect/sql-d1":"4.0.0-rc.112","@effect/vitest":"4.0.0-rc.112","effect":"4.0.0-rc.112","effect-cf":"0.40.0","esbuild":"0.28.1","miniflare":"5.20260811.1-alpha","typescript":"7.0.2","vite-plus":"0.3.0","vitest":"4.1.11"},"peerDependencies":{"@cloudflare/puppeteer":"^1.1.0","effect":"^4.0.0-rc.112","effect-cf":"^0.40.0"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./Alarm":{"types":"./dist/Alarm.d.mts","default":"./dist/Alarm.mjs"},"./BrowserRestCapture":{"types":"./dist/BrowserRestCapture.d.mts","default":"./dist/BrowserRestCapture.mjs"},"./BrowserRestCrawl":{"types":"./dist/BrowserRestCrawl.d.mts","default":"./dist/BrowserRestCrawl.mjs"},"./CloudflareBindings":{"types":"./dist/CloudflareBindings.d.mts","default":"./dist/CloudflareBindings.mjs"},"./CloudflareBrowser":{"types":"./dist/CloudflareBrowser.d.mts","default":"./dist/CloudflareBrowser.mjs"},"./CloudflareCodeMode":{"types":"./dist/CloudflareCodeMode.d.mts","default":"./dist/CloudflareCodeMode.mjs"},"./CloudflareConfig":{"types":"./dist/CloudflareConfig.d.mts","default":"./dist/CloudflareConfig.mjs"},"./CloudflareMemory":{"types":"./dist/CloudflareMemory.d.mts","default":"./dist/CloudflareMemory.mjs"},"./CloudflareScheduling":{"types":"./dist/CloudflareScheduling.d.mts","default":"./dist/CloudflareScheduling.mjs"},"./CloudflareSubscriptions":{"types":"./dist/CloudflareSubscriptions.d.mts","default":"./dist/CloudflareSubscriptions.mjs"},"./CloudflareThreadClient":{"types":"./dist/CloudflareThreadClient.d.mts","default":"./dist/CloudflareThreadClient.mjs"},"./InteractiveBrowser":{"types":"./dist/InteractiveBrowser.d.mts","default":"./dist/InteractiveBrowser.mjs"},"./ProtectedBrowser":{"types":"./dist/ProtectedBrowser.d.mts","default":"./dist/ProtectedBrowser.mjs"},"./ThreadObject":{"types":"./dist/ThreadObject.d.mts","default":"./dist/ThreadObject.mjs"},"./WakeScheduler":{"types":"./dist/WakeScheduler.d.mts","default":"./dist/WakeScheduler.mjs"}},"description":"Cloudflare Layer assembly for Effect Agent: Durable Objects and Browser Run adapters.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/platform-cloudflare"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json"},"peerDependenciesMeta":{"@cloudflare/puppeteer":{"optional":true}}}
package/src/Alarm.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  Context,
12
12
  DateTime,
13
13
  Effect,
14
+ Fiber,
14
15
  Layer,
15
16
  Option,
16
17
  Random,
@@ -231,6 +232,27 @@ export class ThreadPublication extends Context.Service<
231
232
  });
232
233
  }
233
234
 
235
+ /**
236
+ * @internal Host-assembled message recovery. These obligations outlive source Runs and never
237
+ * defer a ready source Attempt while a destination is processing an accepted message.
238
+ */
239
+ export const ThreadMessageDelivery = Context.Reference<{
240
+ readonly drain: Effect.Effect<void, DurableAlarmError>;
241
+ readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;
242
+ }>("@effect-agent/platform-cloudflare/ThreadMessageDelivery", {
243
+ defaultValue: () => ({ drain: Effect.void, pendingDeadline: Effect.succeed(Option.none()) }),
244
+ });
245
+
246
+ const earliestDeadline = (
247
+ left: Option.Option<number>,
248
+ right: Option.Option<number>,
249
+ ): Option.Option<number> =>
250
+ Option.isSome(left)
251
+ ? Option.isSome(right)
252
+ ? Option.some(Math.min(left.value, right.value))
253
+ : left
254
+ : right;
255
+
234
256
  /** @internal A committed source operation must not become a failed operation because delivery failed. */
235
257
  export const publishCommitted = Effect.gen(function* () {
236
258
  const publication = yield* ThreadPublication;
@@ -465,6 +487,15 @@ export class ThreadMaintenance extends Context.Service<
465
487
  const stalls = yield* Ref.make(0);
466
488
  const mutations = yield* ThreadMutationGate;
467
489
  const publication = yield* ThreadPublication;
490
+ const messages = yield* ThreadMessageDelivery;
491
+
492
+ const pendingDeadline = Effect.gen(function* () {
493
+ return earliestDeadline(
494
+ yield* publication.pendingDeadline,
495
+ yield* messages.pendingDeadline,
496
+ );
497
+ });
498
+
468
499
  const maintenancePassGate = yield* Semaphore.make(1);
469
500
  const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));
470
501
 
@@ -487,7 +518,7 @@ export class ThreadMaintenance extends Context.Service<
487
518
  }
488
519
  }),
489
520
  );
490
- const deadline = yield* publication.pendingDeadline;
521
+ const deadline = yield* pendingDeadline;
491
522
 
492
523
  if (Option.isSome(deadline)) {
493
524
  yield* runTransaction("ensure publication alarm", () =>
@@ -577,6 +608,10 @@ export class ThreadMaintenance extends Context.Service<
577
608
  }),
578
609
  );
579
610
 
611
+ // Run one bounded message wave beside source work. Slow destination admission or
612
+ // status RPCs cannot consume the source Attempt's execution window. Join before
613
+ // acknowledging the alarm so the final deadline includes all delivery mutations.
614
+ const delivery = yield* Effect.forkChild(messages.drain);
580
615
  const deadline = yield* publication.pendingDeadline;
581
616
 
582
617
  if (
@@ -588,13 +623,14 @@ export class ThreadMaintenance extends Context.Service<
588
623
  const pending = yield* publication.pendingDeadline;
589
624
 
590
625
  if (started._tag === "CaughtUp" || Option.isSome(pending)) {
626
+ yield* Fiber.join(delivery);
591
627
  yield* failpoint.hit("maintenance:finish:before");
592
628
 
593
629
  const disposition = yield* mutations.withSnapshot((active) =>
594
630
  Effect.gen(function* () {
595
631
  // Re-read under the producer gate: a concurrent append/host mutation cannot be
596
632
  // cleared using a stale empty deadline. Dirty generations bound all producer races.
597
- const latest = yield* publication.pendingDeadline;
633
+ const latest = yield* pendingDeadline;
598
634
  const now = yield* Clock.currentTimeMillis;
599
635
 
600
636
  return yield* runTransaction("finish publication pass", () =>
@@ -640,6 +676,8 @@ export class ThreadMaintenance extends Context.Service<
640
676
  // One head Attempt per event. The runtime yields after a committed turn when the
641
677
  // soft deadline is reached; queued followers belong to a subsequent alarm.
642
678
  const settlement = yield* runtime.processThreadHead(identity.threadId, { yieldAfter });
679
+
680
+ yield* Fiber.join(delivery);
643
681
  // Observe residual state before acknowledging this exact pass-start generation.
644
682
  const remaining = yield* Stream.runCollect(ledger.scanNonterminal);
645
683
  const reports = new Map(recovered.map((report) => [report.submissionId, report]));
@@ -671,7 +709,7 @@ export class ThreadMaintenance extends Context.Service<
671
709
 
672
710
  const alarmDisposition = yield* mutations.withSnapshot((active) =>
673
711
  Effect.gen(function* () {
674
- const publicationDeadline = yield* publication.pendingDeadline;
712
+ const publicationDeadline = yield* pendingDeadline;
675
713
 
676
714
  return yield* runTransaction("finish maintenance pass", () =>
677
715
  ctx.storage.transaction(async (transaction) => {
@@ -1,5 +1,6 @@
1
1
  import { AgentInputError } from "@effect-agent/core/AgentError";
2
2
  import { AgentId, type ThreadId } from "@effect-agent/core/Identifiers";
3
+ import { MessageAdmission } from "@effect-agent/core/Messaging";
3
4
  import { DigestError } from "@effect-agent/thread/Digest";
4
5
  import {
5
6
  Receipt,
@@ -13,6 +14,7 @@ import {
13
14
  CanonicalSequence,
14
15
  DefinitionDigests,
15
16
  PersistedJson,
17
+ WorkerAdmission,
16
18
  } from "@effect-agent/thread/Records";
17
19
  import {
18
20
  AdmissionFence,
@@ -114,6 +116,8 @@ export class SubmitRequest extends Schema.Class<SubmitRequest>(
114
116
  idempotencyKey: IdempotencyKey,
115
117
  admissionGroup: Schema.optionalKey(AdmissionGroup),
116
118
  admissionFence: Schema.optionalKey(AdmissionFence),
119
+ workerAdmission: Schema.optionalKey(WorkerAdmission),
120
+ messageAdmission: Schema.optionalKey(MessageAdmission),
117
121
  definitions: DefinitionDigests,
118
122
  inputPayload: PersistedJson,
119
123
  }) {}
@@ -601,6 +605,12 @@ export class CloudflareThreadClient extends Context.Service<
601
605
  ...(options.admissionFence === undefined
602
606
  ? {}
603
607
  : { admissionFence: options.admissionFence }),
608
+ ...(options.workerAdmission === undefined
609
+ ? {}
610
+ : { workerAdmission: options.workerAdmission }),
611
+ ...(options.messageAdmission === undefined
612
+ ? {}
613
+ : { messageAdmission: options.messageAdmission }),
604
614
  definitions: options.definitions,
605
615
  inputPayload,
606
616
  });
@@ -320,6 +320,12 @@ const submitEndpoint = (encoded: unknown): Effect.Effect<unknown, never, Endpoin
320
320
  ...(request.admissionFence === undefined
321
321
  ? {}
322
322
  : { admissionFence: request.admissionFence }),
323
+ ...(request.workerAdmission === undefined
324
+ ? {}
325
+ : { workerAdmission: request.workerAdmission }),
326
+ ...(request.messageAdmission === undefined
327
+ ? {}
328
+ : { messageAdmission: request.messageAdmission }),
323
329
  definitions: request.definitions,
324
330
  }),
325
331
  );
@@ -10,6 +10,7 @@ import {
10
10
  RunToolAuthorization,
11
11
  toolFailureObserverLayer,
12
12
  } from "@effect-agent/engine/RunOptions";
13
+ import { doMessageDeliveryStoreLayer } from "@effect-agent/storage-cloudflare/DoMessageDeliveryStore";
13
14
  import {
14
15
  type DoStorageFailpointHandler,
15
16
  type DoStorageFailpoint,
@@ -42,6 +43,11 @@ import {
42
43
  DurableRuntimeFailpoint,
43
44
  type DurableRuntimeFailpointHandler,
44
45
  } from "@effect-agent/thread/DurableFailpoint";
46
+ import {
47
+ type MessageDeliveryStore,
48
+ MessageDeliveryDriver,
49
+ type MessageDeliveryError,
50
+ } from "@effect-agent/thread/MessageDelivery";
45
51
  import {
46
52
  operationAuthorizerLayer,
47
53
  type OperationAuthorizerService,
@@ -77,7 +83,13 @@ import {
77
83
  CloudflareDurableRuntimeConfigValue,
78
84
  CloudflarePlatformConfigError,
79
85
  } from "../CloudflareConfig.ts";
86
+ import { CloudflareThreadClient } from "../CloudflareThreadClient.ts";
80
87
  import { cloudflareWakeSchedulerLayer } from "../WakeScheduler.ts";
88
+ import {
89
+ guardedMessageDeliveryStoreLayer,
90
+ threadMessageDeliveryLayer,
91
+ } from "./message-delivery.ts";
92
+ import { cloudflarePreparedInputAdmissionLayer } from "./prepared-admission.ts";
81
93
  import { ProgressWaitRegistry } from "./progress-wait.ts";
82
94
  import { threadPortTransportLayer } from "./transport.ts";
83
95
 
@@ -162,6 +174,7 @@ export type CloudflareBootstrapServices =
162
174
  export type CloudflareDurableRuntimeInitializationError =
163
175
  | CloudflarePlatformConfigError
164
176
  | DigestError
177
+ | MessageDeliveryError
165
178
  | DoStorageInitializationError;
166
179
 
167
180
  /** The services `ThreadObject.layer` provides, including its single owner SQL client. */
@@ -169,6 +182,7 @@ export type CloudflareDurableRuntimeServices =
169
182
  | DurableAgentRuntime
170
183
  | SubmissionLedger
171
184
  | ThreadStore
185
+ | MessageDeliveryStore
172
186
  | WakeScheduler
173
187
  | DurableAlarmService
174
188
  | ThreadMaintenance
@@ -357,7 +371,7 @@ export const layerFromBindings = <E = never, R = never>(
357
371
  options: ThreadPublicationOptions<E, R> = {},
358
372
  ): Layer.Layer<
359
373
  CloudflareDurableRuntimeServices,
360
- DoStorageInitializationError | E,
374
+ DoStorageInitializationError | MessageDeliveryError | E,
361
375
  | DurableObjectContext
362
376
  | ThreadObjectNamespace
363
377
  | CloudflareBootstrapServices
@@ -388,6 +402,19 @@ export const layerFromBindings = <E = never, R = never>(
388
402
  Layer.provide(infrastructure),
389
403
  );
390
404
 
405
+ const messageStore = guardedMessageDeliveryStoreLayer.pipe(
406
+ Layer.provide(doMessageDeliveryStoreLayer().pipe(Layer.provide(infrastructure))),
407
+ );
408
+
409
+ const messageRecovery = threadMessageDeliveryLayer.pipe(
410
+ // A single wave stays within the alarm event budget even at the policy's five-minute
411
+ // attempt ceiling. More due rows retain their indexed deadline for the next alarm.
412
+ Layer.provide(MessageDeliveryDriver.layer({ batchSize: 4, concurrency: 4 })),
413
+ Layer.provide(cloudflarePreparedInputAdmissionLayer),
414
+ Layer.provide(CloudflareThreadClient.layer),
415
+ Layer.provide(messageStore),
416
+ );
417
+
391
418
  const publication = (options.publication ?? ThreadPublication.layer).pipe(
392
419
  Layer.provide(Layer.mergeAll(rawLocalPorts, Layer.effect(SqlClient)(SqlClient))),
393
420
  );
@@ -463,6 +490,10 @@ export const layerFromBindings = <E = never, R = never>(
463
490
  const base = Layer.mergeAll(DurableAlarmService.layer, ProgressWaitRegistry.layer);
464
491
 
465
492
  const runtimeStack = DurableAgentRuntime.layerWithBindings(bindings).pipe(
493
+ Layer.provide(
494
+ cloudflarePreparedInputAdmissionLayer.pipe(Layer.provide(CloudflareThreadClient.layer)),
495
+ ),
496
+ Layer.provideMerge(messageStore),
466
497
  Layer.provideMerge(routedPorts),
467
498
  Layer.provideMerge(cloudflareWakeSchedulerLayer),
468
499
  Layer.provideMerge(base),
@@ -470,8 +501,9 @@ export const layerFromBindings = <E = never, R = never>(
470
501
 
471
502
  return Layer.mergeAll(
472
503
  runtimeStack,
473
- ThreadMaintenance.layer.pipe(Layer.provide(runtimeStack)),
504
+ ThreadMaintenance.layer.pipe(Layer.provide(runtimeStack), Layer.provide(messageRecovery)),
474
505
  portsEndpointLayer,
506
+ messageStore,
475
507
  ).pipe(
476
508
  Layer.provideMerge(publication),
477
509
  Layer.provideMerge(ThreadMutationGate.layer),